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:
@@ -0,0 +1,5 @@
|
|||||||
|
public/
|
||||||
|
resources/
|
||||||
|
node_modules/
|
||||||
|
.hugo_build.lock
|
||||||
|
static/
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["prettier-plugin-go-template", "prettier-plugin-toml"],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["layouts/**/*.html", "themes/**/*.html"],
|
||||||
|
"options": {
|
||||||
|
"parser": "go-template",
|
||||||
|
"goTemplateBracketSpacing": true,
|
||||||
|
"printWidth": 120
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": "*.toml",
|
||||||
|
"options": {
|
||||||
|
"parser": "toml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": "*.css",
|
||||||
|
"options": {
|
||||||
|
"printWidth": 100,
|
||||||
|
"singleQuote": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": "*.md",
|
||||||
|
"options": {
|
||||||
|
"proseWrap": "preserve"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
+330
-131
@@ -7,53 +7,58 @@
|
|||||||
|
|
||||||
/* ── Design tokens — sneaker drop culture ────────────────────── */
|
/* ── Design tokens — sneaker drop culture ────────────────────── */
|
||||||
@theme {
|
@theme {
|
||||||
|
|
||||||
/* Dark base — deep navy-black */
|
/* Dark base — deep navy-black */
|
||||||
--color-void: #050510;
|
--color-void: #050510;
|
||||||
--color-ink: #09091A;
|
--color-ink: #09091a;
|
||||||
--color-concrete: #0F0F22;
|
--color-concrete: #0f0f22;
|
||||||
--color-zinc: #1C1C38;
|
--color-zinc: #1c1c38;
|
||||||
--color-smoke: #383860;
|
--color-smoke: #383860;
|
||||||
--color-fog: #6868A0;
|
--color-fog: #6868a0;
|
||||||
--color-chalk: #B8B8E0;
|
--color-chalk: #b8b8e0;
|
||||||
--color-paper: #EEEEFF;
|
--color-paper: #eeeeff;
|
||||||
|
|
||||||
/* Gradient triad — pink → purple → ice */
|
/* Gradient triad — pink → purple → ice */
|
||||||
--color-heat: #FF1A8C; /* hot pink — primary energy */
|
--color-heat: #ff1a8c; /* hot pink — primary energy */
|
||||||
--color-pulse: #9B00FF; /* electric purple — mid */
|
--color-pulse: #9b00ff; /* electric purple — mid */
|
||||||
--color-frost: #00C8FF; /* ice blue — cool accent */
|
--color-frost: #00c8ff; /* ice blue — cool accent */
|
||||||
--color-ember: #FF4455; /* alert red */
|
--color-ember: #ff4455; /* alert red */
|
||||||
--color-lime: #1AFF8D; /* acid lime — highlight */
|
--color-lime: #1aff8d; /* acid lime — highlight */
|
||||||
--color-stem: #FF7A1A; /* peony stem orange */
|
--color-stem: #ff7a1a; /* peony stem orange */
|
||||||
|
|
||||||
/* Backward-compat aliases so existing templates still work */
|
/* Backward-compat aliases so existing templates still work */
|
||||||
--color-gold: var(--color-heat);
|
--color-gold: var(--color-heat);
|
||||||
--color-gold-dim: #CC1570;
|
--color-gold-dim: #cc1570;
|
||||||
--color-hot: var(--color-heat);
|
--color-hot: var(--color-heat);
|
||||||
--color-volt: var(--color-lime);
|
--color-volt: var(--color-lime);
|
||||||
--color-ice: var(--color-frost);
|
--color-ice: var(--color-frost);
|
||||||
--color-mist: var(--color-zinc);
|
--color-mist: var(--color-zinc);
|
||||||
--color-ash: var(--color-smoke);
|
--color-ash: var(--color-smoke);
|
||||||
--color-graphite: var(--color-concrete);
|
--color-graphite: var(--color-concrete);
|
||||||
--color-charcoal: var(--color-ink);
|
--color-charcoal: var(--color-ink);
|
||||||
|
|
||||||
/* ── Typography ─────────────────────────────────────────────── */
|
/* ── Typography ─────────────────────────────────────────────── */
|
||||||
--font-display: "Bebas Neue", "Arial Black", sans-serif;
|
--font-display: "Bebas Neue", "Arial Black", sans-serif;
|
||||||
--font-body: "Barlow", system-ui, sans-serif;
|
--font-body: "Barlow", system-ui, sans-serif;
|
||||||
--font-comic: "Unbounded", "Arial Black", sans-serif;
|
--font-comic: "Unbounded", "Arial Black", sans-serif;
|
||||||
--font-mono: "Share Tech Mono", "Courier New", monospace;
|
--font-mono: "Share Tech Mono", "Courier New", monospace;
|
||||||
|
|
||||||
/* ── Easing ─────────────────────────────────────────────────── */
|
/* ── Easing ─────────────────────────────────────────────────── */
|
||||||
--ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
|
--ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||||
--ease-sharp: cubic-bezier(0.4, 0, 0.6, 1);
|
--ease-sharp: cubic-bezier(0.4, 0, 0.6, 1);
|
||||||
--ease-cinematic: cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
--ease-cinematic: cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
|
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Base ─────────────────────────────────────────────────────── */
|
/* ── Base ─────────────────────────────────────────────────────── */
|
||||||
@layer base {
|
@layer base {
|
||||||
*, *::before, *::after { box-sizing: border-box; }
|
*,
|
||||||
[x-cloak] { display: none !important; }
|
*::before,
|
||||||
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
[x-cloak] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
background-color: var(--color-void);
|
background-color: var(--color-void);
|
||||||
@@ -66,9 +71,16 @@
|
|||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
body { min-height: 100vh; }
|
body {
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
font-family: var(--font-display);
|
font-family: var(--font-display);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
letter-spacing: 0.01em;
|
letter-spacing: 0.01em;
|
||||||
@@ -82,7 +94,12 @@
|
|||||||
transition: color 0.2s var(--ease-sharp);
|
transition: color 0.2s var(--ease-sharp);
|
||||||
}
|
}
|
||||||
|
|
||||||
img, video { max-width: 100%; height: auto; display: block; }
|
img,
|
||||||
|
video {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
::selection {
|
::selection {
|
||||||
background-color: var(--color-heat);
|
background-color: var(--color-heat);
|
||||||
@@ -95,14 +112,20 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Gradient scrollbar */
|
/* Gradient scrollbar */
|
||||||
::-webkit-scrollbar { width: 4px; height: 4px; }
|
::-webkit-scrollbar {
|
||||||
::-webkit-scrollbar-track { background: var(--color-ink); }
|
width: 4px;
|
||||||
::-webkit-scrollbar-thumb { background: linear-gradient(180deg, var(--color-heat), var(--color-frost)); }
|
height: 4px;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: var(--color-ink);
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: linear-gradient(180deg, var(--color-heat), var(--color-frost));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Components ───────────────────────────────────────────────── */
|
/* ── Components ───────────────────────────────────────────────── */
|
||||||
@layer components {
|
@layer components {
|
||||||
|
|
||||||
/* ── Gradient text ─────────────────────────────────────────── */
|
/* ── Gradient text ─────────────────────────────────────────── */
|
||||||
.text-gradient {
|
.text-gradient {
|
||||||
background: var(--color-heat);
|
background: var(--color-heat);
|
||||||
@@ -113,7 +136,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.text-gradient-animated {
|
.text-gradient-animated {
|
||||||
background: linear-gradient(90deg, var(--color-heat), var(--color-pulse), var(--color-frost), var(--color-heat));
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
var(--color-heat),
|
||||||
|
var(--color-pulse),
|
||||||
|
var(--color-frost),
|
||||||
|
var(--color-heat)
|
||||||
|
);
|
||||||
background-size: 300% 100%;
|
background-size: 300% 100%;
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
@@ -128,7 +157,7 @@
|
|||||||
to top,
|
to top,
|
||||||
rgba(5, 5, 16, 0.98) 0%,
|
rgba(5, 5, 16, 0.98) 0%,
|
||||||
rgba(5, 5, 16, 0.65) 40%,
|
rgba(5, 5, 16, 0.65) 40%,
|
||||||
rgba(5, 5, 16, 0.1) 70%,
|
rgba(5, 5, 16, 0.1) 70%,
|
||||||
transparent 100%
|
transparent 100%
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -136,8 +165,8 @@
|
|||||||
.overlay-gradient-hero {
|
.overlay-gradient-hero {
|
||||||
background: linear-gradient(
|
background: linear-gradient(
|
||||||
155deg,
|
155deg,
|
||||||
rgba(5, 5, 16, 0.1) 0%,
|
rgba(5, 5, 16, 0.1) 0%,
|
||||||
rgba(5, 5, 16, 0.5) 45%,
|
rgba(5, 5, 16, 0.5) 45%,
|
||||||
rgba(5, 5, 16, 0.97) 100%
|
rgba(5, 5, 16, 0.97) 100%
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -165,23 +194,58 @@
|
|||||||
padding: 5px 16px;
|
padding: 5px 16px;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
clip-path: polygon(8px 0, 100% 0, calc(100% - 8px) 100%, 0 100%);
|
clip-path: polygon(8px 0, 100% 0, calc(100% - 8px) 100%, 0 100%);
|
||||||
transition: transform 0.15s var(--ease-bounce), filter 0.2s;
|
transition:
|
||||||
|
transform 0.15s var(--ease-bounce),
|
||||||
|
filter 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.badge:hover { transform: skewX(-4deg) scale(1.06); filter: brightness(1.2); }
|
a.badge:hover {
|
||||||
a.badge, a > .badge { cursor: pointer; }
|
transform: skewX(-4deg) scale(1.06);
|
||||||
|
filter: brightness(1.2);
|
||||||
|
}
|
||||||
|
a.badge,
|
||||||
|
a > .badge {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.badge-heat { background: var(--color-heat); color: #fff; }
|
.badge-heat {
|
||||||
.badge-pulse { background: var(--color-pulse); color: #fff; }
|
background: var(--color-heat);
|
||||||
.badge-frost { background: var(--color-frost); color: var(--color-void); }
|
color: #fff;
|
||||||
.badge-lime { background: var(--color-lime); color: var(--color-void); }
|
}
|
||||||
.badge-ember { background: var(--color-ember); color: #fff; }
|
.badge-pulse {
|
||||||
.badge-stem { background: var(--color-stem); color: var(--color-void); }
|
background: var(--color-pulse);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.badge-frost {
|
||||||
|
background: var(--color-frost);
|
||||||
|
color: var(--color-void);
|
||||||
|
}
|
||||||
|
.badge-lime {
|
||||||
|
background: var(--color-lime);
|
||||||
|
color: var(--color-void);
|
||||||
|
}
|
||||||
|
.badge-ember {
|
||||||
|
background: var(--color-ember);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.badge-stem {
|
||||||
|
background: var(--color-stem);
|
||||||
|
color: var(--color-void);
|
||||||
|
}
|
||||||
|
|
||||||
/* Semantic aliases kept for template compat */
|
/* Semantic aliases kept for template compat */
|
||||||
.badge-hot { background: var(--color-heat); color: #fff; }
|
.badge-hot {
|
||||||
.badge-volt { background: var(--color-lime); color: var(--color-void); }
|
background: var(--color-heat);
|
||||||
.badge-ice { background: var(--color-frost); color: var(--color-void); }
|
color: #fff;
|
||||||
|
}
|
||||||
|
.badge-volt {
|
||||||
|
background: var(--color-lime);
|
||||||
|
color: var(--color-void);
|
||||||
|
}
|
||||||
|
.badge-ice {
|
||||||
|
background: var(--color-frost);
|
||||||
|
color: var(--color-void);
|
||||||
|
}
|
||||||
|
|
||||||
.badge-gradient {
|
.badge-gradient {
|
||||||
background: var(--color-heat);
|
background: var(--color-heat);
|
||||||
@@ -214,13 +278,13 @@
|
|||||||
clip-path: polygon(10px 0, 100% 0, calc(100% - 10px) 100%, 0 100%);
|
clip-path: polygon(10px 0, 100% 0, calc(100% - 10px) 100%, 0 100%);
|
||||||
transition:
|
transition:
|
||||||
box-shadow 0.25s var(--ease-sharp),
|
box-shadow 0.25s var(--ease-sharp),
|
||||||
transform 0.2s var(--ease-bounce);
|
transform 0.2s var(--ease-bounce);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* shimmer sweep */
|
/* shimmer sweep */
|
||||||
.btn::before {
|
.btn::before {
|
||||||
content: '';
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background: linear-gradient(
|
background: linear-gradient(
|
||||||
@@ -236,11 +300,16 @@
|
|||||||
|
|
||||||
.btn:hover {
|
.btn:hover {
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
box-shadow: 0 8px 32px rgba(255, 26, 140, 0.5),
|
box-shadow:
|
||||||
0 2px 8px rgba(155, 0, 255, 0.2);
|
0 8px 32px rgba(255, 26, 140, 0.5),
|
||||||
|
0 2px 8px rgba(155, 0, 255, 0.2);
|
||||||
|
}
|
||||||
|
.btn:hover::before {
|
||||||
|
transform: translateX(200%);
|
||||||
|
}
|
||||||
|
.btn:active {
|
||||||
|
transform: translateY(0px);
|
||||||
}
|
}
|
||||||
.btn:hover::before { transform: translateX(200%); }
|
|
||||||
.btn:active { transform: translateY(0px); }
|
|
||||||
|
|
||||||
.btn-outline {
|
.btn-outline {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
@@ -248,7 +317,9 @@
|
|||||||
color: var(--color-heat);
|
color: var(--color-heat);
|
||||||
clip-path: none;
|
clip-path: none;
|
||||||
}
|
}
|
||||||
.btn-outline::before { display: none; }
|
.btn-outline::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
.btn-outline:hover {
|
.btn-outline:hover {
|
||||||
background: var(--color-heat);
|
background: var(--color-heat);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
@@ -269,7 +340,9 @@
|
|||||||
color: var(--color-chalk);
|
color: var(--color-chalk);
|
||||||
clip-path: none;
|
clip-path: none;
|
||||||
}
|
}
|
||||||
.btn-ghost::before { display: none; }
|
.btn-ghost::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
.btn-ghost:hover {
|
.btn-ghost:hover {
|
||||||
border-color: var(--color-heat);
|
border-color: var(--color-heat);
|
||||||
color: var(--color-heat);
|
color: var(--color-heat);
|
||||||
@@ -301,13 +374,13 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transition:
|
transition:
|
||||||
border-color 0.2s var(--ease-sharp),
|
border-color 0.2s var(--ease-sharp),
|
||||||
box-shadow 0.3s var(--ease-out-expo),
|
box-shadow 0.3s var(--ease-out-expo),
|
||||||
transform 0.25s var(--ease-out-expo);
|
transform 0.25s var(--ease-out-expo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* gradient top bar */
|
/* gradient top bar */
|
||||||
.card-comic::after {
|
.card-comic::after {
|
||||||
content: '';
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
@@ -325,25 +398,30 @@
|
|||||||
box-shadow:
|
box-shadow:
|
||||||
0 0 0 1.5px rgba(255, 26, 140, 0.4),
|
0 0 0 1.5px rgba(255, 26, 140, 0.4),
|
||||||
0 20px 60px rgba(255, 26, 140, 0.18),
|
0 20px 60px rgba(255, 26, 140, 0.18),
|
||||||
0 8px 24px rgba(155, 0, 255, 0.12),
|
0 8px 24px rgba(155, 0, 255, 0.12),
|
||||||
6px 6px 0 rgba(255, 26, 140, 0.22);
|
6px 6px 0 rgba(255, 26, 140, 0.22);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-comic:hover::after { opacity: 1; }
|
.card-comic:hover::after {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Isometric triangle grid — 3 sets of lines at 0° / 60° / -60°
|
/* ── Isometric triangle grid — 3 sets of lines at 0° / 60° / -60°
|
||||||
Creates an infinite isometric floor-tile illusion.
|
Creates an infinite isometric floor-tile illusion.
|
||||||
Colors: heat (horizontal) · frost (60°) · pulse (-60°)
|
Colors: heat (horizontal) · frost (60°) · pulse (-60°)
|
||||||
────────────────────────────────────────────────────────────── */
|
────────────────────────────────────────────────────────────── */
|
||||||
.speed-lines {
|
.speed-lines {
|
||||||
background-image:
|
background-image: repeating-linear-gradient(
|
||||||
repeating-linear-gradient(
|
-55deg,
|
||||||
-55deg,
|
rgba(255, 26, 140, 0.14) 0,
|
||||||
rgba(255, 26, 140, 0.14) 0, rgba(255, 26, 140, 0.14) 1px,
|
rgba(255, 26, 140, 0.14) 1px,
|
||||||
transparent 1px, transparent 22px,
|
transparent 1px,
|
||||||
rgba(0, 200, 255, 0.08) 22px, rgba(0, 200, 255, 0.08) 23px,
|
transparent 22px,
|
||||||
transparent 23px, transparent 44px
|
rgba(0, 200, 255, 0.08) 22px,
|
||||||
);
|
rgba(0, 200, 255, 0.08) 23px,
|
||||||
|
transparent 23px,
|
||||||
|
transparent 44px
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Diamond crosshatch ──────────────────────────────────── */
|
/* ── Diamond crosshatch ──────────────────────────────────── */
|
||||||
@@ -351,13 +429,17 @@
|
|||||||
background-image:
|
background-image:
|
||||||
repeating-linear-gradient(
|
repeating-linear-gradient(
|
||||||
45deg,
|
45deg,
|
||||||
rgba(255, 26, 140, 0.07) 0, rgba(255, 26, 140, 0.07) 1px,
|
rgba(255, 26, 140, 0.07) 0,
|
||||||
transparent 1px, transparent 24px
|
rgba(255, 26, 140, 0.07) 1px,
|
||||||
|
transparent 1px,
|
||||||
|
transparent 24px
|
||||||
),
|
),
|
||||||
repeating-linear-gradient(
|
repeating-linear-gradient(
|
||||||
-45deg,
|
-45deg,
|
||||||
rgba(0, 200, 255, 0.05) 0, rgba(0, 200, 255, 0.05) 1px,
|
rgba(0, 200, 255, 0.05) 0,
|
||||||
transparent 1px, transparent 24px
|
rgba(0, 200, 255, 0.05) 1px,
|
||||||
|
transparent 1px,
|
||||||
|
transparent 24px
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,9 +447,13 @@
|
|||||||
.spray-bg {
|
.spray-bg {
|
||||||
background-image:
|
background-image:
|
||||||
radial-gradient(circle, rgba(255, 26, 140, 0.09) 1px, transparent 1px),
|
radial-gradient(circle, rgba(255, 26, 140, 0.09) 1px, transparent 1px),
|
||||||
radial-gradient(circle, rgba(0, 200, 255, 0.06) 1px, transparent 1px);
|
radial-gradient(circle, rgba(0, 200, 255, 0.06) 1px, transparent 1px);
|
||||||
background-size: 18px 18px, 29px 29px;
|
background-size:
|
||||||
background-position: 0 0, 9px 9px;
|
18px 18px,
|
||||||
|
29px 29px;
|
||||||
|
background-position:
|
||||||
|
0 0,
|
||||||
|
9px 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Noise overlay ──────────────────────────────────────────── */
|
/* ── Noise overlay ──────────────────────────────────────────── */
|
||||||
@@ -399,10 +485,15 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
animation: marquee-scroll 32s linear infinite;
|
animation: marquee-scroll 32s linear infinite;
|
||||||
}
|
}
|
||||||
.marquee-track:hover { animation-play-state: paused; }
|
.marquee-track:hover {
|
||||||
|
animation-play-state: paused;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Section rules ──────────────────────────────────────────── */
|
/* ── Section rules ──────────────────────────────────────────── */
|
||||||
.section-rule { border: none; border-top: 1px solid var(--color-zinc); }
|
.section-rule {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--color-zinc);
|
||||||
|
}
|
||||||
|
|
||||||
.section-rule-electric {
|
.section-rule-electric {
|
||||||
border: none;
|
border: none;
|
||||||
@@ -419,9 +510,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ── Neon glow utilities ────────────────────────────────────── */
|
/* ── Neon glow utilities ────────────────────────────────────── */
|
||||||
.neon-heat { box-shadow: 0 0 24px rgba(255, 26, 140, 0.35), 0 0 60px rgba(255, 26, 140, 0.08); }
|
.neon-heat {
|
||||||
.neon-pulse { box-shadow: 0 0 24px rgba(155, 0, 255, 0.35), 0 0 60px rgba(155, 0, 255, 0.08); }
|
box-shadow:
|
||||||
.neon-frost { box-shadow: 0 0 24px rgba( 0, 200, 255, 0.35), 0 0 60px rgba( 0, 200, 255, 0.08); }
|
0 0 24px rgba(255, 26, 140, 0.35),
|
||||||
|
0 0 60px rgba(255, 26, 140, 0.08);
|
||||||
|
}
|
||||||
|
.neon-pulse {
|
||||||
|
box-shadow:
|
||||||
|
0 0 24px rgba(155, 0, 255, 0.35),
|
||||||
|
0 0 60px rgba(155, 0, 255, 0.08);
|
||||||
|
}
|
||||||
|
.neon-frost {
|
||||||
|
box-shadow:
|
||||||
|
0 0 24px rgba(0, 200, 255, 0.35),
|
||||||
|
0 0 60px rgba(0, 200, 255, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Prose editorial ────────────────────────────────────────── */
|
/* ── Prose editorial ────────────────────────────────────────── */
|
||||||
.prose-editorial {
|
.prose-editorial {
|
||||||
@@ -432,15 +535,25 @@
|
|||||||
max-width: 72ch;
|
max-width: 72ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose-editorial > * + * { margin-top: 1.6em; }
|
.prose-editorial > * + * {
|
||||||
|
margin-top: 1.6em;
|
||||||
|
}
|
||||||
|
|
||||||
.prose-editorial strong { color: var(--color-paper); font-weight: 600; }
|
.prose-editorial strong {
|
||||||
.prose-editorial em { font-style: italic; color: var(--color-paper); }
|
color: var(--color-paper);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.prose-editorial em {
|
||||||
|
font-style: italic;
|
||||||
|
color: var(--color-paper);
|
||||||
|
}
|
||||||
|
|
||||||
.prose-editorial a {
|
.prose-editorial a {
|
||||||
color: var(--color-heat);
|
color: var(--color-heat);
|
||||||
border-bottom: 1px solid rgba(255, 26, 140, 0.35);
|
border-bottom: 1px solid rgba(255, 26, 140, 0.35);
|
||||||
transition: border-color 0.2s, color 0.2s;
|
transition:
|
||||||
|
border-color 0.2s,
|
||||||
|
color 0.2s;
|
||||||
}
|
}
|
||||||
.prose-editorial a:hover {
|
.prose-editorial a:hover {
|
||||||
color: var(--color-frost);
|
color: var(--color-frost);
|
||||||
@@ -457,7 +570,9 @@
|
|||||||
letter-spacing: 0.01em;
|
letter-spacing: 0.01em;
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
}
|
}
|
||||||
.prose-editorial blockquote p { margin: 0; }
|
.prose-editorial blockquote p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.prose-editorial h2 {
|
.prose-editorial h2 {
|
||||||
font-size: 2.5rem;
|
font-size: 2.5rem;
|
||||||
@@ -509,7 +624,9 @@
|
|||||||
background: linear-gradient(90deg, var(--color-heat), var(--color-pulse), var(--color-frost));
|
background: linear-gradient(90deg, var(--color-heat), var(--color-pulse), var(--color-frost));
|
||||||
box-shadow: 0 0 12px rgba(255, 26, 140, 0.6);
|
box-shadow: 0 0 12px rgba(255, 26, 140, 0.6);
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
transition: width 0.4s var(--ease-out-expo), opacity 0.3s ease;
|
transition:
|
||||||
|
width 0.4s var(--ease-out-expo),
|
||||||
|
opacity 0.3s ease;
|
||||||
width: 0;
|
width: 0;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
@@ -517,62 +634,128 @@
|
|||||||
|
|
||||||
/* ── Utilities ────────────────────────────────────────────────── */
|
/* ── Utilities ────────────────────────────────────────────────── */
|
||||||
@layer utilities {
|
@layer utilities {
|
||||||
|
|
||||||
.gutter-x {
|
.gutter-x {
|
||||||
padding-left: clamp(1rem, 4vw, 3rem);
|
padding-left: clamp(1rem, 4vw, 3rem);
|
||||||
padding-right: clamp(1rem, 4vw, 3rem);
|
padding-right: clamp(1rem, 4vw, 3rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Aspect ratios */
|
/* Aspect ratios */
|
||||||
.aspect-editorial { aspect-ratio: 3 / 4; }
|
.aspect-editorial {
|
||||||
.aspect-cinema { aspect-ratio: 21 / 9; }
|
aspect-ratio: 3 / 4;
|
||||||
.aspect-portrait { aspect-ratio: 2 / 3; }
|
}
|
||||||
|
.aspect-cinema {
|
||||||
|
aspect-ratio: 21 / 9;
|
||||||
|
}
|
||||||
|
.aspect-portrait {
|
||||||
|
aspect-ratio: 2 / 3;
|
||||||
|
}
|
||||||
|
|
||||||
/* Text wrapping */
|
/* Text wrapping */
|
||||||
.text-balance { text-wrap: balance; }
|
.text-balance {
|
||||||
.text-pretty { text-wrap: pretty; }
|
text-wrap: balance;
|
||||||
|
}
|
||||||
|
.text-pretty {
|
||||||
|
text-wrap: pretty;
|
||||||
|
}
|
||||||
|
|
||||||
/* Offset shadow */
|
/* Offset shadow */
|
||||||
.shadow-comic { box-shadow: 5px 5px 0 var(--color-heat); }
|
.shadow-comic {
|
||||||
.shadow-comic-hot { box-shadow: 5px 5px 0 var(--color-heat); }
|
box-shadow: 5px 5px 0 var(--color-heat);
|
||||||
.shadow-comic-volt { box-shadow: 5px 5px 0 var(--color-lime); }
|
}
|
||||||
.shadow-comic-ice { box-shadow: 5px 5px 0 var(--color-frost); }
|
.shadow-comic-hot {
|
||||||
|
box-shadow: 5px 5px 0 var(--color-heat);
|
||||||
|
}
|
||||||
|
.shadow-comic-volt {
|
||||||
|
box-shadow: 5px 5px 0 var(--color-lime);
|
||||||
|
}
|
||||||
|
.shadow-comic-ice {
|
||||||
|
box-shadow: 5px 5px 0 var(--color-frost);
|
||||||
|
}
|
||||||
|
|
||||||
/* Text stroke — hollow headline */
|
/* Text stroke — hollow headline */
|
||||||
.text-stroke-gold { -webkit-text-stroke: 1.5px var(--color-heat); color: transparent; }
|
.text-stroke-gold {
|
||||||
.text-stroke-paper { -webkit-text-stroke: 1.5px var(--color-paper); color: transparent; }
|
-webkit-text-stroke: 1.5px var(--color-heat);
|
||||||
.text-stroke-heat { -webkit-text-stroke: 1.5px var(--color-heat); color: transparent; }
|
color: transparent;
|
||||||
.text-stroke-frost { -webkit-text-stroke: 1.5px var(--color-frost); color: transparent; }
|
}
|
||||||
|
.text-stroke-paper {
|
||||||
|
-webkit-text-stroke: 1.5px var(--color-paper);
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
.text-stroke-heat {
|
||||||
|
-webkit-text-stroke: 1.5px var(--color-heat);
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
.text-stroke-frost {
|
||||||
|
-webkit-text-stroke: 1.5px var(--color-frost);
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
/* Scrollbar hide */
|
/* Scrollbar hide */
|
||||||
.scrollbar-hide { scrollbar-width: none; -ms-overflow-style: none; }
|
.scrollbar-hide {
|
||||||
.scrollbar-hide::-webkit-scrollbar { display: none; }
|
scrollbar-width: none;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
}
|
||||||
|
.scrollbar-hide::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Keyframes ────────────────────────────────────────────────── */
|
/* ── Keyframes ────────────────────────────────────────────────── */
|
||||||
@keyframes gradient-shift {
|
@keyframes gradient-shift {
|
||||||
0% { background-position: 0% 50%; }
|
0% {
|
||||||
50% { background-position: 100% 50%; }
|
background-position: 0% 50%;
|
||||||
100% { background-position: 0% 50%; }
|
}
|
||||||
|
50% {
|
||||||
|
background-position: 100% 50%;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
background-position: 0% 50%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes marquee-scroll {
|
@keyframes marquee-scroll {
|
||||||
to { transform: translateX(-50%); }
|
to {
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes scroll-line {
|
@keyframes scroll-line {
|
||||||
0% { transform: translateY(-100%); opacity: 0; }
|
0% {
|
||||||
20% { opacity: 1; }
|
transform: translateY(-100%);
|
||||||
80% { opacity: 1; }
|
opacity: 0;
|
||||||
100% { transform: translateY(100%); opacity: 0; }
|
}
|
||||||
|
20% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
80% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateY(100%);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Logo glitch animation ───────────────────────────────────── */
|
/* ── Logo glitch animation ───────────────────────────────────── */
|
||||||
@keyframes glitch-clip {
|
@keyframes glitch-clip {
|
||||||
0%, 88%, 100% { transform: translate(0); clip-path: none; }
|
0%,
|
||||||
90% { transform: translate(-3px, 1px); clip-path: polygon(0 15%, 100% 15%, 100% 40%, 0 40%); }
|
88%,
|
||||||
92% { transform: translate(3px, -1px); clip-path: polygon(0 60%, 100% 60%, 100% 78%, 0 78%); }
|
100% {
|
||||||
94% { transform: translate(0); clip-path: none; }
|
transform: translate(0);
|
||||||
|
clip-path: none;
|
||||||
|
}
|
||||||
|
90% {
|
||||||
|
transform: translate(-3px, 1px);
|
||||||
|
clip-path: polygon(0 15%, 100% 15%, 100% 40%, 0 40%);
|
||||||
|
}
|
||||||
|
92% {
|
||||||
|
transform: translate(3px, -1px);
|
||||||
|
clip-path: polygon(0 60%, 100% 60%, 100% 78%, 0 78%);
|
||||||
|
}
|
||||||
|
94% {
|
||||||
|
transform: translate(0);
|
||||||
|
clip-path: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a:hover .logo-glitch {
|
a:hover .logo-glitch {
|
||||||
@@ -591,15 +774,24 @@ footer .logo-img {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes logo-float {
|
@keyframes logo-float {
|
||||||
0%, 100% { transform: translateY(0); filter: drop-shadow(0 0 8px rgba(255, 26, 140, 0.35)); }
|
0%,
|
||||||
50% { transform: translateY(-4px); filter: drop-shadow(0 6px 14px rgba(255, 26, 140, 0.6)); }
|
100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
filter: drop-shadow(0 0 8px rgba(255, 26, 140, 0.35));
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(-4px);
|
||||||
|
filter: drop-shadow(0 6px 14px rgba(255, 26, 140, 0.6));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Nav & footer link hover polish ─────────────────────────── */
|
/* ── Nav & footer link hover polish ─────────────────────────── */
|
||||||
|
|
||||||
/* Desktop nav links — lift + glow on hover */
|
/* Desktop nav links — lift + glow on hover */
|
||||||
header nav a.label {
|
header nav a.label {
|
||||||
transition: color 0.2s var(--ease-sharp), transform 0.2s var(--ease-out-expo);
|
transition:
|
||||||
|
color 0.2s var(--ease-sharp),
|
||||||
|
transform 0.2s var(--ease-out-expo);
|
||||||
}
|
}
|
||||||
header nav a.label:hover {
|
header nav a.label:hover {
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
@@ -612,7 +804,9 @@ header nav a.label span {
|
|||||||
|
|
||||||
/* Footer links — subtle lift */
|
/* Footer links — subtle lift */
|
||||||
footer nav a.label {
|
footer nav a.label {
|
||||||
transition: color 0.2s var(--ease-sharp), transform 0.2s var(--ease-out-expo);
|
transition:
|
||||||
|
color 0.2s var(--ease-sharp),
|
||||||
|
transform 0.2s var(--ease-out-expo);
|
||||||
}
|
}
|
||||||
footer nav a.label:hover {
|
footer nav a.label:hover {
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
@@ -636,10 +830,15 @@ footer nav a.label:hover svg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes page-out {
|
@keyframes page-out {
|
||||||
to { opacity: 0; transform: translateY(-10px); }
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes page-in {
|
@keyframes page-in {
|
||||||
from { opacity: 0; transform: translateY(14px); }
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(14px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-5
@@ -17,7 +17,9 @@
|
|||||||
bar.style.width = "100%";
|
bar.style.width = "100%";
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
bar.style.opacity = "0";
|
bar.style.opacity = "0";
|
||||||
setTimeout(() => { bar.style.width = "0"; }, 350);
|
setTimeout(() => {
|
||||||
|
bar.style.width = "0";
|
||||||
|
}, 350);
|
||||||
}, 150);
|
}, 150);
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
@@ -37,9 +39,11 @@ function initLazyVideos(root) {
|
|||||||
observer.unobserve(video);
|
observer.unobserve(video);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
{ rootMargin: "300px" }
|
{ rootMargin: "300px" },
|
||||||
);
|
);
|
||||||
(root || document).querySelectorAll("video[data-src]").forEach((v) => observer.observe(v));
|
(root || document)
|
||||||
|
.querySelectorAll("video[data-src]")
|
||||||
|
.forEach((v) => observer.observe(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
initLazyVideos();
|
initLazyVideos();
|
||||||
@@ -67,7 +71,9 @@ document.body.addEventListener("htmx:historyRestore", () => {
|
|||||||
bar.style.width = "100%";
|
bar.style.width = "100%";
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
bar.style.opacity = "0";
|
bar.style.opacity = "0";
|
||||||
setTimeout(() => { bar.style.width = "0"; }, 350);
|
setTimeout(() => {
|
||||||
|
bar.style.width = "0";
|
||||||
|
}, 350);
|
||||||
}, 150);
|
}, 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,4 +87,3 @@ document.body.addEventListener("htmx:historyRestore", () => {
|
|||||||
window.scrollTo({ top: 0, behavior: "instant" });
|
window.scrollTo({ top: 0, behavior: "instant" });
|
||||||
window.dispatchEvent(new Event("scroll"));
|
window.dispatchEvent(new Event("scroll"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ title: "About Pivoine"
|
|||||||
description: "A magazine dedicated to the intersection of artificial intelligence and aesthetic culture."
|
description: "A magazine dedicated to the intersection of artificial intelligence and aesthetic culture."
|
||||||
---
|
---
|
||||||
|
|
||||||
*Pivoine* is an independent editorial project exploring how machine intelligence reshapes visual culture.
|
_Pivoine_ is an independent editorial project exploring how machine intelligence reshapes visual culture.
|
||||||
|
|
||||||
We publish editorial features, artist profiles, and critical essays about AI-generated art — approaching this emerging medium with the same rigour and aesthetic seriousness as any other.
|
We publish editorial features, artist profiles, and critical essays about AI-generated art — approaching this emerging medium with the same rigour and aesthetic seriousness as any other.
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ The name comes from the French word for **peony** — a flower that is both extr
|
|||||||
|
|
||||||
## What We Publish
|
## What We Publish
|
||||||
|
|
||||||
We are interested in the **editorial dimension** of AI image-making. Not the tools, not the prompts, not the speed records — but the *work* itself and the questions it raises about authorship, aesthetics, and what it means to make an image in an age when images are free.
|
We are interested in the **editorial dimension** of AI image-making. Not the tools, not the prompts, not the speed records — but the _work_ itself and the questions it raises about authorship, aesthetics, and what it means to make an image in an age when images are free.
|
||||||
|
|
||||||
Each feature is a collaboration between a human sensibility and a machine process. The artists and authors we publish treat the generator as a medium, not a shortcut.
|
Each feature is a collaboration between a human sensibility and a machine process. The artists and authors we publish treat the generator as a medium, not a shortcut.
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
---
|
---
|
||||||
title: "Valknar"
|
title: "Valknar"
|
||||||
name: "Valknar"
|
name: "Valknar"
|
||||||
bio: "Valknar treats diffusion models as a engine of contradiction — pitting the cute against the grotesque, the opulent against the decayed, and the familiar against the deeply wrong. The results are cinematic concept images that feel like stills from films that should not exist."
|
bio: "Valknar treats diffusion models as a engine of contradiction — pitting the cute against the grotesque, the opulent against the decayed, and the familiar against the deeply wrong. The results are cinematic concept images that feel like stills from films that should not exist."
|
||||||
social:
|
social:
|
||||||
instagram: "valknarix"
|
instagram: "valknarix"
|
||||||
x: "valknar100"
|
x: "valknar100"
|
||||||
---
|
---
|
||||||
|
|
||||||
Valknar approaches AI generation as a collision course. The work takes familiar cultural touchstones — video game icons, children's characters, Renaissance still life — and forces them through genre frameworks they were never designed to survive: survival horror, Gigeresque biomechanics, neo-Tokyo neon, Burtonesque gothic.
|
Valknar approaches AI generation as a collision course. The work takes familiar cultural touchstones — video game icons, children's characters, Renaissance still life — and forces them through genre frameworks they were never designed to survive: survival horror, Gigeresque biomechanics, neo-Tokyo neon, Burtonesque gothic.
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ description: "Legal information and editorial responsibility."
|
|||||||
|
|
||||||
## Editorial Policy
|
## Editorial Policy
|
||||||
|
|
||||||
*Pivoine* is an independent publication. All AI-generated images and videos published on this site are the creative work of the named authors using various generative AI tools. The editorial team curates, commissions, and publishes this work under the publication's name.
|
_Pivoine_ is an independent publication. All AI-generated images and videos published on this site are the creative work of the named authors using various generative AI tools. The editorial team curates, commissions, and publishes this work under the publication's name.
|
||||||
|
|
||||||
## Copyright
|
## Copyright
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
---
|
---
|
||||||
title: "The Pale Pour"
|
title: "The Pale Pour"
|
||||||
description: "A skeletal Grim Reaper tends bar in a subterranean Gothic absinthe den, where the Green Fairy's bioluminescent fog coils between candlelit bottles and tarnished mirrors."
|
description: "A skeletal Grim Reaper tends bar in a subterranean Gothic absinthe den, where the Green Fairy's bioluminescent fog coils between candlelit bottles and tarnished mirrors."
|
||||||
date: 2026-05-07
|
date: 2026-05-07
|
||||||
author: "valknar"
|
author: "valknar"
|
||||||
featured: true
|
featured: true
|
||||||
categories:
|
categories:
|
||||||
- Dark
|
- Dark
|
||||||
- Surrealist
|
- Surrealist
|
||||||
@@ -17,7 +17,7 @@ tags:
|
|||||||
- Macabre
|
- Macabre
|
||||||
slug: the-pale-pour
|
slug: the-pale-pour
|
||||||
prompt:
|
prompt:
|
||||||
scene: "A cinematic, wide-angle interior shot of a subterranean, rustic Gothic Absinthe bar. The atmosphere is thick with a swirling, ethereal green bioluminescent fog (\"The Green Fairy\"). In the center, a skeletal Grim Reaper stands behind a heavy, scarred oak bar, draped in tattered, ink-black hooded robes; his bony hands are delicately preparing a traditional absinthe drip over a silver slotted spoon and sugar cube."
|
scene: 'A cinematic, wide-angle interior shot of a subterranean, rustic Gothic Absinthe bar. The atmosphere is thick with a swirling, ethereal green bioluminescent fog ("The Green Fairy"). In the center, a skeletal Grim Reaper stands behind a heavy, scarred oak bar, draped in tattered, ink-black hooded robes; his bony hands are delicately preparing a traditional absinthe drip over a silver slotted spoon and sugar cube.'
|
||||||
environment: "Vaulted stone ceilings with cracked ribs, dripping wax from oversized iron chandeliers, walls lined with dusty, unlabeled apothecary bottles and antique mirrors showing tarnished reflections. Plush, rotting emerald velvet barstools and flickering candlelight."
|
environment: "Vaulted stone ceilings with cracked ribs, dripping wax from oversized iron chandeliers, walls lined with dusty, unlabeled apothecary bottles and antique mirrors showing tarnished reflections. Plush, rotting emerald velvet barstools and flickering candlelight."
|
||||||
style: "Moody chiaroscuro lighting, deep shadows contrasted with vibrant neon-emerald highlights. Art Nouveau accents, hyper-realistic textures of bone, aged wood, and etched glass. Dark Victorian aesthetic, macabre elegance, 8k resolution, photorealistic with a touch of oil painting gloom."
|
style: "Moody chiaroscuro lighting, deep shadows contrasted with vibrant neon-emerald highlights. Art Nouveau accents, hyper-realistic textures of bone, aged wood, and etched glass. Dark Victorian aesthetic, macabre elegance, 8k resolution, photorealistic with a touch of oil painting gloom."
|
||||||
video: "Cinematic dolly shot: The grim reaper in a dark cloak stands at a dimly lit Absinth bar, surrounded by glowing green potions. The camera slowly zooms in on the figure as he dunks a spoon in the green potion with one hand and with his other hand's index finger igniting the spoon into a small flame."
|
video: "Cinematic dolly shot: The grim reaper in a dark cloak stands at a dimly lit Absinth bar, surrounded by glowing green potions. The camera slowly zooms in on the figure as he dunks a spoon in the green potion with one hand and with his other hand's index finger igniting the spoon into a small flame."
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
---
|
---
|
||||||
title: "The Count's Chamber"
|
title: "The Count's Chamber"
|
||||||
description: "The room speaks before its master does — an ancient Gothic chamber of firelight and shadow, an armchair that still holds the warmth of centuries, and a wine glass of blood on a small table, patiently waiting."
|
description: "The room speaks before its master does — an ancient Gothic chamber of firelight and shadow, an armchair that still holds the warmth of centuries, and a wine glass of blood on a small table, patiently waiting."
|
||||||
date: 2026-05-08
|
date: 2026-05-08
|
||||||
author: "valknar"
|
author: "valknar"
|
||||||
featured: false
|
featured: false
|
||||||
categories:
|
categories:
|
||||||
- Dark
|
- Dark
|
||||||
- Gothic
|
- Gothic
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
---
|
---
|
||||||
title: "The Warlord's Hour"
|
title: "The Warlord's Hour"
|
||||||
description: "A fearsome samurai warlord, clad in magnificent lacquered armour, receives the quiet ceremony of sake from a geisha — power and grace suspended in a single, breathless moment on an ancient throne."
|
description: "A fearsome samurai warlord, clad in magnificent lacquered armour, receives the quiet ceremony of sake from a geisha — power and grace suspended in a single, breathless moment on an ancient throne."
|
||||||
date: 2026-05-08
|
date: 2026-05-08
|
||||||
author: "valknar"
|
author: "valknar"
|
||||||
featured: false
|
featured: false
|
||||||
categories:
|
categories:
|
||||||
- Historical
|
- Historical
|
||||||
- Dark
|
- Dark
|
||||||
|
|||||||
@@ -1,69 +1,69 @@
|
|||||||
baseURL = "https://pivoine.art/"
|
baseURL = "https://pivoine.art/"
|
||||||
languageCode = "en-us"
|
languageCode = "en-us"
|
||||||
title = "Pivoine"
|
title = "Pivoine"
|
||||||
copyright = "© 2026 Pivoine Editorial"
|
copyright = "© 2026 Pivoine Editorial"
|
||||||
|
|
||||||
enableRobotsTXT = true
|
enableRobotsTXT = true
|
||||||
|
|
||||||
[pagination]
|
[pagination]
|
||||||
pagerSize = 12
|
pagerSize = 12
|
||||||
|
|
||||||
[sitemap]
|
[sitemap]
|
||||||
changefreq = "weekly"
|
changefreq = "weekly"
|
||||||
priority = 0.5
|
priority = 0.5
|
||||||
filename = "sitemap.xml"
|
filename = "sitemap.xml"
|
||||||
|
|
||||||
[params]
|
[params]
|
||||||
description = "An editorial magazine for AI-generated art and generative aesthetics."
|
description = "An editorial magazine for AI-generated art and generative aesthetics."
|
||||||
tagline = "Where the machine dreams."
|
tagline = "Where the machine dreams."
|
||||||
author = "Pivoine Editorial"
|
author = "Pivoine Editorial"
|
||||||
ogImage = "/images/og-default.jpg"
|
ogImage = "/images/og-default.jpg"
|
||||||
logoText = "PIVOINE"
|
logoText = "PIVOINE"
|
||||||
copyrightYear = "2026"
|
copyrightYear = "2026"
|
||||||
twitterHandle = "valknar100"
|
twitterHandle = "valknar100"
|
||||||
umamiSrc = "https://umami.pivoine.art/script.js"
|
umamiSrc = "https://umami.pivoine.art/script.js"
|
||||||
umamiId = "9190b814-0480-498a-b5fe-1fe1dc162766"
|
umamiId = "9190b814-0480-498a-b5fe-1fe1dc162766"
|
||||||
|
|
||||||
[params.social]
|
[params.social]
|
||||||
instagram = "https://instagram.com/valknarix"
|
instagram = "https://instagram.com/valknarix"
|
||||||
x = "https://x.com/valknar100"
|
x = "https://x.com/valknar100"
|
||||||
|
|
||||||
[taxonomies]
|
[taxonomies]
|
||||||
category = "categories"
|
category = "categories"
|
||||||
tag = "tags"
|
tag = "tags"
|
||||||
|
|
||||||
[[menus.main]]
|
[[menus.main]]
|
||||||
name = "Posts"
|
name = "Posts"
|
||||||
url = "/posts/"
|
url = "/posts/"
|
||||||
weight = 1
|
weight = 1
|
||||||
[[menus.main]]
|
[[menus.main]]
|
||||||
name = "Authors"
|
name = "Authors"
|
||||||
url = "/authors/"
|
url = "/authors/"
|
||||||
weight = 2
|
weight = 2
|
||||||
[[menus.main]]
|
[[menus.main]]
|
||||||
name = "Categories"
|
name = "Categories"
|
||||||
url = "/categories/"
|
url = "/categories/"
|
||||||
weight = 3
|
weight = 3
|
||||||
[[menus.main]]
|
[[menus.main]]
|
||||||
name = "About"
|
name = "About"
|
||||||
url = "/about/"
|
url = "/about/"
|
||||||
weight = 4
|
weight = 4
|
||||||
|
|
||||||
[[menus.footer]]
|
[[menus.footer]]
|
||||||
name = "About"
|
name = "About"
|
||||||
url = "/about/"
|
url = "/about/"
|
||||||
weight = 1
|
weight = 1
|
||||||
[[menus.footer]]
|
[[menus.footer]]
|
||||||
name = "Imprint"
|
name = "Imprint"
|
||||||
url = "/imprint/"
|
url = "/imprint/"
|
||||||
weight = 2
|
weight = 2
|
||||||
|
|
||||||
[markup.goldmark.renderer]
|
[markup.goldmark.renderer]
|
||||||
unsafe = true
|
unsafe = true
|
||||||
|
|
||||||
[markup.highlight]
|
[markup.highlight]
|
||||||
style = "dracula"
|
style = "dracula"
|
||||||
noClasses = true
|
noClasses = true
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
writeStats = true
|
writeStats = true
|
||||||
|
|||||||
+62
-56
@@ -1,65 +1,71 @@
|
|||||||
{{- define "main" -}}
|
{{- define "main" -}}
|
||||||
<section class="relative min-h-screen flex flex-col items-center justify-center overflow-hidden noise gutter-x py-32 text-center">
|
<section
|
||||||
|
class="relative min-h-screen flex flex-col items-center justify-center overflow-hidden noise gutter-x py-32 text-center"
|
||||||
|
>
|
||||||
|
<!-- Background texture -->
|
||||||
|
<div class="absolute inset-0 speed-lines opacity-60"></div>
|
||||||
|
<div
|
||||||
|
class="absolute inset-0"
|
||||||
|
style="background: radial-gradient(ellipse 80% 60% at 50% 50%, rgba(155,0,255,0.06) 0%, transparent 70%)"
|
||||||
|
></div>
|
||||||
|
|
||||||
<!-- Background texture -->
|
<!-- Decorative hollow "404" behind everything -->
|
||||||
<div class="absolute inset-0 speed-lines opacity-60"></div>
|
<div class="absolute inset-0 flex items-center justify-center pointer-events-none select-none" aria-hidden="true">
|
||||||
<div class="absolute inset-0"
|
<span
|
||||||
style="background: radial-gradient(ellipse 80% 60% at 50% 50%, rgba(155,0,255,0.06) 0%, transparent 70%)"></div>
|
class="font-display leading-none"
|
||||||
|
style="font-size: clamp(14rem, 40vw, 32rem);
|
||||||
<!-- Decorative hollow "404" behind everything -->
|
|
||||||
<div class="absolute inset-0 flex items-center justify-center pointer-events-none select-none" aria-hidden="true">
|
|
||||||
<span
|
|
||||||
class="font-display leading-none"
|
|
||||||
style="font-size: clamp(14rem, 40vw, 32rem);
|
|
||||||
color: transparent;
|
color: transparent;
|
||||||
-webkit-text-stroke: 1px rgba(255,26,140,0.07);
|
-webkit-text-stroke: 1px rgba(255,26,140,0.07);
|
||||||
letter-spacing: -0.02em;">404</span>
|
letter-spacing: -0.02em;"
|
||||||
</div>
|
>404</span
|
||||||
|
>
|
||||||
<!-- Content -->
|
|
||||||
<div class="relative z-10 flex flex-col items-center gap-6 max-w-2xl mx-auto">
|
|
||||||
|
|
||||||
<!-- Eyebrow badge -->
|
|
||||||
<span class="badge badge-gradient" style="animation: mob-link-in 0.5s var(--ease-out-expo) 0ms both">
|
|
||||||
Error 404
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<!-- Main headline -->
|
|
||||||
<h1
|
|
||||||
class="font-display leading-none text-balance"
|
|
||||||
style="font-size: clamp(4rem, 14vw, 10rem);
|
|
||||||
animation: mob-link-in 0.6s var(--ease-out-expo) 80ms both"
|
|
||||||
>
|
|
||||||
<span class="text-stroke-heat">PAGE</span><br>
|
|
||||||
<span class="text-gradient">NOT FOUND</span>
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<!-- Gradient divider -->
|
|
||||||
<div class="gradient-line w-32 mx-auto" style="animation: mob-link-in 0.4s ease 200ms both"></div>
|
|
||||||
|
|
||||||
<!-- Description -->
|
|
||||||
<p
|
|
||||||
class="text-fog font-body text-base md:text-lg leading-relaxed max-w-md text-pretty"
|
|
||||||
style="animation: mob-link-in 0.5s var(--ease-out-expo) 260ms both"
|
|
||||||
>
|
|
||||||
This drop got pulled. The page you're looking for doesn't exist, was moved, or got lost in the grid.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<!-- CTA -->
|
|
||||||
<div class="flex flex-wrap gap-4 justify-center"
|
|
||||||
style="animation: mob-link-in 0.5s var(--ease-out-expo) 340ms both">
|
|
||||||
<a href="/" class="btn">Back to the Drop {{ partial "icon.html" "arrow-right" }}</a>
|
|
||||||
<a href="/posts/" class="btn btn-ghost">Browse all posts {{ partial "icon.html" "arrow-right" }}</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
<!-- Content -->
|
||||||
|
<div class="relative z-10 flex flex-col items-center gap-6 max-w-2xl mx-auto">
|
||||||
|
<!-- Eyebrow badge -->
|
||||||
|
<span class="badge badge-gradient" style="animation: mob-link-in 0.5s var(--ease-out-expo) 0ms both">
|
||||||
|
Error 404
|
||||||
|
</span>
|
||||||
|
|
||||||
<!-- Bottom graffiti tag -->
|
<!-- Main headline -->
|
||||||
<div
|
<h1
|
||||||
class="graffiti-tag absolute -bottom-6 left-1/2 -translate-x-1/2 select-none pointer-events-none whitespace-nowrap"
|
class="font-display leading-none text-balance"
|
||||||
style="-webkit-text-stroke-color: rgba(0,200,255,0.05);"
|
style="font-size: clamp(4rem, 14vw, 10rem);
|
||||||
aria-hidden="true"
|
animation: mob-link-in 0.6s var(--ease-out-expo) 80ms both"
|
||||||
>LOST</div>
|
>
|
||||||
|
<span class="text-stroke-heat">PAGE</span><br />
|
||||||
|
<span class="text-gradient">NOT FOUND</span>
|
||||||
|
</h1>
|
||||||
|
|
||||||
</section>
|
<!-- Gradient divider -->
|
||||||
|
<div class="gradient-line w-32 mx-auto" style="animation: mob-link-in 0.4s ease 200ms both"></div>
|
||||||
|
|
||||||
|
<!-- Description -->
|
||||||
|
<p
|
||||||
|
class="text-fog font-body text-base md:text-lg leading-relaxed max-w-md text-pretty"
|
||||||
|
style="animation: mob-link-in 0.5s var(--ease-out-expo) 260ms both"
|
||||||
|
>
|
||||||
|
This drop got pulled. The page you're looking for doesn't exist, was moved, or got lost in the grid.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- CTA -->
|
||||||
|
<div
|
||||||
|
class="flex flex-wrap gap-4 justify-center"
|
||||||
|
style="animation: mob-link-in 0.5s var(--ease-out-expo) 340ms both"
|
||||||
|
>
|
||||||
|
<a href="/" class="btn">Back to the Drop {{ partial "icon.html" "arrow-right" }}</a>
|
||||||
|
<a href="/posts/" class="btn btn-ghost">Browse all posts {{ partial "icon.html" "arrow-right" }}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Bottom graffiti tag -->
|
||||||
|
<div
|
||||||
|
class="graffiti-tag absolute -bottom-6 left-1/2 -translate-x-1/2 select-none pointer-events-none whitespace-nowrap"
|
||||||
|
style="-webkit-text-stroke-color: rgba(0,200,255,0.05);"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
LOST
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|||||||
+155
-119
@@ -1,33 +1,34 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="{{ .Site.LanguageCode }}" class="scroll-smooth">
|
<html lang="{{ .Site.LanguageCode }}" class="scroll-smooth">
|
||||||
<head>
|
<head>
|
||||||
{{- partial "head.html" . -}}
|
{{- partial "head.html" . -}}
|
||||||
</head>
|
</head>
|
||||||
<body
|
<body
|
||||||
class="bg-void text-paper font-body min-h-screen flex flex-col antialiased"
|
class="bg-void text-paper font-body min-h-screen flex flex-col antialiased"
|
||||||
hx-boost="true"
|
hx-boost="true"
|
||||||
hx-select="#main-content"
|
hx-select="#main-content"
|
||||||
hx-target="#main-content"
|
hx-target="#main-content"
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
hx-push-url="true"
|
hx-push-url="true"
|
||||||
>
|
>
|
||||||
|
<!-- HTMX transition progress bar -->
|
||||||
|
<div id="progress-bar" aria-hidden="true"></div>
|
||||||
|
|
||||||
<!-- HTMX transition progress bar -->
|
{{- partial "nav.html" . -}}
|
||||||
<div id="progress-bar" aria-hidden="true"></div>
|
|
||||||
|
|
||||||
{{- partial "nav.html" . -}}
|
{{- block "page-background" . -}}{{- end -}}
|
||||||
|
|
||||||
{{- block "page-background" . -}}{{- end -}}
|
|
||||||
|
|
||||||
<main id="main-content" class="flex-1" hx-history-elt>
|
<main id="main-content" class="flex-1" hx-history-elt>
|
||||||
{{- block "main" . }}{{- end }}
|
{{- block "main" . }}{{- end }}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
{{- partial "footer.html" . -}}
|
{{- partial "footer.html" . -}}
|
||||||
|
|
||||||
<!-- ── Global lightbox — lives outside #main-content so HTMX never touches it -->
|
|
||||||
<div
|
<!-- ── Global lightbox — lives outside #main-content so HTMX never touches it -->
|
||||||
x-data="{
|
<div
|
||||||
|
x-data="{
|
||||||
open: false,
|
open: false,
|
||||||
idx: 0,
|
idx: 0,
|
||||||
fill: false,
|
fill: false,
|
||||||
@@ -36,106 +37,141 @@
|
|||||||
prev() { this.idx = (this.idx - 1 + this.items.length) % this.items.length },
|
prev() { this.idx = (this.idx - 1 + this.items.length) % this.items.length },
|
||||||
next() { this.idx = (this.idx + 1) % this.items.length }
|
next() { this.idx = (this.idx + 1) % this.items.length }
|
||||||
}"
|
}"
|
||||||
@lightbox:open.window="items = $event.detail.items; idx = $event.detail.idx; open = true"
|
@lightbox:open.window="items = $event.detail.items; idx = $event.detail.idx; open = true"
|
||||||
@lightbox:close.window="close()"
|
@lightbox:close.window="close()"
|
||||||
@keydown.escape.window="open && close()"
|
@keydown.escape.window="open && close()"
|
||||||
@keydown.arrow-left.window="open && prev()"
|
@keydown.arrow-left.window="open && prev()"
|
||||||
@keydown.arrow-right.window="open && next()"
|
@keydown.arrow-right.window="open && next()"
|
||||||
@keydown.f.window="open && (fill = !fill)"
|
@keydown.f.window="open && (fill = !fill)"
|
||||||
x-show="open"
|
x-show="open"
|
||||||
x-cloak
|
x-cloak
|
||||||
x-transition:enter="transition duration-200 ease-out"
|
x-transition:enter="transition duration-200 ease-out"
|
||||||
x-transition:enter-start="opacity-0"
|
x-transition:enter-start="opacity-0"
|
||||||
x-transition:enter-end="opacity-100"
|
x-transition:enter-end="opacity-100"
|
||||||
x-transition:leave="transition duration-150 ease-in"
|
x-transition:leave="transition duration-150 ease-in"
|
||||||
x-transition:leave-start="opacity-100"
|
x-transition:leave-start="opacity-100"
|
||||||
x-transition:leave-end="opacity-0"
|
x-transition:leave-end="opacity-0"
|
||||||
class="fixed inset-0 z-[200] flex items-center justify-center bg-void/95 backdrop-blur-sm"
|
class="fixed inset-0 z-[200] flex items-center justify-center bg-void/95 backdrop-blur-sm"
|
||||||
@click.self="close()"
|
@click.self="close()"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
aria-label="Media lightbox"
|
aria-label="Media lightbox"
|
||||||
>
|
>
|
||||||
<!-- Top chrome bar -->
|
<!-- Top chrome bar -->
|
||||||
<div class="absolute top-0 inset-x-0 z-10 flex items-center justify-between px-2 h-14"
|
<div
|
||||||
style="background: linear-gradient(to bottom, rgba(5,5,16,0.85), transparent)">
|
class="absolute top-0 inset-x-0 z-10 flex items-center justify-between px-2 h-14"
|
||||||
<div class="absolute top-0 inset-x-0 h-px gradient-line"></div>
|
style="background: linear-gradient(to bottom, rgba(5,5,16,0.85), transparent)"
|
||||||
<div class="w-24"></div>
|
>
|
||||||
<div class="label text-fog tabular-nums"
|
<div class="absolute top-0 inset-x-0 h-px gradient-line"></div>
|
||||||
x-text="items.length ? `${String(idx + 1).padStart(2,'0')} / ${String(items.length).padStart(2,'0')}` : ''"></div>
|
<div class="w-24"></div>
|
||||||
<div class="flex items-center w-24 justify-end gap-1">
|
<div
|
||||||
<button @click="fill = !fill"
|
class="label text-fog tabular-nums"
|
||||||
class="w-10 h-10 flex items-center justify-center label transition-colors"
|
x-text="items.length ? `${String(idx + 1).padStart(2,'0')} / ${String(items.length).padStart(2,'0')}` : ''"
|
||||||
:class="fill ? 'text-heat hover:text-chalk' : 'text-fog hover:text-heat'"
|
></div>
|
||||||
:aria-label="fill ? 'Switch to fit mode' : 'Switch to fill mode'"
|
<div class="flex items-center w-24 justify-end gap-1">
|
||||||
x-text="fill ? 'FIT' : 'FILL'"></button>
|
<button
|
||||||
<button @click="close()"
|
@click="fill = !fill"
|
||||||
class="w-10 h-10 flex items-center justify-center label text-fog hover:text-chalk transition-colors"
|
class="w-10 h-10 flex items-center justify-center label transition-colors"
|
||||||
aria-label="Close">✕</button>
|
:class="fill ? 'text-heat hover:text-chalk' : 'text-fog hover:text-heat'"
|
||||||
|
:aria-label="fill ? 'Switch to fit mode' : 'Switch to fill mode'"
|
||||||
|
x-text="fill ? 'FIT' : 'FILL'"
|
||||||
|
></button>
|
||||||
|
<button
|
||||||
|
@click="close()"
|
||||||
|
class="w-10 h-10 flex items-center justify-center label text-fog hover:text-chalk transition-colors"
|
||||||
|
aria-label="Close"
|
||||||
|
>
|
||||||
|
✕
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Prev -->
|
||||||
|
<button
|
||||||
|
@click="prev()"
|
||||||
|
x-show="items.length > 1"
|
||||||
|
class="absolute left-2 top-1/2 -translate-y-1/2 z-10 w-10 h-10 md:w-12 md:h-12 flex items-center justify-center text-fog hover:text-heat transition-colors text-xl"
|
||||||
|
aria-label="Previous"
|
||||||
|
>
|
||||||
|
{{- partial "icon.html" "arrow-left" -}}
|
||||||
|
</button>
|
||||||
|
<!-- Media -->
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 flex items-center justify-center transition-[padding] duration-300"
|
||||||
|
:class="fill ? 'p-0' : 'pt-14 pb-14 px-14 md:px-20'"
|
||||||
|
>
|
||||||
|
<video
|
||||||
|
x-show="items[idx] && items[idx].video"
|
||||||
|
:src="items[idx] && items[idx].video ? items[idx].video : ''"
|
||||||
|
:poster="items[idx] ? items[idx].img : ''"
|
||||||
|
x-effect="if (open && items[idx] && items[idx].video) { $el.load(); $el.play() }"
|
||||||
|
:class="fill ? 'w-full h-full object-cover' : 'max-w-full max-h-full object-contain'"
|
||||||
|
class="transition-all duration-300"
|
||||||
|
controls
|
||||||
|
loop
|
||||||
|
muted
|
||||||
|
playsinline
|
||||||
|
></video>
|
||||||
|
<img
|
||||||
|
x-show="items[idx] && !items[idx].video"
|
||||||
|
:src="items[idx] && !items[idx].video ? items[idx].img : ''"
|
||||||
|
alt=""
|
||||||
|
:class="fill ? 'w-full h-full object-cover' : 'max-w-full max-h-full object-contain'"
|
||||||
|
class="transition-all duration-300"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<!-- Next -->
|
||||||
|
<button
|
||||||
|
@click="next()"
|
||||||
|
x-show="items.length > 1"
|
||||||
|
class="absolute right-2 top-1/2 -translate-y-1/2 z-10 w-10 h-10 md:w-12 md:h-12 flex items-center justify-center text-fog hover:text-heat transition-colors text-xl"
|
||||||
|
aria-label="Next"
|
||||||
|
>
|
||||||
|
{{- partial "icon.html" "arrow-right" -}}
|
||||||
|
</button>
|
||||||
|
<!-- Dots -->
|
||||||
|
<div
|
||||||
|
x-show="items.length > 1"
|
||||||
|
class="absolute bottom-0 inset-x-0 z-10 flex items-center justify-center h-14 gap-2"
|
||||||
|
style="background: linear-gradient(to top, rgba(5,5,16,0.85), transparent)"
|
||||||
|
>
|
||||||
|
<div class="absolute bottom-0 inset-x-0 h-px gradient-line"></div>
|
||||||
|
<template x-for="(item, i) in items" :key="i">
|
||||||
|
<button
|
||||||
|
@click="idx = i"
|
||||||
|
class="h-1.5 rounded-full transition-all duration-300"
|
||||||
|
:class="i === idx ? 'w-5 bg-heat' : 'w-1.5 bg-fog hover:bg-chalk'"
|
||||||
|
:aria-label="`Go to item ${i + 1}`"
|
||||||
|
></button>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Prev -->
|
|
||||||
<button @click="prev()" x-show="items.length > 1"
|
|
||||||
class="absolute left-2 top-1/2 -translate-y-1/2 z-10 w-10 h-10 md:w-12 md:h-12 flex items-center justify-center text-fog hover:text-heat transition-colors text-xl"
|
|
||||||
aria-label="Previous">{{- partial "icon.html" "arrow-left" -}}</button>
|
|
||||||
<!-- Media -->
|
|
||||||
<div class="absolute inset-0 flex items-center justify-center transition-[padding] duration-300"
|
|
||||||
:class="fill ? 'p-0' : 'pt-14 pb-14 px-14 md:px-20'">
|
|
||||||
<video
|
|
||||||
x-show="items[idx] && items[idx].video"
|
|
||||||
:src="items[idx] && items[idx].video ? items[idx].video : ''"
|
|
||||||
:poster="items[idx] ? items[idx].img : ''"
|
|
||||||
x-effect="if (open && items[idx] && items[idx].video) { $el.load(); $el.play() }"
|
|
||||||
:class="fill ? 'w-full h-full object-cover' : 'max-w-full max-h-full object-contain'"
|
|
||||||
class="transition-all duration-300"
|
|
||||||
controls loop muted playsinline></video>
|
|
||||||
<img
|
|
||||||
x-show="items[idx] && !items[idx].video"
|
|
||||||
:src="items[idx] && !items[idx].video ? items[idx].img : ''"
|
|
||||||
alt=""
|
|
||||||
:class="fill ? 'w-full h-full object-cover' : 'max-w-full max-h-full object-contain'"
|
|
||||||
class="transition-all duration-300">
|
|
||||||
</div>
|
|
||||||
<!-- Next -->
|
|
||||||
<button @click="next()" x-show="items.length > 1"
|
|
||||||
class="absolute right-2 top-1/2 -translate-y-1/2 z-10 w-10 h-10 md:w-12 md:h-12 flex items-center justify-center text-fog hover:text-heat transition-colors text-xl"
|
|
||||||
aria-label="Next">{{- partial "icon.html" "arrow-right" -}}</button>
|
|
||||||
<!-- Dots -->
|
|
||||||
<div x-show="items.length > 1"
|
|
||||||
class="absolute bottom-0 inset-x-0 z-10 flex items-center justify-center h-14 gap-2"
|
|
||||||
style="background: linear-gradient(to top, rgba(5,5,16,0.85), transparent)">
|
|
||||||
<div class="absolute bottom-0 inset-x-0 h-px gradient-line"></div>
|
|
||||||
<template x-for="(item, i) in items" :key="i">
|
|
||||||
<button @click="idx = i"
|
|
||||||
class="h-1.5 rounded-full transition-all duration-300"
|
|
||||||
:class="i === idx ? 'w-5 bg-heat' : 'w-1.5 bg-fog hover:bg-chalk'"
|
|
||||||
:aria-label="`Go to item ${i + 1}`"></button>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- HTMX (page transitions & progressive enhancement) -->
|
<!-- HTMX (page transitions & progressive enhancement) -->
|
||||||
<script src="https://unpkg.com/htmx.org@2.0.4/dist/htmx.min.js"></script>
|
<script src="https://unpkg.com/htmx.org@2.0.4/dist/htmx.min.js"></script>
|
||||||
<!-- Alpine.js store initialisation (must run before alpine:init) -->
|
<!-- Alpine.js store initialisation (must run before alpine:init) -->
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('alpine:init', () => {
|
document.addEventListener("alpine:init", () => {
|
||||||
Alpine.store('nav', { path: window.location.pathname, open: false })
|
Alpine.store("nav", { path: window.location.pathname, open: false });
|
||||||
})
|
});
|
||||||
</script>
|
</script>
|
||||||
<!-- Alpine.js (reactive UI — nav, interactions) -->
|
<!-- Alpine.js (reactive UI — nav, interactions) -->
|
||||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.14.8/dist/cdn.min.js"></script>
|
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.14.8/dist/cdn.min.js"></script>
|
||||||
<!-- Site JS -->
|
<!-- Site JS -->
|
||||||
{{- $js := resources.Get "js/main.js" -}}
|
{{- $js := resources.Get "js/main.js" -}}
|
||||||
{{- if eq hugo.Environment "production" -}}
|
{{- if eq hugo.Environment "production" -}}
|
||||||
{{- $js = $js | minify | fingerprint "sha256" -}}
|
{{- $js = $js | minify | fingerprint "sha256" -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
<script src="{{ $js.RelPermalink }}"{{ if eq hugo.Environment "production" }} integrity="{{ $js.Data.Integrity }}"{{ end }} defer></script>
|
<script
|
||||||
|
src="{{ $js.RelPermalink }}"
|
||||||
|
{{ if eq hugo.Environment "production" }}integrity="{{ $js.Data.Integrity }}"{{ end }}
|
||||||
|
defer
|
||||||
|
></script>
|
||||||
|
|
||||||
{{- block "scripts" . }}{{- end }}
|
{{- block "scripts" . }}{{- end }}
|
||||||
|
|
||||||
{{- if and (eq hugo.Environment "production") .Site.Params.umamiId -}}
|
{{- if and (eq hugo.Environment "production") .Site.Params.umamiId -}}
|
||||||
<!-- Umami analytics — cookie-free, self-hosted -->
|
<!-- Umami analytics — cookie-free, self-hosted -->
|
||||||
<script defer src="{{ .Site.Params.umamiSrc }}" data-website-id="{{ .Site.Params.umamiId }}"></script>
|
<script defer src="{{ .Site.Params.umamiSrc }}" data-website-id="{{ .Site.Params.umamiId }}"></script>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+27
-29
@@ -1,34 +1,32 @@
|
|||||||
{{- define "main" -}}
|
{{- define "main" -}}
|
||||||
|
<!-- Page header -->
|
||||||
|
<header class="gutter-x pt-36 pb-14 border-b border-zinc speed-lines">
|
||||||
|
<div class="max-w-4xl">
|
||||||
|
{{- with .Data.Singular -}}
|
||||||
|
<span class="badge badge-pulse mb-5 inline-block">{{ . | title }}</span>
|
||||||
|
{{- else -}}
|
||||||
|
<span class="badge badge-pulse mb-5 inline-block">{{ .Kind | title }}</span>
|
||||||
|
{{- end -}}
|
||||||
|
<h1 class="font-display text-5xl md:text-7xl text-paper text-balance leading-none">{{ .Title }}</h1>
|
||||||
|
{{- with .Description -}}
|
||||||
|
<p class="text-chalk text-lg mt-5 max-w-xl leading-relaxed text-pretty font-body">{{ . }}</p>
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
<!-- Page header -->
|
<div class="gradient-line"></div>
|
||||||
<header class="gutter-x pt-36 pb-14 border-b border-zinc speed-lines">
|
|
||||||
<div class="max-w-4xl">
|
<!-- Posts grid -->
|
||||||
{{- with .Data.Singular -}}
|
<section class="gutter-x py-16 md:py-24">
|
||||||
<span class="badge badge-pulse mb-5 inline-block">{{ . | title }}</span>
|
{{- if .Paginator.Pages -}}
|
||||||
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-5">
|
||||||
|
{{- range .Paginator.Pages -}}
|
||||||
|
{{- partial "post-card.html" . -}}
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
{{- partial "pagination.html" . -}}
|
||||||
{{- else -}}
|
{{- else -}}
|
||||||
<span class="badge badge-pulse mb-5 inline-block">{{ .Kind | title }}</span>
|
<p class="label text-fog text-center py-24">No posts yet.</p>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
<h1 class="font-display text-5xl md:text-7xl text-paper text-balance leading-none">{{ .Title }}</h1>
|
</section>
|
||||||
{{- with .Description -}}
|
|
||||||
<p class="text-chalk text-lg mt-5 max-w-xl leading-relaxed text-pretty font-body">{{ . }}</p>
|
|
||||||
{{- end -}}
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div class="gradient-line"></div>
|
|
||||||
|
|
||||||
<!-- Posts grid -->
|
|
||||||
<section class="gutter-x py-16 md:py-24">
|
|
||||||
{{- if .Paginator.Pages -}}
|
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-5">
|
|
||||||
{{- range .Paginator.Pages -}}
|
|
||||||
{{- partial "post-card.html" . -}}
|
|
||||||
{{- end -}}
|
|
||||||
</div>
|
|
||||||
{{- partial "pagination.html" . -}}
|
|
||||||
{{- else -}}
|
|
||||||
<p class="label text-fog text-center py-24">No posts yet.</p>
|
|
||||||
{{- end -}}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
{{- define "main" -}}
|
{{- define "main" -}}
|
||||||
|
<!-- Page header -->
|
||||||
|
<header class="gutter-x pt-36 pb-16 border-b border-mist">
|
||||||
|
<div class="max-w-3xl">
|
||||||
|
<h1 class="font-display text-5xl md:text-7xl text-paper text-balance mb-5">{{ .Title }}</h1>
|
||||||
|
{{- with .Description -}}
|
||||||
|
<p class="text-chalk text-xl leading-relaxed text-pretty">{{ . }}</p>
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
<!-- Page header -->
|
<!-- Page content -->
|
||||||
<header class="gutter-x pt-36 pb-16 border-b border-mist">
|
<article class="gutter-x py-16 md:py-24 max-w-3xl prose-editorial">
|
||||||
<div class="max-w-3xl">
|
{{ .Content }}
|
||||||
<h1 class="font-display text-5xl md:text-7xl text-paper text-balance mb-5">{{ .Title }}</h1>
|
</article>
|
||||||
{{- with .Description -}}
|
|
||||||
<p class="text-chalk text-xl leading-relaxed text-pretty">{{ . }}</p>
|
|
||||||
{{- end -}}
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<!-- Page content -->
|
|
||||||
<article class="gutter-x py-16 md:py-24 max-w-3xl prose-editorial">
|
|
||||||
{{ .Content }}
|
|
||||||
</article>
|
|
||||||
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|||||||
+30
-27
@@ -1,32 +1,35 @@
|
|||||||
{{- define "main" -}}
|
{{- define "main" -}}
|
||||||
|
<!-- Taxonomy header -->
|
||||||
|
<header class="gutter-x pt-36 pb-14 border-b border-zinc speed-lines">
|
||||||
|
<div class="max-w-4xl">
|
||||||
|
<span class="badge badge-frost text-void mb-5 inline-block">Browse</span>
|
||||||
|
<h1 class="font-display text-5xl md:text-7xl text-paper leading-none">{{ .Title }}</h1>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
<!-- Taxonomy header -->
|
<div class="gradient-line"></div>
|
||||||
<header class="gutter-x pt-36 pb-14 border-b border-zinc speed-lines">
|
|
||||||
<div class="max-w-4xl">
|
|
||||||
<span class="badge badge-frost text-void mb-5 inline-block">Browse</span>
|
|
||||||
<h1 class="font-display text-5xl md:text-7xl text-paper leading-none">{{ .Title }}</h1>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div class="gradient-line"></div>
|
<!-- Terms badge cloud -->
|
||||||
|
<section class="gutter-x py-16 md:py-24">
|
||||||
<!-- Terms badge cloud -->
|
{{- if .Data.Terms -}}
|
||||||
<section class="gutter-x py-16 md:py-24">
|
<div class="flex flex-wrap gap-4">
|
||||||
{{- if .Data.Terms -}}
|
{{- range .Data.Terms.Alphabetical -}}
|
||||||
<div class="flex flex-wrap gap-4">
|
<a
|
||||||
{{- range .Data.Terms.Alphabetical -}}
|
href="{{ .Page.RelPermalink }}"
|
||||||
<a
|
class="group card-comic flex items-baseline gap-3 bg-concrete px-5 py-4 hover:border-heat transition-all"
|
||||||
href="{{ .Page.RelPermalink }}"
|
>
|
||||||
class="group card-comic flex items-baseline gap-3 bg-concrete px-5 py-4 hover:border-heat transition-all"
|
<span class="font-display text-2xl text-paper group-hover:text-heat transition-colors leading-none"
|
||||||
>
|
>{{ .Page.Title }}</span
|
||||||
<span class="font-display text-2xl text-paper group-hover:text-heat transition-colors leading-none">{{ .Page.Title }}</span>
|
>
|
||||||
<span class="badge badge-outline text-xs ml-1 group-hover:bg-heat group-hover:text-white group-hover:border-heat transition-all">{{ .Count }}</span>
|
<span
|
||||||
</a>
|
class="badge badge-outline text-xs ml-1 group-hover:bg-heat group-hover:text-white group-hover:border-heat transition-all"
|
||||||
|
>{{ .Count }}</span
|
||||||
|
>
|
||||||
|
</a>
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
{{- else -}}
|
||||||
|
<p class="label text-fog text-center py-24">No entries yet.</p>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</div>
|
</section>
|
||||||
{{- else -}}
|
|
||||||
<p class="label text-fog text-center py-24">No entries yet.</p>
|
|
||||||
{{- end -}}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|||||||
+52
-47
@@ -1,54 +1,59 @@
|
|||||||
{{- define "main" -}}
|
{{- define "main" -}}
|
||||||
|
<!-- Header -->
|
||||||
|
<header class="gutter-x pt-36 pb-14 border-b border-zinc speed-lines">
|
||||||
|
<span class="badge badge-frost text-void mb-5 inline-block">Contributors</span>
|
||||||
|
<h1 class="font-display text-5xl md:text-7xl text-paper leading-none">Authors</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
<!-- Header -->
|
<div class="gradient-line"></div>
|
||||||
<header class="gutter-x pt-36 pb-14 border-b border-zinc speed-lines">
|
|
||||||
<span class="badge badge-frost text-void mb-5 inline-block">Contributors</span>
|
|
||||||
<h1 class="font-display text-5xl md:text-7xl text-paper leading-none">Authors</h1>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div class="gradient-line"></div>
|
<!-- Authors grid -->
|
||||||
|
<section class="gutter-x py-16 md:py-24">
|
||||||
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
{{- range .Pages -}}
|
||||||
|
<a href="{{ .RelPermalink }}" class="group card-comic flex flex-col items-start gap-5 p-6 bg-concrete">
|
||||||
|
<!-- Avatar — bundle avatar.* first, fall back to .Params.avatar -->
|
||||||
|
{{- $avatarRes := .Resources.GetMatch "avatar.*" -}}
|
||||||
|
{{- $avatarSrc := "" -}}
|
||||||
|
{{- with $avatarRes }}
|
||||||
|
{{ $avatarSrc = .RelPermalink }}
|
||||||
|
{{ else }}
|
||||||
|
{{ with $.Params.avatar }}{{ $avatarSrc = . }}{{ end }}
|
||||||
|
{{ end -}}
|
||||||
|
{{- if $avatarSrc -}}
|
||||||
|
<div class="w-20 h-20 overflow-hidden border border-zinc group-hover:border-heat transition-colors">
|
||||||
|
<img
|
||||||
|
src="{{ $avatarSrc }}"
|
||||||
|
alt="{{ .Params.name | default .Title }}"
|
||||||
|
class="w-full h-full object-cover transition-transform duration-700 group-hover:scale-105"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{{- else -}}
|
||||||
|
<div class="w-20 h-20 bg-zinc border border-zinc flex items-center justify-center">
|
||||||
|
<span class="font-display text-2xl text-fog">{{ substr (.Params.name | default .Title) 0 1 }}</span>
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
<!-- Authors grid -->
|
|
||||||
<section class="gutter-x py-16 md:py-24">
|
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
||||||
{{- range .Pages -}}
|
|
||||||
<a href="{{ .RelPermalink }}" class="group card-comic flex flex-col items-start gap-5 p-6 bg-concrete">
|
|
||||||
|
|
||||||
<!-- Avatar — bundle avatar.* first, fall back to .Params.avatar -->
|
<!-- Info -->
|
||||||
{{- $avatarRes := .Resources.GetMatch "avatar.*" -}}
|
<div class="flex-1">
|
||||||
{{- $avatarSrc := "" -}}
|
<h2 class="font-display text-xl text-paper group-hover:text-heat transition-colors mb-2 leading-none">
|
||||||
{{- with $avatarRes }}{{ $avatarSrc = .RelPermalink }}{{ else }}{{ with $.Params.avatar }}{{ $avatarSrc = . }}{{ end }}{{ end -}}
|
{{ .Params.name | default .Title }}
|
||||||
{{- if $avatarSrc -}}
|
</h2>
|
||||||
<div class="w-20 h-20 overflow-hidden border border-zinc group-hover:border-heat transition-colors">
|
{{- with .Params.bio -}}
|
||||||
<img
|
<p class="text-fog text-sm leading-relaxed line-clamp-3 mt-2 font-body">{{ . }}</p>
|
||||||
src="{{ $avatarSrc }}"
|
{{- end -}}
|
||||||
alt="{{ .Params.name | default .Title }}"
|
</div>
|
||||||
class="w-full h-full object-cover transition-transform duration-700 group-hover:scale-105"
|
|
||||||
loading="lazy"
|
<span
|
||||||
>
|
class="badge badge-outline group-hover:bg-heat group-hover:text-white group-hover:border-heat transition-all mt-auto"
|
||||||
</div>
|
>
|
||||||
{{- else -}}
|
View works
|
||||||
<div class="w-20 h-20 bg-zinc border border-zinc flex items-center justify-center">
|
{{ partial "icon.html" "arrow-right" }}
|
||||||
<span class="font-display text-2xl text-fog">{{ substr (.Params.name | default .Title) 0 1 }}</span>
|
</span>
|
||||||
</div>
|
</a>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
</div>
|
||||||
<!-- Info -->
|
</section>
|
||||||
<div class="flex-1">
|
|
||||||
<h2 class="font-display text-xl text-paper group-hover:text-heat transition-colors mb-2 leading-none">
|
|
||||||
{{ .Params.name | default .Title }}
|
|
||||||
</h2>
|
|
||||||
{{- with .Params.bio -}}
|
|
||||||
<p class="text-fog text-sm leading-relaxed line-clamp-3 mt-2 font-body">{{ . }}</p>
|
|
||||||
{{- end -}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<span class="badge badge-outline group-hover:bg-heat group-hover:text-white group-hover:border-heat transition-all mt-auto">
|
|
||||||
View works {{ partial "icon.html" "arrow-right" }}
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
{{- end -}}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|||||||
+91
-83
@@ -1,97 +1,105 @@
|
|||||||
{{- define "main" -}}
|
{{- define "main" -}}
|
||||||
{{- $slug := .File.Dir | strings.TrimSuffix "/" | path.Base -}}
|
{{- $slug := .File.Dir | strings.TrimSuffix "/" | path.Base -}}
|
||||||
{{- $posts := where .Site.RegularPages "Params.author" $slug -}}
|
{{- $posts := where .Site.RegularPages "Params.author" $slug -}}
|
||||||
|
|
||||||
<!-- ── PROFILE HEADER ────────────────────────────────────────── -->
|
|
||||||
<header class="gutter-x pt-36 pb-20 border-b border-zinc speed-lines">
|
|
||||||
<div class="max-w-5xl mx-auto">
|
|
||||||
<div class="flex flex-col md:flex-row gap-10 md:gap-16 items-start">
|
|
||||||
|
|
||||||
<!-- Avatar — page bundle avatar.* takes precedence, falls back to .Params.avatar -->
|
<!-- ── PROFILE HEADER ────────────────────────────────────────── -->
|
||||||
{{- $avatarRes := .Resources.GetMatch "avatar.*" -}}
|
<header class="gutter-x pt-36 pb-20 border-b border-zinc speed-lines">
|
||||||
{{- $avatarSrc := "" -}}
|
<div class="max-w-5xl mx-auto">
|
||||||
{{- with $avatarRes }}{{ $avatarSrc = .RelPermalink }}{{ else }}{{ with $.Params.avatar }}{{ $avatarSrc = . }}{{ end }}{{ end -}}
|
<div class="flex flex-col md:flex-row gap-10 md:gap-16 items-start">
|
||||||
{{- if $avatarSrc -}}
|
<!-- Avatar — page bundle avatar.* takes precedence, falls back to .Params.avatar -->
|
||||||
<div class="flex-shrink-0 w-36 h-36 md:w-48 md:h-48 overflow-hidden border-2 border-heat neon-heat">
|
{{- $avatarRes := .Resources.GetMatch "avatar.*" -}}
|
||||||
<img
|
{{- $avatarSrc := "" -}}
|
||||||
src="{{ $avatarSrc }}"
|
{{- with $avatarRes }}
|
||||||
alt="{{ .Params.name | default .Title }}"
|
{{ $avatarSrc = .RelPermalink }}
|
||||||
class="w-full h-full object-cover"
|
{{ else }}
|
||||||
loading="lazy"
|
{{ with $.Params.avatar }}{{ $avatarSrc = . }}{{ end }}
|
||||||
>
|
{{ end -}}
|
||||||
</div>
|
{{- if $avatarSrc -}}
|
||||||
{{- else -}}
|
<div class="flex-shrink-0 w-36 h-36 md:w-48 md:h-48 overflow-hidden border-2 border-heat neon-heat">
|
||||||
<div class="flex-shrink-0 w-36 h-36 md:w-48 md:h-48 bg-concrete border-2 border-zinc flex items-center justify-center">
|
<img
|
||||||
<span class="font-display text-5xl text-smoke">{{ substr (.Params.name | default .Title) 0 1 }}</span>
|
src="{{ $avatarSrc }}"
|
||||||
</div>
|
alt="{{ .Params.name | default .Title }}"
|
||||||
{{- end -}}
|
class="w-full h-full object-cover"
|
||||||
|
loading="lazy"
|
||||||
<!-- Info -->
|
/>
|
||||||
<div class="flex-1 min-w-0">
|
</div>
|
||||||
<span class="badge badge-gradient mb-5 inline-block">Artist</span>
|
{{- else -}}
|
||||||
<h1 class="font-display text-4xl md:text-6xl text-paper text-balance mb-4 leading-none">
|
<div
|
||||||
{{ .Params.name | default .Title }}
|
class="flex-shrink-0 w-36 h-36 md:w-48 md:h-48 bg-concrete border-2 border-zinc flex items-center justify-center"
|
||||||
</h1>
|
>
|
||||||
{{- with .Params.bio -}}
|
<span class="font-display text-5xl text-smoke">{{ substr (.Params.name | default .Title) 0 1 }}</span>
|
||||||
<p class="text-chalk text-lg max-w-2xl leading-relaxed text-pretty mb-8 font-body font-light">{{ . }}</p>
|
</div>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
<!-- Social links — values may be full URLs or bare slugs -->
|
|
||||||
{{- with .Params.social -}}
|
<!-- Info -->
|
||||||
{{- $bases := dict "instagram" "https://instagram.com/" "x" "https://x.com/" "twitter" "https://x.com/" "github" "https://github.com/" "behance" "https://www.behance.net/" "artstation" "https://www.artstation.com/" -}}
|
<div class="flex-1 min-w-0">
|
||||||
<div class="flex flex-wrap gap-3">
|
<span class="badge badge-gradient mb-5 inline-block">Artist</span>
|
||||||
{{- range $platform, $handle := . -}}
|
<h1 class="font-display text-4xl md:text-6xl text-paper text-balance mb-4 leading-none">
|
||||||
{{- $href := cond (hasPrefix $handle "http") $handle (printf "%s%s" (index $bases $platform | default "#") $handle) -}}
|
{{ .Params.name | default .Title }}
|
||||||
<a
|
</h1>
|
||||||
href="{{ $href }}"
|
{{- with .Params.bio -}}
|
||||||
target="_blank"
|
<p class="text-chalk text-lg max-w-2xl leading-relaxed text-pretty mb-8 font-body font-light">{{ . }}</p>
|
||||||
rel="noopener noreferrer"
|
{{- end -}}
|
||||||
class="badge badge-outline"
|
|
||||||
>{{ $platform | upper }} {{ partial "icon.html" "arrow-external" }}</a>
|
|
||||||
|
<!-- Social links — values may be full URLs or bare slugs -->
|
||||||
|
{{- with .Params.social -}}
|
||||||
|
{{- $bases := dict "instagram" "https://instagram.com/" "x" "https://x.com/" "twitter" "https://x.com/" "github" "https://github.com/" "behance" "https://www.behance.net/" "artstation" "https://www.artstation.com/" -}}
|
||||||
|
<div class="flex flex-wrap gap-3">
|
||||||
|
{{- range $platform, $handle := . -}}
|
||||||
|
{{- $href := cond (hasPrefix $handle "http") $handle (printf "%s%s" (index $bases $platform | default "#") $handle) -}}
|
||||||
|
<a href="{{ $href }}" target="_blank" rel="noopener noreferrer" class="badge badge-outline"
|
||||||
|
>{{ $platform | upper }} {{ partial "icon.html" "arrow-external" }}</a
|
||||||
|
>
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Post count -->
|
||||||
|
{{- if $posts -}}
|
||||||
|
<p class="label text-fog mt-6">
|
||||||
|
{{ len $posts }} {{ if eq (len $posts) 1 }}editorial{{ else }}editorials{{ end }}
|
||||||
|
</p>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</div>
|
</div>
|
||||||
{{- end -}}
|
|
||||||
|
|
||||||
<!-- Post count -->
|
|
||||||
{{- if $posts -}}
|
|
||||||
<p class="label text-fog mt-6">{{ len $posts }} {{ if eq (len $posts) 1 }}editorial{{ else }}editorials{{ end }}</p>
|
|
||||||
{{- end -}}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</header>
|
||||||
</header>
|
|
||||||
|
|
||||||
<div class="gradient-line"></div>
|
<div class="gradient-line"></div>
|
||||||
|
|
||||||
<!-- ── AUTHOR BIO (Markdown body) ────────────────────────────── -->
|
<!-- ── AUTHOR BIO (Markdown body) ────────────────────────────── -->
|
||||||
{{- with .Content -}}
|
{{- with .Content -}}
|
||||||
<div class="gutter-x py-12 border-b border-zinc">
|
<div class="gutter-x py-12 border-b border-zinc">
|
||||||
<div class="max-w-5xl mx-auto prose-editorial">{{ . }}</div>
|
<div class="max-w-5xl mx-auto prose-editorial">{{ . }}</div>
|
||||||
</div>
|
</div>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
<!-- ── AUTHOR'S POSTS ─────────────────────────────────────────── -->
|
|
||||||
{{- if $posts -}}
|
<!-- ── AUTHOR'S POSTS ─────────────────────────────────────────── -->
|
||||||
<section class="gutter-x py-16 md:py-24">
|
{{- if $posts -}}
|
||||||
<div class="max-w-5xl mx-auto">
|
<section class="gutter-x py-16 md:py-24">
|
||||||
<div class="flex items-center gap-5 mb-10">
|
<div class="max-w-5xl mx-auto">
|
||||||
<h2 class="font-display text-3xl md:text-5xl text-paper leading-none">
|
<div class="flex items-center gap-5 mb-10">
|
||||||
Works by <span class="text-gradient">{{ .Params.name | default .Title }}</span>
|
<h2 class="font-display text-3xl md:text-5xl text-paper leading-none">
|
||||||
</h2>
|
Works by <span class="text-gradient">{{ .Params.name | default .Title }}</span>
|
||||||
<div class="flex-1 gradient-line ml-2"></div>
|
</h2>
|
||||||
</div>
|
<div class="flex-1 gradient-line ml-2"></div>
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-5">
|
</div>
|
||||||
{{- range first 4 ($posts.ByDate.Reverse) -}}
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-5">
|
||||||
{{- partial "post-card.html" . -}}
|
{{- range first 4 ($posts.ByDate.Reverse) -}}
|
||||||
{{- end -}}
|
{{- partial "post-card.html" . -}}
|
||||||
</div>
|
{{- end -}}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</div>
|
||||||
{{- else -}}
|
</section>
|
||||||
<div class="gutter-x py-24 text-center">
|
{{- else -}}
|
||||||
<p class="label text-fog">No editorials published yet.</p>
|
<div class="gutter-x py-24 text-center">
|
||||||
</div>
|
<p class="label text-fog">No editorials published yet.</p>
|
||||||
{{- end -}}
|
</div>
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
{{- define "main" -}}
|
{{- define "main" -}}
|
||||||
|
<!-- Category header -->
|
||||||
|
<header class="gutter-x pt-36 pb-16 border-b border-mist">
|
||||||
|
<div class="max-w-4xl">
|
||||||
|
<span class="label text-ash block mb-4">Category</span>
|
||||||
|
<h1 class="font-display text-5xl md:text-7xl text-paper text-balance">{{ .Title }}</h1>
|
||||||
|
<p class="text-ash label mt-5">
|
||||||
|
{{ len .Pages }} {{ if eq (len .Pages) 1 }}editorial{{ else }}editorials{{ end }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
<!-- Category header -->
|
<!-- Posts grid -->
|
||||||
<header class="gutter-x pt-36 pb-16 border-b border-mist">
|
<section class="gutter-x py-16 md:py-24">
|
||||||
<div class="max-w-4xl">
|
{{- if .Paginator.Pages -}}
|
||||||
<span class="label text-ash block mb-4">Category</span>
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-x-5 gap-y-12">
|
||||||
<h1 class="font-display text-5xl md:text-7xl text-paper text-balance">{{ .Title }}</h1>
|
{{- range .Paginator.Pages -}}
|
||||||
<p class="text-ash label mt-5">{{ len .Pages }} {{ if eq (len .Pages) 1 }}editorial{{ else }}editorials{{ end }}</p>
|
{{- partial "post-card.html" . -}}
|
||||||
</div>
|
{{- end -}}
|
||||||
</header>
|
</div>
|
||||||
|
{{- partial "pagination.html" . -}}
|
||||||
<!-- Posts grid -->
|
{{- else -}}
|
||||||
<section class="gutter-x py-16 md:py-24">
|
<p class="text-ash label text-center py-24">No posts in this category yet.</p>
|
||||||
{{- if .Paginator.Pages -}}
|
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-x-5 gap-y-12">
|
|
||||||
{{- range .Paginator.Pages -}}
|
|
||||||
{{- partial "post-card.html" . -}}
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</div>
|
</section>
|
||||||
{{- partial "pagination.html" . -}}
|
|
||||||
{{- else -}}
|
|
||||||
<p class="text-ash label text-center py-24">No posts in this category yet.</p>
|
|
||||||
{{- end -}}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|||||||
+146
-122
@@ -1,134 +1,158 @@
|
|||||||
{{- define "main" -}}
|
{{- define "main" -}}
|
||||||
{{- $posts := where .Site.RegularPages "Section" "posts" -}}
|
{{- $posts := where .Site.RegularPages "Section" "posts" -}}
|
||||||
{{- $featured := where $posts "Params.featured" true -}}
|
{{- $featured := where $posts "Params.featured" true -}}
|
||||||
{{- $hero := index $featured 0 -}}
|
{{- $hero := index $featured 0 -}}
|
||||||
{{- $latest := where $posts "Permalink" "ne" $hero.Permalink -}}
|
{{- $latest := where $posts "Permalink" "ne" $hero.Permalink -}}
|
||||||
|
|
||||||
<!-- ── HERO ──────────────────────────────────────────────────── -->
|
|
||||||
{{- with $hero -}}
|
|
||||||
<section class="relative min-h-screen flex items-end overflow-hidden noise">
|
|
||||||
|
|
||||||
<!-- Background media — bundle banner.png first, fallback to front matter -->
|
<!-- ── HERO ──────────────────────────────────────────────────── -->
|
||||||
{{- $heroBanner := .Resources.GetMatch "banner.png" -}}
|
{{- with $hero -}}
|
||||||
{{- if not $heroBanner -}}{{- $heroBanner = .Resources.GetMatch "banner.*" -}}{{- end -}}
|
<section class="relative min-h-screen flex items-end overflow-hidden noise">
|
||||||
{{- if $heroBanner -}}
|
<!-- Background media — bundle banner.png first, fallback to front matter -->
|
||||||
<div class="absolute inset-0">
|
{{- $heroBanner := .Resources.GetMatch "banner.png" -}}
|
||||||
{{- partial "img.html" (dict "res" $heroBanner "widths" (slice 1200 1920 2560) "sizes" "100vw" "class" "w-full h-full object-cover" "alt" "" "loading" "eager") -}}
|
{{- if not $heroBanner -}}{{- $heroBanner = .Resources.GetMatch "banner.*" -}}{{- end -}}
|
||||||
</div>
|
{{- if $heroBanner -}}
|
||||||
{{- else -}}
|
<div class="absolute inset-0">
|
||||||
{{- $heroBannerSrc := "" -}}
|
{{- partial "img.html" (dict "res" $heroBanner "widths" (slice 1200 1920 2560) "sizes" "100vw" "class" "w-full h-full object-cover" "alt" "" "loading" "eager") -}}
|
||||||
{{- with .Params.background }}{{ $heroBannerSrc = .src }}{{ else }}{{ with $.Params.banner }}{{ $heroBannerSrc = .src }}{{ end }}{{ end -}}
|
</div>
|
||||||
{{- with $heroBannerSrc -}}
|
{{- else -}}
|
||||||
<div class="absolute inset-0">
|
{{- $heroBannerSrc := "" -}}
|
||||||
<img src="{{ . }}" alt="" class="w-full h-full object-cover" loading="eager" decoding="async">
|
{{- with .Params.background }}
|
||||||
</div>
|
{{ $heroBannerSrc = .src }}
|
||||||
{{- end -}}
|
{{ else }}
|
||||||
{{- end -}}
|
{{ with $.Params.banner }}{{ $heroBannerSrc = .src }}{{ end }}
|
||||||
|
{{ end -}}
|
||||||
<!-- Cinematic overlay -->
|
{{- with $heroBannerSrc -}}
|
||||||
<div class="absolute inset-0 overlay-gradient-hero"></div>
|
<div class="absolute inset-0">
|
||||||
|
<img src="{{ . }}" alt="" class="w-full h-full object-cover" loading="eager" decoding="async" />
|
||||||
<!-- Hero content -->
|
|
||||||
<div class="relative z-10 gutter-x pb-20 md:pb-32 w-full">
|
|
||||||
<div class="max-w-5xl">
|
|
||||||
|
|
||||||
<!-- Drop label + category badges -->
|
|
||||||
<div class="flex flex-wrap items-center gap-3 mb-6">
|
|
||||||
<span class="badge badge-pulse">Featured Drop</span>
|
|
||||||
{{- with .Params.categories -}}
|
|
||||||
{{- range first 1 . -}}
|
|
||||||
<a href="/categories/{{ . | urlize }}/" class="badge badge-outline">{{ . }}</a>
|
|
||||||
{{- end -}}
|
|
||||||
{{- end -}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Title -->
|
|
||||||
<h1 class="font-display text-6xl md:text-8xl text-paper text-balance mb-6 leading-none">
|
|
||||||
{{- .Title -}}
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<!-- Description -->
|
|
||||||
<p class="text-chalk text-base md:text-lg max-w-2xl mb-10 leading-relaxed text-pretty font-body opacity-90 line-clamp-3">
|
|
||||||
{{- .Description -}}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<!-- CTA + author -->
|
|
||||||
<div class="flex flex-wrap items-center gap-6">
|
|
||||||
<a href="{{ .RelPermalink }}" class="btn btn-outline">View Editorial {{ partial "icon.html" "arrow-right" }}</a>
|
|
||||||
{{- with .Params.author -}}
|
|
||||||
{{- $author := site.GetPage (printf "authors/%s" .) -}}
|
|
||||||
{{- with $author -}}
|
|
||||||
<div class="flex items-center gap-3">
|
|
||||||
{{- $avRes := .Resources.GetMatch "avatar.*" -}}
|
|
||||||
{{- $avSrc := "" -}}
|
|
||||||
{{- with $avRes }}{{ $avSrc = .RelPermalink }}{{ else }}{{ with $author.Params.avatar }}{{ $avSrc = . }}{{ end }}{{ end -}}
|
|
||||||
{{- with $avSrc -}}
|
|
||||||
<img src="{{ . }}" alt="{{ $author.Params.name | default $author.Title }}"
|
|
||||||
class="w-8 h-8 object-cover border border-heat/50">
|
|
||||||
{{- end -}}
|
|
||||||
<span class="label text-chalk">
|
|
||||||
By <a href="{{ .RelPermalink }}" class="text-heat hover:text-frost transition-colors">{{ .Params.name | default .Title }}</a>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
{{- end -}}
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Cinematic overlay -->
|
||||||
|
<div class="absolute inset-0 overlay-gradient-hero"></div>
|
||||||
|
|
||||||
|
<!-- Hero content -->
|
||||||
|
<div class="relative z-10 gutter-x pb-20 md:pb-32 w-full">
|
||||||
|
<div class="max-w-5xl">
|
||||||
|
<!-- Drop label + category badges -->
|
||||||
|
<div class="flex flex-wrap items-center gap-3 mb-6">
|
||||||
|
<span class="badge badge-pulse">Featured Drop</span>
|
||||||
|
{{- with .Params.categories -}}
|
||||||
|
{{- range first 1 . -}}
|
||||||
|
<a href="/categories/{{ . | urlize }}/" class="badge badge-outline">{{ . }}</a>
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<h1 class="font-display text-6xl md:text-8xl text-paper text-balance mb-6 leading-none">
|
||||||
|
{{- .Title -}}
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<!-- Description -->
|
||||||
|
<p
|
||||||
|
class="text-chalk text-base md:text-lg max-w-2xl mb-10 leading-relaxed text-pretty font-body opacity-90 line-clamp-3"
|
||||||
|
>
|
||||||
|
{{- .Description -}}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- CTA + author -->
|
||||||
|
<div class="flex flex-wrap items-center gap-6">
|
||||||
|
<a href="{{ .RelPermalink }}" class="btn btn-outline"
|
||||||
|
>View Editorial {{ partial "icon.html" "arrow-right" }}</a
|
||||||
|
>
|
||||||
|
{{- with .Params.author -}}
|
||||||
|
{{- $author := site.GetPage (printf "authors/%s" .) -}}
|
||||||
|
{{- with $author -}}
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
{{- $avRes := .Resources.GetMatch "avatar.*" -}}
|
||||||
|
{{- $avSrc := "" -}}
|
||||||
|
{{- with $avRes }}
|
||||||
|
{{ $avSrc = .RelPermalink }}
|
||||||
|
{{ else }}
|
||||||
|
{{ with $author.Params.avatar }}{{ $avSrc = . }}{{ end }}
|
||||||
|
{{ end -}}
|
||||||
|
{{- with $avSrc -}}
|
||||||
|
<img
|
||||||
|
src="{{ . }}"
|
||||||
|
alt="{{ $author.Params.name | default $author.Title }}"
|
||||||
|
class="w-8 h-8 object-cover border border-heat/50"
|
||||||
|
/>
|
||||||
|
{{- end -}}
|
||||||
|
<span class="label text-chalk">
|
||||||
|
By
|
||||||
|
<a href="{{ .RelPermalink }}" class="text-heat hover:text-frost transition-colors"
|
||||||
|
>{{ .Params.name | default .Title }}</a
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
<!-- Scroll indicator -->
|
||||||
</div>
|
<div class="absolute bottom-8 right-8 z-10 hidden md:flex flex-col items-center gap-2">
|
||||||
|
<span class="label text-fog" style="writing-mode: vertical-lr; letter-spacing: 0.25em;">SCROLL</span>
|
||||||
<!-- Scroll indicator -->
|
<div class="w-px h-12 bg-zinc relative overflow-hidden">
|
||||||
<div class="absolute bottom-8 right-8 z-10 hidden md:flex flex-col items-center gap-2">
|
<div
|
||||||
<span class="label text-fog" style="writing-mode: vertical-lr; letter-spacing: 0.25em;">SCROLL</span>
|
class="absolute top-0 left-0 right-0 h-full"
|
||||||
<div class="w-px h-12 bg-zinc relative overflow-hidden">
|
style="background: linear-gradient(var(--color-heat), var(--color-frost));
|
||||||
<div class="absolute top-0 left-0 right-0 h-full"
|
animation: scroll-line 1.8s ease-in-out infinite;"
|
||||||
style="background: linear-gradient(var(--color-heat), var(--color-frost));
|
></div>
|
||||||
animation: scroll-line 1.8s ease-in-out infinite;"></div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</section>
|
||||||
|
|
||||||
</section>
|
|
||||||
{{- end -}}
|
|
||||||
|
|
||||||
<div class="gradient-line" style="opacity:0.2"></div>
|
|
||||||
|
|
||||||
<!-- ── LATEST POSTS ──────────────────────────────────────────── -->
|
|
||||||
<section class="gutter-x py-16 md:py-24 relative overflow-hidden">
|
|
||||||
|
|
||||||
<!-- Decorative graffiti tag behind heading -->
|
|
||||||
<div class="graffiti-tag absolute -top-6 -right-4 opacity-100 select-none pointer-events-none"
|
|
||||||
style="-webkit-text-stroke-color: rgba(0,200,255,0.07);" aria-hidden="true">DROPS</div>
|
|
||||||
|
|
||||||
<div class="relative z-10 flex flex-wrap items-end justify-between gap-4 mb-10">
|
|
||||||
<h2 class="font-display text-5xl md:text-7xl leading-none">
|
|
||||||
<span class="text-stroke-heat">LATEST</span> <span class="text-gradient">DROPS</span>
|
|
||||||
</h2>
|
|
||||||
<a href="/posts/" class="btn btn-ghost">All posts {{ partial "icon.html" "arrow-right" }}</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="relative z-10 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-5">
|
|
||||||
{{- range first 8 $latest -}}
|
|
||||||
{{- partial "post-card.html" . -}}
|
|
||||||
{{- end -}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{- if gt (len $latest) 8 -}}
|
|
||||||
<div class="relative z-10 mt-14 text-center">
|
|
||||||
<a href="/posts/" class="btn btn-outline">View All {{ len $posts }} Posts {{ partial "icon.html" "arrow-right" }}</a>
|
|
||||||
</div>
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- ── ABOUT STRIP ───────────────────────────────────────────── -->
|
<div class="gradient-line" style="opacity:0.2"></div>
|
||||||
<section class="bg-concrete border-t border-b border-zinc gutter-x py-16 md:py-20 spray-bg relative overflow-hidden">
|
|
||||||
<div class="max-w-3xl mx-auto text-center relative z-10">
|
|
||||||
<span class="badge badge-frost text-void mb-6 inline-block">About the Magazine</span>
|
|
||||||
<p class="font-display text-3xl md:text-5xl text-paper leading-tight text-balance mb-10">
|
|
||||||
{{ .Site.Params.description }}
|
|
||||||
</p>
|
|
||||||
<a href="/about/" class="btn btn-outline">About the magazine {{ partial "icon.html" "arrow-right" }}</a>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
|
<!-- ── LATEST POSTS ──────────────────────────────────────────── -->
|
||||||
|
<section class="gutter-x py-16 md:py-24 relative overflow-hidden">
|
||||||
|
<!-- Decorative graffiti tag behind heading -->
|
||||||
|
<div
|
||||||
|
class="graffiti-tag absolute -top-6 -right-4 opacity-100 select-none pointer-events-none"
|
||||||
|
style="-webkit-text-stroke-color: rgba(0,200,255,0.07);"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
DROPS
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="relative z-10 flex flex-wrap items-end justify-between gap-4 mb-10">
|
||||||
|
<h2 class="font-display text-5xl md:text-7xl leading-none">
|
||||||
|
<span class="text-stroke-heat">LATEST</span> <span class="text-gradient">DROPS</span>
|
||||||
|
</h2>
|
||||||
|
<a href="/posts/" class="btn btn-ghost">All posts {{ partial "icon.html" "arrow-right" }}</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="relative z-10 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-5">
|
||||||
|
{{- range first 8 $latest -}}
|
||||||
|
{{- partial "post-card.html" . -}}
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{- if gt (len $latest) 8 -}}
|
||||||
|
<div class="relative z-10 mt-14 text-center">
|
||||||
|
<a href="/posts/" class="btn btn-outline"
|
||||||
|
>View All {{ len $posts }} Posts {{ partial "icon.html" "arrow-right" }}</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ── ABOUT STRIP ───────────────────────────────────────────── -->
|
||||||
|
<section class="bg-concrete border-t border-b border-zinc gutter-x py-16 md:py-20 spray-bg relative overflow-hidden">
|
||||||
|
<div class="max-w-3xl mx-auto text-center relative z-10">
|
||||||
|
<span class="badge badge-frost text-void mb-6 inline-block">About the Magazine</span>
|
||||||
|
<p class="font-display text-3xl md:text-5xl text-paper leading-tight text-balance mb-10">
|
||||||
|
{{ .Site.Params.description }}
|
||||||
|
</p>
|
||||||
|
<a href="/about/" class="btn btn-outline">About the magazine {{ partial "icon.html" "arrow-right" }}</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|||||||
@@ -1,24 +1,39 @@
|
|||||||
{{- /* Inline author byline for post single pages.
|
{{- /* 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">
|
<div class="flex items-center gap-4 py-6 border-t border-b border-zinc my-8 max-w-2xl">
|
||||||
{{- $avatarRes := .Resources.GetMatch "avatar.*" -}}
|
{{- $avatarRes := .Resources.GetMatch "avatar.*" -}}
|
||||||
{{- if $avatarRes -}}
|
{{- if $avatarRes -}}
|
||||||
{{- $av := $avatarRes.Resize "96x webp" -}}
|
{{- $av := $avatarRes.Resize "96x webp" -}}
|
||||||
<a href="{{ $.RelPermalink }}" class="flex-shrink-0">
|
<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>
|
</a>
|
||||||
{{- else -}}{{- with .Params.avatar -}}
|
{{- else -}}
|
||||||
<a href="{{ $.RelPermalink }}" class="flex-shrink-0">
|
{{- with .Params.avatar -}}
|
||||||
<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 href="{{ $.RelPermalink }}" class="flex-shrink-0">
|
||||||
</a>
|
<img
|
||||||
{{- end -}}{{- end -}}
|
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">
|
<div class="min-w-0">
|
||||||
<a href="{{ .RelPermalink }}" class="text-base font-display text-heat hover:text-frost transition-colors block">
|
<a href="{{ .RelPermalink }}" class="text-base font-display text-heat hover:text-frost transition-colors block">
|
||||||
{{ .Params.name | default .Title }}
|
{{ .Params.name | default .Title }}
|
||||||
</a>
|
</a>
|
||||||
{{- with .Params.bio -}}
|
{{- 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 -}}
|
{{- end -}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
<footer class="relative overflow-hidden border-t border-zinc gutter-x py-14 mt-auto bg-ink speed-lines">
|
<footer class="relative overflow-hidden border-t border-zinc gutter-x py-14 mt-auto bg-ink speed-lines">
|
||||||
|
|
||||||
<!-- Decorative background text -->
|
<!-- Decorative background text -->
|
||||||
<div
|
<div
|
||||||
class="graffiti-tag absolute -bottom-6 -right-4 select-none pointer-events-none"
|
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;"
|
style="-webkit-text-stroke-color: rgba(255,26,140,0.07); opacity: 1;"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
>PIVOINE</div>
|
>
|
||||||
|
PIVOINE
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="gradient-line mb-10 relative z-10"></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">
|
<div class="relative z-10 flex flex-col md:flex-row md:items-start justify-between gap-10">
|
||||||
|
|
||||||
<!-- Brand -->
|
<!-- Brand -->
|
||||||
<div>
|
<div>
|
||||||
<a href="/" class="block mb-4 hover:opacity-90 transition-opacity w-fit" aria-label="{{ .Site.Title }} Home">
|
<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">
|
<nav aria-label="Footer navigation">
|
||||||
<ul class="flex flex-wrap gap-x-8 gap-y-4">
|
<ul class="flex flex-wrap gap-x-8 gap-y-4">
|
||||||
{{- range .Site.Menus.footer -}}
|
{{- range .Site.Menus.footer -}}
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ .URL }}" class="label text-fog hover:text-heat transition-colors">{{ .Name }}</a>
|
<a href="{{ .URL }}" class="label text-fog hover:text-heat transition-colors">{{ .Name }}</a>
|
||||||
</li>
|
</li>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- with .Site.Params.social -}}
|
{{- with .Site.Params.social -}}
|
||||||
{{- range $platform, $url := . -}}
|
{{- range $platform, $url := . -}}
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ $url }}" target="_blank" rel="noopener noreferrer" class="label text-fog hover:text-frost transition-colors">
|
<a
|
||||||
{{- $platform | upper -}} {{ partial "icon.html" "arrow-external" }}
|
href="{{ $url }}"
|
||||||
</a>
|
target="_blank"
|
||||||
</li>
|
rel="noopener noreferrer"
|
||||||
|
class="label text-fog hover:text-frost transition-colors"
|
||||||
|
>
|
||||||
|
{{- $platform | upper -}}
|
||||||
|
{{ partial "icon.html" "arrow-external" }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
+96
-44
@@ -1,81 +1,133 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8" />
|
||||||
<meta name="htmx-config" content='{"globalViewTransitions":true,"scrollBehavior":"smooth"}'>
|
<meta name="htmx-config" content='{"globalViewTransitions":true,"scrollBehavior":"smooth"}' />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="theme-color" content="#FF1A8C">
|
<meta name="theme-color" content="#FF1A8C" />
|
||||||
|
|
||||||
<title>
|
<title>
|
||||||
{{- if .IsHome -}}
|
{{- if .IsHome -}}
|
||||||
{{- .Site.Title }} — {{ .Site.Params.tagline -}}
|
{{- .Site.Title }} —
|
||||||
|
{{ .Site.Params.tagline -}}
|
||||||
{{- else -}}
|
{{- else -}}
|
||||||
{{- .Title }} — {{ .Site.Title -}}
|
{{- .Title }} —
|
||||||
|
{{ .Site.Title -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</title>
|
</title>
|
||||||
|
|
||||||
<meta name="description" content="{{ with .Description }}{{ . }}{{ else }}{{ .Site.Params.description }}{{ end }}">
|
<meta name="description" content="{{ with .Description }}{{ . }}{{ else }}{{ .Site.Params.description }}{{ end }}" />
|
||||||
<meta name="author" content="{{ with .Params.author }}{{ . }}{{ else }}{{ .Site.Params.author }}{{ 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 }}
|
{{- if .Site.Params.robots }}<meta name="robots" content="{{ .Site.Params.robots }}" />{{ end }}
|
||||||
|
|
||||||
|
|
||||||
<!-- Open Graph -->
|
<!-- Open Graph -->
|
||||||
<meta property="og:site_name" content="{{ .Site.Title }}">
|
<meta property="og:site_name" content="{{ .Site.Title }}" />
|
||||||
<meta property="og:title" content="{{ if .IsHome }}{{ .Site.Title }} — {{ .Site.Params.tagline }}{{ else }}{{ .Title }}{{ end }}">
|
<meta
|
||||||
<meta property="og:description" content="{{ with .Description }}{{ . }}{{ else }}{{ .Site.Params.description }}{{ end }}">
|
property="og:title"
|
||||||
<meta property="og:url" content="{{ .Permalink }}">
|
content="{{ if .IsHome }}
|
||||||
<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}">
|
{{ .Site.Title }} —
|
||||||
<meta property="og:locale" content="{{ .Site.LanguageCode | default "en_US" | replaceRE "-" "_" }}">
|
{{ .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 -}}
|
{{- $ogImage := .Site.Params.ogImage -}}
|
||||||
{{- $ogImageAlt := .Site.Title -}}
|
{{- $ogImageAlt := .Site.Title -}}
|
||||||
{{- with .Params.banner -}}
|
{{- with .Params.banner -}}
|
||||||
{{- $ogImage = .src -}}
|
{{- $ogImage = .src -}}
|
||||||
{{- $ogImageAlt = $.Title -}}
|
{{- $ogImageAlt = $.Title -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
<meta property="og:image" content="{{ $ogImage | absURL }}">
|
<meta property="og:image" content="{{ $ogImage | absURL }}" />
|
||||||
<meta property="og:image:alt" content="{{ $ogImageAlt }}">
|
<meta property="og:image:alt" content="{{ $ogImageAlt }}" />
|
||||||
<meta property="og:image:width" content="1200">
|
<meta property="og:image:width" content="1200" />
|
||||||
<meta property="og:image:height" content="630">
|
<meta property="og:image:height" content="630" />
|
||||||
|
|
||||||
{{- if .IsPage }}
|
{{- if .IsPage }}
|
||||||
<meta property="article:published_time" content="{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}">
|
<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" }}">
|
<meta property="article:modified_time" content="{{ .Lastmod.Format "2006-01-02T15:04:05Z07:00" }}" />
|
||||||
{{- with .Params.author }}<meta property="article:author" content="{{ . }}">{{ end }}
|
{{- with .Params.author }}<meta property="article:author" content="{{ . }}" />{{ end }}
|
||||||
{{- range .Params.categories }}<meta property="article:section" content="{{ . }}">{{ end }}
|
{{- range .Params.categories }}<meta property="article:section" content="{{ . }}" />{{ end }}
|
||||||
{{- range .Params.tags }}<meta property="article:tag" content="{{ . }}">{{ end }}
|
{{- range .Params.tags }}<meta property="article:tag" content="{{ . }}" />{{ end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
|
|
||||||
<!-- Twitter / X Card -->
|
<!-- Twitter / X Card -->
|
||||||
<meta name="twitter:card" content="summary_large_image">
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
{{- with .Site.Params.twitterHandle }}
|
{{- with .Site.Params.twitterHandle }}
|
||||||
<meta name="twitter:site" content="@{{ . }}">
|
<meta name="twitter:site" content="@{{ . }}" />
|
||||||
{{- end }}
|
{{- end }}
|
||||||
<meta name="twitter:title" content="{{ if .IsHome }}{{ .Site.Title }} — {{ .Site.Params.tagline }}{{ else }}{{ .Title }}{{ end }}">
|
<meta
|
||||||
<meta name="twitter:description" content="{{ with .Description }}{{ . }}{{ else }}{{ .Site.Params.description }}{{ end }}">
|
name="twitter:title"
|
||||||
<meta name="twitter:image" content="{{ $ogImage | absURL }}">
|
content="{{ if .IsHome }}
|
||||||
<meta name="twitter:image:alt" content="{{ $ogImageAlt }}">
|
{{ .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 -->
|
<!-- Canonical -->
|
||||||
<link rel="canonical" href="{{ .Permalink }}">
|
<link rel="canonical" href="{{ .Permalink }}" />
|
||||||
|
|
||||||
<!-- JSON-LD structured data -->
|
<!-- JSON-LD structured data -->
|
||||||
{{- partial "schema.html" . -}}
|
{{- partial "schema.html" . -}}
|
||||||
|
|
||||||
|
|
||||||
<!-- Fonts — Bebas Neue + Barlow + Share Tech Mono (non-render-blocking) -->
|
<!-- Fonts — Bebas Neue + Barlow + Share Tech Mono (non-render-blocking) -->
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<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
|
||||||
<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'">
|
rel="preload"
|
||||||
<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>
|
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 via Hugo Pipes + PostCSS + Tailwind v4 -->
|
||||||
{{- $css := resources.Get "css/main.css" | css.PostCSS -}}
|
{{- $css := resources.Get "css/main.css" | css.PostCSS -}}
|
||||||
{{- if eq hugo.Environment "production" -}}
|
{{- if eq hugo.Environment "production" -}}
|
||||||
{{- $css = $css | minify | fingerprint "sha256" -}}
|
{{- $css = $css | minify | fingerprint "sha256" -}}
|
||||||
{{- end -}}
|
{{- 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 -->
|
<!-- Favicon & PWA -->
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
|
<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="32x32" href="/favicon-32x32.png" />
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.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.svg" type="image/svg+xml" />
|
||||||
<link rel="icon" href="/favicon.ico" sizes="any">
|
<link rel="icon" href="/favicon.ico" sizes="any" />
|
||||||
<link rel="manifest" href="/site.webmanifest">
|
<link rel="manifest" href="/site.webmanifest" />
|
||||||
<meta name="msapplication-TileColor" content="#050510">
|
<meta name="msapplication-TileColor" content="#050510" />
|
||||||
|
|||||||
@@ -1,11 +1,55 @@
|
|||||||
{{- /* Inline SVG icon. Usage: {{ partial "icon.html" "arrow-right" }}
|
{{- /* 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 := . -}}
|
{{- $name := . -}}
|
||||||
{{- if eq $name "arrow-right" -}}
|
{{- 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" -}}
|
{{- 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" -}}
|
{{- 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 -}}
|
{{- end -}}
|
||||||
|
|||||||
+11
-10
@@ -2,15 +2,16 @@
|
|||||||
Renders a Hugo image resource as an optimised WebP <img> with responsive srcset.
|
Renders a Hugo image resource as an optimised WebP <img> with responsive srcset.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
res — Hugo image resource (required)
|
res — Hugo image resource (required)
|
||||||
widths — slice of pixel widths to generate, e.g. (slice 600 1200)
|
widths — slice of pixel widths to generate, e.g. (slice 600 1200)
|
||||||
default: (slice 800 1600)
|
default: (slice 800 1600)
|
||||||
sizes — value for the <img sizes> attribute
|
sizes — value for the <img sizes> attribute
|
||||||
default: "100vw"
|
default: "100vw"
|
||||||
class — CSS classes applied to <img>
|
class — CSS classes applied to <img>
|
||||||
alt — alt text (default "")
|
alt — alt text (default "")
|
||||||
loading — "lazy" or "eager" (default "lazy")
|
loading — "lazy" or "eager" (default "lazy")
|
||||||
*/ -}}
|
*/
|
||||||
|
-}}
|
||||||
{{- $res := .res -}}
|
{{- $res := .res -}}
|
||||||
{{- $widths := .widths | default (slice 800 1600) -}}
|
{{- $widths := .widths | default (slice 800 1600) -}}
|
||||||
{{- $sizes := .sizes | default "100vw" -}}
|
{{- $sizes := .sizes | default "100vw" -}}
|
||||||
@@ -35,4 +36,4 @@
|
|||||||
height="{{ $primary.Height }}"
|
height="{{ $primary.Height }}"
|
||||||
loading="{{ $loading }}"
|
loading="{{ $loading }}"
|
||||||
decoding="async"
|
decoding="async"
|
||||||
>
|
/>
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
{{- /*
|
{{- /*
|
||||||
Logo image.
|
Logo image.
|
||||||
Usage: {{ partial "logo.html" (dict "class" "h-8 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")
|
Params: class — CSS classes on the <img /> element (default: "h-9 w-auto") */ -}}
|
||||||
*/ -}}
|
|
||||||
{{- $class := .class | 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
@@ -2,35 +2,32 @@
|
|||||||
Renders an image or video from a front matter map.
|
Renders an image or video from a front matter map.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
{{ partial "media.html" (dict "media" .Params.banner "class" "w-full h-full object-cover") }}
|
{{ 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)
|
|
||||||
*/ -}}
|
|
||||||
|
|
||||||
|
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 -}}
|
{{- $media := .media -}}
|
||||||
{{- $class := .class | default "" -}}
|
{{- $class := .class | default "" -}}
|
||||||
{{- $lazy := .lazy | default true -}}
|
{{- $lazy := .lazy | default true -}}
|
||||||
|
|
||||||
{{- with $media -}}
|
{{- with $media -}}
|
||||||
{{- if eq .type "video" -}}
|
{{- if eq .type "video" -}}
|
||||||
<video
|
<video
|
||||||
class="{{ $class }}"
|
class="{{ $class }}"
|
||||||
src="{{ .src }}"
|
src="{{ .src }}"
|
||||||
autoplay
|
autoplay
|
||||||
loop
|
loop
|
||||||
muted
|
muted
|
||||||
playsinline
|
playsinline
|
||||||
{{- with .alt }} aria-label="{{ . }}"{{ end }}
|
{{- with .alt }}aria-label="{{ . }}"{{ end }}
|
||||||
></video>
|
></video>
|
||||||
{{- else -}}
|
{{- else -}}
|
||||||
<img
|
<img
|
||||||
class="{{ $class }}"
|
class="{{ $class }}"
|
||||||
src="{{ .src }}"
|
src="{{ .src }}"
|
||||||
alt="{{ .alt | default "" }}"
|
alt="{{ .alt | default "" }}"
|
||||||
{{- if $lazy }} loading="lazy" decoding="async"{{ end }}
|
{{- if $lazy }}loading="lazy" decoding="async"{{ end }}
|
||||||
>
|
/>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|||||||
+88
-53
@@ -10,7 +10,11 @@
|
|||||||
:class="$store.nav.open || scrolled ? 'bg-ink/95 backdrop-blur-md shadow-[0_1px_0_var(--color-zinc)]' : ''"
|
:class="$store.nav.open || scrolled ? 'bg-ink/95 backdrop-blur-md shadow-[0_1px_0_var(--color-zinc)]' : ''"
|
||||||
>
|
>
|
||||||
<!-- Logotype -->
|
<!-- 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") -}}
|
{{- 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">
|
<span class="logo-glitch font-display text-2xl md:text-3xl leading-none tracking-wide">
|
||||||
{{- .Site.Params.logoText -}}
|
{{- .Site.Params.logoText -}}
|
||||||
@@ -20,19 +24,19 @@
|
|||||||
<!-- Desktop navigation -->
|
<!-- Desktop navigation -->
|
||||||
<nav class="hidden md:flex items-center gap-8" aria-label="Primary navigation">
|
<nav class="hidden md:flex items-center gap-8" aria-label="Primary navigation">
|
||||||
{{- range .Site.Menus.main -}}
|
{{- range .Site.Menus.main -}}
|
||||||
{{- $href := .URL -}}
|
{{- $href := .URL -}}
|
||||||
<a
|
<a
|
||||||
href="{{ $href }}"
|
href="{{ $href }}"
|
||||||
class="label relative transition-colors"
|
class="label relative transition-colors"
|
||||||
:class="($store.nav.path === '{{ $href }}' || ('{{ $href }}' !== '/' && $store.nav.path.startsWith('{{ $href }}'))) ? 'text-heat' : 'text-fog hover:text-chalk'"
|
:class="($store.nav.path === '{{ $href }}' || ('{{ $href }}' !== '/' && $store.nav.path.startsWith('{{ $href }}'))) ? 'text-heat' : 'text-fog hover:text-chalk'"
|
||||||
>
|
>
|
||||||
{{ .Name }}
|
{{ .Name }}
|
||||||
<span
|
<span
|
||||||
class="absolute -bottom-0.5 left-0 h-px bg-heat transition-all duration-300 ease-out"
|
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="($store.nav.path === '{{ $href }}' || ('{{ $href }}' !== '/' && $store.nav.path.startsWith('{{ $href }}'))) ? 'width: 100%' : 'width: 0'"
|
||||||
style="width: 0"
|
style="width: 0"
|
||||||
></span>
|
></span>
|
||||||
</a>
|
</a>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
@@ -45,12 +49,18 @@
|
|||||||
aria-controls="mobile-menu"
|
aria-controls="mobile-menu"
|
||||||
aria-label="Toggle navigation"
|
aria-label="Toggle navigation"
|
||||||
>
|
>
|
||||||
<span class="block h-px w-6 bg-current transition-all duration-300 origin-center"
|
<span
|
||||||
:class="$store.nav.open ? 'rotate-45 translate-y-[7px]' : ''"></span>
|
class="block h-px w-6 bg-current transition-all duration-300 origin-center"
|
||||||
<span class="block h-px w-4 bg-current transition-all duration-200"
|
:class="$store.nav.open ? 'rotate-45 translate-y-[7px]' : ''"
|
||||||
:class="$store.nav.open ? 'opacity-0' : 'opacity-100'"></span>
|
></span>
|
||||||
<span class="block h-px w-6 bg-current transition-all duration-300 origin-center"
|
<span
|
||||||
:class="$store.nav.open ? '-rotate-45 -translate-y-[7px]' : ''"></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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -73,51 +83,70 @@
|
|||||||
<div class="gradient-line flex-none"></div>
|
<div class="gradient-line flex-none"></div>
|
||||||
|
|
||||||
<!-- Decorative background text -->
|
<!-- Decorative background text -->
|
||||||
<div class="graffiti-tag absolute -bottom-4 -right-4 select-none pointer-events-none"
|
<div
|
||||||
style="-webkit-text-stroke-color: rgba(155,0,255,0.07);" aria-hidden="true">MENU</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 -->
|
<!-- Main nav links -->
|
||||||
<nav class="flex-1 flex flex-col justify-center gutter-x py-10" aria-label="Mobile navigation">
|
<nav class="flex-1 flex flex-col justify-center gutter-x py-10" aria-label="Mobile navigation">
|
||||||
<div class="flex flex-col gap-0">
|
<div class="flex flex-col gap-0">
|
||||||
{{- $i := 0 -}}
|
{{- $i := 0 -}}
|
||||||
{{- range .Site.Menus.main -}}
|
{{- range .Site.Menus.main -}}
|
||||||
{{- $href := .URL -}}
|
{{- $href := .URL -}}
|
||||||
<a
|
<a
|
||||||
href="{{ $href }}"
|
href="{{ $href }}"
|
||||||
class="group relative leading-none py-3 overflow-hidden"
|
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"
|
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"
|
@click="$store.nav.open = false"
|
||||||
>
|
>
|
||||||
<!-- Hover sweep -->
|
<!-- Hover sweep -->
|
||||||
<span class="absolute inset-y-0 left-0 w-0 group-hover:w-full transition-all duration-300 ease-out"
|
<span
|
||||||
style="background: linear-gradient(90deg, rgba(255,26,140,0.07), transparent);"></span>
|
class="absolute inset-y-0 left-0 w-0 group-hover:w-full transition-all duration-300 ease-out"
|
||||||
<!-- Link text -->
|
style="background: linear-gradient(90deg, rgba(255,26,140,0.07), transparent);"
|
||||||
<span class="relative transition-colors duration-200 text-paper group-hover:text-heat uppercase"
|
></span>
|
||||||
:class="($store.nav.path === '{{ $href }}' || ('{{ $href }}' !== '/' && $store.nav.path.startsWith('{{ $href }}'))) ? 'text-gradient' : ''"
|
<!-- Link text -->
|
||||||
>{{ .Name }}</span>
|
<span
|
||||||
<!-- Index number -->
|
class="relative transition-colors duration-200 text-paper group-hover:text-heat uppercase"
|
||||||
<span class="absolute right-0 top-1/2 -translate-y-1/2 label text-smoke group-hover:text-heat transition-colors duration-200"
|
:class="($store.nav.path === '{{ $href }}' || ('{{ $href }}' !== '/' && $store.nav.path.startsWith('{{ $href }}'))) ? 'text-gradient' : ''"
|
||||||
style="animation: mob-link-in 0.4s var(--ease-out-expo) {{ add (mul $i 70) 100 }}ms both"
|
>{{ .Name }}</span
|
||||||
>0{{ add $i 1 }}</span>
|
>
|
||||||
</a>
|
<!-- Index number -->
|
||||||
{{- $i = add $i 1 -}}
|
<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 -}}
|
{{- end -}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gradient-line my-8"
|
<div class="gradient-line my-8" style="animation: mob-link-in 0.4s ease {{ mul $i 70 }}ms both"></div>
|
||||||
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"
|
<div
|
||||||
style="animation: mob-link-in 0.4s ease {{ add (mul $i 70) 40 }}ms both">
|
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 -}}
|
{{- 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 -}}
|
{{- end -}}
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<!-- Bottom bar -->
|
<!-- Bottom bar -->
|
||||||
<div class="flex-none gutter-x pb-8 pt-4 border-t border-zinc"
|
<div
|
||||||
style="animation: mob-link-in 0.4s ease 420ms both">
|
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>
|
<p class="label text-smoke">{{ .Site.Params.tagline }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -125,8 +154,14 @@
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@keyframes mob-link-in {
|
@keyframes mob-link-in {
|
||||||
from { opacity: 0; transform: translateY(14px); }
|
from {
|
||||||
to { opacity: 1; transform: translateY(0); }
|
opacity: 0;
|
||||||
}
|
transform: translateY(14px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,33 +1,40 @@
|
|||||||
{{- /* Custom pagination component.
|
{{- /* Custom pagination component.
|
||||||
Call as: {{ partial "pagination.html" . }}
|
Call as: {{ partial "pagination.html" .
|
||||||
|
}}
|
||||||
*/ -}}
|
*/ -}}
|
||||||
{{- $paginator := .Paginator -}}
|
{{- $paginator := .Paginator -}}
|
||||||
{{- if gt $paginator.TotalPages 1 -}}
|
{{- 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 -}}
|
{{- range $paginator.Pagers -}}
|
||||||
<a
|
<a
|
||||||
href="{{ $paginator.Prev.URL }}"
|
href="{{ .URL }}"
|
||||||
class="label border border-mist text-ash px-5 py-3 hover:border-gold hover:text-gold transition-all duration-300"
|
class="label border px-4 py-3 transition-all duration-300 {{ if eq . $paginator }}
|
||||||
aria-label="Previous page"
|
border-gold text-gold
|
||||||
>{{ partial "icon.html" "arrow-left" }} Prev</a>
|
{{ else }}
|
||||||
{{- end -}}
|
border-mist text-ash hover:border-gold hover:text-gold
|
||||||
|
{{ end }}"
|
||||||
|
{{- if eq . $paginator }}aria-current="page"{{ end }}
|
||||||
|
>{{ .PageNumber }}</a
|
||||||
|
>
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
{{- range $paginator.Pagers -}}
|
{{- if $paginator.HasNext -}}
|
||||||
<a
|
<a
|
||||||
href="{{ .URL }}"
|
href="{{ $paginator.Next.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 }}"
|
class="label border border-mist text-ash px-5 py-3 hover:border-gold hover:text-gold transition-all duration-300"
|
||||||
{{- if eq . $paginator }} aria-current="page"{{ end }}
|
aria-label="Next page"
|
||||||
>{{ .PageNumber }}</a>
|
>Next {{ partial "icon.html" "arrow-right" }}</a
|
||||||
{{- end -}}
|
>
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
{{- if $paginator.HasNext -}}
|
</nav>
|
||||||
<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>
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|||||||
@@ -1,50 +1,56 @@
|
|||||||
{{- /* Large overlay card for featured/secondary slots.
|
{{- /* Large overlay card for featured/secondary slots.
|
||||||
Expects a post page as context (.).
|
Expects a post page as context (.).
|
||||||
*/ -}}
|
*/
|
||||||
|
-}}
|
||||||
{{- $post := . -}}
|
{{- $post := . -}}
|
||||||
<article class="group relative overflow-hidden aspect-[3/4] md:aspect-[4/5] card-comic">
|
<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 }}">
|
<a href="{{ $post.RelPermalink }}" class="block w-full h-full" aria-label="{{ $post.Title }}">
|
||||||
|
|
||||||
<!-- Background media — bundle banner.png → 01.png → .Params.banner -->
|
<!-- Background media — bundle banner.png → 01.png → .Params.banner -->
|
||||||
{{- $thumb := $post.Resources.GetMatch "banner.png" -}}
|
{{- $thumb := $post.Resources.GetMatch "banner.png" -}}
|
||||||
{{- if not $thumb -}}{{- $thumb = $post.Resources.GetMatch "01.png" -}}{{- end -}}
|
{{- if not $thumb -}}{{- $thumb = $post.Resources.GetMatch "01.png" -}}{{- end -}}
|
||||||
<div class="card-media w-full h-full absolute inset-0">
|
<div class="card-media w-full h-full absolute inset-0">
|
||||||
{{- if $thumb -}}
|
{{- 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) -}}
|
{{- 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 -}}
|
{{- else -}}
|
||||||
<div class="w-full h-full bg-concrete flex items-center justify-center halftone">
|
{{- with $post.Params.banner -}}
|
||||||
<span class="label text-smoke">PIVOINE</span>
|
{{- partial "media.html" (dict "media" . "class" "w-full h-full object-cover") -}}
|
||||||
</div>
|
{{- else -}}
|
||||||
{{- end -}}{{- end -}}
|
<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>
|
</div>
|
||||||
|
|
||||||
<!-- Gradient overlay -->
|
<!-- Gradient overlay -->
|
||||||
<div class="absolute inset-0 overlay-gradient transition-opacity duration-500 group-hover:opacity-90"></div>
|
<div class="absolute inset-0 overlay-gradient transition-opacity duration-500 group-hover:opacity-90"></div>
|
||||||
|
|
||||||
<!-- Diagonal heat accent -->
|
<!-- Diagonal heat accent -->
|
||||||
<div class="absolute bottom-16 left-0 w-28 h-[3px] opacity-0 group-hover:opacity-90 transition-opacity duration-300"
|
<div
|
||||||
style="background: linear-gradient(90deg, var(--color-heat), var(--color-pulse)); transform: skewX(-20deg) translateX(-4px);"></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 -->
|
<!-- Content -->
|
||||||
<div class="absolute bottom-0 left-0 right-0 p-5 md:p-6">
|
<div class="absolute bottom-0 left-0 right-0 p-5 md:p-6">
|
||||||
{{- with $post.Params.categories -}}
|
{{- with $post.Params.categories -}}
|
||||||
<div class="flex flex-wrap gap-2 mb-3">
|
<div class="flex flex-wrap gap-2 mb-3">
|
||||||
{{- range first 1 . -}}
|
{{- range first 1 . -}}
|
||||||
<span class="badge badge-outline">{{ . }}</span>
|
<span class="badge badge-outline">{{ . }}</span>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</div>
|
</div>
|
||||||
{{- end -}}
|
{{- 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 -}}
|
{{- $post.Title -}}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
{{- with $post.Params.author -}}
|
{{- with $post.Params.author -}}
|
||||||
{{- $authorPage := site.GetPage (printf "authors/%s" .) -}}
|
{{- $authorPage := site.GetPage (printf "authors/%s" .) -}}
|
||||||
{{- with $authorPage -}}
|
{{- with $authorPage -}}
|
||||||
<span class="label text-chalk opacity-70">{{ .Params.name | default .Title }}</span>
|
<span class="label text-chalk opacity-70">{{ .Params.name | default .Title }}</span>
|
||||||
<span class="text-smoke opacity-60" aria-hidden="true">/</span>
|
<span class="text-smoke opacity-60" aria-hidden="true">/</span>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
<time class="label text-chalk opacity-70" datetime="{{ $post.Date.Format "2006-01-02" }}">
|
<time class="label text-chalk opacity-70" datetime="{{ $post.Date.Format "2006-01-02" }}">
|
||||||
@@ -52,6 +58,5 @@
|
|||||||
</time>
|
</time>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</article>
|
</article>
|
||||||
|
|||||||
@@ -1,36 +1,41 @@
|
|||||||
{{- /* Compact post card for grids.
|
{{- /* Compact post card for grids.
|
||||||
Expects a post page as context (.).
|
Expects a post page as context (.).
|
||||||
*/ -}}
|
*/
|
||||||
|
-}}
|
||||||
{{- $post := . -}}
|
{{- $post := . -}}
|
||||||
<article class="group card-comic flex flex-col bg-concrete">
|
<article class="group card-comic flex flex-col bg-concrete">
|
||||||
<a href="{{ $post.RelPermalink }}" class="block flex-1 flex flex-col">
|
<a href="{{ $post.RelPermalink }}" class="block flex-1 flex flex-col">
|
||||||
|
|
||||||
<!-- Thumbnail — bundle banner.png → 01.png → .Params.banner -->
|
<!-- Thumbnail — bundle banner.png → 01.png → .Params.banner -->
|
||||||
{{- $thumb := $post.Resources.GetMatch "banner.png" -}}
|
{{- $thumb := $post.Resources.GetMatch "banner.png" -}}
|
||||||
{{- if not $thumb -}}{{- $thumb = $post.Resources.GetMatch "01.png" -}}{{- end -}}
|
{{- if not $thumb -}}{{- $thumb = $post.Resources.GetMatch "01.png" -}}{{- end -}}
|
||||||
<div class="card-media aspect-editorial">
|
<div class="card-media aspect-editorial">
|
||||||
{{- if $thumb -}}
|
{{- 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) -}}
|
{{- 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 -}}
|
{{- else -}}
|
||||||
<div class="w-full h-full flex items-center justify-center halftone">
|
{{- with $post.Params.banner -}}
|
||||||
<span class="label text-smoke text-xs">PIVOINE</span>
|
{{- partial "media.html" (dict "media" . "class" "w-full h-full object-cover") -}}
|
||||||
</div>
|
{{- else -}}
|
||||||
{{- end -}}{{- end -}}
|
<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>
|
</div>
|
||||||
|
|
||||||
<!-- Category badge — parallelogram -->
|
<!-- Category badge — parallelogram -->
|
||||||
{{- with $post.Params.categories -}}
|
{{- with $post.Params.categories -}}
|
||||||
<div class="flex flex-wrap gap-2 px-4 pt-4">
|
<div class="flex flex-wrap gap-2 px-4 pt-4">
|
||||||
{{- range first 1 . -}}
|
{{- range first 1 . -}}
|
||||||
<span class="badge">{{ . }}</span>
|
<span class="badge">{{ . }}</span>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</div>
|
</div>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
|
|
||||||
<!-- Title -->
|
<!-- 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 -}}
|
{{- $post.Title -}}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
@@ -42,10 +47,26 @@
|
|||||||
{{- $avRes := .Resources.GetMatch "avatar.*" -}}
|
{{- $avRes := .Resources.GetMatch "avatar.*" -}}
|
||||||
{{- if $avRes -}}
|
{{- if $avRes -}}
|
||||||
{{- $av := $avRes.Resize "64x webp" -}}
|
{{- $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">
|
<img
|
||||||
{{- else -}}{{- with .Params.avatar -}}
|
src="{{ $av.RelPermalink }}"
|
||||||
<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">
|
alt="{{ $authorPage.Params.name | default $authorPage.Title }}"
|
||||||
{{- end -}}{{- end -}}
|
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="label text-fog">{{ .Params.name | default .Title }}</span>
|
||||||
<span class="text-smoke" aria-hidden="true">/</span>
|
<span class="text-smoke" aria-hidden="true">/</span>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
@@ -54,6 +75,5 @@
|
|||||||
{{- $post.Date.Format "Jan 2006" -}}
|
{{- $post.Date.Format "Jan 2006" -}}
|
||||||
</time>
|
</time>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</article>
|
</article>
|
||||||
|
|||||||
@@ -20,10 +20,10 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
{{- else if and .IsPage (eq .Section "posts") -}}
|
{{- else if and .IsPage (eq .Section "posts") -}}
|
||||||
{{- $authorPage := "" -}}
|
{{- $authorPage := "" -}}
|
||||||
{{- with .Params.author -}}
|
{{- with .Params.author -}}
|
||||||
{{- $authorPage = site.GetPage (printf "authors/%s" .) -}}
|
{{- $authorPage = site.GetPage (printf "authors/%s" .) -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
<script type="application/ld+json">
|
<script type="application/ld+json">
|
||||||
{
|
{
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
|
|||||||
+234
-208
@@ -1,235 +1,261 @@
|
|||||||
{{- define "page-background" -}}
|
{{- define "page-background" -}}
|
||||||
{{- with .Params.background -}}
|
{{- with .Params.background -}}
|
||||||
<div class="fixed inset-0 -z-10 overflow-hidden" aria-hidden="true">
|
<div class="fixed inset-0 -z-10 overflow-hidden" aria-hidden="true">
|
||||||
{{- partial "media.html" (dict "media" . "class" "w-full h-full object-cover opacity-[0.15] blur-md scale-110" "lazy" false) -}}
|
{{- partial "media.html" (dict "media" . "class" "w-full h-full object-cover opacity-[0.15] blur-md scale-110" "lazy" false) -}}
|
||||||
<div class="absolute inset-0" style="background: rgba(5,5,16,0.7)"></div>
|
<div class="absolute inset-0" style="background: rgba(5,5,16,0.7)"></div>
|
||||||
</div>
|
</div>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
{{- define "main" -}}
|
{{- define "main" -}}
|
||||||
|
|
||||||
<!-- ── ARTICLE HEADER ────────────────────────────────────────── -->
|
<!-- ── ARTICLE HEADER ────────────────────────────────────────── -->
|
||||||
<header class="gutter-x pt-36 pb-12 max-w-5xl mx-auto relative overflow-hidden">
|
<header class="gutter-x pt-36 pb-12 max-w-5xl mx-auto relative overflow-hidden">
|
||||||
|
<!-- Faded decorative category text -->
|
||||||
<!-- Faded decorative category text -->
|
{{- with index .Params.categories 0 -}}
|
||||||
{{- with index .Params.categories 0 -}}
|
<div
|
||||||
<div class="graffiti-tag absolute -top-2 -right-4 select-none pointer-events-none"
|
class="graffiti-tag absolute -top-2 -right-4 select-none pointer-events-none"
|
||||||
style="-webkit-text-stroke-color: rgba(155,0,255,0.08);" aria-hidden="true">{{ . }}</div>
|
style="-webkit-text-stroke-color: rgba(155,0,255,0.08);"
|
||||||
{{- end -}}
|
aria-hidden="true"
|
||||||
|
>
|
||||||
<!-- Categories -->
|
{{ . }}
|
||||||
{{- with .Params.categories -}}
|
</div>
|
||||||
<div class="flex flex-wrap gap-2 mb-6">
|
|
||||||
{{- range . -}}
|
|
||||||
<a
|
|
||||||
href="/categories/{{ . | urlize }}/"
|
|
||||||
class="badge badge-outline"
|
|
||||||
>{{ . }}</a>
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</div>
|
|
||||||
{{- end -}}
|
|
||||||
|
|
||||||
<!-- Title -->
|
|
||||||
<h1 class="font-display text-5xl md:text-7xl lg:text-8xl text-paper text-balance mb-8 leading-none">
|
|
||||||
{{- .Title -}}
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<!-- Description -->
|
<!-- Categories -->
|
||||||
{{- with .Description -}}
|
{{- with .Params.categories -}}
|
||||||
<p class="text-chalk text-xl md:text-2xl max-w-2xl mb-10 leading-relaxed text-pretty font-body font-light">
|
<div class="flex flex-wrap gap-2 mb-6">
|
||||||
{{ . }}
|
{{- range . -}}
|
||||||
</p>
|
<a href="/categories/{{ . | urlize }}/" class="badge badge-outline">{{ . }}</a>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
</div>
|
||||||
<!-- Author byline -->
|
|
||||||
{{- with .Params.author -}}
|
|
||||||
{{- $authorPage := site.GetPage (printf "authors/%s" .) -}}
|
|
||||||
{{- with $authorPage -}}
|
|
||||||
{{- partial "author-card.html" . -}}
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- end -}}
|
|
||||||
|
|
||||||
<!-- Date + reading info -->
|
|
||||||
<div class="flex flex-wrap items-center gap-6">
|
<!-- Title -->
|
||||||
<time class="label text-fog" datetime="{{ .Date.Format "2006-01-02" }}">
|
<h1 class="font-display text-5xl md:text-7xl lg:text-8xl text-paper text-balance mb-8 leading-none">
|
||||||
{{- .Date.Format "January 2, 2006" -}}
|
{{- .Title -}}
|
||||||
</time>
|
</h1>
|
||||||
{{- $imgCount := len (.Resources.Match "[0-9]*.png") -}}
|
|
||||||
{{- $itemCount := $imgCount -}}
|
<!-- Description -->
|
||||||
{{- if and (eq $imgCount 0) .Params.items -}}{{- $itemCount = len .Params.items -}}{{- end -}}
|
{{- with .Description -}}
|
||||||
{{- if gt $itemCount 0 -}}
|
<p class="text-chalk text-xl md:text-2xl max-w-2xl mb-10 leading-relaxed text-pretty font-body font-light">
|
||||||
<span class="label text-fog">{{ $itemCount }} {{ if eq $itemCount 1 }}Work{{ else }}Works{{ end }}</span>
|
{{ . }}
|
||||||
|
</p>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</div>
|
|
||||||
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<!-- ── GRADIENT DIVIDER ──────────────────────────────────────── -->
|
<!-- Author byline -->
|
||||||
<div class="gradient-line mb-0"></div>
|
{{- with .Params.author -}}
|
||||||
|
{{- $authorPage := site.GetPage (printf "authors/%s" .) -}}
|
||||||
|
{{- with $authorPage -}}
|
||||||
|
{{- partial "author-card.html" . -}}
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
<!-- ── BANNER MEDIA — bundle banner.png → 01.png → .Params.banner ── -->
|
|
||||||
{{- $bannerImg := .Resources.GetMatch "banner.png" -}}
|
|
||||||
{{- if not $bannerImg -}}{{- $bannerImg = .Resources.GetMatch "01.png" -}}{{- end -}}
|
|
||||||
{{- if $bannerImg -}}
|
|
||||||
<div class="w-full overflow-hidden mb-16 md:mb-24" style="height: clamp(320px, 60vh, 75vh)">
|
|
||||||
{{- partial "img.html" (dict "res" $bannerImg "widths" (slice 1200 1800) "sizes" "100vw" "class" "w-full h-full object-cover object-center" "alt" .Title "loading" "eager") -}}
|
|
||||||
</div>
|
|
||||||
{{- else -}}{{- with .Params.banner -}}
|
|
||||||
<div class="w-full overflow-hidden mb-16 md:mb-24" style="height: clamp(320px, 60vh, 75vh)">
|
|
||||||
{{- partial "media.html" (dict "media" . "class" "w-full h-full object-cover object-center" "lazy" false) -}}
|
|
||||||
</div>
|
|
||||||
{{- end -}}{{- end -}}
|
|
||||||
|
|
||||||
<!-- ── PROSE BODY ────────────────────────────────────────────── -->
|
<!-- Date + reading info -->
|
||||||
{{- with .Content -}}
|
<div class="flex flex-wrap items-center gap-6">
|
||||||
<article class="gutter-x mb-20 md:mb-28">
|
<time class="label text-fog" datetime="{{ .Date.Format "2006-01-02" }}">
|
||||||
<div class="max-w-5xl mx-auto">
|
{{- .Date.Format "January 2, 2006" -}}
|
||||||
<div class="max-w-3xl prose-editorial">
|
</time>
|
||||||
{{ . }}
|
{{- $imgCount := len (.Resources.Match "[0-9]*.png") -}}
|
||||||
|
{{- $itemCount := $imgCount -}}
|
||||||
|
{{- if and (eq $imgCount 0) .Params.items -}}{{- $itemCount = len .Params.items -}}{{- end -}}
|
||||||
|
{{- if gt $itemCount 0 -}}
|
||||||
|
<span class="label text-fog">{{ $itemCount }} {{ if eq $itemCount 1 }}Work{{ else }}Works{{ end }}</span>
|
||||||
|
{{- end -}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</header>
|
||||||
</article>
|
|
||||||
{{- end -}}
|
|
||||||
|
|
||||||
{{- /* ── GENERATION NOTES (disabled) ─────────────────────────────
|
<!-- ── GRADIENT DIVIDER ──────────────────────────────────────── -->
|
||||||
|
<div class="gradient-line mb-0"></div>
|
||||||
|
|
||||||
|
<!-- ── BANNER MEDIA — bundle banner.png → 01.png → .Params.banner ── -->
|
||||||
|
{{- $bannerImg := .Resources.GetMatch "banner.png" -}}
|
||||||
|
{{- if not $bannerImg -}}{{- $bannerImg = .Resources.GetMatch "01.png" -}}{{- end -}}
|
||||||
|
{{- if $bannerImg -}}
|
||||||
|
<div class="w-full overflow-hidden mb-16 md:mb-24" style="height: clamp(320px, 60vh, 75vh)">
|
||||||
|
{{- partial "img.html" (dict "res" $bannerImg "widths" (slice 1200 1800) "sizes" "100vw" "class" "w-full h-full object-cover object-center" "alt" .Title "loading" "eager") -}}
|
||||||
|
</div>
|
||||||
|
{{- else -}}
|
||||||
|
{{- with .Params.banner -}}
|
||||||
|
<div class="w-full overflow-hidden mb-16 md:mb-24" style="height: clamp(320px, 60vh, 75vh)">
|
||||||
|
{{- partial "media.html" (dict "media" . "class" "w-full h-full object-cover object-center" "lazy" false) -}}
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ── PROSE BODY ────────────────────────────────────────────── -->
|
||||||
|
{{- with .Content -}}
|
||||||
|
<article class="gutter-x mb-20 md:mb-28">
|
||||||
|
<div class="max-w-5xl mx-auto">
|
||||||
|
<div class="max-w-3xl prose-editorial">
|
||||||
|
{{ . }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ── GENERATION NOTES (disabled — remove comment tags to enable)
|
||||||
{{- with .Params.prompt -}}
|
{{- with .Params.prompt -}}
|
||||||
<section class="gutter-x mb-20 md:mb-28">
|
<section class="gutter-x mb-20 md:mb-28">
|
||||||
<div class="max-w-5xl mx-auto">
|
<div class="max-w-5xl mx-auto">
|
||||||
<div class="flex items-center gap-5 mb-8">
|
<div class="flex items-center gap-5 mb-8">
|
||||||
<span class="badge badge-outline">Generation Notes</span>
|
<span class="badge badge-outline">Generation Notes</span>
|
||||||
<div class="flex-1 gradient-line"></div>
|
<div class="flex-1 gradient-line"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-px bg-zinc">
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-px bg-zinc">
|
||||||
{{- with .scene -}}
|
{{- with .scene -}}
|
||||||
<div class="bg-concrete p-6 md:p-8">
|
<div class="bg-concrete p-6 md:p-8">
|
||||||
<p class="label text-fog mb-4">Scene</p>
|
<p class="label text-fog mb-4">Scene</p>
|
||||||
<p class="font-body text-sm text-chalk leading-relaxed">{{ . }}</p>
|
<p class="font-body text-sm text-chalk leading-relaxed">{{ . }}</p>
|
||||||
</div>
|
</div>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- with .environment -}}
|
{{- with .environment -}}
|
||||||
<div class="bg-concrete p-6 md:p-8">
|
<div class="bg-concrete p-6 md:p-8">
|
||||||
<p class="label text-fog mb-4">Environment</p>
|
<p class="label text-fog mb-4">Environment</p>
|
||||||
<p class="font-body text-sm text-chalk leading-relaxed">{{ . }}</p>
|
<p class="font-body text-sm text-chalk leading-relaxed">{{ . }}</p>
|
||||||
</div>
|
</div>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- with .style -}}
|
{{- with .style -}}
|
||||||
<div class="bg-concrete p-6 md:p-8">
|
<div class="bg-concrete p-6 md:p-8">
|
||||||
<p class="label text-fog mb-4">Lighting & Style</p>
|
<p class="label text-fog mb-4">Lighting & Style</p>
|
||||||
<p class="font-body text-sm text-chalk leading-relaxed">{{ . }}</p>
|
<p class="font-body text-sm text-chalk leading-relaxed">{{ . }}</p>
|
||||||
</div>
|
</div>
|
||||||
{{- end -}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{{- end -}}
|
|
||||||
*/ -}}
|
|
||||||
|
|
||||||
<!-- ── GALLERY ───────────────────────────────────────────────── -->
|
|
||||||
{{- $bundleImages := .Resources.Match "[0-9]*.png" -}}
|
|
||||||
{{- $legacyItems := slice -}}
|
|
||||||
{{- with .Params.items -}}{{- $legacyItems = . -}}{{- end -}}
|
|
||||||
{{- if or $bundleImages $legacyItems -}}
|
|
||||||
<section class="gutter-x pb-24 md:pb-32" aria-label="Gallery">
|
|
||||||
<div class="max-w-5xl mx-auto">
|
|
||||||
|
|
||||||
{{- if $bundleImages -}}
|
|
||||||
{{- /* Pre-compute lightbox items so Alpine gets a static JSON array */ -}}
|
|
||||||
{{- $lbItems := slice -}}
|
|
||||||
{{- range $bundleImages -}}
|
|
||||||
{{- $stem := .Name | strings.TrimSuffix ".png" -}}
|
|
||||||
{{- $video := $.Resources.GetMatch (printf "%s.mp4" $stem) -}}
|
|
||||||
{{- $webp := .Resize "1200x webp" -}}
|
|
||||||
{{- $entry := dict "img" $webp.RelPermalink "video" "" -}}
|
|
||||||
{{- if $video -}}{{- $entry = dict "img" $webp.RelPermalink "video" $video.RelPermalink -}}{{- end -}}
|
|
||||||
{{- $lbItems = $lbItems | append $entry -}}
|
|
||||||
{{- end -}}
|
|
||||||
|
|
||||||
<div x-data="{ items: {{ $lbItems | jsonify }} }">
|
|
||||||
|
|
||||||
<div class="flex items-center gap-5 mb-10">
|
|
||||||
<span class="badge badge-gradient">Gallery</span>
|
|
||||||
<span class="label text-fog">{{ len $bundleImages }} {{ if eq (len $bundleImages) 1 }}work{{ else }}works{{ end }}</span>
|
|
||||||
<div class="flex-1 gradient-line ml-2"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="columns-1 sm:columns-2 lg:columns-3 gap-5 space-y-5">
|
|
||||||
{{- range $i, $img := $bundleImages -}}
|
|
||||||
{{- $stem := $img.Name | strings.TrimSuffix ".png" -}}
|
|
||||||
{{- $video := $.Resources.GetMatch (printf "%s.mp4" $stem) -}}
|
|
||||||
<figure class="break-inside-avoid group card-comic cursor-zoom-in"
|
|
||||||
@click="$dispatch('lightbox:open', { items, idx: {{ $i }} })">
|
|
||||||
<div class="card-media min-h-48">
|
|
||||||
{{- if $video -}}
|
|
||||||
<video class="w-full pointer-events-none" src="{{ $video.RelPermalink }}" poster="{{ $img.RelPermalink }}" autoplay loop muted playsinline></video>
|
|
||||||
{{- else -}}
|
|
||||||
{{- partial "img.html" (dict "res" $img "widths" (slice 800 1200) "sizes" "(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw" "class" "w-full pointer-events-none") -}}
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</div>
|
</div>
|
||||||
</figure>
|
|
||||||
{{- end -}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{- else -}}
|
|
||||||
<!-- Legacy front-matter items -->
|
|
||||||
<div class="flex items-center gap-5 mb-10">
|
|
||||||
<span class="badge badge-gradient">Gallery</span>
|
|
||||||
<span class="label text-fog">{{ len $legacyItems }} {{ if eq (len $legacyItems) 1 }}work{{ else }}works{{ end }}</span>
|
|
||||||
<div class="flex-1 gradient-line ml-2"></div>
|
|
||||||
</div>
|
|
||||||
<div x-data="{ selected: null }" class="columns-1 sm:columns-2 lg:columns-3 gap-5 space-y-5">
|
|
||||||
{{- range $i, $item := $legacyItems -}}
|
|
||||||
<figure class="break-inside-avoid group cursor-pointer card-comic" @click="selected = selected === {{ $i }} ? null : {{ $i }}">
|
|
||||||
<div class="card-media">
|
|
||||||
{{- partial "media.html" (dict "media" $item "class" "w-full") -}}
|
|
||||||
</div>
|
</div>
|
||||||
{{- with $item.description -}}
|
</section>
|
||||||
<figcaption class="px-4 py-3 text-fog text-sm leading-relaxed font-body transition-colors group-hover:text-chalk">{{ . }}</figcaption>
|
{{- end -}}
|
||||||
{{- end -}}
|
-->
|
||||||
</figure>
|
|
||||||
{{- end -}}
|
<!-- ── GALLERY ───────────────────────────────────────────────── -->
|
||||||
</div>
|
{{- $bundleImages := .Resources.Match "[0-9]*.png" -}}
|
||||||
|
{{- $legacyItems := slice -}}
|
||||||
|
{{- with .Params.items -}}{{- $legacyItems = . -}}{{- end -}}
|
||||||
|
{{- if or $bundleImages $legacyItems -}}
|
||||||
|
<section class="gutter-x pb-24 md:pb-32" aria-label="Gallery">
|
||||||
|
<div class="max-w-5xl mx-auto">
|
||||||
|
{{- if $bundleImages -}}
|
||||||
|
{{- /* Pre-compute lightbox items so Alpine gets a static JSON array */ -}}
|
||||||
|
{{- $lbItems := slice -}}
|
||||||
|
{{- range $bundleImages -}}
|
||||||
|
{{- $stem := .Name | strings.TrimSuffix ".png" -}}
|
||||||
|
{{- $video := $.Resources.GetMatch (printf "%s.mp4" $stem) -}}
|
||||||
|
{{- $webp := .Resize "1200x webp" -}}
|
||||||
|
{{- $entry := dict "img" $webp.RelPermalink "video" "" -}}
|
||||||
|
{{- if $video -}}{{- $entry = dict "img" $webp.RelPermalink "video" $video.RelPermalink -}}{{- end -}}
|
||||||
|
{{- $lbItems = $lbItems | append $entry -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
|
||||||
|
<div x-data="{ items: {{ $lbItems | jsonify }} }">
|
||||||
|
<div class="flex items-center gap-5 mb-10">
|
||||||
|
<span class="badge badge-gradient">Gallery</span>
|
||||||
|
<span class="label text-fog"
|
||||||
|
>{{ len $bundleImages }} {{ if eq (len $bundleImages) 1 }}work{{ else }}works{{ end }}</span
|
||||||
|
>
|
||||||
|
<div class="flex-1 gradient-line ml-2"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="columns-1 sm:columns-2 lg:columns-3 gap-5 space-y-5">
|
||||||
|
{{- range $i, $img := $bundleImages -}}
|
||||||
|
{{- $stem := $img.Name | strings.TrimSuffix ".png" -}}
|
||||||
|
{{- $video := $.Resources.GetMatch (printf "%s.mp4" $stem) -}}
|
||||||
|
<figure
|
||||||
|
class="break-inside-avoid group card-comic cursor-zoom-in"
|
||||||
|
@click="$dispatch('lightbox:open', { items, idx: {{ $i }} })"
|
||||||
|
>
|
||||||
|
<div class="card-media min-h-48">
|
||||||
|
{{- if $video -}}
|
||||||
|
<video
|
||||||
|
class="w-full pointer-events-none"
|
||||||
|
src="{{ $video.RelPermalink }}"
|
||||||
|
poster="{{ $img.RelPermalink }}"
|
||||||
|
autoplay
|
||||||
|
loop
|
||||||
|
muted
|
||||||
|
playsinline
|
||||||
|
></video>
|
||||||
|
{{- else -}}
|
||||||
|
{{- partial "img.html" (dict "res" $img "widths" (slice 800 1200) "sizes" "(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw" "class" "w-full pointer-events-none") -}}
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
</figure>
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{- else -}}
|
||||||
|
<!-- Legacy front-matter items -->
|
||||||
|
<div class="flex items-center gap-5 mb-10">
|
||||||
|
<span class="badge badge-gradient">Gallery</span>
|
||||||
|
<span class="label text-fog"
|
||||||
|
>{{ len $legacyItems }} {{ if eq (len $legacyItems) 1 }}work{{ else }}works{{ end }}</span
|
||||||
|
>
|
||||||
|
<div class="flex-1 gradient-line ml-2"></div>
|
||||||
|
</div>
|
||||||
|
<div x-data="{ selected: null }" class="columns-1 sm:columns-2 lg:columns-3 gap-5 space-y-5">
|
||||||
|
{{- range $i, $item := $legacyItems -}}
|
||||||
|
<figure
|
||||||
|
class="break-inside-avoid group cursor-pointer card-comic"
|
||||||
|
@click="selected = selected === {{ $i }} ? null : {{ $i }}"
|
||||||
|
>
|
||||||
|
<div class="card-media">
|
||||||
|
{{- partial "media.html" (dict "media" $item "class" "w-full") -}}
|
||||||
|
</div>
|
||||||
|
{{- with $item.description -}}
|
||||||
|
<figcaption
|
||||||
|
class="px-4 py-3 text-fog text-sm leading-relaxed font-body transition-colors group-hover:text-chalk"
|
||||||
|
>
|
||||||
|
{{ . }}
|
||||||
|
</figcaption>
|
||||||
|
{{- end -}}
|
||||||
|
</figure>
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{{- end -}}
|
|
||||||
|
|
||||||
<!-- ── TAGS ─────────────────────────────────────────────────── -->
|
<!-- ── TAGS ─────────────────────────────────────────────────── -->
|
||||||
{{- with .Params.tags -}}
|
{{- with .Params.tags -}}
|
||||||
<footer class="gutter-x border-t border-zinc pt-10 pb-20">
|
<footer class="gutter-x border-t border-zinc pt-10 pb-20">
|
||||||
<div class="max-w-5xl mx-auto flex flex-wrap gap-3 items-center">
|
<div class="max-w-5xl mx-auto flex flex-wrap gap-3 items-center">
|
||||||
<span class="label text-fog">Tagged:</span>
|
<span class="label text-fog">Tagged:</span>
|
||||||
{{- range . -}}
|
{{- range . -}}
|
||||||
<a
|
<a href="/tags/{{ . | urlize }}/" class="badge badge-outline"># {{ . }}</a>
|
||||||
href="/tags/{{ . | urlize }}/"
|
{{- end -}}
|
||||||
class="badge badge-outline"
|
</div>
|
||||||
># {{ . }}</a>
|
</footer>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
{{- end -}}
|
|
||||||
|
|
||||||
<!-- ── RELATED POSTS ─────────────────────────────────────────── -->
|
|
||||||
{{- $related := .Site.RegularPages.Related . | first 3 -}}
|
<!-- ── RELATED POSTS ─────────────────────────────────────────── -->
|
||||||
{{- with $related -}}
|
{{- $related := .Site.RegularPages.Related . | first 3 -}}
|
||||||
<section class="bg-concrete border-t border-zinc gutter-x py-16 md:py-24 spray-bg">
|
{{- with $related -}}
|
||||||
<div class="max-w-5xl mx-auto">
|
<section class="bg-concrete border-t border-zinc gutter-x py-16 md:py-24 spray-bg">
|
||||||
<div class="flex items-center gap-5 mb-10">
|
<div class="max-w-5xl mx-auto">
|
||||||
<h2 class="font-display text-3xl md:text-4xl text-paper leading-none">
|
<div class="flex items-center gap-5 mb-10">
|
||||||
More <span class="text-gradient">Drops</span>
|
<h2 class="font-display text-3xl md:text-4xl text-paper leading-none">
|
||||||
</h2>
|
More <span class="text-gradient">Drops</span>
|
||||||
<div class="flex-1 gradient-line ml-2"></div>
|
</h2>
|
||||||
</div>
|
<div class="flex-1 gradient-line ml-2"></div>
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-5">
|
</div>
|
||||||
{{- range . -}}
|
<div class="grid grid-cols-1 sm:grid-cols-3 gap-5">
|
||||||
{{- partial "post-card.html" . -}}
|
{{- range . -}}
|
||||||
{{- end -}}
|
{{- partial "post-card.html" . -}}
|
||||||
</div>
|
{{- end -}}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</div>
|
||||||
{{- end -}}
|
</section>
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|||||||
+22
-22
@@ -1,26 +1,26 @@
|
|||||||
{{- define "main" -}}
|
{{- define "main" -}}
|
||||||
|
<!-- Tag header -->
|
||||||
|
<header class="gutter-x pt-36 pb-16 border-b border-mist">
|
||||||
|
<div class="max-w-4xl">
|
||||||
|
<span class="label text-ash block mb-4">Tag</span>
|
||||||
|
<h1 class="font-display text-5xl md:text-7xl text-paper text-balance"># {{ .Title }}</h1>
|
||||||
|
<p class="text-ash label mt-5">
|
||||||
|
{{ len .Pages }} {{ if eq (len .Pages) 1 }}editorial{{ else }}editorials{{ end }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
<!-- Tag header -->
|
<!-- Posts grid -->
|
||||||
<header class="gutter-x pt-36 pb-16 border-b border-mist">
|
<section class="gutter-x py-16 md:py-24">
|
||||||
<div class="max-w-4xl">
|
{{- if .Paginator.Pages -}}
|
||||||
<span class="label text-ash block mb-4">Tag</span>
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-x-5 gap-y-12">
|
||||||
<h1 class="font-display text-5xl md:text-7xl text-paper text-balance"># {{ .Title }}</h1>
|
{{- range .Paginator.Pages -}}
|
||||||
<p class="text-ash label mt-5">{{ len .Pages }} {{ if eq (len .Pages) 1 }}editorial{{ else }}editorials{{ end }}</p>
|
{{- partial "post-card.html" . -}}
|
||||||
</div>
|
{{- end -}}
|
||||||
</header>
|
</div>
|
||||||
|
{{- partial "pagination.html" . -}}
|
||||||
<!-- Posts grid -->
|
{{- else -}}
|
||||||
<section class="gutter-x py-16 md:py-24">
|
<p class="text-ash label text-center py-24">No posts with this tag yet.</p>
|
||||||
{{- if .Paginator.Pages -}}
|
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-x-5 gap-y-12">
|
|
||||||
{{- range .Paginator.Pages -}}
|
|
||||||
{{- partial "post-card.html" . -}}
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</div>
|
</section>
|
||||||
{{- partial "pagination.html" . -}}
|
|
||||||
{{- else -}}
|
|
||||||
<p class="text-ash label text-center py-24">No posts with this tag yet.</p>
|
|
||||||
{{- end -}}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|||||||
+8
-3
@@ -4,13 +4,18 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "hugo server --buildDrafts --disableFastRender",
|
"dev": "hugo server --buildDrafts --disableFastRender",
|
||||||
"build": "NODE_ENV=production hugo --minify"
|
"build": "NODE_ENV=production hugo --minify",
|
||||||
|
"format": "prettier --write \"layouts/**/*.html\" \"assets/**/*.css\" \"assets/**/*.js\" \"content/**/*.md\" \"*.toml\"",
|
||||||
|
"format:check": "prettier --check \"layouts/**/*.html\" \"assets/**/*.css\" \"assets/**/*.js\" \"content/**/*.md\" \"*.toml\""
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"tailwindcss": "^4.0.0",
|
|
||||||
"@tailwindcss/postcss": "^4.0.0",
|
"@tailwindcss/postcss": "^4.0.0",
|
||||||
"autoprefixer": "^10.4.0",
|
"autoprefixer": "^10.4.0",
|
||||||
"postcss": "^8.5.0",
|
"postcss": "^8.5.0",
|
||||||
"postcss-cli": "^11.0.0"
|
"postcss-cli": "^11.0.0",
|
||||||
|
"prettier": "^3.8.3",
|
||||||
|
"prettier-plugin-go-template": "^0.0.15",
|
||||||
|
"prettier-plugin-toml": "^2.0.6",
|
||||||
|
"tailwindcss": "^4.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+56
@@ -20,6 +20,15 @@ importers:
|
|||||||
postcss-cli:
|
postcss-cli:
|
||||||
specifier: ^11.0.0
|
specifier: ^11.0.0
|
||||||
version: 11.0.1(jiti@2.6.1)(postcss@8.5.8)
|
version: 11.0.1(jiti@2.6.1)(postcss@8.5.8)
|
||||||
|
prettier:
|
||||||
|
specifier: ^3.8.3
|
||||||
|
version: 3.8.3
|
||||||
|
prettier-plugin-go-template:
|
||||||
|
specifier: ^0.0.15
|
||||||
|
version: 0.0.15(prettier@3.8.3)
|
||||||
|
prettier-plugin-toml:
|
||||||
|
specifier: ^2.0.6
|
||||||
|
version: 2.0.6(prettier@3.8.3)
|
||||||
tailwindcss:
|
tailwindcss:
|
||||||
specifier: ^4.0.0
|
specifier: ^4.0.0
|
||||||
version: 4.2.2
|
version: 4.2.2
|
||||||
@@ -134,6 +143,12 @@ packages:
|
|||||||
'@tailwindcss/postcss@4.2.2':
|
'@tailwindcss/postcss@4.2.2':
|
||||||
resolution: {integrity: sha512-n4goKQbW8RVXIbNKRB/45LzyUqN451deQK0nzIeauVEqjlI49slUlgKYJM2QyUzap/PcpnS7kzSUmPb1sCRvYQ==}
|
resolution: {integrity: sha512-n4goKQbW8RVXIbNKRB/45LzyUqN451deQK0nzIeauVEqjlI49slUlgKYJM2QyUzap/PcpnS7kzSUmPb1sCRvYQ==}
|
||||||
|
|
||||||
|
'@taplo/core@0.2.0':
|
||||||
|
resolution: {integrity: sha512-r8bl54Zj1In3QLkiW/ex694bVzpPJ9EhwqT9xkcUVODnVUGirdB1JTsmiIv0o1uwqZiwhi8xNnTOQBRQCpizrQ==}
|
||||||
|
|
||||||
|
'@taplo/lib@0.5.0':
|
||||||
|
resolution: {integrity: sha512-+xIqpQXJco3T+VGaTTwmhxLa51qpkQxCjRwezjFZgr+l21ExlywJFcDfTrNmL6lG6tqb0h8GyJKO3UPGPtSCWg==}
|
||||||
|
|
||||||
ansi-regex@5.0.1:
|
ansi-regex@5.0.1:
|
||||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -413,6 +428,23 @@ packages:
|
|||||||
resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==}
|
resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==}
|
||||||
engines: {node: ^10 || ^12 || >=14}
|
engines: {node: ^10 || ^12 || >=14}
|
||||||
|
|
||||||
|
prettier-plugin-go-template@0.0.15:
|
||||||
|
resolution: {integrity: sha512-WqU92E1NokWYNZ9mLE6ijoRg6LtIGdLMePt2C7UBDjXeDH9okcRI3zRqtnWR4s5AloiqyvZ66jNBAa9tmRY5EQ==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
prettier: ^3.0.0
|
||||||
|
|
||||||
|
prettier-plugin-toml@2.0.6:
|
||||||
|
resolution: {integrity: sha512-12N/wBuHa9jd/KVy9pRP20NMKxQfQLMseQCt66lIbLaPLItvGUcSIryE1eZZMJ7loSws6Ig3M2Elc2EreNh76w==}
|
||||||
|
engines: {node: '>=16.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
prettier: ^3.0.3
|
||||||
|
|
||||||
|
prettier@3.8.3:
|
||||||
|
resolution: {integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==}
|
||||||
|
engines: {node: '>=14'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
pretty-hrtime@1.0.3:
|
pretty-hrtime@1.0.3:
|
||||||
resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==}
|
resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
@@ -462,6 +494,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||||
engines: {node: '>=8.0'}
|
engines: {node: '>=8.0'}
|
||||||
|
|
||||||
|
ulid@2.4.0:
|
||||||
|
resolution: {integrity: sha512-fIRiVTJNcSRmXKPZtGzFQv9WRrZ3M9eoptl/teFJvjOzmpU+/K/JH6HZ8deBfb5vMEpicJcLn7JmvdknlMq7Zg==}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
universalify@2.0.1:
|
universalify@2.0.1:
|
||||||
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
|
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
|
||||||
engines: {node: '>= 10.0.0'}
|
engines: {node: '>= 10.0.0'}
|
||||||
@@ -585,6 +621,12 @@ snapshots:
|
|||||||
postcss: 8.5.8
|
postcss: 8.5.8
|
||||||
tailwindcss: 4.2.2
|
tailwindcss: 4.2.2
|
||||||
|
|
||||||
|
'@taplo/core@0.2.0': {}
|
||||||
|
|
||||||
|
'@taplo/lib@0.5.0':
|
||||||
|
dependencies:
|
||||||
|
'@taplo/core': 0.2.0
|
||||||
|
|
||||||
ansi-regex@5.0.1: {}
|
ansi-regex@5.0.1: {}
|
||||||
|
|
||||||
ansi-styles@4.3.0:
|
ansi-styles@4.3.0:
|
||||||
@@ -820,6 +862,18 @@ snapshots:
|
|||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
source-map-js: 1.2.1
|
source-map-js: 1.2.1
|
||||||
|
|
||||||
|
prettier-plugin-go-template@0.0.15(prettier@3.8.3):
|
||||||
|
dependencies:
|
||||||
|
prettier: 3.8.3
|
||||||
|
ulid: 2.4.0
|
||||||
|
|
||||||
|
prettier-plugin-toml@2.0.6(prettier@3.8.3):
|
||||||
|
dependencies:
|
||||||
|
'@taplo/lib': 0.5.0
|
||||||
|
prettier: 3.8.3
|
||||||
|
|
||||||
|
prettier@3.8.3: {}
|
||||||
|
|
||||||
pretty-hrtime@1.0.3: {}
|
pretty-hrtime@1.0.3: {}
|
||||||
|
|
||||||
read-cache@1.0.0:
|
read-cache@1.0.0:
|
||||||
@@ -861,6 +915,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-number: 7.0.0
|
is-number: 7.0.0
|
||||||
|
|
||||||
|
ulid@2.4.0: {}
|
||||||
|
|
||||||
universalify@2.0.1: {}
|
universalify@2.0.1: {}
|
||||||
|
|
||||||
update-browserslist-db@1.2.3(browserslist@4.28.1):
|
update-browserslist-db@1.2.3(browserslist@4.28.1):
|
||||||
|
|||||||
Reference in New Issue
Block a user