Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions .claude/skills/logo/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ neon hero; otherwise keep text to a minimum.
An app-icon-style **glossy dark-glass badge** holding a **neon-green hero
glyph** with a soft neon glow, the repo name set beneath. Modern / techy, dark
neon aesthetic, suitable as an app icon / favicon. The dark-glass badge is used
in *both* variants — only the surrounding canvas, the badge's depth treatment,
and the title color change between light and dark.
in *both* variants — the canvas is transparent in both, so only the title
color (and the dark variant's title glow) changes between light and dark.

## What stays the same vs. what changes

Expand Down Expand Up @@ -55,8 +55,6 @@ minimal-hue philosophy.
| Neon bright core | `190, 250, 213` | `#befdd5` | inner glow core |
| Deep green | `21, 128, 61` | `#15803d` | light-mode title (contrast on white) |
| Glass top → bottom | `34,37,46` → `9,10,13` | `#22252e` → `#090a0d` | badge body gradient |
| Dark canvas top → bottom | `12,13,16` → `6,6,8` | `#0c0d10` → `#060608` | dark variant background |
| Light canvas top → bottom | `251,251,253` → `231,232,236` | `#fbfbfd` → `#e7e8ec` | light variant background |

### Geometry (at 1x; render at 2x supersample, then downscale with LANCZOS)

Expand Down Expand Up @@ -92,14 +90,14 @@ any hero shape picks up the same glow.

| Element | Dark variant | Light variant |
|---------|--------------|---------------|
| Canvas | dark gradient + soft radial green pool | light gradient |
| Badge depth | neon green halo behind badge | soft offset drop shadow |
| Canvas | transparent | transparent |
| Badge & hero | dark glass + neon glyph | **identical** |
| Title | `#86efac` with soft glow | `#15803d`, no glow |

Rationale: the neon halo and glowing title disappear on white, so the light
variant swaps them for a drop shadow and a deeper green that holds contrast;
the badge itself never changes.
Rationale: the badge is a clean cutout on a transparent canvas, so it sits on
whatever page color is behind it. The glowing neon title vanishes on white, so
the light variant swaps it for a deeper green that holds contrast; the badge
itself never changes.

## How to build

Expand Down
47 changes: 9 additions & 38 deletions .claude/skills/logo/make_logo.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,6 @@ def draw_hero(md, box, neon):
W, H = 1590 * SS, 1098 * SS

# palette
BG_TOP, BG_BOT = (12, 13, 16), (6, 6, 8) # dark canvas gradient
LIGHT_TOP, LIGHT_BOT = (251, 251, 253), (231, 232, 236) # light canvas gradient
GLASS_TOP, GLASS_BOT = (34, 37, 46), (9, 10, 13) # dark-glass badge gradient
NEON = (134, 239, 172) # #86efac signature neon green (hero + dark title)
NEON_BRIGHT = (190, 250, 213) # lighter core that sells the glow
Expand Down Expand Up @@ -130,44 +128,17 @@ def vgrad(top, bot):

def render(theme):
"""Render one variant; ``theme`` is ``'light'`` or ``'dark'``."""
# --- canvas ---
if theme == "light":
img = vgrad(LIGHT_TOP, LIGHT_BOT).convert("RGBA")
else:
img = vgrad(BG_TOP, BG_BOT).convert("RGBA")
lift_mask = Image.new("L", (W, H), 0) # soft radial pool of light
ImageDraw.Draw(lift_mask).ellipse(
[
W // 2 - 520 * SS,
int(H * 0.42) - 380 * SS,
W // 2 + 520 * SS,
int(H * 0.42) + 380 * SS,
],
fill=70,
)
lift_mask = lift_mask.filter(ImageFilter.GaussianBlur(220 * SS))
img.paste(Image.new("RGBA", (W, H), (26, 40, 32, 255)), (0, 0), lift_mask)

# --- transparent canvas: the badge is a clean cutout with no
# backdrop, so the README shows it over whatever page color sits
# behind it. Only the title color (and the dark variant's title
# glow) changes per theme. ---
img = Image.new("RGBA", (W, H), (0, 0, 0, 0))
draw = ImageDraw.Draw(img)

# The badge uses the FIXED module-level geometry (BADGE_BOX) in every
# variant, so the central glass rectangle is the exact same size and
# position regardless of theme, hero, or title.

# --- depth behind the badge: shadow (light) or neon halo (dark) ---
if theme == "light":
shadow = Image.new("RGBA", (W, H), (0, 0, 0, 0))
ImageDraw.Draw(shadow).rounded_rectangle(
[BADGE_X0, BADGE_Y0 + 16 * SS, BADGE_X1, BADGE_Y1 + 16 * SS],
BADGE_RADIUS,
fill=(20, 24, 30, 90),
)
img.alpha_composite(shadow.filter(ImageFilter.GaussianBlur(46 * SS)))
else:
halo = Image.new("RGBA", (W, H), (0, 0, 0, 0))
ImageDraw.Draw(halo).rounded_rectangle(BADGE_BOX, BADGE_RADIUS, fill=(*NEON, 90))
img.alpha_composite(halo.filter(ImageFilter.GaussianBlur(55 * SS)))

# --- glass body (dark in BOTH themes) ---
mask = Image.new("L", (W, H), 0)
ImageDraw.Draw(mask).rounded_rectangle(BADGE_BOX, BADGE_RADIUS, fill=255)
Expand All @@ -181,9 +152,9 @@ def render(theme):
fill=(255, 255, 255, 26),
)
gloss = gloss.filter(ImageFilter.GaussianBlur(26 * SS))
img.paste(
gloss, (0, 0), Image.composite(gloss.getchannel("A"), Image.new("L", (W, H), 0), mask)
)
# clip the sheen to the badge, then composite so the glass stays opaque
gloss.putalpha(Image.composite(gloss.getchannel("A"), Image.new("L", (W, H), 0), mask))
img.alpha_composite(gloss)

# --- neon hairline border ---
draw.rounded_rectangle(BADGE_BOX, BADGE_RADIUS, outline=(*NEON, 70), width=2 * SS)
Expand Down Expand Up @@ -216,7 +187,7 @@ def render(theme):
img.alpha_composite(glow.filter(ImageFilter.GaussianBlur(14 * SS)))
draw.text((tx, ty), TITLE, font=font, fill=NEON)

out = img.convert("RGB").resize((1590, 1098), Image.LANCZOS)
out = img.resize((1590, 1098), Image.LANCZOS) # keep alpha
path = f"logo-{theme}.png"
out.save(path)
print("saved", path)
Expand Down
Binary file modified logo-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified logo-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading