// 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 <mark>; 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 <del>/<ins> 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.
.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;
}
// 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);
}
}
}