repos / pico

pico services - prose.sh, pastes.sh, imgs.sh, feeds.sh, pgs.sh
git clone https://github.com/picosh/pico.git

commit
d94d37a
parent
b9567a1
author
Eric Bower
date
2024-09-03 02:14:52 +0000 UTC
feat(prose): `with_styles` setting in `_readme`

This adds a new frontmatter property in `_readme` that allows users to
request no styles from us.  This allows for better customization in
conjunction with `_styles.css` which is the user-defined CSS stylesheet
that gets loaded.
14 files changed,  +1179, -216
M Makefile
+2, -1
 1@@ -10,7 +10,8 @@ DOCKER_BUILDX_BUILD?=$(DOCKER_CMD) buildx build --push --platform $(DOCKER_PLATF
 2 WRITE?=0
 3 
 4 smol:
 5-	curl https://pico.sh/smol.css -o ./prose/public/smol.css
 6+	curl https://pico.sh/smol.css -o ./prose/public/smol-v2.css
 7+	cat ./prose/artifacts/main.css >> ./prose/public/smol-v2.css
 8 	curl https://pico.sh/smol.css -o ./pastes/public/smol.css
 9 .PHONY: smol
10 
M pastes/public/smol.css
+140, -158
  1@@ -15,9 +15,13 @@
  2   box-shadow: none;
  3 }
  4 
  5+:root {
  6+  --line-height: 1.3rem;
  7+  --grid-height: 0.65rem;
  8+}
  9+
 10 @media (prefers-color-scheme: light) {
 11   :root {
 12-    --main-hue: 250;
 13     --white: #2e3f53;
 14     --white-light: #cfe0f4;
 15     --white-dark: #6c6a6a;
 16@@ -32,13 +36,11 @@
 17     --hover: #c11e7a;
 18     --grey: #ccc;
 19     --grey-light: #6a708e;
 20-    --shadow: #e8e8e8;
 21   }
 22 }
 23 
 24 @media (prefers-color-scheme: dark) {
 25   :root {
 26-    --main-hue: 250;
 27     --white: #f2f2f2;
 28     --white-light: #f2f2f2;
 29     --white-dark: #e8e8e8;
 30@@ -53,15 +55,14 @@
 31     --hover: #ff80bf;
 32     --grey: #414558;
 33     --grey-light: #6a708e;
 34-    --shadow: #252525;
 35   }
 36 }
 37 
 38 html {
 39   background-color: var(--bg-color);
 40   color: var(--text-color);
 41-  font-size: 18px;
 42-  line-height: 1.5;
 43+  font-size: 16px;
 44+  line-height: var(--line-height);
 45   font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
 46     Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Arial,
 47     sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
 48@@ -89,8 +90,7 @@ code,
 49 kbd,
 50 samp,
 51 pre {
 52-  font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo,
 53-    monospace;
 54+  font-family: monospace;
 55 }
 56 
 57 code,
 58@@ -103,19 +103,19 @@ pre > code {
 59   background-color: inherit;
 60   padding: 0;
 61   border: none;
 62+  border-radius: 0;
 63 }
 64 
 65 code {
 66   font-size: 90%;
 67   border-radius: 0.3rem;
 68-  padding: 0.1rem 0.3rem;
 69+  padding: 0.025rem 0.3rem;
 70 }
 71 
 72 pre {
 73-  font-size: 14px;
 74-  border-radius: 5px;
 75-  padding: 1rem;
 76-  margin: 1rem 0;
 77+  font-size: 0.8rem;
 78+  border-radius: 1px;
 79+  padding: var(--line-height);
 80   overflow-x: auto;
 81   background-color: var(--pre) !important;
 82 }
 83@@ -124,6 +124,16 @@ small {
 84   font-size: 0.8rem;
 85 }
 86 
 87+details {
 88+  border: 2px solid var(--grey-light);
 89+  padding: calc(var(--line-height) - 2px) 1ch;
 90+  margin-bottom: var(--line-height);
 91+}
 92+
 93+details[open] summary {
 94+  margin-bottom: var(--line-height);
 95+}
 96+
 97 summary {
 98   display: list-item;
 99   cursor: pointer;
100@@ -134,7 +144,7 @@ h2,
101 h3,
102 h4 {
103   margin: 0;
104-  padding: 0.5rem 0 0 0;
105+  padding: 0;
106   border: 0;
107   font-style: normal;
108   font-weight: inherit;
109@@ -149,11 +159,9 @@ path {
110 hr {
111   color: inherit;
112   border: 0;
113-  margin: 0;
114   height: 2px;
115   background: var(--grey);
116-  margin: 1rem auto;
117-  text-align: center;
118+  margin: calc(var(--grid-height) - 2px) auto;
119 }
120 
121 a {
122@@ -164,22 +172,12 @@ a {
123 a:hover,
124 a:visited:hover {
125   text-decoration: underline;
126-  color: var(--hover);
127 }
128 
129 a:visited {
130   color: var(--visited);
131 }
132 
133-a.link-grey {
134-  text-decoration: underline;
135-  color: var(--white);
136-}
137-
138-a.link-grey:visited {
139-  color: var(--white);
140-}
141-
142 section {
143   margin-bottom: 1.4rem;
144 }
145@@ -193,7 +191,8 @@ header {
146 }
147 
148 p {
149-  margin: 0.5rem 0;
150+  margin-top: var(--line-height);
151+  margin-bottom: var(--line-height);
152 }
153 
154 article {
155@@ -203,8 +202,8 @@ article {
156 blockquote {
157   border-left: 5px solid var(--blockquote);
158   background-color: var(--blockquote-bg);
159-  padding: 0.5rem 0.75rem;
160-  margin: 0.5rem 0;
161+  padding: var(--grid-height);
162+  margin: var(--line-height) 0;
163 }
164 
165 blockquote > p {
166@@ -217,16 +216,28 @@ blockquote code {
167 
168 ul,
169 ol {
170-  padding: 0 0 0 1rem;
171-  list-style-position: outside;
172+  padding: 0 0 0 var(--line-height);
173+  list-style-position: inside;
174+  list-style-type: square;
175+  margin: var(--line-height) 0;
176 }
177 
178 ul[style*="list-style-type: none;"] {
179   padding: 0;
180 }
181 
182+ol ul, ol ol, ul ol, ul ul {
183+  padding: 0 0 0 3ch;
184+  margin: 0;
185+}
186+
187 li {
188-  margin: 0.5rem 0;
189+  margin: 0;
190+  padding: 0;
191+}
192+
193+li::marker {
194+  line-height: 0;
195 }
196 
197 li > pre {
198@@ -235,7 +246,7 @@ li > pre {
199 
200 footer {
201   text-align: center;
202-  margin-bottom: 4rem;
203+  margin-bottom: calc(var(--line-height) * 3);
204 }
205 
206 dt {
207@@ -254,6 +265,10 @@ figure {
208   margin: 0;
209 }
210 
211+#toc {
212+  margin-top: var(--line-height);
213+}
214+
215 .container {
216   max-width: 50em;
217   width: 100%;
218@@ -272,21 +287,7 @@ figure {
219 }
220 
221 .mono {
222-  font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo,
223-    monospace;
224-}
225-
226-.link-alt-adj,
227-.link-alt-adj:visited,
228-.link-alt-adj:visited:hover,
229-.link-alt-adj:hover {
230-  color: var(--link-color);
231-  text-decoration: none;
232-}
233-
234-.link-alt-adj:visited:hover,
235-.link-alt-adj:hover {
236-  text-decoration: underline;
237+  font-family: monospace;
238 }
239 
240 .link-alt-hover,
241@@ -315,36 +316,28 @@ figure {
242   text-decoration: underline;
243 }
244 
245-.text-3xl {
246-  font-size: 2.5rem;
247+.text-2xl code, .text-xl code, .text-lg code, .text-md code {
248+  text-transform: none;
249 }
250 
251 .text-2xl {
252-  font-size: 1.9rem;
253-  line-height: 1.15;
254-}
255-
256-.text-xl {
257-  font-size: 1.55rem;
258-  line-height: 1.15;
259-}
260-
261-.text-lg {
262-  font-size: 1.35rem;
263-  line-height: 1.15;
264+  font-size: var(--line-height);
265+  font-weight: bold;
266+  line-height: var(--line-height);
267+  margin-bottom: var(--grid-height);
268+  text-transform: uppercase;
269 }
270 
271-.text-md {
272-  font-size: 1.15rem;
273-  line-height: 1.15;
274+.text-xl, .text-lg, .text-md {
275+  font-size: 1rem;
276+  font-weight: bold;
277+  line-height: var(--line-height);
278+  margin-bottom: var(--grid-height);
279+  text-transform: uppercase;
280 }
281 
282 .text-sm {
283-  font-size: 0.875rem;
284-}
285-
286-.text-xs {
287-  font-size: 0.775rem;
288+  font-size: 0.8rem;
289 }
290 
291 .cursor-pointer {
292@@ -372,19 +365,14 @@ figure {
293 }
294 
295 .text-underline {
296-  border-bottom: 3px solid var(--text-color);
297-  padding-bottom: 3px;
298+  text-decoration: underline;
299+  text-decoration-thickness: 2px;
300 }
301 
302 .text-hdr {
303   color: var(--hover);
304 }
305 
306-.text-underline-hdr {
307-  border-bottom: 3px solid var(--hover);
308-  padding-bottom: 3px;
309-}
310-
311 .font-bold {
312   font-weight: bold;
313 }
314@@ -429,40 +417,32 @@ figure {
315   margin: 0;
316 }
317 
318+.mt-0 {
319+  margin-top: 0;
320+}
321+
322 .mt {
323-  margin-top: 0.5rem;
324+  margin-top: var(--grid-height);
325 }
326 
327 .mt-2 {
328-  margin-top: 1rem;
329+  margin-top: var(--line-height);
330 }
331 
332 .mt-4 {
333-  margin-top: 2rem;
334-}
335-
336-.mt-8 {
337-  margin-top: 4rem;
338+  margin-top: calc(var(--line-height) * 2);
339 }
340 
341 .mb {
342-  margin-bottom: 0.5rem;
343+  margin-bottom: var(--grid-height);
344 }
345 
346 .mb-2 {
347-  margin-bottom: 1rem;
348+  margin-bottom: var(--line-height);
349 }
350 
351 .mb-4 {
352-  margin-bottom: 2rem;
353-}
354-
355-.mb-8 {
356-  margin-bottom: 4rem;
357-}
358-
359-.mb-16 {
360-  margin-bottom: 8rem;
361+  margin-bottom: calc(var(--line-height) * 2);
362 }
363 
364 .mr {
365@@ -482,23 +462,18 @@ figure {
366 }
367 
368 .my {
369-  margin-top: 0.5rem;
370-  margin-bottom: 0.5rem;
371+  margin-top: var(--grid-height);
372+  margin-bottom: var(--grid-height);
373 }
374 
375 .my-2 {
376-  margin-top: 1rem;
377-  margin-bottom: 1rem;
378+  margin-top: var(--line-height);
379+  margin-bottom: var(--line-height);
380 }
381 
382 .my-4 {
383-  margin-top: 2rem;
384-  margin-bottom: 2rem;
385-}
386-
387-.my-8 {
388-  margin-top: 4rem;
389-  margin-bottom: 4rem;
390+  margin-top: calc(var(--line-height) * 2);
391+  margin-bottom: calc(var(--line-height) * 2);
392 }
393 
394 .mx {
395@@ -512,11 +487,11 @@ figure {
396 }
397 
398 .m-1 {
399-  margin: 0.5rem;
400+  margin: var(--grid-height);
401 }
402 
403 .p-1 {
404-  padding: 0.5rem;
405+  padding: var(--grid-height);
406 }
407 
408 .p-0 {
409@@ -534,23 +509,18 @@ figure {
410 }
411 
412 .py {
413-  padding-top: 0.5rem;
414-  padding-bottom: 0.5rem;
415+  padding-top: var(--grid-height);
416+  padding-bottom: var(--grid-height);
417 }
418 
419 .py-2 {
420-  padding-top: 1rem;
421-  padding-bottom: 1rem;
422+  padding-top: var(--line-height);
423+  padding-bottom: var(--line-height);
424 }
425 
426 .py-4 {
427-  padding-top: 2rem;
428-  padding-bottom: 2rem;
429-}
430-
431-.py-8 {
432-  padding-top: 4rem;
433-  padding-bottom: 4rem;
434+  padding-top: calc(var(--line-height) * 2);
435+  padding-bottom: calc(var(--line-height) * 2);
436 }
437 
438 .justify-between {
439@@ -562,28 +532,28 @@ figure {
440 }
441 
442 .gap {
443-  gap: 0.5rem;
444+  gap: var(--grid-height);
445 }
446 
447 .gap-2 {
448-  gap: 1rem;
449+  gap: var(--line-height);
450 }
451 
452 .group {
453   display: flex;
454   flex-direction: column;
455-  gap: 0.5rem;
456+  gap: var(--grid-height);
457 }
458 
459 .group-2 {
460   display: flex;
461   flex-direction: column;
462-  gap: 1rem;
463+  gap: var(--line-height);
464 }
465 
466 .group-h {
467   display: flex;
468-  gap: 0.5rem;
469+  gap: var(--grid-height);
470   align-items: center;
471 }
472 
473@@ -622,7 +592,8 @@ figure {
474 .md h3,
475 .md h4 {
476   padding: 0;
477-  margin: 1.5rem 0 0.9rem 0;
478+  margin: 0;
479+  /* margin: 1.5rem 0 0.9rem 0; */
480   font-weight: bold;
481 }
482 
483@@ -634,26 +605,24 @@ figure {
484   text-decoration: none;
485 }
486 
487-.md h1 {
488-  font-size: 1.6rem;
489-  line-height: 1.15;
490-  border-bottom: 2px solid var(--grey);
491-  padding-bottom: 0.7rem;
492-}
493-
494-.md h2 {
495-  font-size: 1.3rem;
496-  line-height: 1.15;
497-  color: var(--white-dark);
498+h1 code, h2 code, h3 code, h4 code {
499+  text-transform: none;
500 }
501 
502-.md h3 {
503-  font-size: 1.2rem;
504-  color: var(--white-dark);
505+.md h1 {
506+  font-size: 1rem;
507+  line-height: var(--line-height);
508+  margin-top: calc(var(--line-height) * 2);
509+  margin-bottom: var(--grid-height);
510+  text-transform: uppercase;
511 }
512 
513-.md h4 {
514+.md h2, .md h3, .md h4 {
515   font-size: 1rem;
516+  line-height: var(--line-height);
517+  margin-top: calc(var(--line-height) * 2);
518+  margin-bottom: var(--line-height);
519+  text-transform: uppercase;
520   color: var(--white-dark);
521 }
522 
523@@ -669,8 +638,8 @@ figure {
524   border: 3px solid #FF79C6;
525   padding: 8px 10px 10px 10px;
526   border-radius: 10px;
527-  box-shadow: 0px 5px 0px 0px var(--shadow);
528   background-size: 100%;
529+  margin: 0:
530   -webkit-background-clip: text;
531   -moz-background-clip: text;
532   -webkit-text-fill-color: transparent;
533@@ -689,47 +658,40 @@ figure {
534 .btn-link:visited {
535   border: 2px solid var(--link-color);
536   color: var(--link-color);
537-  padding: 0.4rem 1rem;
538+  padding: var(--grid-height) 1rem;
539   text-decoration: none;
540   font-weight: bold;
541   display: inline-block;
542 }
543 
544-.btn-link:visited:hover,
545-.btn-link:hover {
546-  border: 2px solid var(--hover);
547-}
548-
549-.btn-link-alt,
550-.btn-link-alt:visited {
551-  border: 2px solid var(--white);
552-  color: var(--white);
553-}
554-
555 .box {
556   border: 2px solid var(--grey-light);
557-  padding: 0.5rem 0.75rem;
558+  padding: var(--line-height);
559 }
560 
561 .box-sm {
562   border: 2px solid var(--grey-light);
563-  padding: 0.15rem 0.35rem;
564+  padding: var(--grid-height);
565 }
566 
567 .box-alert {
568   border: 2px solid var(--hover);
569-  padding: 0.5rem 0.75rem;
570+  padding: var(--line-height);
571 }
572 
573 .box-sm-alert {
574   border: 2px solid var(--hover);
575-  padding: 0.15rem 0.35rem;
576+  padding: var(--grid-height);
577 }
578 
579 .list-none {
580   list-style-type: none;
581 }
582 
583+.list-square {
584+  list-style-type: square;
585+}
586+
587 .list-disc {
588   list-style-type: disc;
589 }
590@@ -766,3 +728,23 @@ figure {
591     flex-direction: column;
592   }
593 }
594+
595+#debug {
596+  position: relative;
597+}
598+
599+#debug .debug-grid {
600+  width: 100%;
601+  height: 100%;
602+  position: absolute;
603+  top: 0;
604+  left: 0;
605+  right: 0;
606+  bottom: 0;
607+  z-index: -1;
608+  background-image:
609+    repeating-linear-gradient(var(--code) 0 1px, transparent 1px 100%),
610+    repeating-linear-gradient(90deg, var(--code) 0 1px, transparent 1px 100%);
611+  background-size: 1ch var(--grid-height);
612+  margin: 0;
613+}
M prose/api.go
+43, -34
  1@@ -40,17 +40,18 @@ type PostItemData struct {
  2 }
  3 
  4 type BlogPageData struct {
  5-	Site      shared.SitePageData
  6-	PageTitle string
  7-	URL       template.URL
  8-	RSSURL    template.URL
  9-	Username  string
 10-	Readme    *ReadmeTxt
 11-	Header    *HeaderTxt
 12-	Posts     []PostItemData
 13-	HasCSS    bool
 14-	CssURL    template.URL
 15-	HasFilter bool
 16+	Site       shared.SitePageData
 17+	PageTitle  string
 18+	URL        template.URL
 19+	RSSURL     template.URL
 20+	Username   string
 21+	Readme     *ReadmeTxt
 22+	Header     *HeaderTxt
 23+	Posts      []PostItemData
 24+	HasCSS     bool
 25+	WithStyles bool
 26+	CssURL     template.URL
 27+	HasFilter  bool
 28 }
 29 
 30 type ReadPageData struct {
 31@@ -76,6 +77,7 @@ type PostPageData struct {
 32 	PublishAtISO string
 33 	PublishAt    string
 34 	HasCSS       bool
 35+	WithStyles   bool
 36 	CssURL       template.URL
 37 	Tags         []string
 38 	Image        template.URL
 39@@ -92,14 +94,15 @@ type TransparencyPageData struct {
 40 }
 41 
 42 type HeaderTxt struct {
 43-	Title     string
 44-	Bio       string
 45-	Nav       []shared.Link
 46-	HasLinks  bool
 47-	Layout    string
 48-	Image     template.URL
 49-	ImageCard string
 50-	Favicon   template.URL
 51+	Title      string
 52+	Bio        string
 53+	Nav        []shared.Link
 54+	HasLinks   bool
 55+	Layout     string
 56+	Image      template.URL
 57+	ImageCard  string
 58+	Favicon    template.URL
 59+	WithStyles bool
 60 }
 61 
 62 type ReadmeTxt struct {
 63@@ -199,10 +202,11 @@ func blogHandler(w http.ResponseWriter, r *http.Request) {
 64 	}
 65 
 66 	headerTxt := &HeaderTxt{
 67-		Title:     GetBlogName(username),
 68-		Bio:       "",
 69-		Layout:    "default",
 70-		ImageCard: "summary",
 71+		Title:      GetBlogName(username),
 72+		Bio:        "",
 73+		Layout:     "default",
 74+		ImageCard:  "summary",
 75+		WithStyles: true,
 76 	}
 77 	readmeTxt := &ReadmeTxt{}
 78 
 79@@ -216,6 +220,7 @@ func blogHandler(w http.ResponseWriter, r *http.Request) {
 80 		headerTxt.Layout = parsedText.Layout
 81 		headerTxt.Image = template.URL(parsedText.Image)
 82 		headerTxt.ImageCard = parsedText.ImageCard
 83+		headerTxt.WithStyles = parsedText.WithStyles
 84 		headerTxt.Favicon = template.URL(parsedText.Favicon)
 85 		if parsedText.Title != "" {
 86 			headerTxt.Title = parsedText.Title
 87@@ -276,17 +281,18 @@ func blogHandler(w http.ResponseWriter, r *http.Request) {
 88 	}
 89 
 90 	data := BlogPageData{
 91-		Site:      *cfg.GetSiteData(),
 92-		PageTitle: headerTxt.Title,
 93-		URL:       template.URL(cfg.FullBlogURL(curl, username)),
 94-		RSSURL:    template.URL(cfg.RssBlogURL(curl, username, tag)),
 95-		Readme:    readmeTxt,
 96-		Header:    headerTxt,
 97-		Username:  username,
 98-		Posts:     postCollection,
 99-		HasCSS:    hasCSS,
100-		CssURL:    template.URL(cfg.CssURL(username)),
101-		HasFilter: tag != "",
102+		Site:       *cfg.GetSiteData(),
103+		PageTitle:  headerTxt.Title,
104+		URL:        template.URL(cfg.FullBlogURL(curl, username)),
105+		RSSURL:     template.URL(cfg.RssBlogURL(curl, username, tag)),
106+		Readme:     readmeTxt,
107+		Header:     headerTxt,
108+		Username:   username,
109+		Posts:      postCollection,
110+		HasCSS:     hasCSS,
111+		CssURL:     template.URL(cfg.CssURL(username)),
112+		HasFilter:  tag != "",
113+		WithStyles: headerTxt.WithStyles,
114 	}
115 
116 	err = ts.Execute(w, data)
117@@ -366,6 +372,7 @@ func postHandler(w http.ResponseWriter, r *http.Request) {
118 	ogImage := ""
119 	ogImageCard := ""
120 	hasCSS := false
121+	withStyles := true
122 	var data PostPageData
123 
124 	css, err := dbpool.FindPostWithFilename("_styles.css", user.ID, cfg.Space)
125@@ -395,6 +402,7 @@ func postHandler(w http.ResponseWriter, r *http.Request) {
126 		if readmeParsed.MetaData.Title != "" {
127 			blogName = readmeParsed.MetaData.Title
128 		}
129+		withStyles = readmeParsed.WithStyles
130 		ogImage = readmeParsed.Image
131 		ogImageCard = readmeParsed.ImageCard
132 		favicon = readmeParsed.Favicon
133@@ -454,6 +462,7 @@ func postHandler(w http.ResponseWriter, r *http.Request) {
134 			Footer:       footerHTML,
135 			Unlisted:     unlisted,
136 			Diff:         template.HTML(diff),
137+			WithStyles:   withStyles,
138 		}
139 	} else {
140 		// TODO: HACK to support imgs slugs inside prose
R prose/public/main.css => prose/artifacts/main.css
+12, -0
 1@@ -12,6 +12,14 @@ table {
 2   border-collapse: separate;
 3 }
 4 
 5+header blockquote {
 6+  margin: var(--grid-height) 0;
 7+}
 8+
 9+.transform-none {
10+  text-transform: none;
11+}
12+
13 .post-date {
14   width: 110px;
15 }
16@@ -28,6 +36,10 @@ table {
17   border-radius: 5px;
18 }
19 
20+.footnotes li p {
21+  display: inline;
22+}
23+
24 #readme {
25   display: none;
26 }
M prose/html/base.layout.tmpl
+0, -3
 1@@ -8,9 +8,6 @@
 2 
 3         <meta name="keywords" content="blog, blogging, write, writing, hackers, developers, terminal" />
 4 
 5-        <link rel="stylesheet" href="/smol.css" />
 6-        <link rel="stylesheet" href="/main.css" />
 7-
 8         {{template "meta" .}}
 9     </head>
10     <body {{template "attrs" .}}>{{template "body" .}}</body>
M prose/html/blog-aside.partial.tmpl
+5, -5
 1@@ -2,7 +2,7 @@
 2 <main class="flex">
 3     <section class="flex-1 mr">
 4         <div>
 5-            <h1 class="text-2xl font-bold">{{.Header.Title}}</h1>
 6+            <h1 class="text-2xl font-bold mt-2">{{.Header.Title}}</h1>
 7             {{if .Header.Bio}}<span>{{.Header.Bio}}</span>{{end}}
 8         </div>
 9 
10@@ -25,12 +25,12 @@
11             <a href={{.URL}}>clear filters</a>
12         {{end}}
13 
14-        <div class="posts group mt">
15+        <div class="posts group mt-2">
16         {{range .Posts}}
17             <article>
18                 <div class="flex items-center">
19                     <time datetime="{{.PublishAtISO}}" class="text-sm post-date">{{.PublishAt}}</time>
20-                    <span class="text-md flex-1"><a href="{{.URL}}">{{.Title}}</a></span>
21+                    <span class="text-md flex-1 m-0 transform-none"><a href="{{.URL}}">{{.Title}}</a></span>
22                 </div>
23             </article>
24         {{end}}
25@@ -46,9 +46,9 @@
26         <nav>
27             <ul>
28                 {{range .Header.Nav}}
29-                <li><a href="{{.URL}}" class="text-md">{{.Text}}</a></li>
30+                <li><a href="{{.URL}}" class="text-md transform-none">{{.Text}}</a></li>
31                 {{end}}
32-                <li><a href="{{.RSSURL}}" class="text-md">rss</a></li>
33+                <li><a href="{{.RSSURL}}" class="text-md transform-none">rss</a></li>
34             </ul>
35         </nav>
36     </aside>
M prose/html/blog-default.partial.tmpl
+6, -6
 1@@ -1,12 +1,12 @@
 2 {{define "blog-default"}}
 3 <header class="text-center">
 4-    <h1 class="text-2xl font-bold">{{.Header.Title}}</h1>
 5-    {{if .Header.Bio}}<p class="text-lg">{{.Header.Bio}}</p>{{end}}
 6+    <h1 class="text-2xl font-bold mt-2">{{.Header.Title}}</h1>
 7+    {{if .Header.Bio}}<span>{{.Header.Bio}}</span>{{end}}
 8     <nav>
 9         {{range .Header.Nav}}
10-        <a href="{{.URL}}" class="text-lg">{{.Text}}</a> |
11+        <a href="{{.URL}}" class="text-lg transform-none">{{.Text}}</a> |
12         {{end}}
13-        <a href="{{.RSSURL}}" class="text-lg">rss</a>
14+        <a href="{{.RSSURL}}" class="text-lg transform-none">rss</a>
15     </nav>
16     <hr />
17 </header>
18@@ -20,7 +20,7 @@
19     </section>
20     {{end}}
21 
22-    <section class="posts group mt">
23+    <section class="posts group mt-2">
24         {{if .HasFilter}}
25             <a href={{.URL}}>clear filters</a>
26         {{end}}
27@@ -28,7 +28,7 @@
28         <article>
29             <div class="flex items-center">
30                 <time datetime="{{.PublishAtISO}}" class="text-sm post-date">{{.PublishAt}}</time>
31-                <span class="text-md flex-1"><a href="{{.URL}}">{{.Title}}</a></span>
32+                <span class="text-md flex-1 m-0 transform-none"><a href="{{.URL}}">{{.Title}}</a></span>
33             </div>
34         </article>
35         {{end}}
M prose/html/blog.page.tmpl
+4, -0
 1@@ -41,6 +41,10 @@
 2 {{if .Header.Bio}}<meta property="twitter:description" content="{{.Header.Bio}}">{{end}}
 3 
 4 <link rel="alternate" href="{{.RSSURL}}" type="application/rss+xml" title="RSS feed for {{.Header.Title}}" />
 5+{{if .WithStyles}}
 6+  <link rel="stylesheet" href="/smol.css" />
 7+{{else}}
 8+{{end}}
 9 <link rel="stylesheet" href="/syntax.css" />
10 {{if .HasCSS}}<link rel="stylesheet" href="{{.CssURL}}" />{{end}}
11 {{end}}
M prose/html/imgs.page.tmpl
+3, -1
 1@@ -2,7 +2,9 @@
 2 
 3 {{define "title"}}{{.PageTitle}}{{end}}
 4 
 5-{{define "meta"}}{{end}}
 6+{{define "meta"}}
 7+<link rel="stylesheet" href="/smol.css" />
 8+{{end}}
 9 
10 {{define "attrs"}}id="blog"{{end}}
11 
M prose/html/post.page.tmpl
+9, -3
 1@@ -41,6 +41,10 @@
 2 {{if .Description}}<meta property="twitter:description" content="{{.Description}}">{{end}}
 3 
 4 <link rel="stylesheet" href="/syntax.css" />
 5+{{if .WithStyles}}
 6+  <link rel="stylesheet" href="/smol.css" />
 7+{{else}}
 8+{{end}}
 9 {{if .HasCSS}}<link rel="stylesheet" href="{{.CssURL}}" />{{end}}
10 {{end}}
11 
12@@ -53,13 +57,15 @@
13         {{if .Unlisted}} <code>unlisted</code>{{end}}
14         <time datetime="{{.PublishAtISO}}">{{.PublishAt}}</time>
15         <span>&middot;<span>
16-        <a href="{{.BlogURL}}">{{.BlogName}}</a></p>
17-    {{if .Description}}<blockquote class="font-italic">{{.Description}}</blockquote>{{end}}
18+        <a href="{{.BlogURL}}">{{.BlogName}}</a>
19+    </p>
20+    {{if .Description}}<blockquote>{{.Description}}</blockquote>{{end}}
21     <div class="tags">
22     {{range .Tags}}
23-        <a class="tag" href="{{$.BlogURL}}?tag={{.}}">#{{.}}</a>
24+        <a class="link-alt tag" href="{{$.BlogURL}}?tag={{.}}">#{{.}}</a>
25     {{end}}
26     </div>
27+    <hr />
28 </header>
29 <main>
30     <article class="md">
M prose/html/read.page.tmpl
+3, -0
 1@@ -24,6 +24,9 @@
 2 <meta property="og:image:height" content="300" />
 3 <meta itemprop="image" content="https://{{.Site.Domain}}/card.png" />
 4 <meta property="og:image" content="https://{{.Site.Domain}}/card.png" />
 5+
 6+<link rel="stylesheet" href="/smol.css" />
 7+<link rel="stylesheet" href="/main.css" />
 8 {{end}}
 9 
10 {{define "attrs"}}{{end}}
A prose/public/smol-v2.css
+849, -0
  1@@ -0,0 +1,849 @@
  2+*,
  3+::before,
  4+::after {
  5+  box-sizing: border-box;
  6+}
  7+
  8+::-moz-focus-inner {
  9+  border-style: none;
 10+  padding: 0;
 11+}
 12+:-moz-focusring {
 13+  outline: 1px dotted ButtonText;
 14+}
 15+:-moz-ui-invalid {
 16+  box-shadow: none;
 17+}
 18+
 19+:root {
 20+  --line-height: 1.3rem;
 21+  --grid-height: 0.65rem;
 22+}
 23+
 24+@media (prefers-color-scheme: light) {
 25+  :root {
 26+    --white: #2e3f53;
 27+    --white-light: #cfe0f4;
 28+    --white-dark: #6c6a6a;
 29+    --code: #52576f;
 30+    --pre: #e1e7ee;
 31+    --bg-color: #f4f4f4;
 32+    --text-color: #24292f;
 33+    --link-color: #005cc5;
 34+    --visited: #6f42c1;
 35+    --blockquote: #005cc5;
 36+    --blockquote-bg: #cfe0f4;
 37+    --hover: #c11e7a;
 38+    --grey: #ccc;
 39+    --grey-light: #6a708e;
 40+  }
 41+}
 42+
 43+@media (prefers-color-scheme: dark) {
 44+  :root {
 45+    --white: #f2f2f2;
 46+    --white-light: #f2f2f2;
 47+    --white-dark: #e8e8e8;
 48+    --code: #414558;
 49+    --pre: #252525;
 50+    --bg-color: #282a36;
 51+    --text-color: #f2f2f2;
 52+    --link-color: #8be9fd;
 53+    --visited: #bd93f9;
 54+    --blockquote: #bd93f9;
 55+    --blockquote-bg: #353548;
 56+    --hover: #ff80bf;
 57+    --grey: #414558;
 58+    --grey-light: #6a708e;
 59+  }
 60+}
 61+
 62+html {
 63+  background-color: var(--bg-color);
 64+  color: var(--text-color);
 65+  font-size: 16px;
 66+  line-height: var(--line-height);
 67+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
 68+    Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Arial,
 69+    sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
 70+  -webkit-text-size-adjust: 100%;
 71+  -moz-tab-size: 4;
 72+  -o-tab-size: 4;
 73+  tab-size: 4;
 74+}
 75+
 76+body {
 77+  margin: 0 auto;
 78+}
 79+
 80+img {
 81+  max-width: 100%;
 82+  height: auto;
 83+}
 84+
 85+b,
 86+strong {
 87+  font-weight: bold;
 88+}
 89+
 90+code,
 91+kbd,
 92+samp,
 93+pre {
 94+  font-family: monospace;
 95+}
 96+
 97+code,
 98+kbd,
 99+samp {
100+  border: 2px solid var(--code);
101+}
102+
103+pre > code {
104+  background-color: inherit;
105+  padding: 0;
106+  border: none;
107+  border-radius: 0;
108+}
109+
110+code {
111+  font-size: 90%;
112+  border-radius: 0.3rem;
113+  padding: 0.025rem 0.3rem;
114+}
115+
116+pre {
117+  font-size: 0.8rem;
118+  border-radius: 1px;
119+  padding: var(--line-height);
120+  overflow-x: auto;
121+  background-color: var(--pre) !important;
122+}
123+
124+small {
125+  font-size: 0.8rem;
126+}
127+
128+details {
129+  border: 2px solid var(--grey-light);
130+  padding: calc(var(--line-height) - 2px) 1ch;
131+  margin-bottom: var(--line-height);
132+}
133+
134+details[open] summary {
135+  margin-bottom: var(--line-height);
136+}
137+
138+summary {
139+  display: list-item;
140+  cursor: pointer;
141+}
142+
143+h1,
144+h2,
145+h3,
146+h4 {
147+  margin: 0;
148+  padding: 0;
149+  border: 0;
150+  font-style: normal;
151+  font-weight: inherit;
152+  font-size: inherit;
153+}
154+
155+path {
156+  fill: var(--text-color);
157+  stroke: var(--text-color);
158+}
159+
160+hr {
161+  color: inherit;
162+  border: 0;
163+  height: 2px;
164+  background: var(--grey);
165+  margin: calc(var(--grid-height) - 2px) auto;
166+}
167+
168+a {
169+  text-decoration: none;
170+  color: var(--link-color);
171+}
172+
173+a:hover,
174+a:visited:hover {
175+  text-decoration: underline;
176+}
177+
178+a:visited {
179+  color: var(--visited);
180+}
181+
182+section {
183+  margin-bottom: 1.4rem;
184+}
185+
186+section:last-child {
187+  margin-bottom: 0;
188+}
189+
190+header {
191+  margin: 1rem auto;
192+}
193+
194+p {
195+  margin-top: var(--line-height);
196+  margin-bottom: var(--line-height);
197+}
198+
199+article {
200+  overflow-wrap: break-word;
201+}
202+
203+blockquote {
204+  border-left: 5px solid var(--blockquote);
205+  background-color: var(--blockquote-bg);
206+  padding: var(--grid-height);
207+  margin: var(--line-height) 0;
208+}
209+
210+blockquote > p {
211+  margin: 0;
212+}
213+
214+blockquote code {
215+  border: 1px solid var(--blockquote);
216+}
217+
218+ul,
219+ol {
220+  padding: 0 0 0 var(--line-height);
221+  list-style-position: inside;
222+  list-style-type: square;
223+  margin: var(--line-height) 0;
224+}
225+
226+ul[style*="list-style-type: none;"] {
227+  padding: 0;
228+}
229+
230+ol ul, ol ol, ul ol, ul ul {
231+  padding: 0 0 0 3ch;
232+  margin: 0;
233+}
234+
235+li {
236+  margin: 0;
237+  padding: 0;
238+}
239+
240+li::marker {
241+  line-height: 0;
242+}
243+
244+li > pre {
245+  padding: 0;
246+}
247+
248+footer {
249+  text-align: center;
250+  margin-bottom: calc(var(--line-height) * 3);
251+}
252+
253+dt {
254+  font-weight: bold;
255+}
256+
257+dd {
258+  margin-left: 0;
259+}
260+
261+dd:not(:last-child) {
262+  margin-bottom: 0.5rem;
263+}
264+
265+figure {
266+  margin: 0;
267+}
268+
269+#toc {
270+  margin-top: var(--line-height);
271+}
272+
273+.container {
274+  max-width: 50em;
275+  width: 100%;
276+}
277+
278+.container-sm {
279+  max-width: 40em;
280+  width: 100%;
281+}
282+
283+.container-center {
284+  width: 100%;
285+  height: 100%;
286+  display: flex;
287+  justify-content: center;
288+}
289+
290+.mono {
291+  font-family: monospace;
292+}
293+
294+.link-alt-hover,
295+.link-alt-hover:visited,
296+.link-alt-hover:visited:hover,
297+.link-alt-hover:hover {
298+  color: var(--hover);
299+  text-decoration: none;
300+}
301+
302+.link-alt-hover:visited:hover,
303+.link-alt-hover:hover {
304+  text-decoration: underline;
305+}
306+
307+.link-alt,
308+.link-alt:visited,
309+.link-alt:visited:hover,
310+.link-alt:hover {
311+  color: var(--white);
312+  text-decoration: none;
313+}
314+
315+.link-alt:visited:hover,
316+.link-alt:hover {
317+  text-decoration: underline;
318+}
319+
320+.text-2xl code, .text-xl code, .text-lg code, .text-md code {
321+  text-transform: none;
322+}
323+
324+.text-2xl {
325+  font-size: var(--line-height);
326+  font-weight: bold;
327+  line-height: var(--line-height);
328+  margin-bottom: var(--grid-height);
329+  text-transform: uppercase;
330+}
331+
332+.text-xl, .text-lg, .text-md {
333+  font-size: 1rem;
334+  font-weight: bold;
335+  line-height: var(--line-height);
336+  margin-bottom: var(--grid-height);
337+  text-transform: uppercase;
338+}
339+
340+.text-sm {
341+  font-size: 0.8rem;
342+}
343+
344+.cursor-pointer {
345+  cursor: pointer;
346+}
347+
348+.w-full {
349+  width: 100%;
350+}
351+
352+.h-full {
353+  height: 100%;
354+}
355+
356+.border {
357+  border: 2px solid var(--grey-light);
358+}
359+
360+.text-left {
361+  text-align: left;
362+}
363+
364+.text-center {
365+  text-align: center;
366+}
367+
368+.text-underline {
369+  text-decoration: underline;
370+  text-decoration-thickness: 2px;
371+}
372+
373+.text-hdr {
374+  color: var(--hover);
375+}
376+
377+.font-bold {
378+  font-weight: bold;
379+}
380+
381+.font-italic {
382+  font-style: italic;
383+}
384+
385+.inline {
386+  display: inline;
387+}
388+
389+.inline-block {
390+  display: inline-block;
391+}
392+
393+.max-w-half {
394+  max-width: 50%;
395+}
396+
397+.h-screen {
398+  height: 100vh;
399+}
400+
401+.w-screen {
402+  width: 100vw;
403+}
404+
405+.flex {
406+  display: flex;
407+}
408+
409+.flex-col {
410+  flex-direction: column;
411+}
412+
413+.items-center {
414+  align-items: center;
415+}
416+
417+.m-0 {
418+  margin: 0;
419+}
420+
421+.mt-0 {
422+  margin-top: 0;
423+}
424+
425+.mt {
426+  margin-top: var(--grid-height);
427+}
428+
429+.mt-2 {
430+  margin-top: var(--line-height);
431+}
432+
433+.mt-4 {
434+  margin-top: calc(var(--line-height) * 2);
435+}
436+
437+.mb {
438+  margin-bottom: var(--grid-height);
439+}
440+
441+.mb-2 {
442+  margin-bottom: var(--line-height);
443+}
444+
445+.mb-4 {
446+  margin-bottom: calc(var(--line-height) * 2);
447+}
448+
449+.mr {
450+  margin-right: 0.5rem;
451+}
452+
453+.ml-sm {
454+  margin-left: 0.25rem;
455+}
456+
457+.ml {
458+  margin-left: 0.5rem;
459+}
460+
461+.pt-0 {
462+  padding-top: 0;
463+}
464+
465+.my {
466+  margin-top: var(--grid-height);
467+  margin-bottom: var(--grid-height);
468+}
469+
470+.my-2 {
471+  margin-top: var(--line-height);
472+  margin-bottom: var(--line-height);
473+}
474+
475+.my-4 {
476+  margin-top: calc(var(--line-height) * 2);
477+  margin-bottom: calc(var(--line-height) * 2);
478+}
479+
480+.mx {
481+  margin-left: 0.5rem;
482+  margin-right: 0.5rem;
483+}
484+
485+.mx-2 {
486+  margin-left: 1rem;
487+  margin-right: 1rem;
488+}
489+
490+.m-1 {
491+  margin: var(--grid-height);
492+}
493+
494+.p-1 {
495+  padding: var(--grid-height);
496+}
497+
498+.p-0 {
499+  padding: 0;
500+}
501+
502+.px-2 {
503+  padding-left: 1rem;
504+  padding-right: 1rem;
505+}
506+
507+.px-4 {
508+  padding-left: 2rem;
509+  padding-right: 2rem;
510+}
511+
512+.py {
513+  padding-top: var(--grid-height);
514+  padding-bottom: var(--grid-height);
515+}
516+
517+.py-2 {
518+  padding-top: var(--line-height);
519+  padding-bottom: var(--line-height);
520+}
521+
522+.py-4 {
523+  padding-top: calc(var(--line-height) * 2);
524+  padding-bottom: calc(var(--line-height) * 2);
525+}
526+
527+.justify-between {
528+  justify-content: space-between;
529+}
530+
531+.justify-center {
532+  justify-content: center;
533+}
534+
535+.gap {
536+  gap: var(--grid-height);
537+}
538+
539+.gap-2 {
540+  gap: var(--line-height);
541+}
542+
543+.group {
544+  display: flex;
545+  flex-direction: column;
546+  gap: var(--grid-height);
547+}
548+
549+.group-2 {
550+  display: flex;
551+  flex-direction: column;
552+  gap: var(--line-height);
553+}
554+
555+.group-h {
556+  display: flex;
557+  gap: var(--grid-height);
558+  align-items: center;
559+}
560+
561+.flex-1 {
562+  flex: 1;
563+}
564+
565+.items-end {
566+  align-items: end;
567+}
568+
569+.items-start {
570+  align-items: start;
571+}
572+
573+.justify-end {
574+  justify-content: end;
575+}
576+
577+.font-grey-light {
578+  color: var(--grey-light);
579+}
580+
581+.hidden {
582+  display: none;
583+}
584+
585+.align-right {
586+  text-align: right;
587+}
588+
589+/* ==== MARKDOWN ==== */
590+
591+.md h1,
592+.md h2,
593+.md h3,
594+.md h4 {
595+  padding: 0;
596+  margin: 0;
597+  /* margin: 1.5rem 0 0.9rem 0; */
598+  font-weight: bold;
599+}
600+
601+.md h1 a,
602+.md h2 a,
603+.md h3 a,
604+.md h4 a {
605+  color: var(--grey-light);
606+  text-decoration: none;
607+}
608+
609+h1 code, h2 code, h3 code, h4 code {
610+  text-transform: none;
611+}
612+
613+.md h1 {
614+  font-size: 1rem;
615+  line-height: var(--line-height);
616+  margin-top: calc(var(--line-height) * 2);
617+  margin-bottom: var(--grid-height);
618+  text-transform: uppercase;
619+}
620+
621+.md h2, .md h3, .md h4 {
622+  font-size: 1rem;
623+  line-height: var(--line-height);
624+  margin-top: calc(var(--line-height) * 2);
625+  margin-bottom: var(--line-height);
626+  text-transform: uppercase;
627+  color: var(--white-dark);
628+}
629+
630+/* ==== HELPERS ==== */
631+
632+.logo-header {
633+  line-height: 1;
634+  display: inline-block;
635+  background-color: #FF79C6;
636+  background-image: linear-gradient(to right, #FF5555, #FF79C6, #F8F859);
637+  color: transparent;
638+  background-clip: text;
639+  border: 3px solid #FF79C6;
640+  padding: 8px 10px 10px 10px;
641+  border-radius: 10px;
642+  background-size: 100%;
643+  margin: 0:
644+  -webkit-background-clip: text;
645+  -moz-background-clip: text;
646+  -webkit-text-fill-color: transparent;
647+  -moz-text-fill-color: transparent;
648+}
649+
650+.btn {
651+  border: 2px solid var(--link-color);
652+  color: var(--link-color);
653+  padding: 0.4rem 1rem;
654+  font-weight: bold;
655+  display: inline-block;
656+}
657+
658+.btn-link,
659+.btn-link:visited {
660+  border: 2px solid var(--link-color);
661+  color: var(--link-color);
662+  padding: var(--grid-height) 1rem;
663+  text-decoration: none;
664+  font-weight: bold;
665+  display: inline-block;
666+}
667+
668+.box {
669+  border: 2px solid var(--grey-light);
670+  padding: var(--line-height);
671+}
672+
673+.box-sm {
674+  border: 2px solid var(--grey-light);
675+  padding: var(--grid-height);
676+}
677+
678+.box-alert {
679+  border: 2px solid var(--hover);
680+  padding: var(--line-height);
681+}
682+
683+.box-sm-alert {
684+  border: 2px solid var(--hover);
685+  padding: var(--grid-height);
686+}
687+
688+.list-none {
689+  list-style-type: none;
690+}
691+
692+.list-square {
693+  list-style-type: square;
694+}
695+
696+.list-disc {
697+  list-style-type: disc;
698+}
699+
700+.list-decimal {
701+  list-style-type: decimal;
702+}
703+
704+.pill {
705+  border: 1px solid var(--link-color);
706+  color: var(--link-color);
707+}
708+
709+.pill-alert {
710+  border: 1px solid var(--hover);
711+  color: var(--hover);
712+}
713+
714+.pill-info {
715+  border: 1px solid var(--visited);
716+  color: var(--visited);
717+}
718+
719+@media only screen and (max-width: 40em) {
720+  body {
721+    padding: 0 1rem;
722+  }
723+
724+  header {
725+    margin: 0;
726+  }
727+
728+  .flex-collapse {
729+    flex-direction: column;
730+  }
731+}
732+
733+#debug {
734+  position: relative;
735+}
736+
737+#debug .debug-grid {
738+  width: 100%;
739+  height: 100%;
740+  position: absolute;
741+  top: 0;
742+  left: 0;
743+  right: 0;
744+  bottom: 0;
745+  z-index: -1;
746+  background-image:
747+    repeating-linear-gradient(var(--code) 0 1px, transparent 1px 100%),
748+    repeating-linear-gradient(90deg, var(--code) 0 1px, transparent 1px 100%);
749+  background-size: 1ch var(--grid-height);
750+  margin: 0;
751+}
752+body {
753+  max-width: var(--body-max-width, 720px);
754+}
755+
756+table {
757+  display: block;
758+  max-width: fit-content;
759+  margin: 0 auto;
760+  overflow-x: auto;
761+  white-space: nowrap;
762+  border-spacing: 10px;
763+  border-collapse: separate;
764+}
765+
766+header blockquote {
767+  margin: var(--grid-height) 0;
768+}
769+
770+.transform-none {
771+  text-transform: none;
772+}
773+
774+.post-date {
775+  width: 110px;
776+}
777+
778+.layout-aside {
779+  max-width: 50rem;
780+}
781+
782+.layout-aside aside {
783+  width: 200px;
784+}
785+
786+.layout-aside img {
787+  border-radius: 5px;
788+}
789+
790+.footnotes li p {
791+  display: inline;
792+}
793+
794+#readme {
795+  display: none;
796+}
797+
798+.albums {
799+  width: 100%;
800+  display: grid;
801+  grid-template-columns: repeat(3, 1fr);
802+  grid-template-rows: repeat(auto-fill, 200px);
803+  grid-row-gap: 0.5rem;
804+  grid-column-gap: 1rem;
805+}
806+
807+.thumbnail-container {
808+  position: relative;
809+  background-color: #000;
810+  display: flex;
811+  flex-direction: column;
812+  align-items: center;
813+  justify-content: center;
814+  padding: 3px;
815+  min-height: 200px;
816+}
817+
818+.thumbnail {
819+  z-index: 1;
820+  object-fit: contain;
821+  max-width: 200px;
822+  height: auto;
823+}
824+
825+#toc {
826+  margin: 0;
827+}
828+
829+.thumbnail-link {
830+  z-index: 1;
831+}
832+
833+@media only screen and (max-width: 600px) {
834+  .layout-aside main {
835+    flex-direction: column;
836+  }
837+
838+  aside {
839+    display: none;
840+  }
841+
842+  #readme {
843+    display: block;
844+  }
845+
846+  .albums {
847+    grid-template-columns: repeat(1, 1fr);
848+    justify-content: center;
849+  }
850+}
M prose/public/smol.css
+90, -0
 1@@ -766,3 +766,93 @@ figure {
 2     flex-direction: column;
 3   }
 4 }
 5+
 6+/* was: main.css */
 7+
 8+body {
 9+  max-width: var(--body-max-width, 720px);
10+}
11+
12+table {
13+  display: block;
14+  max-width: fit-content;
15+  margin: 0 auto;
16+  overflow-x: auto;
17+  white-space: nowrap;
18+  border-spacing: 10px;
19+  border-collapse: separate;
20+}
21+
22+.post-date {
23+  width: 110px;
24+}
25+
26+.layout-aside {
27+  max-width: 50rem;
28+}
29+
30+.layout-aside aside {
31+  width: 200px;
32+}
33+
34+.layout-aside img {
35+  border-radius: 5px;
36+}
37+
38+#readme {
39+  display: none;
40+}
41+
42+.albums {
43+  width: 100%;
44+  display: grid;
45+  grid-template-columns: repeat(3, 1fr);
46+  grid-template-rows: repeat(auto-fill, 200px);
47+  grid-row-gap: 0.5rem;
48+  grid-column-gap: 1rem;
49+}
50+
51+.thumbnail-container {
52+  position: relative;
53+  background-color: #000;
54+  display: flex;
55+  flex-direction: column;
56+  align-items: center;
57+  justify-content: center;
58+  padding: 3px;
59+  min-height: 200px;
60+}
61+
62+.thumbnail {
63+  z-index: 1;
64+  object-fit: contain;
65+  max-width: 200px;
66+  height: auto;
67+}
68+
69+#toc {
70+  margin: 0;
71+}
72+
73+.thumbnail-link {
74+  z-index: 1;
75+}
76+
77+@media only screen and (max-width: 600px) {
78+  .layout-aside main {
79+    flex-direction: column;
80+  }
81+
82+  aside {
83+    display: none;
84+  }
85+
86+  #readme {
87+    display: block;
88+  }
89+
90+  .albums {
91+    grid-template-columns: repeat(1, 1fr);
92+    justify-content: center;
93+  }
94+}
M shared/mdparser.go
+13, -5
 1@@ -40,6 +40,7 @@ type MetaData struct {
 2 	ImageCard   string
 3 	Favicon     string
 4 	Hidden      bool
 5+	WithStyles  bool
 6 }
 7 
 8 type ParsedText struct {
 9@@ -68,9 +69,9 @@ func toString(obj interface{}) (string, error) {
10 	}
11 }
12 
13-func toBool(obj interface{}) (bool, error) {
14+func toBool(obj interface{}, fallback bool) (bool, error) {
15 	if obj == nil {
16-		return false, nil
17+		return fallback, nil
18 	}
19 	switch val := obj.(type) {
20 	case bool:
21@@ -213,8 +214,9 @@ func CreateGoldmark(extenders ...goldmark.Extender) goldmark.Markdown {
22 func ParseText(text string) (*ParsedText, error) {
23 	parsed := ParsedText{
24 		MetaData: &MetaData{
25-			Tags:    []string{},
26-			Aliases: []string{},
27+			Tags:       []string{},
28+			Aliases:    []string{},
29+			WithStyles: true,
30 		},
31 	}
32 	hili := highlighting.NewHighlighting(
33@@ -291,12 +293,18 @@ func ParseText(text string) (*ParsedText, error) {
34 	}
35 	parsed.MetaData.ImageCard = card
36 
37-	hidden, err := toBool(metaData["draft"])
38+	hidden, err := toBool(metaData["draft"], false)
39 	if err != nil {
40 		return &parsed, fmt.Errorf("front-matter field (%s): %w", "draft", err)
41 	}
42 	parsed.MetaData.Hidden = hidden
43 
44+	withStyles, err := toBool(metaData["with_styles"], true)
45+	if err != nil {
46+		return &parsed, fmt.Errorf("front-matter field (%s): %w", "with_style", err)
47+	}
48+	parsed.MetaData.WithStyles = withStyles
49+
50 	favicon, err := toString(metaData["favicon"])
51 	if err != nil {
52 		return &parsed, fmt.Errorf("front-matter field (%s): %w", "favicon", err)