diff --git a/site/BRAND_ASSETS.md b/site/BRAND_ASSETS.md index db57c9ac..95b5dc10 100644 --- a/site/BRAND_ASSETS.md +++ b/site/BRAND_ASSETS.md @@ -1,15 +1,12 @@ -# ALGAL header identity +# ALGAL website identity -The header preserves the three overlapping circles from `favicon.svg` at its -current 28px size. `algal-mark.svg` removes only the opaque rounded background -rectangle; its view box, circle coordinates, strokes, and group are unchanged. -The name and transparent mark share the released Design Kit metallic foil recipe. -The extracted original artwork remains visible when masks or forced colors -disable the decorative paint. The favicon itself is unchanged. +The favicon silhouette comes from the actual header mark, `algal-mark.svg`. Browser variants render it in pure white on transparency. Apple touch variants use the same white mark on black. The visible bounds are centered horizontally and vertically and fill the square on their longest axis, preserving the aspect ratio with no added padding. -- Original `favicon.svg` SHA-256: `340aad988f525145b7caf7545abf311fa5f52cf46c399f172bc948de437d4a88`. -- Transparent `algal-mark.svg` SHA-256: `c962e23d88fea8c8e4aa10ebadbad97af09d54d65b3ed3d63080eef94396a07b`. +Run `bun run generate:icons` to regenerate the SVG and PNG variants from `algal-mark.svg`. -The stylesheet and browser controller are build-only dependencies; the CLI keeps -its zero required runtime dependency contract. No product copy or page layout -is generated by Design Kit. +| File | Size | SHA-256 | +| --- | --- | --- | +| algal-mark.svg | SVG | `c962e23d88fea8c8e4aa10ebadbad97af09d54d65b3ed3d63080eef94396a07b` | +| favicon.svg | SVG | `75802f85fecb6d76c8507c8374b81875101b6dec4733154f4dadc34c3394b63e` | +| favicon-48.png | 48×48 | `19cf28dfd722aa94260e9d61e9f742336a62d68cfccd5013684368655a5721d0` | +| apple-touch-icon.png | 180×180 | `6b92c290b40a46c2dc8a570fd8d3f710f613ef59d1be85c79daa20148782e533` | diff --git a/site/apple-touch-icon.png b/site/apple-touch-icon.png index c05547d7..b46d01b0 100644 Binary files a/site/apple-touch-icon.png and b/site/apple-touch-icon.png differ diff --git a/site/favicon-48.png b/site/favicon-48.png index 76ced384..22bd6f9a 100644 Binary files a/site/favicon-48.png and b/site/favicon-48.png differ diff --git a/site/favicon.svg b/site/favicon.svg index 0b2af007..4e43b201 100644 --- a/site/favicon.svg +++ b/site/favicon.svg @@ -1 +1 @@ - + diff --git a/site/generate-icons.ts b/site/generate-icons.ts index b4bb23bf..81097e2e 100644 --- a/site/generate-icons.ts +++ b/site/generate-icons.ts @@ -1,15 +1,33 @@ -// Renders the SVG favicon into the PNG sizes that browsers, link unfurlers, -// and iOS home screens request. Run `bun run generate:icons` after editing -// site/favicon.svg and commit the PNGs beside it. +// Browser icons follow the current transparent header mark. Run +// `bun run generate:icons` and commit the SVG and PNG derivatives together. import { readFile, writeFile } from "node:fs/promises"; import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; import { Resvg } from "@resvg/resvg-js"; const siteDirectory = dirname(fileURLToPath(import.meta.url)); -const svg = await readFile(join(siteDirectory, "favicon.svg"), "utf8"); - +const source = await readFile(join(siteDirectory, "algal-mark.svg"), "utf8"); +const white = source.replace(/stroke="[^"]*"/gu, 'stroke="#ffffff"'); +const sample = new Resvg(white, { fitTo: { mode: "width", value: 2048 } }).render(); +const pixels = sample.pixels; +let left = sample.width, top = sample.height, right = -1, bottom = -1; +for (let y = 0; y < sample.height; y++) for (let x = 0; x < sample.width; x++) { + if (pixels[(y * sample.width + x) * 4 + 3]! > 0) { + left = Math.min(left, x); right = Math.max(right, x); + top = Math.min(top, y); bottom = Math.max(bottom, y); + } +} +if (right < left) throw new Error("The header mark is empty"); +const scale = sample.width / 32; +const side = Math.max(right - left + 1, bottom - top + 1) / scale; +const cx = (left + right + 1) / 2 / scale, cy = (top + bottom + 1) / 2 / scale; +const box = [cx - side / 2, cy - side / 2, side, side].join(" "); +const svg = white.replace('viewBox="0 0 32 32"', `viewBox="${box}"`); +await writeFile(join(siteDirectory, "favicon.svg"), svg); for (const [file, size] of [["favicon-48.png", 48], ["apple-touch-icon.png", 180]] as const) { - const png = new Resvg(svg, { fitTo: { mode: "width", value: size } }).render().asPng(); + const png = new Resvg(svg, { + fitTo: { mode: "width", value: size }, + ...(file === "apple-touch-icon.png" ? { background: "#000000" } : {}), + }).render().asPng(); await writeFile(join(siteDirectory, file), png); }