guito 1.0.9 → 1.0.11

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/CHANGELOG.md CHANGED
@@ -4,6 +4,30 @@ All notable changes to Guito are documented in this file. The project follows [S
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.0.11] - 2026-10-12
8
+
9
+ ### Added
10
+
11
+ - Keyboard shortcuts for the commit history. **Ctrl+F** focuses the commit search box, **Ctrl+J** selects and scrolls to the current branch's commit (or the checked-out commit when HEAD is detached), and **Ctrl+G** opens a **Go to Commit** dialog. Type a row number to jump to that row of the list as currently shown, or a commit hash (at least 4 characters) to jump to that commit. History that isn't loaded yet is fetched as needed, and the dialog explains when a row is out of range, a hash is ambiguous or unknown, or the commit is hidden by the current branch or search filter. On macOS, Cmd works in place of Ctrl. The shortcuts do nothing while a dialog is open.
12
+ - **Code review of uncommitted changes.** A new **Code review** button sits after the stash buttons on the uncommitted changes panel. It has Claude Code review everything not yet committed: staged, unstaged and untracked files. While the review runs, the button turns into **Stop review**. When it finishes, the results open in a new tab: a VS Code editor tab inside the extension, or a browser tab in standalone Guito. Each finding shows its severity and comment and links to the file and line. Its **Auto fix** button has Claude Code fix that one problem in the working tree. Claude Code may only read and edit files; it cannot run commands or use git. The fix shows up as an ordinary uncommitted edit, and **Stop** cancels a running fix. Reviews and fixes use the configured review model, effort, instructions and timeout (`guito.aiReview.*`). The last review is kept per worktree in `.git/guito-working-review.json`.
13
+
14
+ ### Changed
15
+
16
+ - Ref pills in the commit history now match the graph. Each branch pill takes the color of its graph line; the current branch stays filled, now in its line color instead of a fixed blue. Local and remote branches and tags share one pill style. Remote branches get a cloud icon and tags keep the tag icon, and tags use a soft yellow that no graph line uses. To keep that yellow unique, the graph's two yellowish line colors were replaced with violet and silver. Prefer a quieter look? The new **Gray branch and tag pills** setting (`guito.grayRefBadges` in VS Code, off by default) draws every branch and tag pill in one neutral gray, with the current branch filled.
17
+ - The close buttons on the uncommitted changes panel, commit detail, settings, pull request, diff and merge conflict views, and the error banner's dismiss button now share one look and behavior, matching the commit panel's close button.
18
+
19
+ ### Removed
20
+
21
+ - Stashes no longer appear in the commit history. The "Show stashes" setting (`guito.showStashes` in VS Code) is gone, and the latest stash commit is no longer drawn in the graph; stashes are listed only in the repository panel.
22
+
23
+ ## [1.0.10] - 2026-10-10
24
+
25
+ ### Added
26
+
27
+ - Sort the repository panel's worktrees and pull requests. New **Worktree order** and **Pull request order** settings (`guito.worktreeSort` and `guito.prSort` inside the extension) order each section independently: worktrees offer Default order, Name A–Z and Name Z–A, while pull requests offer Newest first, Oldest first, Title A–Z and Title Z–A. The defaults keep the current behavior.
28
+ - Both side panels can now be resized. Drag the thin handle on the repository panel's right edge or on a commit detail / working panel's left edge to give it more or less room; arrow keys resize too (hold Shift for bigger steps), and double-clicking the handle returns the panel to its default width. Each choice is remembered between sessions, and the two right-hand panels share one width so the detail view keeps its size as you move between commits and uncommitted changes.
29
+ - The diff viewers now include a code minimap. A scaled-down preview of the changed file sits on the modified side of every diff — commits, working-tree and branch comparisons, and pull request reviews alike — with green marks where lines were added and red marks where lines were removed, so the shape of a change is visible without scrolling. Clicking or dragging the minimap moves the diff, and the diff dialog's header has a new **Toggle minimap** button for hiding it when you would rather give the code the full width.
30
+
7
31
  ## [1.0.9] - 2026-10-04
8
32
 
9
33
  ### Fixed
package/README.md CHANGED
@@ -14,7 +14,7 @@ The name combines **GUI** and **Git**: **G**u**IT**o. It is also a [Portuguese w
14
14
  - Stashes listed in the commit table with apply, pop, and drop actions.
15
15
  - Commit search by subject, body, author, or hash, with loading feedback and retries.
16
16
  - Local and remote branch filtering.
17
- - Commit and working-tree diffs powered by the Monaco editor, with inline and side-by-side layouts.
17
+ - Commit and working-tree diffs powered by the Monaco editor, with inline and side-by-side layouts and a code minimap preview of the changed file.
18
18
  - Fetch, pull, pull with rebase, push, and sync actions.
19
19
  - Context actions for creating branches and tags, checking out commits, cherry-picking, reverting, merging, rebasing, resetting, and exporting archives.
20
20
  - Working-tree actions for stashing changes, resetting tracked changes, and cleaning untracked files.
@@ -97,9 +97,9 @@ The settings dialog also manages preferences that have no VS Code equivalent: th
97
97
  | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
98
98
  | `guito.autoReload` | Reload commits and the working tree automatically when the repository changes outside Guito, for example from a terminal. On by default. |
99
99
  | `guito.showGraph` | Show the Git graph beside the commit history. On by default. |
100
- | `guito.showStashes` | Show stash entries above the commit history. Off by default. |
101
100
  | `guito.showTags` | Show tag badges attached to commits. On by default. |
102
101
  | `guito.showRemoteBranches` | Show remote branches in the repository panel and the branch pills on commits. On by default. |
102
+ | `guito.grayRefBadges` | Show branch and tag pills in a single neutral gray instead of graph lane colors. Off by default. |
103
103
  | `guito.fileListView` | How changed-file lists are shown: `flat` (default) lists every file with its full path, `tree` groups them into collapsible folders. |
104
104
  | `guito.refListView` | How branches and tags are shown in the repository panel: `flat` (default) lists full names, `tree` groups them into collapsible namespace folders. |
105
105
  | `guito.sidePanelSectionsExpanded`| Open the repository panel with all sections expanded. On by default. |
package/bin/ai-review.js CHANGED
@@ -2,7 +2,7 @@ import { spawn } from 'node:child_process';
2
2
  import { createHash } from 'node:crypto';
3
3
  import { homedir } from 'node:os';
4
4
  import { join } from 'node:path';
5
- const SEVERITIES = ['blocker', 'concern', 'suggestion', 'nit'];
5
+ export const SEVERITIES = ['blocker', 'concern', 'suggestion', 'nit'];
6
6
  /** Effort levels Claude Code accepts for --effort; '' leaves it to Claude Code. */
7
7
  export const AI_REVIEW_EFFORTS = ['', 'low', 'medium', 'high', 'xhigh', 'max'];
8
8
  /** How much a drafted commit message says beyond its subject line. */
@@ -267,7 +267,7 @@ export function parseModelReview(raw) {
267
267
  };
268
268
  }
269
269
  /** Identity of a finding across re-reviews: same place, same point. */
270
- function fingerprint(file, title) {
270
+ export function fingerprint(file, title) {
271
271
  const normalized = title
272
272
  .toLowerCase()
273
273
  .replace(/[^a-z0-9]+/g, ' ')
@@ -275,7 +275,7 @@ function fingerprint(file, title) {
275
275
  return createHash('sha1').update(`${file}\u0000${normalized}`).digest('hex').slice(0, 16);
276
276
  }
277
277
  /** Renders one file's diff with the line numbers the model must cite. */
278
- function renderFileDiff(diff, budget) {
278
+ export function renderFileDiff(diff, budget) {
279
279
  const header = `--- FILE: ${diff.path}${diff.oldPath && diff.oldPath !== diff.path ? ` (renamed from ${diff.oldPath})` : ''} [${diff.status}] ---`;
280
280
  if (diff.binary)
281
281
  return `${header}\n(binary file, not reviewable)\n`;
@@ -320,7 +320,7 @@ function renderThreads(threads) {
320
320
  })
321
321
  .join('\n');
322
322
  }
323
- const REVIEW_CONTRACT = `Reply with one JSON object and nothing else:
323
+ export const REVIEW_CONTRACT = `Reply with one JSON object and nothing else:
324
324
  {"summary": "<one or two sentences on the change as a whole>",
325
325
  "findings": [
326
326
  {"file": "<path exactly as given in the diff header, or \\"\\" for the change as a whole>",
@@ -16,6 +16,7 @@ import { avatarCache } from './avatars.js';
16
16
  import { repositoryState } from './repository-state.js';
17
17
  import { createAiReviewer, resolveAiReviewConfig, } from './ai-review.js';
18
18
  import { generateCommitMessage } from './commit-message.js';
19
+ import { WorkingReviewBusyError, createWorkingReviewer, } from './working-review.js';
19
20
  const execFileAsync = promisify(execFile);
20
21
  const AZURE_API_VERSION = '5.0-preview';
21
22
  // The Policy API has been GA since 4.1 and does not answer to the
@@ -250,7 +251,7 @@ const azureErrorMessage = (result) => {
250
251
  return result.body;
251
252
  }
252
253
  };
253
- export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 8080, apiToken, azureDevOpsUrl, prBranchNameTemplate, autoReload, diffViewer, showGraph, showStashes, showTags, showRemoteBranches, issueRegex, issueUrl, allowMerge, fileListView, refListView, sidePanelSectionsExpanded, searchMode, searchCaseSensitive, aiReview, azureRequestImpl, aiReviewModelImpl, avatarFetchImpl, onLog, }) {
254
+ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 8080, apiToken, azureDevOpsUrl, prBranchNameTemplate, autoReload, diffViewer, showGraph, showTags, showRemoteBranches, grayRefBadges, issueRegex, issueUrl, allowMerge, fileListView, refListView, sidePanelSectionsExpanded, searchMode, searchCaseSensitive, worktreeSort, prSort, aiReview, azureRequestImpl, aiReviewModelImpl, avatarFetchImpl, onLog, }) {
254
255
  // Initialize server
255
256
  const app = fastify({
256
257
  logger: false,
@@ -501,14 +502,18 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
501
502
  // azureDevOpsUrl, which wins over the file.
502
503
  let settingsPath = '';
503
504
  let reviewStorePath = '';
505
+ // Per worktree: each one has its own uncommitted changes.
506
+ let workingReviewStorePath = '';
504
507
  try {
505
508
  const gitDir = (await git.revparse(['--absolute-git-dir'])).trim();
506
509
  settingsPath = join(gitDir, 'guito-settings.json');
507
510
  reviewStorePath = join(gitDir, 'guito-ai-reviews.json');
511
+ workingReviewStorePath = join(gitDir, 'guito-working-review.json');
508
512
  }
509
513
  catch {
510
514
  settingsPath = join(repositoryPath, '.git', 'guito-settings.json');
511
515
  reviewStorePath = join(repositoryPath, '.git', 'guito-ai-reviews.json');
516
+ workingReviewStorePath = join(repositoryPath, '.git', 'guito-working-review.json');
512
517
  }
513
518
  const readSettings = async () => {
514
519
  try {
@@ -674,9 +679,9 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
674
679
  const [file, azure] = await Promise.all([readSettings(), effectiveAzureUrl()]);
675
680
  const fileAutoReload = typeof file.autoReload === 'boolean' ? file.autoReload : undefined;
676
681
  const fileShowGraph = typeof file.showGraph === 'boolean' ? file.showGraph : undefined;
677
- const fileShowStashes = typeof file.showStashes === 'boolean' ? file.showStashes : undefined;
678
682
  const fileShowTags = typeof file.showTags === 'boolean' ? file.showTags : undefined;
679
683
  const fileShowRemoteBranches = typeof file.showRemoteBranches === 'boolean' ? file.showRemoteBranches : undefined;
684
+ const fileGrayRefBadges = typeof file.grayRefBadges === 'boolean' ? file.grayRefBadges : undefined;
680
685
  const fileFileListView = file.fileListView === 'tree' || file.fileListView === 'flat' ? file.fileListView : undefined;
681
686
  const fileRefListView = file.refListView === 'tree' || file.refListView === 'flat' ? file.refListView : undefined;
682
687
  const fileSidePanelSectionsExpanded = typeof file.sidePanelSectionsExpanded === 'boolean'
@@ -685,6 +690,17 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
685
690
  const fileSearchMode = file.searchMode === 'filter' || file.searchMode === 'navigate' ? file.searchMode : undefined;
686
691
  const fileAllowMerge = typeof file.allowMerge === 'boolean' ? file.allowMerge : undefined;
687
692
  const fileSearchCaseSensitive = typeof file.searchCaseSensitive === 'boolean' ? file.searchCaseSensitive : undefined;
693
+ const fileWorktreeSort = file.worktreeSort === 'default' ||
694
+ file.worktreeSort === 'name-asc' ||
695
+ file.worktreeSort === 'name-desc'
696
+ ? file.worktreeSort
697
+ : undefined;
698
+ const filePrSort = file.prSort === 'newest' ||
699
+ file.prSort === 'oldest' ||
700
+ file.prSort === 'title-asc' ||
701
+ file.prSort === 'title-desc'
702
+ ? file.prSort
703
+ : undefined;
688
704
  const filePrBranchNameTemplate = typeof file.prBranchNameTemplate === 'string' && file.prBranchNameTemplate.trim()
689
705
  ? file.prBranchNameTemplate.trim()
690
706
  : undefined;
@@ -724,11 +740,11 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
724
740
  autoReload: typeof autoReload === 'boolean' ? autoReload : (fileAutoReload ?? true),
725
741
  diffViewer: diffViewer === 'vscode' ? 'vscode' : 'guito',
726
742
  showGraph: typeof showGraph === 'boolean' ? showGraph : (fileShowGraph ?? true),
727
- showStashes: typeof showStashes === 'boolean' ? showStashes : (fileShowStashes ?? false),
728
743
  showTags: typeof showTags === 'boolean' ? showTags : (fileShowTags ?? true),
729
744
  showRemoteBranches: typeof showRemoteBranches === 'boolean'
730
745
  ? showRemoteBranches
731
746
  : (fileShowRemoteBranches ?? true),
747
+ grayRefBadges: typeof grayRefBadges === 'boolean' ? grayRefBadges : (fileGrayRefBadges ?? false),
732
748
  fileListView: fileListView ?? fileFileListView ?? 'flat',
733
749
  refListView: refListView ?? fileRefListView ?? 'flat',
734
750
  sidePanelSectionsExpanded: typeof sidePanelSectionsExpanded === 'boolean'
@@ -738,6 +754,8 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
738
754
  searchCaseSensitive: typeof searchCaseSensitive === 'boolean'
739
755
  ? searchCaseSensitive
740
756
  : (fileSearchCaseSensitive ?? false),
757
+ worktreeSort: worktreeSort ?? fileWorktreeSort ?? 'default',
758
+ prSort: prSort ?? filePrSort ?? 'newest',
741
759
  allowMerge: typeof allowMerge === 'boolean' ? allowMerge : (fileAllowMerge ?? true),
742
760
  aiReview: resolveAiReviewConfig(file.aiReview, aiReview),
743
761
  issueLinking,
@@ -791,6 +809,8 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
791
809
  author_email: '%aE',
792
810
  parents: '%P',
793
811
  },
812
+ // Stashes are listed only in the side panel, never in the history graph.
813
+ '--exclude=refs/stash': null,
794
814
  '--all': null,
795
815
  };
796
816
  if (Number.isFinite(limit) && limit > 0) {
@@ -801,7 +821,7 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
801
821
  }
802
822
  const [log, count, identity] = await Promise.all([
803
823
  git.log(options),
804
- git.raw(['rev-list', '--count', '--all']),
824
+ git.raw(['rev-list', '--count', '--exclude=refs/stash', '--all']),
805
825
  configuredIdentity(),
806
826
  ]);
807
827
  const commits = log.all.map((commit) => ({
@@ -837,7 +857,7 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
837
857
  // NUL separators are safe because Git commit messages cannot contain
838
858
  // NUL bytes. Searching in JS lets insensitive mode fold accents too,
839
859
  // which Git's --regexp-ignore-case does not do consistently.
840
- const raw = await git.raw(['log', '--all', '--format=%H%x00%B%x00']);
860
+ const raw = await git.raw(['log', '--exclude=refs/stash', '--all', '--format=%H%x00%B%x00']);
841
861
  const fields = raw.split('\0');
842
862
  const normalizedQuery = normalizeSearchText(query, caseSensitive);
843
863
  const hashes = [];
@@ -1838,15 +1858,15 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
1838
1858
  if (typeof body.autoReload === 'boolean') {
1839
1859
  settings.autoReload = body.autoReload;
1840
1860
  }
1841
- if (typeof body.showStashes === 'boolean') {
1842
- settings.showStashes = body.showStashes;
1843
- }
1844
1861
  if (typeof body.showTags === 'boolean') {
1845
1862
  settings.showTags = body.showTags;
1846
1863
  }
1847
1864
  if (typeof body.showRemoteBranches === 'boolean') {
1848
1865
  settings.showRemoteBranches = body.showRemoteBranches;
1849
1866
  }
1867
+ if (typeof body.grayRefBadges === 'boolean') {
1868
+ settings.grayRefBadges = body.grayRefBadges;
1869
+ }
1850
1870
  if (body.fileListView === 'tree' || body.fileListView === 'flat') {
1851
1871
  settings.fileListView = body.fileListView;
1852
1872
  }
@@ -1862,6 +1882,17 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
1862
1882
  if (typeof body.searchCaseSensitive === 'boolean') {
1863
1883
  settings.searchCaseSensitive = body.searchCaseSensitive;
1864
1884
  }
1885
+ if (body.worktreeSort === 'default' ||
1886
+ body.worktreeSort === 'name-asc' ||
1887
+ body.worktreeSort === 'name-desc') {
1888
+ settings.worktreeSort = body.worktreeSort;
1889
+ }
1890
+ if (body.prSort === 'newest' ||
1891
+ body.prSort === 'oldest' ||
1892
+ body.prSort === 'title-asc' ||
1893
+ body.prSort === 'title-desc') {
1894
+ settings.prSort = body.prSort;
1895
+ }
1865
1896
  if (typeof body.allowMerge === 'boolean') {
1866
1897
  settings.allowMerge = body.allowMerge;
1867
1898
  }
@@ -3441,6 +3472,79 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
3441
3472
  return resp.status(400).type('application/json').send({ error: err.message });
3442
3473
  }
3443
3474
  });
3475
+ // ==================== Code review of uncommitted changes ====================
3476
+ // One Claude Code run over everything not yet committed; the findings open
3477
+ // in their own tab, where each one can be handed back to Claude Code to fix.
3478
+ // Runs are started here and followed by polling GET /api/working-review.
3479
+ const workingReviewer = createWorkingReviewer({
3480
+ storePath: workingReviewStorePath,
3481
+ cwd: repositoryPath,
3482
+ loadChanges: async () => {
3483
+ await mutationQueue;
3484
+ const snapshot = await working.snapshot();
3485
+ let branch = '';
3486
+ try {
3487
+ branch = await currentBranch();
3488
+ }
3489
+ catch {
3490
+ branch = '';
3491
+ }
3492
+ return {
3493
+ branch,
3494
+ diffs: snapshot.files.map((file) => ({
3495
+ path: file.path,
3496
+ oldPath: file.oldPath ?? '',
3497
+ status: file.status,
3498
+ binary: file.status === 'binary',
3499
+ lines: file.lines ?? [],
3500
+ })),
3501
+ };
3502
+ },
3503
+ config: refreshAiReviewConfig,
3504
+ runModel: aiReviewModelImpl,
3505
+ log: (line) => onLog?.(line),
3506
+ });
3507
+ const workingReviewError = (resp, err) => resp
3508
+ .status(err instanceof WorkingReviewBusyError ? 409 : 400)
3509
+ .type('application/json')
3510
+ .send({ error: err.message });
3511
+ app.get('/api/working-review', async (_req, resp) => {
3512
+ try {
3513
+ return resp.type('application/json').send({ state: await workingReviewer.state() });
3514
+ }
3515
+ catch (err) {
3516
+ return workingReviewError(resp, err);
3517
+ }
3518
+ });
3519
+ app.post('/api/working-review', async (req, resp) => {
3520
+ try {
3521
+ const state = await workingReviewer.start({
3522
+ model: strField(req.body?.model),
3523
+ effort: typeof req.body?.effort === 'string' ? req.body.effort : undefined,
3524
+ });
3525
+ return resp.type('application/json').send({ state });
3526
+ }
3527
+ catch (err) {
3528
+ return workingReviewError(resp, err);
3529
+ }
3530
+ });
3531
+ app.post('/api/working-review/cancel', async (_req, resp) => {
3532
+ workingReviewer.cancel();
3533
+ return resp.type('application/json').send({ ok: true });
3534
+ });
3535
+ app.post('/api/working-review/findings/:id/fix', async (req, resp) => {
3536
+ try {
3537
+ const state = await workingReviewer.startFix(String(req.params?.id ?? ''));
3538
+ return resp.type('application/json').send({ state });
3539
+ }
3540
+ catch (err) {
3541
+ return workingReviewError(resp, err);
3542
+ }
3543
+ });
3544
+ app.post('/api/working-review/fix/cancel', async (_req, resp) => {
3545
+ workingReviewer.cancelFix();
3546
+ return resp.type('application/json').send({ ok: true });
3547
+ });
3444
3548
  // ==================== Commit Detail ====================
3445
3549
  app.post('/api/commit/detail', async (req, resp) => {
3446
3550
  try {
@@ -3633,8 +3737,11 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
3633
3737
  address,
3634
3738
  aiReview: aiReviewer,
3635
3739
  generateCommitMessage: draftCommitMessage,
3740
+ workingReview: workingReviewer,
3636
3741
  close: async () => {
3637
3742
  aiReviewer.stop();
3743
+ workingReviewer.cancel();
3744
+ workingReviewer.cancelFix();
3638
3745
  await app.close();
3639
3746
  },
3640
3747
  updateSettings: (settings) => {
@@ -3643,13 +3750,15 @@ export async function startGuitoServer({ repositoryPath, uiRoot, host, port = 80
3643
3750
  autoReload = settings.autoReload;
3644
3751
  diffViewer = settings.diffViewer;
3645
3752
  showGraph = settings.showGraph;
3646
- showStashes = settings.showStashes;
3647
3753
  fileListView = settings.fileListView;
3648
3754
  sidePanelSectionsExpanded = settings.sidePanelSectionsExpanded;
3649
3755
  searchMode = settings.searchMode;
3650
3756
  searchCaseSensitive = settings.searchCaseSensitive;
3757
+ worktreeSort = settings.worktreeSort;
3758
+ prSort = settings.prSort;
3651
3759
  showTags = settings.showTags;
3652
3760
  showRemoteBranches = settings.showRemoteBranches;
3761
+ grayRefBadges = settings.grayRefBadges;
3653
3762
  issueRegex = settings.issueRegex;
3654
3763
  issueUrl = settings.issueUrl;
3655
3764
  allowMerge = settings.allowMerge;
@@ -9,5 +9,5 @@
9
9
  <style>:root{--bg:#1e1e1e;--bg-alt:#232323;--bg-hover:#2a2d2e;--border:#3c3c3c;--text:#cccccc;--text-bright:#e8e8e8;--text-dim:#9d9d9d;--accent:#3794ff;--red:#f14c4c;--mono:ui-monospace, "Cascadia Code", "SF Mono", Menlo, Consolas, monospace}*{box-sizing:border-box}html,body{height:100%;margin:0}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:13px;color:var(--text);background:var(--bg);overflow:hidden}</style><link rel="stylesheet" href="styles-I7K2YZTW.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles-I7K2YZTW.css"></noscript></head>
10
10
  <body>
11
11
  <app-root></app-root>
12
- <script src="polyfills-5CFQRCPP.js" type="module"></script><script src="main-VNIXKHUJ.js" type="module"></script></body>
12
+ <script src="polyfills-5CFQRCPP.js" type="module"></script><script src="main-3MOB345X.js" type="module"></script></body>
13
13
  </html>