@ok-ggwp/git-gloss 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -4
- package/dist/ary/browse.js +4 -61
- package/dist/ary/picker.js +163 -0
- package/dist/ary/server.js +87 -37
- package/dist/attention.js +34 -0
- package/dist/carry.js +4 -1
- package/dist/cli.js +2 -1
- package/dist/commands/add.js +17 -1
- package/dist/commands/ary.js +3 -3
- package/dist/commands/hunks.js +8 -1
- package/dist/commands/review.js +5 -4
- package/dist/commands/reviews.js +58 -5
- package/dist/commands/show.js +56 -20
- package/dist/commands/signals.js +89 -0
- package/dist/commands/sync.js +14 -2
- package/dist/commands/why.js +3 -2
- package/dist/config.js +248 -0
- package/dist/floor.js +148 -0
- package/dist/git.js +29 -3
- package/dist/glob.js +76 -0
- package/dist/html/client.js +1032 -296
- package/dist/html/data.js +26 -1
- package/dist/html/page.js +1 -1
- package/dist/html/style.css +310 -164
- package/dist/loader.js +7 -3
- package/dist/merge.js +5 -0
- package/dist/plain.js +9 -0
- package/dist/render.js +55 -5
- package/dist/reviews.js +98 -4
- package/dist/safe-match.js +30 -0
- package/dist/schema.js +55 -4
- package/dist/selection.js +21 -0
- package/dist/signals.js +302 -0
- package/dist/validate.js +10 -1
- package/package.json +1 -1
- package/skills/gloss/SKILL.md +42 -2
- package/dist/ary/client.js +0 -401
- package/dist/ary/index.html +0 -13
- package/dist/ary/style.css +0 -115
package/dist/html/data.js
CHANGED
|
@@ -2,8 +2,10 @@ import { commitDiff, commitSubject, git } from '../git.js';
|
|
|
2
2
|
import { reviewStatus, statusPhrase, verdict } from '../reviews.js';
|
|
3
3
|
import { parseDiff } from '../diff.js';
|
|
4
4
|
import { loadGloss } from '../loader.js';
|
|
5
|
+
import { belowFloor } from '../render.js';
|
|
6
|
+
import { showsImpact, tryAnalyze } from '../floor.js';
|
|
5
7
|
import { bodyLines, changedCount, gapText, isGap, refLabel, slice, sliceStats } from '../selection.js';
|
|
6
|
-
import { NECESSITY, NECESSITY_HELP, servesOf } from '../schema.js';
|
|
8
|
+
import { IMPACT, IMPACT_HELP, NECESSITY, NECESSITY_HELP, servesOf } from '../schema.js';
|
|
7
9
|
function pageReviews(sha) {
|
|
8
10
|
return reviewStatus(sha).map((s) => ({
|
|
9
11
|
stage: s.stage,
|
|
@@ -57,10 +59,23 @@ function pageHunk(h, lines, status, alsoIn) {
|
|
|
57
59
|
lines: pageLines(h, lines),
|
|
58
60
|
};
|
|
59
61
|
}
|
|
62
|
+
// The order a reviewer should read a commit's groups in. Deterministic: a
|
|
63
|
+
// stable sort over the groups as they come, so ties keep their order.
|
|
64
|
+
export function reviewOrder(groups, focus = []) {
|
|
65
|
+
const rank = (g) => IMPACT.indexOf((g.impact ?? g.impact_derived)) + 1; // 0: unrated
|
|
66
|
+
const first = (g) => (focus.includes(g.id) ? focus.indexOf(g.id) : focus.length);
|
|
67
|
+
return groups
|
|
68
|
+
.map((g, i) => ({ g, i }))
|
|
69
|
+
.sort((a, b) => first(a.g) - first(b.g) || rank(b.g) - rank(a.g) || (b.g.added + b.g.removed) - (a.g.added + a.g.removed) || a.i - b.i)
|
|
70
|
+
.map((x) => x.g.id);
|
|
71
|
+
}
|
|
60
72
|
const allLines = (h) => Array.from({ length: changedCount(h) }, (_, i) => i + 1);
|
|
61
73
|
export function commitData(gloss) {
|
|
62
74
|
const [author, date] = git(['log', '-1', '--format=%an%x00%aI', gloss.sha]).trim().split('\0');
|
|
63
75
|
const a = gloss.note.annotation;
|
|
76
|
+
const an = tryAnalyze(gloss);
|
|
77
|
+
// Same threshold as `show`: derived impact badges only where the diff puts a group above module.
|
|
78
|
+
const derivedImpact = showsImpact(gloss.groups.map((x) => x.group), an);
|
|
64
79
|
// Which groups claim each changed line, so shared lines are split between
|
|
65
80
|
// their groups in the bar and each hunk can link to the groups it shares
|
|
66
81
|
// lines with. A header-only hunk counts as one shared unit.
|
|
@@ -85,6 +100,9 @@ export function commitData(gloss) {
|
|
|
85
100
|
id: g.id,
|
|
86
101
|
intent: g.intent,
|
|
87
102
|
necessity: g.necessity,
|
|
103
|
+
impact: g.impact,
|
|
104
|
+
impact_reason: g.impact_reason,
|
|
105
|
+
impact_derived: g.impact || !derivedImpact ? undefined : an?.groups.get(g.id)?.floor,
|
|
88
106
|
serves: servesOf(g),
|
|
89
107
|
removal_impact: g.removal_impact,
|
|
90
108
|
evidence: g.evidence,
|
|
@@ -108,8 +126,11 @@ export function commitData(gloss) {
|
|
|
108
126
|
glossed: true,
|
|
109
127
|
task: a.task,
|
|
110
128
|
summary: a.summary,
|
|
129
|
+
attention: a.attention ?? null,
|
|
130
|
+
computed: an ? { floor: an.floor, derived: an.derived, below: belowFloor(a.attention, an), timedOut: an.timedOut } : null,
|
|
111
131
|
warnings: gloss.warnings,
|
|
112
132
|
groups,
|
|
133
|
+
order: reviewOrder(groups, a.attention?.focus),
|
|
113
134
|
unannotated: gloss.unannotated.map((u) => pageHunk(u.hunk, u.lines, 'unannotated', [])),
|
|
114
135
|
alternatives: a.alternatives ?? [],
|
|
115
136
|
risks: a.risks ?? [],
|
|
@@ -125,8 +146,11 @@ function unglossedData(sha) {
|
|
|
125
146
|
date,
|
|
126
147
|
glossed: false,
|
|
127
148
|
task: '',
|
|
149
|
+
attention: null,
|
|
150
|
+
computed: null,
|
|
128
151
|
warnings: [],
|
|
129
152
|
groups: [],
|
|
153
|
+
order: [],
|
|
130
154
|
unannotated: parseDiff(commitDiff(sha)).map((h) => pageHunk(h, null, 'unannotated', [])),
|
|
131
155
|
alternatives: [],
|
|
132
156
|
risks: [],
|
|
@@ -138,6 +162,7 @@ export function buildPageData(shas, range = null, merges = []) {
|
|
|
138
162
|
range,
|
|
139
163
|
merges: merges.map((sha) => ({ sha, subject: commitSubject(sha) })),
|
|
140
164
|
necessity: NECESSITY.map((name) => ({ name, help: NECESSITY_HELP[name] })),
|
|
165
|
+
impact: IMPACT.map((name) => ({ name, help: IMPACT_HELP[name] })),
|
|
141
166
|
commits: shas.map((sha) => {
|
|
142
167
|
const gloss = loadGloss(sha);
|
|
143
168
|
return gloss ? commitData(gloss) : unglossedData(sha);
|
package/dist/html/page.js
CHANGED
|
@@ -27,7 +27,7 @@ ${asset('./style.css')}
|
|
|
27
27
|
<div id="app"><noscript>This page needs JavaScript to render the gloss.</noscript></div>
|
|
28
28
|
<script type="application/json" id="gloss-data">${embedJson(data)}</script>
|
|
29
29
|
<script nonce="${nonce}">
|
|
30
|
-
${asset('./client.js')}
|
|
30
|
+
${data.ary ? asset('../ary/picker.js') + '\n' : ''}${asset('./client.js')}
|
|
31
31
|
</script>
|
|
32
32
|
</body>
|
|
33
33
|
</html>
|
package/dist/html/style.css
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
|
+
/* Review desk: a rail of groups (or commits) and a detail pane. System fonts
|
|
2
|
+
only: the page is one file and its CSP allows no other source. */
|
|
1
3
|
:root {
|
|
2
|
-
--bg: #
|
|
3
|
-
--
|
|
4
|
-
--
|
|
5
|
-
--
|
|
6
|
-
--
|
|
7
|
-
--
|
|
8
|
-
--
|
|
9
|
-
--accent: #
|
|
4
|
+
--bg: #f3f4f6;
|
|
5
|
+
--panel: #ffffff;
|
|
6
|
+
--ink: #14171f;
|
|
7
|
+
--muted: #586073;
|
|
8
|
+
--line: #dde0e6;
|
|
9
|
+
--accent: #3446d6;
|
|
10
|
+
--accent-soft: #e7eafb;
|
|
11
|
+
--accent-strong: #2536a8;
|
|
12
|
+
--on-accent: #ffffff;
|
|
13
|
+
--ok: #1b6b35;
|
|
14
|
+
--warn: #a5530a;
|
|
10
15
|
--warn-bg: #fff4e5;
|
|
11
16
|
--warn-border: #f0b35b;
|
|
12
17
|
--warn-text: #7a4300;
|
|
13
|
-
--add-bg: #
|
|
14
|
-
--add-mark: #
|
|
15
|
-
--del-bg: #
|
|
16
|
-
--del-mark: #
|
|
18
|
+
--add-bg: #e3f5e8;
|
|
19
|
+
--add-mark: #1b6b35;
|
|
20
|
+
--del-bg: #fbe7e8;
|
|
21
|
+
--del-mark: #b3262b;
|
|
17
22
|
--meta-bg: #eef1f8;
|
|
18
23
|
--meta-text: #4a5a85;
|
|
19
24
|
|
|
@@ -24,6 +29,19 @@
|
|
|
24
29
|
--n-speculative: #9c36b5;
|
|
25
30
|
--n-mechanical: #868e96;
|
|
26
31
|
|
|
32
|
+
/* Impact meter and attention gauge: one hue per step, and the steps differ
|
|
33
|
+
in lightness too, so they read without colour. */
|
|
34
|
+
--impact-local: #5b6373;
|
|
35
|
+
--impact-module: #0b6e83;
|
|
36
|
+
--impact-shared: #a5530a;
|
|
37
|
+
--impact-contract: #6b46c1;
|
|
38
|
+
--impact-sensitive: #b3262b;
|
|
39
|
+
--attention-skim: #5b6373;
|
|
40
|
+
--attention-look: #0b6e83;
|
|
41
|
+
--attention-careful: #a5530a;
|
|
42
|
+
--attention-must-read: #b3262b;
|
|
43
|
+
--attention-none: #586073;
|
|
44
|
+
|
|
27
45
|
--mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
|
|
28
46
|
--sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
29
47
|
color-scheme: light;
|
|
@@ -31,21 +49,24 @@
|
|
|
31
49
|
|
|
32
50
|
@media (prefers-color-scheme: dark) {
|
|
33
51
|
:root {
|
|
34
|
-
--bg: #
|
|
35
|
-
--
|
|
36
|
-
--
|
|
37
|
-
--
|
|
38
|
-
--
|
|
39
|
-
--
|
|
40
|
-
--
|
|
41
|
-
--accent: #
|
|
52
|
+
--bg: #101218;
|
|
53
|
+
--panel: #181b23;
|
|
54
|
+
--ink: #e8eaf0;
|
|
55
|
+
--muted: #a0a7b6;
|
|
56
|
+
--line: #2b303c;
|
|
57
|
+
--accent: #8fa0ff;
|
|
58
|
+
--accent-soft: #232a4a;
|
|
59
|
+
--accent-strong: #b3bfff;
|
|
60
|
+
--on-accent: #101218;
|
|
61
|
+
--ok: #62d089;
|
|
62
|
+
--warn: #f0a24a;
|
|
42
63
|
--warn-bg: #33270f;
|
|
43
64
|
--warn-border: #a2701e;
|
|
44
65
|
--warn-text: #f3c77a;
|
|
45
|
-
--add-bg: #
|
|
46
|
-
--add-mark: #
|
|
47
|
-
--del-bg: #
|
|
48
|
-
--del-mark: #
|
|
66
|
+
--add-bg: #14301d;
|
|
67
|
+
--add-mark: #62d089;
|
|
68
|
+
--del-bg: #3a1b1f;
|
|
69
|
+
--del-mark: #ff8085;
|
|
49
70
|
--meta-bg: #20263a;
|
|
50
71
|
--meta-text: #a3b1dc;
|
|
51
72
|
|
|
@@ -55,143 +76,209 @@
|
|
|
55
76
|
--n-incidental: #e0a43e;
|
|
56
77
|
--n-speculative: #cf7ee4;
|
|
57
78
|
--n-mechanical: #8d949b;
|
|
79
|
+
|
|
80
|
+
--impact-local: #a3aab8;
|
|
81
|
+
--impact-module: #4cc3d9;
|
|
82
|
+
--impact-shared: #f0a24a;
|
|
83
|
+
--impact-contract: #b39dff;
|
|
84
|
+
--impact-sensitive: #ff8085;
|
|
85
|
+
--attention-skim: #a3aab8;
|
|
86
|
+
--attention-look: #4cc3d9;
|
|
87
|
+
--attention-careful: #f0a24a;
|
|
88
|
+
--attention-must-read: #ff8085;
|
|
89
|
+
--attention-none: #a0a7b6;
|
|
58
90
|
color-scheme: dark;
|
|
59
91
|
}
|
|
60
92
|
}
|
|
61
93
|
|
|
62
94
|
* { box-sizing: border-box; }
|
|
63
95
|
html { -webkit-text-size-adjust: 100%; }
|
|
64
|
-
body {
|
|
65
|
-
margin: 0;
|
|
66
|
-
background: var(--bg);
|
|
67
|
-
color: var(--text);
|
|
68
|
-
font: 15px/1.55 var(--sans);
|
|
69
|
-
}
|
|
70
|
-
main { min-width: 0; }
|
|
96
|
+
body { margin: 0; background: var(--bg); color: var(--ink); font: 14px/1.5 var(--sans); }
|
|
71
97
|
a { color: var(--accent); text-decoration: none; }
|
|
72
98
|
a:hover { text-decoration: underline; }
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
margin: 0 auto;
|
|
81
|
-
padding: 24px 16px 64px;
|
|
82
|
-
gap: 32px;
|
|
83
|
-
}
|
|
84
|
-
@media (min-width: 1100px) {
|
|
85
|
-
.layout { grid-template-columns: 240px minmax(0, 1fr); padding: 32px 32px 80px; }
|
|
86
|
-
}
|
|
99
|
+
button { font: inherit; color: inherit; cursor: pointer; }
|
|
100
|
+
button:disabled { cursor: default; opacity: 0.5; }
|
|
101
|
+
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
102
|
+
code, .mono { font-family: var(--mono); font-size: 12px; }
|
|
103
|
+
.eyebrow { font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
|
|
104
|
+
.muted { color: var(--muted); }
|
|
105
|
+
kbd { font-family: var(--mono); font-size: 11px; border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 4px; padding: 0 5px; background: var(--panel); }
|
|
87
106
|
|
|
88
|
-
|
|
89
|
-
.toc { display: none; }
|
|
90
|
-
@media (min-width: 1100px) {
|
|
91
|
-
.toc { display: block; position: sticky; top: 24px; align-self: start; max-height: calc(100vh - 48px); overflow: auto; }
|
|
92
|
-
}
|
|
93
|
-
.toc h2 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); margin: 0 0 8px; }
|
|
94
|
-
.toc ol { list-style: none; margin: 0 0 24px; padding: 0; }
|
|
95
|
-
.toc li a {
|
|
96
|
-
display: flex; align-items: center; gap: 8px;
|
|
97
|
-
padding: 4px 8px; border-radius: 6px; color: var(--text);
|
|
98
|
-
font-family: var(--mono); font-size: 12.5px;
|
|
99
|
-
}
|
|
100
|
-
.toc li a:hover { background: var(--surface-2); text-decoration: none; }
|
|
101
|
-
.toc li.hidden a { opacity: 0.35; }
|
|
102
|
-
.toc li.active a { background: var(--surface-2); }
|
|
103
|
-
|
|
104
|
-
.dot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--c); }
|
|
105
|
-
|
|
106
|
-
/* Header */
|
|
107
|
-
.commit { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; color: var(--muted); font-size: 13px; }
|
|
108
|
-
.sha { font-family: var(--mono); background: var(--surface-2); border: 1px solid var(--border); padding: 1px 6px; border-radius: 5px; color: var(--text); }
|
|
109
|
-
h1 { font-size: 24px; line-height: 1.3; margin: 8px 0 16px; letter-spacing: -0.01em; }
|
|
110
|
-
.statement { margin: 0 0 8px; max-width: 75ch; }
|
|
111
|
-
.statement .label { color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; margin-right: 6px; }
|
|
112
|
-
|
|
113
|
-
.warning {
|
|
114
|
-
margin: 16px 0; padding: 12px 14px; border-radius: 8px;
|
|
115
|
-
background: var(--warn-bg); border: 1px solid var(--warn-border); color: var(--warn-text);
|
|
116
|
-
}
|
|
107
|
+
.desk { min-height: 100vh; display: flex; flex-direction: column; }
|
|
117
108
|
|
|
118
|
-
/*
|
|
119
|
-
.
|
|
120
|
-
.
|
|
121
|
-
.
|
|
122
|
-
.
|
|
123
|
-
.
|
|
124
|
-
.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
109
|
+
/* Top bar */
|
|
110
|
+
.top { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 20px; padding: 10px 16px; background: var(--panel); border-bottom: 1px solid var(--line); }
|
|
111
|
+
.brand { font-weight: 600; letter-spacing: -0.01em; }
|
|
112
|
+
.sha { font-family: var(--mono); font-size: 12px; background: var(--bg); border: 1px solid var(--line); border-radius: 5px; padding: 1px 6px; color: var(--ink); }
|
|
113
|
+
.subject { flex: 1 1 260px; min-width: 0; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
114
|
+
.seg { display: flex; flex-wrap: wrap; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; background: var(--bg); }
|
|
115
|
+
.seg button { border: 0; background: transparent; padding: 6px 12px; min-height: 44px; color: var(--muted); }
|
|
116
|
+
.seg button[aria-pressed="true"] { background: var(--ink); color: var(--panel); font-weight: 500; }
|
|
117
|
+
.seg .n { opacity: 0.75; margin-left: 4px; font-variant-numeric: tabular-nums; }
|
|
118
|
+
.prog { display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: 13px; }
|
|
119
|
+
.track { width: 120px; height: 6px; border-radius: 3px; background: var(--line); overflow: hidden; }
|
|
120
|
+
.track i { display: block; height: 100%; width: 0; background: var(--accent); }
|
|
121
|
+
|
|
122
|
+
/* Branch pickers and revision box in the top bar, only when served by `git gloss ary` */
|
|
123
|
+
.ary-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; min-width: 0; }
|
|
124
|
+
.ary-repo { color: var(--muted); font-family: var(--mono); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 200px; }
|
|
125
|
+
.ary-field { display: flex; align-items: center; gap: 6px; color: var(--muted); font-size: 12px; }
|
|
126
|
+
.ary-notice { flex-basis: 100%; margin: 0; padding: 6px 10px; border-radius: 8px; border: 1px dashed var(--warn); font-size: 13px; color: var(--ink); }
|
|
127
|
+
.combo { position: relative; }
|
|
128
|
+
.combo-btn, .combo-panel input, .ary-rev input { border: 1px solid var(--line); background: var(--panel); color: var(--ink); border-radius: 8px; min-height: 36px; padding: 4px 12px; font-size: 13px; }
|
|
129
|
+
.combo-btn { position: relative; max-width: 220px; padding-right: 28px; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--mono); font-size: 12.5px; }
|
|
130
|
+
.combo-btn::after { content: "▾"; position: absolute; right: 10px; color: var(--muted); }
|
|
131
|
+
.combo-btn:hover { background: var(--accent-soft); }
|
|
132
|
+
.combo-panel { position: absolute; z-index: 10; left: 0; top: calc(100% + 4px); width: 300px; max-width: calc(100vw - 32px); display: grid; gap: 6px; padding: 6px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); box-shadow: 0 8px 24px rgb(0 0 0 / 0.25); }
|
|
133
|
+
.combo-panel[hidden] { display: none; }
|
|
134
|
+
.combo-panel input { width: 100%; }
|
|
135
|
+
.combo-list { max-height: min(50vh, 320px); overflow: auto; }
|
|
136
|
+
.combo-group { margin-top: 8px; padding: 10px 8px 4px; border-top: 1px solid var(--line); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink); }
|
|
137
|
+
.combo-group:first-child { margin-top: 0; padding-top: 4px; border-top: 0; }
|
|
138
|
+
.combo-group .count { margin-left: 6px; color: var(--muted); font-weight: 400; }
|
|
139
|
+
.combo-item { display: block; width: 100%; text-align: left; border: 0; background: none; border-radius: 6px; padding: 5px 8px 5px 20px; font-family: var(--mono); font-size: 12.5px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
140
|
+
.combo-item:hover, .combo-item.active { background: var(--accent-soft); }
|
|
141
|
+
.combo-item[aria-selected="true"] { color: var(--accent); font-weight: 600; }
|
|
142
|
+
.combo-more { padding: 6px 8px; color: var(--muted); font-size: 12.5px; }
|
|
143
|
+
.ary-rev input { width: 220px; max-width: 100%; font-family: var(--mono); font-size: 12.5px; }
|
|
144
|
+
|
|
145
|
+
/* Body: rail above the pane when narrow, beside it from 900px */
|
|
146
|
+
.body { flex: 1; display: grid; grid-template-columns: minmax(0, 1fr); align-items: start; }
|
|
147
|
+
@media (min-width: 900px) {
|
|
148
|
+
/* the rail's panel colour runs the full height, however tall the top bar is */
|
|
149
|
+
.body { grid-template-columns: 360px minmax(0, 1fr); background: linear-gradient(90deg, var(--panel) 359px, var(--line) 359px 360px, transparent 360px); }
|
|
150
|
+
.body.range { grid-template-columns: 400px minmax(0, 1fr); background: linear-gradient(90deg, var(--panel) 399px, var(--line) 399px 400px, transparent 400px); }
|
|
151
|
+
/* the bar stays put and the rail fits in what is left (--top-h is measured by the script) */
|
|
152
|
+
.top { position: sticky; top: 0; z-index: 5; }
|
|
153
|
+
.rail { position: sticky; top: var(--top-h, 0px); max-height: calc(100vh - var(--top-h, 0px)); overflow: auto; overscroll-behavior: contain; border-bottom: 0; border-right: 1px solid var(--line); }
|
|
128
154
|
}
|
|
155
|
+
.rail { background: var(--panel); border-bottom: 1px solid var(--line); display: flex; flex-direction: column; min-width: 0; }
|
|
156
|
+
.main { min-width: 0; padding: 20px 16px 48px; }
|
|
157
|
+
@media (min-width: 900px) { .main { padding: 28px 40px 48px; } }
|
|
158
|
+
|
|
159
|
+
/* Attention: the card in the rail, the large one in a commit overview */
|
|
160
|
+
.att { margin: 20px 0 0; padding: 16px 18px; border: 1.5px solid var(--lv); border-radius: 12px; background: var(--panel); max-width: 720px; --lv: var(--attention-none); }
|
|
161
|
+
.att .lvl { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; font-size: 22px; font-weight: 600; letter-spacing: 0.02em; color: var(--lv); }
|
|
162
|
+
.att .src { font-size: 12px; font-weight: 500; letter-spacing: 0; color: var(--muted); border: 1px solid var(--line); border-radius: 999px; padding: 0 8px; }
|
|
163
|
+
.att ul { margin: 10px 0 0; padding-left: 20px; }
|
|
164
|
+
.att li { margin-bottom: 4px; }
|
|
165
|
+
.att .look { margin: 10px 0 0; font-size: 13px; }
|
|
166
|
+
.att .override { margin: 10px 0 0; font-size: 13px; color: var(--warn-text); background: var(--warn-bg); border-radius: 6px; padding: 6px 10px; }
|
|
167
|
+
.att .timedout { margin: 10px 0 0; padding: 6px 10px 6px 28px; font-size: 13px; color: var(--warn-text); background: var(--warn-bg); border-radius: 6px; }
|
|
168
|
+
.att .override.mismatch { font-weight: 600; border: 1px solid var(--warn-border); }
|
|
169
|
+
.gauge { display: inline-flex; gap: 3px; }
|
|
170
|
+
.gauge i { display: block; width: 22px; height: 8px; border-radius: 2px; background: var(--line); }
|
|
171
|
+
.gauge i.on { background: var(--lv); }
|
|
172
|
+
.gauge.small i { width: 12px; height: 6px; }
|
|
173
|
+
|
|
174
|
+
/* Impact meter: five bars that grow, filled up to the level */
|
|
175
|
+
.meter { display: inline-flex; align-items: flex-end; gap: 2px; height: 16px; flex: none; }
|
|
176
|
+
.meter i { display: block; width: 4px; border-radius: 1px; background: var(--line); }
|
|
177
|
+
.meter i.on { background: var(--m, var(--impact-local)); }
|
|
178
|
+
.meter i:nth-child(1) { height: 6px; }
|
|
179
|
+
.meter i:nth-child(2) { height: 9px; }
|
|
180
|
+
.meter i:nth-child(3) { height: 11px; }
|
|
181
|
+
.meter i:nth-child(4) { height: 14px; }
|
|
182
|
+
.meter i:nth-child(5) { height: 16px; }
|
|
183
|
+
.meter.unrated i { background: transparent; border: 1px dashed var(--muted); }
|
|
184
|
+
|
|
185
|
+
/* Rail: groups */
|
|
186
|
+
.rail h2 { margin: 0; }
|
|
187
|
+
.railhead { padding: 4px 24px 8px; }
|
|
188
|
+
.necs { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 16px 10px; }
|
|
189
|
+
.chip { display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--line); border-radius: 999px; padding: 2px 10px; font-size: 13px; background: var(--panel); color: var(--ink); }
|
|
190
|
+
button.chip { min-height: 32px; }
|
|
129
191
|
.chip .count { color: var(--muted); font-variant-numeric: tabular-nums; }
|
|
130
|
-
.chip[aria-pressed="false"] { opacity: 0.
|
|
131
|
-
.chip
|
|
132
|
-
.
|
|
133
|
-
|
|
134
|
-
.
|
|
135
|
-
.
|
|
136
|
-
.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
.
|
|
192
|
+
.chip[aria-pressed="false"] { opacity: 0.6; text-decoration: line-through; }
|
|
193
|
+
.chip.link { cursor: pointer; }
|
|
194
|
+
.chip.link:hover { background: var(--accent-soft); }
|
|
195
|
+
.rows { display: flex; flex-direction: column; padding: 0 8px; }
|
|
196
|
+
.row { display: flex; align-items: stretch; border-radius: 8px; border: 1px solid transparent; }
|
|
197
|
+
.row.sel { background: var(--accent-soft); border-color: var(--accent); }
|
|
198
|
+
.row.done .rtitle { color: var(--muted); }
|
|
199
|
+
.check { flex: 0 0 44px; min-height: 44px; border: 0; background: transparent; display: flex; align-items: center; justify-content: center; }
|
|
200
|
+
.check span { width: 18px; height: 18px; border: 1.5px solid var(--muted); border-radius: 5px; display: flex; align-items: center; justify-content: center; background: var(--panel); font-size: 13px; line-height: 1; }
|
|
201
|
+
.check[aria-pressed="true"] span { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
|
|
202
|
+
.pick { flex: 1; min-width: 0; border: 0; background: transparent; text-align: left; display: flex; align-items: center; gap: 10px; padding: 8px 8px 8px 0; min-height: 56px; }
|
|
203
|
+
.rtxt { display: flex; flex-direction: column; min-width: 0; flex: 1; }
|
|
204
|
+
.rtitle { font-weight: 500; line-height: 1.3; overflow-wrap: anywhere; }
|
|
205
|
+
.rsub { color: var(--muted); font-size: 12px; overflow-wrap: anywhere; }
|
|
206
|
+
.flag { flex: none; font-size: 11px; font-weight: 600; border: 1px solid var(--lv, var(--attention-careful)); color: var(--lv, var(--attention-careful)); border-radius: 4px; padding: 0 5px; }
|
|
207
|
+
.emptyrows { padding: 8px 24px 16px; color: var(--muted); }
|
|
208
|
+
.overviewrow { padding: 12px 8px 4px; }
|
|
209
|
+
.overviewrow .row .pick { min-height: 44px; padding-left: 16px; }
|
|
210
|
+
.railfoot { margin-top: auto; padding: 16px; border-top: 1px solid var(--line); font-size: 13px; }
|
|
211
|
+
.railfoot .eyebrow { margin-bottom: 6px; }
|
|
212
|
+
.railfoot a { display: inline-block; padding: 8px 0; }
|
|
141
213
|
|
|
142
|
-
/*
|
|
143
|
-
.
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
.
|
|
148
|
-
.
|
|
149
|
-
.
|
|
150
|
-
.
|
|
151
|
-
.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
.
|
|
156
|
-
.
|
|
157
|
-
.
|
|
214
|
+
/* Rail: commits of a range */
|
|
215
|
+
.sum { margin: 16px; padding: 14px 16px; border: 1px solid var(--line); border-radius: 10px; background: var(--bg); }
|
|
216
|
+
.sum .line { margin-top: 8px; color: var(--muted); font-size: 13px; }
|
|
217
|
+
.sum .line b { color: var(--ink); font-weight: 600; }
|
|
218
|
+
.strip { display: flex; gap: 3px; height: 14px; margin-top: 10px; }
|
|
219
|
+
.strip i { display: block; flex: 1; border-radius: 3px; background: var(--lv); min-width: 2px; }
|
|
220
|
+
.strip i.none { background: transparent; border: 1.5px dashed var(--attention-none); }
|
|
221
|
+
.commits { display: flex; flex-direction: column; padding: 0 8px 16px; }
|
|
222
|
+
.crow { margin-bottom: 2px; }
|
|
223
|
+
.crow > .pick { display: block; width: 100%; border: 1px solid transparent; border-radius: 8px; padding: 10px 12px; min-height: 64px; }
|
|
224
|
+
.crow.sel > .pick { background: var(--accent-soft); border-color: var(--accent); }
|
|
225
|
+
.rtop { display: flex; align-items: center; gap: 10px; }
|
|
226
|
+
.rtop .sha { border: 0; background: transparent; padding: 0; color: var(--muted); }
|
|
227
|
+
.lv { margin-left: auto; display: inline-flex; align-items: center; gap: 8px; font-size: 11.5px; font-weight: 600; letter-spacing: 0.05em; color: var(--lv); }
|
|
228
|
+
.csubject { display: block; font-weight: 500; line-height: 1.3; margin-top: 2px; overflow-wrap: anywhere; }
|
|
229
|
+
.cmeta { display: block; color: var(--muted); font-size: 12px; margin-top: 2px; }
|
|
230
|
+
.crow .rows { padding: 2px 0 8px 12px; }
|
|
231
|
+
.mergelist { padding: 0 24px 16px; color: var(--muted); font-size: 13px; }
|
|
232
|
+
.mergelist .eyebrow { margin-bottom: 4px; }
|
|
233
|
+
|
|
234
|
+
/* Detail pane */
|
|
235
|
+
.crumbs { color: var(--muted); font-size: 13px; }
|
|
236
|
+
.commit { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; color: var(--muted); font-size: 13px; margin-bottom: 8px; }
|
|
237
|
+
h1 { font-size: 26px; line-height: 1.25; margin: 6px 0 14px; letter-spacing: -0.015em; font-weight: 600; max-width: 40ch; overflow-wrap: anywhere; }
|
|
238
|
+
h2 { font-size: 15px; margin: 28px 0 10px; }
|
|
239
|
+
.tags { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; }
|
|
240
|
+
.imp { display: inline-flex; align-items: center; gap: 8px; font-weight: 500; color: var(--m); }
|
|
241
|
+
.imp.derived { font-style: italic; }
|
|
242
|
+
.reason { margin: 10px 0 0; color: var(--muted); max-width: 70ch; overflow-wrap: anywhere; }
|
|
243
|
+
.stats { font-family: var(--mono); font-size: 12px; color: var(--muted); white-space: nowrap; }
|
|
158
244
|
.plus { color: var(--add-mark); }
|
|
159
245
|
.minus { color: var(--del-mark); }
|
|
160
246
|
.stale { font-size: 12px; color: var(--warn-text); background: var(--warn-bg); border-radius: 4px; padding: 0 6px; }
|
|
161
|
-
|
|
162
|
-
.
|
|
163
|
-
.
|
|
164
|
-
.
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
.
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
.
|
|
177
|
-
.
|
|
178
|
-
.
|
|
247
|
+
.warning { margin: 16px 0 0; padding: 12px 14px; border-radius: 8px; max-width: 720px; background: var(--warn-bg); border: 1px solid var(--warn-border); color: var(--warn-text); }
|
|
248
|
+
.statement { margin: 12px 0 0; max-width: 75ch; overflow-wrap: anywhere; }
|
|
249
|
+
.statement .label { color: var(--muted); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; margin-right: 8px; }
|
|
250
|
+
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 12px; margin: 24px 0 8px; align-items: start; }
|
|
251
|
+
.card { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 14px 16px; min-width: 0; }
|
|
252
|
+
.card p { margin: 4px 0 0; overflow-wrap: anywhere; }
|
|
253
|
+
.files { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
|
|
254
|
+
.frow { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 8px 16px; border-top: 1px solid var(--line); }
|
|
255
|
+
.frow:first-child { border-top: 0; }
|
|
256
|
+
.frow .mono { overflow-wrap: anywhere; min-width: 0; }
|
|
257
|
+
.chead { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; margin: 28px 0 10px; }
|
|
258
|
+
.chead h2 { margin: 0; }
|
|
259
|
+
.btn { display: inline-flex; align-items: center; border: 1px solid var(--line); background: var(--panel); border-radius: 8px; padding: 8px 16px; min-height: 44px; color: var(--ink); }
|
|
260
|
+
.btn:hover:not(:disabled) { background: var(--accent-soft); }
|
|
261
|
+
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); font-weight: 500; }
|
|
262
|
+
.btn.primary:hover:not(:disabled) { background: var(--accent-strong); border-color: var(--accent-strong); }
|
|
263
|
+
.btn.small { min-height: 36px; padding: 4px 12px; font-size: 13px; }
|
|
264
|
+
.nav { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 28px; }
|
|
265
|
+
.keys { margin-left: auto; color: var(--muted); font-size: 12px; align-self: center; }
|
|
179
266
|
|
|
180
267
|
/* Hunks */
|
|
181
|
-
.hunk { border: 1px solid var(--
|
|
182
|
-
.hunk
|
|
183
|
-
.hunk-head {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
187
|
-
.
|
|
268
|
+
.hunk { margin-top: 12px; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; background: var(--panel); }
|
|
269
|
+
.hunk-head { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; padding: 8px 14px; background: var(--bg); border-bottom: 1px solid var(--line); font-size: 12.5px; }
|
|
270
|
+
.hunk.closed .hunk-head { border-bottom: 0; }
|
|
271
|
+
.htoggle { display: inline-flex; align-items: center; gap: 8px; border: 0; background: transparent; padding: 6px 4px; min-height: 36px; text-align: left; border-radius: 6px; }
|
|
272
|
+
.htoggle:hover { background: var(--accent-soft); }
|
|
273
|
+
.hunk-head .file { font-family: var(--mono); font-weight: 500; overflow-wrap: anywhere; }
|
|
274
|
+
.chev { color: var(--muted); width: 1em; }
|
|
188
275
|
.hunk-head .range { font-family: var(--mono); color: var(--muted); }
|
|
189
276
|
.also { color: var(--muted); }
|
|
190
277
|
.also a { font-family: var(--mono); }
|
|
191
|
-
.scroll { overflow-x: auto; }
|
|
192
|
-
table.diff { border-collapse: collapse; width: 100%; font-family: var(--mono); font-size: 12.5px; line-height: 1.
|
|
278
|
+
.scroll { overflow-x: auto; overscroll-behavior-x: contain; }
|
|
279
|
+
table.diff { border-collapse: collapse; width: 100%; font-family: var(--mono); font-size: 12.5px; line-height: 1.6; }
|
|
193
280
|
table.diff td { padding: 0 8px; vertical-align: top; }
|
|
194
|
-
td.ln { width: 1%; min-width: 3.2em; text-align: right; color: var(--muted); user-select: none;
|
|
281
|
+
td.ln { width: 1%; min-width: 3.2em; text-align: right; color: var(--muted); user-select: none; }
|
|
195
282
|
td.mark { width: 1%; padding: 0 2px 0 4px; user-select: none; }
|
|
196
283
|
td.text { white-space: pre; }
|
|
197
284
|
tr.add { background: var(--add-bg); }
|
|
@@ -199,31 +286,90 @@ tr.add td.mark { color: var(--add-mark); }
|
|
|
199
286
|
tr.del { background: var(--del-bg); }
|
|
200
287
|
tr.del td.mark { color: var(--del-mark); }
|
|
201
288
|
tr.meta td { background: var(--meta-bg); color: var(--meta-text); }
|
|
202
|
-
tr.gap td { background: var(--
|
|
203
|
-
|
|
204
|
-
/*
|
|
205
|
-
.
|
|
206
|
-
.
|
|
207
|
-
.
|
|
208
|
-
.
|
|
209
|
-
|
|
289
|
+
tr.gap td { background: var(--bg); color: var(--muted); font-style: italic; font-family: var(--sans); padding: 2px 8px; }
|
|
290
|
+
|
|
291
|
+
/* A commit's groups in the detail pane (range pages) */
|
|
292
|
+
.filters { margin: 12px 0 0; }
|
|
293
|
+
.main .necs { padding: 10px 0; }
|
|
294
|
+
.main .rows { padding: 8px; background: var(--panel); border: 1px solid var(--line); border-radius: 10px; }
|
|
295
|
+
.back { margin-bottom: 12px; max-width: 100%; text-align: left; }
|
|
296
|
+
|
|
297
|
+
/* Overview extras */
|
|
298
|
+
.bar { display: flex; height: 10px; border-radius: 5px; overflow: hidden; background: var(--line); max-width: 720px; }
|
|
299
|
+
.bar span { display: block; height: 100%; background: var(--c); min-width: 2px; }
|
|
300
|
+
.bar span + span { border-left: 2px solid var(--panel); }
|
|
301
|
+
.legend { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 8px; font-size: 12.5px; color: var(--muted); }
|
|
302
|
+
.legend .dot { margin-right: 6px; }
|
|
303
|
+
.dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--c, var(--muted)); }
|
|
304
|
+
.legend + .chips { margin-top: 12px; }
|
|
305
|
+
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
306
|
+
.chips .chip b { font-family: var(--mono); font-weight: 500; font-size: 12px; }
|
|
307
|
+
.chips .chip span { color: var(--muted); }
|
|
308
|
+
.warnbox { margin: 20px 0 0; padding: 16px 18px; border: 1px dashed var(--warn); border-radius: 12px; background: var(--panel); max-width: 720px; }
|
|
309
|
+
.warnbox .t { font-weight: 600; }
|
|
310
|
+
.warnbox p { margin: 6px 0 0; }
|
|
311
|
+
.cmd { font-family: var(--mono); font-size: 12px; color: var(--muted); }
|
|
312
|
+
.unannotated { border: 1px dashed var(--del-mark); border-radius: 10px; padding: 12px 16px; background: var(--panel); }
|
|
313
|
+
.unannotated > p { margin: 0 0 4px; }
|
|
314
|
+
.list { margin: 0; padding-left: 20px; max-width: 70ch; }
|
|
315
|
+
.list li { margin-bottom: 6px; overflow-wrap: anywhere; }
|
|
210
316
|
.list .why { color: var(--muted); }
|
|
211
317
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
.
|
|
217
|
-
.
|
|
218
|
-
.
|
|
219
|
-
.
|
|
220
|
-
.
|
|
221
|
-
.
|
|
222
|
-
.
|
|
223
|
-
|
|
224
|
-
/* Reviews recorded for a commit */
|
|
225
|
-
.reviews { margin: 8px 0 12px; display: flex; flex-direction: column; gap: 4px; }
|
|
226
|
-
.review summary { cursor: pointer; }
|
|
318
|
+
/* Recorded reviews: a compact status block in the rail, the full view in the pane */
|
|
319
|
+
.reviews { display: flex; flex-direction: column; gap: 2px; }
|
|
320
|
+
.rvrow { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 44px; padding: 4px 8px; border: 0; border-radius: 8px; background: transparent; text-align: left; }
|
|
321
|
+
.rvrow:hover { background: var(--accent-soft); }
|
|
322
|
+
.rvdot.ok { color: var(--ok); }
|
|
323
|
+
.rvdot.warn { color: var(--warn); }
|
|
324
|
+
.rvdot.none { color: var(--muted); }
|
|
325
|
+
.rvdot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: currentColor; }
|
|
326
|
+
.rvstage { font-weight: 600; }
|
|
327
|
+
.rvtxt { color: var(--muted); font-size: 12.5px; flex: 1; min-width: 0; overflow-wrap: anywhere; }
|
|
328
|
+
.rvn { color: var(--muted); font-variant-numeric: tabular-nums; flex: none; }
|
|
227
329
|
.review-ok { color: var(--ok); font-weight: 600; }
|
|
228
|
-
.review-none { color: var(--muted);
|
|
229
|
-
.
|
|
330
|
+
.review-none { color: var(--muted); }
|
|
331
|
+
.rvstagepane { margin-top: 28px; }
|
|
332
|
+
.rvstagepane h2 { margin: 0 0 6px; font-size: 18px; }
|
|
333
|
+
.rvsum { margin: 0 0 12px; }
|
|
334
|
+
.rvsum .stale { background: transparent; padding: 0; font-size: inherit; color: var(--warn); font-weight: 600; }
|
|
335
|
+
.entry { margin: 0 0 20px; max-width: 75ch; }
|
|
336
|
+
.entry.old { border-top: 1px solid var(--line); padding-top: 8px; }
|
|
337
|
+
.entry summary { cursor: pointer; padding: 6px 0; min-height: 36px; }
|
|
338
|
+
.entry summary .ehead { display: inline-flex; }
|
|
339
|
+
.ehead { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin-bottom: 8px; }
|
|
340
|
+
.chip.good { color: var(--ok); border-color: var(--ok); }
|
|
341
|
+
.chip.bad { color: var(--warn); border-color: var(--warn); }
|
|
342
|
+
|
|
343
|
+
/* Rendered markdown */
|
|
344
|
+
.md { max-width: 75ch; overflow-wrap: anywhere; }
|
|
345
|
+
.md p { margin: 0 0 10px; }
|
|
346
|
+
.md h3, .md h4, .md h5, .md h6 { margin: 18px 0 6px; line-height: 1.3; }
|
|
347
|
+
.md h3 { font-size: 17px; }
|
|
348
|
+
.md h4 { font-size: 15px; }
|
|
349
|
+
.md h5, .md h6 { font-size: 14px; }
|
|
350
|
+
.md ul, .md ol { margin: 0 0 10px; padding-left: 22px; }
|
|
351
|
+
.md li { margin-bottom: 4px; }
|
|
352
|
+
.md code { background: var(--bg); border: 1px solid var(--line); border-radius: 4px; padding: 0 4px; }
|
|
353
|
+
.md pre { margin: 0 0 12px; padding: 10px 12px; background: var(--bg); border: 1px solid var(--line); border-radius: 8px; overflow-x: auto; overscroll-behavior-x: contain; }
|
|
354
|
+
.md pre code { border: 0; padding: 0; background: transparent; white-space: pre; overflow-wrap: normal; }
|
|
355
|
+
|
|
356
|
+
footer { padding: 16px; color: var(--muted); font-size: 12.5px; border-top: 1px solid var(--line); }
|
|
357
|
+
footer p { margin: 6px 0 0; }
|
|
358
|
+
|
|
359
|
+
@media (max-width: 600px) {
|
|
360
|
+
h1 { font-size: 22px; }
|
|
361
|
+
.keys { display: none; }
|
|
362
|
+
.track { width: 80px; }
|
|
363
|
+
}
|
|
364
|
+
main footer { padding-left: 0; padding-right: 0; margin-top: 32px; }
|
|
365
|
+
.linkbtn { border: 0; background: transparent; padding: 8px 0; min-height: 36px; color: var(--accent); text-decoration: underline; text-align: left; }
|
|
366
|
+
|
|
367
|
+
.railsec { margin-top: 12px; padding: 12px 16px 4px; border-top: 1px solid var(--line); font-size: 13px; }
|
|
368
|
+
.railsec .eyebrow { margin-bottom: 4px; }
|
|
369
|
+
.overviewrow .lv { margin-left: 8px; flex: none; }
|
|
370
|
+
.focuscards { display: flex; flex-direction: column; gap: 8px; max-width: 720px; }
|
|
371
|
+
.focuscard { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; width: 100%; text-align: left; padding: 12px 16px; min-height: 44px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); }
|
|
372
|
+
.focuscard:hover { background: var(--accent-soft); border-color: var(--accent); }
|
|
373
|
+
.fctitle { font-weight: 600; overflow-wrap: anywhere; }
|
|
374
|
+
.fcmeta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; }
|
|
375
|
+
.fcreason { color: var(--muted); overflow-wrap: anywhere; }
|