diff --git a/src/components/layout/CMDPalette/index.tsx b/src/components/layout/CMDPalette/index.tsx index 2e57d23..db767b6 100644 --- a/src/components/layout/CMDPalette/index.tsx +++ b/src/components/layout/CMDPalette/index.tsx @@ -16,6 +16,7 @@ const TYPE_LABELS: Record = { article: 'Article', element: 'Element', page: 'Page', + section: 'Section', }; /* INDEX ENTRY */ @@ -82,8 +83,12 @@ const buildRows = (entries: PaletteEntry[]): RenderRow[] => { return rows; }; +interface Props { + currentPath?: string; +} + /* COMPONENT */ -export default function CommandPalette() { +export default function CommandPalette({ currentPath = '/' }) { const [isOpen, setIsOpen] = useState(false); const [query, setQuery] = useState(''); const [index, setIndex] = useState([]); @@ -150,17 +155,49 @@ export default function CommandPalette() { /* FILTERED ENTRIES -> RENDER ROWS */ const filtered = useMemo(() => { - if (!query.trim()) { - return index.filter((e) => e.depth <= 2).slice(0, MAX_DEFAULT); + if (query.trim()) { + const q = normalize(query); + return index + .map((entry) => ({ entry, score: scoreEntry(entry, q) })) + .filter((r) => r.score > 0) + .sort((a, b) => b.score - a.score) + .slice(0, MAX_SEARCH) + .map((r) => r.entry); } - const q = normalize(query); - return index - .map((entry) => ({ entry, score: scoreEntry(entry, q) })) - .filter((r) => r.score > 0) - .sort((a, b) => b.score - a.score) - .slice(0, MAX_SEARCH) - .map((r) => r.entry); - }, [index, query]); + + if (currentPath === '/') { + return index.filter((e) => e.depth === 1); + } + + const segments = currentPath.replace(/\/$/, '').split('/').filter(Boolean); + const parentPath = '/' + segments.slice(0, -1).join('/'); + const normalizedCurrent = currentPath.replace(/\/$/, ''); + + const siblings = index.filter((e) => { + const ePath = e.path.replace(/\/$/, ''); + return ( + ePath !== normalizedCurrent && + ePath.startsWith(parentPath) && + e.depth === segments.length + ); + }); + + const children = index.filter((e) => { + const ePath = e.path.replace(/\/$/, ''); + return ( + ePath.startsWith(normalizedCurrent) && e.depth === segments.length + 1 + ); + }); + + const parent = index.filter((e) => { + const ePath = e.path.replace(/\/$/, ''); + return ePath === parentPath; + }); + + const contextual = [...parent, ...siblings, ...children]; + + return contextual; + }, [index, query, currentPath]); const rows = useMemo(() => buildRows(filtered), [filtered]); diff --git a/src/components/layout/MastHead.astro b/src/components/layout/MastHead.astro index 769b405..2b85266 100644 --- a/src/components/layout/MastHead.astro +++ b/src/components/layout/MastHead.astro @@ -13,13 +13,13 @@ import CommandPalette from "./CMDPalette" ] - + diff --git a/src/content/articles/alchemical-materialism/cover/src.png b/src/content/articles/alchemical-materialism/cover/src.png deleted file mode 100644 index a380b98..0000000 Binary files a/src/content/articles/alchemical-materialism/cover/src.png and /dev/null differ diff --git a/src/content/articles/alchemical-materialism/index.mdoc b/src/content/articles/alchemical-materialism/index.mdoc index b88c106..055a291 100644 --- a/src/content/articles/alchemical-materialism/index.mdoc +++ b/src/content/articles/alchemical-materialism/index.mdoc @@ -3,10 +3,7 @@ title: Alchemical Materialism subtitle: A Systematic Framework for Worldbuilding Through Elemental Combination summary: A Systematic Framework for Worldbuilding Through Elemental Combination cover: - src: /content/articles/alchemical-materialism/cover/src.png - alt: Man approach a volcano - caption: The Eshian God-Alchemists claimed this was the face of Monad - showInHeader: true + showInHeader: false publishDate: 2026-02-20T11:17:00.000Z status: published isFeatured: false diff --git a/src/keystatic/fields/content.ts b/src/keystatic/fields/content.ts index bef597b..237f18f 100644 --- a/src/keystatic/fields/content.ts +++ b/src/keystatic/fields/content.ts @@ -10,6 +10,9 @@ export const createContentField = ( ) => fields.markdoc({ label: 'Body', + options: { + heading: [2, 3, 4, 5, 6], + }, components: { ...sharedComponents, ...additionalComponents, diff --git a/src/layouts/ContentLayout.astro b/src/layouts/ContentLayout.astro index 93cc846..6b5643c 100644 --- a/src/layouts/ContentLayout.astro +++ b/src/layouts/ContentLayout.astro @@ -15,6 +15,7 @@ const { entry, collectionName } = Astro.props; const { Content } = await render(entry); const { title, summary, subtitle, updateDate, publishDate, tags, seo } = entry.data; +const hasMargin = Astro.slots.has('margin') const breadcrumbs = await getBreadcrumbs( entry.data.parent ?? null, @@ -48,11 +49,41 @@ const headerCover = tags={tags} subtitle={subtitle} /> -
- - - +
+
+ + + +
+ {hasMargin &&( + + )}
+ + diff --git a/src/lib/types/content.ts b/src/lib/types/content.ts index b3478c8..f151ec6 100644 --- a/src/lib/types/content.ts +++ b/src/lib/types/content.ts @@ -1,7 +1,7 @@ import type { CollectionEntry } from 'astro:content'; /** Registered Content Type identifiers **/ -export type ContentType = 'article' | 'page' | 'element'; +export type ContentType = 'article' | 'page' | 'element' | 'section'; /** * Minimal common shape for everything that participates in path resoltution and parent chain walking. diff --git a/src/lib/utils/paths.ts b/src/lib/utils/paths.ts index 8a6506e..ef95977 100644 --- a/src/lib/utils/paths.ts +++ b/src/lib/utils/paths.ts @@ -174,7 +174,7 @@ export const buildPaletteIndex = ( return { label: r.entry.data.title, path: `/${r.path}`, - type: r.type, + type: r.type === 'article' && depth <= 1 ? 'section' : r.type, parent: parentTitle, depth, }; diff --git a/src/styles/base/content copy.css b/src/styles/base/content copy.css new file mode 100644 index 0000000..231cfce --- /dev/null +++ b/src/styles/base/content copy.css @@ -0,0 +1,651 @@ +.content { + @mixin responsive-wrapper; + font-family: var(--font-body); + /* === Headings === */ + & h1 { + margin-block: var(--el-h1-vspace-top) var(--el-h1-vspace-bottom); + padding-bottom: var(--spacing-snug); + border-bottom: var(--size-4) solid var(--el-h1-color); + + font-family: var(--el-h1-font-family), serif; + font-size: var(--el-h1-font-size); + font-weight: 400; + line-height: var(--typo-leading-tight); + color: var(--el-h1-color); + text-transform: uppercase; + letter-spacing: -0.0137em; + + & + p, + & + ul, + & + ol, + & + blockquote { + margin-block: calc(1em * var(--typo-leading-normal) * var(--vspace-tight)) + calc(1em * var(--typo-leading-normal) * var(--vspace-snug)); + } + + & + h2 { + margin-block: calc(1em * 1.125 * var(--vspace-snug)) + calc(1em * 1.125 * var(--vspace-normal)); + } + } + + & h2 { + margin-block: var(--el-h2-vspace-top) var(--el-h2-vspace-bottom); + padding-left: var(--spacing-snug); + border-left: var(--size-4) solid var(--el-h2-color); + + font-family: var(--el-h2-font-family), serif; + font-size: var(--el-h2-font-size); + font-weight: 900; + line-height: 1.1765; + color: var(--el-h2-color); + text-transform: uppercase; + letter-spacing: -0.0096em; + + & + p, + & + ul, + & + ol, + & + blockquote { + margin-block: calc(1em * var(--typo-leading-normal) * var(--vspace-tight)) + calc(1em * var(--typo-leading-normal) * var(--vspace-snug)); + } + + & + h3 { + margin-block: calc(1em * 1.125 * var(--vspace-compressed)) + calc(1em * 1.125 * var(--vspace-snug)); + } + } + + & h3 { + margin-block: var(--el-h3-vspace-top) var(--el-h3-vspace-bottom); + padding: var(--spacing-tight) var(--spacing-snug); + + font-family: var(--el-h3-font-family), serif; + font-size: var(--el-h3-font-size); + font-weight: 800; + line-height: 1.2; + color: var(--color-surface-base); + text-transform: uppercase; + letter-spacing: -0.004em; + + background: var(--el-h3-color); + } + + & h4 { + margin-block: var(--el-h4-vspace-top) var(--el-h4-vspace-bottom); + padding: var(--spacing-tight) var(--spacing-snug); + border-top: var(--size-3) solid var(--el-h4-color); + border-bottom: var(--size-3) solid var(--el-h4-color); + + font-family: var(--el-h4-font-family), serif; + font-size: var(--el-h4-font-size); + font-weight: 800; + line-height: 1.125; + text-transform: uppercase; + letter-spacing: 0.0025em; + } + + & h5 { + margin-block: var(--el-h5-vspace-top) var(--el-h5-vspace-bottom); + padding: var(--spacing-tight) var(--spacing-snug); + + font-family: var(--el-h5-font-family), serif; + font-size: var(--el-h5-font-size); + font-weight: 800; + line-height: 1.28; + color: var(--el-h5-color); + text-transform: uppercase; + letter-spacing: 0.05em; + + &::before, + &::after { + content: ''; + padding-right: var(--spacing-tight); + line-height: 1; + } + + &::before { + content: '⭑'; + } + + &::after { + content: ''; + } + } + + & h6 { + margin-block: var(--el-h6-vspace-top) var(--el-h6-vspace-bottom); + + font-family: var(--el-h6-font-family), serif; + font-size: var(--el-h6-font-size); + font-weight: 900; + line-height: 1.4; + color: var(--el-h6-color); + text-transform: uppercase; + letter-spacing: 0.035em; + } + + & h3, + & h4, + & h5, + & h6 { + & + p, + & + ul, + & + ol, + & + blockquote { + margin-block: calc( + 1em * var(--typo-leading-normal) * var(--vspace-compressed) + ) + calc(1em * var(--typo-leading-normal) * var(--vspace-snug)); + } + } + + /* === Body Text === */ + + & p { + margin-block: var(--el-p-vspace-top) var(--el-p-vspace-bottom); + + font-family: var(--el-p-font-family), sans-serif; + font-size: var(--el-p-font-size); + font-weight: 400; + line-height: var(--typo-leading-normal); + color: var(--el-p-color); + text-align: justify; + } + + & blockquote { + margin-block: var(--el-p-vspace-top) var(--el-p-vspace-bottom); + padding: var(--spacing-snug) 0 var(--spacing-snug) + var(--spacing-comfortable); + border-left: var(--size-4) solid var(--color-text-tertiary); + + font-family: var(--el-blockquote-font-family), serif; + font-size: var(--el-blockquote-font-size); + font-weight: 500; + font-style: normal; + line-height: var(--typo-leading-comfortable); + color: var(--el-blockquote-color); + } + + /* === Code === */ + + pre { + margin-block: var(--el-pre-vspace-top) var(--el-pre-vspace-bottom); + padding: var(--spacing-comfortable); + + font-family: var(--el-pre-font-family), monospace; + font-size: var(--el-pre-font-size); + line-height: 1.5385; + color: var(--el-pre-color); + + background: var(--el-pre-background); + } + + code { + padding: 0.1em 0.3em; + + font-family: var(--font-mono), monospace; + font-size: var(--typo-size-sm); + color: var(--color-text-inverse); + + background: var(--color-surface-inverse); + } + + kbd { + padding: 0.1em 0.3em; + border: 1px solid var(--color-text-primary); + border-radius: 2px; + + font-family: var(--font-mono), monospace; + font-size: var(--typo-size-xs); + color: var(--color-text-inverse); + text-transform: uppercase; + + background: var(--color-surface-inverse); + } + + samp { + padding: 0.1em 0.3em; + border-left: var(--size-1) solid var(--color-text-tertiary); + + font-family: var(--font-mono), monospace; + font-size: var(--typo-size-sm); + color: var(--color-text-primary); + + background: var(--color-surface-elevated-2); + } + + var { + font-family: var(--font-mono), monospace; + font-weight: 600; + font-style: normal; + color: var(--color-text-secondary); + } + + /* === Lists === */ + + ul, + ol { + margin-block: var(--el-list-vspace-top) var(--el-list-vspace-bottom); + font-size: var(--el-list-font-size); + line-height: var(--typo-leading-normal); + color: var(--el-list-color); + } + + ul ul, + ul ol, + ol ul, + ol ol { + margin-block: var(--el-list-nested-vspace-top) + var(--el-list-nested-vspace-bottom); + } + + li { + margin-block: var(--el-li-vspace-top) var(--el-li-vspace-bottom); + + li { + margin-block: var(--el-li-nested-vspace-top) + var(--el-li-nested-vspace-bottom); + } + } + + ul { + padding-left: var(--spacing-cozy); + list-style: none; + + li { + padding-left: var(--spacing-cozy); + + &::marker { + content: '⎊'; + color: var(--color-text-primary); + } + } + + ul, + ol { + padding-left: var(--spacing-cozy); + } + + ul li::marker { + content: '⋊'; + color: var(--color-text-primary); + } + + ul ul, + ul ol, + ol ul, + ol ol { + padding-left: var(--spacing-cozy); + } + + ul ul li::marker, + ol ul li::marker { + content: '◆'; + color: var(--color-text-primary); + } + + ul ul ul, + ul ul ol, + ul ol ul, + ul ol ol, + ol ul ul, + ol ul ol, + ol ol ul, + ol ol ol { + padding-left: var(--spacing-cozy); + } + + ul ul ul li::marker, + ul ol ul li::marker, + ol ul ul li::marker, + ol ol ul li::marker { + content: '⯀'; + color: var(--color-text-primary); + } + } + + ol { + counter-reset: ol-l1; + contain: style; + padding-left: var(--spacing-cozy); + list-style: none; + + & > li { + counter-increment: ol-l1; + margin-left: 1.5em; + padding-left: var(--spacing-cozy); + + &::marker { + content: counter(ol-l1, decimal-leading-zero) '.)'; + color: var(--color-text-primary); + } + } + } + + ol > li > ol { + counter-reset: ol-l2; + padding-left: var(--spacing-cozy); + + & > li { + counter-increment: ol-l2; + margin-left: 0.825em; + + &::marker { + content: counter(ol-l2, lower-alpha) '.)'; + color: var(--color-text-primary); + } + } + } + + ol > li > ul { + padding-left: var(--spacing-cozy); + } + + ol > li > ol > li > ol, + ol > li > ul > li > ol { + counter-reset: ol-l3; + margin-left: 0; + padding-left: var(--spacing-cozy); + + & > li { + counter-increment: ol-l3; + + &::marker { + content: counter(ol-l3, upper-roman) '.)'; + color: var(--color-text-primary); + } + } + } + + ol > li > ol > li > ul, + ol > li > ul > li > ul { + padding-left: var(--spacing-cozy); + } + + ol > li > ol > li > ol > li > ol, + ol > li > ol > li > ul > li > ol, + ol > li > ul > li > ol > li > ol, + ol > li > ul > li > ul > li > ol { + counter-reset: ol-l4; + margin-left: 0; + padding-left: var(--spacing-cozy); + + & > li { + counter-increment: ol-l4; + + &::marker { + content: counter(ol-l4, lower-greek) '.)'; + color: var(--color-text-primary); + } + } + } + + ol > li > ol > li > ol > li > ul, + ol > li > ol > li > ul > li > ul, + ol > li > ul > li > ol > li > ul, + ol > li > ul > li > ul > li > ul { + padding-left: var(--spacing-cozy); + } + + ol li, + ul li { + list-style-position: outside; + } + + .list-inside ol li, + .list-inside ul li { + list-style-position: inside; + } + + /* === Tables === */ + + table { + border-collapse: collapse; + + width: 100%; + margin-block: var(--spacing-tight) var(--spacing-tight); + border: var(--size-2) solid var(--color-text-primary); + + font-size: var(--typo-size-md); + line-height: 1.2; + + & thead th, + & th { + padding: 0 var(--spacing-snug) var(--spacing-snug); + + font-family: var(--el-th-font-family), serif; + font-size: var(--typo-size-sm); + font-weight: 900; + line-height: 1.2; + color: var(--el-th-color); + text-transform: uppercase; + + background: var(--el-th-background); + } + + & tbody td, + & td { + padding: var(--spacing-snug); + border: var(--size-1) solid var(--color-text-secondary); + + font-family: var(--el-td-font-family), monospace; + font-size: var(--typo-size-sm); + line-height: 1.2; + color: var(--el-td-color); + text-align: center; + } + } + + /* === DL / DT / DD === */ + + dl { + margin-block: calc(1em * var(--typo-leading-normal) * var(--vspace-snug)) + calc(1em * var(--typo-leading-normal) * var(--vspace-compressed)); + font-size: var(--typo-size-md); + line-height: var(--typo-leading-normal); + } + + dt { + margin-block: calc(1em * 1.4 * var(--vspace-snug)) + calc(1em * 1.4 * var(--vspace-compressed)); + padding: var(--spacing-snug); + + font-family: var(--el-dt-font-family), serif; + font-size: var(--typo-size-lg); + font-weight: 700; + line-height: 1.4; + color: var(--el-dt-color); + text-transform: uppercase; + letter-spacing: 0.035em; + + background: var(--el-dt-background); + } + + dd { + margin-block: calc( + 1em * var(--typo-leading-normal) * var(--vspace-compressed) + ) + calc(1em * var(--typo-leading-normal) * var(--vspace-tight)); + padding: 0 var(--spacing-comfortable); + + font-family: var(--el-dd-font-family), sans-serif; + font-size: var(--typo-size-md); + line-height: var(--typo-leading-normal); + color: var(--el-dd-color); + } + + /* === HR === */ + + hr { + position: relative; + + overflow: visible; + + height: var(--size-3); + margin-block: var(--spacing-relaxed) 0; + border: none; + + background: var(--hr-color); + + &::after { + content: '▼'; + + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + + padding: 0 0.25em; + + font-size: var(--typo-size-4xl); + line-height: var(--typo-leading-compressed); + color: var(--hr-symbol-color); + + background: var(--hr-symbol-background); + } + } + + /* === Inline Elements === */ + + em, + i { + font-style: italic; + letter-spacing: 0.025em; + } + + strong, + b { + font-weight: 900; + letter-spacing: 0.025em; + } + + a { + position: relative; + + padding: 0.1em 0.2em; + + font-weight: 600; + color: var(--color-text-primary); + text-decoration: underline; + text-decoration-thickness: var(--size-1); + text-underline-offset: 2px; + + transition: + color 0.5s ease-in-out, + background 0.5s ease-in-out; + + &:hover { + cursor: pointer; + color: var(--color-surface-base); + text-decoration: none; + background: var(--color-text-primary); + } + + &:visited, + &:active { + color: var(--color-primary-emphasis); + } + } + + small { + font-size: var(--typo-size-xs); + color: var(--color-text-tertiary); + } + + sub, + sup { + font-size: 0.5625em; + font-weight: 600; + color: var(--color-text-secondary); + } + + del, + s { + color: var(--color-text-tertiary); + text-decoration: line-through; + text-decoration-thickness: var(--size-1); + } + + ins { + font-weight: 600; + color: var(--color-text-primary); + text-decoration: underline; + text-decoration-color: var(--color-primary); + text-decoration-thickness: var(--size-1); + + background: transparent; + } + + abbr { + cursor: help; + text-decoration: underline dotted; + text-underline-offset: var(--size-1); + } + + dfn { + font-weight: 700; + font-style: normal; + color: var(--color-text-primary); + } + + cite { + font-weight: 600; + font-style: normal; + color: var(--color-text-secondary); + } + + q { + font-style: normal; + + &::before { + content: '»'; + } + + &::after { + content: '«'; + } + } + + time { + font-family: var(--font-mono), monospace; + font-size: var(--typo-size-sm); + color: var(--color-text-secondary); + } + + /* === Article Lead Paragraph === */ + + & article { + & > p:first-of-type { + font-size: var(--typo-size-xl); + font-weight: 700; + line-height: 1.4; + letter-spacing: 0.022em; + + &::first-letter { + float: left; + + margin: 0.1em 0.1em 0 0; + padding: 0; + + font-family: var(--font-display), serif; + font-size: 4em; + font-weight: bold; + line-height: 1; + color: var(--color-primary); + + @supports (initial-letter: 4) { + float: none; + + margin: 0; + padding-right: var(--spacing-snug); + + font-size: inherit; + line-height: inherit; + + initial-letter: 3; + } + } + } + } +} diff --git a/src/styles/base/content.css b/src/styles/base/content.css index 231cfce..b402005 100644 --- a/src/styles/base/content.css +++ b/src/styles/base/content.css @@ -1,46 +1,11 @@ .content { - @mixin responsive-wrapper; font-family: var(--font-body); - /* === Headings === */ - & h1 { - margin-block: var(--el-h1-vspace-top) var(--el-h1-vspace-bottom); - padding-bottom: var(--spacing-snug); - border-bottom: var(--size-4) solid var(--el-h1-color); - - font-family: var(--el-h1-font-family), serif; - font-size: var(--el-h1-font-size); - font-weight: 400; - line-height: var(--typo-leading-tight); - color: var(--el-h1-color); - text-transform: uppercase; - letter-spacing: -0.0137em; - - & + p, - & + ul, - & + ol, - & + blockquote { - margin-block: calc(1em * var(--typo-leading-normal) * var(--vspace-tight)) - calc(1em * var(--typo-leading-normal) * var(--vspace-snug)); - } - - & + h2 { - margin-block: calc(1em * 1.125 * var(--vspace-snug)) - calc(1em * 1.125 * var(--vspace-normal)); - } - } + font-size: var(--typo-size-responsive); & h2 { - margin-block: var(--el-h2-vspace-top) var(--el-h2-vspace-bottom); - padding-left: var(--spacing-snug); - border-left: var(--size-4) solid var(--el-h2-color); - - font-family: var(--el-h2-font-family), serif; - font-size: var(--el-h2-font-size); - font-weight: 900; - line-height: 1.1765; - color: var(--el-h2-color); - text-transform: uppercase; - letter-spacing: -0.0096em; + @mixin heading-2; + @mixin pl var(--spacing-snug); + @mixin border-l var(--size-4), solid, var(--el-h2-color); & + p, & + ul, @@ -57,595 +22,47 @@ } & h3 { - margin-block: var(--el-h3-vspace-top) var(--el-h3-vspace-bottom); - padding: var(--spacing-tight) var(--spacing-snug); + @mixin heading-3; + @mixin py var(--spacing-tight); + @mixin px var(--spacing-snug); - font-family: var(--el-h3-font-family), serif; - font-size: var(--el-h3-font-size); - font-weight: 800; - line-height: 1.2; - color: var(--color-surface-base); - text-transform: uppercase; - letter-spacing: -0.004em; - - background: var(--el-h3-color); + color: var(--color-text-inverse); + background: var(--color-surface-inverse); } & h4 { - margin-block: var(--el-h4-vspace-top) var(--el-h4-vspace-bottom); - padding: var(--spacing-tight) var(--spacing-snug); - border-top: var(--size-3) solid var(--el-h4-color); - border-bottom: var(--size-3) solid var(--el-h4-color); + @mixin heading-4; + @mixin py var(--spacing-tight); + @mixin px var(--spacing-snug); + @mixin border-t var(--size-3), solid, var(--el-h4-color); + @mixin border-b var(--size-3), solid, var(--el-h4-color); - font-family: var(--el-h4-font-family), serif; - font-size: var(--el-h4-font-size); - font-weight: 800; - line-height: 1.125; - text-transform: uppercase; - letter-spacing: 0.0025em; + color: var(--el-h4-color); } & h5 { - margin-block: var(--el-h5-vspace-top) var(--el-h5-vspace-bottom); - padding: var(--spacing-tight) var(--spacing-snug); + @mixin heading-5; + @mixin py var(--spacing-tight); + @mixin px var(--spacing-snug); - font-family: var(--el-h5-font-family), serif; - font-size: var(--el-h5-font-size); - font-weight: 800; - line-height: 1.28; color: var(--el-h5-color); - text-transform: uppercase; - letter-spacing: 0.05em; &::before, &::after { - content: ''; - padding-right: var(--spacing-tight); - line-height: 1; - } + @mixin pr var(--spacing-tight); - &::before { - content: '⭑'; - } - - &::after { - content: ''; - } - } - - & h6 { - margin-block: var(--el-h6-vspace-top) var(--el-h6-vspace-bottom); - - font-family: var(--el-h6-font-family), serif; - font-size: var(--el-h6-font-size); - font-weight: 900; - line-height: 1.4; - color: var(--el-h6-color); - text-transform: uppercase; - letter-spacing: 0.035em; - } - - & h3, - & h4, - & h5, - & h6 { - & + p, - & + ul, - & + ol, - & + blockquote { - margin-block: calc( - 1em * var(--typo-leading-normal) * var(--vspace-compressed) - ) - calc(1em * var(--typo-leading-normal) * var(--vspace-snug)); - } - } - - /* === Body Text === */ - - & p { - margin-block: var(--el-p-vspace-top) var(--el-p-vspace-bottom); - - font-family: var(--el-p-font-family), sans-serif; - font-size: var(--el-p-font-size); - font-weight: 400; - line-height: var(--typo-leading-normal); - color: var(--el-p-color); - text-align: justify; - } - - & blockquote { - margin-block: var(--el-p-vspace-top) var(--el-p-vspace-bottom); - padding: var(--spacing-snug) 0 var(--spacing-snug) - var(--spacing-comfortable); - border-left: var(--size-4) solid var(--color-text-tertiary); - - font-family: var(--el-blockquote-font-family), serif; - font-size: var(--el-blockquote-font-size); - font-weight: 500; - font-style: normal; - line-height: var(--typo-leading-comfortable); - color: var(--el-blockquote-color); - } - - /* === Code === */ - - pre { - margin-block: var(--el-pre-vspace-top) var(--el-pre-vspace-bottom); - padding: var(--spacing-comfortable); - - font-family: var(--el-pre-font-family), monospace; - font-size: var(--el-pre-font-size); - line-height: 1.5385; - color: var(--el-pre-color); - - background: var(--el-pre-background); - } - - code { - padding: 0.1em 0.3em; - - font-family: var(--font-mono), monospace; - font-size: var(--typo-size-sm); - color: var(--color-text-inverse); - - background: var(--color-surface-inverse); - } - - kbd { - padding: 0.1em 0.3em; - border: 1px solid var(--color-text-primary); - border-radius: 2px; - - font-family: var(--font-mono), monospace; - font-size: var(--typo-size-xs); - color: var(--color-text-inverse); - text-transform: uppercase; - - background: var(--color-surface-inverse); - } - - samp { - padding: 0.1em 0.3em; - border-left: var(--size-1) solid var(--color-text-tertiary); - - font-family: var(--font-mono), monospace; - font-size: var(--typo-size-sm); - color: var(--color-text-primary); - - background: var(--color-surface-elevated-2); - } - - var { - font-family: var(--font-mono), monospace; - font-weight: 600; - font-style: normal; - color: var(--color-text-secondary); - } - - /* === Lists === */ - - ul, - ol { - margin-block: var(--el-list-vspace-top) var(--el-list-vspace-bottom); - font-size: var(--el-list-font-size); - line-height: var(--typo-leading-normal); - color: var(--el-list-color); - } - - ul ul, - ul ol, - ol ul, - ol ol { - margin-block: var(--el-list-nested-vspace-top) - var(--el-list-nested-vspace-bottom); - } - - li { - margin-block: var(--el-li-vspace-top) var(--el-li-vspace-bottom); - - li { - margin-block: var(--el-li-nested-vspace-top) - var(--el-li-nested-vspace-bottom); - } - } - - ul { - padding-left: var(--spacing-cozy); - list-style: none; - - li { - padding-left: var(--spacing-cozy); - - &::marker { - content: '⎊'; - color: var(--color-text-primary); - } - } - - ul, - ol { - padding-left: var(--spacing-cozy); - } - - ul li::marker { - content: '⋊'; - color: var(--color-text-primary); - } - - ul ul, - ul ol, - ol ul, - ol ol { - padding-left: var(--spacing-cozy); - } - - ul ul li::marker, - ol ul li::marker { - content: '◆'; - color: var(--color-text-primary); - } - - ul ul ul, - ul ul ol, - ul ol ul, - ul ol ol, - ol ul ul, - ol ul ol, - ol ol ul, - ol ol ol { - padding-left: var(--spacing-cozy); - } - - ul ul ul li::marker, - ul ol ul li::marker, - ol ul ul li::marker, - ol ol ul li::marker { - content: '⯀'; - color: var(--color-text-primary); - } - } - - ol { - counter-reset: ol-l1; - contain: style; - padding-left: var(--spacing-cozy); - list-style: none; - - & > li { - counter-increment: ol-l1; - margin-left: 1.5em; - padding-left: var(--spacing-cozy); - - &::marker { - content: counter(ol-l1, decimal-leading-zero) '.)'; - color: var(--color-text-primary); - } - } - } - - ol > li > ol { - counter-reset: ol-l2; - padding-left: var(--spacing-cozy); - - & > li { - counter-increment: ol-l2; - margin-left: 0.825em; - - &::marker { - content: counter(ol-l2, lower-alpha) '.)'; - color: var(--color-text-primary); - } - } - } - - ol > li > ul { - padding-left: var(--spacing-cozy); - } - - ol > li > ol > li > ol, - ol > li > ul > li > ol { - counter-reset: ol-l3; - margin-left: 0; - padding-left: var(--spacing-cozy); - - & > li { - counter-increment: ol-l3; - - &::marker { - content: counter(ol-l3, upper-roman) '.)'; - color: var(--color-text-primary); - } - } - } - - ol > li > ol > li > ul, - ol > li > ul > li > ul { - padding-left: var(--spacing-cozy); - } - - ol > li > ol > li > ol > li > ol, - ol > li > ol > li > ul > li > ol, - ol > li > ul > li > ol > li > ol, - ol > li > ul > li > ul > li > ol { - counter-reset: ol-l4; - margin-left: 0; - padding-left: var(--spacing-cozy); - - & > li { - counter-increment: ol-l4; - - &::marker { - content: counter(ol-l4, lower-greek) '.)'; - color: var(--color-text-primary); - } - } - } - - ol > li > ol > li > ol > li > ul, - ol > li > ol > li > ul > li > ul, - ol > li > ul > li > ol > li > ul, - ol > li > ul > li > ul > li > ul { - padding-left: var(--spacing-cozy); - } - - ol li, - ul li { - list-style-position: outside; - } - - .list-inside ol li, - .list-inside ul li { - list-style-position: inside; - } - - /* === Tables === */ - - table { - border-collapse: collapse; - - width: 100%; - margin-block: var(--spacing-tight) var(--spacing-tight); - border: var(--size-2) solid var(--color-text-primary); - - font-size: var(--typo-size-md); - line-height: 1.2; - - & thead th, - & th { - padding: 0 var(--spacing-snug) var(--spacing-snug); - - font-family: var(--el-th-font-family), serif; - font-size: var(--typo-size-sm); - font-weight: 900; - line-height: 1.2; - color: var(--el-th-color); - text-transform: uppercase; - - background: var(--el-th-background); - } - - & tbody td, - & td { - padding: var(--spacing-snug); - border: var(--size-1) solid var(--color-text-secondary); - - font-family: var(--el-td-font-family), monospace; - font-size: var(--typo-size-sm); - line-height: 1.2; - color: var(--el-td-color); - text-align: center; - } - } - - /* === DL / DT / DD === */ - - dl { - margin-block: calc(1em * var(--typo-leading-normal) * var(--vspace-snug)) - calc(1em * var(--typo-leading-normal) * var(--vspace-compressed)); - font-size: var(--typo-size-md); - line-height: var(--typo-leading-normal); - } - - dt { - margin-block: calc(1em * 1.4 * var(--vspace-snug)) - calc(1em * 1.4 * var(--vspace-compressed)); - padding: var(--spacing-snug); - - font-family: var(--el-dt-font-family), serif; - font-size: var(--typo-size-lg); - font-weight: 700; - line-height: 1.4; - color: var(--el-dt-color); - text-transform: uppercase; - letter-spacing: 0.035em; - - background: var(--el-dt-background); - } - - dd { - margin-block: calc( - 1em * var(--typo-leading-normal) * var(--vspace-compressed) - ) - calc(1em * var(--typo-leading-normal) * var(--vspace-tight)); - padding: 0 var(--spacing-comfortable); - - font-family: var(--el-dd-font-family), sans-serif; - font-size: var(--typo-size-md); - line-height: var(--typo-leading-normal); - color: var(--el-dd-color); - } - - /* === HR === */ - - hr { - position: relative; - - overflow: visible; - - height: var(--size-3); - margin-block: var(--spacing-relaxed) 0; - border: none; - - background: var(--hr-color); - - &::after { - content: '▼'; - - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - - padding: 0 0.25em; - - font-size: var(--typo-size-4xl); + content: ""; line-height: var(--typo-leading-compressed); - color: var(--hr-symbol-color); - - background: var(--hr-symbol-background); } - } - - /* === Inline Elements === */ - - em, - i { - font-style: italic; - letter-spacing: 0.025em; - } - - strong, - b { - font-weight: 900; - letter-spacing: 0.025em; - } - - a { - position: relative; - - padding: 0.1em 0.2em; - - font-weight: 600; - color: var(--color-text-primary); - text-decoration: underline; - text-decoration-thickness: var(--size-1); - text-underline-offset: 2px; - - transition: - color 0.5s ease-in-out, - background 0.5s ease-in-out; - - &:hover { - cursor: pointer; - color: var(--color-surface-base); - text-decoration: none; - background: var(--color-text-primary); - } - - &:visited, - &:active { - color: var(--color-primary-emphasis); - } - } - - small { - font-size: var(--typo-size-xs); - color: var(--color-text-tertiary); - } - - sub, - sup { - font-size: 0.5625em; - font-weight: 600; - color: var(--color-text-secondary); - } - - del, - s { - color: var(--color-text-tertiary); - text-decoration: line-through; - text-decoration-thickness: var(--size-1); - } - - ins { - font-weight: 600; - color: var(--color-text-primary); - text-decoration: underline; - text-decoration-color: var(--color-primary); - text-decoration-thickness: var(--size-1); - - background: transparent; - } - - abbr { - cursor: help; - text-decoration: underline dotted; - text-underline-offset: var(--size-1); - } - - dfn { - font-weight: 700; - font-style: normal; - color: var(--color-text-primary); - } - - cite { - font-weight: 600; - font-style: normal; - color: var(--color-text-secondary); - } - - q { - font-style: normal; &::before { - content: '»'; - } - - &::after { - content: '«'; + content: '▼'; } } - time { - font-family: var(--font-mono), monospace; - font-size: var(--typo-size-sm); - color: var(--color-text-secondary); - } + & h6 { + @mixin heading-6; - /* === Article Lead Paragraph === */ - - & article { - & > p:first-of-type { - font-size: var(--typo-size-xl); - font-weight: 700; - line-height: 1.4; - letter-spacing: 0.022em; - - &::first-letter { - float: left; - - margin: 0.1em 0.1em 0 0; - padding: 0; - - font-family: var(--font-display), serif; - font-size: 4em; - font-weight: bold; - line-height: 1; - color: var(--color-primary); - - @supports (initial-letter: 4) { - float: none; - - margin: 0; - padding-right: var(--spacing-snug); - - font-size: inherit; - line-height: inherit; - - initial-letter: 3; - } - } - } + color: var(--el-h6-color); } } diff --git a/src/styles/base/dimensions.css b/src/styles/base/dimensions.css index 0e135f5..3c73bb5 100644 --- a/src/styles/base/dimensions.css +++ b/src/styles/base/dimensions.css @@ -91,9 +91,5 @@ --spacing-generous: var(--size-16); --spacing-luxurious: var(--size-24); --spacing-expansive: var(--size-32); - - /* == Responsive Content Dimensions */ - --layout-max-width: 90rem; - --content-max-width: 75ch; } } diff --git a/src/styles/base/elements.css b/src/styles/base/elements.css index 76be2b9..05dbc4f 100644 --- a/src/styles/base/elements.css +++ b/src/styles/base/elements.css @@ -4,43 +4,49 @@ --el-h1-color: var(--color-text-primary); --el-h1-font-family: var(--font-display); --el-h1-font-size: var(--typo-size-7xl); + --el-h1-leading: 1.125; --el-h2-color: var(--color-text-primary); --el-h2-font-family: var(--font-header); --el-h2-font-size: var(--typo-size-5xl); + --el-h2-leading: 1.1765; --el-h3-color: var(--color-text-secondary); --el-h3-font-family: var(--font-header); --el-h3-font-size: var(--typo-size-4xl); + --el-h3-leading: 1.2; --el-h4-color: var(--color-text-secondary); --el-h4-font-family: var(--font-header); --el-h4-font-size: var(--typo-size-3xl); + --el-h4-leading: 1.125; --el-h5-color: var(--color-text-secondary); --el-h5-font-family: var(--font-header); --el-h5-font-size: var(--typo-size-2xl); + --el-h5-leading: 1.28; --el-h6-color: var(--color-text-secondary); --el-h6-font-family: var(--font-header); --el-h6-font-size: var(--typo-size-xl); + --el-h6-leading: 1.4; /* === Heading Vertical Spacing === */ - --el-h1-vspace-base: calc(1em * 1.125); + --el-h1-vspace-base: calc(1em * var(--el-h1-leading)); --el-h1-vspace-top: calc(var(--el-h1-vspace-base) * var(--vspace-snug)); --el-h1-vspace-bottom: calc( var(--el-h1-vspace-base) * var(--vspace-compressed) ); - --el-h2-vspace-base: calc(1em * 1.1765); + --el-h2-vspace-base: calc(1em * var(--el-h2-leading)); --el-h2-vspace-top: calc(var(--el-h2-vspace-base) * var(--vspace-snug)); --el-h2-vspace-bottom: calc( var(--el-h2-vspace-base) * var(--vspace-compressed) ); - --el-h3-vspace-base: calc(1em * 1.2); + --el-h3-vspace-base: calc(1em * var(--el-h3-leading)); --el-h3-vspace-top: calc(var(--el-h3-vspace-base) * var(--vspace-cozy)); --el-h3-vspace-bottom: calc(var(--el-h3-vspace-base) * var(--vspace-snug)); - --el-h4-vspace-base: calc(1em * 1.125); + --el-h4-vspace-base: calc(1em * var(--el-h4-leading)); --el-h4-vspace-top: calc(var(--el-h4-vspace-base) * var(--vspace-normal)); --el-h4-vspace-bottom: calc(var(--el-h4-vspace-base) * var(--vspace-tight)); - --el-h5-vspace-base: calc(1em * 1.28); + --el-h5-vspace-base: calc(1em * var(--el-h5-leading)); --el-h5-vspace-top: calc(var(--el-h5-vspace-base) * var(--vspace-cozy)); --el-h5-vspace-bottom: calc(var(--el-h5-vspace-base) * var(--vspace-tight)); - --el-h6-vspace-base: calc(1em * 1.4); + --el-h6-vspace-base: calc(1em * var(--el-h6-leading)); --el-h6-vspace-top: calc(var(--el-h6-vspace-base) * var(--vspace-snug)); --el-h6-vspace-bottom: calc( var(--el-h6-vspace-base) * var(--vspace-compressed) @@ -119,18 +125,3 @@ --hr-symbol-color: var(--color-text-tertiary); --hr-symbol-background: var(--color-surface-base); } - -.responsivewrapper { - max-width: clamp(60ch, 90vw, 90ch); - margin-inline: auto; - padding: 0 var(--spacing-cozy); -} - -.layoutwrapper { - width: 100%; - margin-inline: auto; - - @media screen and (--max-layout) { - padding-inline: var(--spacing-comfortable); - } -} diff --git a/src/styles/base/ui.css b/src/styles/base/ui.css index aeac701..00ca7fe 100644 --- a/src/styles/base/ui.css +++ b/src/styles/base/ui.css @@ -25,11 +25,16 @@ --ui-typo-size-5xl: 2rem; /* === MastHead === */ - --el-masthead-font-size: var(--ui-font-size-xl); - --el-masthead-line-height: var(--typo-leading-snug); - --el-masthead-paddingY: var(--ui-spacing-relaxed); - --el-masthead-height: calc( - (var(--el-masthead-font-size) * var(--el-masthead-line-height)) + - (var(--el-masthead-paddingY) * 2) + --ui-masthead-font-size: var(--ui-font-size-xl); + --ui-masthead-line-height: var(--typo-leading-snug); + --ui-masthead-paddingY: var(--ui-spacing-relaxed); + --ui-masthead-height: calc( + (var(--ui-masthead-font-size) * var(--ui-masthead-line-height)) + + (var(--ui-masthead-paddingY) * 2) ); + + /* === Content/Marginalia === */ + --ui-content-width: minmax(0, 72ch); + --ui-margin-width: minmax(18ch, 1fr); + --ui-layout-width: 90rem; } diff --git a/src/styles/mixins/containers.css b/src/styles/mixins/containers.css index e53fa02..d529d52 100644 --- a/src/styles/mixins/containers.css +++ b/src/styles/mixins/containers.css @@ -11,8 +11,9 @@ @define-mixin layout-wrapper { @mixin mx auto; @mixin px var(--spacing-comfortable); + width: 100%; - max-width: var(--layout-max-width); + max-width: var(--ui-layout-width); @media screen and (--max-layout) { @mixin px var(--spacing-comfortable); diff --git a/src/styles/mixins/typography.css b/src/styles/mixins/typography.css new file mode 100644 index 0000000..72fc5be --- /dev/null +++ b/src/styles/mixins/typography.css @@ -0,0 +1,73 @@ +@define-mixin heading-1 { + @mixin mt var(--el-h1-vspace-top); + @mixin mb var(--el-h1-vspace-bottom); + @mixin pb var(--spacing-snug); + + font-family: var(--el-h1-font-family); + font-size: var(--el-h1-font-size); + font-weight: 400; + line-height: var(--el-h1-leading); + color: var(--el-h1-color); + text-transform: uppercase; + letter-spacing: -0.0137em; +} + +@define-mixin heading-2 { + @mixin mt var(--el-h2-vspace-top); + @mixin mb var(--el-h2-vspace-bottom); + + font-family: var(--el-h2-font-family); + font-size: var(--el-h2-font-size); + font-weight: 900; + line-height: var(--el-h2-leading); + text-transform: uppercase; + letter-spacing: -0.0096em; +} + +@define-mixin heading-3 { + @mixin mt var(--el-h3-vspace-top); + @mixin mb var(--el-h3-vspace-bottom); + + font-family: var(--el-h3-font-family); + font-size: var(--el-h3-font-size); + font-weight: 800; + line-height: var(--el-h3-leading); + text-transform: uppercase; + letter-spacing: -0.004em; +} + +@define-mixin heading-4 { + @mixin mt var(--el-h4-vspace-top); + @mixin mb var(--el-h4-vspace-bottom); + + font-family: var(--el-h4-font-family); + font-size: var(--el-h4-font-size); + font-weight: 800; + line-height: var(--el-h4-leading); + text-transform: uppercase; + letter-spacing: 0.0025em; +} + +@define-mixin heading-5 { + @mixin mt var(--el-h5-vspace-top); + @mixin mb var(--el-h5-vspace-bottom); + + font-family: var(--el-h5-font-family); + font-size: var(--el-h5-font-size); + font-weight: 800; + line-height: var(--el-h5-leading); + text-transform: uppercase; + letter-spacing: 0.05em; +} + +@define-mixin heading-6 { + @mixin mt var(--el-h6-vspace-top); + @mixin mb var(--el-h6-vspace-bottom); + + font-family: var(--el-h6-font-family); + font-size: var(--el-h6-font-size); + font-weight: 900; + line-height: var(--el-h6-leading); + text-transform: uppercase; + letter-spacing: 0.035em; +}