github-issue-tower-defence-management 1.188.0 → 1.189.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.
Files changed (70) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +3 -0
  3. package/bin/adapter/entry-points/cli/index.js +20 -12
  4. package/bin/adapter/entry-points/cli/index.js.map +1 -1
  5. package/bin/adapter/entry-points/cli/projectConfig.js.map +1 -1
  6. package/bin/adapter/entry-points/console/ui-dist/assets/index-CLHvrafO.css +2 -0
  7. package/bin/adapter/entry-points/console/ui-dist/assets/index-CZ1NNzIm.js +86 -0
  8. package/bin/adapter/entry-points/console/ui-dist/index.html +2 -2
  9. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +1 -0
  10. package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
  11. package/bin/domain/usecases/HandleScheduledEventUseCase.js +1 -0
  12. package/bin/domain/usecases/HandleScheduledEventUseCase.js.map +1 -1
  13. package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js +3 -4
  14. package/bin/domain/usecases/NotifyFinishedIssuePreparationUseCase.js.map +1 -1
  15. package/bin/domain/usecases/RevertOrphanedPreparationUseCase.js +3 -3
  16. package/bin/domain/usecases/RevertOrphanedPreparationUseCase.js.map +1 -1
  17. package/bin/domain/usecases/TriagerApprovalDispatchUseCase.js +13 -1
  18. package/bin/domain/usecases/TriagerApprovalDispatchUseCase.js.map +1 -1
  19. package/bin/domain/usecases/isHumanComment.js +21 -0
  20. package/bin/domain/usecases/isHumanComment.js.map +1 -0
  21. package/bin/domain/usecases/nextStepAgentDispatchRepeatedMessage.js +5 -0
  22. package/bin/domain/usecases/nextStepAgentDispatchRepeatedMessage.js.map +1 -0
  23. package/bin/domain/usecases/resolveNextStepAgentDispatchRepetition.js +62 -12
  24. package/bin/domain/usecases/resolveNextStepAgentDispatchRepetition.js.map +1 -1
  25. package/package.json +1 -1
  26. package/src/adapter/entry-points/cli/index.test.ts +2 -0
  27. package/src/adapter/entry-points/cli/index.ts +39 -16
  28. package/src/adapter/entry-points/cli/projectConfig.ts +1 -0
  29. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleCopyStoryNameButton.stories.tsx +23 -0
  30. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleCopyStoryNameButton.test.tsx +40 -0
  31. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleCopyStoryNameButton.tsx +17 -0
  32. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleStoryList.test.tsx +26 -1
  33. package/src/adapter/entry-points/console/ui/src/features/console/components/list/ConsoleStoryList.tsx +2 -0
  34. package/src/adapter/entry-points/console/ui/src/index.css +14 -0
  35. package/src/adapter/entry-points/console/ui-dist/assets/index-CLHvrafO.css +2 -0
  36. package/src/adapter/entry-points/console/ui-dist/assets/index-CZ1NNzIm.js +86 -0
  37. package/src/adapter/entry-points/console/ui-dist/index.html +2 -2
  38. package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +2 -0
  39. package/src/domain/usecases/HandleScheduledEventUseCase.ts +2 -0
  40. package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.test.ts +98 -0
  41. package/src/domain/usecases/NotifyFinishedIssuePreparationUseCase.ts +9 -5
  42. package/src/domain/usecases/RevertOrphanedPreparationUseCase.ts +9 -4
  43. package/src/domain/usecases/TriagerApprovalDispatchUseCase.test.ts +88 -0
  44. package/src/domain/usecases/TriagerApprovalDispatchUseCase.ts +17 -2
  45. package/src/domain/usecases/isHumanComment.test.ts +90 -0
  46. package/src/domain/usecases/isHumanComment.ts +23 -0
  47. package/src/domain/usecases/nextStepAgentDispatchRepeatedMessage.ts +2 -0
  48. package/src/domain/usecases/resolveNextStepAgentDispatchRepetition.test.ts +312 -72
  49. package/src/domain/usecases/resolveNextStepAgentDispatchRepetition.ts +103 -19
  50. package/types/adapter/entry-points/cli/index.d.ts.map +1 -1
  51. package/types/adapter/entry-points/cli/projectConfig.d.ts +1 -0
  52. package/types/adapter/entry-points/cli/projectConfig.d.ts.map +1 -1
  53. package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
  54. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts +1 -0
  55. package/types/domain/usecases/HandleScheduledEventUseCase.d.ts.map +1 -1
  56. package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts +1 -0
  57. package/types/domain/usecases/NotifyFinishedIssuePreparationUseCase.d.ts.map +1 -1
  58. package/types/domain/usecases/RevertOrphanedPreparationUseCase.d.ts +1 -0
  59. package/types/domain/usecases/RevertOrphanedPreparationUseCase.d.ts.map +1 -1
  60. package/types/domain/usecases/TriagerApprovalDispatchUseCase.d.ts.map +1 -1
  61. package/types/domain/usecases/isHumanComment.d.ts +5 -0
  62. package/types/domain/usecases/isHumanComment.d.ts.map +1 -0
  63. package/types/domain/usecases/nextStepAgentDispatchRepeatedMessage.d.ts +2 -0
  64. package/types/domain/usecases/nextStepAgentDispatchRepeatedMessage.d.ts.map +1 -0
  65. package/types/domain/usecases/resolveNextStepAgentDispatchRepetition.d.ts +5 -2
  66. package/types/domain/usecases/resolveNextStepAgentDispatchRepetition.d.ts.map +1 -1
  67. package/bin/adapter/entry-points/console/ui-dist/assets/index-CA6c7Pfz.js +0 -86
  68. package/bin/adapter/entry-points/console/ui-dist/assets/index-D1xvwesF.css +0 -2
  69. package/src/adapter/entry-points/console/ui-dist/assets/index-CA6c7Pfz.js +0 -86
  70. package/src/adapter/entry-points/console/ui-dist/assets/index-D1xvwesF.css +0 -2
@@ -1510,6 +1510,7 @@ mysteryKey: 'value'
1510
1510
  projectUrl: 'https://github.com/orgs/test/projects/1',
1511
1511
  issueUrl: 'https://github.com/test/repo/issues/1',
1512
1512
  thresholdForAutoReject: 3,
1513
+ thresholdForDispatchLoop: 6,
1513
1514
  workflowBlockerResolvedWebhookUrl: null,
1514
1515
  allowedIssueAuthors: null,
1515
1516
  labelsAsLlmAgentName: null,
@@ -1553,6 +1554,7 @@ mysteryKey: 'value'
1553
1554
  projectUrl: 'https://github.com/orgs/override/projects/2',
1554
1555
  issueUrl: 'https://github.com/test/repo/issues/1',
1555
1556
  thresholdForAutoReject: 3,
1557
+ thresholdForDispatchLoop: 6,
1556
1558
  workflowBlockerResolvedWebhookUrl: null,
1557
1559
  allowedIssueAuthors: null,
1558
1560
  labelsAsLlmAgentName: null,
@@ -33,6 +33,7 @@ import { projectCacheDirectory } from '../../repositories/localStorageCacheDirec
33
33
  import { NodeLocalCommandRunner } from '../../repositories/NodeLocalCommandRunner';
34
34
  import { NodeTmuxSessionRepository } from '../../repositories/NodeTmuxSessionRepository';
35
35
  import { ProcTakeOwnershipSpawnRepository } from '../../repositories/ProcTakeOwnershipSpawnRepository';
36
+ import { DEFAULT_THRESHOLD_FOR_DISPATCH_LOOP } from '../../../domain/usecases/resolveNextStepAgentDispatchRepetition';
36
37
  import { ProxyClaudeTokenUsageRepository } from '../../repositories/ProxyClaudeTokenUsageRepository';
37
38
  import { SystemDateRepository } from '../../repositories/SystemDateRepository';
38
39
  import {
@@ -89,10 +90,29 @@ type StartDaemonOptions = {
89
90
  configFilePath: string;
90
91
  };
91
92
 
93
+ const resolvePositiveIntegerOption = (
94
+ rawValue: number | string | undefined,
95
+ optionName: string,
96
+ fallback: number,
97
+ ): number => {
98
+ if (rawValue === undefined) {
99
+ return fallback;
100
+ }
101
+ const parsed = Number(rawValue);
102
+ if (!Number.isFinite(parsed) || !Number.isInteger(parsed) || parsed <= 0) {
103
+ console.error(
104
+ `Invalid value for --${optionName}. It must be a positive integer.`,
105
+ );
106
+ process.exit(1);
107
+ }
108
+ return parsed;
109
+ };
110
+
92
111
  type NotifyFinishedOptions = {
93
112
  issueUrl: string;
94
113
  projectUrl?: string;
95
114
  thresholdForAutoReject?: string;
115
+ thresholdForDispatchLoop?: string;
96
116
  workflowBlockerResolvedWebhookUrl?: string;
97
117
  configFilePath: string;
98
118
  missingAgentName?: string;
@@ -414,6 +434,7 @@ program
414
434
  projectUrl,
415
435
  preparationProcessCheckCommand,
416
436
  thresholdForAutoReject: config.thresholdForAutoReject ?? 3,
437
+ thresholdForDispatchLoop: config.thresholdForDispatchLoop,
417
438
  awLogDirectoryPath: config.awLogDirectoryPath,
418
439
  awLogStaleThresholdMinutes: config.awLogStaleThresholdMinutes,
419
440
  labelsAsLlmAgentName: config.labelsAsLlmAgentName ?? null,
@@ -498,6 +519,10 @@ program
498
519
  '--thresholdForAutoReject <count>',
499
520
  'Threshold for auto-escalation after consecutive rejections (default: 3)',
500
521
  )
522
+ .option(
523
+ '--thresholdForDispatchLoop <count>',
524
+ 'Threshold for auto-escalation after one agent is dispatched this many times since the last human comment, whether it names itself or two agents name each other in turn (default: 6)',
525
+ )
501
526
  .option(
502
527
  '--workflowBlockerResolvedWebhookUrl <url>',
503
528
  'Webhook URL to notify when a workflow blocker issue status changes to awaiting quality check. Supports {URL} and {MESSAGE} placeholders.',
@@ -528,6 +553,9 @@ program
528
553
  thresholdForAutoReject: options.thresholdForAutoReject
529
554
  ? Number(options.thresholdForAutoReject)
530
555
  : undefined,
556
+ thresholdForDispatchLoop: options.thresholdForDispatchLoop
557
+ ? Number(options.thresholdForDispatchLoop)
558
+ : undefined,
531
559
  workflowBlockerResolvedWebhookUrl:
532
560
  options.workflowBlockerResolvedWebhookUrl,
533
561
  };
@@ -558,22 +586,16 @@ program
558
586
  process.exit(1);
559
587
  }
560
588
 
561
- let thresholdForAutoReject = 3;
562
- const rawThreshold = config.thresholdForAutoReject;
563
- if (rawThreshold !== undefined) {
564
- const parsed = Number(rawThreshold);
565
- if (
566
- !Number.isFinite(parsed) ||
567
- !Number.isInteger(parsed) ||
568
- parsed <= 0
569
- ) {
570
- console.error(
571
- 'Invalid value for --thresholdForAutoReject. It must be a positive integer.',
572
- );
573
- process.exit(1);
574
- }
575
- thresholdForAutoReject = parsed;
576
- }
589
+ const thresholdForAutoReject = resolvePositiveIntegerOption(
590
+ config.thresholdForAutoReject,
591
+ 'thresholdForAutoReject',
592
+ 3,
593
+ );
594
+ const thresholdForDispatchLoop = resolvePositiveIntegerOption(
595
+ config.thresholdForDispatchLoop,
596
+ 'thresholdForDispatchLoop',
597
+ DEFAULT_THRESHOLD_FOR_DISPATCH_LOOP,
598
+ );
577
599
 
578
600
  const workflowBlockerResolvedWebhookUrl: string | null =
579
601
  config.workflowBlockerResolvedWebhookUrl ?? null;
@@ -640,6 +662,7 @@ program
640
662
  projectUrl,
641
663
  issueUrl: options.issueUrl,
642
664
  thresholdForAutoReject,
665
+ thresholdForDispatchLoop,
643
666
  workflowBlockerResolvedWebhookUrl,
644
667
  allowedIssueAuthors,
645
668
  labelsAsLlmAgentName: config.labelsAsLlmAgentName ?? null,
@@ -15,6 +15,7 @@ export type ConfigFile = {
15
15
  allowedIssueAuthors?: string;
16
16
  autoAssignManagerAuthors?: string;
17
17
  thresholdForAutoReject?: number;
18
+ thresholdForDispatchLoop?: number;
18
19
  workflowBlockerResolvedWebhookUrl?: string;
19
20
  projectName?: string;
20
21
  preparationProcessCheckCommand?: string;
@@ -0,0 +1,23 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { ConsoleCopyStoryNameButton } from './ConsoleCopyStoryNameButton';
3
+
4
+ const meta: Meta<typeof ConsoleCopyStoryNameButton> = {
5
+ title: 'Console/ConsoleCopyStoryNameButton',
6
+ component: ConsoleCopyStoryNameButton,
7
+ };
8
+
9
+ export default meta;
10
+
11
+ type Story = StoryObj<typeof ConsoleCopyStoryNameButton>;
12
+
13
+ export const SimpleStoryName: Story = {
14
+ args: {
15
+ storyName: 'TDPM Console port',
16
+ },
17
+ };
18
+
19
+ export const RegularPrefixedStoryName: Story = {
20
+ args: {
21
+ storyName: 'regular / regular payment invoice tax',
22
+ },
23
+ };
@@ -0,0 +1,40 @@
1
+ import { act, fireEvent, render, waitFor } from '@testing-library/react';
2
+ import { ConsoleCopyStoryNameButton } from './ConsoleCopyStoryNameButton';
3
+
4
+ const storyName = 'TDPM Console port';
5
+
6
+ describe('ConsoleCopyStoryNameButton', () => {
7
+ const writeText = jest.fn(async () => {});
8
+
9
+ beforeEach(() => {
10
+ writeText.mockClear();
11
+ Object.defineProperty(navigator, 'clipboard', {
12
+ configurable: true,
13
+ value: { writeText },
14
+ });
15
+ });
16
+
17
+ it('renders with text "Copy name"', () => {
18
+ const { getByRole } = render(
19
+ <ConsoleCopyStoryNameButton storyName={storyName} />,
20
+ );
21
+ expect(getByRole('button', { name: 'Copy story name' })).toHaveTextContent(
22
+ 'Copy name',
23
+ );
24
+ });
25
+
26
+ it('writes the story name to clipboard and changes the accessible label after click', async () => {
27
+ const { getByRole } = render(
28
+ <ConsoleCopyStoryNameButton storyName={storyName} />,
29
+ );
30
+ await act(async () => {
31
+ fireEvent.click(getByRole('button', { name: 'Copy story name' }));
32
+ });
33
+ expect(writeText).toHaveBeenCalledWith(storyName);
34
+ await waitFor(() => {
35
+ expect(
36
+ getByRole('button', { name: 'Story name copied to clipboard' }),
37
+ ).toBeInTheDocument();
38
+ });
39
+ });
40
+ });
@@ -0,0 +1,17 @@
1
+ import { ConsoleClipboardCopyButton } from '../shared/ConsoleClipboardCopyButton';
2
+
3
+ export type ConsoleCopyStoryNameButtonProps = {
4
+ storyName: string;
5
+ };
6
+
7
+ export const ConsoleCopyStoryNameButton = ({
8
+ storyName,
9
+ }: ConsoleCopyStoryNameButtonProps) => (
10
+ <ConsoleClipboardCopyButton
11
+ value={storyName}
12
+ idleText="Copy name"
13
+ idleAriaLabel="Copy story name"
14
+ copiedAriaLabel="Story name copied to clipboard"
15
+ className="console-copy-story-name-button"
16
+ />
17
+ );
@@ -1,4 +1,4 @@
1
- import { fireEvent, render, waitFor } from '@testing-library/react';
1
+ import { act, fireEvent, render, waitFor } from '@testing-library/react';
2
2
  import type { ConsoleColor, ConsoleStoryEntry } from '../../logic/types';
3
3
  import { ConsoleStoryList } from './ConsoleStoryList';
4
4
 
@@ -32,6 +32,16 @@ const defaultProps = {
32
32
  };
33
33
 
34
34
  describe('ConsoleStoryList', () => {
35
+ const writeText = jest.fn(async () => {});
36
+
37
+ beforeEach(() => {
38
+ writeText.mockClear();
39
+ Object.defineProperty(navigator, 'clipboard', {
40
+ configurable: true,
41
+ value: { writeText },
42
+ });
43
+ });
44
+
35
45
  it('renders each story name and its open item count', () => {
36
46
  const { getByText } = render(<ConsoleStoryList {...defaultProps} />);
37
47
  expect(getByText('TDPM Console port')).toBeInTheDocument();
@@ -345,4 +355,19 @@ describe('ConsoleStoryList', () => {
345
355
  );
346
356
  expect(getByText('Color update failed')).toBeInTheDocument();
347
357
  });
358
+
359
+ it('renders a "Copy name" button for each story row', () => {
360
+ const { getAllByRole } = render(<ConsoleStoryList {...defaultProps} />);
361
+ const buttons = getAllByRole('button', { name: 'Copy story name' });
362
+ expect(buttons).toHaveLength(storyEntries.length);
363
+ });
364
+
365
+ it('writes the first row story name to clipboard when its "Copy name" button is clicked', async () => {
366
+ const { getAllByRole } = render(<ConsoleStoryList {...defaultProps} />);
367
+ const [firstButton] = getAllByRole('button', { name: 'Copy story name' });
368
+ await act(async () => {
369
+ fireEvent.click(firstButton);
370
+ });
371
+ expect(writeText).toHaveBeenCalledWith(storyEntries[0].storyName);
372
+ });
348
373
  });
@@ -1,6 +1,7 @@
1
1
  import { useEffect, useRef, useState } from 'react';
2
2
  import { CONSOLE_COLOR_PALETTE, colorFromEnum } from '../../logic/colors';
3
3
  import type { ConsoleColor, ConsoleStoryEntry } from '../../logic/types';
4
+ import { ConsoleCopyStoryNameButton } from './ConsoleCopyStoryNameButton';
4
5
 
5
6
  const ALL_COLORS = Object.keys(CONSOLE_COLOR_PALETTE) as ConsoleColor[];
6
7
 
@@ -239,6 +240,7 @@ export const ConsoleStoryList = ({
239
240
  {entry.storyName}
240
241
  </span>
241
242
  )}
243
+ <ConsoleCopyStoryNameButton storyName={entry.storyName} />
242
244
  <span className="console-story-count">
243
245
  {entry.openItemCount}
244
246
  </span>
@@ -342,6 +342,20 @@ body {
342
342
  display: inline-block;
343
343
  }
344
344
 
345
+ .console-copy-story-name-button {
346
+ height: 24px;
347
+ padding: 0 8px;
348
+ border: 1px solid #30363d;
349
+ border-radius: 6px;
350
+ color: #c9d1d9;
351
+ font-size: 0.75rem;
352
+ }
353
+
354
+ .console-copy-story-name-button:hover {
355
+ background-color: #21262d;
356
+ color: #e6edf3;
357
+ }
358
+
345
359
  .console-group-count {
346
360
  color: #8b949e;
347
361
  font-size: 0.75rem;
@@ -0,0 +1,2 @@
1
+ /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-outline-style:solid;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, 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;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--font-weight-semibold:600;--radius-md:.375rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-input:#e5e5e5;--color-ring:#0a0a0a;--color-background:#fff;--color-foreground:#0a0a0a;--color-primary:#171717;--color-primary-foreground:#fafafa;--color-secondary:#f5f5f5;--color-secondary-foreground:#171717;--color-accent:#f5f5f5;--color-accent-foreground:#171717}}@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%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, 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;-webkit-text-decoration:inherit;-webkit-text-decoration: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:where(:not(iframe)){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]){appearance:button}::file-selector-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{.visible{visibility:visible}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.block{display:block}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.grow{flex-grow:1}.items-center{align-items:center}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing) * 2)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-input{border-color:var(--color-input)}.border-transparent{border-color:#0000}.bg-background{background-color:var(--color-background)}.bg-primary{background-color:var(--color-primary)}.bg-secondary{background-color:var(--color-secondary)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-2{padding-block:calc(var(--spacing) * 2)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.whitespace-nowrap{white-space:nowrap}.text-foreground{color:var(--color-foreground)}.text-primary-foreground{color:var(--color-primary-foreground)}.text-secondary-foreground{color:var(--color-secondary-foreground)}.lowercase{text-transform:lowercase}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media (hover:hover){.hover\:bg-accent:hover{background-color:var(--color-accent)}.hover\:bg-primary\/90:hover{background-color:#171717e6}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--color-primary) 90%, transparent)}}.hover\:bg-secondary\/80:hover{background-color:#f5f5f5cc}@supports (color:color-mix(in lab, red, red)){.hover\:bg-secondary\/80:hover{background-color:color-mix(in oklab, var(--color-secondary) 80%, transparent)}}.hover\:text-accent-foreground:hover{color:var(--color-accent-foreground)}}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-ring:focus-visible{--tw-ring-color:var(--color-ring)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}}html{font-size:clamp(15px,2.1vw,26px)}body{color:#e6edf3;background-color:#0d1117;margin:0;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif}.console-app{flex-direction:column;width:100%;min-height:100dvh;display:flex}.console-tabbar{-webkit-overflow-scrolling:touch;background:#161b22;border-bottom:2px solid #30363d;flex-wrap:nowrap;align-items:stretch;gap:0;min-height:42px;padding:0 8px;display:flex;overflow-x:auto}.console-tab{color:#8b949e;white-space:nowrap;cursor:pointer;background:0 0;border:none;border-bottom:2px solid #0000;align-items:center;gap:6px;margin-bottom:-2px;padding:10px 14px;font-size:.8125rem;font-weight:500;line-height:1.2;text-decoration:none;display:inline-flex}.console-tab:hover{color:#e6edf3}.console-tab[data-active=true]{color:#e6edf3;border-bottom-color:#2f81f7;font-weight:700}.console-tab-badge{text-align:center;color:#e6edf3;background:#484f58;border-radius:20px;min-width:20px;padding:1px 7px;font-size:.6875rem;font-weight:700;line-height:1.5}.console-tab-badge[data-zero=true]{color:#8b949e;background:#30363d}.console-tab-pjname{align-self:center;margin-left:auto;padding:0 8px}.console-tab-pjname-button{color:#8b949e;cursor:pointer;background:0 0;border:none;border-radius:4px;align-items:center;gap:3px;padding:2px 4px;font-size:.7188rem;line-height:1;display:flex}.console-tab-pjname-button:hover{color:#e6edf3;background:#21262d}.console-tab-pjname-arrow{font-size:.625rem}.console-tab-pjname-dropdown{z-index:100;background:#161b22;border:1px solid #30363d;border-radius:6px;min-width:120px;margin:0;padding:4px 0;list-style:none;box-shadow:0 8px 24px #01040980}.console-tab-pjname-option{color:#e6edf3;cursor:pointer;text-align:left;background:0 0;border:none;width:100%;padding:4px 12px;font-size:.7188rem;display:block}.console-tab-pjname-option:hover,.console-tab-pjname-option[data-active=true]{background:#21262d}.console-tab-geninfo{color:#8b949e;align-self:center;padding:0 4px;font-size:.6875rem}.console-tab-settings{align-self:center;padding:0 4px}.console-timer-settings-button{color:#8b949e;cursor:pointer;background:0 0;border:none;border-radius:4px;padding:4px 8px;font-size:1rem;line-height:1}.console-timer-settings-button:hover{color:#e6edf3;background:#21262d}.console-timer-settings-dialog{z-index:100;justify-content:flex-end;align-items:flex-start;padding:48px 16px 0;display:flex;position:fixed;inset:0}.console-timer-settings-backdrop{cursor:default;z-index:-1;background:#01040999;border:none;position:fixed;inset:0}.console-timer-settings-dialog-inner{background:#161b22;border:1px solid #30363d;border-radius:8px;min-width:280px;max-width:400px;max-height:80vh;padding:20px;overflow-y:auto}.console-timer-settings-title{color:#e6edf3;margin:0 0 16px;font-size:.9375rem;font-weight:600}.console-timer-settings-row{justify-content:space-between;align-items:center;margin-bottom:16px;display:flex}.console-timer-settings-label{color:#c9d1d9;font-size:.875rem}.console-timer-settings-loading{color:#8b949e;padding:8px 0;font-size:.875rem}.console-timer-settings-project-list{margin:0;padding:0;list-style:none}.console-timer-settings-project-row{border-bottom:1px solid #21262d;align-items:center;gap:8px;padding:6px 0;display:flex}.console-timer-settings-project-row:last-child{border-bottom:none}.console-timer-settings-pjcode{color:#c9d1d9;flex:1;font-family:ui-monospace,SFMono-Regular,monospace;font-size:.8125rem}.console-timer-settings-minutes-input{color:#e6edf3;text-align:right;background:#0d1117;border:1px solid #30363d;border-radius:4px;width:56px;padding:3px 6px;font-size:.8125rem}.console-timer-settings-minutes-label{color:#8b949e;width:24px;font-size:.75rem}.console-timer-settings-actions{justify-content:flex-end;margin-top:16px;display:flex}.console-timer-settings-save{color:#fff;cursor:pointer;background:#238636;border:1px solid #f0f6fc1a;border-radius:6px;padding:6px 14px;font-size:.8125rem;font-weight:500}.console-timer-settings-save:hover{background:#2ea043}.console-list{margin:0;padding:12px 18px 18px;list-style:none}.console-list-group{list-style:none}.console-item-row .console-item-icon{flex:none;margin-top:3px}.console-group-header{background:#0b0f14;border-bottom:1px solid #21262d;justify-content:space-between;align-items:center;padding:6px 12px;display:flex}.console-storytag{align-items:center;gap:8px;font-size:.8125rem;font-weight:700;display:inline-flex}.console-story-dot{border-radius:999px;width:10px;height:10px;display:inline-block}.console-copy-story-name-button{color:#c9d1d9;border:1px solid #30363d;border-radius:6px;height:24px;padding:0 8px;font-size:.75rem}.console-copy-story-name-button:hover{color:#e6edf3;background-color:#21262d}.console-group-count{color:#8b949e;font-size:.75rem}.console-story-color-palette{flex-wrap:wrap;gap:4px;padding:6px 0;display:flex}.console-story-color-swatch{cursor:pointer;color:#e6edf3;border:2px solid #0000;border-radius:6px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;font-size:.625rem;display:inline-flex}.console-story-color-swatch:hover{border-color:#e6edf3}.console-story-color-swatch:disabled{opacity:.4;cursor:not-allowed}.console-story-color-swatch-label{font-size:.5rem;line-height:1}.console-item-row{color:#e6edf3;text-align:left;cursor:pointer;background:#161b22;border:1px solid #30363d;border-radius:8px;align-items:flex-start;gap:14px;width:100%;margin-bottom:10px;padding:12px 16px;display:flex}.console-item-row:hover{background:#1a2029;border-color:#484f58}.console-item-row[data-active=true]{background:#1a2029;border-color:#4493f8}.console-item-meta{flex:1;min-width:0}.console-item-title{font-size:.9063rem;font-weight:600;display:block}.console-item-sub{color:#8b949e;margin-top:3px;font-size:.7813rem;display:block}.console-item-pill{color:#8b949e;border:1px solid #30363d;border-radius:20px;margin-right:6px;padding:1px 8px;font-size:.6875rem;display:inline-block}.console-item-createdat{color:#8b949e;cursor:help}.console-item-fields{color:#adbac7;flex-wrap:wrap;gap:4px 10px;margin-top:4px;font-size:.7188rem;display:flex}.console-item-field{word-break:break-all;align-items:baseline;gap:4px;min-width:0;display:inline-flex}.console-item-field-label{color:#6e7681;text-transform:uppercase;letter-spacing:.03em;font-size:.625rem}.console-list-message{color:#8b949e;padding:16px;font-size:.875rem}.console-list-empty{text-align:center;color:#8b949e;padding:40px;font-size:.875rem}.console-list-error,.console-detail-fetch-error{color:#f85149}.console-detail-fetch-error-line{margin:0}.console-comment-notloaded,.console-files-notloaded,.console-commits-notloaded,.console-detail-body-notloaded{color:#8b949e}.console-detail{flex-direction:column;flex:1 0 auto;gap:12px;padding:16px 16px 0;display:flex}.console-detail-topline{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.console-detail-title{align-items:center;gap:8px;margin:0;font-size:1.25rem;display:flex}.console-detail-title-text{flex:1}.console-detail-number{color:#8b949e;font-weight:400}.console-detail-closed-label{color:#a371f7;font-size:.8125rem}.console-detail-subbar{align-items:center;gap:12px;font-size:.8125rem;display:flex}.console-detail-link{color:#4493f8}.console-detail-repo{color:#8b949e;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.console-copy-url-button{color:#c9d1d9;border:1px solid #30363d;border-radius:6px;height:24px;padding:0 8px;font-size:.75rem}.console-copy-url-button:hover{color:#e6edf3;background-color:#21262d}.console-detail-pill,.console-label-chip,.console-detail-status-chip{border:1px solid #30363d;border-radius:999px;padding:2px 8px;font-size:.75rem;display:inline-block}.console-detail-agent-chip{color:#8b949e;border:1px solid #30363d;border-radius:999px;padding:2px 8px;font-size:.75rem;font-weight:400;display:inline-block}.console-detail-pr-status{flex-wrap:wrap;align-items:center;gap:6px;display:inline-flex}.console-related-pr-group{align-items:center;gap:6px;display:inline-flex}.console-related-pr-label{color:#8b949e;font-size:.75rem}.console-detail-ci-missing{opacity:.85;font-weight:400}.console-detail-mergeable-chip{font-weight:600}.console-detail-mergeable-chip-unknown{opacity:.7;font-weight:400}.console-detail-labels{flex-wrap:wrap;gap:6px;display:flex}.console-detail-createdat{color:#8b949e;font-size:.75rem}.console-panel{border:1px solid #30363d;border-radius:8px;overflow:hidden}.console-panel-header{background:#161b22;justify-content:space-between;align-items:center;display:flex}.console-panel-toggle{color:#e6edf3;text-align:left;cursor:pointer;background:0 0;border:none;flex:1;align-items:center;gap:8px;padding:6px 12px;font-size:.875rem;font-weight:600;display:flex}.console-panel-toggle:hover{background:#1a2029}.console-panel-action{padding:6px 12px}.console-panel-body{padding:12px}.console-markdown{word-break:break-word;font-size:.875rem;line-height:1.5}.console-markdown ul{margin:.5em 0;padding-left:1.5em;list-style:outside}.console-markdown ol{margin:.5em 0;padding-left:1.5em;list-style:decimal}.console-markdown li{margin:.25em 0}.console-markdown table{border-collapse:collapse;margin:.5em 0}.console-markdown th,.console-markdown td{border:1px solid #30363d;padding:4px 8px}.console-markdown th{background:#161b22}.console-markdown h1,.console-markdown h2,.console-markdown h3,.console-markdown h4,.console-markdown h5,.console-markdown h6{margin:1em 0 .5em;font-weight:700;line-height:1.25}.console-markdown h1{font-size:1.6em}.console-markdown h2{font-size:1.4em}.console-markdown h3{font-size:1.2em}.console-markdown h4{font-size:1.05em}.console-markdown h5{font-size:.95em}.console-markdown h6{color:#8b949e;font-size:.9em}.console-markdown pre{background:#161b22;border:1px solid #30363d;border-radius:6px;margin:.5em 0;padding:12px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.8125rem;line-height:1.45;overflow-x:auto}.console-markdown code{background:#6e768166;border-radius:4px;padding:.15em .4em;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.9em}.console-markdown pre code{font-size:inherit;background:0 0;border-radius:0;padding:0}.console-markdown-code-block{flex-direction:column;margin:.5em 0;display:flex}.console-markdown-code-block pre{margin:0}.console-markdown-code-copy-host{justify-content:flex-end;margin-bottom:4px;display:flex}.console-copy-code-button{color:#c9d1d9;background-color:#161b22;border:1px solid #30363d;border-radius:6px;height:24px;padding:0 8px;font-size:.75rem}.console-copy-code-button:hover{color:#e6edf3;background-color:#21262d}.console-markdown blockquote{color:#8b949e;border-left:3px solid #30363d;margin:.5em 0;padding:0 1em}.console-markdown a{color:#4493f8;text-decoration:none}.console-markdown a:hover{text-decoration:underline}.console-markdown-reference-host{display:inline}.console-markdown-reference{vertical-align:baseline;align-items:center;gap:.25em;display:inline-flex}.console-markdown-reference .console-item-icon{flex-shrink:0}.console-markdown-reference-title{text-decoration:none}.console-markdown-reference:hover .console-markdown-reference-title{text-decoration:underline}.console-markdown hr{border:none;border-top:1px solid #30363d;margin:1em 0}.console-mermaid-error{color:#f85149;font-size:.8125rem}.console-mermaid-enlarge{color:#e6edf3;background:#21262d;border:1px solid #30363d;border-radius:6px;width:100%;margin-top:6px;padding:10px 12px;font-size:.8125rem;display:block}.console-mermaid-modal{z-index:1000;background:#0d1117;flex-direction:column;display:flex;position:fixed;inset:0}.console-mermaid-modal-bar{border-bottom:1px solid #30363d;align-items:center;gap:8px;padding:8px 12px;display:flex}.console-mermaid-modal-button,.console-mermaid-modal-close{color:#e6edf3;background:#21262d;border:1px solid #30363d;border-radius:6px;min-width:44px;min-height:44px;font-size:1.125rem}.console-mermaid-modal-button:disabled{opacity:.4}.console-mermaid-modal-close{margin-left:auto}.console-mermaid-modal-scale{text-align:center;color:#8b949e;min-width:4.5rem;font-size:.875rem}.console-mermaid-modal-viewport{-webkit-overflow-scrolling:touch;flex:1;overflow:auto}.console-mermaid-modal-canvas{min-width:100%}.console-comment{background:#161b22;border:1px solid #30363d;border-radius:8px;margin-bottom:10px;padding:12px 16px}.console-comment-header{color:#8b949e;gap:8px;font-size:.75rem;display:flex}.console-comment-show-all{color:#e6edf3;cursor:pointer;background:#21262d;border:1px solid #30363d;border-radius:6px;margin-bottom:10px;padding:6px 12px;font-size:.75rem;font-weight:600}.console-comment-show-all:hover{background-color:#262c34;border-color:#484f58}.console-comment-author{color:#e6edf3;font-weight:600}.console-files,.console-commits{margin:0;padding:0;list-style:none}.console-commit{align-items:center;gap:8px;padding:4px 0;font-size:.8125rem;display:flex}.console-file{flex-direction:column;font-size:.8125rem;display:flex}.console-file-tree,.console-file-tree-children{margin:0;padding:0;list-style:none}.console-file-tree-dir{flex-direction:column;display:flex}.console-file-tree-dir-name{color:#8b949e;align-items:center;gap:6px;padding:4px 0;font-weight:600;display:flex}.console-file-tree-dir-icon{flex:none}.console-file-badge{text-align:center;border:1px solid;border-radius:4px;width:18px;font-size:.6875rem}.console-file-path,.console-commit-message{flex:1;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.console-file-add,.console-pr-add{color:#3fb950}.console-file-del,.console-pr-del{color:#f85149}.console-commit-sha{color:#8b949e;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.console-detail-dock{z-index:100;background:#161b22;border-top:2px solid #30363d;margin-top:auto;position:sticky;bottom:0}.console-detail-dock-composer{max-height:50vh;padding:8px 16px 0;overflow-y:auto}.console-actionbar{padding:10px 16px;padding-bottom:calc(10px + env(safe-area-inset-bottom));background:#161b22}.console-operation-bar{flex-direction:column;gap:8px;width:100%;display:flex}.console-op-group{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:8px;display:flex}.console-op-group-review{gap:10px}.console-op-group-stories{max-height:33vh;overflow-y:auto}.console-op-button{color:#e6edf3;white-space:nowrap;cursor:pointer;background:#21262d;border:1px solid #30363d;border-radius:6px;padding:9px 16px;font-size:.8125rem;font-weight:600}.console-op-button:hover{border-color:#484f58}.console-op-button:disabled{opacity:.4;cursor:not-allowed}.console-op-requirement{text-align:right;color:#8b949e;width:100%;margin:0;font-size:.75rem}.console-op-button-approve{color:#fff;background:#238636;border-color:#2ea043}.console-op-button-reject{color:#ffd166;background:#7d5000;border-color:#a06800}.console-op-button-wrong{color:#f85149;background:#3a1518;border-color:#f85149}.console-op-button-unneeded{color:#aab0b8;background:#2a2d31;border-color:#6e7681}.console-op-button-snooze{color:#79c0ff;background:#1c2b4a;border-color:#4493f8}.console-pr-section{border:1px solid #30363d;border-radius:8px;flex-direction:column;gap:10px;padding:12px;display:flex}.console-pr-statbar{color:#8b949e;gap:12px;font-size:.75rem;display:flex}.console-pr-repo{color:#8b949e;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.console-detail-screen{flex-direction:column;flex:1 0 auto;display:flex}.console-panel-open-link{color:#4493f8;font-size:.8125rem;font-weight:400}.console-composer{margin-top:4px}.console-composer-toggle{color:#8b949e;cursor:pointer;background:0 0;border:none;margin-left:auto;padding:2px 0;font-size:.7813rem;display:block}.console-composer-toggle:hover{color:#e6edf3}.console-composer-form{margin-top:8px}.console-composer-input{box-sizing:border-box;color:#e6edf3;width:100%;font:inherit;resize:vertical;background:#21262d;border:1px solid #30363d;border-radius:6px;padding:8px;font-size:.875rem}.console-composer-attach{align-items:center;gap:8px;padding:0 10px;display:flex}.console-composer-file-input{display:none}.console-composer-attach-button{color:#c9d1d9;cursor:pointer;background:#21262d;border:1px solid #30363d;border-radius:4px;padding:4px 8px;font-size:.75rem}.console-composer-attach-button:disabled{opacity:.6;cursor:default}.console-composer-row{justify-content:flex-end;align-items:center;gap:8px;margin-top:6px;display:flex}.console-composer-submit{color:#fff;cursor:pointer;background:#238636;border:1px solid #2ea043;border-radius:6px;padding:7px 16px;font-size:.8125rem;font-weight:600}.console-composer-submit:disabled{opacity:.6;cursor:default}.console-composer-status{color:#8b949e;font-size:.75rem}.console-composer-error{color:#f85149}.console-undo-toast{z-index:9998;white-space:nowrap;border-radius:10px;align-items:center;gap:12px;max-width:92vw;padding:12px 18px;font-size:.8438rem;display:flex;position:fixed;top:12px;left:50%;transform:translate(-50%);box-shadow:0 4px 20px #0009}.console-undo-toast-green{color:#3fb950;background:#0d3320;border:1px solid #2ea043}.console-undo-toast-amber{color:#ffd166;background:#3a2800;border:1px solid #a06800}.console-undo-toast-red{color:#f85149;background:#3a1518;border:1px solid #da3633}.console-undo-toast-gray{color:#aab0b8;background:#2a2d31;border:1px solid #6e7681}.console-undo-toast-blue{color:#79c0ff;background:#0d1f40;border:1px solid #4493f8}.console-undo-toast-error{color:#f85149;background:#3a1518;border:1px solid #f85149}.console-undo-toast-message{text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.console-undo-toast-undo{cursor:pointer;color:inherit;background:#ffffff1f;border:none;border-radius:6px;flex:none;padding:4px 12px;font-size:.8125rem;font-weight:700}.console-undo-toast-undo:hover{background:#ffffff38}.console-undo-toast-countdown{opacity:.7;flex:none;font-size:.6875rem}.console-undo-toast-bar{opacity:.5;background:currentColor;border-radius:0 0 10px 10px;height:3px;transition:width .1s linear;position:absolute;bottom:0;left:0}.console-file-row{width:100%;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;padding:4px 0;font-size:.8125rem;display:flex}.console-file-row:hover{background:#1a2029}.console-file-caret{color:#8b949e;flex:none;width:1em}.console-file-diff{border-collapse:collapse;width:100%;margin:4px 0 8px;font:.8125rem/1.6 ui-monospace,SFMono-Regular,Menlo,monospace}.console-file-diff td{white-space:pre-wrap;word-break:break-word;vertical-align:top;padding:0 10px}.console-diff-ln{text-align:right;color:#6e7681;-webkit-user-select:none;user-select:none;white-space:nowrap;border-right:1px solid #30363d;width:1%;padding:0 8px}.console-file-diff td.console-diff-ln{white-space:nowrap;word-break:normal;overflow-wrap:normal}.console-diff-add td{background:#2ea04326}.console-diff-add .console-diff-code{color:#aff5b4}.console-diff-del td{background:#f8514926}.console-diff-del .console-diff-code{color:#ffdcd7}.console-diff-hunk td{color:#79c0ff;background:#161b22}.console-diff-ctx .console-diff-code{color:#c9d1d9}.console-file-diff-empty{color:#8b949e;padding:8px 14px;font-size:.75rem}.console-file-diff-image{padding:8px 14px}.console-file-diff-image-content{object-fit:contain;object-position:left top;border:1px solid #30363d;border-radius:4px;max-width:100%;max-height:420px}.console-diff-comment-cell{text-align:center;-webkit-user-select:none;user-select:none;width:1%;padding:0 2px}.console-diff-comment-button{color:#6e7681;cursor:pointer;opacity:.6;background:0 0;border:1px solid #30363d;border-radius:4px;width:18px;height:18px;padding:0;font-size:.875rem;line-height:16px}.console-diff-row:hover .console-diff-comment-button,.console-diff-comment-button:focus-visible,.console-diff-comment-button[aria-expanded=true]{opacity:1;color:#fff;background:#1f6feb;border-color:#2f81f7}.console-diff-composer-row td{background:#0d1117;padding:6px 10px}.console-diff-composer{background:#161b22;border:1px solid #30363d;border-radius:6px;flex-direction:column;gap:6px;padding:8px;display:flex}.console-diff-composer-anchor{color:#8b949e;font-size:.6875rem}.console-diff-composer-input{resize:vertical;color:#c9d1d9;width:100%;font:inherit;background:#0d1117;border:1px solid #30363d;border-radius:6px;padding:6px 8px}.console-diff-composer-controls{align-items:center;gap:8px;display:flex}.console-diff-composer-submit{color:#fff;cursor:pointer;background:#238636;border:1px solid #238636;border-radius:6px;padding:4px 12px}.console-diff-composer-submit:disabled{opacity:.6;cursor:default}.console-diff-composer-cancel{color:#c9d1d9;cursor:pointer;background:0 0;border:1px solid #30363d;border-radius:6px;padding:4px 12px}.console-diff-composer-status{color:#8b949e;font-size:.75rem}.console-diff-composer-error{color:#ff7b72}.console-diff-composer-posted{color:#3fb950;margin:0;font-size:.75rem}.console-pr-header{flex-wrap:wrap;align-items:center;gap:10px;padding-top:4px;display:flex}.console-pr-section-title{color:#e6edf3;font-size:.9375rem;font-weight:600}.console-pr-section-state{color:#8b949e;border:1px solid #6e7681;border-radius:999px;padding:1px 8px;font-size:.6875rem}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}