// spec.sr.ht stylesheet. // // Mirrors the SourceHut service pattern (see paste.sr.ht/scss/main.scss and // compare.sr.ht/scss/main.scss): pull in the shared `base` partial (Bootstrap 4 // plus the SourceHut chrome — contrast, variables, nav, events, highlight, // dark) and then add only what is unique to the document views. // // Build: `make css`, which is `sassc -I /usr/share/sourcehut/scss scss/main.scss` // plus minify plus a content-hashed filename. The shared partials come from // core.sr.ht's `make install`; dart-sass works too for a local build. // // The output is EMBEDDED INTO THE BINARY (web/templates.go's //go:embed static), // so `make css` alone does not restyle a running daemon: build the CSS, then // `go build`, then restart. @import "base"; // Let scheme-aware widgets follow prefers-color-scheme, as compare.sr.ht does. :root { color-scheme: light dark; } // ---- Rendered document ---------------------------------------------------- .spec-doc { // Prose, not code: a comfortable measure matters more than filling the // column. The sidebar already takes a quarter of the width, so this only // bites on very wide screens. max-width: 46rem; h1, h2, h3, h4, h5, h6 { margin-top: 1.5rem; } // The first heading sits directly under the page title; the extra top margin // reads as a gap rather than as structure. > :first-child { margin-top: 0; } blockquote { padding-left: 0.75rem; border-left: 3px solid $gray-400; color: $gray-700; @media (prefers-color-scheme: dark) { border-left-color: $gray-700; color: $gray-300; } } table { @extend .table; width: auto; } img { max-width: 100%; } } // A wikilink that resolved to nothing. The renderer emits it as a span rather // than dropping it, so the read plane doubles as a link checker — which only // works if it is visibly different from a link that resolved. .wikilink-missing { color: $danger; text-decoration: line-through dotted; } // ---- Search --------------------------------------------------------------- .search-hit { margin-bottom: 0.75rem; } .search-snippet { color: $gray-700; // bleve wraps matched terms in ; the browser default is a yellow that // is unreadable on the dark chrome. mark { padding: 0; background: transparent; color: inherit; font-weight: 700; } @media (prefers-color-scheme: dark) { color: $gray-300; } } // ---- Proposal review ------------------------------------------------------ .proposal-actions { margin: 1rem 0; form { margin-right: 0.5rem; } } .proposal-doc { margin-top: 1.5rem; padding-top: 1rem; border-top: 1px solid $gray-300; @media (prefers-color-scheme: dark) { border-top-color: $gray-700; } } // ---- Prose diff ----------------------------------------------------------- // // The renderer (web/diff.go) emits this markup: a hunk per heading path, a // block per change, and inline / spans or a two-column view depending // on how badly the block was rewritten. Colours follow Bootstrap's success and // danger so added and removed read the same here as everywhere else. // // Every block of the proposed document is on the page, because every block can // be commented on — so the visual weight is what keeps this a diff rather than a // document dump. A changed block is bordered, tinted and full size; an unchanged // one is a collapsed, dimmed, borderless line. That contrast is load-bearing: // remove it and a reviewer can no longer see at a glance what the agent did. .prosediff { font-size: 0.95rem; .ph-hunk { margin-bottom: 1rem; } .ph-path { font-family: $font-family-monospace; font-size: 0.8rem; color: $gray-600; padding: 0.15rem 0; @media (prefers-color-scheme: dark) { color: $gray-400; } } .ph-block { padding: 0.35rem 0.6rem; margin: 0.2rem 0; border-left: 3px solid transparent; border-radius: 2px; } .ph-label { display: block; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.03em; color: $gray-600; margin-bottom: 0.15rem; @media (prefers-color-scheme: dark) { color: $gray-400; } } .ph-insert { border-left-color: $success; background: rgba($success, 0.08); } .ph-delete { border-left-color: $danger; background: rgba($danger, 0.08); } .ph-modify { border-left-color: $gray-400; background: rgba($gray-500, 0.06); } .ph-move { border-left-color: $info; color: $gray-600; font-style: italic; } // Unchanged text: present, addressable, and deliberately quiet. It is a //
collapsed to one line, so a long untouched section costs a few // dim rows rather than screens of prose between the changes. .ph-context { padding: 0; margin: 0; border-left-color: transparent; color: $gray-600; @media (prefers-color-scheme: dark) { color: $gray-500; } > .ph-context-label { padding: 0.1rem 0.6rem; font-size: 0.85rem; cursor: pointer; list-style-position: outside; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } // Expanded, it indents under its own summary and stays uncoloured: it is // still context, even while being read. > .ph-body, > .ph-code, > .ph-threads, > .ph-form { margin-left: 1.2rem; } &[open] > .ph-context-label { color: $gray-700; @media (prefers-color-scheme: dark) { color: $gray-400; } } } // Inline marks: a deletion is struck through in danger, an insertion is // underlined in success. Both keep a faint background so a one-word change is // visible without reading the colour. del { text-decoration: line-through; color: $danger; background: rgba($danger, 0.12); text-decoration-thickness: 1px; } ins { text-decoration: none; color: darken($success, 8%); background: rgba($success, 0.14); @media (prefers-color-scheme: dark) { color: lighten($success, 8%); } } // The two-column fallback for shredded blocks: old on the left, new on the // right, stacking on a narrow screen so it never overflows the page. .ph-cols { display: flex; flex-wrap: wrap; gap: 0.75rem; } .ph-col { flex: 1 1 20rem; min-width: 0; padding: 0.4rem 0.6rem; border-radius: 2px; } .ph-old { background: rgba($danger, 0.06); } .ph-new { background: rgba($success, 0.06); } // Code / frontmatter line diffs keep their wrapping and are read line by line. .ph-code { margin: 0; padding: 0.25rem 0; background: transparent; white-space: pre-wrap; word-break: break-word; .ph-line-del { display: block; background: rgba($danger, 0.1); } .ph-line-ins { display: block; background: rgba($success, 0.1); } } } // ---- Review threads ------------------------------------------------------- // // Rendered both inside a diff block (web/diff.go executes "blockthreads" into // the block's markup) and, for comments whose anchor is lost, in the page's own // area — so these styles are outside .prosediff and apply in both places. .ph-threads { margin: 0.35rem 0 0.15rem; } .ph-thread { margin: 0.35rem 0; padding: 0.4rem 0.6rem; border-left: 3px solid $info; background: rgba($info, 0.06); border-radius: 2px; // A resolved thread is history: it stays readable and stays where it was, but // stops asking for attention the way an open one does. &.ph-thread-resolved { border-left-color: $gray-400; background: transparent; opacity: 0.7; } } .ph-thread-head { font-size: 0.8rem; margin-bottom: 0.2rem; .ph-author { font-weight: 700; } .ph-when { color: $gray-600; margin-left: 0.35rem; @media (prefers-color-scheme: dark) { color: $gray-400; } } .badge { margin-left: 0.35rem; } } // A comment is prose someone typed, newlines included; the server escapes it and // the browser must not then reflow it into one paragraph. .ph-comment-body { white-space: pre-wrap; word-break: break-word; } .ph-reply { margin-top: 0.4rem; padding-left: 0.6rem; border-left: 2px solid $gray-400; @media (prefers-color-scheme: dark) { border-left-color: $gray-700; } } .ph-thread-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.4rem; } // The compose and reply forms fold away behind a summary: the review page shows // one control per block, and a textarea per block would bury the diff. .ph-form { font-size: 0.85rem; > summary { cursor: pointer; color: $gray-600; @media (prefers-color-scheme: dark) { color: $gray-400; } } textarea { margin: 0.3rem 0; } } .ph-compose { margin: 0.2rem 0 0.4rem; } // Comments whose block is gone. The warning border is the point: they are shown // because dropping them would hide a critique, and marked because they no longer // describe anything on this page. .ph-lost { border-top-color: $warning; .ph-thread { border-left-color: $warning; background: rgba($warning, 0.06); } }