/* =========================================== RESPONSIVE, 768px (tablet) =========================================== */ /* ========================================================================== Git Source Browser ========================================================================== */ .git-repo-header { margin-bottom: var(--gap-pane); } /* The identity line, templated (`.git-repo-name`) and described (`#git-repo-name`). The separator is punctuation the reader never presses, so a described one is drawn here rather than said in the description. */ .git-repo-name, #git-repo-name { font-size: var(--text-head); margin: 0 0 var(--gap-bound); } .git-repo-name a, #git-repo-name a { color: var(--content); text-decoration: none; } .git-repo-name a:hover, #git-repo-name a:hover { opacity: 0.6; } .git-repo-name .sep { opacity: 0.3; margin: 0 var(--gap-bound); } #git-repo-name .run { gap: 0; } #git-repo-name .link + .link::before { content: "/"; opacity: 0.3; margin: 0 var(--gap-bound); } .git-repo-desc { opacity: 0.6; margin: 0 0 var(--gap-section); font-size: var(--text-note); } .git-clone-url { font-family: var(--font-mono); font-size: var(--text-fine); padding: var(--gap-peer) var(--gap-group); background: var(--surface-overlay); border: 1px solid var(--border); border-radius: var(--radius-control); display: inline-block; user-select: all; margin-bottom: var(--gap-section); } .git-linked-project { margin-top: var(--gap-peer); font-size: var(--text-note); } .git-linked-project a { color: var(--content); } /* Ref bar (branch/tag chooser + the places the repo has). Described: `crate::quasi::widgets::git_nav` emits the region, the field and the list, so these rules dress the renderer's own class names rather than hand-written ones. The strip is a list drawn across, which is where "how a set is laid out" has always lived. */ #git-nav { margin-bottom: var(--gap-section); font-size: var(--text-note); } /* The run already lays out across and wraps; only the rhythm is the app's. */ #git-nav .run { gap: var(--gap-section); } /* The label reads beside the control rather than over it: the bar is one line and a stacked label would set its height. */ #git-nav .form-group { display: flex; align-items: center; gap: var(--gap-peer); margin: 0; } #git-nav .form-label { margin: 0; white-space: nowrap; } #git-nav select.field { width: auto; font-family: var(--font-mono); font-size: var(--text-fine); padding: var(--gap-bound) var(--gap-peer); border: 1px solid var(--border); border-radius: var(--radius-control); } /* The strip is the list drawn across. Everything else about a list -- the markers, the box -- is the design system's and is not restated here. */ #git-nav .list { display: flex; gap: var(--gap-section); } #git-nav .row { margin: 0; padding: 0; border: 0; background: none; } #git-nav .row-activate { text-decoration: none; color: var(--content); opacity: 0.6; } #git-nav .row-activate:hover, #git-nav .row-current .row-activate { opacity: 1; } /* Breadcrumb navigation */ .git-breadcrumb, #git-breadcrumb { font-family: var(--font-mono); font-size: var(--text-note); margin-bottom: var(--gap-section); } .git-breadcrumb a, #git-breadcrumb a { color: var(--content); text-decoration: none; } .git-breadcrumb a:hover, #git-breadcrumb a:hover { text-decoration: underline; } .git-breadcrumb .sep { opacity: 0.3; margin: 0 var(--gap-bound); } /* The trail's separators, for `#git-repo-name`'s reason. `.text` is the last crumb, which is the thing itself and goes nowhere. */ #git-breadcrumb .run { gap: 0; } #git-breadcrumb .run > * + *::before, #git-breadcrumb .run > * + * > .text::before { content: "/"; opacity: 0.3; margin: 0 var(--gap-bound); } #git-breadcrumb .text { display: inline; margin: 0; } /* File tree table */ .git-tree { width: 100%; border-collapse: collapse; font-size: var(--text-note); } .git-tree th { text-align: left; padding: var(--gap-peer) var(--gap-group); border-bottom: 2px solid var(--border); font-family: var(--font-mono); font-size: var(--text-fine); opacity: 0.5; text-transform: uppercase; } .git-tree td { padding: var(--gap-peer) var(--gap-group); border-bottom: 1px solid var(--border); } .git-tree tr:last-child td { border-bottom: none; } .git-tree .icon { width: 1.5rem; text-align: center; opacity: 0.4; font-family: var(--font-mono); } .tree-icon-dir { font-weight: 700; color: var(--content); } .tree-icon-file { font-size: var(--text-note); } .git-tree .name a { text-decoration: none; color: var(--content); } .git-tree .name a:hover { text-decoration: underline; } .git-tree .size { text-align: right; opacity: 0.5; font-family: var(--font-mono); font-size: var(--text-fine); } /* The same listing, described (`crate::quasi::git_browse`). `.git-tree` stays because `repo.html` still writes it; the `col-` classes are the renderer's, taken from the column names. The icon column is gone on purpose: it was one character wide and said what the trailing slash on a directory's name already said. */ #git-browse .table { font-size: var(--text-note); } #git-browse .col-Name .cell-link { font-family: var(--font-mono); } #git-browse .col-Size { text-align: right; opacity: 0.5; font-family: var(--font-mono); font-size: var(--text-fine); } /* README rendering */ .git-readme { margin-top: var(--gap-page); padding-top: var(--gap-pane); border-top: 1px solid var(--border); } .git-readme h2 { font-size: var(--text-body); opacity: 0.5; margin-bottom: var(--gap-section); } .git-readme-body { line-height: 1.6; } .git-readme-body h1, .git-readme-body h2, .git-readme-body h3 { margin-top: var(--gap-pane); margin-bottom: var(--gap-peer); } .git-readme-body pre { background: var(--surface-overlay); padding: var(--gap-section); border-radius: var(--radius-control); overflow-x: auto; font-family: var(--font-mono); font-size: var(--text-fine); } .git-readme-body code { font-family: var(--font-mono); font-size: var(--text-note); background: var(--surface-overlay); padding: var(--gap-bound); border-radius: var(--radius-fine); } .git-readme-body pre code { background: none; padding: 0; } .git-readme-body table { border-collapse: collapse; margin: var(--gap-section) 0; } .git-readme-body th, .git-readme-body td { border: 1px solid var(--border); padding: var(--gap-peer) var(--gap-group); } /* The strip over a file: how big it is, and the other ways to read it. Described (`crate::quasi::git_browse`, `crate::quasi::git_blame`). */ #git-file-header { padding: var(--gap-peer) var(--gap-group); background: var(--surface-overlay); border: 1px solid var(--border); border-bottom: none; border-radius: var(--radius-control) var(--radius-control) 0 0; font-size: var(--text-fine); } /* The described strip is a run, which lays out across already; what the app still says is that the count and the links go to opposite ends. */ #git-file-header .run { justify-content: space-between; } #git-file-header .text { margin: 0; font-family: var(--font-mono); opacity: 0.6; } /* The design system's link colour and underline stand; what the strip adds is that these read as file actions rather than as prose links. */ #git-file-header .link { font-family: var(--font-mono); opacity: 0.6; } #git-file-header .link:hover { opacity: 1; } /* The file view, described (`crate::quasi::git_browse`): a table of one row per line, under the strip that names the file. The `col-` classes are the renderer's. */ #git-browse .col-Line { width: 1px; white-space: nowrap; text-align: right; user-select: none; opacity: 0.3; font-family: var(--font-mono); font-size: var(--text-fine); border-right: 1px solid var(--border); } #git-browse .col-Line .cell-link { color: inherit; display: block; } #git-browse .col-Line .cell-link:hover { opacity: 0.7; } #git-browse .col-Code { white-space: pre; font-family: var(--font-mono); font-size: var(--text-fine); line-height: 1.5; } /* The line the address names. `data-value` rather than `:target`, since a row identity is not an element id: `page-git-file.js` sets this. */ #git-browse .table-row.is-line { background: var(--highlight-faint); } /* The strip and the table are one box: the strip rounds its top corners and the table under it rounds the bottom two. Only the file view has a strip, which is why this is a sibling rule and not one on the table. */ #git-file-header ~ .table { border: 1px solid var(--border); border-radius: 0 0 var(--radius-control) var(--radius-control); overflow-x: auto; } #git-binary-notice { padding: var(--gap-page); text-align: center; opacity: 0.5; font-family: var(--font-mono); font-size: var(--text-note); border: 1px solid var(--border); border-radius: 0 0 var(--radius-control) var(--radius-control); } #git-binary-notice .run { justify-content: center; } #git-binary-notice .text { margin: 0; } /* Syntax highlighting. The class names are quasi-webview's, from `makeover_layout::Syntax::name`, and the scope-to-class mapping is `src/git/mod.rs`'s `syntax_of` (quasi `19d7602d`, 2026-09-02). It matched syntect's own emitted scopes until then, which meant this file held half a mapping the server held the other half of. The palette below it is unchanged and still fixed across all 31 themes. Not scoped under `.git-file-content` any more: a code node is a code node wherever it is drawn, and a fingerprint in a table or a clone URL in a sentence wants the same colours as a line of a file. */ .lex-keyword { color: var(--syntax-keyword); } .lex-string { color: var(--syntax-string); } .lex-comment { color: var(--syntax-comment); font-style: italic; } .lex-constant { color: var(--syntax-constant); } .lex-entity { color: var(--syntax-entity); } .lex-variable { color: var(--syntax-variable); } .lex-support { color: var(--syntax-support); } /* The element the runs sit in. `code` is quasi-webview's, and it is the whole of what makes an inline literal read as one: a monospace face and the whitespace kept. A block form (`
`) inherits both from the browser. */
code.code {
font-family: var(--font-mono);
white-space: pre;
}
/* Commit list */
.git-commit-list { list-style: none; }
.git-commit { padding: var(--gap-section) 0; border-bottom: 1px solid var(--border); }
.git-commit:last-child { border-bottom: none; }
.git-commit-message { font-size: var(--text-note); margin: 0 0 var(--gap-bound); }
.git-commit-message .summary { font-weight: 600; }
.git-commit-meta {
font-family: var(--font-mono);
font-size: var(--text-fine);
opacity: 0.5;
display: flex;
gap: var(--gap-section);
flex-wrap: wrap;
}
.git-commit-oid { font-family: var(--font-mono); font-size: var(--text-fine); }
.git-commit-oid a { color: var(--content); text-decoration: none; }
.git-commit-oid a:hover { text-decoration: underline; }
.git-pagination {
display: flex;
justify-content: center;
gap: var(--gap-section);
margin-top: var(--gap-pane);
padding-top: var(--gap-section);
font-size: var(--text-note);
}
.git-pagination a { color: var(--content); text-decoration: none; }
.git-pagination a:hover { text-decoration: underline; }
/* Release items on repo page */
.git-release { margin-bottom: var(--gap-pane); padding: var(--gap-section); background: var(--surface-overlay); }
.git-release-title { margin: 0 0 var(--gap-bound); font-size: var(--text-lead); }
.git-release-title a { color: var(--content); text-decoration: none; }
.git-release-meta { font-size: var(--text-note); opacity: 0.6; margin-bottom: var(--gap-peer); }
.git-release-desc { font-size: var(--text-note); opacity: 0.8; margin-bottom: var(--gap-section); }
.git-release-versions { font-size: var(--text-fine); }
.git-release-version {
display: flex;
gap: var(--gap-section);
align-items: center;
padding: var(--gap-bound) 0;
border-top: 1px solid var(--border);
}
.git-release-version .version-number { font-family: var(--font-mono); }
.git-release-version .version-badge {
font-size: var(--text-fine);
padding: var(--gap-bound) var(--gap-peer);
background: var(--content);
color: var(--surface-page);
border-radius: var(--radius-fine);
}
.git-release-version .version-meta { opacity: 0.5; }
/* Git commit detail + diff */
/* The commit page, described (`crate::quasi::git_commit`). */
#git-commit-detail { margin-bottom: var(--gap-pane); }
/* The message, as it was written: a commit message's line breaks are the
author's and wrapping them away loses the shape of the thing. */
#git-commit-detail > .text {
font-family: var(--font-mono);
font-size: var(--text-note);
white-space: pre-wrap;
line-height: 1.5;
padding: var(--gap-section);
background: var(--surface-overlay);
border: 1px solid var(--border);
margin-bottom: var(--gap-section);
}
/* Trailers, lifted out of the message body and shown as what they are. Rows
here rather than a `dl`: the description says a list of pairs and the grid is
this sheet's reading of it. */
#git-commit-detail > .list { font-size: var(--text-note); margin-bottom: var(--gap-section); }
#git-commit-detail > .list .row {
display: grid;
grid-template-columns: max-content 1fr;
gap: var(--gap-bound) var(--gap-section);
}
#git-commit-detail > .list .row-primary { opacity: 0.6; }
#git-commit-detail > .list .row-meta { font-family: var(--font-mono); font-size: var(--text-fine); }
#git-commit-detail-meta { font-size: var(--text-note); opacity: 0.7; line-height: 1.8; }
#git-commit-detail-meta .text { margin: 0; }
#git-commit-oid .code { font-size: var(--text-fine); word-break: break-all; }
#git-commit-parents .link { font-family: var(--font-mono); }
/* Tags, with the annotation an annotated tag carries */
.git-tag-list { list-style: none; }
.git-tag { padding: var(--gap-section) 0; border-bottom: 1px solid var(--border); }
.git-tag:last-child { border-bottom: none; }
.git-tag-name { font-size: var(--text-note); font-weight: 600; margin: 0 0 var(--gap-bound); }
.git-tag-name a { color: var(--content); text-decoration: none; }
.git-tag-name a:hover { text-decoration: underline; }
.git-tag-lightweight { font-weight: 400; font-size: var(--text-fine); opacity: 0.5; }
.git-tag-message {
font-family: var(--font-mono);
font-size: var(--text-note);
white-space: pre-wrap;
line-height: 1.5;
padding: var(--gap-peer) var(--gap-section);
border-left: 2px solid var(--border);
margin-bottom: var(--gap-bound);
}
.git-tag-meta {
font-family: var(--font-mono);
font-size: var(--text-fine);
opacity: 0.5;
display: flex;
gap: var(--gap-section);
flex-wrap: wrap;
}
.git-tag-meta a { color: var(--content); text-decoration: none; }
.git-tag-meta a:hover { text-decoration: underline; }
/* Signature state. Neutral by default: only a bad signature gets a colour. */
.git-signature { font-size: var(--text-fine); opacity: 0.7; }
.git-signature a { color: var(--content); }
.git-signature.is-verified { opacity: 1; }
.git-signature.is-bad { color: var(--danger); opacity: 1; }
/* refs/replace/*: object substitutions, listed but not applied while browsing */
.git-replace-intro { padding-bottom: var(--gap-section); font-size: var(--text-note); }
.git-replace-intro p { margin: 0; }
.git-replace-notice {
font-size: var(--text-note);
border-left: 2px solid var(--border);
padding: var(--gap-peer) var(--gap-section);
margin: 0 0 var(--gap-section);
}
.git-replace-table { width: 100%; border-collapse: collapse; font-size: var(--text-note); }
.git-replace-table th {
text-align: left;
font-weight: 400;
opacity: 0.5;
font-size: var(--text-fine);
padding: var(--gap-bound) var(--gap-section) var(--gap-bound) 0;
border-bottom: 1px solid var(--border);
}
.git-replace-table td { padding: var(--gap-peer) var(--gap-section) var(--gap-peer) 0; border-bottom: 1px solid var(--border); }
.git-replace-table a { color: var(--content); text-decoration: none; }
.git-replace-table a:hover { text-decoration: underline; }
/* Git notes (refs/notes/*) shown against the object they annotate.
Described: `crate::quasi::widgets::git_notes` emits the panel, so these rules
dress the renderer's classes. The body is the one part that is still the
app's own markup -- it comes out of docengine already -- and it keeps
`.git-note-body`, which the annotations panel writes too. */
#notes { margin-bottom: var(--gap-pane); }
#notes > .region {
border: 1px solid var(--border);
border-left: 2px solid var(--content);
margin-bottom: var(--gap-section);
}
/* The header is the note's leading row: the namespace on the left and where it
came from on the right. The auto margin is what puts it there; the shipped
rule used `space-between` on a header that held its own elements. */
#notes > .region > .region .run {
padding: var(--gap-peer) var(--gap-section);
border-bottom: 1px solid var(--border);
font-size: var(--text-fine);
}
#notes > .region > .region .run > :first-child { margin-right: auto; }
#notes .text { margin: 0; opacity: 0.6; }
.git-note-namespaces {
display: flex;
flex-wrap: wrap;
gap: var(--gap-group);
padding: var(--gap-section) 0;
border-bottom: 1px solid var(--border);
margin-bottom: var(--gap-section);
font-size: var(--text-note);
}
.git-note-namespaces a { color: var(--content); text-decoration: none; opacity: 0.6; }
.git-note-namespaces a:hover { opacity: 1; }
.git-note-namespaces a.is-selected { opacity: 1; text-decoration: underline; }
.git-note-target-kind { opacity: 0.6; }
.git-notes-fetch { padding-bottom: var(--gap-section); font-size: var(--text-note); }
.git-notes-fetch p { margin: 0 0 var(--gap-peer); }
.git-note-feed-cap { font-size: var(--text-fine); opacity: 0.6; padding-top: var(--gap-section); }
.git-note-search {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--gap-group);
padding-bottom: var(--gap-section);
font-size: var(--text-note);
}
.git-note-search input[type="search"] { flex: 1 1 16rem; }
.git-note-search label { display: flex; align-items: center; gap: var(--gap-bound); opacity: 0.8; }
.git-note-excerpt {
margin: var(--gap-bound) 0 0;
font-size: var(--text-note);
opacity: 0.7;
}
.git-note-paging {
display: flex;
gap: var(--gap-group);
align-items: center;
padding-top: var(--gap-section);
font-size: var(--text-note);
}
.git-note-paging span { font-size: var(--text-fine); opacity: 0.6; }
.git-note-feed-link { padding-top: var(--gap-peer); font-size: var(--text-fine); }
.git-note-badge {
font-size: var(--text-fine);
padding: var(--gap-bound) var(--gap-peer);
border: 1px solid var(--border);
border-radius: var(--radius-fine);
color: var(--content);
text-decoration: none;
opacity: 0.7;
}
.git-note-badge:hover { opacity: 1; }
.git-note-body { padding: var(--gap-section); font-size: var(--text-note); }
.git-note-body > :first-child { margin-top: 0; }
.git-note-body > :last-child { margin-bottom: 0; }
/* Writing a note. Only rendered for a reader who can push. */
/* The write halves and the reader's own annotations, described. `#annotation`
is the reader's own note on this commit, which lives in their annotation
repository rather than in the one being browsed; `#annotations` is the
read-only panel above it. */
#git-notes-edit,
#annotation,
#annotations {
border-top: 1px solid var(--border);
padding-top: var(--gap-section);
margin-bottom: var(--gap-pane);
}
#git-notes-edit textarea,
#annotation textarea { font-family: var(--font-mono); font-size: var(--text-note); }
#git-notes-edit .form { margin-bottom: var(--gap-section); }
#git-notes-edit .button { margin-bottom: var(--gap-pane); }
#annotations .heading { font-size: var(--text-note); margin: 0 0 var(--gap-peer); }
#annotations > .text { font-size: var(--text-note); color: var(--content-muted); }
/* A merge notice: what is on screen is not exactly what was typed. */
#git-notes-edit > .text[data-tone="warning"],
#annotation > .text[data-tone="warning"] {
border-left: 2px solid var(--content);
padding: var(--gap-peer) var(--gap-section);
margin-bottom: var(--gap-section);
font-size: var(--text-note);
}
.git-annotations-privacy,
.git-annotations-empty,
.git-annotations-count { font-size: var(--text-note); color: var(--content-muted); }
.git-annotations-list { list-style: none; margin: 0; padding: 0; }
.git-annotation-entry {
border: 1px solid var(--border);
padding: var(--gap-section);
margin-bottom: var(--gap-section);
}
.git-annotation-header {
display: flex;
gap: var(--gap-peer);
flex-wrap: wrap;
align-items: baseline;
font-size: var(--text-note);
margin-bottom: var(--gap-peer);
}
.git-annotation-target,
.git-annotation-namespace,
.git-annotation-when { font-family: var(--font-mono); color: var(--content-muted); }
.git-annotation-orphan { font-size: var(--text-note); color: var(--content-muted); }
/* The diff, described (`crate::quasi::git_commit`). `19d7602d`: a row says
which side it is on through `data-change`, and the sign is drawn here rather
than written into the content, so a terminal can spell it its own way. */
#git-diff-stats {
font-size: var(--text-note);
padding: var(--gap-section) 0;
margin-bottom: var(--gap-section);
border-bottom: 1px solid var(--border);
}
#git-diff-stats .text { margin: 0; }
#git-diff-stats .text[data-tone="success"] { color: var(--diff-add); }
#git-diff-stats .text[data-tone="danger"] { color: var(--diff-del); }
#git-commit [id^="diff-"] { margin-bottom: var(--gap-pane); border: 1px solid var(--border); }
#git-commit [id^="diff-header-"] {
padding: var(--gap-peer) var(--gap-section);
background: var(--surface-overlay);
border-bottom: 1px solid var(--border);
border-radius: 0;
font-size: var(--text-note);
}
/* The counts sit at the far end, as `.git-diff-file-stats` did with its auto
margin. */
#git-commit [id^="diff-header-"] .link + .cell-drops-next { margin-left: auto; }
#git-commit [id^="diff-header-"] .text { margin: 0; font-size: var(--text-fine); }
#git-commit [id^="diff-header-"] .text[data-tone="success"] { color: var(--diff-add); }
#git-commit [id^="diff-header-"] .text[data-tone="danger"] { color: var(--diff-del); }
#git-commit [id^="diff-"] .table {
font-family: var(--font-mono);
font-size: var(--text-fine);
border: 0;
}
#git-commit [id^="diff-"] .col-Old,
#git-commit [id^="diff-"] .col-New {
text-align: right;
opacity: 0.35;
user-select: none;
}
#git-commit [id^="diff-"] .col-Line { white-space: pre-wrap; word-break: break-all; }
/* The hunk header: the one row of the table that is on neither side. */
#git-commit [id^="diff-"] .table-row:not([data-change]) .col-Line {
background: var(--highlight-faint);
opacity: 0.6;
}
#git-commit [id^="diff-"] .table-row[data-change="added"] { background: var(--diff-add-bg); }
#git-commit [id^="diff-"] .table-row[data-change="removed"] { background: var(--diff-del-bg); }
/* The sign, drawn rather than said. `::before` on the line cell, so it lands in
the gutter the origin column used to be. */
#git-commit [id^="diff-"] .table-row[data-change] .col-Line::before {
display: inline-block;
width: 1ch;
margin-right: var(--gap-bound);
user-select: none;
}
#git-commit [id^="diff-"] .table-row[data-change="added"] .col-Line::before {
content: "+";
color: var(--diff-add);
}
#git-commit [id^="diff-"] .table-row[data-change="removed"] .col-Line::before {
content: "-";
color: var(--diff-del);
}
#git-commit [id^="diff-"] .table-row[data-change="context"] .col-Line::before { content: " "; }
/* Git blame view */
/* Git blame view, described (`crate::quasi::git_blame`). The `col-` classes are
the renderer's, taken from the column names the description gives. */
#git-blame .table {
border: 1px solid var(--border);
border-radius: 0 0 var(--radius-control) var(--radius-control);
font-size: var(--text-fine);
}
#git-blame .cell { font-family: var(--font-mono); }
#git-blame .cell-link { color: var(--content); text-decoration: none; }
#git-blame .cell-link:hover { text-decoration: underline; }
#git-blame .col-Author { opacity: 0.5; }
#git-blame .col-Date { opacity: 0.35; }
#git-blame .col-Line { text-align: right; opacity: 0.35; user-select: none; }
#git-blame .col-Code { white-space: pre; }
/* The two repository listings, /git and /git/{owner}, moved to the description
layer. Both were a