docs: thumbnails skill and humanizer skill
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
---
|
||||
name: create-thumbnail
|
||||
description: Generate on-brand ClassroomIO thumbnails (blog posts, changelogs, YouTube videos) as 1920×1080 PNGs. Builds HTML+CSS from the brand token system and renders deterministically via headless Chrome. Use when the user asks to create/make a thumbnail, cover image, or video/blog banner for ClassroomIO.
|
||||
---
|
||||
|
||||
You are producing a **1920×1080 (16:9) ClassroomIO thumbnail** by writing an HTML file that
|
||||
consumes the brand token CSS in this skill, then rendering it to PNG with `render.py`. The
|
||||
output must look designed-in-Figma, not templated. The "Self-Host ClassroomIO with Dokploy"
|
||||
two-tile thumbnail is the **quality bar to match or beat — it is NOT a template to clone.**
|
||||
|
||||
## Vary the composition — do not default to one layout
|
||||
|
||||
The brand system is fixed (colors, font, tiles, pills, gradients). The **composition is not.**
|
||||
Every thumbnail must be a deliberate design choice, not a find-and-replace of the last one.
|
||||
|
||||
- **Pick the pattern from the content**, not from what you made last time (see the catalog below).
|
||||
A release is a hero icon; a guide is editorial; a multi-item feature is a concept map. Only a
|
||||
true "X with/via Y" integration should reach for the two-tile connect.
|
||||
- **When you DO reuse a pattern** (e.g. a series like "self-host with Dokploy / Coolify / Railway"
|
||||
where consistency is the point), still vary within it — the focal treatment, the pill copy, the
|
||||
headline emphasis, the accent/texture. Series consistency is a choice the user should confirm,
|
||||
not your default.
|
||||
- **Actively avoid** shipping three near-identical images in a row. If the last thumbnail you made
|
||||
used a layout, reach for a different one unless the user asked to match a set.
|
||||
- Treat `template-two-tile.html` as **one** starting point among the patterns, not THE template.
|
||||
For other patterns, compose fresh from `thumbnail.css` classes.
|
||||
|
||||
If a request is ambiguous about style, propose a pattern (and, for a series, ask whether to match
|
||||
the existing set) before generating — don't silently reuse the previous layout.
|
||||
|
||||
## Why this pipeline produces quality (do not skip these)
|
||||
|
||||
1. **Deterministic fonts.** Geist is embedded as base64 `@font-face`. A Google Fonts `<link>`
|
||||
does NOT load before the headless screenshot — the headline silently falls back to system
|
||||
sans and looks off-brand. This is the single biggest failure mode. `render.py` handles it.
|
||||
2. **Real assets, recolored.** ClassroomIO logo = the actual `apps/website/static/logo-512.png`,
|
||||
recolored white via `filter: brightness(0) invert(1)`. Never redraw it.
|
||||
3. **Official third-party logos.** For a partner/tool, fetch the OFFICIAL svg (e.g. Dokploy:
|
||||
`https://dokploy.com/icon.svg`). Prefer an svg whose paths are `fill="white"` (or force white)
|
||||
so it drops onto the blue tile cleanly. A wrong-but-close logo destroys credibility.
|
||||
4. **Honest gradients, never frosted-white chips.** Tiles and pills are real blue gradients with
|
||||
iridescent borders (see `thumbnail.css`). `rgba(255,255,255,0.1)` frosted glass reads off-brand.
|
||||
|
||||
## Design spec (source of truth)
|
||||
|
||||
The full pattern catalog and Figma-exact tokens live in
|
||||
`company/blog-thumbnail-agent/README.md` — **read it before generating**, alongside the six
|
||||
reference PNGs in that folder. `thumbnail.css` in this skill already encodes those tokens
|
||||
(background vignette, glass tiles, pills, frame, title). Consume the CSS classes; don't re-derive.
|
||||
|
||||
### Pick the pattern from the content (each is a distinct look — rotate them)
|
||||
- **A — Editorial / link:** blog posts, guides pointing to a URL. Frame on TOP. Link pill + optional `Guide` pill. Title centered or bottom-left. No tiles.
|
||||
- **B — Concept map:** multi-item features (languages, integrations) as a connected node graph over a faint globe.
|
||||
- **C — Before → After:** upgrades, limit increases. Two glass tiles + arrow, action pill below, title bottom. Frame on BOTTOM.
|
||||
- **D — Hero icon:** releases, security, single-concept. One big centered glass tile, version/`New Feature` pill, 2-line title. Frame on BOTTOM.
|
||||
- **Two-tile connect** (C/D hybrid): "X with/via Y" integrations — two tiles joined by an arrow node. `template-two-tile.html` is a starting point. **Powerful but overused — don't reach for it by reflex.**
|
||||
|
||||
Beyond the pattern, vary the levers that keep a set from looking identical: background
|
||||
**texture** (chevrons / stacked cards / constellation / globe — match the topic), **title
|
||||
placement** (centered vs bottom-left), **pill copy**, and the **focal treatment**. A guide about
|
||||
one platform often reads better as Pattern A or D (single hero) than as another two-tile clone.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Choose a pattern deliberately** and confirm intent if unstated: pattern, the partner/tool (and
|
||||
whether to use its real logo), the headline, the pill text, and any URL. Recommend a pattern that
|
||||
fits the content; don't over-ask. If this belongs to an existing series, ask whether to match that
|
||||
set or give it a fresh look — do not silently reuse the last layout.
|
||||
2. **Fetch third-party assets** if needed (official svg logo). Verify it renders white on blue.
|
||||
3. **Author the HTML** in the scratchpad. Copy a template (e.g. `template-two-tile.html`) as a
|
||||
starting point, or write fresh linking `thumbnail.css`:
|
||||
- `<link rel="stylesheet" href="<abs-path-to-skill>/thumbnail.css" />`
|
||||
- Use `data:image/png;base64,__CIO_LOGO_B64__` for the ClassroomIO logo (render.py fills it).
|
||||
- Paste the partner's white svg inline inside a `.svg-icon` container.
|
||||
- Keep everything except the headline low-contrast so it reads at thumbnail size.
|
||||
4. **Render:** `python3 <skill>/render.py <input.html> <output.png>`. This inlines local
|
||||
stylesheets, substitutes `__GEIST_WOFF2_B64__` / `__CIO_LOGO_B64__`, and screenshots at
|
||||
1920×1080 (device scale 1). Requires Google Chrome at the standard macOS path.
|
||||
5. **Review the PNG visually** (Read the image). Check: brand font actually applied, logos correct
|
||||
and white, text not clipped, gradients present, ≤2 title lines. Iterate on the HTML if needed.
|
||||
6. **Deliver:** save the final PNG to `~/Downloads/` (or a path the user names) and report it.
|
||||
Output is ~880KB — under YouTube's 2MB thumbnail cap.
|
||||
|
||||
## Files in this skill
|
||||
- `SKILL.md` — this guide.
|
||||
- `thumbnail.css` — Figma-exact brand tokens (background, tiles, pills, connector, frame, title).
|
||||
- `template-two-tile.html` — starting point for the two-tile connect pattern.
|
||||
- `render.py` — inlines assets + renders HTML → PNG via headless Chrome.
|
||||
|
||||
Brand palette: deep blue `#0233BD` · brand blue `#2F6BF1` · light blue `#ADC3FF` · violet `#8071F2`.
|
||||
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Render a ClassroomIO thumbnail HTML to a 1920x1080 PNG via headless Chrome.
|
||||
|
||||
Resolves the two stable brand assets from the repo and inlines them as base64
|
||||
so the render is deterministic (a Google Fonts <link> does NOT load before the
|
||||
screenshot — that is the #1 cause of off-brand headlines). Third-party logos are
|
||||
NOT handled here: fetch the official svg per task and inline it in your HTML.
|
||||
|
||||
Placeholders replaced in the HTML before rendering:
|
||||
__GEIST_WOFF2_B64__ -> apps/dashboard/static/fonts/geist/geist-latin.woff2
|
||||
__CIO_LOGO_B64__ -> apps/website/static/logo-512.png
|
||||
|
||||
Usage:
|
||||
python3 render.py <input.html> <output.png>
|
||||
"""
|
||||
import base64
|
||||
import pathlib
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
REPO_ROOT = pathlib.Path(__file__).resolve().parents[2]
|
||||
GEIST = REPO_ROOT / "apps/dashboard/static/fonts/geist/geist-latin.woff2"
|
||||
CIO_LOGO = REPO_ROOT / "apps/website/static/logo-512.png"
|
||||
CHROME = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
|
||||
|
||||
|
||||
def b64(path: pathlib.Path) -> str:
|
||||
if not path.exists():
|
||||
sys.exit(f"Missing brand asset: {path}")
|
||||
|
||||
return base64.b64encode(path.read_bytes()).decode()
|
||||
|
||||
|
||||
def inline_local_stylesheets(html: str, base_dir: pathlib.Path) -> str:
|
||||
"""Replace <link rel="stylesheet" href="local.css"> with an inline <style>
|
||||
so placeholders inside the CSS also get substituted."""
|
||||
pattern = re.compile(r'<link[^>]*rel=["\']stylesheet["\'][^>]*href=["\']([^"\']+)["\'][^>]*>')
|
||||
|
||||
def replace(match: "re.Match[str]") -> str:
|
||||
href = match.group(1)
|
||||
if href.startswith(("http://", "https://", "//")):
|
||||
return match.group(0)
|
||||
|
||||
css_path = (base_dir / href).resolve()
|
||||
if not css_path.exists():
|
||||
sys.exit(f"Linked stylesheet not found: {css_path}")
|
||||
|
||||
return f"<style>\n{css_path.read_text()}\n</style>"
|
||||
|
||||
return pattern.sub(replace, html)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
if len(sys.argv) != 3:
|
||||
sys.exit("Usage: python3 render.py <input.html> <output.png>")
|
||||
|
||||
src = pathlib.Path(sys.argv[1]).resolve()
|
||||
out = pathlib.Path(sys.argv[2]).resolve()
|
||||
if not src.exists():
|
||||
sys.exit(f"Input HTML not found: {src}")
|
||||
|
||||
html = src.read_text()
|
||||
html = inline_local_stylesheets(html, src.parent)
|
||||
html = html.replace("__GEIST_WOFF2_B64__", b64(GEIST))
|
||||
html = html.replace("__CIO_LOGO_B64__", b64(CIO_LOGO))
|
||||
|
||||
inlined = src.with_suffix(".inlined.html")
|
||||
inlined.write_text(html)
|
||||
|
||||
subprocess.run(
|
||||
[
|
||||
CHROME,
|
||||
"--headless",
|
||||
"--disable-gpu",
|
||||
"--hide-scrollbars",
|
||||
"--force-device-scale-factor=1",
|
||||
"--window-size=1920,1080",
|
||||
f"--screenshot={out}",
|
||||
f"file://{inlined}",
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
print(f"Rendered {out}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,68 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="stylesheet" href="thumbnail.css" />
|
||||
<style>
|
||||
/* Hero-icon (Pattern D) layout */
|
||||
.stage {
|
||||
position: absolute; top: 132px; left: 0; right: 0;
|
||||
display: flex; flex-direction: column; align-items: center;
|
||||
}
|
||||
.pill-wrap { margin-top: 52px; }
|
||||
.title {
|
||||
margin-top: 46px; text-align: center; font-size: 100px;
|
||||
}
|
||||
/* DigitalOcean mark sits a touch larger in the tile */
|
||||
.tile .svg-icon { width: 168px; }
|
||||
/* small floating accent squares around the hero tile */
|
||||
.accent {
|
||||
position: absolute; padding: 2px; border-radius: 16px;
|
||||
background: linear-gradient(135deg, #0233BD 23%, #ADC3FF 42%, #8071F2 54%, #0233BD 82%);
|
||||
box-shadow: 0 18px 36px rgba(6, 18, 66, 0.4);
|
||||
}
|
||||
.accent > div {
|
||||
width: 100%; height: 100%; border-radius: 14px;
|
||||
background: linear-gradient(145deg, #0233BD 10%, #2F6BF1 94%);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="texture">
|
||||
<div class="card-line" style="width:520px;height:520px;"></div>
|
||||
<div class="card-line" style="width:780px;height:720px;border-radius:80px;"></div>
|
||||
<div class="card-line" style="width:1060px;height:920px;border-radius:110px;"></div>
|
||||
<div class="card-line" style="width:1380px;height:1140px;border-radius:140px;"></div>
|
||||
<div class="spark" style="top:170px;left:360px;">✦</div>
|
||||
<div class="spark" style="top:240px;right:330px;font-size:26px;">✦</div>
|
||||
<div class="spark" style="bottom:250px;left:220px;">✦</div>
|
||||
</div>
|
||||
|
||||
<!-- Frame on the BOTTOM edge (Pattern D) -->
|
||||
<div class="frame bottom">
|
||||
<div class="brand">
|
||||
<img src="data:image/png;base64,__CIO_LOGO_B64__" alt="ClassroomIO" />
|
||||
<div class="name">ClassroomIO</div>
|
||||
</div>
|
||||
<div class="domain"><span class="globe"></span><span>classroomio.com</span></div>
|
||||
</div>
|
||||
|
||||
<div class="stage">
|
||||
<div style="position:relative;">
|
||||
<div class="accent" style="width:70px;height:70px;top:-34px;left:-64px;"><div></div></div>
|
||||
<div class="accent" style="width:44px;height:44px;bottom:-18px;right:-58px;"><div></div></div>
|
||||
|
||||
<div class="tile-wrap"><div class="tile">
|
||||
<div class="svg-icon">
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="#ffffff"><path d="M12.04 0C5.408-.02.005 5.37.005 11.992h4.638c0-4.923 4.882-8.731 10.064-6.855a6.95 6.95 0 014.147 4.148c1.889 5.177-1.924 10.055-6.84 10.064v-4.61H7.391v4.623h4.61V24c7.86 0 13.967-7.588 11.397-15.83-1.115-3.59-3.985-6.446-7.575-7.575A12.8 12.8 0 0012.039 0zM7.39 19.362H3.828v3.564H7.39zm-3.563 0v-2.978H.85v2.978z"/></svg>
|
||||
</div>
|
||||
<div class="label">DigitalOcean</div>
|
||||
</div></div>
|
||||
</div>
|
||||
|
||||
<div class="pill-wrap"><div class="pill"><span>SELF-HOST GUIDE</span></div></div>
|
||||
|
||||
<div class="title">Self-Host ClassroomIO<br/><span class="tail">on </span>DigitalOcean</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,66 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="stylesheet" href="thumbnail.css" />
|
||||
<style>
|
||||
/* Layout-only overrides for the two-tile connect pattern */
|
||||
.stage { position: absolute; top: 238px; left: 0; right: 0; display: flex; flex-direction: column; align-items: center; }
|
||||
.tiles { display: flex; align-items: center; }
|
||||
.pill-wrap { margin-top: 56px; }
|
||||
.title { position: absolute; bottom: 70px; left: 0; right: 0; text-align: center; font-size: 104px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="texture">
|
||||
<div class="card-line" style="width:520px;height:520px;"></div>
|
||||
<div class="card-line" style="width:760px;height:700px;border-radius:80px;"></div>
|
||||
<div class="card-line" style="width:1040px;height:900px;border-radius:110px;"></div>
|
||||
<div class="card-line" style="width:1360px;height:1120px;border-radius:140px;"></div>
|
||||
<div class="spark" style="top:150px;right:360px;">✦</div>
|
||||
<div class="spark" style="bottom:250px;left:150px;">✦</div>
|
||||
<div class="spark" style="bottom:180px;right:220px;font-size:26px;">✦</div>
|
||||
</div>
|
||||
|
||||
<!-- Frame on ONE edge only. Two-tile/hero patterns use the TOP frame here. -->
|
||||
<div class="frame top">
|
||||
<div class="brand">
|
||||
<img src="data:image/png;base64,__CIO_LOGO_B64__" alt="ClassroomIO" />
|
||||
<div class="name">ClassroomIO</div>
|
||||
</div>
|
||||
<div class="domain"><span class="globe"></span><span>classroomio.com</span></div>
|
||||
</div>
|
||||
|
||||
<div class="stage">
|
||||
<div class="tiles">
|
||||
<!-- Left tile: ClassroomIO -->
|
||||
<div class="tile-wrap"><div class="tile">
|
||||
<img src="data:image/png;base64,__CIO_LOGO_B64__" alt="ClassroomIO" />
|
||||
<div class="label">ClassroomIO</div>
|
||||
</div></div>
|
||||
|
||||
<!-- Connector: arrow node between the two tiles -->
|
||||
<div class="connector">
|
||||
<div class="dash"></div>
|
||||
<div class="node"><div class="node-inner">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="M13 6l6 6-6 6"/></svg>
|
||||
</div></div>
|
||||
<div class="dash"></div>
|
||||
</div>
|
||||
|
||||
<!-- Right tile: the partner/tool. Paste the OFFICIAL white svg inside .svg-icon
|
||||
(fetch it per task; e.g. Dokploy: https://dokploy.com/icon.svg). -->
|
||||
<div class="tile-wrap"><div class="tile">
|
||||
<div class="svg-icon"><!-- PARTNER_SVG_HERE --></div>
|
||||
<div class="label">Partner</div>
|
||||
</div></div>
|
||||
</div>
|
||||
|
||||
<!-- Category / action pill -->
|
||||
<div class="pill-wrap"><div class="pill"><span>DEPLOY IN MINUTES</span></div></div>
|
||||
</div>
|
||||
|
||||
<!-- Title: bold white, ≤2 lines. Lighter tail via <span class="tail"> for hierarchy. -->
|
||||
<div class="title">Primary Headline<br/><span class="tail">with </span>Partner</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,87 @@
|
||||
/* ClassroomIO thumbnail brand tokens — Figma-exact. Consume these; do not eyeball.
|
||||
Palette: deep blue #0233BD · brand blue #2F6BF1 · light blue #ADC3FF · violet #8071F2 */
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist';
|
||||
font-style: normal;
|
||||
font-weight: 100 900;
|
||||
font-display: block;
|
||||
src: url(data:font/woff2;base64,__GEIST_WOFF2_B64__) format('woff2');
|
||||
}
|
||||
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
html, body { width: 1920px; height: 1080px; }
|
||||
|
||||
body {
|
||||
font-family: 'Geist', sans-serif;
|
||||
width: 1920px; height: 1080px; position: relative; overflow: hidden;
|
||||
/* Royal-blue full-bleed with center-bright vignette */
|
||||
background: radial-gradient(120% 110% at 50% 42%, #2B5BE0 0%, #1D49C7 42%, #12318F 78%, #0E2A7E 100%);
|
||||
}
|
||||
|
||||
/* --- faint white texture (keep ~5-12% opacity; never competes with title) --- */
|
||||
.texture { position: absolute; inset: 0; pointer-events: none; }
|
||||
.card-line {
|
||||
position: absolute; top: 50%; left: 50%;
|
||||
border: 2px solid rgba(255, 255, 255, 0.06);
|
||||
border-radius: 60px; transform: translate(-50%, -58%);
|
||||
}
|
||||
.spark { position: absolute; color: #8FE8DC; opacity: .85; font-size: 34px; }
|
||||
|
||||
/* --- frame (logo + wordmark on ONE edge, domain on the other; never both edges) --- */
|
||||
.frame { position: absolute; left: 0; right: 0; display: flex; justify-content: space-between; padding: 0 72px; align-items: center; }
|
||||
.frame.top { top: 52px; }
|
||||
.frame.bottom { bottom: 52px; }
|
||||
.brand { display: flex; align-items: center; gap: 18px; }
|
||||
.brand img { width: 52px; height: 52px; filter: brightness(0) invert(1); }
|
||||
.brand .name { color: #fff; font-size: 40px; font-weight: 700; letter-spacing: -1px; }
|
||||
.domain { display: flex; align-items: center; gap: 14px; color: #fff; font-size: 34px; font-weight: 600; }
|
||||
.domain .globe { width: 36px; height: 36px; border: 2.5px solid #fff; border-radius: 50%; position: relative; opacity: .92; }
|
||||
.domain .globe::before { content: ''; position: absolute; inset: -2.5px 8px; border: 2.5px solid #fff; border-radius: 50%; }
|
||||
.domain .globe::after { content: ''; position: absolute; left: -2.5px; right: -2.5px; top: 50%; height: 0; border-top: 2.5px solid #fff; transform: translateY(-1px); }
|
||||
.domain span { text-decoration: underline; text-underline-offset: 6px; }
|
||||
|
||||
/* --- glass icon tile (patterns C & D): blue gradient fill + iridescent border, NOT frosted white --- */
|
||||
.tile-wrap {
|
||||
padding: 2.5px; border-radius: 44px;
|
||||
background: linear-gradient(135deg, #0233BD 23%, #ADC3FF 42%, #8071F2 54%, #0233BD 82%);
|
||||
box-shadow: 0 40px 80px rgba(6, 18, 66, 0.45);
|
||||
}
|
||||
.tile {
|
||||
width: 300px; height: 300px; border-radius: 42px;
|
||||
background: linear-gradient(145deg, #0233BD 10%, #2F6BF1 94%);
|
||||
display: flex; align-items: center; justify-content: center; position: relative; overflow: hidden;
|
||||
}
|
||||
.tile::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 55%; background: linear-gradient(180deg, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0)); }
|
||||
.tile img { width: 172px; height: 172px; filter: brightness(0) invert(1); position: relative; z-index: 1; }
|
||||
.tile .svg-icon { width: 186px; height: auto; position: relative; z-index: 1; }
|
||||
.tile .svg-icon svg { width: 100%; height: auto; }
|
||||
.tile .label { position: absolute; bottom: 24px; left: 0; right: 0; text-align: center; color: rgba(255, 255, 255, 0.85); font-size: 26px; font-weight: 600; letter-spacing: .5px; }
|
||||
|
||||
/* --- connector (two-tile / before->after) --- */
|
||||
.connector { display: flex; align-items: center; margin: 0 -6px; z-index: 2; }
|
||||
.connector .dash { width: 44px; height: 4px; border-radius: 4px; background: rgba(255, 255, 255, 0.35); }
|
||||
.connector .node {
|
||||
width: 74px; height: 74px; margin: 0 10px; border-radius: 50%;
|
||||
padding: 2.5px; background: linear-gradient(135deg, #0233BD 23%, #ADC3FF 42%, #8071F2 54%, #0233BD 82%);
|
||||
box-shadow: 0 16px 32px rgba(6, 18, 66, 0.4);
|
||||
}
|
||||
.connector .node-inner { width: 100%; height: 100%; border-radius: 50%; background: linear-gradient(145deg, #0233BD 10%, #2F6BF1 94%); display: flex; align-items: center; justify-content: center; }
|
||||
.connector .node-inner svg { width: 36px; height: 36px; }
|
||||
|
||||
/* --- pill / badge: fully gradient-built (fill + iridescent border + clipped gradient text) --- */
|
||||
.pill-wrap {
|
||||
padding: 2px; border-radius: 999px;
|
||||
background: linear-gradient(180deg, #0233BD 24%, #C1D4FF 55%, #93B4FF 80%);
|
||||
box-shadow: 0 16px 32px rgba(6, 18, 66, 0.35);
|
||||
}
|
||||
.pill { height: 70px; padding: 0 40px; border-radius: 999px; background: linear-gradient(180deg, #0233BD 0%, #0C4BDA 100%); display: flex; align-items: center; }
|
||||
.pill span {
|
||||
font-size: 30px; font-weight: 700; letter-spacing: .5px;
|
||||
background: linear-gradient(180deg, #FFFFFF 0%, #8EACFF 100%);
|
||||
-webkit-background-clip: text; background-clip: text; color: transparent;
|
||||
}
|
||||
|
||||
/* --- title: bold white Title Case, tight tracking; lighter 78%-white tail for hierarchy --- */
|
||||
.title { color: #fff; font-weight: 700; line-height: 1.02; letter-spacing: -3px; }
|
||||
.title .tail { font-weight: 500; color: rgba(255, 255, 255, 0.78); }
|
||||
Reference in New Issue
Block a user