QDB Theme Fidelity Checklist

Working checklist, not a committed FDP artifact. Check items off as they land. Each item names the concrete gap between what we have now and the archived reference (bash.org 2007 for base look, qdb.us 2016 for voting UX).

A. Highest-impact, CSS-only (scoped to :root[data-theme="qdb"])

B. Needs a template/JS change, not just CSS

C. New chrome the original had that we have none of

D. qdb.us refinements not yet carried over

    1. _New threads.vote_count column, accumulated in both ReadModelBuilder (full rebuild) and IncrementalReadModelUpdater (incremental path): counts every distinct (identity, tag) upvote/downvote event, not gated by approval (unlike score_total) — this is "total votes cast by anyone," a genuinely different, more honest number than the approval-gated score. TagScore::isVoteTag() added so upvote/downvote are identified in one place. ThreadRepository's two SELECTs and ThreadRowSupport updated to carry it through._

    2. _LocalWriteService::applyThreadTag() now also returns vote_count (new currentThreadVoteCount() helper mirroring the score one); TagApiController includes it in the AJAX response text._

    3. _thread_reactions.js gained a third score format, bare-ratio ("(score/total)"), alongside the existing labeled/bare ones — bindThreadReactions now parses vote_count from the response and passes it through. quote_card.php sets data-score-format= "bare-ratio" and renders (score/voteCount) server-side too._

    _Verified end-to-end for real, not just structurally: applied a real upvote via LocalWriteService using the fixture's real identity (openpgp:0168ff..., which happens to be pre-approved there), got back score_total=1 vote_count=1, and confirmed the board re-rendered (1/1). This is more verification depth than Stage 4 managed for plain upvote/downvote (which only got structural/code-path verification), so this closes that earlier gap too._ _Schema note: this is a read-model (cache) column, not a canonical-data migration — any already-running deployment just needs one ./v3 rebuild after this ships; existing canonical thread-label records are re-aggregated from scratch with full fidelity, nothing is lost. Did this myself for local dev's state/cache/post_index_qdb.sqlite3._

E. Lower priority / cosmetic


My suggested order: A (all CSS-only, biggest visual payoff, zero risk) → the color-coding and button-wording parts of B → C's footer/header → then D/reopening the vote-ratio decision only if you still want it after seeing A–C.

Two items need your decision before I touch them: hiding the modern board chrome (B) and whether to reopen the vote-ratio display (D) — both change things we deliberately scoped out in Step 2.

Post-checklist fixes

  • Orange-on-orange text on /tools/: the C2 "flatten the nav" item added a blanket :root[data-theme="qdb"] a { color: var(--line) } so plain links read orange. That unintentionally also applied to anchor-styled buttons elsewhere in the app — .tool-launcher-button (tools.css) sets its own background: var(--button-bg), which is the same orange as --line in this theme, so the text became invisible. Fixed by giving .tool-launcher-button (and .offline-health-open-archive, same pattern, defensively) an explicit color: var(--active-ink) rather than relying on the generic link rule. Checked every other var(--button-bg)/var(--active-bg) background usage site-wide for the same exposure — this was the only real instance.