diff --git a/backend/internal/web/templates/admin-prototype.html b/backend/internal/web/templates/admin-prototype.html
index 760c57d..fb2c876 100644
--- a/backend/internal/web/templates/admin-prototype.html
+++ b/backend/internal/web/templates/admin-prototype.html
@@ -163,6 +163,12 @@ body[data-variant="B"] .sheet, body[data-variant="C"] .sheet {
padding: 22px 20px 14px;
}
.topbar form { margin: 0; }
+.topbar-actions {
+ display: flex;
+ align-items: center;
+ gap: 18px;
+ margin-left: auto;
+}
.ghost {
position: relative;
@@ -210,7 +216,7 @@ main.page { padding: 0 20px 40px; }
.sec {
margin: 0;
padding: 18px 0 8px;
- font: 500 10px/1 var(--font-mono);
+ font: 500 11px/1 var(--font-mono);
letter-spacing: .2em;
text-transform: uppercase;
color: var(--mute-2);
@@ -230,12 +236,8 @@ main.page { padding: 0 20px 40px; }
color: var(--paper);
}
.verdict .attn { color: var(--patina); }
-.verdict .counts {
- font: 500 11px/1.5 var(--font-mono);
- letter-spacing: .08em;
- color: var(--mute);
-}
-.verdict .counts b { color: var(--paper-dim); font-weight: 600; }
+.verdict .counts { font: inherit; color: var(--mute); }
+.verdict .counts b { color: var(--paper-dim); font-weight: 400; }
/* ---- stats block: label / figure rows, every figure a link but a zero ---- */
.stats { margin: 4px 0 0; }
@@ -248,13 +250,13 @@ main.page { padding: 0 20px 40px; }
border-bottom: 1px solid var(--rule);
}
.stat .lbl {
- font: 500 10px/1 var(--font-mono);
+ font: 500 11px/1 var(--font-mono);
letter-spacing: .14em;
text-transform: uppercase;
color: var(--mute-2);
}
.stat .fig {
- font: 400 17px/1 var(--font-display);
+ font: 400 19px/1 var(--font-display);
color: var(--paper);
}
.stat a.fig:hover { color: var(--patina); }
@@ -262,15 +264,18 @@ main.page { padding: 0 20px 40px; }
.stat a.fig:hover { border-bottom-color: var(--patina); }
.stat .fig.zero { color: var(--mute); }
-/* ---- marks: patina is the admin accent; never ember, never danger ---- */
+/* ---- marks: patina is the admin accent; never ember, never danger.
+ A lane in trouble overrides to danger (#122 review); paused stays
+ patina — deliberate, not a problem. ---- */
.mark, .mark-p {
- font: 500 10px/1 var(--font-mono);
+ font: 500 11px/1 var(--font-mono);
letter-spacing: .14em;
text-transform: uppercase;
color: var(--patina);
white-space: nowrap;
}
.mark-faint { color: var(--mute-2); }
+.mark.bad { color: var(--danger); }
/* ================= VARIANT A — narrow, prose rows (760px) ================= */
/* No new tokens. Facts are a meta line under the title, like the reading
@@ -297,7 +302,7 @@ main.page { padding: 0 20px 40px; }
flex-wrap: wrap;
gap: 3px 10px;
align-items: baseline;
- font: 500 10px/1.5 var(--font-mono);
+ font: 500 11px/1.5 var(--font-mono);
letter-spacing: .1em;
text-transform: uppercase;
color: var(--mute-2);
@@ -309,7 +314,7 @@ main.page { padding: 0 20px 40px; }
.pst .pst-site { font: 400 19px/1.2 var(--font-display); color: var(--paper-dim); }
.pst .pst-facts {
margin-top: 4px;
- font: 500 10px/1.6 var(--font-mono);
+ font: 500 11px/1.6 var(--font-mono);
letter-spacing: .1em;
text-transform: uppercase;
color: var(--mute-2);
@@ -327,9 +332,9 @@ main.page { padding: 0 20px 40px; }
border-bottom: 1px solid var(--rule);
}
.lrow .lane-site { font: 400 19px/1.2 var(--font-display); color: var(--paper-dim); }
-.lrow.attention .lane-site { color: var(--patina); }
+.lrow.attention .lane-site { color: var(--danger); }
.lrow .lane-fact {
- font: 500 10px/1 var(--font-mono);
+ font: 500 11px/1 var(--font-mono);
letter-spacing: .14em;
text-transform: uppercase;
color: var(--mute-2);
@@ -364,7 +369,7 @@ main.page { padding: 0 20px 40px; }
.tbl .thead span {
padding: 10px 0 8px;
border-bottom: 1px solid var(--rule);
- font: 500 10px/1 var(--font-mono);
+ font: 500 11px/1 var(--font-mono);
letter-spacing: .14em;
text-transform: uppercase;
color: var(--mute-2);
@@ -373,13 +378,13 @@ main.page { padding: 0 20px 40px; }
.tbl .trow > * {
padding: 11px 0;
border-bottom: 1px solid var(--rule);
- font: 500 10px/1.6 var(--font-mono);
+ font: 500 11px/1.6 var(--font-mono);
letter-spacing: .1em;
text-transform: uppercase;
color: var(--mute-2);
}
.tbl .trow .c-title {
- font: 400 16px/1.3 var(--font-display);
+ font: 400 17px/1.3 var(--font-display);
letter-spacing: 0;
text-transform: none;
color: var(--paper);
@@ -388,27 +393,30 @@ main.page { padding: 0 20px 40px; }
.tbl .trow.attention .c-title { color: var(--patina); }
.tbl .trow .c-site { letter-spacing: .04em; }
.tbl .trow .c-ch { color: var(--paper-dim); }
-.tbl .trow .c-note { color: var(--mute-2); }
+.tbl .trow .c-note { display: flex; flex-wrap: wrap; gap: 2px 8px; color: var(--mute-2); }
.tbl .trow .c-act { text-align: right; }
-.tbl .trow .c-act .ghost { font-size: 10px; }
+.tbl .trow .c-act .ghost { font-size: 11px; }
.tbl .trow > .confirm-row { grid-column: 1 / -1; }
.tbl .trow .c-act .ghost:hover { color: var(--patina); border-bottom-color: var(--patina); }
/* Landing per-Site table: site + library shape + five outcome sums over 12h. */
-.tbl.sites { grid-template-columns: 120px 1fr repeat(8, 62px) 120px; }
-.tbl.sites .trow > * { font: 500 10px/1.6 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--mute-2); }
-.tbl.sites .c-site { font: 400 17px/1.3 var(--font-display); letter-spacing: 0; text-transform: none; color: var(--paper-dim); }
-.tbl.sites .c-state { color: var(--patina); }
+.tbl.sites { grid-template-columns: 120px 1fr repeat(8, 54px) minmax(150px, 1fr); }
+.tbl.sites .trow > * { font: 500 11px/1.6 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--mute-2); }
+.tbl.sites .c-site { font: 400 18px/1.3 var(--font-display); letter-spacing: 0; text-transform: none; color: var(--paper-dim); }
+.tbl.sites .c-state { color: var(--patina); white-space: nowrap; }
+.tbl.sites .c-state.bad { color: var(--danger); }
.tbl.sites .c-num { text-align: right; color: var(--paper-dim); }
/* Lanes page in B: one aligned row per Lane. */
-.tbl.lanes { grid-template-columns: 130px 60px 70px 64px 96px 1fr 190px; }
-.tbl.lanes .trow > * { font: 500 10px/1.6 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--mute-2); }
-.tbl.lanes .c-site { font: 400 17px/1.3 var(--font-display); letter-spacing: 0; text-transform: none; color: var(--paper-dim); }
-.tbl.lanes .trow.attention .c-site { color: var(--patina); }
-.tbl.lanes .c-skip { color: var(--patina); }
+.tbl.lanes { grid-template-columns: 130px 60px 70px 64px 96px 1fr 170px; }
+.tbl.lanes .trow > * { font: 500 11px/1.6 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--mute-2); }
+.tbl.lanes .c-site { font: 400 18px/1.3 var(--font-display); letter-spacing: 0; text-transform: none; color: var(--paper-dim); }
+.tbl.lanes .trow.attention .c-site { color: var(--danger); }
+.tbl.lanes .c-skip { white-space: nowrap; }
+.tbl.lanes .c-skip .bad { color: var(--danger); }
+.tbl.lanes .c-skip .ok { color: var(--patina); }
.tbl.lanes .c-ctrl { text-align: right; }
-.tbl.lanes .c-ctrl .ghost { font-size: 10px; }
+.tbl.lanes .c-ctrl .ghost { font-size: 11px; }
/* ========== VARIANT C — wide, two-line blocks (no table, no card) ========= */
/* Line one: title + action. Line two: every fact as one indented mono line.
@@ -431,7 +439,7 @@ main.page { padding: 0 20px 40px; }
flex-wrap: wrap;
gap: 4px 12px;
align-items: baseline;
- font: 500 10px/1.6 var(--font-mono);
+ font: 500 11px/1.6 var(--font-mono);
letter-spacing: .1em;
text-transform: uppercase;
color: var(--mute-2);
@@ -444,7 +452,7 @@ main.page { padding: 0 20px 40px; }
.pblk .p1 .mark { font-size: 10px; }
.pblk .p2 {
margin-top: 4px;
- font: 500 10px/1.6 var(--font-mono);
+ font: 500 11px/1.6 var(--font-mono);
letter-spacing: .1em;
text-transform: uppercase;
color: var(--mute-2);
@@ -453,14 +461,14 @@ main.page { padding: 0 20px 40px; }
/* Lane rows in C: site + state line, facts + controls line. */
.lblk { padding: 10px 0; border-bottom: 1px solid var(--rule); }
.lblk .l1 { display: flex; align-items: baseline; gap: 14px; font: 400 19px/1.2 var(--font-display); color: var(--paper-dim); }
-.lblk.attention .l1 { color: var(--patina); }
+.lblk.attention .l1 { color: var(--danger); }
.lblk .l2 {
margin-top: 4px;
display: flex;
flex-wrap: wrap;
gap: 4px 14px;
align-items: center;
- font: 500 10px/1.6 var(--font-mono);
+ font: 500 11px/1.6 var(--font-mono);
letter-spacing: .1em;
text-transform: uppercase;
color: var(--mute-2);
@@ -743,7 +751,7 @@ const SERIES = [
sighting: false, pending: false, orphan: true },
{ key: "demonic:return-of-the-sss-class-rankers", site: "demonic",
title: "Return of the SSS-Class Ranker", kind: "manga",
- ch: null, chLabel: "—", checked: null, readers: 1, cover: false, url: false,
+ ch: null, chLabel: "—", checked: 13 * 60, readers: 1, cover: false, url: false,
sighting: false, pending: false },
{ key: "novelfull:reverend-insanity", site: "novelfull",
title: "Reverend Insanity", kind: "novel",
@@ -866,10 +874,18 @@ function rowMarks(s) {
if (!s.cover) m.push("no cover");
if (s.sighting) m.push("reader sighting");
if (s.readers === 0) m.push("orphan");
- if (s.pending) m.push(`requested ${age(s.pendingAgo)}`);
return m;
}
+/* notes render as chips, capped at two with a +N tail — a wall of stacked
+ marks at list density reads as noise, not signal */
+function noteChips(s) {
+ const m = rowMarks(s);
+ const chips = m.slice(0, 2).map(x => `${x}`).join("");
+ const more = m.length - 2;
+ return chips + (more > 0 ? `+${more}` : "");
+}
+
/* ------------------------------------------------------------------ */
/* State: variant + page from the URL, filter/site/kind from search. */
/* ------------------------------------------------------------------ */
@@ -890,7 +906,7 @@ const esc = s => String(s).replace(/[&<>"']/g, c => ({ "&": "&", "<": "<"
/* ------------------------------------------------------------------ */
/* Shared chrome */
/* ------------------------------------------------------------------ */
-const mark = ``;
+const mark = ``;
function chrome(active) {
const nav = [
@@ -899,8 +915,10 @@ function chrome(active) {
`${label}`).join("");
return `${mark}BookmarkManager
- Library
-
+