Serve CSS as a static asset via Roda static plugin
Assisted-by: Claude Opus 4.6 via pi
change pnoqsupllywtrkkzszlkwvklstnomxwn
commit 6e6f235cbc384751e593f4447ce9110b8f4ebc23
author Alpha Chen <alpha@kejadlen.dev>
date
parent mynvwvnk
diff --git a/lib/views/layout.rb b/lib/views/layout.rb
index b11f844..77cef2a 100644
--- a/lib/views/layout.rb
+++ b/lib/views/layout.rb
@@ -15,170 +15,10 @@ module Views
           meta(charset: "utf-8")
           meta(name: "viewport", content: "width=device-width, initial-scale=1")
           title { @title }
-          style { raw(safe(css)) }
+          link(rel: "stylesheet", href: "/css/app.css")
         end
         body(&)
       end
     end
-
-    private
-
-    def css
-      <<~CSS
-        /* -------------------- */
-        /* A (more) Modern Reset */
-        /* @link https://piccalil.li/blog/a-more-modern-css-reset/ */
-        /* -------------------- */
-
-        /* Box sizing rules */
-        *,
-        *::before,
-        *::after {
-          box-sizing: border-box;
-        }
-
-        /* Prevent font size inflation */
-        html {
-          -moz-text-size-adjust: none;
-          -webkit-text-size-adjust: none;
-          text-size-adjust: none;
-        }
-
-        /* Remove default margin in favour of better control in authored CSS */
-        body, h1, h2, h3, h4, p,
-        figure, blockquote, dl, dd {
-          margin-block-end: 0;
-        }
-
-        /* Remove list styles on ul, ol elements with a list role,
-           which suggests default styling will be removed */
-        ul[role='list'],
-        ol[role='list'] {
-          list-style: none;
-        }
-
-        /* Set core body defaults */
-        body {
-          min-height: 100vh;
-          line-height: 1.5;
-        }
-
-        /* Set shorter line heights on headings and interactive elements */
-        h1, h2, h3, h4,
-        button, input, label {
-          line-height: 1.1;
-        }
-
-        /* Balance text wrapping on headings */
-        h1, h2,
-        h3, h4 {
-          text-wrap: balance;
-        }
-
-        /* A elements that don't have a class get default styles */
-        a:not([class]) {
-          text-decoration-skip-ink: auto;
-          color: currentColor;
-        }
-
-        /* Make images easier to work with */
-        img,
-        picture {
-          max-width: 100%;
-          display: block;
-        }
-
-        /* Inherit fonts for inputs and buttons */
-        input, button,
-        textarea, select {
-          font-family: inherit;
-          font-size: inherit;
-        }
-
-        /* Make sure textareas without a rows attribute are not tiny */
-        textarea:not([rows]) {
-          min-height: 10em;
-        }
-
-        /* Anything that has been anchored to should have extra scroll margin */
-        :target {
-          scroll-margin-block: 5ex;
-        }
-
-        /* -------------------- */
-        /* Flow utility — vertical rhythm via Utopia space tokens */
-        /* @link https://piccalil.li/blog/my-favourite-3-lines-of-css/ */
-        /* -------------------- */
-
-        .flow > * + * {
-          margin-block-start: var(--flow-space, var(--space-s));
-        }
-
-        /* -------------------- */
-        /* Utopia fluid type scale */
-        /* -------------------- */
-
-        /* @link https://utopia.fyi/type/calculator?c=360,18,1.2,1240,20,1.25,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
-        :root {
-          --step--2: clamp(0.7813rem, 0.7736rem + 0.0341vw, 0.8rem);
-          --step--1: clamp(0.9375rem, 0.9119rem + 0.1136vw, 1rem);
-          --step-0: clamp(1.125rem, 1.0739rem + 0.2273vw, 1.25rem);
-          --step-1: clamp(1.35rem, 1.2631rem + 0.3864vw, 1.5625rem);
-          --step-2: clamp(1.62rem, 1.4837rem + 0.6057vw, 1.9531rem);
-          --step-3: clamp(1.944rem, 1.7405rem + 0.9044vw, 2.4414rem);
-          --step-4: clamp(2.3328rem, 2.0387rem + 1.3072vw, 3.0518rem);
-          --step-5: clamp(2.7994rem, 2.384rem + 1.8461vw, 3.8147rem);
-        }
-
-        /* @link https://utopia.fyi/space/calculator?c=360,18,1.2,1240,20,1.25,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
-        :root {
-          --space-3xs: clamp(0.3125rem, 0.3125rem + 0vw, 0.3125rem);
-          --space-2xs: clamp(0.5625rem, 0.5369rem + 0.1136vw, 0.625rem);
-          --space-xs: clamp(0.875rem, 0.8494rem + 0.1136vw, 0.9375rem);
-          --space-s: clamp(1.125rem, 1.0739rem + 0.2273vw, 1.25rem);
-          --space-m: clamp(1.6875rem, 1.6108rem + 0.3409vw, 1.875rem);
-          --space-l: clamp(2.25rem, 2.1477rem + 0.4545vw, 2.5rem);
-          --space-xl: clamp(3.375rem, 3.2216rem + 0.6818vw, 3.75rem);
-          --space-2xl: clamp(4.5rem, 4.2955rem + 0.9091vw, 5rem);
-          --space-3xl: clamp(6.75rem, 6.4432rem + 1.3636vw, 7.5rem);
-
-          /* One-up pairs */
-          --space-3xs-2xs: clamp(0.3125rem, 0.1847rem + 0.5682vw, 0.625rem);
-          --space-2xs-xs: clamp(0.5625rem, 0.4091rem + 0.6818vw, 0.9375rem);
-          --space-xs-s: clamp(0.875rem, 0.7216rem + 0.6818vw, 1.25rem);
-          --space-s-m: clamp(1.125rem, 0.8182rem + 1.3636vw, 1.875rem);
-          --space-m-l: clamp(1.6875rem, 1.3551rem + 1.4773vw, 2.5rem);
-          --space-l-xl: clamp(2.25rem, 1.6364rem + 2.7273vw, 3.75rem);
-          --space-xl-2xl: clamp(3.375rem, 2.7102rem + 2.9545vw, 5rem);
-          --space-2xl-3xl: clamp(4.5rem, 3.2727rem + 5.4545vw, 7.5rem);
-
-          /* Custom pairs */
-          --space-s-l: clamp(1.125rem, 0.5625rem + 2.5vw, 2.5rem);
-        }
-
-        /* @link https://utopia.fyi/grid/calculator?c=360,18,1.2,1240,20,1.25,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
-        :root {
-          --grid-max-width: 77.50rem;
-          --grid-gutter: var(--space-s-l, clamp(1.125rem, 0.5625rem + 2.5vw, 2.5rem));
-          --grid-columns: 12;
-        }
-
-        .u-container {
-          max-width: var(--grid-max-width);
-          padding-inline: var(--grid-gutter);
-          margin-inline: auto;
-        }
-
-        .u-grid {
-          display: grid;
-          gap: var(--grid-gutter);
-        }
-
-        /* @link https://utopia.fyi/clamp/calculator?a=360,1240,16—48 */
-        :root {
-          --fluid-16-48: clamp(1rem, 0.1818rem + 3.6364vw, 3rem);
-        }
-      CSS
-    end
   end
 end
diff --git a/lib/web.rb b/lib/web.rb
index 7dfe7d4..b6306de 100644
--- a/lib/web.rb
+++ b/lib/web.rb
@@ -5,6 +5,8 @@ require "roda"
 require_relative "views/series/new"
 
 class Web < Roda
+  plugin :static, ["/css", "/js"]
+
   route do |r|
     r.root do
       Views::Series::New.new.call
diff --git a/public/css/app.css b/public/css/app.css
new file mode 100644
index 0000000..5114b01
--- /dev/null
+++ b/public/css/app.css
@@ -0,0 +1,153 @@
+/* -------------------- */
+/* A (more) Modern Reset */
+/* @link https://piccalil.li/blog/a-more-modern-css-reset/ */
+/* -------------------- */
+
+/* Box sizing rules */
+*,
+*::before,
+*::after {
+  box-sizing: border-box;
+}
+
+/* Prevent font size inflation */
+html {
+  -moz-text-size-adjust: none;
+  -webkit-text-size-adjust: none;
+  text-size-adjust: none;
+}
+
+/* Remove default margin in favour of better control in authored CSS */
+body, h1, h2, h3, h4, p,
+figure, blockquote, dl, dd {
+  margin-block-end: 0;
+}
+
+/* Remove list styles on ul, ol elements with a list role,
+   which suggests default styling will be removed */
+ul[role='list'],
+ol[role='list'] {
+  list-style: none;
+}
+
+/* Set core body defaults */
+body {
+  min-height: 100vh;
+  line-height: 1.5;
+}
+
+/* Set shorter line heights on headings and interactive elements */
+h1, h2, h3, h4,
+button, input, label {
+  line-height: 1.1;
+}
+
+/* Balance text wrapping on headings */
+h1, h2,
+h3, h4 {
+  text-wrap: balance;
+}
+
+/* A elements that don't have a class get default styles */
+a:not([class]) {
+  text-decoration-skip-ink: auto;
+  color: currentColor;
+}
+
+/* Make images easier to work with */
+img,
+picture {
+  max-width: 100%;
+  display: block;
+}
+
+/* Inherit fonts for inputs and buttons */
+input, button,
+textarea, select {
+  font-family: inherit;
+  font-size: inherit;
+}
+
+/* Make sure textareas without a rows attribute are not tiny */
+textarea:not([rows]) {
+  min-height: 10em;
+}
+
+/* Anything that has been anchored to should have extra scroll margin */
+:target {
+  scroll-margin-block: 5ex;
+}
+
+/* -------------------- */
+/* Flow utility — vertical rhythm via Utopia space tokens */
+/* @link https://piccalil.li/blog/my-favourite-3-lines-of-css/ */
+/* -------------------- */
+
+.flow > * + * {
+  margin-block-start: var(--flow-space, var(--space-s));
+}
+
+/* -------------------- */
+/* Utopia fluid type scale */
+/* -------------------- */
+
+/* @link https://utopia.fyi/type/calculator?c=360,18,1.2,1240,20,1.25,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
+:root {
+  --step--2: clamp(0.7813rem, 0.7736rem + 0.0341vw, 0.8rem);
+  --step--1: clamp(0.9375rem, 0.9119rem + 0.1136vw, 1rem);
+  --step-0: clamp(1.125rem, 1.0739rem + 0.2273vw, 1.25rem);
+  --step-1: clamp(1.35rem, 1.2631rem + 0.3864vw, 1.5625rem);
+  --step-2: clamp(1.62rem, 1.4837rem + 0.6057vw, 1.9531rem);
+  --step-3: clamp(1.944rem, 1.7405rem + 0.9044vw, 2.4414rem);
+  --step-4: clamp(2.3328rem, 2.0387rem + 1.3072vw, 3.0518rem);
+  --step-5: clamp(2.7994rem, 2.384rem + 1.8461vw, 3.8147rem);
+}
+
+/* @link https://utopia.fyi/space/calculator?c=360,18,1.2,1240,20,1.25,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
+:root {
+  --space-3xs: clamp(0.3125rem, 0.3125rem + 0vw, 0.3125rem);
+  --space-2xs: clamp(0.5625rem, 0.5369rem + 0.1136vw, 0.625rem);
+  --space-xs: clamp(0.875rem, 0.8494rem + 0.1136vw, 0.9375rem);
+  --space-s: clamp(1.125rem, 1.0739rem + 0.2273vw, 1.25rem);
+  --space-m: clamp(1.6875rem, 1.6108rem + 0.3409vw, 1.875rem);
+  --space-l: clamp(2.25rem, 2.1477rem + 0.4545vw, 2.5rem);
+  --space-xl: clamp(3.375rem, 3.2216rem + 0.6818vw, 3.75rem);
+  --space-2xl: clamp(4.5rem, 4.2955rem + 0.9091vw, 5rem);
+  --space-3xl: clamp(6.75rem, 6.4432rem + 1.3636vw, 7.5rem);
+
+  /* One-up pairs */
+  --space-3xs-2xs: clamp(0.3125rem, 0.1847rem + 0.5682vw, 0.625rem);
+  --space-2xs-xs: clamp(0.5625rem, 0.4091rem + 0.6818vw, 0.9375rem);
+  --space-xs-s: clamp(0.875rem, 0.7216rem + 0.6818vw, 1.25rem);
+  --space-s-m: clamp(1.125rem, 0.8182rem + 1.3636vw, 1.875rem);
+  --space-m-l: clamp(1.6875rem, 1.3551rem + 1.4773vw, 2.5rem);
+  --space-l-xl: clamp(2.25rem, 1.6364rem + 2.7273vw, 3.75rem);
+  --space-xl-2xl: clamp(3.375rem, 2.7102rem + 2.9545vw, 5rem);
+  --space-2xl-3xl: clamp(4.5rem, 3.2727rem + 5.4545vw, 7.5rem);
+
+  /* Custom pairs */
+  --space-s-l: clamp(1.125rem, 0.5625rem + 2.5vw, 2.5rem);
+}
+
+/* @link https://utopia.fyi/grid/calculator?c=360,18,1.2,1240,20,1.25,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
+:root {
+  --grid-max-width: 77.50rem;
+  --grid-gutter: var(--space-s-l, clamp(1.125rem, 0.5625rem + 2.5vw, 2.5rem));
+  --grid-columns: 12;
+}
+
+.u-container {
+  max-width: var(--grid-max-width);
+  padding-inline: var(--grid-gutter);
+  margin-inline: auto;
+}
+
+.u-grid {
+  display: grid;
+  gap: var(--grid-gutter);
+}
+
+/* @link https://utopia.fyi/clamp/calculator?a=360,1240,16—48 */
+:root {
+  --fluid-16-48: clamp(1rem, 0.1818rem + 3.6364vw, 3rem);
+}