diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..5881d9a --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +public/ +resources/ +node_modules/ +.hugo_build.lock +static/ diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..aa40779 --- /dev/null +++ b/.prettierrc @@ -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" + } + } + ] +} diff --git a/assets/css/main.css b/assets/css/main.css index 9d08e1c..06ccf74 100644 --- a/assets/css/main.css +++ b/assets/css/main.css @@ -7,53 +7,58 @@ /* ── Design tokens — sneaker drop culture ────────────────────── */ @theme { - /* Dark base — deep navy-black */ - --color-void: #050510; - --color-ink: #09091A; - --color-concrete: #0F0F22; - --color-zinc: #1C1C38; - --color-smoke: #383860; - --color-fog: #6868A0; - --color-chalk: #B8B8E0; - --color-paper: #EEEEFF; + --color-void: #050510; + --color-ink: #09091a; + --color-concrete: #0f0f22; + --color-zinc: #1c1c38; + --color-smoke: #383860; + --color-fog: #6868a0; + --color-chalk: #b8b8e0; + --color-paper: #eeeeff; /* Gradient triad — pink → purple → ice */ - --color-heat: #FF1A8C; /* hot pink — primary energy */ - --color-pulse: #9B00FF; /* electric purple — mid */ - --color-frost: #00C8FF; /* ice blue — cool accent */ - --color-ember: #FF4455; /* alert red */ - --color-lime: #1AFF8D; /* acid lime — highlight */ - --color-stem: #FF7A1A; /* peony stem orange */ + --color-heat: #ff1a8c; /* hot pink — primary energy */ + --color-pulse: #9b00ff; /* electric purple — mid */ + --color-frost: #00c8ff; /* ice blue — cool accent */ + --color-ember: #ff4455; /* alert red */ + --color-lime: #1aff8d; /* acid lime — highlight */ + --color-stem: #ff7a1a; /* peony stem orange */ /* Backward-compat aliases so existing templates still work */ - --color-gold: var(--color-heat); - --color-gold-dim: #CC1570; - --color-hot: var(--color-heat); - --color-volt: var(--color-lime); - --color-ice: var(--color-frost); - --color-mist: var(--color-zinc); - --color-ash: var(--color-smoke); - --color-graphite: var(--color-concrete); - --color-charcoal: var(--color-ink); + --color-gold: var(--color-heat); + --color-gold-dim: #cc1570; + --color-hot: var(--color-heat); + --color-volt: var(--color-lime); + --color-ice: var(--color-frost); + --color-mist: var(--color-zinc); + --color-ash: var(--color-smoke); + --color-graphite: var(--color-concrete); + --color-charcoal: var(--color-ink); /* ── Typography ─────────────────────────────────────────────── */ --font-display: "Bebas Neue", "Arial Black", sans-serif; - --font-body: "Barlow", system-ui, sans-serif; - --font-comic: "Unbounded", "Arial Black", sans-serif; - --font-mono: "Share Tech Mono", "Courier New", monospace; + --font-body: "Barlow", system-ui, sans-serif; + --font-comic: "Unbounded", "Arial Black", sans-serif; + --font-mono: "Share Tech Mono", "Courier New", monospace; /* ── Easing ─────────────────────────────────────────────────── */ - --ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1); - --ease-sharp: cubic-bezier(0.4, 0, 0.6, 1); + --ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1); + --ease-sharp: cubic-bezier(0.4, 0, 0.6, 1); --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 ─────────────────────────────────────────────────────── */ @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 { background-color: var(--color-void); @@ -66,9 +71,16 @@ 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-weight: 400; letter-spacing: 0.01em; @@ -82,7 +94,12 @@ 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 { background-color: var(--color-heat); @@ -95,14 +112,20 @@ } /* Gradient scrollbar */ - ::-webkit-scrollbar { width: 4px; height: 4px; } - ::-webkit-scrollbar-track { background: var(--color-ink); } - ::-webkit-scrollbar-thumb { background: linear-gradient(180deg, var(--color-heat), var(--color-frost)); } + ::-webkit-scrollbar { + width: 4px; + height: 4px; + } + ::-webkit-scrollbar-track { + background: var(--color-ink); + } + ::-webkit-scrollbar-thumb { + background: linear-gradient(180deg, var(--color-heat), var(--color-frost)); + } } /* ── Components ───────────────────────────────────────────────── */ @layer components { - /* ── Gradient text ─────────────────────────────────────────── */ .text-gradient { background: var(--color-heat); @@ -113,7 +136,13 @@ } .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%; -webkit-background-clip: text; background-clip: text; @@ -128,7 +157,7 @@ to top, rgba(5, 5, 16, 0.98) 0%, rgba(5, 5, 16, 0.65) 40%, - rgba(5, 5, 16, 0.1) 70%, + rgba(5, 5, 16, 0.1) 70%, transparent 100% ); } @@ -136,8 +165,8 @@ .overlay-gradient-hero { background: linear-gradient( 155deg, - rgba(5, 5, 16, 0.1) 0%, - rgba(5, 5, 16, 0.5) 45%, + rgba(5, 5, 16, 0.1) 0%, + rgba(5, 5, 16, 0.5) 45%, rgba(5, 5, 16, 0.97) 100% ); } @@ -165,23 +194,58 @@ padding: 5px 16px; text-transform: uppercase; 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, a > .badge { cursor: pointer; } + a.badge:hover { + 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-pulse { 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); } + .badge-heat { + background: var(--color-heat); + color: #fff; + } + .badge-pulse { + 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 */ - .badge-hot { background: var(--color-heat); color: #fff; } - .badge-volt { background: var(--color-lime); color: var(--color-void); } - .badge-ice { background: var(--color-frost); color: var(--color-void); } + .badge-hot { + background: var(--color-heat); + color: #fff; + } + .badge-volt { + background: var(--color-lime); + color: var(--color-void); + } + .badge-ice { + background: var(--color-frost); + color: var(--color-void); + } .badge-gradient { background: var(--color-heat); @@ -214,13 +278,13 @@ clip-path: polygon(10px 0, 100% 0, calc(100% - 10px) 100%, 0 100%); transition: box-shadow 0.25s var(--ease-sharp), - transform 0.2s var(--ease-bounce); + transform 0.2s var(--ease-bounce); cursor: pointer; } /* shimmer sweep */ .btn::before { - content: ''; + content: ""; position: absolute; inset: 0; background: linear-gradient( @@ -236,11 +300,16 @@ .btn:hover { transform: translateY(-2px); - box-shadow: 0 8px 32px rgba(255, 26, 140, 0.5), - 0 2px 8px rgba(155, 0, 255, 0.2); + box-shadow: + 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 { background: transparent; @@ -248,7 +317,9 @@ color: var(--color-heat); clip-path: none; } - .btn-outline::before { display: none; } + .btn-outline::before { + display: none; + } .btn-outline:hover { background: var(--color-heat); color: #fff; @@ -269,7 +340,9 @@ color: var(--color-chalk); clip-path: none; } - .btn-ghost::before { display: none; } + .btn-ghost::before { + display: none; + } .btn-ghost:hover { border-color: var(--color-heat); color: var(--color-heat); @@ -301,13 +374,13 @@ overflow: hidden; transition: border-color 0.2s var(--ease-sharp), - box-shadow 0.3s var(--ease-out-expo), - transform 0.25s var(--ease-out-expo); + box-shadow 0.3s var(--ease-out-expo), + transform 0.25s var(--ease-out-expo); } /* gradient top bar */ .card-comic::after { - content: ''; + content: ""; position: absolute; top: 0; left: 0; @@ -325,25 +398,30 @@ box-shadow: 0 0 0 1.5px rgba(255, 26, 140, 0.4), 0 20px 60px rgba(255, 26, 140, 0.18), - 0 8px 24px rgba(155, 0, 255, 0.12), - 6px 6px 0 rgba(255, 26, 140, 0.22); + 0 8px 24px rgba(155, 0, 255, 0.12), + 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° Creates an infinite isometric floor-tile illusion. Colors: heat (horizontal) · frost (60°) · pulse (-60°) ────────────────────────────────────────────────────────────── */ .speed-lines { - background-image: - repeating-linear-gradient( - -55deg, - rgba(255, 26, 140, 0.14) 0, rgba(255, 26, 140, 0.14) 1px, - transparent 1px, transparent 22px, - rgba(0, 200, 255, 0.08) 22px, rgba(0, 200, 255, 0.08) 23px, - transparent 23px, transparent 44px - ); + background-image: repeating-linear-gradient( + -55deg, + rgba(255, 26, 140, 0.14) 0, + rgba(255, 26, 140, 0.14) 1px, + transparent 1px, + transparent 22px, + rgba(0, 200, 255, 0.08) 22px, + rgba(0, 200, 255, 0.08) 23px, + transparent 23px, + transparent 44px + ); } /* ── Diamond crosshatch ──────────────────────────────────── */ @@ -351,13 +429,17 @@ background-image: repeating-linear-gradient( 45deg, - rgba(255, 26, 140, 0.07) 0, rgba(255, 26, 140, 0.07) 1px, - transparent 1px, transparent 24px + rgba(255, 26, 140, 0.07) 0, + rgba(255, 26, 140, 0.07) 1px, + transparent 1px, + transparent 24px ), repeating-linear-gradient( -45deg, - rgba(0, 200, 255, 0.05) 0, rgba(0, 200, 255, 0.05) 1px, - transparent 1px, transparent 24px + rgba(0, 200, 255, 0.05) 0, + rgba(0, 200, 255, 0.05) 1px, + transparent 1px, + transparent 24px ); } @@ -365,9 +447,13 @@ .spray-bg { background-image: radial-gradient(circle, rgba(255, 26, 140, 0.09) 1px, transparent 1px), - radial-gradient(circle, rgba(0, 200, 255, 0.06) 1px, transparent 1px); - background-size: 18px 18px, 29px 29px; - background-position: 0 0, 9px 9px; + radial-gradient(circle, rgba(0, 200, 255, 0.06) 1px, transparent 1px); + background-size: + 18px 18px, + 29px 29px; + background-position: + 0 0, + 9px 9px; } /* ── Noise overlay ──────────────────────────────────────────── */ @@ -399,10 +485,15 @@ white-space: nowrap; animation: marquee-scroll 32s linear infinite; } - .marquee-track:hover { animation-play-state: paused; } + .marquee-track:hover { + animation-play-state: paused; + } /* ── 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 { border: none; @@ -419,9 +510,21 @@ } /* ── 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-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); } + .neon-heat { + box-shadow: + 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 { @@ -432,15 +535,25 @@ 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 em { font-style: italic; color: var(--color-paper); } + .prose-editorial strong { + color: var(--color-paper); + font-weight: 600; + } + .prose-editorial em { + font-style: italic; + color: var(--color-paper); + } .prose-editorial a { color: var(--color-heat); 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 { color: var(--color-frost); @@ -457,7 +570,9 @@ letter-spacing: 0.01em; line-height: 1.1; } - .prose-editorial blockquote p { margin: 0; } + .prose-editorial blockquote p { + margin: 0; + } .prose-editorial h2 { font-size: 2.5rem; @@ -509,7 +624,9 @@ background: linear-gradient(90deg, var(--color-heat), var(--color-pulse), var(--color-frost)); box-shadow: 0 0 12px rgba(255, 26, 140, 0.6); 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; opacity: 0; } @@ -517,62 +634,128 @@ /* ── Utilities ────────────────────────────────────────────────── */ @layer utilities { - .gutter-x { - padding-left: clamp(1rem, 4vw, 3rem); + padding-left: clamp(1rem, 4vw, 3rem); padding-right: clamp(1rem, 4vw, 3rem); } /* Aspect ratios */ - .aspect-editorial { aspect-ratio: 3 / 4; } - .aspect-cinema { aspect-ratio: 21 / 9; } - .aspect-portrait { aspect-ratio: 2 / 3; } + .aspect-editorial { + aspect-ratio: 3 / 4; + } + .aspect-cinema { + aspect-ratio: 21 / 9; + } + .aspect-portrait { + aspect-ratio: 2 / 3; + } /* Text wrapping */ - .text-balance { text-wrap: balance; } - .text-pretty { text-wrap: pretty; } + .text-balance { + text-wrap: balance; + } + .text-pretty { + text-wrap: pretty; + } /* Offset shadow */ - .shadow-comic { box-shadow: 5px 5px 0 var(--color-heat); } - .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); } + .shadow-comic { + box-shadow: 5px 5px 0 var(--color-heat); + } + .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-gold { -webkit-text-stroke: 1.5px var(--color-heat); 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; } + .text-stroke-gold { + -webkit-text-stroke: 1.5px var(--color-heat); + 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-width: none; -ms-overflow-style: none; } - .scrollbar-hide::-webkit-scrollbar { display: none; } + .scrollbar-hide { + scrollbar-width: none; + -ms-overflow-style: none; + } + .scrollbar-hide::-webkit-scrollbar { + display: none; + } } /* ── Keyframes ────────────────────────────────────────────────── */ @keyframes gradient-shift { - 0% { background-position: 0% 50%; } - 50% { background-position: 100% 50%; } - 100% { background-position: 0% 50%; } + 0% { + background-position: 0% 50%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0% 50%; + } } @keyframes marquee-scroll { - to { transform: translateX(-50%); } + to { + transform: translateX(-50%); + } } @keyframes scroll-line { - 0% { transform: translateY(-100%); opacity: 0; } - 20% { opacity: 1; } - 80% { opacity: 1; } - 100% { transform: translateY(100%); opacity: 0; } + 0% { + transform: translateY(-100%); + opacity: 0; + } + 20% { + opacity: 1; + } + 80% { + opacity: 1; + } + 100% { + transform: translateY(100%); + opacity: 0; + } } /* ── Logo glitch animation ───────────────────────────────────── */ @keyframes glitch-clip { - 0%, 88%, 100% { 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; } + 0%, + 88%, + 100% { + 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 { @@ -591,15 +774,24 @@ footer .logo-img { } @keyframes logo-float { - 0%, 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)); } + 0%, + 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 ─────────────────────────── */ /* Desktop nav links — lift + glow on hover */ 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 { transform: translateY(-1px); @@ -612,7 +804,9 @@ header nav a.label span { /* Footer links — subtle lift */ 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 { transform: translateY(-1px); @@ -636,10 +830,15 @@ footer nav a.label:hover svg { } @keyframes page-out { - to { opacity: 0; transform: translateY(-10px); } + to { + opacity: 0; + transform: translateY(-10px); + } } @keyframes page-in { - from { opacity: 0; transform: translateY(14px); } + from { + opacity: 0; + transform: translateY(14px); + } } - diff --git a/assets/js/main.js b/assets/js/main.js index 5c10af4..3f34876 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -17,7 +17,9 @@ bar.style.width = "100%"; setTimeout(() => { bar.style.opacity = "0"; - setTimeout(() => { bar.style.width = "0"; }, 350); + setTimeout(() => { + bar.style.width = "0"; + }, 350); }, 150); }); })(); @@ -37,9 +39,11 @@ function initLazyVideos(root) { 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(); @@ -67,7 +71,9 @@ document.body.addEventListener("htmx:historyRestore", () => { bar.style.width = "100%"; setTimeout(() => { bar.style.opacity = "0"; - setTimeout(() => { bar.style.width = "0"; }, 350); + setTimeout(() => { + bar.style.width = "0"; + }, 350); }, 150); } @@ -81,4 +87,3 @@ document.body.addEventListener("htmx:historyRestore", () => { window.scrollTo({ top: 0, behavior: "instant" }); window.dispatchEvent(new Event("scroll")); }); - diff --git a/content/about/index.md b/content/about/index.md index 60391f1..75fcc89 100644 --- a/content/about/index.md +++ b/content/about/index.md @@ -3,7 +3,7 @@ title: "About Pivoine" 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. @@ -13,7 +13,7 @@ The name comes from the French word for **peony** — a flower that is both extr ## 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. diff --git a/content/authors/valknar/index.md b/content/authors/valknar/index.md index ec74561..e8f98b0 100644 --- a/content/authors/valknar/index.md +++ b/content/authors/valknar/index.md @@ -1,10 +1,10 @@ --- title: "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." +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." social: 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. diff --git a/content/imprint/index.md b/content/imprint/index.md index a5dcdf7..106d9b6 100644 --- a/content/imprint/index.md +++ b/content/imprint/index.md @@ -10,7 +10,7 @@ description: "Legal information and editorial responsibility." ## 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 diff --git a/content/posts/2026-05-07-the-pale-pour/index.md b/content/posts/2026-05-07-the-pale-pour/index.md index f733c4f..27861c5 100644 --- a/content/posts/2026-05-07-the-pale-pour/index.md +++ b/content/posts/2026-05-07-the-pale-pour/index.md @@ -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." -date: 2026-05-07 -author: "valknar" -featured: true +date: 2026-05-07 +author: "valknar" +featured: true categories: - Dark - Surrealist @@ -17,7 +17,7 @@ tags: - Macabre slug: the-pale-pour 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." 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." diff --git a/content/posts/2026-05-08-the-counts-chamber/index.md b/content/posts/2026-05-08-the-counts-chamber/index.md index 2bb31f2..88f1653 100644 --- a/content/posts/2026-05-08-the-counts-chamber/index.md +++ b/content/posts/2026-05-08-the-counts-chamber/index.md @@ -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." -date: 2026-05-08 -author: "valknar" -featured: false +date: 2026-05-08 +author: "valknar" +featured: false categories: - Dark - Gothic diff --git a/content/posts/2026-05-08-the-warlords-hour/index.md b/content/posts/2026-05-08-the-warlords-hour/index.md index e8aa587..f4c0154 100644 --- a/content/posts/2026-05-08-the-warlords-hour/index.md +++ b/content/posts/2026-05-08-the-warlords-hour/index.md @@ -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." -date: 2026-05-08 -author: "valknar" -featured: false +date: 2026-05-08 +author: "valknar" +featured: false categories: - Historical - Dark diff --git a/hugo.toml b/hugo.toml index 779b1f0..1f3908f 100644 --- a/hugo.toml +++ b/hugo.toml @@ -1,69 +1,69 @@ -baseURL = "https://pivoine.art/" +baseURL = "https://pivoine.art/" languageCode = "en-us" -title = "Pivoine" -copyright = "© 2026 Pivoine Editorial" +title = "Pivoine" +copyright = "© 2026 Pivoine Editorial" enableRobotsTXT = true [pagination] - pagerSize = 12 +pagerSize = 12 [sitemap] - changefreq = "weekly" - priority = 0.5 - filename = "sitemap.xml" +changefreq = "weekly" +priority = 0.5 +filename = "sitemap.xml" [params] - description = "An editorial magazine for AI-generated art and generative aesthetics." - tagline = "Where the machine dreams." - author = "Pivoine Editorial" - ogImage = "/images/og-default.jpg" - logoText = "PIVOINE" - copyrightYear = "2026" - twitterHandle = "valknar100" - umamiSrc = "https://umami.pivoine.art/script.js" - umamiId = "9190b814-0480-498a-b5fe-1fe1dc162766" +description = "An editorial magazine for AI-generated art and generative aesthetics." +tagline = "Where the machine dreams." +author = "Pivoine Editorial" +ogImage = "/images/og-default.jpg" +logoText = "PIVOINE" +copyrightYear = "2026" +twitterHandle = "valknar100" +umamiSrc = "https://umami.pivoine.art/script.js" +umamiId = "9190b814-0480-498a-b5fe-1fe1dc162766" [params.social] - instagram = "https://instagram.com/valknarix" - x = "https://x.com/valknar100" +instagram = "https://instagram.com/valknarix" +x = "https://x.com/valknar100" [taxonomies] - category = "categories" - tag = "tags" +category = "categories" +tag = "tags" [[menus.main]] - name = "Posts" - url = "/posts/" - weight = 1 +name = "Posts" +url = "/posts/" +weight = 1 [[menus.main]] - name = "Authors" - url = "/authors/" - weight = 2 +name = "Authors" +url = "/authors/" +weight = 2 [[menus.main]] - name = "Categories" - url = "/categories/" - weight = 3 +name = "Categories" +url = "/categories/" +weight = 3 [[menus.main]] - name = "About" - url = "/about/" - weight = 4 +name = "About" +url = "/about/" +weight = 4 [[menus.footer]] - name = "About" - url = "/about/" - weight = 1 +name = "About" +url = "/about/" +weight = 1 [[menus.footer]] - name = "Imprint" - url = "/imprint/" - weight = 2 +name = "Imprint" +url = "/imprint/" +weight = 2 [markup.goldmark.renderer] - unsafe = true +unsafe = true [markup.highlight] - style = "dracula" - noClasses = true +style = "dracula" +noClasses = true [build] - writeStats = true +writeStats = true diff --git a/layouts/404.html b/layouts/404.html index 93e7639..c465d6c 100644 --- a/layouts/404.html +++ b/layouts/404.html @@ -1,65 +1,71 @@ {{- define "main" -}} -
+
+ +
+
- -
-
- - -
+ +
+ + +

+ This drop got pulled. The page you're looking for doesn't exist, was moved, or got lost in the grid. +

+ + +
+ Back to the Drop {{ partial "icon.html" "arrow-right" }} + Browse all posts {{ partial "icon.html" "arrow-right" }} +
+ + + + +
{{- end -}} diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html index 3ca3683..3e790f7 100644 --- a/layouts/_default/baseof.html +++ b/layouts/_default/baseof.html @@ -1,33 +1,34 @@ - - {{- partial "head.html" . -}} - - + + {{- partial "head.html" . -}} + + + + - - + {{- partial "nav.html" . -}} - {{- partial "nav.html" . -}} + {{- block "page-background" . -}}{{- end -}} - {{- block "page-background" . -}}{{- end -}} -
- {{- block "main" . }}{{- end }} -
+
+ {{- block "main" . }}{{- end }} +
- {{- partial "footer.html" . -}} + {{- partial "footer.html" . -}} - -
-
@@ -22,17 +22,23 @@
@@ -73,51 +83,70 @@
- + -
+

{{ .Site.Params.tagline }}

@@ -125,8 +154,14 @@ diff --git a/layouts/partials/pagination.html b/layouts/partials/pagination.html index 5cb505f..96d77ea 100644 --- a/layouts/partials/pagination.html +++ b/layouts/partials/pagination.html @@ -1,33 +1,40 @@ {{- /* Custom pagination component. - Call as: {{ partial "pagination.html" . }} + Call as: {{ partial "pagination.html" . +}} */ -}} {{- $paginator := .Paginator -}} {{- if gt $paginator.TotalPages 1 -}} - {{- end -}} diff --git a/layouts/partials/post-card-large.html b/layouts/partials/post-card-large.html index 1f6e8f8..26c841a 100644 --- a/layouts/partials/post-card-large.html +++ b/layouts/partials/post-card-large.html @@ -1,50 +1,56 @@ {{- /* Large overlay card for featured/secondary slots. - Expects a post page as context (.). -*/ -}} + Expects a post page as context (.). + */ +-}} {{- $post := . -}}
- {{- $thumb := $post.Resources.GetMatch "banner.png" -}} {{- if not $thumb -}}{{- $thumb = $post.Resources.GetMatch "01.png" -}}{{- end -}}
{{- if $thumb -}} {{- partial "img.html" (dict "res" $thumb "widths" (slice 800 1200) "sizes" "(max-width: 768px) 100vw, 50vw" "class" "w-full h-full object-cover" "alt" $post.Title) -}} - {{- else -}}{{- with $post.Params.banner -}} - {{- partial "media.html" (dict "media" . "class" "w-full h-full object-cover") -}} {{- else -}} -
- PIVOINE -
- {{- end -}}{{- end -}} + {{- with $post.Params.banner -}} + {{- partial "media.html" (dict "media" . "class" "w-full h-full object-cover") -}} + {{- else -}} +
+ PIVOINE +
+ {{- end -}} + {{- end -}}
-
+
{{- with $post.Params.categories -}} -
- {{- range first 1 . -}} - {{ . }} - {{- end -}} -
+
+ {{- range first 1 . -}} + {{ . }} + {{- end -}} +
{{- end -}} -

+

{{- $post.Title -}}

{{- with $post.Params.author -}} {{- $authorPage := site.GetPage (printf "authors/%s" .) -}} {{- with $authorPage -}} - {{ .Params.name | default .Title }} - + {{ .Params.name | default .Title }} + {{- end -}} {{- end -}}
-
diff --git a/layouts/partials/post-card.html b/layouts/partials/post-card.html index c1fc03f..c5d6f9a 100644 --- a/layouts/partials/post-card.html +++ b/layouts/partials/post-card.html @@ -1,36 +1,41 @@ {{- /* Compact post card for grids. - Expects a post page as context (.). -*/ -}} + Expects a post page as context (.). + */ +-}} {{- $post := . -}}
- {{- $thumb := $post.Resources.GetMatch "banner.png" -}} {{- if not $thumb -}}{{- $thumb = $post.Resources.GetMatch "01.png" -}}{{- end -}}
{{- if $thumb -}} {{- partial "img.html" (dict "res" $thumb "widths" (slice 600 1000) "sizes" "(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 25vw" "class" "w-full h-full object-cover" "alt" $post.Title) -}} - {{- else -}}{{- with $post.Params.banner -}} - {{- partial "media.html" (dict "media" . "class" "w-full h-full object-cover") -}} {{- else -}} -
- PIVOINE -
- {{- end -}}{{- end -}} + {{- with $post.Params.banner -}} + {{- partial "media.html" (dict "media" . "class" "w-full h-full object-cover") -}} + {{- else -}} +
+ PIVOINE +
+ {{- end -}} + {{- end -}}
{{- with $post.Params.categories -}} -
- {{- range first 1 . -}} - {{ . }} - {{- end -}} -
+
+ {{- range first 1 . -}} + {{ . }} + {{- end -}} +
{{- end -}} + -

+

{{- $post.Title -}}

@@ -42,10 +47,26 @@ {{- $avRes := .Resources.GetMatch "avatar.*" -}} {{- if $avRes -}} {{- $av := $avRes.Resize "64x webp" -}} - {{ $authorPage.Params.name | default $authorPage.Title }} - {{- else -}}{{- with .Params.avatar -}} - {{ $authorPage.Params.name | default $authorPage.Title }} - {{- end -}}{{- end -}} + {{ $authorPage.Params.name | default $authorPage.Title }} + {{- else -}} + {{- with .Params.avatar -}} + {{ $authorPage.Params.name | default $authorPage.Title }} + {{- end -}} + {{- end -}} {{ .Params.name | default .Title }} {{- end -}} @@ -54,6 +75,5 @@ {{- $post.Date.Format "Jan 2006" -}}
- diff --git a/layouts/partials/schema.html b/layouts/partials/schema.html index 9858677..ef0faaf 100644 --- a/layouts/partials/schema.html +++ b/layouts/partials/schema.html @@ -20,10 +20,10 @@ } {{- else if and .IsPage (eq .Section "posts") -}} -{{- $authorPage := "" -}} -{{- with .Params.author -}} - {{- $authorPage = site.GetPage (printf "authors/%s" .) -}} -{{- end -}} + {{- $authorPage := "" -}} + {{- with .Params.author -}} + {{- $authorPage = site.GetPage (printf "authors/%s" .) -}} + {{- end -}}