Merge pull request #13 from Patiun/claude/patiun-rebrand-gjoo9f

Light mode GK monogram and stronger background seals
This commit is contained in:
Greg Kilmer
2026-10-18 16:35:20 -04:00
committed by GitHub
16 changed files with 56 additions and 19 deletions
+14 -1
View File
@@ -1,7 +1,8 @@
/** /**
* Writes the light and foil versions of the motif SVGs from the dark originals * Writes the light and foil versions of the motif SVGs from the dark originals
* in src/assets/motifs, using the inks Greg picked on the light motif board * in src/assets/motifs, using the inks Greg picked on the light motif board
* (2026-10-18). Run after a motif changes: node packages/ui/scripts/light-motifs.mjs * (2026-10-18), and the light GK monogram in src/assets/brand/light. Run after
* a motif or the monogram changes: node packages/ui/scripts/light-motifs.mjs
* *
* light/ deep gold line: the dark inks swapped for Starlight-page inks, glow removed * light/ deep gold line: the dark inks swapped for Starlight-page inks, glow removed
* foil/ the dark seal with its gold as foil, glow kept * foil/ the dark seal with its gold as foil, glow kept
@@ -63,3 +64,15 @@ for (const f of files) {
} }
} }
console.log(`${files.length} motifs written`); console.log(`${files.length} motifs written`);
// The GK monogram on Starlight: a pale disc, deep gold rings and ink letters.
const MONOGRAM = {
...LIGHT,
"#131C2B": "#FFFFFF",
"#1F3B49": "#ECE6D8",
"#15232F": "#FBF9F4",
};
const brand = join(dir, "../brand");
mkdirSync(join(brand, "light"), { recursive: true });
writeFileSync(join(brand, "light", "gk-monogram.svg"), recolor(readFileSync(join(brand, "gk-monogram.svg"), "utf8"), MONOGRAM));
console.log("monogram written");
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.6 KiB

+2 -2
View File
@@ -39,7 +39,7 @@ const other = second === false ? null : (second ?? first);
top: 760px; top: 760px;
width: 620px; width: 620px;
height: 620px; height: 620px;
opacity: 0.07; opacity: calc(0.07 * var(--gk-ghost));
transform: rotate(-10deg); transform: rotate(-10deg);
} }
.right { .right {
@@ -47,7 +47,7 @@ const other = second === false ? null : (second ?? first);
top: 64%; top: 64%;
width: 560px; width: 560px;
height: 560px; height: 560px;
opacity: 0.06; opacity: calc(0.06 * var(--gk-ghost));
transform: rotate(8deg); transform: rotate(8deg);
} }
@media (max-width: 640px) { @media (max-width: 640px) {
+8 -1
View File
@@ -2,12 +2,13 @@
/** The site footer: the header divider again, then the monogram line and links. */ /** The site footer: the header divider again, then the monogram line and links. */
import monogram from "../assets/brand/gk-monogram.svg?url"; import monogram from "../assets/brand/gk-monogram.svg?url";
import Divider from "./Divider.astro"; import Divider from "./Divider.astro";
import Motif from "./Motif.astro";
const year = new Date().getFullYear(); const year = new Date().getFullYear();
--- ---
<footer class="gk-site-footer"> <footer class="gk-site-footer">
<div class="gk-wrap"><Divider seed="footer" /></div> <div class="gk-wrap"><Divider seed="footer" /></div>
<div class="gk-wrap row"> <div class="gk-wrap row">
<span class="mark"><img src={monogram} alt="" width="40" height="40" />© {year} Greg Kilmer · Web Development · a Patiun LLC company</span> <span class="mark"><Motif src={monogram} alt="" width="40" height="40" />© {year} Greg Kilmer · Web Development · a Patiun LLC company</span>
<span class="links"> <span class="links">
<a href="/inquiries" class="gk-text strong">Start an inquiry</a> <a href="/inquiries" class="gk-text strong">Start an inquiry</a>
<a href="/about" class="gk-text gk-quiet">About</a> <a href="/about" class="gk-text gk-quiet">About</a>
@@ -37,6 +38,12 @@ const year = new Date().getFullYear();
align-items: center; align-items: center;
gap: 12px; gap: 12px;
} }
.mark :global(img) {
border-radius: 50%;
}
:global(:root[data-theme="light"]) .mark :global(img) {
box-shadow: 0 1px 3px rgba(19, 28, 43, 0.14);
}
.links { .links {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
+7 -3
View File
@@ -38,7 +38,7 @@ const decs = [60, 30, 0, -30].map((d, i) => ({ at: (i / 4) * 100, label: `${d >
store ? ( store ? (
<nav aria-label="Store" class="nav"> <nav aria-label="Store" class="nav">
<a href="/store" class="brand" aria-current={store.current === "/store" ? "page" : undefined}> <a href="/store" class="brand" aria-current={store.current === "/store" ? "page" : undefined}>
<img src={monogram} alt="" width="72" height="72" class="mono" /> <Motif src={monogram} alt="" width="72" height="72" class="mono" loading="eager" />
<span class="words"> <span class="words">
<span class="name store-name">Store.GregKilmer.com</span> <span class="name store-name">Store.GregKilmer.com</span>
<span class="store-tag">a Patiun LLC workshop</span> <span class="store-tag">a Patiun LLC workshop</span>
@@ -54,7 +54,7 @@ const decs = [60, 30, 0, -30].map((d, i) => ({ at: (i / 4) * 100, label: `${d >
) : ( ) : (
<nav aria-label="Primary" class="nav"> <nav aria-label="Primary" class="nav">
<a href="/" class="brand" aria-current={aria("home")}> <a href="/" class="brand" aria-current={aria("home")}>
<img src={monogram} alt="" width="72" height="72" class="mono" /> <Motif src={monogram} alt="" width="72" height="72" class="mono" loading="eager" />
<span class="words"> <span class="words">
<span class="name">GREG KILMER</span> <span class="name">GREG KILMER</span>
<span class="tag">DEVELOPER<Star size={8} tone="teal" />MAKER<Star size={8} tone="teal" />STORYTELLER</span> <span class="tag">DEVELOPER<Star size={8} tone="teal" />MAKER<Star size={8} tone="teal" />STORYTELLER</span>
@@ -132,7 +132,7 @@ const decs = [60, 30, 0, -30].map((d, i) => ({ at: (i / 4) * 100, label: `${d >
top: -40px; top: -40px;
width: 900px; width: 900px;
max-width: none; max-width: none;
opacity: 0.22; opacity: calc(0.22 * var(--gk-ghost));
} }
.nav { .nav {
max-width: var(--gk-page-max); max-width: var(--gk-page-max);
@@ -160,6 +160,10 @@ const decs = [60, 30, 0, -30].map((d, i) => ({ at: (i / 4) * 100, label: `${d >
border-radius: 50%; border-radius: 50%;
transition: filter 0.25s ease; transition: filter 0.25s ease;
} }
/* On Starlight the pale disc needs a soft edge to sit apart from the page. */
:global(:root[data-theme="light"]) .mono {
box-shadow: 0 1px 4px rgba(19, 28, 43, 0.14);
}
.brand:hover .mono, .brand:hover .mono,
.brand:focus-visible .mono { .brand:focus-visible .mono {
filter: drop-shadow(0 0 6px rgba(var(--gk-gold-bright-rgb), 0.7)) drop-shadow(0 0 16px rgba(var(--gk-teal-rgb), 0.45)); filter: drop-shadow(0 0 6px rgba(var(--gk-gold-bright-rgb), 0.7)) drop-shadow(0 0 16px rgba(var(--gk-teal-rgb), 0.45));
+9 -3
View File
@@ -46,10 +46,16 @@ export type SealName = keyof typeof seals;
export { filamentBanner }; export { filamentBanner };
// Light mode and foil versions, written by scripts/light-motifs.mjs. // Light mode and foil versions (and the light monogram), written by scripts/light-motifs.mjs.
const byFile = (m: Record<string, string>) => Object.fromEntries(Object.entries(m).map(([p, u]) => [p.slice(p.lastIndexOf("/") + 1), u])); const byFile = (m: Record<string, string>) => Object.fromEntries(Object.entries(m).map(([p, u]) => [p.slice(p.lastIndexOf("/") + 1), u]));
const darkFiles = byFile(import.meta.glob<string>("../assets/motifs/*.svg", { query: "?url", import: "default", eager: true })); const darkFiles = byFile({
const lightFiles = byFile(import.meta.glob<string>("../assets/motifs/light/*.svg", { query: "?url", import: "default", eager: true })); ...import.meta.glob<string>("../assets/motifs/*.svg", { query: "?url", import: "default", eager: true }),
...import.meta.glob<string>("../assets/brand/gk-monogram.svg", { query: "?url", import: "default", eager: true }),
});
const lightFiles = byFile({
...import.meta.glob<string>("../assets/motifs/light/*.svg", { query: "?url", import: "default", eager: true }),
...import.meta.glob<string>("../assets/brand/light/*.svg", { query: "?url", import: "default", eager: true }),
});
const foilFiles = byFile(import.meta.glob<string>("../assets/motifs/foil/*.svg", { query: "?url", import: "default", eager: true })); const foilFiles = byFile(import.meta.glob<string>("../assets/motifs/foil/*.svg", { query: "?url", import: "default", eager: true }));
const foilLightFiles = byFile(import.meta.glob<string>("../assets/motifs/foil-light/*.svg", { query: "?url", import: "default", eager: true })); const foilLightFiles = byFile(import.meta.glob<string>("../assets/motifs/foil-light/*.svg", { query: "?url", import: "default", eager: true }));
const fileOf = Object.fromEntries(Object.entries(darkFiles).map(([f, u]) => [u, f])); const fileOf = Object.fromEntries(Object.entries(darkFiles).map(([f, u]) => [u, f]));
+3
View File
@@ -48,6 +48,8 @@
--gk-wash: 1; --gk-wash: 1;
/* The star chart grid behind the page; off in dark, faint ink lines in light. */ /* The star chart grid behind the page; off in dark, faint ink lines in light. */
--gk-chart: none; --gk-chart: none;
/* How strong the faint seals behind pages and panels are; light mode lifts them. */
--gk-ghost: 1;
--gk-filament: linear-gradient(90deg, transparent, var(--gk-gold) 25%, var(--gk-teal-bright) 75%, transparent); --gk-filament: linear-gradient(90deg, transparent, var(--gk-gold) 25%, var(--gk-teal-bright) 75%, transparent);
@@ -111,6 +113,7 @@
--gk-midnight-rgb: 255, 255, 255; --gk-midnight-rgb: 255, 255, 255;
--gk-dust-accent-rgb: 106, 47, 224; --gk-dust-accent-rgb: 106, 47, 224;
--gk-wash: 0.5; --gk-wash: 0.5;
--gk-ghost: 1.6;
--gk-chart: --gk-chart:
repeating-linear-gradient(0deg, rgba(19, 28, 43, 0.032) 0 1px, transparent 1px 44px), repeating-linear-gradient(0deg, rgba(19, 28, 43, 0.032) 0 1px, transparent 1px 44px),
repeating-linear-gradient(90deg, rgba(19, 28, 43, 0.032) 0 1px, transparent 1px 44px); repeating-linear-gradient(90deg, rgba(19, 28, 43, 0.032) 0 1px, transparent 1px 44px);
@@ -105,7 +105,7 @@ const now = nowStatuses(s, post);
position: absolute; position: absolute;
width: 150%; width: 150%;
max-width: none; max-width: none;
opacity: 0.32; opacity: calc(0.32 * var(--gk-ghost));
pointer-events: none; pointer-events: none;
} }
.art :global(.path) { .art :global(.path) {
@@ -4,6 +4,7 @@
* monogram, which also stands in when there is no cover or it fails to load. * monogram, which also stands in when there is no cover or it fails to load.
*/ */
import monogram from "@gk/ui/assets/brand/gk-monogram.svg?url"; import monogram from "@gk/ui/assets/brand/gk-monogram.svg?url";
import Motif from "@gk/ui/components/Motif.astro";
interface Props { interface Props {
src?: string; src?: string;
@@ -16,7 +17,7 @@ const { src, alt = "", width = 176, height = 120, class: className } = Astro.pro
const mark = Math.round(Math.min(width, height) / 2); const mark = Math.round(Math.min(width, height) / 2);
--- ---
<span class:list={["thumb", className]} style={`--w:${width}px;--h:${height}px`}> <span class:list={["thumb", className]} style={`--w:${width}px;--h:${height}px`}>
<img src={monogram} alt="" width={mark} height={mark} class="mono" aria-hidden="true" /> <Motif src={monogram} alt="" width={mark} height={mark} class="mono" aria-hidden="true" />
{src && <img src={src} alt={alt} loading="lazy" decoding="async" class="photo" onerror="this.remove()" />} {src && <img src={src} alt={alt} loading="lazy" decoding="async" class="photo" onerror="this.remove()" />}
</span> </span>
@@ -37,7 +37,7 @@ const { title, seal, as: H = "h2" } = Astro.props;
position: absolute; position: absolute;
right: -26px; right: -26px;
top: -26px; top: -26px;
opacity: 0.14; opacity: calc(0.14 * var(--gk-ghost));
pointer-events: none; pointer-events: none;
} }
.head { .head {
@@ -7,6 +7,7 @@
import monogram from "@gk/ui/assets/brand/gk-monogram.svg?url"; import monogram from "@gk/ui/assets/brand/gk-monogram.svg?url";
import Chip from "@gk/ui/components/Chip.astro"; import Chip from "@gk/ui/components/Chip.astro";
import Icon from "@gk/ui/components/Icon.astro"; import Icon from "@gk/ui/components/Icon.astro";
import Motif from "@gk/ui/components/Motif.astro";
import Star from "@gk/ui/components/Star.astro"; import Star from "@gk/ui/components/Star.astro";
import type { StatusView } from "../../lib/home.ts"; import type { StatusView } from "../../lib/home.ts";
import { formatDate, type SiteIndex } from "../../lib/site.ts"; import { formatDate, type SiteIndex } from "../../lib/site.ts";
@@ -25,7 +26,7 @@ const postHref = post ? s.href(post) : null;
<img src={v.cover} alt="" class="thumb photo" loading="lazy" decoding="async" width="56" height="56" /> <img src={v.cover} alt="" class="thumb photo" loading="lazy" decoding="async" width="56" height="56" />
) : ( ) : (
<span class="thumb tile" aria-hidden="true"> <span class="thumb tile" aria-hidden="true">
<img src={monogram} alt="" width="28" height="28" /> <Motif src={monogram} alt="" width="28" height="28" />
</span> </span>
) )
} }
@@ -92,7 +92,7 @@ const facts = d.facts ?? [];
position: absolute; position: absolute;
right: -60px; right: -60px;
bottom: -80px; bottom: -80px;
opacity: 0.12; opacity: calc(0.12 * var(--gk-ghost));
pointer-events: none; pointer-events: none;
} }
.main { .main {
+1 -1
View File
@@ -227,7 +227,7 @@ const listFormat = new Intl.ListFormat("en", { style: "long", type: "conjunction
position: absolute; position: absolute;
right: -90px; right: -90px;
top: -90px; top: -90px;
opacity: 0.14; opacity: calc(0.14 * var(--gk-ghost));
pointer-events: none; pointer-events: none;
} }
.work > :not(:global(.work-seal), :global(.gk-corner)) { .work > :not(:global(.work-seal), :global(.gk-corner)) {
+1 -1
View File
@@ -209,7 +209,7 @@ const wrapped = s
top: -26px; top: -26px;
width: 104px; width: 104px;
height: 104px; height: 104px;
opacity: 0.14; opacity: calc(0.14 * var(--gk-ghost));
pointer-events: none; pointer-events: none;
} }
.panel-kicker { .panel-kicker {
+1 -1
View File
@@ -402,7 +402,7 @@ const isCore = (group: { core?: string[] }, item: string) => group.core?.some((c
position: absolute; position: absolute;
right: -30px; right: -30px;
top: -30px; top: -30px;
opacity: 0.12; opacity: calc(0.12 * var(--gk-ghost));
pointer-events: none; pointer-events: none;
} }
.panel-head { .panel-head {
+1 -1
View File
@@ -328,7 +328,7 @@ const colorStrips = selling.flatMap((l) =>
position: absolute; position: absolute;
right: -40px; right: -40px;
bottom: -60px; bottom: -60px;
opacity: 0.08; opacity: calc(0.08 * var(--gk-ghost));
pointer-events: none; pointer-events: none;
} }
summary { summary {