diff --git a/app/globals.css b/app/globals.css index 6eea0cd..fd9e750 100644 --- a/app/globals.css +++ b/app/globals.css @@ -175,6 +175,148 @@ padding: 2rem; } +/* === Local prose styles (Tailwind Typography plugin is not installed) === */ +.prose { + color: var(--color-ink); + font-size: 1rem; + line-height: 1.75; + overflow-wrap: break-word; +} + +.prose :where(h1, h2, h3, h4, h5, h6) { + color: var(--color-ink); + scroll-margin-top: 96px; +} + +.prose :where(h1) { margin: 2.75rem 0 1rem; } +.prose :where(h2) { margin: 3rem 0 1rem; padding-bottom: 0.5rem; border-bottom: 1px solid var(--color-border); } +.prose :where(h3) { margin: 2.25rem 0 0.75rem; } +.prose :where(h4, h5, h6) { margin: 1.75rem 0 0.5rem; } +.prose :where(h1, h2, h3, h4, h5, h6):first-child { margin-top: 0; } + +.prose :where(p) { + margin: 1.25rem 0; + color: var(--color-ink); +} + +.prose :where(a) { + color: var(--color-accent); + text-decoration-thickness: 1px; +} + +.prose :where(ul, ol) { + margin: 1.5rem 0; + padding-left: 1.5rem; +} + +.prose :where(li) { margin: 0.45rem 0; padding-left: 0.2rem; } +.prose :where(li)::marker { color: var(--color-accent); } +.prose :where(li > p) { margin: 0.5rem 0; } + +.prose :where(blockquote) { + margin: 2rem 0; + border-left: 4px solid color-mix(in oklch, var(--color-accent) 45%, var(--color-border)); + border-radius: 0 1rem 1rem 0; + background: color-mix(in oklch, var(--color-surface) 70%, transparent); + padding: 0.75rem 1rem 0.75rem 1.25rem; + color: var(--color-ink-soft); +} + +.prose :where(blockquote p) { margin: 0.5rem 0; } + +.prose :where(.callout, [data-callout]) { + margin: 2rem 0; + border: 1px solid color-mix(in oklch, var(--color-accent) 28%, var(--color-border)); + border-radius: 1rem; + background: color-mix(in oklch, var(--color-accent) 8%, var(--color-surface)); + padding: 1rem; +} + +.prose :where(details) { + margin: 2rem 0; + border: 1px solid var(--color-border); + border-radius: 1rem; + background: color-mix(in oklch, var(--color-surface) 82%, var(--color-canvas)); + padding: 1rem 1.125rem; +} + +.prose :where(summary) { + cursor: pointer; + color: var(--color-ink); + font-weight: 700; +} + +.prose :where(details[open] summary) { margin-bottom: 0.75rem; } +.prose :where(details > :last-child) { margin-bottom: 0; } + +.prose :where(figure) { margin: 2.5rem 0; } + +.prose :where(img) { + display: block; + max-width: min(100%, 56rem); + height: auto; + margin: 2rem auto; + border: 1px solid var(--color-border); + border-radius: 1rem; + background: var(--color-surface); + box-shadow: var(--shadow-card); +} + +.prose :where(p:has(> img:only-child)) { + margin: 2.5rem 0 1rem; +} + +.prose :where(p:has(> img:only-child) + em), +.prose :where(p:has(> img:only-child) + strong) { + display: block; + margin-top: -0.5rem; + text-align: center; + color: var(--color-ink-soft); + font-size: 0.875rem; + line-height: 1.5; +} + +.prose :where(figcaption) { + margin-top: 0.75rem; + color: var(--color-ink-soft); + font-size: 0.875rem; + line-height: 1.5; + text-align: center; +} + +.prose :where(table) { + width: 100%; + min-width: 40rem; + border-collapse: collapse; + color: var(--color-ink); +} + +.prose :where(th, td) { + border: 1px solid var(--color-border); + padding: 0.75rem 0.875rem; + text-align: left; + vertical-align: top; +} + +.prose :where(th) { + background: var(--color-surface); + color: var(--color-ink); + font-weight: 700; +} + +.prose :where(tbody tr:nth-child(even)) { + background: color-mix(in oklch, var(--color-surface) 55%, transparent); +} + +.prose :where(pre) { + max-width: 100%; + overflow-x: auto; +} + +.prose :where(:not(pre) > code) { + color: var(--color-ink); +} + /* === Code Blocks: Borderless, VS Code Style, Line Numbers === */ [data-rehype-pretty-code-figure] { @apply relative overflow-hidden rounded-[var(--radius-code)]; @@ -325,23 +467,24 @@ html.dark code[data-theme*=" "] span { font-size: 1.1em !important; } .katex-display { - overflow: visible; + overflow-x: auto; + overflow-y: hidden; max-width: 100%; - margin: 1.5em 0; + margin: 1.75em 0; + padding: 0.25rem 0 0.6rem; text-align: center; + -webkit-overflow-scrolling: touch; } .katex-display > .katex { - display: block; + display: inline-block; + min-width: max-content; text-align: center; - white-space: normal; + white-space: nowrap; } @media (max-width: 640px) { - .katex-display > .katex { - transform: scale(0.85); - transform-origin: center top; - } .katex-display { - margin: 0.8em 0; + margin: 1.25em 0; + text-align: left; } } .prose p + .katex-display { margin-top: 0.5em; } diff --git a/app/posts/[slug]/page.tsx b/app/posts/[slug]/page.tsx index 281b9f1..b369273 100644 --- a/app/posts/[slug]/page.tsx +++ b/app/posts/[slug]/page.tsx @@ -37,7 +37,7 @@ export default async function PostPage({ params }: { params: Promise<{ slug: str
-
+

@@ -50,9 +50,11 @@ export default async function PostPage({ params }: { params: Promise<{ slug: str {post.coverImage && ( {`Cover )} {post.tags.length > 0 && ( @@ -65,7 +67,7 @@ export default async function PostPage({ params }: { params: Promise<{ slug: str

)} -
+
diff --git a/mdx-components.tsx b/mdx-components.tsx index 64fbb34..d23fbfe 100644 --- a/mdx-components.tsx +++ b/mdx-components.tsx @@ -30,12 +30,12 @@ export function useMDXComponents(components: MDXComponents): MDXComponents {
{children}
), p: ({ children }) => ( -

+

{children}

), blockquote: ({ children }) => ( -
+
{children}
), @@ -75,11 +75,18 @@ export function useMDXComponents(components: MDXComponents): MDXComponents { ), img: ({ src, alt, ...rest }) => ( - {alt} + {alt ), table: ({ children }) => ( -
- +
+
{children}
@@ -91,8 +98,8 @@ export function useMDXComponents(components: MDXComponents): MDXComponents { li: (props) =>
  • , // Figures and captions - figure: (props) =>
    , - figcaption: (props) =>
    , + figure: (props) =>
    , + figcaption: (props) =>
    , // Subscripts and superscripts sup: (props) => , @@ -104,7 +111,7 @@ export function useMDXComponents(components: MDXComponents): MDXComponents { ), // Collapsible sections - details: (props) =>
    , - summary: (props) => , + details: (props) =>
    , + summary: (props) => , } }