getgloss 0.1.1 → 0.2.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.
@@ -3,12 +3,35 @@
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Gloss</title>
7
- <script type="module" crossorigin src="/assets/index-GpOF1p41.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-BiGi3rBS.css">
6
+ <title>Gloss - Local diff reviews for coding agents</title>
7
+ <meta
8
+ name="description"
9
+ content="Gloss opens local code diffs in a browser and saves review comments as JSON and Markdown in your repo."
10
+ />
11
+ <link rel="canonical" href="https://getgloss.dev/" />
12
+ <link rel="icon" type="image/svg+xml" href="/logo.svg" />
13
+ <meta property="og:title" content="Gloss - Local diff reviews for coding agents" />
14
+ <meta
15
+ property="og:description"
16
+ content="Review local code changes in a browser, then save line comments back to the working tree."
17
+ />
18
+ <meta property="og:type" content="website" />
19
+ <meta property="og:url" content="https://getgloss.dev/" />
20
+ <meta property="og:image" content="https://getgloss.dev/og.png" />
21
+ <meta property="og:image:alt" content="Gloss local code diff review interface" />
22
+ <meta property="og:image:width" content="1200" />
23
+ <meta property="og:image:height" content="630" />
24
+ <meta name="twitter:card" content="summary_large_image" />
25
+ <meta name="twitter:title" content="Gloss - Local diff reviews for coding agents" />
26
+ <meta
27
+ name="twitter:description"
28
+ content="Comment on local code diffs and save feedback in your repo."
29
+ />
30
+ <meta name="twitter:image" content="https://getgloss.dev/og.png" />
31
+ <script type="module" crossorigin src="/assets/index-xfsP7fu_.js"></script>
32
+ <link rel="stylesheet" crossorigin href="/assets/index-BQXNNRgM.css">
9
33
  </head>
10
34
  <body>
11
35
  <div id="root"></div>
12
36
  </body>
13
37
  </html>
14
-
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env sh
2
+ set -eu
3
+
4
+ if ! command -v npm >/dev/null 2>&1; then
5
+ echo "npm is required. Install Node.js first: https://nodejs.org/" >&2
6
+ exit 1
7
+ fi
8
+
9
+ npm install -g getgloss
10
+ gloss --version
@@ -0,0 +1,14 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" role="img" aria-labelledby="title desc">
2
+ <title id="title">Gloss logo</title>
3
+ <desc id="desc">A dark rounded square with red and green diff hunks.</desc>
4
+ <rect x="8" y="8" width="240" height="240" rx="54" fill="#14171B" />
5
+ <rect x="9" y="9" width="238" height="238" rx="53" fill="none" stroke="#56606C" stroke-width="2" />
6
+ <rect x="36" y="56" width="150" height="72" rx="26" fill="#4B1F26" />
7
+ <rect x="36.5" y="56.5" width="149" height="71" rx="25.5" fill="none" stroke="#EF8A8C" stroke-opacity="0.45" />
8
+ <rect x="70" y="128" width="150" height="72" rx="26" fill="#183C2B" />
9
+ <rect x="70.5" y="128.5" width="149" height="71" rx="25.5" fill="none" stroke="#74D59A" stroke-opacity="0.5" />
10
+ <path d="M68 92H118" fill="none" stroke="#F4F1EA" stroke-width="16" stroke-linecap="round" />
11
+ <path d="M103 164H153M128 139V189" fill="none" stroke="#F4F1EA" stroke-width="16" stroke-linecap="round" />
12
+ <path d="M154 92H164" fill="none" stroke="#EF8A8C" stroke-width="16" stroke-linecap="round" />
13
+ <path d="M187 164H197" fill="none" stroke="#74D59A" stroke-width="16" stroke-linecap="round" />
14
+ </svg>
Binary file
@@ -10,11 +10,13 @@ when the current working tree has code changes.
10
10
  From the repo root, open a blocking review with:
11
11
 
12
12
  ```bash
13
- gloss open --json --base HEAD
13
+ gloss open --json
14
14
  ```
15
15
 
16
- Use `--base <ref>` when the user specifies a comparison base such as
17
- `origin/main` or `origin/master`.
16
+ Gloss opens staged, unstaged, and untracked working changes first. If the
17
+ working tree is clean, it falls back to the branch diff against the best
18
+ available merge-base. Use `--base <ref>` only when the user specifies a
19
+ comparison base such as `HEAD`, `origin/main`, or `origin/master`.
18
20
 
19
21
  Leave the command running. Do not interrupt, kill, background, detach, or treat
20
22
  the waiting process as cleanup. The wait is intentional: Gloss exits after the
@@ -55,4 +57,3 @@ gloss mcp
55
57
 
56
58
  The MCP server exposes tools to list pending reviews, fetch review details,
57
59
  watch for completion, read feedback, and mark a review resolved.
58
-
@@ -0,0 +1,279 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Gloss Setup</title>
7
+ <link rel="icon" type="image/svg+xml" href="/logo.svg" />
8
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
10
+ <link
11
+ href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700;800&display=swap"
12
+ rel="stylesheet"
13
+ />
14
+ <meta
15
+ name="description"
16
+ content="Set up Gloss for local code-diff reviews with coding agents."
17
+ />
18
+ <style>
19
+ :root {
20
+ color-scheme: dark;
21
+ --color-midnight-ink: #111111;
22
+ --color-site-accent: #3fb950;
23
+ --color-ghost-ash: #f9f9f9;
24
+ --color-deep-graphite: #2b2b2b;
25
+ --color-muted-stone: #b7b3a2;
26
+ --color-light-grayscale: #eeeeee;
27
+ --color-shadow-ink: #000000;
28
+ --color-subtle-gray: #d6d6d6;
29
+ --color-silver-mist: #9c9c9c;
30
+ --color-dark-frost: #222222;
31
+ --color-slate-border: #565656;
32
+ --font-primary:
33
+ "JetBrains Mono", "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
34
+ --font-mono: var(--font-primary);
35
+ --grid-line: rgba(249, 249, 249, 0.055);
36
+ --border-soft: rgba(214, 214, 214, 0.18);
37
+ --radius-nav: 4px;
38
+ --radius-cards: 12px;
39
+ --radius-panel: 8px;
40
+
41
+ font-family: var(--font-primary);
42
+ background: var(--color-midnight-ink);
43
+ color: var(--color-ghost-ash);
44
+ }
45
+
46
+ * {
47
+ box-sizing: border-box;
48
+ }
49
+
50
+ html {
51
+ background: var(--color-midnight-ink);
52
+ }
53
+
54
+ body {
55
+ min-width: 320px;
56
+ min-height: 100vh;
57
+ margin: 0;
58
+ background:
59
+ linear-gradient(var(--grid-line) 1px, transparent 1px),
60
+ linear-gradient(90deg, var(--grid-line) 1px, transparent 1px),
61
+ var(--color-midnight-ink);
62
+ background-size: 32px 32px;
63
+ }
64
+
65
+ main {
66
+ width: min(860px, calc(100vw - 32px));
67
+ margin: 0 auto;
68
+ padding: 32px 0 80px;
69
+ }
70
+
71
+ nav {
72
+ position: sticky;
73
+ top: 0;
74
+ z-index: 3;
75
+ display: flex;
76
+ align-items: center;
77
+ justify-content: space-between;
78
+ gap: 16px;
79
+ margin-bottom: 64px;
80
+ padding: 16px 0;
81
+ border-bottom: 1px solid var(--border-soft);
82
+ background: rgba(17, 17, 17, 0.94);
83
+ backdrop-filter: blur(16px);
84
+ font-size: 12px;
85
+ }
86
+
87
+ a {
88
+ color: var(--color-site-accent);
89
+ text-decoration: none;
90
+ }
91
+
92
+ a:hover {
93
+ text-decoration: underline;
94
+ }
95
+
96
+ a:focus-visible {
97
+ outline: 2px solid var(--color-site-accent);
98
+ outline-offset: 2px;
99
+ }
100
+
101
+ .wordmark {
102
+ display: inline-flex;
103
+ align-items: center;
104
+ gap: 9px;
105
+ color: var(--color-ghost-ash);
106
+ font-weight: 500;
107
+ text-decoration: none;
108
+ }
109
+
110
+ .mark {
111
+ display: block;
112
+ width: 28px;
113
+ height: 28px;
114
+ border: 1px solid var(--border-soft);
115
+ border-radius: var(--radius-nav);
116
+ background: var(--color-shadow-ink);
117
+ }
118
+
119
+ h1 {
120
+ max-width: 760px;
121
+ margin: 0;
122
+ color: var(--color-ghost-ash);
123
+ font-size: 64px;
124
+ font-weight: 500;
125
+ line-height: 0.9;
126
+ letter-spacing: 0;
127
+ }
128
+
129
+ .lede {
130
+ max-width: 660px;
131
+ margin: 16px 0 0;
132
+ color: var(--color-silver-mist);
133
+ font-size: 16px;
134
+ line-height: 1.5;
135
+ }
136
+
137
+ section {
138
+ margin-top: 48px;
139
+ border-top: 1px solid var(--border-soft);
140
+ padding-top: 32px;
141
+ }
142
+
143
+ h2 {
144
+ margin: 0 0 16px;
145
+ color: var(--color-site-accent);
146
+ font-size: 12px;
147
+ font-weight: 500;
148
+ letter-spacing: 0;
149
+ text-transform: uppercase;
150
+ }
151
+
152
+ p,
153
+ li {
154
+ color: var(--color-subtle-gray);
155
+ font-size: 15px;
156
+ line-height: 1.65;
157
+ }
158
+
159
+ ul {
160
+ margin: 12px 0 0;
161
+ padding-left: 22px;
162
+ }
163
+
164
+ code,
165
+ pre {
166
+ font-family: var(--font-mono);
167
+ }
168
+
169
+ code {
170
+ color: var(--color-ghost-ash);
171
+ }
172
+
173
+ pre {
174
+ overflow-x: auto;
175
+ margin: 12px 0 0;
176
+ border: 1px solid var(--border-soft);
177
+ border-radius: var(--radius-panel);
178
+ background: var(--color-dark-frost);
179
+ color: var(--color-ghost-ash);
180
+ padding: 16px;
181
+ font-size: 13px;
182
+ line-height: 1.7;
183
+ }
184
+
185
+ .note {
186
+ border: 1px solid var(--color-slate-border);
187
+ border-radius: var(--radius-cards);
188
+ background: var(--color-dark-frost);
189
+ padding: 16px;
190
+ }
191
+
192
+ .note p {
193
+ margin: 0;
194
+ color: var(--color-subtle-gray);
195
+ }
196
+
197
+ @media (max-width: 640px) {
198
+ nav {
199
+ justify-content: flex-start;
200
+ overflow-x: auto;
201
+ white-space: nowrap;
202
+ }
203
+
204
+ h1 {
205
+ font-size: 48px;
206
+ }
207
+ }
208
+ </style>
209
+ </head>
210
+ <body>
211
+ <main>
212
+ <nav>
213
+ <a class="wordmark" href="/">
214
+ <img class="mark" src="/logo.svg" alt="" aria-hidden="true" />
215
+ Gloss
216
+ </a>
217
+ <a href="/setup.md">Raw setup.md</a>
218
+ </nav>
219
+
220
+ <header>
221
+ <h1>Set up Gloss for agent reviews.</h1>
222
+ <p class="lede">
223
+ Install the CLI, then add the Gloss instruction block to the file your coding agent
224
+ already reads.
225
+ </p>
226
+ </header>
227
+
228
+ <section>
229
+ <h2>Install</h2>
230
+ <pre>npm install -g getgloss</pre>
231
+ <pre>gloss help</pre>
232
+ </section>
233
+
234
+ <section>
235
+ <h2>Agent Instruction</h2>
236
+ <p>Give a new agent chat this instruction:</p>
237
+ <pre>Install Gloss with npm. Then read https://getgloss.dev/setup.md.</pre>
238
+ </section>
239
+
240
+ <section>
241
+ <h2>Claude Code Skill</h2>
242
+ <p>Install the optional skill when you want /gloss-style behavior in Claude Code.</p>
243
+ <pre>mkdir -p ~/.claude/skills/gloss
244
+ curl -fsSL https://getgloss.dev/skill/SKILL.md -o ~/.claude/skills/gloss/SKILL.md</pre>
245
+ <p>
246
+ The skill runs <code>gloss open --json --base HEAD</code>, waits for submission, reads the
247
+ feedback file, fixes comments, and validates the change.
248
+ </p>
249
+ </section>
250
+
251
+ <section>
252
+ <h2>Persistent Instructions</h2>
253
+ <p>Add the canonical Gloss block to the instruction file your agent actually loads.</p>
254
+ <pre>curl -fsSL https://getgloss.dev/prompt.md >> /absolute/path/to/AGENTS.md</pre>
255
+ <ul>
256
+ <li>Codex usually reads <code>${CODEX_HOME:-$HOME/.codex}/AGENTS.md</code>.</li>
257
+ <li>Claude Code usually reads <code>$HOME/.claude/CLAUDE.md</code>.</li>
258
+ <li>Project-local agents often read <code>AGENTS.md</code> from the repo root.</li>
259
+ </ul>
260
+ </section>
261
+
262
+ <section>
263
+ <h2>Use</h2>
264
+ <pre>gloss open --json --base HEAD</pre>
265
+ <p>
266
+ Leave the command running. Gloss exits after the browser review is submitted and writes
267
+ feedback under <code>.gloss/reviews/&lt;reviewId&gt;/</code>.
268
+ </p>
269
+ </section>
270
+
271
+ <section class="note">
272
+ <p>
273
+ Agents should read <a href="/setup.md">/setup.md</a>. Humans can use this page as the
274
+ browser-friendly version.
275
+ </p>
276
+ </section>
277
+ </main>
278
+ </body>
279
+ </html>
package/dist/web/setup.md CHANGED
@@ -24,6 +24,24 @@ npm i -g getgloss
24
24
  If the user did not explicitly ask you to install software, ask before
25
25
  installing a global npm package.
26
26
 
27
+ ## Install the Claude Code Skill
28
+
29
+ Gloss ships a Claude Code skill in the repository at `skill/SKILL.md`. If the
30
+ user wants Claude Code to know when to use Gloss automatically, install it with
31
+ the `skills` CLI:
32
+
33
+ ```bash
34
+ # Global (available across all projects)
35
+ npx skills add iamrajjoshi/gloss --skill gloss -g -a claude-code
36
+
37
+ # Project-local (only inside the current project)
38
+ npx skills add iamrajjoshi/gloss --skill gloss -a claude-code
39
+ ```
40
+
41
+ Use the global install for a cross-project review workflow. Use the
42
+ project-local install only when the user wants Gloss behavior scoped to the
43
+ current repo.
44
+
27
45
  ## Update Your Persistent Instructions
28
46
 
29
47
  Add Gloss guidance to the persistent instruction file this agent will actually
@@ -110,9 +128,14 @@ After updating your instructions, briefly tell the user which file you changed.
110
128
  Open a review and wait until the user submits feedback:
111
129
 
112
130
  ```bash
113
- gloss open --json --base HEAD
131
+ gloss open --json
114
132
  ```
115
133
 
134
+ By default Gloss opens staged, unstaged, and untracked working changes. If the
135
+ working tree is clean, it falls back to the branch diff against the best
136
+ available merge-base. Pass `--base <ref>` only when the user asks for a specific
137
+ comparison base.
138
+
116
139
  Open a review and return immediately:
117
140
 
118
141
  ```bash
@@ -130,4 +153,3 @@ Diagnose setup:
130
153
  ```bash
131
154
  gloss doctor
132
155
  ```
133
-
@@ -0,0 +1,22 @@
1
+ ---
2
+ name: gloss
3
+ description: Open local code changes in Gloss for browser review, wait for feedback, and address the returned comments.
4
+ ---
5
+
6
+ # Gloss
7
+
8
+ Use this skill when the user asks to review local code changes with Gloss, says
9
+ "gloss this", "open gloss", "review my changes", or wants a browser-based local
10
+ diff review before a PR.
11
+
12
+ ## Workflow
13
+
14
+ 1. Run `gloss open --json --base ${base:-HEAD}` from the repo root.
15
+ 2. Wait for the command to exit. It blocks until the browser review is submitted.
16
+ 3. Parse the JSON output and read `feedbackPath` if present.
17
+ 4. Address each comment in order by file and line.
18
+ 5. Validate the fix with the narrowest relevant tests or build.
19
+ 6. Summarize the comments addressed and the validation performed.
20
+
21
+ If the user asks only to open the review and not wait, run
22
+ `gloss open --json --no-watch`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "getgloss",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Local browser-based diff review for coding-agent loops.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.33.2",
package/skill/SKILL.md CHANGED
@@ -1,23 +1,27 @@
1
1
  ---
2
2
  name: gloss
3
- description: Open local code changes in Gloss for browser review, wait for feedback, and address the returned comments.
3
+ description: Open local working-tree or branch changes in Gloss for browser review, wait for feedback, and address returned comments. Use when the user asks to review local code changes, open Gloss, inspect a browser diff, or comment on a diff before a PR.
4
4
  ---
5
5
 
6
6
  # Gloss
7
7
 
8
- Use this skill when the user asks to review local code changes with Gloss, says
9
- "gloss this", "open gloss", "review my changes", or wants a browser-based local
10
- diff review before a PR.
11
-
12
8
  ## Workflow
13
9
 
14
- 1. Run `gloss open --json --base ${base:-HEAD}` from the repo root.
10
+ 1. Run `gloss open --json` from the repo root unless the user names a base ref.
15
11
  2. Wait for the command to exit. It blocks until the browser review is submitted.
16
12
  3. Parse the JSON output and read `feedbackPath` if present.
17
13
  4. Address each comment in order by file and line.
18
14
  5. Validate the fix with the narrowest relevant tests or build.
19
15
  6. Summarize the comments addressed and the validation performed.
20
16
 
17
+ Gloss opens staged, unstaged, and untracked working changes first. If the
18
+ working tree is clean, it falls back to the branch diff against the best
19
+ available merge-base. Use `--base <ref>` only when the user asks for a specific
20
+ comparison such as `origin/main`, `origin/master`, or `HEAD`.
21
+
22
+ If you need less-common options, run `gloss open --help` for command-specific
23
+ flags or `gloss --help` for the top-level command list instead of guessing
24
+ parameters.
25
+
21
26
  If the user asks only to open the review and not wait, run
22
27
  `gloss open --json --no-watch`.
23
-
@@ -1 +0,0 @@
1
- /*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.block{display:block}.contents{display:contents}.hidden{display:none}}:root{color-scheme:dark;color:#f4f1ea;background:#101113;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}*{box-sizing:border-box}body{background:linear-gradient(#ffffff06,#0000 280px),#101113;min-width:320px;margin:0}button,textarea{font:inherit}button{color:inherit}.review-shell{width:min(1320px,100vw - 32px);margin:0 auto;padding:18px 0 110px}.topbar{z-index:5;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);background:#101113eb;justify-content:space-between;align-items:center;gap:16px;padding:14px 0 16px;display:flex;position:sticky;top:0}.brand-row{align-items:center;gap:10px;display:flex}.brand-row h1{letter-spacing:0;margin:0;font-size:20px;font-weight:700}.brand-mark{color:#d8f28f;background:#1b1d21;border:1px solid #3d4147;border-radius:7px;place-items:center;width:28px;height:28px;font-weight:800;display:grid}.muted{color:#9da3ad;margin:4px 0 0;font-size:13px}.branch-pill{color:#cbd1da;background:#181a1e;border:1px solid #30343a;border-radius:7px;align-items:center;gap:8px;min-width:0;max-width:46vw;padding:7px 10px;font-size:13px;display:inline-flex}.branch-pill span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.diff-stack{gap:12px;display:grid}.file-card{background:#15171a;border:1px solid #30343a;border-radius:8px;overflow:hidden}.file-header{cursor:pointer;text-align:left;background:#1b1d21;border:0;border-bottom:1px solid #30343a;grid-template-columns:auto auto minmax(0,1fr) auto auto auto;align-items:center;gap:9px;width:100%;padding:10px 12px;display:grid}.file-path,.rename-path{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.file-path{color:#f4f1ea;font-family:SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:13px}.rename-path{color:#8e96a3;max-width:240px;font-size:12px}.stat{font-family:SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:12px;font-weight:700}.stat.add{color:#74d59a}.stat.del{color:#ef8a8c}.diff-table{border:0;width:100%;margin:0;padding:6px 0;overflow-x:auto}.sr-only{clip:rect(0,0,0,0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.hunk+.hunk{border-top:1px solid #24282e}.hunk-header,.hidden-lines,.binary-note{color:#8f98a6;text-align:left;background:#20242a;border:0;width:100%;font-family:SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:12px}.hunk-header{padding:8px 14px}.hidden-lines{cursor:pointer;padding:7px 14px;display:block}.binary-note{padding:14px}.diff-row{color:#d8dde5;cursor:cell;text-align:left;background:0 0;border:0;grid-template-columns:58px 58px 24px minmax(680px,1fr);align-items:stretch;width:100%;min-height:26px;display:grid}.diff-row:hover,.diff-row.selected{background:#2a2f36}.diff-row.add{background:#43a05f24}.diff-row.delete{background:#c94c5229}.diff-row.add:hover,.diff-row.delete:hover{filter:brightness(1.18)}.line-number{-webkit-user-select:none;user-select:none;color:#727b88;text-align:right;border-right:1px solid #252a31;padding-right:10px;font-family:SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:12px;line-height:26px}.marker{-webkit-user-select:none;user-select:none;color:#8e96a3;text-align:center;font-family:SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:12px;line-height:26px}.diff-row code{white-space:pre;font-family:SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:12.5px;line-height:26px;overflow:visible}.inline-comment{color:#f4e5b0;background:#252116;border:1px solid #45412b;border-radius:7px;align-items:flex-start;gap:8px;margin:4px 12px 8px 140px;padding:8px 10px;font-size:13px;display:flex}.popover{z-index:20;background:#202329;border:1px solid #4b5059;border-radius:8px;width:min(360px,100vw - 24px);padding:12px;position:fixed;box-shadow:0 24px 80px #0000006b}.popover-title{color:#f4f1ea;justify-content:space-between;align-items:center;font-size:13px;font-weight:700;display:flex}.popover-subtitle{color:#9da3ad;margin-top:2px;font-size:12px}.popover textarea{resize:vertical;color:#f4f1ea;background:#121417;border:1px solid #3b4048;border-radius:7px;outline:none;width:100%;min-height:96px;margin-top:10px;padding:9px}.popover textarea:focus{border-color:#d8f28f}.popover-actions,.submit-actions{justify-content:flex-end;align-items:center;gap:10px;display:flex}.popover-actions{margin-top:10px}.primary-button,.icon-button{cursor:pointer;border:1px solid #0000;border-radius:7px;justify-content:center;align-items:center;display:inline-flex}.primary-button{color:#171912;background:#d8f28f;gap:8px;min-height:34px;padding:0 12px;font-size:13px;font-weight:800}.primary-button:disabled{cursor:default;opacity:.58}.icon-button{color:#aab1bc;background:0 0;width:28px;height:28px}.icon-button:hover{color:#f4f1ea;background:#30343a}.submit-bar{z-index:10;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);background:#181a1ef0;border:1px solid #343941;border-radius:8px;justify-content:space-between;align-items:center;gap:18px;width:min(1320px,100vw - 36px);margin:0 auto;padding:12px;display:flex;position:fixed;bottom:18px;left:18px;right:18px;box-shadow:0 18px 70px #00000061}.comment-list{flex:1;gap:8px;min-width:0;display:flex;overflow-x:auto}.comment-chip{color:#f4e5b0;background:#242116;border:1px solid #45412b;border-radius:7px;align-items:center;gap:8px;min-width:max-content;padding:5px 7px 5px 10px;font-family:SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:12px;display:inline-flex}.submit-message{color:#9da3ad;text-overflow:ellipsis;white-space:nowrap;max-width:36vw;font-size:13px;overflow:hidden}.submit-message.error{color:#ef8a8c}.submit-message.done{color:#74d59a}.empty-shell{place-items:center;min-height:100vh;padding:24px;display:grid}.empty-panel{text-align:center;background:#181a1e;border:1px solid #30343a;border-radius:8px;width:min(420px,100%);padding:22px}.empty-panel h1{margin:0 0 8px}.empty-diff{color:#9da3ad;background:#181a1e;border:1px solid #30343a;border-radius:8px;padding:22px}.spin{animation:1s linear infinite spin}@keyframes spin{to{transform:rotate(360deg)}}@media(max-width:720px){.review-shell{width:calc(100vw - 18px)}.topbar{flex-direction:column;align-items:flex-start}.branch-pill{max-width:100%}.file-header{grid-template-columns:auto auto minmax(0,1fr) auto auto}.rename-path{display:none}.diff-row{grid-template-columns:46px 46px 22px minmax(520px,1fr)}.inline-comment{margin-left:108px}.submit-bar{flex-direction:column;align-items:stretch}.submit-actions{justify-content:space-between}}