Extract inline styles into CSS classes in templates
All style attributes replaced with semantic class names defined in _css.html. Makes the templates readable and keeps styling centralized for future pages.
change mpotkqtzkyzolqqlqoryvoqtunlnmsvz
commit 419174f56d48b693f4e0898de5327609ba36bb81
author Alpha Chen <alpha@kejadlen.dev>
date
parent lsrmsupv
diff --git a/src/quire/web.rs b/src/quire/web.rs
index 125bd82..43724ad 100644
--- a/src/quire/web.rs
+++ b/src/quire/web.rs
@@ -141,9 +141,9 @@ impl<S: Send + Sync> FromRequestParts<S> for RemoteUser {
 
 fn state_color(state: &str) -> &'static str {
     match state {
-        "complete" => "var(--ok)",
-        "failed" => "var(--bad)",
-        _ => "var(--muted)",
+        "complete" => "c-ok",
+        "failed" => "c-bad",
+        _ => "c-muted",
     }
 }
 
diff --git a/templates/_base.html b/templates/_base.html
index c4534cc..fa8081c 100644
--- a/templates/_base.html
+++ b/templates/_base.html
@@ -8,7 +8,7 @@
 </head>
 <body>
 {% block nav %}{% endblock %}
-<main style="padding:22px 56px 32px">
+<main class="page-main">
 {% block content %}{% endblock %}
 </main>
 {% include "_footer.html" %}
diff --git a/templates/_css.html b/templates/_css.html
index b2e65ee..fa8d6c4 100644
--- a/templates/_css.html
+++ b/templates/_css.html
@@ -12,6 +12,177 @@
   --ok: #4a7a3a;
   --bad: #9a3a28;
 }
-body { margin:0; background:var(--bg); color:var(--ink); font-family:var(--font-humanist); font-size:15px; line-height:1.6; }
-a { color:var(--accent); }
-pre { white-space:pre-wrap; word-break:break-word; }
+
+body {
+  margin: 0;
+  background: var(--bg);
+  color: var(--ink);
+  font-family: var(--font-humanist);
+  font-size: 15px;
+  line-height: 1.6;
+}
+
+a { color: var(--accent); }
+pre { white-space: pre-wrap; word-break: break-word; }
+
+/* Layout */
+
+.page-nav {
+  padding: 14px 56px;
+  border-bottom: 1px solid var(--rule);
+  font-family: var(--font-mono);
+  font-size: 14px;
+  font-weight: 500;
+  letter-spacing: -0.2px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.page-nav .breadcrumbs .sep { color: var(--rule2); }
+.page-nav .crumb-muted { color: var(--muted); }
+.page-nav .crumb-faint { color: var(--mutedFaint); }
+.page-nav .shortcuts { font-size: 11px; color: var(--mutedFaint); }
+
+.page-main { padding: 22px 56px 32px; }
+
+.page-footer {
+  padding: 16px 56px 24px;
+  border-top: 1px solid var(--rule);
+  font-family: var(--font-mono);
+  font-size: 11px;
+  color: var(--mutedFaint);
+  letter-spacing: 0.2px;
+  display: flex;
+  justify-content: space-between;
+}
+
+/* CI run list */
+
+.ci-heading {
+  font-family: var(--font-mono);
+  font-size: 19px;
+  font-weight: 600;
+  margin: 0 0 16px;
+}
+
+.ci-table {
+  width: 100%;
+  border-collapse: collapse;
+  font-family: var(--font-mono);
+  font-size: 12.5px;
+  line-height: 1.6;
+}
+
+.ci-table thead th {
+  text-align: left;
+  padding: 6px 8px;
+  font-weight: 400;
+  color: var(--mutedFaint);
+}
+
+.ci-table thead tr { border-bottom: 1px solid var(--rule2); }
+.ci-table tbody { border-top: 1px solid var(--rule); }
+.ci-table td { padding: 6px 8px; }
+.ci-table .empty { padding: 16px; color: var(--muted); }
+
+.ci-status-dot {
+  display: inline-block;
+  width: 6px;
+  height: 6px;
+  border-radius: 3px;
+}
+
+.ci-sha-link {
+  color: var(--accent);
+  text-decoration: none;
+  border-bottom: 1px dotted var(--rule2);
+}
+
+/* CI run detail */
+
+.ci-meta {
+  padding: 16px 0;
+  border-bottom: 1px solid var(--rule);
+}
+
+.ci-meta-primary {
+  font-family: var(--font-mono);
+  font-size: 15px;
+  line-height: 1.6;
+}
+
+.ci-meta-secondary {
+  font-family: var(--font-mono);
+  font-size: 12px;
+  color: var(--mutedFaint);
+  margin-top: 4px;
+}
+
+/* CI jobs */
+
+.ci-job {
+  margin: 24px 0 0;
+}
+
+.ci-job-header {
+  font-family: var(--font-mono);
+  font-size: 13px;
+  font-weight: 500;
+  padding: 8px 0;
+  border-bottom: 1px solid var(--rule2);
+}
+
+.ci-sh {
+  margin: 8px 0;
+}
+
+.ci-sh-meta {
+  font-family: var(--font-mono);
+  font-size: 11px;
+  color: var(--mutedFaint);
+  margin-bottom: 2px;
+}
+
+.ci-sh-cmd {
+  font-family: var(--font-mono);
+  font-size: 12px;
+  color: var(--muted);
+  margin-bottom: 4px;
+}
+
+.ci-sh-log {
+  font-family: var(--font-mono);
+  font-size: 12px;
+  line-height: 1.65;
+  background: var(--code);
+  color: var(--ink);
+  padding: 10px 14px;
+  border-left: 2px solid var(--accent);
+  overflow: auto;
+  margin: 0 0 8px;
+}
+
+.ci-empty { padding: 16px 0; color: var(--muted); }
+
+/* Error page */
+
+.error-title {
+  color: var(--bad);
+  font-family: var(--font-mono);
+}
+
+.error-detail {
+  font-family: var(--font-mono);
+  font-size: 12px;
+  background: var(--code);
+  padding: 14px 18px;
+  overflow: auto;
+}
+
+/* Color tokens */
+
+.c-ok { color: var(--ok); }
+.c-bad { color: var(--bad); }
+.c-muted { color: var(--muted); }
+.c-accent { color: var(--accent); }
diff --git a/templates/_footer.html b/templates/_footer.html
index e4ad42d..0bb35d0 100644
--- a/templates/_footer.html
+++ b/templates/_footer.html
@@ -1,4 +1,4 @@
-<footer style="padding:16px 56px 24px;border-top:1px solid var(--rule);font-family:var(--font-mono);font-size:11px;color:var(--mutedFaint);letter-spacing:0.2px;display:flex;justify-content:space-between">
-<span>quire</span>
-<span>?</span>
+<footer class="page-footer">
+  <span>quire</span>
+  <span>?</span>
 </footer>
diff --git a/templates/_nav.html b/templates/_nav.html
index d89ca16..b38391b 100644
--- a/templates/_nav.html
+++ b/templates/_nav.html
@@ -1,4 +1,10 @@
-<nav style="padding:14px 56px;border-bottom:1px solid var(--rule);font-family:var(--font-mono);font-size:14px;font-weight:500;letter-spacing:-0.2px;display:flex;justify-content:space-between;align-items:center">
-<div><span style="color:var(--mutedFaint)">quire</span> <span style="color:var(--rule2)">/</span> <span>{{ repo }}</span> <span style="color:var(--rule2)">/</span> <span style="color:var(--muted)">{{ page }}</span></div>
-<div style="font-size:11px;color:var(--mutedFaint)">press [?] for shortcuts</div>
+<nav class="page-nav">
+  <div class="breadcrumbs">
+    <span class="crumb-faint">quire</span>
+    <span class="sep">/</span>
+    <span>{{ repo }}</span>
+    <span class="sep">/</span>
+    <span class="crumb-muted">{{ page }}</span>
+  </div>
+  <div class="shortcuts">press [?] for shortcuts</div>
 </nav>
diff --git a/templates/ci/run_detail.html b/templates/ci/run_detail.html
index 6841148..f43e154 100644
--- a/templates/ci/run_detail.html
+++ b/templates/ci/run_detail.html
@@ -3,41 +3,49 @@
 {% block title %}ci · {{ repo }} · {{ run.sha_short }}{% endblock %}
 
 {% block nav %}
-<nav style="padding:14px 56px;border-bottom:1px solid var(--rule);font-family:var(--font-mono);font-size:14px;font-weight:500;letter-spacing:-0.2px;display:flex;justify-content:space-between;align-items:center">
-<div><span style="color:var(--mutedFaint)">quire</span> <span style="color:var(--rule2)">/</span> <span>{{ repo }}</span> <span style="color:var(--rule2)">/</span> <span style="color:var(--muted)">ci · {{ run.sha_short }}</span></div>
-<div style="font-size:11px;color:var(--mutedFaint)">press [?] for shortcuts</div>
+<nav class="page-nav">
+  <div class="breadcrumbs">
+    <span class="crumb-faint">quire</span>
+    <span class="sep">/</span>
+    <span>{{ repo }}</span>
+    <span class="sep">/</span>
+    <span class="crumb-muted">ci · {{ run.sha_short }}</span>
+  </div>
+  <div class="shortcuts">press [?] for shortcuts</div>
 </nav>
 {% endblock %}
 
 {% block content %}
-<div style="padding:16px 0;border-bottom:1px solid var(--rule)">
-<div style="font-family:var(--font-mono);font-size:15px;line-height:1.6">
-<span style="color:{{ run.state_color }}">{{ run.state }}</span> · <span style="color:var(--accent)">{{ run.sha_short }}</span> · {{ run.ref_short }}
-</div>
-<div style="font-family:var(--font-mono);font-size:12px;color:var(--mutedFaint);margin-top:4px">
-queued {{ run.queued }} · started {{ run.started }} · finished {{ run.finished }} · {{ run.duration }}
-</div>
+<div class="ci-meta">
+  <div class="ci-meta-primary">
+    <span class="{{ run.state_color }}">{{ run.state }}</span>
+    · <span class="c-accent">{{ run.sha_short }}</span>
+    · {{ run.ref_short }}
+  </div>
+  <div class="ci-meta-secondary">
+    queued {{ run.queued }} · started {{ run.started }} · finished {{ run.finished }} · {{ run.duration }}
+  </div>
 </div>
+
 {% for job in jobs %}
-<div style="margin:24px 0 0">
-<div style="font-family:var(--font-mono);font-size:13px;font-weight:500;padding:8px 0;border-bottom:1px solid var(--rule2)">
-<span style="color:{{ job.state_color }}">{{ job.state }}</span> · {{ job.job_id }} · {{ job.duration }}{{ job.exit_str }}
-</div>
-{% for sh in job.sh_events %}
-<div style="margin:8px 0">
-<div style="font-family:var(--font-mono);font-size:11px;color:var(--mutedFaint);margin-bottom:2px">
-sh-{{ sh.index }} · {{ sh.duration }} · exit {{ sh.exit_code }}
-</div>
-<div style="font-family:var(--font-mono);font-size:12px;color:var(--muted);margin-bottom:4px">
-{{ sh.cmd_display }}
-</div>
-{% if !sh.log_content.is_empty() %}
-<pre style="font-family:var(--font-mono);font-size:12px;line-height:1.65;background:var(--code);color:var(--ink);padding:10px 14px;border-left:2px solid var(--accent);overflow:auto;margin:0 0 8px">{{ sh.log_content }}</pre>
-{% endif %}
-</div>
-{% endfor %}
+<div class="ci-job">
+  <div class="ci-job-header">
+    <span class="{{ job.state_color }}">{{ job.state }}</span>
+    · {{ job.job_id }} · {{ job.duration }}{{ job.exit_str }}
+  </div>
+  {% for sh in job.sh_events %}
+  <div class="ci-sh">
+    <div class="ci-sh-meta">
+      sh-{{ sh.index }} · {{ sh.duration }} · exit {{ sh.exit_code }}
+    </div>
+    <div class="ci-sh-cmd">{{ sh.cmd_display }}</div>
+    {% if !sh.log_content.is_empty() %}
+    <pre class="ci-sh-log">{{ sh.log_content }}</pre>
+    {% endif %}
+  </div>
+  {% endfor %}
 </div>
 {% else %}
-<div style="padding:16px 0;color:var(--muted)">no jobs recorded</div>
+<div class="ci-empty">no jobs recorded</div>
 {% endfor %}
 {% endblock %}
diff --git a/templates/ci/run_list.html b/templates/ci/run_list.html
index 3871c32..4ddd66c 100644
--- a/templates/ci/run_list.html
+++ b/templates/ci/run_list.html
@@ -3,36 +3,42 @@
 {% block title %}ci · {{ repo }}{% endblock %}
 
 {% block nav %}
-<nav style="padding:14px 56px;border-bottom:1px solid var(--rule);font-family:var(--font-mono);font-size:14px;font-weight:500;letter-spacing:-0.2px;display:flex;justify-content:space-between;align-items:center">
-<div><span style="color:var(--mutedFaint)">quire</span> <span style="color:var(--rule2)">/</span> <span>{{ repo }}</span> <span style="color:var(--rule2)">/</span> <span style="color:var(--muted)">ci</span></div>
-<div style="font-size:11px;color:var(--mutedFaint)">press [?] for shortcuts</div>
+<nav class="page-nav">
+  <div class="breadcrumbs">
+    <span class="crumb-faint">quire</span>
+    <span class="sep">/</span>
+    <span>{{ repo }}</span>
+    <span class="sep">/</span>
+    <span class="crumb-muted">ci</span>
+  </div>
+  <div class="shortcuts">press [?] for shortcuts</div>
 </nav>
 {% endblock %}
 
 {% block content %}
-<h2 style="font-family:var(--font-mono);font-size:19px;font-weight:600;margin:0 0 16px">ci runs</h2>
-<table style="width:100%;border-collapse:collapse;font-family:var(--font-mono);font-size:12.5px;line-height:1.6">
-<thead>
-<tr style="border-bottom:1px solid var(--rule2)">
-  <th style="text-align:left;padding:6px 8px;font-weight:400;color:var(--mutedFaint)"></th>
-  <th style="text-align:left;padding:6px 8px;font-weight:400;color:var(--mutedFaint)">sha</th>
-  <th style="text-align:left;padding:6px 8px;font-weight:400;color:var(--mutedFaint)">ref</th>
-  <th style="text-align:left;padding:6px 8px;font-weight:400;color:var(--mutedFaint)">queued</th>
-  <th style="text-align:left;padding:6px 8px;font-weight:400;color:var(--mutedFaint)">duration</th>
-</tr>
-</thead>
-<tbody style="border-top:1px solid var(--rule)">
-{% for run in runs %}
-<tr>
-  <td style="padding:6px 8px"><span style="display:inline-block;width:6px;height:6px;border-radius:3px;background:{{ run.state_color }}"></span></td>
-  <td style="padding:6px 8px"><a href="/repo/{{ repo }}/ci/{{ run.id }}" style="color:var(--accent);text-decoration:none;border-bottom:1px dotted var(--rule2)">{{ run.sha_short }}</a></td>
-  <td style="padding:6px 8px">{{ run.ref_short }}</td>
-  <td style="padding:6px 8px">{{ run.queued }}</td>
-  <td style="padding:6px 8px">{{ run.duration }}</td>
-</tr>
-{% else %}
-<tr><td colspan="5" style="padding:16px;color:var(--muted)">no runs yet</td></tr>
-{% endfor %}
-</tbody>
+<h2 class="ci-heading">ci runs</h2>
+<table class="ci-table">
+  <thead>
+    <tr>
+      <th></th>
+      <th>sha</th>
+      <th>ref</th>
+      <th>queued</th>
+      <th>duration</th>
+    </tr>
+  </thead>
+  <tbody>
+  {% for run in runs %}
+    <tr>
+      <td><span class="ci-status-dot {{ run.state_color }}"></span></td>
+      <td><a href="/repo/{{ repo }}/ci/{{ run.id }}" class="ci-sha-link">{{ run.sha_short }}</a></td>
+      <td>{{ run.ref_short }}</td>
+      <td>{{ run.queued }}</td>
+      <td>{{ run.duration }}</td>
+    </tr>
+  {% else %}
+    <tr><td colspan="5" class="empty">no runs yet</td></tr>
+  {% endfor %}
+  </tbody>
 </table>
 {% endblock %}
diff --git a/templates/error.html b/templates/error.html
index b576e0e..b963f8b 100644
--- a/templates/error.html
+++ b/templates/error.html
@@ -3,13 +3,19 @@
 {% block title %}{{ title }}{% endblock %}
 
 {% block nav %}
-<nav style="padding:14px 56px;border-bottom:1px solid var(--rule);font-family:var(--font-mono);font-size:14px;font-weight:500;letter-spacing:-0.2px;display:flex;justify-content:space-between;align-items:center">
-<div><span style="color:var(--mutedFaint)">quire</span> <span style="color:var(--rule2)">/</span> <span>{{ repo }}</span> <span style="color:var(--rule2)">/</span> <span style="color:var(--muted)">error</span></div>
-<div style="font-size:11px;color:var(--mutedFaint)">press [?] for shortcuts</div>
+<nav class="page-nav">
+  <div class="breadcrumbs">
+    <span class="crumb-faint">quire</span>
+    <span class="sep">/</span>
+    <span>{{ repo }}</span>
+    <span class="sep">/</span>
+    <span class="crumb-muted">error</span>
+  </div>
+  <div class="shortcuts">press [?] for shortcuts</div>
 </nav>
 {% endblock %}
 
 {% block content %}
-<p style="color:var(--bad);font-family:var(--font-mono)">{{ title }}</p>
-<pre style="font-family:var(--font-mono);font-size:12px;background:var(--code);padding:14px 18px;overflow:auto">{{ detail }}</pre>
+<p class="error-title">{{ title }}</p>
+<pre class="error-detail">{{ detail }}</pre>
 {% endblock %}