Bootstrapped during the 2026-06-06 BlockNinja consolidation. Was previously an unversioned directory inside ~/src/blockninja-themes/editorial. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
366 lines
9.1 KiB
Go
366 lines
9.1 KiB
Go
package main
|
||
|
||
// editorialUtilityCSS is the theme's custom utility layer appended to the host
|
||
// Tailwind input. It is intentionally light: no @font-face rules (those are
|
||
// emitted by the host from the admin's font assignments per docs/FONTS.md), no
|
||
// hardcoded hex / rgb / named colours. Every colour goes through the shadcn
|
||
// HSL variable consumer pattern: `hsl(var(--token))`.
|
||
//
|
||
// What this CSS contracts to deliver (cross-checked against the UAT §13):
|
||
// - .prose-editorial: 64ch measure, indented continuation paragraphs.
|
||
// - .editorial-dropcap p:first-of-type::first-letter: oxblood accent,
|
||
// ≥ 3× body font-size.
|
||
// - .editorial-marginalia: italic Source Serif 4 12px right-rail asides.
|
||
// - .editorial-masthead-wordmark: Playfair Display 900 italic.
|
||
// - .editorial-pullquote: Playfair italic 38px in oxblood accent.
|
||
// - .editorial-section-label: uppercase + small-caps + hairline.
|
||
// - .editorial-hairline / hr.editorial-rule: 1px solid hsl(var(--border)).
|
||
// - .editorial-button: transparent fill, 1px border, hover → accent text.
|
||
// - .editorial-caption: Source Serif italic 14px with hairline above.
|
||
//
|
||
// All `font-family` declarations route through the three CSS variables
|
||
// (`--font-heading`, `--font-body`, `--font-mono`) the host exposes on :root,
|
||
// with fallback stacks derived from spec §3.
|
||
const editorialUtilityCSS = `
|
||
/* === Editorial theme — utility layer === */
|
||
|
||
:root {
|
||
--editorial-measure: 64ch;
|
||
--editorial-rule: 1px solid hsl(var(--border));
|
||
}
|
||
|
||
/* --- Narrow editorial column with indented continuation paragraphs --- */
|
||
|
||
.prose-editorial {
|
||
max-width: var(--editorial-measure);
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
font-family: var(--font-body, "Source Serif 4", "Source Serif Pro", Georgia, serif);
|
||
color: hsl(var(--foreground));
|
||
line-height: 1.65;
|
||
}
|
||
|
||
.prose-editorial p {
|
||
margin: 0 0 1em 0;
|
||
text-indent: 0;
|
||
}
|
||
|
||
.prose-editorial p + p {
|
||
text-indent: 1.5em;
|
||
}
|
||
|
||
.prose-editorial h1,
|
||
.prose-editorial h2,
|
||
.prose-editorial h3,
|
||
.prose-editorial h4 {
|
||
font-family: var(--font-heading, "Playfair Display", Georgia, serif);
|
||
font-weight: 700;
|
||
letter-spacing: -0.01em;
|
||
color: hsl(var(--foreground));
|
||
}
|
||
|
||
.prose-editorial a {
|
||
color: hsl(var(--accent));
|
||
text-decoration: underline;
|
||
text-decoration-thickness: 1px;
|
||
text-underline-offset: 2px;
|
||
}
|
||
|
||
/* --- Drop cap — oxblood accent first letter, ≥ 3x body size --- */
|
||
|
||
.editorial-dropcap p:first-of-type::first-letter {
|
||
font-family: var(--font-heading, "Playfair Display", Georgia, serif);
|
||
font-weight: 900;
|
||
font-style: italic;
|
||
color: hsl(var(--accent));
|
||
float: left;
|
||
font-size: 4.5em;
|
||
line-height: 0.85;
|
||
padding-right: 0.12em;
|
||
padding-top: 0.05em;
|
||
margin-bottom: -0.1em;
|
||
}
|
||
|
||
/* --- Marginalia rail (right-side italic notes) --- */
|
||
|
||
.editorial-marginalia {
|
||
font-family: var(--font-body, "Source Serif 4", "Source Serif Pro", Georgia, serif);
|
||
font-style: italic;
|
||
font-size: 12px;
|
||
line-height: 1.5;
|
||
color: hsl(var(--muted-foreground));
|
||
}
|
||
|
||
.editorial-marginalia aside {
|
||
margin: 0 0 1.5rem 0;
|
||
padding-left: 0.75rem;
|
||
border-left: var(--editorial-rule);
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.editorial-marginalia {
|
||
margin-top: 1.5rem;
|
||
border-top: var(--editorial-rule);
|
||
padding-top: 1rem;
|
||
}
|
||
}
|
||
|
||
/* --- Masthead wordmark --- */
|
||
|
||
.editorial-masthead-wordmark {
|
||
font-family: var(--font-heading, "Playfair Display", Georgia, serif);
|
||
font-weight: 900;
|
||
font-style: italic;
|
||
letter-spacing: -0.02em;
|
||
color: hsl(var(--foreground));
|
||
}
|
||
|
||
.editorial-masthead-kicker {
|
||
font-family: var(--font-mono, "JetBrains Mono", "SF Mono", ui-monospace, monospace);
|
||
font-size: 11px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.15em;
|
||
color: hsl(var(--muted-foreground));
|
||
}
|
||
|
||
.editorial-masthead-rule {
|
||
border: 0;
|
||
border-top: var(--editorial-rule);
|
||
margin: 0.5rem 0 0 0;
|
||
}
|
||
|
||
/* --- Pull quote — Playfair italic in oxblood --- */
|
||
|
||
.editorial-pullquote {
|
||
font-family: var(--font-heading, "Playfair Display", Georgia, serif);
|
||
font-style: italic;
|
||
font-size: 38px;
|
||
line-height: 1.2;
|
||
color: hsl(var(--accent));
|
||
margin: 2.5rem auto;
|
||
max-width: var(--editorial-measure);
|
||
border: none;
|
||
}
|
||
|
||
.editorial-pullquote-attribution {
|
||
display: block;
|
||
margin-top: 1rem;
|
||
font-family: var(--font-body, "Source Serif 4", Georgia, serif);
|
||
font-style: normal;
|
||
font-size: 14px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.12em;
|
||
color: hsl(var(--muted-foreground));
|
||
}
|
||
|
||
/* --- Section label — small-caps with hairline rule --- */
|
||
|
||
.editorial-section-label {
|
||
font-family: var(--font-body, "Source Serif 4", Georgia, serif);
|
||
text-transform: uppercase;
|
||
font-variant: small-caps;
|
||
font-feature-settings: "smcp";
|
||
letter-spacing: 0.15em;
|
||
font-size: 13px;
|
||
color: hsl(var(--foreground));
|
||
}
|
||
|
||
.editorial-section-label-rule {
|
||
border: 0;
|
||
border-top: var(--editorial-rule);
|
||
margin: 0.5rem 0 1.5rem 0;
|
||
}
|
||
|
||
/* --- Hairline rules --- */
|
||
|
||
hr.editorial-rule,
|
||
.editorial-hairline {
|
||
border: 0;
|
||
border-top: var(--editorial-rule);
|
||
margin: 1.5rem 0;
|
||
}
|
||
|
||
/* --- Byline --- */
|
||
|
||
.editorial-byline {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.75rem;
|
||
padding: 0.75rem 0;
|
||
border-top: var(--editorial-rule);
|
||
border-bottom: var(--editorial-rule);
|
||
}
|
||
|
||
.editorial-byline-photo {
|
||
width: 36px;
|
||
height: 36px;
|
||
border-radius: 50%;
|
||
background-color: hsl(var(--muted));
|
||
flex-shrink: 0;
|
||
object-fit: cover;
|
||
}
|
||
|
||
.editorial-byline-author {
|
||
font-family: var(--font-mono, "JetBrains Mono", monospace), var(--font-body, "Source Serif 4", Georgia, serif);
|
||
/* The spec calls for Inter for UI bylines. Fallback to Inter then system. */
|
||
font-family: var(--font-body, "Inter", -apple-system, sans-serif);
|
||
font-weight: 500;
|
||
font-size: 15px;
|
||
color: hsl(var(--foreground));
|
||
}
|
||
|
||
.editorial-byline-meta {
|
||
font-family: var(--font-body, "Inter", -apple-system, sans-serif);
|
||
font-size: 12px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.1em;
|
||
color: hsl(var(--muted-foreground));
|
||
}
|
||
|
||
/* --- Override: heading (Playfair, tight tracking, optional small-caps kicker) --- */
|
||
|
||
.editorial-heading {
|
||
font-family: var(--font-heading, "Playfair Display", Georgia, serif);
|
||
font-weight: 700;
|
||
letter-spacing: -0.015em;
|
||
color: hsl(var(--foreground));
|
||
line-height: 1.15;
|
||
}
|
||
|
||
.editorial-heading-kicker {
|
||
display: block;
|
||
margin-bottom: 0.5rem;
|
||
font-family: var(--font-body, "Inter", -apple-system, sans-serif);
|
||
font-size: 12px;
|
||
text-transform: uppercase;
|
||
font-variant: small-caps;
|
||
font-feature-settings: "smcp";
|
||
letter-spacing: 0.18em;
|
||
color: hsl(var(--muted-foreground));
|
||
}
|
||
|
||
/* --- Override: text body (Source Serif, hanging quotes) --- */
|
||
|
||
.editorial-text {
|
||
font-family: var(--font-body, "Source Serif 4", "Source Serif Pro", Georgia, serif);
|
||
color: hsl(var(--foreground));
|
||
line-height: 1.7;
|
||
max-width: var(--editorial-measure);
|
||
}
|
||
|
||
.editorial-text p + p {
|
||
text-indent: 1.5em;
|
||
margin-top: 0;
|
||
}
|
||
|
||
.editorial-text blockquote {
|
||
hanging-punctuation: first;
|
||
font-style: italic;
|
||
border-left: var(--editorial-rule);
|
||
padding-left: 1rem;
|
||
margin-left: 0;
|
||
}
|
||
|
||
/* --- Override: button (hairline border, no fill, accent on hover) --- */
|
||
|
||
.editorial-button {
|
||
display: inline-block;
|
||
padding: 0.5rem 1rem;
|
||
font-family: var(--font-body, "Inter", -apple-system, sans-serif);
|
||
font-size: 13px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.12em;
|
||
background-color: transparent;
|
||
color: hsl(var(--foreground));
|
||
border: 1px solid hsl(var(--border));
|
||
text-decoration: none;
|
||
cursor: pointer;
|
||
transition: color 150ms ease, border-color 150ms ease;
|
||
}
|
||
|
||
.editorial-button:hover,
|
||
.editorial-button:focus {
|
||
color: hsl(var(--accent));
|
||
border-color: hsl(var(--accent));
|
||
}
|
||
|
||
.editorial-button:focus-visible {
|
||
outline: 2px solid hsl(var(--ring));
|
||
outline-offset: 2px;
|
||
}
|
||
|
||
/* --- Override: image (Source Serif italic caption with hairline above) --- */
|
||
|
||
.editorial-figure {
|
||
margin: 1.5rem 0;
|
||
}
|
||
|
||
.editorial-figure img {
|
||
display: block;
|
||
width: 100%;
|
||
height: auto;
|
||
}
|
||
|
||
.editorial-figure figcaption {
|
||
margin-top: 0.75rem;
|
||
padding-top: 0.5rem;
|
||
border-top: var(--editorial-rule);
|
||
font-family: var(--font-body, "Source Serif 4", "Source Serif Pro", Georgia, serif);
|
||
font-style: italic;
|
||
font-size: 14px;
|
||
color: hsl(var(--muted-foreground));
|
||
}
|
||
|
||
/* --- Colophon --- */
|
||
|
||
.editorial-colophon {
|
||
border-top: var(--editorial-rule);
|
||
padding-top: 1.5rem;
|
||
font-family: var(--font-body, "Inter", -apple-system, sans-serif);
|
||
font-size: 13px;
|
||
color: hsl(var(--muted-foreground));
|
||
}
|
||
|
||
.editorial-colophon-issn {
|
||
font-family: var(--font-mono, "JetBrains Mono", monospace);
|
||
font-size: 11px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.1em;
|
||
}
|
||
|
||
/* --- Page layout — narrow editorial column --- */
|
||
|
||
.editorial-column {
|
||
max-width: var(--editorial-measure);
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
padding-left: 1rem;
|
||
padding-right: 1rem;
|
||
}
|
||
|
||
.editorial-wide {
|
||
max-width: 96rem;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
padding-left: 1rem;
|
||
padding-right: 1rem;
|
||
}
|
||
|
||
.editorial-article-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr;
|
||
gap: 1.5rem;
|
||
max-width: 80rem;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
padding-left: 1rem;
|
||
padding-right: 1rem;
|
||
}
|
||
|
||
@media (min-width: 1024px) {
|
||
.editorial-article-grid {
|
||
grid-template-columns: minmax(0, 64ch) 16rem;
|
||
}
|
||
}
|
||
`
|