diff --git a/public/admin/config.yml b/public/admin/config.yml index 810c193..c206900 100644 --- a/public/admin/config.yml +++ b/public/admin/config.yml @@ -27,6 +27,23 @@ logo: media_folder: "public/uploads" public_folder: "/uploads" +# Keep the git repo lean: images are stored as plain git blobs (no LFS), so +# every upload is converted client-side to WebP q85 and capped at 2048px +# (documented media_libraries transformations). A phone photo lands in the +# repo as ~100-300 KB instead of 5-10 MB. +media_libraries: + default: + config: + slugify_filename: true + transformations: + raster_image: + format: webp + quality: 85 + width: 2048 + height: 2048 + svg: + optimize: true + collections: - name: news label: "News" diff --git a/public/admin/preview.css b/public/admin/preview.css index 990e80c..6509685 100644 --- a/public/admin/preview.css +++ b/public/admin/preview.css @@ -1,24 +1,61 @@ -/* Entry-preview styles for the Sveltia editor (registered via the officially - supported CMS.registerPreviewStyle API). Mirrors the portal's article look - so editors see roughly what readers will see. Kept intentionally tiny. */ +/* Entry-preview styles for the Sveltia editor, registered via the documented + CMS.registerPreviewStyle API (bare element selectors, per the official docs + example). This file MIRRORS the article styles 1:1 — the design tokens from + :root and the `.prose` block in src/styles/global.css — with `.prose` + dropped from selectors (the preview pane has no such wrapper). + KEEP IN SYNC: when you touch `.prose` or the tokens in global.css, update + the corresponding value here (a matching reminder sits next to `.prose`). + Fonts: same families as the site (site inlines them; the preview loads them + from Google Fonts — editors' browsers are online by definition). */ @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400..700&family=Space+Grotesk:wght@500..700&display=swap"); +:root { + /* tokens copied from global.css :root */ + --galaxy: #00004a; + --moon: #f5f5f5; + --text: #101228; + --muted: #46536a; + --border: #e2e5ee; + --link: #0057c2; + --font-body: "Inter", Arial, system-ui, sans-serif; + --font-display: "Space Grotesk", var(--font-body); + --fs-s: 0.9rem; + --fs-l: 1.125rem; + --fs-xl: 1.5rem; + --radius: 16px; +} + +/* preview shell ≈ article column */ body { - font-family: "Inter", Arial, system-ui, sans-serif; - color: #101228; - line-height: 1.65; + font-family: var(--font-body); + color: var(--text); max-width: 70ch; margin: 0 auto; padding: 24px; } -h1, h2 { font-family: "Space Grotesk", "Inter", sans-serif; color: #00004a; } -h3, h4 { color: #00004a; } -a { color: #0057c2; } -img { max-width: 100%; height: auto; border-radius: 16px; } + +/* = global.css base heading/link rules = */ +h1, h2 { font-family: var(--font-display); font-weight: 500; letter-spacing: -0.025em; line-height: 1.1; } +h3 { font-weight: 600; } +h1, h2, h3 { overflow-wrap: break-word; text-wrap: balance; } +a { color: var(--link); text-decoration: underline; text-underline-offset: 3px; } + +/* = global.css `.prose` rules, selectors unwrapped = */ +body { line-height: 1.65; overflow-wrap: break-word; } +h1 { color: var(--galaxy); } +h2 { color: var(--galaxy); margin: 44px 0 12px; font-size: var(--fs-xl); } +h3 { color: var(--galaxy); margin: 30px 0 8px; font-size: var(--fs-l); } +p { margin: 0 0 16px; text-wrap: pretty; } +ul, ol { margin: 0 0 16px; padding-left: 22px; } +li { margin: 6px 0; } blockquote { - margin: 22px 0; padding: 12px 20px; - border-left: 3px solid #00e4d8; background: #f5f5f5; + margin: 22px 0; padding: 12px 20px; border-left: 3px solid var(--galaxy); + background: var(--moon); color: var(--text); } -table { width: 100%; border-collapse: collapse; } -th, td { padding: 10px 12px; border-bottom: 1px solid #e2e5ee; text-align: left; } -thead th { border-bottom: 2px solid #00e4d8; color: #00004a; } +img { max-width: 100%; height: auto; border: 1px solid var(--border); border-radius: var(--radius); } +img + em, p > em:only-child { color: var(--muted); font-size: var(--fs-s); } +hr { border: 0; border-top: 1px solid var(--border); margin: 32px 0; } +table { display: block; width: 100%; overflow-x: auto; border-collapse: collapse; margin: 0 0 16px; font-size: var(--fs-s); } +th { text-align: left; font-weight: 600; color: var(--galaxy); } +th, td { padding: 10px 12px; border-bottom: 1px solid var(--border); } +thead th { border-bottom: 2px solid var(--galaxy); } diff --git a/src/styles/global.css b/src/styles/global.css index d47b3d0..53bb578 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -559,6 +559,8 @@ span.page-step { color: var(--muted); } /* disabled end stop — non-interactive } /* Long unbroken strings (URLs, identifiers) wrap instead of forcing page overflow */ +/* KEEP IN SYNC: public/admin/preview.css mirrors this .prose block (and the + tokens it uses) so the CMS entry preview matches the article 1:1. */ .prose { line-height: 1.65; overflow-wrap: break-word; } .prose a { overflow-wrap: anywhere; } .prose h2 { color: var(--galaxy); margin: 44px 0 12px; font-size: var(--fs-xl); }