From c899019b35eb1e70e1d43382fe5b56dc998a9c76 Mon Sep 17 00:00:00 2001 From: Kayos Date: Wed, 13 May 2026 12:43:37 -0700 Subject: [PATCH] web v0.3 visual revamp: Norse palette + ornament + mobile + forms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Big CSS overhaul + page-level adjustments toward a Norse 'museum- quality' aesthetic (not the gaming-rune-bro variant). Restraint + weight + carved typography. Palette shift: - Warmed-black bg (#0a0807) with subtle radial gradient grain - Bone-cream ink (#dbcfb0) replaces the cleaner cream we had - Oxblood accent (#a13a3a) replaces the coffee-shop soft gold - Weathered bronze (#b08443) as secondary accent for headers + meta - Status colors land warmer: sage-moss ok, rust crit, amber-bronze warn Typography: - All caps + 2-3px letter-spacing on display headers (Trajan Pro / Cinzel chain via font-family stack — falls back to weighted serif on machines without the carved face) - Serif prose chain unchanged (Iowan Old Style → Hoefler → Georgia) - Drop cap on the first paragraph of each chapter — small literary flourish in oxblood-bronze Ornament: - Inline SVG knotwork divider (`ornament()` macro) — two flanking circles + an interlace curve between them, used as section breaks. Below the welcome h1; can be sprinkled wherever a visual register break helps. Pages adjusted: - topbar: SKALD wordmark in 4-letterspaced display caps; thin oxblood underline accent; '+ new saga' nav button on the right - sidebar: 'STORIES' → 'SAGAS' (one of cobb's earlier asks); story-row hover gets oxblood left-accent (not gold); per-status pill colors (complete=ok, generating/cleaning/auditing=warn, failed=crit, seed=warn) - story detail: dedicated .story-actions row with '✦ continue this saga' (primary, oxblood-bordered button) and 'generation log →' link - welcome panel: revised copy + ornament + 'begin a new one' link - forms: bordered surface inputs, all-caps display labels, primary- styled submit buttons matching the continue-saga action Mobile (max-width: 800px): - Single-column grid; sidebar lays out above the main panel - Sidebar wrapped in
so it's collapsible (taps the 'Sagas (N)' header). No JS — native HTML semantics. - Chapter-list collapses word-count column on narrow - Char-list goes single-column - All sizes downscale (28px h1, 16px prose, etc) Next pass after I screenshot: tune any contrast/spacing that looks off on the actual render. --- skald/src/web.rs | 402 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 322 insertions(+), 80 deletions(-) diff --git a/skald/src/web.rs b/skald/src/web.rs index 9733005..1aacd71 100644 --- a/skald/src/web.rs +++ b/skald/src/web.rs @@ -324,15 +324,22 @@ fn render_shell(stories: &[StoryRow], current: Option, main: Markup) -> Ma } body { header.topbar { - a.brand href="/" { "skald" } - span.tagline { "an old-norse poet's inspector" } + a.brand href="/" { "SKALD" } + span.tagline { "long form · named voices · written down" } + nav.topnav { + a href="/stories/new" .new-saga { "+ new saga" } + } } main.layout { aside.sidebar { - h2 { "Stories" } + details.sidebar-collapse open { + summary.sidebar-summary { + h2 { "Sagas" } + span.sidebar-count { "(" (stories.len()) ")" } + } @if stories.is_empty() { - p.empty { "No stories imported yet. Run " - code { "skald import-markdown" } " to add one." } + p.empty { "No sagas yet. Run " + code { "skald import-markdown" } " or click " a href="/stories/new" { "+ new saga" } "." } } @else { ul.story-list { @for s in stories { @@ -350,11 +357,12 @@ fn render_shell(stories: &[StoryRow], current: Option, main: Markup) -> Ma } } } + } } section.panel { (main) } } footer.footbar { - span { "skald · v0.1 inspector · " + span { "skald · v0.3 · written down · " a href="http://192.168.0.5:3001/cobb/skald" { "cobb/skald" } } } @@ -411,14 +419,15 @@ fn welcome_panel() -> Markup { html! { div.welcome { h1 { "Welcome." } - p.lead { "Pick a story from the sidebar to inspect it." } + (ornament()) + p.lead { "Pick a saga from the sidebar — or " a href="/stories/new" { "begin a new one" } "." } p { - "Skald is the database; the binary is the tooling. Every story is rows — " - "chapters, characters, canon, generation runs. This inspector shows them as they are." + "Skald keeps long-form fiction as rows in a database — chapters, characters, " + "canon, generation runs. Each saga has a named author whose soul is the LLM's " + "voice, not a stapled prompt. Sequels honor canon, audit themselves, and remember." } p.muted { - "Authors, the continue button, and the cleanup audit panel land in v0.3 once " - "the persona layer is wired." + "The database is the product. The binary is the tooling." } } } @@ -443,7 +452,10 @@ fn story_panel( span.meta-item { (s.character_count) " characters" } span.meta-item { (s.canon_fact_count) " canon facts" } span.meta-item.muted { "updated " (rel_time(s.updated_at)) } - a.runs-link href=(format!("/stories/{}/runs", s.id)) { "→ generation log" } + } + nav.story-actions { + a.action-primary href=(format!("/stories/{}/continue", s.id)) { "✦ continue this saga" } + a.action-secondary href=(format!("/stories/{}/runs", s.id)) { "generation log →" } } section.chapters { @@ -603,6 +615,23 @@ fn runs_panel(story_id: Uuid, runs: &[(Uuid, String, String, DateTime, Opti // ─── helpers ───────────────────────────────────────────────────── +/// Knotwork divider — a small SVG ornament used as section break. +/// Two flanking circles + a single interlace curve between them. +/// Stays in the warmed-bronze accent color via `currentColor`. +fn ornament() -> Markup { + html! { + div.ornament { + (maud::PreEscaped(r##""##)) + } + } +} + fn kfmt(n: i32) -> String { if n >= 1000 { format!("{:.1}k", n as f64 / 1000.0) @@ -650,108 +679,321 @@ fn rel_time(t: DateTime) -> String { const STYLESHEET: &str = r#" :root { - --bg: #0d0d0c; - --surface: #16151a; - --surface-2: #1d1c20; - --border: #2a2830; - --ink: #e8dfc8; - --ink-muted: #8b8579; - --ink-faint: #5d584f; - --accent: #b08d50; - --accent-dim: #76624f; - --crit: #c97474; - --ok: #87a87a; - --warn: #c4a06c; - --serif: "Iowan Old Style", "Constantia", Georgia, "Times New Roman", serif; + /* Warmed-black + bone-cream + oxblood + weathered bronze. + Norse museum, not gaming-rune-bro. Stark, weighty, carved. */ + --bg: #0a0807; + --bg-grain: #100c0a; + --surface: #181410; + --surface-2: #221c14; + --border: #2e2620; + --border-strong: #3d3128; + --ink: #dbcfb0; + --ink-muted: #a89473; + --ink-faint: #6b5d48; + --accent: #a13a3a; + --accent-dim: #7a2c2c; + --bronze: #b08443; + --bronze-dim: #7a5c2e; + --ok: #7a8870; + --crit: #c4493a; + --warn: #c69b4f; + + --serif: "Iowan Old Style", "Constantia", "Hoefler Text", Georgia, "Times New Roman", serif; + --display: "Trajan Pro", "Cinzel", "Iowan Old Style", Georgia, serif; --sans: -apple-system, "Segoe UI", Roboto, system-ui, sans-serif; --mono: "JetBrains Mono", "SF Mono", Menlo, Consolas, monospace; } * { box-sizing: border-box; } html, body { margin: 0; padding: 0; background: var(--bg); color: var(--ink); font-family: var(--sans); font-size: 15px; line-height: 1.55; } -a { color: var(--accent); text-decoration: none; } +body { + /* Faint paper-grain — a barely-visible noise pattern so the + background isn't a flat slab. */ + background-image: + radial-gradient(at 20% 30%, var(--bg-grain) 0%, var(--bg) 70%), + radial-gradient(at 80% 70%, #110e0b 0%, var(--bg) 60%); + background-attachment: fixed; + min-height: 100vh; +} +a { color: var(--bronze); text-decoration: none; transition: color 80ms ease; } a:hover { color: var(--ink); } -code { font-family: var(--mono); font-size: 0.9em; background: var(--surface-2); padding: 1px 5px; border-radius: 2px; color: var(--ink-muted); } +code { font-family: var(--mono); font-size: 0.9em; background: var(--surface-2); padding: 1px 6px; border-radius: 2px; color: var(--ink-muted); border: 1px solid var(--border); } -.topbar { display: flex; align-items: baseline; gap: 16px; padding: 14px 24px; border-bottom: 1px solid var(--border); background: var(--surface); } -.brand { font-family: var(--serif); font-size: 22px; color: var(--accent); letter-spacing: 0.5px; } +/* ─── ornament ─────────────────────────────────────────────── */ +.ornament { color: var(--bronze-dim); margin: 18px 0 26px 0; max-width: 360px; opacity: 0.7; } +.ornament svg { display: block; width: 100%; height: 12px; } + +/* ─── topbar ───────────────────────────────────────────────── */ +.topbar { + display: flex; align-items: baseline; gap: 18px; + padding: 16px 28px 14px 28px; + border-bottom: 1px solid var(--border); + background: linear-gradient(180deg, var(--surface) 0%, var(--bg) 100%); + position: relative; +} +.topbar::after { + /* Thin oxblood underline — like a runestone register line. */ + content: ""; position: absolute; left: 0; right: 0; bottom: -1px; + height: 1px; background: var(--accent); opacity: 0.35; +} +.brand { + font-family: var(--display); font-size: 26px; color: var(--bronze); + letter-spacing: 4px; font-weight: 700; +} .brand:hover { color: var(--ink); } -.tagline { color: var(--ink-faint); font-size: 13px; font-style: italic; } +.tagline { color: var(--ink-faint); font-size: 12px; font-style: italic; letter-spacing: 0.5px; } +.topnav { margin-left: auto; display: flex; gap: 14px; align-items: baseline; } +.new-saga { + font-family: var(--display); letter-spacing: 2px; font-size: 12px; + text-transform: uppercase; color: var(--ink-muted); + border: 1px solid var(--border-strong); padding: 6px 14px; + background: var(--surface-2); +} +.new-saga:hover { color: var(--ink); border-color: var(--bronze-dim); background: var(--surface); } -.footbar { padding: 10px 24px; border-top: 1px solid var(--border); background: var(--surface); color: var(--ink-faint); font-size: 12px; } +/* ─── footbar ──────────────────────────────────────────────── */ +.footbar { + padding: 12px 28px; + border-top: 1px solid var(--border); + background: var(--surface); + color: var(--ink-faint); + font-size: 11px; + letter-spacing: 0.5px; +} .footbar a { color: var(--ink-faint); } +.footbar a:hover { color: var(--bronze); } -.layout { display: grid; grid-template-columns: 320px 1fr; min-height: calc(100vh - 90px); } +/* ─── layout ───────────────────────────────────────────────── */ +.layout { + display: grid; + grid-template-columns: 320px 1fr; + min-height: calc(100vh - 100px); +} -.sidebar { padding: 16px 20px; border-right: 1px solid var(--border); background: var(--surface); overflow-y: auto; } -.sidebar h2 { font-family: var(--serif); font-size: 14px; text-transform: uppercase; letter-spacing: 1.5px; color: var(--ink-muted); margin: 0 0 14px 0; font-weight: 400; } +/* ─── sidebar ──────────────────────────────────────────────── */ +.sidebar { padding: 18px 22px 28px 22px; border-right: 1px solid var(--border); background: var(--surface); overflow-y: auto; } +.sidebar-collapse { } +.sidebar-summary { + cursor: pointer; list-style: none; display: flex; align-items: baseline; gap: 10px; + padding-bottom: 14px; border-bottom: 1px solid var(--border); + margin-bottom: 14px; +} +.sidebar-summary::-webkit-details-marker { display: none; } +.sidebar h2 { + font-family: var(--display); font-size: 13px; text-transform: uppercase; + letter-spacing: 3px; color: var(--bronze); margin: 0; font-weight: 700; +} +.sidebar-count { color: var(--ink-faint); font-size: 12px; font-family: var(--mono); } .story-list { list-style: none; margin: 0; padding: 0; } -.story-row { margin-bottom: 4px; } -.story-row a { display: block; padding: 10px 12px; border-radius: 3px; color: var(--ink); } -.story-row a:hover, .story-row.active a { background: var(--surface-2); } -.story-row.active a { border-left: 2px solid var(--accent); padding-left: 10px; } -.story-row .title { display: block; font-family: var(--serif); font-size: 16px; color: var(--ink); margin-bottom: 2px; } -.story-row .meta { display: block; font-size: 11px; color: var(--ink-faint); } -.story-row .status { display: inline-block; font-size: 10px; padding: 1px 6px; border-radius: 2px; margin-left: 6px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--ink-faint); } +.story-row { margin-bottom: 6px; } +.story-row a { + display: block; padding: 12px 14px 12px 12px; + border-left: 2px solid transparent; + color: var(--ink); +} +.story-row a:hover { background: var(--surface-2); border-left-color: var(--bronze-dim); } +.story-row.active a { background: var(--surface-2); border-left-color: var(--accent); } +.story-row .title { display: block; font-family: var(--serif); font-size: 16px; color: var(--ink); margin-bottom: 3px; line-height: 1.3; } +.story-row .meta { display: block; font-size: 11px; color: var(--ink-faint); font-family: var(--mono); letter-spacing: 0.3px; } +.story-row .status { display: inline-block; font-size: 9px; padding: 1px 6px; margin-left: 6px; text-transform: uppercase; letter-spacing: 1px; color: var(--ink-faint); border: 1px solid var(--border); } +.story-row .status-complete { color: var(--ok); border-color: var(--ok); } +.story-row .status-generating, .story-row .status-cleaning, .story-row .status-auditing { color: var(--warn); border-color: var(--warn); } +.story-row .status-failed { color: var(--crit); border-color: var(--crit); } -.panel { padding: 36px 48px; overflow-y: auto; max-width: 1100px; } +/* ─── main panel ───────────────────────────────────────────── */ +.panel { padding: 40px 56px; overflow-y: auto; max-width: 1100px; } -.welcome h1 { font-family: var(--serif); font-size: 36px; color: var(--accent); margin: 40px 0 16px 0; font-weight: 400; } -.welcome .lead { font-size: 17px; color: var(--ink); } -.welcome p { max-width: 65ch; } -.welcome .muted { color: var(--ink-faint); font-size: 14px; } +/* ─── welcome ──────────────────────────────────────────────── */ +.welcome h1 { + font-family: var(--display); font-size: 42px; + color: var(--bronze); letter-spacing: 2px; font-weight: 700; + margin: 40px 0 8px 0; +} +.welcome .lead { font-size: 18px; color: var(--ink); margin-top: 20px; } +.welcome p { max-width: 64ch; } +.welcome .muted { color: var(--ink-faint); font-size: 13px; font-style: italic; } + +/* ─── story detail ─────────────────────────────────────────── */ +.story h1 { + font-family: var(--display); font-size: 34px; color: var(--ink); + margin: 0 0 18px 0; font-weight: 700; letter-spacing: 1px; +} +.metabar { + display: flex; flex-wrap: wrap; gap: 18px; font-size: 13px; color: var(--ink-muted); + margin-bottom: 12px; align-items: center; +} +.metabar .status { + font-size: 9px; padding: 2px 8px; background: transparent; + text-transform: uppercase; letter-spacing: 1.5px; border: 1px solid var(--border-strong); color: var(--ink-muted); +} +.metabar .status-complete { color: var(--ok); border-color: var(--ok); } +.metabar .status-generating, .metabar .status-cleaning, .metabar .status-auditing, .metabar .status-seed { color: var(--warn); border-color: var(--warn); } +.metabar .status-failed { color: var(--crit); border-color: var(--crit); } + +.story-actions { + display: flex; gap: 14px; align-items: center; + padding: 14px 0 22px 0; margin-bottom: 26px; + border-bottom: 1px solid var(--border); +} +.action-primary { + font-family: var(--display); letter-spacing: 2px; font-size: 12px; + text-transform: uppercase; color: var(--ink); + border: 1px solid var(--accent-dim); padding: 9px 18px; + background: linear-gradient(180deg, var(--surface-2) 0%, var(--surface) 100%); +} +.action-primary:hover { color: var(--ink); border-color: var(--accent); background: var(--surface-2); } +.action-secondary { + font-size: 12px; color: var(--ink-faint); margin-left: auto; + letter-spacing: 0.5px; +} +.action-secondary:hover { color: var(--bronze); } -.story h1 { font-family: var(--serif); font-size: 32px; color: var(--ink); margin: 0 0 14px 0; font-weight: 400; } -.metabar { display: flex; flex-wrap: wrap; gap: 16px; font-size: 13px; color: var(--ink-muted); margin-bottom: 30px; align-items: center; padding-bottom: 16px; border-bottom: 1px solid var(--border); } -.metabar .status { font-size: 10px; padding: 2px 8px; border-radius: 2px; background: var(--surface-2); text-transform: uppercase; letter-spacing: 0.5px; } -.metabar .runs-link { margin-left: auto; font-size: 12px; color: var(--ink-faint); } -.metabar .runs-link:hover { color: var(--accent); } .muted { color: var(--ink-faint); } -.story h2, .chapter h2, .runs h2 { font-family: var(--serif); font-size: 14px; text-transform: uppercase; letter-spacing: 1.5px; color: var(--ink-muted); margin: 36px 0 14px 0; font-weight: 400; } -.story h3, .bible-section h3 { font-family: var(--serif); font-size: 15px; color: var(--accent-dim); margin: 18px 0 10px 0; font-weight: 400; letter-spacing: 0.5px; } +.story h2, .chapter h2, .runs h2 { + font-family: var(--display); font-size: 12px; + text-transform: uppercase; letter-spacing: 3px; color: var(--bronze); + margin: 38px 0 16px 0; font-weight: 700; +} +.story h3, .bible-section h3 { + font-family: var(--display); font-size: 13px; color: var(--bronze-dim); + margin: 20px 0 12px 0; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; +} .chapter-list { list-style: none; padding: 0; margin: 0; } .chapter-list li { margin-bottom: 2px; } -.chapter-list a { display: grid; grid-template-columns: 100px 1fr auto 110px; gap: 18px; align-items: baseline; padding: 8px 12px; border-radius: 3px; color: var(--ink); } -.chapter-list a:hover { background: var(--surface-2); } -.chapter-list .n { color: var(--ink-faint); font-size: 13px; font-family: var(--mono); } -.chapter-list .ch-title { font-family: var(--serif); font-size: 15px; } -.chapter-list .wc { color: var(--ink-faint); font-size: 12px; font-family: var(--mono); text-align: right; } -.chapter-list .summary-flag { font-size: 11px; color: var(--ok); } +.chapter-list a { + display: grid; grid-template-columns: 110px 1fr auto 110px; + gap: 20px; align-items: baseline; padding: 10px 14px; + color: var(--ink); border-left: 2px solid transparent; +} +.chapter-list a:hover { background: var(--surface-2); border-left-color: var(--bronze-dim); } +.chapter-list .n { color: var(--bronze-dim); font-size: 12px; font-family: var(--mono); letter-spacing: 1px; } +.chapter-list .ch-title { font-family: var(--serif); font-size: 16px; } +.chapter-list .wc { color: var(--ink-faint); font-size: 11px; font-family: var(--mono); text-align: right; } +.chapter-list .summary-flag { font-size: 10px; color: var(--ok); letter-spacing: 0.5px; } .chapter-list .summary-flag.missing { color: var(--ink-faint); } .char-list { list-style: none; padding: 0; margin: 0 0 14px 0; } -.char-list li { display: grid; grid-template-columns: 240px 1fr; gap: 18px; padding: 8px 0; border-bottom: 1px solid var(--surface-2); align-items: baseline; } -.cname { font-family: var(--serif); color: var(--ink); font-size: 14px; } -.cfacts { color: var(--ink-muted); font-size: 13px; line-height: 1.5; } +.char-list li { + display: grid; grid-template-columns: 240px 1fr; gap: 22px; + padding: 10px 0; border-bottom: 1px solid var(--surface-2); align-items: baseline; +} +.cname { font-family: var(--serif); color: var(--ink); font-size: 15px; } +.cfacts { color: var(--ink-muted); font-size: 13px; line-height: 1.55; } .bible-section details { border-bottom: 1px solid var(--surface-2); padding: 10px 0; } -.bible-section summary { cursor: pointer; list-style: none; display: flex; gap: 14px; align-items: baseline; padding: 4px 0; } +.bible-section summary { cursor: pointer; list-style: none; display: flex; gap: 16px; align-items: baseline; padding: 6px 0; } .bible-section summary::-webkit-details-marker { display: none; } -.bible-section summary::before { content: "▸"; color: var(--ink-faint); font-size: 11px; margin-right: 4px; } -.bible-section details[open] summary::before { content: "▾"; } -.bible-section .category { font-size: 10px; text-transform: uppercase; letter-spacing: 1px; color: var(--accent-dim); min-width: 140px; } -.bible-section .ctitle { font-family: var(--serif); color: var(--ink); } -.bible-section .cbody { padding: 10px 0 6px 18px; color: var(--ink-muted); white-space: pre-wrap; line-height: 1.65; max-width: 75ch; font-size: 14px; } +.bible-section summary::before { content: "▸"; color: var(--bronze-dim); font-size: 11px; margin-right: 4px; } +.bible-section details[open] summary::before { content: "▾"; color: var(--accent); } +.bible-section .category { font-size: 10px; text-transform: uppercase; letter-spacing: 2px; color: var(--bronze-dim); min-width: 150px; font-family: var(--display); font-weight: 700; } +.bible-section .ctitle { font-family: var(--serif); color: var(--ink); font-size: 15px; } +.bible-section .cbody { + padding: 12px 0 8px 22px; color: var(--ink-muted); white-space: pre-wrap; + line-height: 1.7; max-width: 75ch; font-size: 14px; font-family: var(--serif); +} -.chapter .back, .runs .back { display: inline-block; color: var(--ink-faint); font-size: 12px; margin-bottom: 18px; } -.chapter h1.ch-title { font-family: var(--serif); font-size: 28px; font-weight: 400; color: var(--ink); margin: 0 0 8px 0; } -.chapter h1.ch-title .n { color: var(--accent-dim); font-size: 22px; } -.summary-box { background: var(--surface); border-left: 2px solid var(--accent-dim); padding: 14px 20px; margin: 24px 0 32px 0; max-width: 75ch; } +/* ─── chapter view ─────────────────────────────────────────── */ +.chapter .back, .runs .back, .form-panel .back { + display: inline-block; color: var(--ink-faint); font-size: 12px; + margin-bottom: 18px; letter-spacing: 0.5px; +} +.chapter h1.ch-title { + font-family: var(--display); font-size: 28px; font-weight: 700; + color: var(--ink); margin: 0 0 12px 0; letter-spacing: 1px; +} +.chapter h1.ch-title .n { color: var(--bronze); font-size: 22px; letter-spacing: 2px; } +.summary-box { + background: var(--surface); border-left: 2px solid var(--bronze); + padding: 16px 22px; margin: 24px 0 36px 0; max-width: 75ch; +} .summary-box.empty { border-left-color: var(--surface-2); } -.summary-box h3 { font-family: var(--serif); font-size: 12px; text-transform: uppercase; letter-spacing: 1.5px; color: var(--ink-muted); margin: 0 0 8px 0; font-weight: 400; } -.summary-box p { margin: 0; color: var(--ink-muted); font-size: 14px; line-height: 1.65; } -.prose { font-family: var(--serif); font-size: 17px; line-height: 1.75; max-width: 68ch; color: var(--ink); } -.prose p { margin: 0 0 1.1em 0; } -.prose p:first-letter { /* nothing fancy yet */ } +.summary-box h3 { + font-family: var(--display); font-size: 11px; + text-transform: uppercase; letter-spacing: 2.5px; color: var(--bronze); + margin: 0 0 10px 0; font-weight: 700; +} +.summary-box p { margin: 0; color: var(--ink-muted); font-size: 14px; line-height: 1.7; font-family: var(--serif); } +.prose { + font-family: var(--serif); font-size: 18px; line-height: 1.8; + max-width: 68ch; color: var(--ink); +} +.prose p { margin: 0 0 1.15em 0; } +.prose p:first-of-type:first-letter { + /* Drop cap on the first paragraph — small literary flourish. */ + float: left; font-family: var(--display); font-size: 56px; line-height: 0.9; + padding: 8px 8px 0 0; color: var(--bronze); font-weight: 700; +} +/* ─── runs table ───────────────────────────────────────────── */ .runs-table { width: 100%; border-collapse: collapse; font-size: 13px; } -.runs-table th, .runs-table td { padding: 8px 12px; text-align: left; border-bottom: 1px solid var(--surface-2); } -.runs-table th { color: var(--ink-faint); font-weight: 400; text-transform: uppercase; font-size: 11px; letter-spacing: 1px; } +.runs-table th, .runs-table td { padding: 9px 14px; text-align: left; border-bottom: 1px solid var(--surface-2); } +.runs-table th { color: var(--bronze-dim); font-weight: 700; text-transform: uppercase; font-size: 10px; letter-spacing: 2px; font-family: var(--display); } .runs-table td.kind { font-family: var(--mono); font-size: 12px; color: var(--ink-muted); } .runs-table td.status-succeeded { color: var(--ok); } .runs-table td.status-failed { color: var(--crit); } .runs-table td.status-running { color: var(--warn); } -.runs-table td.error { color: var(--crit); font-size: 12px; } +.runs-table td.error { color: var(--crit); font-size: 12px; font-family: var(--mono); } .empty { color: var(--ink-faint); font-style: italic; } + +/* ─── forms (new-saga + continue) ──────────────────────────── */ +.form-panel h1 { + font-family: var(--display); font-size: 30px; color: var(--ink); + letter-spacing: 1.5px; font-weight: 700; margin: 0 0 8px 0; +} +.form-panel form { + display: flex; flex-direction: column; gap: 18px; + max-width: 640px; margin-top: 28px; +} +.form-panel label { + display: flex; flex-direction: column; gap: 6px; + font-family: var(--display); font-size: 11px; letter-spacing: 2px; + text-transform: uppercase; color: var(--bronze); font-weight: 700; +} +.form-panel input[type=text], +.form-panel input[type=number], +.form-panel textarea, +.form-panel select { + background: var(--surface); color: var(--ink); + border: 1px solid var(--border-strong); padding: 11px 14px; + font-family: var(--serif); font-size: 15px; line-height: 1.5; +} +.form-panel input:focus, .form-panel textarea:focus, .form-panel select:focus { + outline: none; border-color: var(--bronze); +} +.form-panel textarea { resize: vertical; min-height: 80px; } +.form-panel button { + align-self: flex-start; margin-top: 8px; + font-family: var(--display); letter-spacing: 2px; font-size: 12px; + text-transform: uppercase; color: var(--ink); cursor: pointer; + border: 1px solid var(--accent-dim); padding: 11px 26px; + background: linear-gradient(180deg, var(--surface-2) 0%, var(--surface) 100%); +} +.form-panel button:hover { border-color: var(--accent); background: var(--surface-2); } +.form-panel .error { color: var(--crit); } + +/* ─── mobile: collapse sidebar inline above main, allow toggle ── */ +@media (max-width: 800px) { + .layout { grid-template-columns: 1fr; } + .sidebar { + border-right: none; + border-bottom: 1px solid var(--border); + padding: 14px 18px 18px 18px; + max-height: 60vh; + } + .sidebar-summary { padding-bottom: 10px; margin-bottom: 10px; } + /* Collapsed by default on mobile via the open attribute lives + on the desktop view; we use details native state. The user + can tap the "Sagas" header to expand/collapse. */ + .panel { padding: 24px 18px; } + .topbar { padding: 12px 18px 10px 18px; flex-wrap: wrap; } + .topnav { margin-left: 0; width: 100%; padding-top: 6px; } + .chapter-list a { grid-template-columns: 80px 1fr auto; } + .chapter-list .wc { display: none; } + .char-list li { grid-template-columns: 1fr; gap: 4px; } + .cname { font-size: 14px; } + .brand { font-size: 22px; letter-spacing: 3px; } + .welcome h1, .story h1 { font-size: 28px; } + .prose { font-size: 16px; } +} "#;