git-ents.gitmain
⌘K
foforge
ents.css826 lines · 47.0 KB · csshistorycomment on this file
1/* The workbench stylesheet -- the git-ents "Design Component" handoff
2 * (design_handoff_git_ents_workbench) recreated as one hand-rolled sheet,
3 * keyed to the class taxonomy `crate::pages::layout*` and `crate::render`
4 * already emit (`.wb`/`.rail`/`.wb-bar`/`.split`/`.tree`/`.card`/`.scope`/
5 * `.status`/`.editor-open`/`.blob`/`.comment-meta` ...). The design's exact
6 * tokens (color, geometry, type) live in `:root` below; a page changes its
7 * markup only where a component needs structure the shared classes here
8 * cannot express (an avatar, a state pill's dot, a two-line sidebar row) --
9 * those additive classes are defined here too, so every page draws from one
10 * vocabulary. Type is self-hosted IBM Plex (see the `@font-face` block and
11 * `crate::assets::FONTS`); no rule here depends on a network fetch.
12 *
13 * The `--s-*` syntax-token variables feed `.code .keyword`-family consumers
14 * (`crate::pages::files`'s `arborium` highlighter); the `--diff-*` and
15 * `--status-*` variables feed `.diff` and `.status`
16 * (`crate::pages::commits`). */
17
18@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 400; font-display: swap; src: url("/fonts/plex-sans-400.woff2") format("woff2"); }
19@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 500; font-display: swap; src: url("/fonts/plex-sans-500.woff2") format("woff2"); }
20@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 600; font-display: swap; src: url("/fonts/plex-sans-600.woff2") format("woff2"); }
21@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 700; font-display: swap; src: url("/fonts/plex-sans-700.woff2") format("woff2"); }
22@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 400; font-display: swap; src: url("/fonts/plex-mono-400.woff2") format("woff2"); }
23@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500; font-display: swap; src: url("/fonts/plex-mono-500.woff2") format("woff2"); }
24@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 600; font-display: swap; src: url("/fonts/plex-mono-600.woff2") format("woff2"); }
25
26/* The handoff's light scheme -- its exact token values. */
27:root {
28 --bg: #f4f2ee;
29 --surface: #ffffff;
30 --surface-2: #faf9f6;
31 --raised: #fbfaf7;
32 --ink: #1b1c21;
33 --ink-2: #54555d;
34 --ink-3: #8b8c94;
35 --ink-4: #b6b6bd;
36 --line: #e6e3dd;
37 --line-2: #efece7;
38 --accent: #4a3fc4;
39 --accent-2: #6a5fe0;
40 --accent-soft: #ecebfb;
41 --accent-line: #d8d5f6;
42 --editor: #0d8f9c;
43 --editor-soft: #dff3f3;
44 --editor-line: #b9e3e2;
45 --green: #1c7a49;
46 --green-soft: #e3f2e8;
47 --red: #c23b34;
48 --red-soft: #fae9e7;
49 --amber: #a9791d;
50 --amber-soft: #f6efdd;
51 --violet: #7a3fb0;
52 --violet-soft: #f1e8f8;
53
54 --sans: "IBM Plex Sans", system-ui, -apple-system, sans-serif;
55 --mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
56
57 --radius-card: 12px;
58 --radius-inner: 8px;
59 --radius-chip: 6px;
60 --radius-pill: 20px;
61
62 --shadow-pop: 0 24px 60px rgba(20, 20, 30, .28);
63 --shadow-toast: 0 12px 30px rgba(20, 20, 30, .32);
64
65 /* Deterministic entity/scope chip palette (README: 6 colors, hashed by
66 * name), consumed by `.scope-c0`..`.scope-c5`. */
67 --c0-fg: #4a3fc4; --c0-bg: #ecebfb;
68 --c1-fg: #0d8f9c; --c1-bg: #dff3f3;
69 --c2-fg: #1c7a49; --c2-bg: #e3f2e8;
70 --c3-fg: #a9791d; --c3-bg: #f6efdd;
71 --c4-fg: #b23c8c; --c4-bg: #f8e8f3;
72 --c5-fg: #c23b34; --c5-bg: #fae9e7;
73
74 /* Syntax tokens, tuned to the paper palette. */
75 --s-comment: #8b8c94;
76 --s-keyword: #a3324f;
77 --s-func: #0d8f9c;
78 --s-type: #a9791d;
79 --s-string: #1c7a49;
80 --s-const: #7a3fb0;
81 --s-op: #54555d;
82 --s-prop: #4a3fc4;
83 --diff-add: rgba(28, 122, 73, .10);
84 --diff-del: rgba(194, 59, 52, .09);
85 --status-pass: #1c7a49;
86 --status-fail: #c23b34;
87 --status-error: #a9791d;
88}
89
90/* Dark scheme (README: "dark is a roadmap item -- design both"), derived
91 * from the light palette: the same hues over an ink ground. */
92@media (prefers-color-scheme: dark) {
93 :root {
94 --bg: #16161a;
95 --surface: #1d1e23;
96 --surface-2: #232429;
97 --raised: #26272d;
98 --ink: #ecedf2;
99 --ink-2: #b7b8c0;
100 --ink-3: #85868f;
101 --ink-4: #5b5c65;
102 --line: #303138;
103 --line-2: #292a30;
104 --accent: #9d95f5;
105 --accent-2: #b3abff;
106 --accent-soft: #262353;
107 --accent-line: #3a3672;
108 --editor: #3fc6d2;
109 --editor-soft: #16333650;
110 --editor-line: #2c5a5e;
111 --green: #5cc98b;
112 --green-soft: #143a2650;
113 --red: #f0796f;
114 --red-soft: #3a1e1c50;
115 --amber: #d9a94a;
116 --amber-soft: #37301c50;
117 --violet: #c79be6;
118 --violet-soft: #2c1f3a50;
119 --c0-fg: #9d95f5; --c0-bg: #262353;
120 --c1-fg: #3fc6d2; --c1-bg: #16333650;
121 --c2-fg: #5cc98b; --c2-bg: #143a2650;
122 --c3-fg: #d9a94a; --c3-bg: #37301c50;
123 --c4-fg: #e58fc4; --c4-bg: #3a1f3350;
124 --c5-fg: #f0796f; --c5-bg: #3a1e1c50;
125 --s-comment: #85868f;
126 --s-keyword: #f0796f;
127 --s-func: #3fc6d2;
128 --s-type: #d9a94a;
129 --s-string: #5cc98b;
130 --s-const: #c79be6;
131 --s-op: #b7b8c0;
132 --s-prop: #9d95f5;
133 --diff-add: rgba(92, 201, 139, .13);
134 --diff-del: rgba(240, 121, 111, .13);
135 --status-pass: #5cc98b;
136 --status-fail: #f0796f;
137 --status-error: #d9a94a;
138 --shadow-pop: 0 24px 60px rgba(0, 0, 0, .55);
139 --shadow-toast: 0 12px 30px rgba(0, 0, 0, .6);
140 }
141}
142
143*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
144html { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
145body {
146 font-family: var(--sans);
147 font-size: 14px;
148 line-height: 1.5;
149 background: var(--bg);
150 color: var(--ink);
151 min-height: 100vh;
152 text-rendering: optimizeLegibility;
153}
154h1, h2, h3, h4, h5, h6 { font-family: var(--sans); font-weight: 600; }
155a { color: var(--accent); text-decoration: none; }
156a:hover { color: var(--accent-2); text-decoration: underline; }
157/* Every bare `<code>` (a short oid, a CLI command name, ...) reads as a
158 * small code chip by default; contexts that already carry their own
159 * monospace flow (`.blob-code`, `.doc-body`) reset it back below. */
160code { font-family: var(--mono); font-size: .9em; background: var(--surface-2); border: 1px solid var(--line); border-radius: 5px; padding: 1px 6px; }
161::selection { background: var(--accent-soft); }
162a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible, select:focus-visible, summary:focus-visible {
163 outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px;
164}
165.icon { flex-shrink: 0; fill: none; stroke: currentColor; vertical-align: -0.125em; }
166.muted { color: var(--ink-3); }
167::-webkit-scrollbar { width: 10px; height: 10px; }
168::-webkit-scrollbar-thumb { background: var(--line); border-radius: 8px; border: 3px solid var(--bg); }
169
170/* ============================ SHELL ============================ *
171 * `crate::pages::layout_shell`: a `.wb` row of the fixed 60px icon
172 * `.rail` and a `.wb-main` column whose sticky 56px `.wb-bar` carries the
173 * repo name + branch pill, the `.palette` search, and the `.id-chip`. */
174.wb { display: flex; min-height: 100vh; width: 100%; }
175.rail {
176 position: sticky; top: 0; align-self: flex-start; height: 100vh; width: 60px; flex: none;
177 background: var(--surface); border-right: 1px solid var(--line);
178 display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 12px 0; z-index: 40;
179}
180.rail .nav-mark {
181 width: 34px; height: 34px; border-radius: 9px; background: var(--ink); color: var(--surface);
182 display: flex; align-items: center; justify-content: center;
183 font-family: var(--mono); font-weight: 600; font-size: 15px; letter-spacing: -1px; margin-bottom: 10px;
184}
185.rail a {
186 display: flex; align-items: center; justify-content: center; width: 42px; height: 42px;
187 border-radius: 11px; color: var(--ink-3);
188}
189.rail a:hover { background: var(--surface-2); color: var(--ink); text-decoration: none; }
190.rail a.active { background: var(--accent-soft); color: var(--accent); }
191.rail a .icon { width: 19px; height: 19px; stroke-width: 1.7; }
192.rail .spacer { flex: 1; }
193
194.wb-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
195.wb-bar {
196 position: sticky; top: 0; z-index: 30; height: 56px; flex: none;
197 background: var(--surface); border-bottom: 1px solid var(--line);
198 display: flex; align-items: center; gap: 16px; padding: 0 18px;
199}
200.repo-path { display: flex; align-items: center; gap: 9px; flex: none; min-width: 0; }
201.repo-path .here { font-weight: 600; font-size: 14px; color: var(--ink); }
202.branch {
203 display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 9px;
204 background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-pill);
205 font-family: var(--mono); font-size: 11.5px; color: var(--ink-2);
206}
207.branch .icon { width: 12px; height: 12px; stroke-width: 2; }
208/* `.palette` is a form: undo the stacked-field form rules (column, gap,
209 * bottom margin). Styled as the design's centered palette trigger. */
210.palette {
211 flex: 1; max-width: 520px; margin: 0 auto; height: 34px;
212 display: flex; flex-direction: row; align-items: center; gap: 10px; margin-bottom: 0;
213 padding: 0 12px; background: var(--surface-2); border: 1px solid var(--line);
214 border-radius: 9px; position: relative;
215}
216.palette:focus-within { border-color: var(--accent); }
217.palette .icon { width: 15px; height: 15px; stroke-width: 1.8; color: var(--ink-3); flex: none; }
218.palette input {
219 flex: 1; min-width: 0; border: 0; outline: 0; background: transparent;
220 font-family: var(--sans); font-size: 13px; color: var(--ink);
221}
222.palette input::placeholder { color: var(--ink-3); }
223.palette kbd {
224 font-family: var(--mono); font-size: 11px; color: var(--ink-3);
225 background: var(--surface); border: 1px solid var(--line); border-bottom-width: 2px;
226 border-radius: 5px; padding: 2px 6px; flex: none;
227}
228.id-chip {
229 flex: none; display: inline-flex; align-items: center; gap: 8px; height: 34px;
230 padding: 0 12px 0 6px; border: 1px solid var(--line); border-radius: var(--radius-pill);
231 color: var(--ink); font-size: 12.5px; font-weight: 500;
232}
233.id-chip:hover { border-color: var(--accent-line); color: var(--ink); text-decoration: none; }
234.id-chip .avatar { width: 24px; height: 24px; font-size: 11px; }
235
236/* Initials avatar on the indigo->teal gradient (README: no image assets). */
237.avatar {
238 display: inline-flex; align-items: center; justify-content: center; flex: none;
239 width: 20px; height: 20px; border-radius: 50%;
240 background: linear-gradient(135deg, var(--accent), var(--editor));
241 color: #fff; font-size: 9px; font-weight: 600; text-transform: lowercase; letter-spacing: -.02em;
242}
243
244/* ========================= META RAIL ========================= *
245 * `crate::pages::layout_meta` -- the governance sub-rail beside every
246 * meta-namespace page (`crate::pages::META_SECTIONS`). */
247.meta-layout { display: grid; grid-template-columns: 13rem minmax(0, 1fr); gap: 2rem; align-items: start; }
248.meta-rail { display: flex; flex-direction: column; gap: 2px; position: sticky; top: 78px; }
249.meta-rail a { font-size: 13px; color: var(--ink-2); padding: 7px 11px; border-radius: var(--radius-inner); }
250.meta-rail a:hover { color: var(--ink); background: var(--surface-2); text-decoration: none; }
251.meta-rail a.active { color: var(--accent); font-weight: 600; background: var(--accent-soft); }
252@media (max-width: 900px) {
253 .meta-layout { grid-template-columns: minmax(0, 1fr); }
254 .meta-rail { position: static; flex-direction: row; flex-wrap: wrap; }
255}
256
257/* ===================== CONTENT / SPLIT ===================== */
258.content { max-width: 1120px; width: 100%; margin: 0 auto; padding: 30px 34px 60px; flex: 1; }
259.readable { max-width: 760px; margin-inline: auto; }
260/* Master-detail (`crate::pages::layout_split`): a sticky scrollable
261 * sidebar beside a `min-height:0` detail pane. */
262.split { display: grid; grid-template-columns: 300px minmax(0, 1fr); height: calc(100vh - 56px); }
263.tree {
264 border-right: 1px solid var(--line); background: var(--surface);
265 overflow: auto; position: sticky; top: 0; height: 100%; padding: 10px 8px;
266 font-family: var(--mono); font-size: 12px;
267}
268.tree a {
269 display: flex; align-items: center; gap: 7px; height: 28px; padding: 0 10px;
270 border-radius: 7px; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
271}
272.tree a:hover { background: var(--surface-2); text-decoration: none; }
273.tree a.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
274.tree a span { display: block; overflow: hidden; text-overflow: ellipsis; }
275.tree a .icon { width: 13px; height: 13px; stroke-width: 1.7; color: var(--ink-3); }
276.tree .dir { color: var(--ink-2); }
277.tree .i1 { padding-left: 24px; }
278.tree .i2 { padding-left: 38px; }
279.tree .i3 { padding-left: 52px; }
280.tree-note { display: block; padding: 4px 10px; color: var(--ink-3); }
281.tree .where { font-size: 11px; font-weight: 400; color: var(--ink-3); }
282.pane { padding: 20px 28px 70px; min-width: 0; overflow: auto; }
283.pane .readable, .pane > div { max-width: 820px; margin: 0 auto; }
284
285/* A generic two-line master-detail sidebar row (issues, reviews, commit
286 * lane): a title line and a mono `.side-meta` locator, its active state the
287 * design's accent-soft fill + inset 3px bar. Sits inside `nav.tree`, so it
288 * opts out of the tree's own flex-row link layout. */
289.tree a.side-row {
290 display: flex; flex-direction: column; align-items: stretch; gap: 4px; height: auto;
291 padding: 11px 15px; border-radius: 0; border-bottom: 1px solid var(--line-2);
292 font-family: var(--sans); white-space: normal;
293}
294.tree a.side-row.active { background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent); color: inherit; }
295.side-title { font-size: 13px; font-weight: 500; color: var(--ink); line-height: 1.35; text-wrap: pretty; }
296.side-row.active .side-title { font-weight: 600; }
297.side-meta { display: flex; align-items: center; gap: 6px; }
298.side-meta .dot { width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--ink-4); }
299.side-meta .locator { font-family: var(--mono); font-size: 11px; color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
300.tree-head {
301 display: flex; align-items: center; justify-content: space-between; gap: 8px;
302 padding: 13px 15px; border-bottom: 1px solid var(--line-2);
303 position: sticky; top: 0; background: var(--surface); z-index: 2;
304 font-family: var(--sans); font-size: 13px; font-weight: 600;
305}
306@media (max-width: 900px) {
307 .split { grid-template-columns: minmax(0, 1fr); height: auto; }
308 .tree { position: static; height: auto; max-height: 16rem; border-right: none; border-bottom: 1px solid var(--line); }
309 .pane { height: auto; }
310}
311
312/* ===================== PAGE HEADER ===================== */
313/* Bare `h2` and `p.muted` in page flow are the section-heading and
314 * lead-in idiom (mock: 14px/600 with 26px above; muted lead-ins breathe
315 * instead of sitting flush on the card below). */
316.content h2, .pane h2 { margin: 26px 0 12px; font-size: 14px; font-weight: 600; }
317.content h2:first-child, .pane h2:first-child { margin-top: 0; }
318p.muted { margin-bottom: 16px; font-size: 13px; text-wrap: pretty; }
319.page-header {
320 margin-bottom: 22px; padding-bottom: 16px; border-bottom: 1px solid var(--line);
321 display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap;
322}
323.page-title { font-size: 22px; font-weight: 600; letter-spacing: -.3px; line-height: 1.25; }
324/* A page-title that is itself a repository path (a tree/blob view -- the
325 * `.crumbs` trail right under it names the exact same path) -- monospace so
326 * it reads as the path it is, not prose competing with the crumb trail for
327 * the same information. */
328.page-title.path { font-family: var(--mono); font-size: 18px; word-break: break-all; }
329.page-sub { margin-top: 5px; color: var(--ink-3); font-size: 13px; }
330.page-header .mono { font-family: var(--mono); color: var(--ink-2); }
331/* A `.crumbs` trail directly under a `.page-header` reads as its subtitle --
332 * hug it to the title instead of the header's own bottom border/margin, and
333 * move that border/gap to below the crumbs, in front of the page's content,
334 * so the title and its path trail read as one grouped header. */
335.page-header:has(+ .crumbs) { margin-bottom: 6px; padding-bottom: 0; border-bottom: none; }
336.page-header + .crumbs { margin-bottom: 22px; padding-bottom: 16px; border-bottom: 1px solid var(--line); }
337
338/* ========================= CARDS ========================= */
339.card {
340 background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-card);
341 overflow: hidden; margin-bottom: 18px;
342}
343.card-header {
344 display: flex; align-items: center; justify-content: space-between; gap: 10px;
345 padding: 13px 16px; border-bottom: 1px solid var(--line-2);
346 font-size: 13px; font-weight: 600; color: var(--ink);
347}
348.card-header .btn-ghost { margin-left: auto; }
349/* A form as a card's body gets the mock composer's inner padding, its
350 * action row right-aligned as the mock's composer footer. */
351.card > form { padding: 18px 20px; margin-bottom: 0; }
352.card > form .composer-buttons { justify-content: flex-end; }
353.tree-head .btn { height: 24px; }
354/* Stacked card rows (meta index): name over blurb, sans, left-aligned. */
355.card-row.stack { flex-direction: column; align-items: flex-start; gap: 2px; padding: 13px 16px; font-family: var(--sans); }
356.card-row.stack a { flex: none; font-size: 13.5px; font-weight: 600; color: var(--accent); text-transform: capitalize; }
357.card-row.stack span { font-size: 12.5px; color: var(--ink-3); }
358.card-row {
359 display: flex; align-items: center; gap: 10px; padding: 9px 16px;
360 font-family: var(--mono); font-size: 12.5px;
361}
362.card-row + .card-row { border-top: 1px solid var(--line-2); }
363.card-row .icon { color: var(--ink-3); stroke-width: 1.7; }
364.card-row.is-dir .icon { color: var(--accent); }
365.card-row a { color: var(--ink); flex: 1; min-width: 0; word-break: break-all; }
366.card-row a:hover { color: var(--accent); }
367.card-row a.row-link { display: flex; align-items: center; gap: 10px; text-decoration: none; }
368.card-row:has(.row-link):hover { background: var(--surface-2); }
369.entry-size { margin-left: auto; font-family: var(--mono); font-size: 11.5px; color: var(--ink-3); white-space: nowrap; }
370
371/* ========================= DASHBOARD ========================= *
372 * `crate::pages::dashboard`: three cards on a `.desk` grid, then a
373 * full-width `.desk-wide` history card. */
374.desk { display: grid; grid-template-columns: 1.15fr 1fr 1fr; gap: 18px; align-items: start; margin-bottom: 18px; }
375.desk .card, .desk-wide .card { margin-bottom: 0; }
376.desk-wide { grid-column: 1 / -1; }
377.attention-row { display: flex; flex-direction: column; gap: 3px; padding: 10px 16px; color: inherit; }
378.attention-row:hover { background: var(--surface-2); text-decoration: none; }
379.attention-row + .attention-row { border-top: 1px solid var(--line-2); }
380.attention-row .what { font-size: 12.5px; color: var(--ink); text-wrap: pretty; }
381.attention-row .what .lead { color: var(--amber); font-weight: 500; }
382.attention-row .where { font-family: var(--mono); font-size: 11px; color: var(--ink-3); }
383.history .card-row { flex-wrap: nowrap; gap: 12px; }
384.history .card-row a { flex: none; color: var(--accent); text-decoration: none; }
385.history .card-row a:hover { text-decoration: underline; }
386.desk-subject { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--sans); font-size: 13px; color: var(--ink); }
387.desk-when { flex: none; font-size: 12px; color: var(--ink-3); }
388/* Commit-row trailing author/when: sans, quiet, never wrapping (mock). */
389.row-author { flex: none; font-family: var(--sans); font-size: 12px; color: var(--ink-3); }
390.row-when { flex: none; font-family: var(--sans); font-size: 12px; color: var(--ink-4); white-space: nowrap; }
391@media (max-width: 1100px) { .desk { grid-template-columns: minmax(0, 1fr); } }
392
393/* ===================== BUTTONS ===================== */
394.btn {
395 display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 16px;
396 font-size: 13px; font-weight: 500; color: #fff; background: var(--accent);
397 border: none; border-radius: var(--radius-inner); cursor: pointer;
398 white-space: nowrap; flex: none;
399}
400.btn:hover { background: var(--accent-2); text-decoration: none; color: #fff; }
401.btn-sm { height: 24px; padding: 0 10px; font-size: 11.5px; border-radius: var(--radius-chip); }
402.btn-ghost {
403 color: var(--ink-2); background: var(--surface); border: 1px solid var(--line);
404}
405.btn-ghost:hover { border-color: var(--accent-line); color: var(--accent); background: var(--surface); }
406
407/* ===================== CHIPS & BADGES ===================== *
408 * One `.chip` base; state/verdict/check/scope variants layer color and, for
409 * state/verdict, a leading dot via `.chip .dot`. */
410.chip {
411 display: inline-flex; align-items: center; gap: 5px; height: 19px; padding: 0 8px;
412 border-radius: 5px; font-size: 10.5px; font-weight: 600; white-space: nowrap;
413 color: var(--ink-2); background: var(--surface-2);
414}
415.chip .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
416/* Pill-shaped status chips carry more presence (issue/review state). */
417.chip-pill { height: 22px; padding: 0 10px; border-radius: var(--radius-pill); font-size: 11.5px; gap: 5px; }
418
419.badge { font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-pill); padding: 1px 8px; }
420
421/* Issue state (`crate::pages::issues`). */
422.state-open, .comment-state-open { color: var(--green); background: var(--green-soft); }
423.state-closed, .comment-state-resolved { color: var(--ink-2); background: var(--line-2); }
424.state-in-progress { color: var(--amber); background: var(--amber-soft); }
425/* Review state (`crate::pages::commits`/reviews). */
426.review-draft { color: var(--violet); background: var(--violet-soft); }
427.review-in-review { color: var(--amber); background: var(--amber-soft); }
428.review-approved { color: var(--green); background: var(--green-soft); }
429.review-changes-requested { color: var(--red); background: var(--red-soft); }
430.review-closed { color: var(--ink-2); background: var(--line-2); }
431/* Review verdict badge. */
432.verdict { display: inline-flex; align-items: center; height: 19px; padding: 0 8px; border-radius: 5px; font-size: 10.5px; font-weight: 600; }
433.verdict-approve { color: var(--green); background: var(--green-soft); }
434.verdict-request-changes { color: var(--red); background: var(--red-soft); }
435.verdict-comment { color: var(--ink-2); background: var(--line-2); }
436
437/* Check-status chips (`crate::pages::commits::checks_section`): a glyph
438 * plus the value, one color per pass/fail/error. */
439.status { display: inline-flex; align-items: center; gap: 4px; font-family: var(--mono); font-size: 10.5px; font-weight: 600; border-radius: 5px; padding: 2px 8px; }
440.status::before { font-weight: 700; }
441.status-pass { color: var(--status-pass); background: var(--green-soft); }
442.status-pass::before { content: "\2713"; }
443.status-fail { color: var(--status-fail); background: var(--red-soft); }
444.status-fail::before { content: "\2715"; }
445.status-error { color: var(--status-error); background: var(--amber-soft); }
446.status-error::before { content: "!"; }
447
448/* Scope chips (`crate::pages::dashboard::scope_class`): deterministic
449 * color, fixed 52px width so commit subjects align (README). */
450.scope {
451 display: inline-flex; align-items: center; justify-content: center; flex: none;
452 width: 52px; height: 19px; border-radius: 5px;
453 font-family: var(--mono); font-size: 10px; font-weight: 600; white-space: nowrap;
454 overflow: hidden; text-overflow: ellipsis;
455}
456.scope-c0 { color: var(--c0-fg); background: var(--c0-bg); }
457.scope-c1 { color: var(--c1-fg); background: var(--c1-bg); }
458.scope-c2 { color: var(--c2-fg); background: var(--c2-bg); }
459.scope-c3 { color: var(--c3-fg); background: var(--c3-bg); }
460.scope-c4 { color: var(--c4-fg); background: var(--c4-bg); }
461.scope-c5 { color: var(--c5-fg); background: var(--c5-bg); }
462
463/* ===================== EDITOR PILL ===================== *
464 * `crate::pages::editor_open` -- the signature web<->editor motif: a small
465 * teal pill deep-linking `file:line` into the serving user's editor.
466 * Rendered nothing at all when no editor is configured. */
467.editor-open {
468 display: inline-flex; align-items: center; gap: 3px; height: 20px; padding: 0 7px;
469 background: var(--editor-soft); border: 1px solid var(--editor-line); border-radius: var(--radius-chip);
470 color: var(--editor); font-family: var(--mono); font-size: 10.5px; font-weight: 600; white-space: nowrap;
471}
472.editor-open:hover { color: var(--editor); text-decoration: none; filter: brightness(.96); }
473.editor-open .icon { width: 11px; height: 11px; stroke-width: 2.4; }
474
475/* ===================== ENTITY VIEWS ===================== *
476 * The reflection-driven views (`crate::render`): a definition list for one
477 * entity, a table for a list, a plain list for bare name lists. */
478.entity-view { font-family: var(--mono); font-size: 12.5px; }
479.entity-view dt { padding: 12px 16px 2px; font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-3); }
480.entity-view dd { padding: 0 16px 12px; word-break: break-all; color: var(--ink); }
481.entity-view dt + dt { padding-top: 2px; }
482
483.entity-list { width: 100%; border-collapse: collapse; font-family: var(--mono); font-size: 12px; }
484.entity-list th, .entity-list td { padding: 10px 16px; text-align: left; }
485.entity-list th { white-space: nowrap; }
486.entity-list td.long-token { word-break: break-all; }
487.entity-list thead { background: var(--surface-2); font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-3); }
488.entity-list tbody tr + tr { border-top: 1px solid var(--line-2); }
489.entity-list td a { color: var(--accent); }
490.commits-table th:nth-child(1), .commits-table td:nth-child(1),
491.commits-table th:nth-child(3), .commits-table td:nth-child(3),
492.commits-table th:nth-child(4), .commits-table td:nth-child(4) { white-space: nowrap; }
493
494.string-list { list-style: none; font-family: var(--mono); font-size: 12.5px; }
495.string-list li { display: flex; align-items: center; gap: 10px; padding: 10px 16px; }
496.string-list li + li { border-top: 1px solid var(--line-2); }
497.string-list a { color: var(--ink); }
498.string-list a:hover { color: var(--accent); }
499
500/* Per-entity read failure (`crate::render::unreadable`). */
501.card-row.unreadable span { color: var(--ink-3); font-style: italic; }
502.unreadable-detail { display: block; margin-top: 2px; color: var(--ink-3); font-style: normal; font-family: var(--mono); font-size: 11.5px; word-break: break-all; }
503.unreadable-note { margin-bottom: 18px; }
504.unreadable-note summary {
505 display: inline-flex; align-items: center; gap: 5px; font-family: var(--mono); font-size: 10.5px; font-weight: 600;
506 color: var(--amber); background: var(--amber-soft); border: 1px solid var(--editor-line); border-color: color-mix(in srgb, var(--amber) 30%, transparent);
507 border-radius: var(--radius-pill); padding: 2px 10px; cursor: pointer; list-style: none; user-select: none; -webkit-user-select: none;
508}
509.unreadable-note summary::-webkit-details-marker { display: none; }
510.unreadable-note[open] summary { margin-bottom: 10px; }
511.unreadable-note .card { margin-bottom: 0; }
512.unreadable-note dd { color: var(--ink-3); font-size: 11.5px; }
513
514/* Bare dl/ul markup a custom page emits directly. */
515dl { font-family: var(--mono); font-size: 12.5px; margin-bottom: 18px; }
516dl dt { font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-3); margin-top: 10px; }
517dl dd { word-break: break-all; }
518ul:not(.string-list):not(.doc-body ul) { list-style: none; font-family: var(--mono); font-size: 12.5px; margin-bottom: 18px; }
519ul:not(.string-list):not(.doc-body ul) li { padding: 5px 0; }
520
521/* ===================== BLANKSLATE ===================== */
522.blankslate {
523 text-align: center; padding: 40px 24px; border: 1px dashed var(--line);
524 border-radius: var(--radius-card); background: var(--surface);
525}
526.blankslate h2 { font-size: 13.5px; font-weight: 600; color: var(--ink-2); margin: 0 0 4px; }
527.blankslate p { color: var(--ink-3); font-size: 12.5px; }
528.blankslate code { font-family: var(--mono); background: var(--surface-2); border: 1px solid var(--line); padding: 1px 6px; border-radius: 5px; font-size: 12px; }
529.card .blankslate { border: none; }
530
531/* ===================== MEMBER CARDS ===================== *
532 * `crate::pages::members::member_card`: avatar + username + key-type/state/
533 * provenance badges, key material truncated with a full-key disclosure. */
534.member-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 14px 16px; }
535.member-name { font-family: var(--mono); font-weight: 600; font-size: 15px; color: var(--ink); }
536a.member-name:hover { color: var(--accent); }
537.key-badge { font-family: var(--mono); font-size: 10.5px; font-weight: 600; color: var(--editor); background: var(--editor-soft); border: 1px solid var(--editor-line); border-radius: 5px; padding: 1px 8px; white-space: nowrap; }
538.member-key { padding: 0 16px 14px; font-family: var(--mono); font-size: 12px; }
539.member-key code { color: var(--ink-3); background: var(--surface-2); border-radius: 5px; padding: 2px 6px; }
540.member-key details { margin-top: 6px; }
541.member-key summary { font-size: 11px; color: var(--ink-3); cursor: pointer; user-select: none; -webkit-user-select: none; }
542.member-key pre { margin-top: 5px; padding: 9px 11px; background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-inner); white-space: pre-wrap; word-break: break-all; font-size: 11px; }
543
544/* ===================== FORMS ===================== *
545 * A labeled field is a stacked label + control. Short token fields (`rev`,
546 * `lines`, `state`, `verdict`) stop short instead of stretching. */
547form { display: flex; flex-direction: column; gap: 15px; margin-bottom: 18px; }
548form label { display: flex; flex-direction: column; gap: 6px; font-size: 12px; font-weight: 500; color: var(--ink-2); }
549form input, form textarea, form select {
550 font-family: var(--mono); font-size: 13px; color: var(--ink);
551 background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-inner);
552 padding: 9px 12px; width: 100%;
553}
554form input { height: 34px; }
555form input:focus, form textarea:focus, form select:focus { border-color: var(--accent); outline: none; }
556form input[name="rev"], form input[name="lines"], form input[name="state"], form input[name="verdict"] { max-width: 12rem; }
557form textarea { resize: vertical; min-height: 120px; line-height: 1.55; font-family: var(--sans); }
558form button {
559 align-self: flex-start; display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 18px;
560 font-size: 13px; font-weight: 500; color: #fff; background: var(--accent);
561 border: none; border-radius: var(--radius-inner); cursor: pointer;
562}
563form button:hover { background: var(--accent-2); }
564
565/* Segmented closed-enum picker (state/verdict/review-state): a row of
566 * buttons where the current option fills with its own chip color. */
567.picker { display: flex; flex-wrap: wrap; gap: 6px; }
568.picker button, .picker .opt {
569 display: inline-flex; flex-direction: row; align-items: center; gap: 6px; height: 32px; padding: 0 13px;
570 border-radius: var(--radius-inner); cursor: pointer; font-size: 12.5px; font-weight: 500;
571 color: var(--ink-2); background: var(--surface-2); border: 1px solid var(--line);
572}
573.picker .opt .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-4); }
574.picker .opt.active { font-weight: 600; }
575
576/* Label picker chips (`labelPicker`): pick existing or type-and-create. */
577.label-chip {
578 display: inline-flex; align-items: center; gap: 5px; height: 26px; padding: 0 10px;
579 border-radius: var(--radius-chip); cursor: pointer; font-family: var(--mono); font-size: 11px;
580 color: var(--ink-2); background: var(--surface-2); border: 1px solid var(--line);
581}
582.label-chip.on { color: var(--accent); background: var(--accent-soft); border-color: var(--accent-line); font-weight: 600; }
583
584/* ===================== DISCLOSURES ===================== *
585 * An edit affordance folded shut (issue edit, login-mapping edit): a
586 * bordered card-let whose summary is the whole closed state. */
587.disclosure {
588 background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
589 overflow: hidden; margin-bottom: 12px;
590}
591.disclosure > summary {
592 padding: 11px 16px; cursor: pointer; list-style: none; user-select: none; -webkit-user-select: none;
593 font-size: 12.5px; font-weight: 500; color: var(--ink-2);
594}
595.disclosure > summary::-webkit-details-marker { display: none; }
596.disclosure > summary:hover { color: var(--accent); }
597.disclosure form { padding: 4px 16px 16px; margin-bottom: 0; }
598
599/* ===================== CRUMBS ===================== */
600.crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; margin-bottom: 16px; font-family: var(--mono); font-size: 12px; color: var(--ink-3); word-break: break-all; }
601.crumbs a { color: var(--ink-3); }
602.crumbs a:hover { color: var(--accent); }
603.crumbs .sep { color: var(--ink-4); opacity: .8; display: inline-flex; }
604.crumbs .sep .icon { width: 12px; height: 12px; }
605.crumbs .here { color: var(--ink); }
606
607/* ===================== BLOB VIEW ===================== *
608 * `crate::pages::files`: a blob header bar over the line-per-row source
609 * table. */
610.blob-header {
611 position: relative;
612 display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; padding: 11px 15px;
613 background: var(--surface); border: 1px solid var(--line); border-bottom: none;
614 border-radius: var(--radius-inner) var(--radius-inner) 0 0;
615}
616.blob-header .icon { width: 15px; height: 15px; stroke-width: 1.7; color: var(--ink-3); }
617.blob-title { font-family: var(--mono); font-size: 13px; font-weight: 600; color: var(--ink); }
618.blob-meta { font-size: 12px; color: var(--ink-3); }
619.blob-actions { margin-left: auto; display: flex; align-items: center; gap: 12px; font-size: 12.5px; color: var(--ink-3); }
620.blob-actions a { color: var(--ink-2); }
621.blob-actions a:hover { color: var(--accent); }
622/* A "comment on this file/commit" trigger's popup (`assets/ents.js`):
623 * floats below its trigger's own header row instead of pushing the
624 * header/content box's own seamless border pairing apart. */
625.standalone-composer { position: absolute; top: calc(100% + 8px); right: 14px; z-index: 20; width: min(480px, calc(100vw - 60px)); }
626.standalone-composer .composer-form { margin: 0; max-width: none; }
627.blob {
628 overflow-x: auto; background: var(--surface); border: 1px solid var(--line);
629 border-radius: 0 0 var(--radius-inner) var(--radius-inner); margin-bottom: 18px; padding: 8px 0 10px;
630}
631/* A blob rendered without a header bar keeps all four corners rounded. */
632.blob:first-child { border-radius: var(--radius-inner); }
633.blob table { border-collapse: collapse; width: 100%; font-family: var(--mono); font-size: 12.5px; line-height: 21px; }
634.blob td.blob-nums {
635 position: sticky; left: 0; width: 52px; text-align: right; padding: 0 12px 0 0; vertical-align: top;
636 color: var(--ink-4); background: var(--surface); user-select: none; -webkit-user-select: none; white-space: nowrap;
637}
638.blob-nums a { display: block; color: inherit; padding: 0 .4ch; border-radius: 4px; cursor: pointer; }
639.blob-nums a:hover { color: var(--accent); }
640.blob-nums a:target { color: var(--accent); font-weight: 600; }
641.blob td.blob-code { padding: 0 16px 0 4px; white-space: pre; color: var(--ink); vertical-align: top; }
642.blob-code code { font-family: inherit; font-size: inherit; background: none; border: none; padding: 0; border-radius: 0; }
643.blob tr.blob-comment-row td { padding: 0; background: var(--surface); }
644.blob tr.blob-comment-row .card { margin: 5px 26px 7px 52px; }
645.binary { padding: 40px; text-align: center; font-family: var(--mono); font-size: 12.5px; color: var(--ink-3); }
646
647/* Client-side line selection (`assets/ents.js`): `tr.sel` spans a
648 * clicked/shift-clicked range with the design's accent-soft + inset bar. */
649.blob tr.sel td { background: var(--accent-soft); }
650.blob tr.sel td.blob-nums { color: var(--accent); font-weight: 600; box-shadow: inset 3px 0 0 var(--accent); }
651.blob-add {
652 position: absolute; top: 50%; left: 6px; transform: translateY(-50%);
653 width: 17px; height: 17px; line-height: 16px; padding: 0; text-align: center;
654 font-size: 13px; font-weight: 600; color: #fff; background: var(--accent);
655 border: none; border-radius: 5px; opacity: 0; cursor: pointer; transition: opacity .1s;
656}
657.blob td.blob-nums { position: sticky; } /* keep the affordance's containing block */
658.blob tr:hover .blob-add, .blob-add:focus-visible { opacity: 1; }
659
660/* Inline comment composer (`assets/ents.js` clones `composer-template`). */
661.blob tr.blob-composer td { padding: 0; background: var(--surface); }
662.composer-form {
663 margin: 5px 26px 8px 52px; max-width: 640px; background: var(--surface); border: 1px solid var(--accent);
664 border-radius: 9px; padding: 12px 13px; box-shadow: 0 4px 14px rgba(74, 63, 196, .1);
665}
666.composer-form textarea { min-height: 74px; }
667.composer-buttons { display: flex; flex-direction: row; gap: 8px; }
668.composer-buttons button { margin: 0; height: 28px; padding: 0 14px; }
669.composer-cancel {
670 align-self: flex-start; height: 28px; padding: 0 12px; font-size: 12.5px; font-weight: 500;
671 color: var(--ink-2); background: var(--surface); border: 1px solid var(--line);
672 border-radius: 7px; cursor: pointer;
673}
674.composer-cancel:hover { color: var(--accent); border-color: var(--accent-line); }
675
676/* ===================== COMMITS ===================== */
677.commit { padding: 16px 18px 18px; }
678.commit-subject { font-size: 19px; font-weight: 600; letter-spacing: -.2px; margin-bottom: 8px; }
679/* The commit message body renders through `crate::asciidoc::to_html`, the
680 * same pipeline an issue body or a `.adoc` blob does -- `.doc-body`'s own
681 * element rules (headings, lists, code spans) apply, scaled down to this
682 * compact metadata context instead of a full document card's. */
683.commit-msg.doc-body { padding: 0; max-width: none; font-size: 13px; margin-bottom: 8px; }
684.commit-meta { position: relative; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; color: var(--ink-3); font-size: 12px; font-family: var(--mono); margin-top: 6px; }
685.commit-meta a { color: var(--ink-3); }
686.commit-meta a:hover { color: var(--accent); }
687
688/* ===================== COMMENT CARDS ===================== *
689 * `crate::pages::comments::comment_card` -- the universal conversational
690 * primitive: avatar + author + relative time + optional reply/state, an
691 * AsciiDoc body reusing `.doc-body`. */
692.comment-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 12px 14px 6px; font-size: 11.5px; color: var(--ink-3); }
693.comment-meta .author { color: var(--ink); font-weight: 600; font-size: 12.5px; }
694.comment-meta .reply { font-family: var(--mono); font-size: 10px; }
695.comment-meta .spacer { flex: 1; }
696.comment-body { padding: 0 14px 12px; font-size: 13px; line-height: 1.55; color: var(--ink-2); text-wrap: pretty; }
697.comment-card + .comment-card { border-top: 1px solid var(--line-2); }
698.outdated { color: var(--amber); background: var(--amber-soft); font-family: var(--mono); font-size: 10px; padding: 2px 7px; border-radius: 5px; }
699.comment-state { display: inline-flex; align-items: center; height: 18px; padding: 0 7px; border-radius: 5px; font-size: 10px; font-weight: 600; color: var(--amber); background: var(--amber-soft); }
700.comment-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 10px 14px; border-top: 1px solid var(--line-2); background: var(--surface-2); }
701.comment-actions form { margin: 0; }
702/* An anchored blob thread card's header strip (thread on L<n>). */
703.thread-head { display: flex; align-items: center; gap: 8px; padding: 6px 13px; background: var(--surface-2); border-bottom: 1px solid var(--line-2); font-family: var(--mono); font-size: 11px; color: var(--ink-3); }
704.thread-head .dot { width: 5px; height: 5px; border-radius: 50%; background: var(--accent); flex: none; }
705
706/* ===================== SYNTAX ===================== *
707 * `crate::pages::files::highlight` (`arborium` `ClassNames`). */
708.code .keyword, .code .macro, .code .tag { color: var(--s-keyword); }
709.code .function, .code .constructor { color: var(--s-func); }
710.code .type { color: var(--s-type); }
711.code .string { color: var(--s-string); }
712.code .number, .code .constant, .code .label { color: var(--s-const); }
713.code .comment { color: var(--s-comment); font-style: italic; }
714.code .operator, .code .punctuation { color: var(--s-op); }
715.code .property, .code .attribute { color: var(--s-prop); }
716.code .title { color: var(--s-keyword); font-weight: 600; }
717.code .strong { font-weight: 600; }
718.code .emphasis { font-style: italic; }
719.code .link, .code .url, .code .reference { color: var(--s-prop); text-decoration: underline; }
720.code .markup { color: var(--s-func); }
721
722/* ===================== DIFFS ===================== *
723 * `crate::pages::commits::diff_view`. */
724.diff { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-inner); overflow-x: auto; margin-bottom: 12px; font-family: var(--mono); font-size: 12px; line-height: 19px; }
725.diff .ln { display: block; padding: 2px 14px; white-space: pre; }
726.diff .add { background: var(--diff-add); color: var(--green); }
727.diff .del { background: var(--diff-del); color: var(--red); }
728.diff .hunk { color: var(--accent); background: var(--surface-2); }
729.diff .meta { color: var(--ink-3); }
730.diff .file { color: var(--ink); font-weight: 600; background: var(--surface-2); border-bottom: 1px solid var(--line); padding: 9px 14px; }
731
732/* ===================== RENDERED DOCS ===================== */
733.doc-props { border: 1px solid var(--line); border-radius: var(--radius-inner); background: var(--surface-2); padding: 6px 0; margin: 0 0 18px; }
734.doc-props dd { white-space: pre-wrap; }
735.doc-body { padding: 28px 32px 36px; max-width: 44rem; overflow-wrap: break-word; font-size: 14px; line-height: 1.62; color: var(--ink-2); }
736.doc-body > :first-child { margin-top: 0; }
737.doc-body h1, .doc-body h2, .doc-body h3, .doc-body h4 { font-family: var(--sans); font-weight: 600; letter-spacing: -.01em; line-height: 1.3; margin: 1.6rem 0 .8rem; color: var(--ink); }
738.doc-body h1 { font-size: 1.9rem; letter-spacing: -.02em; margin-top: 0; }
739.doc-body .doc-subtitle { font-style: italic; font-size: 1.1rem; color: var(--ink-3); margin: -.3rem 0 1.1rem; }
740.doc-body h2 { font-size: 1.35rem; padding-bottom: .5rem; border-bottom: 1px solid var(--line); }
741.doc-body h3 { font-size: 1.12rem; }
742.doc-body p, .doc-body ul, .doc-body ol { margin: 0 0 1rem; }
743.doc-body ul, .doc-body ol { padding-left: 1.4rem; list-style: revert; }
744.doc-body li { margin: .25rem 0; }
745.doc-body a { font-weight: 500; text-decoration: underline; }
746.doc-body code, .doc-body .literal { font-family: var(--mono); font-size: .86em; background: var(--surface-2); border: 1px solid var(--line); padding: 1px 5px; border-radius: 5px; }
747.doc-body pre { font-family: var(--mono); font-size: 12.5px; line-height: 1.55; background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-inner); padding: 14px 16px; overflow-x: auto; margin: 0 0 1rem; }
748.doc-body pre code { background: none; border: none; padding: 0; font-size: inherit; }
749.doc-body blockquote { border-left: 3px solid var(--accent); padding: .2rem 0 .2rem 1.1rem; margin: 0 0 1rem; color: var(--ink-3); }
750.doc-body table { border-collapse: collapse; margin: 0 0 1rem; font-size: .95rem; }
751.doc-body th, .doc-body td { border: 1px solid var(--line); padding: .4rem .7rem; text-align: left; }
752.doc-body th { background: var(--surface-2); font-weight: 600; }
753.doc-body img { max-width: 100%; height: auto; }
754.doc-body hr { border: none; border-top: 1px solid var(--line); margin: 1.6rem 0; }
755
756/* ===================== LOGIN ===================== *
757 * `crate::pages::login` -- the inverted device-code flow: a dark code
758 * block, only ever mounted on a hosted deployment. */
759.login-code {
760 font-family: var(--mono); font-size: 15px; color: #fff; background: var(--ink);
761 border-radius: var(--radius-inner); padding: 16px 18px; overflow-x: auto; white-space: pre;
762}
763.login-code .code { color: var(--editor); font-weight: 600; }
764
765/* ============ PAGE-SCOPED ADDITIONS ============ *
766 * Classes the per-page reskin introduced, collected here so the whole
767 * design system stays in one stylesheet (the page modules never edit CSS
768 * themselves; they report the rule and it lands here). */
769
770/* The editor pill sits inside flex rows (`.card-row`, `.blob-actions`,
771 * `.commit-meta`) and must never stretch like a `.card-row a` link does. */
772.editor-open { flex: none; }
773.ed-loc { white-space: nowrap; }
774
775/* Dashboard working-tree change-kind chips (README ChangeKindLabel),
776 * layered on the `.chip` base. */
777.chip-added { color: var(--green); background: var(--green-soft); }
778.chip-modified { color: var(--amber); background: var(--amber-soft); }
779.chip-deleted { color: var(--red); background: var(--red-soft); }
780.chip-renamed { color: var(--accent); background: var(--accent-soft); }
781.chip-untracked { color: var(--ink-2); background: var(--line-2); }
782
783/* Dashboard working-tree path: ellipsize from the front (`direction:rtl`)
784 * so the filename stays visible when the path overflows. */
785.desk-path { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; direction: rtl; text-align: left; }
786
787/* Dashboard header's right-aligned deployment-mode line. */
788.desk-status { display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--ink-3); }
789.desk-status .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--editor); flex: none; }
790
791/* Files' outdated-comments section heading (warn glyph + title). */
792.outdated-head { display: flex; align-items: center; gap: 8px; margin: 0 0 6px; font-size: 12.5px; font-weight: 600; color: var(--ink-2); }
793.outdated-head .icon { width: 14px; height: 14px; stroke-width: 1.9; color: var(--amber); }
794
795/* Issues sidebar status dot, colored by issue state (the chip's own leading
796 * dot already inherits via `.chip .dot`). */
797.side-meta .dot.state-open { background: var(--green); }
798.side-meta .dot.state-in-progress { background: var(--amber); }
799.side-meta .dot.state-closed { background: var(--ink-4); }
800
801/* Segmented pickers: hide the native radio and fill the chosen option.
802 * Issues' state picker is server-rendered (`.opt.active.state-*`, colored by
803 * state); the commit verdict picker is plain radios, so its checked option
804 * fills via `:has()`. */
805.picker .opt { position: relative; }
806.picker .opt input { position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0; pointer-events: none; }
807.picker .opt:has(input:checked) { color: var(--accent); background: var(--accent-soft); border-color: var(--accent-line); font-weight: 600; }
808.picker .opt:has(input:checked) .dot, .picker .opt.active .dot { background: currentColor; }
809.picker .opt.active.state-open { color: var(--green); background: var(--green-soft); border-color: color-mix(in srgb, var(--green) 40%, transparent); }
810.picker .opt.active.state-in-progress { color: var(--amber); background: var(--amber-soft); border-color: color-mix(in srgb, var(--amber) 40%, transparent); }
811.picker .opt.active.state-closed { color: var(--ink-2); background: var(--line-2); border-color: var(--line); }
812
813/* Disclosure summaries (issue Edit, account login-mapping) read as
814 * clickable. */
815details > summary { cursor: pointer; }
816
817/* ===================== RESPONSIVE ===================== */
818@media (max-width: 640px) {
819 .content { padding: 22px 18px 40px; }
820 .wb-bar { gap: 10px; padding: 0 12px; }
821 .palette { max-width: none; }
822 .palette kbd { display: none; }
823 .page-title { font-size: 19px; }
824 .doc-body { padding: 22px 20px 28px; }
825 .doc-body h1 { font-size: 1.6rem; }
826}