toolroll 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/serve.js CHANGED
@@ -120,10 +120,12 @@ import { projectAuthority } from "./project-access.js";
120
120
  * repo, only runs whose task belongs to that repo (or to no repo yet).
121
121
  */
122
122
  import { createConnectionChecker } from "./provider-connection.js";
123
+ import { liftAuthPause, noteSignInProbe, signInNotices } from "./provider-auth.js";
123
124
  import { openRouterModelsCache, openRouterPickerScript } from "./openrouter-models.js";
124
125
  import { checkModels, isNewModel, livePin, modelOptions, modelWords, RUNTIME_TOOLS, runtimeStates, seenModels, setWatch, updateRuntime, watchState } from "./model-catalog.js";
125
126
  import { MODELS_CSS, modelsHtml, modelsScript } from "./models-ui.js";
126
127
  import { ASSISTANTS, modelChoices, detectPreparation, previewProjectInstructions, addProjectInstructions } from "./setup-guide.js";
128
+ import { projectSkillInstalled } from "./skills.js";
127
129
  import { previewSetup, approveSetup } from "./control-setup.js";
128
130
  import { controlSetupHtml, setupPreviewHtml, connectionHtml, connectionWords, hiddenFields } from "./control-ui.js";
129
131
  import { composerSchedule, scheduleEditorHtml, scheduleEditorScript } from "./task-composer.js";
@@ -388,7 +390,16 @@ export function createDecisionServer(options) {
388
390
  const workspaceIncarnation = randomBytes(16).toString('hex');
389
391
  const workspaceValidators = new WorkspaceValidatorCache();
390
392
  const providerHome = options.connectionHome ?? homedir();
391
- const connectionCheck = createConnectionChecker({ home: providerHome, clock, ...(options.connectionProbe === undefined ? {} : { probe: options.connectionProbe }) });
393
+ const checkConnection = createConnectionChecker({ home: providerHome, clock, ...(options.connectionProbe === undefined ? {} : { probe: options.connectionProbe }) });
394
+ // Every sign-in check the console makes also answers a sign-in pause.
395
+ const connectionCheck = async (provider, fresh) => {
396
+ const value = await checkConnection(provider, fresh);
397
+ try {
398
+ noteSignInProbe(store, provider, value.state, clock());
399
+ }
400
+ catch { /* the pause keeps its own state */ }
401
+ return value;
402
+ };
392
403
  const modelCatalog = openRouterModelsCache(options.modelCatalogFetcher);
393
404
  const modelSeams = {
394
405
  home: providerHome,
@@ -3804,7 +3815,7 @@ export function createDecisionServer(options) {
3804
3815
  return null;
3805
3816
  const repos = admissionList() ?? [];
3806
3817
  const setupDone = repos.filter(one => store.liveWorktreeSetup(one) !== null).length;
3807
- const skillDone = repos.filter(one => ["toolroll", "standing-orders"].some(name => existsSync(join(one, ".claude", "skills", name, "SKILL.md")))).length;
3818
+ const skillDone = repos.filter(projectSkillInstalled).length;
3808
3819
  const counted = (done) => repos.length <= 1 ? "" : ` (${done} of ${repos.length} repos)`;
3809
3820
  return [
3810
3821
  {
@@ -4429,6 +4440,7 @@ export function createDecisionServer(options) {
4429
4440
  navigation: [...browserNavigationOf(currentPath, s.chrome.project, needsYou), { label: 'Workspace tools', href: '/menu', active: path.pathname === '/menu' }],
4430
4441
  chats,
4431
4442
  ...(s.refreshSeconds === undefined ? {} : { refreshSeconds: Math.max(5, Math.floor(s.refreshSeconds)) }),
4443
+ ...(s.chrome.signIn === undefined ? {} : { signIn: s.chrome.signIn }),
4432
4444
  };
4433
4445
  if (requestFacts.workspaceRead) {
4434
4446
  const validator = requestFacts.workspaceValidator;
@@ -4544,6 +4556,7 @@ export function createDecisionServer(options) {
4544
4556
  inboxSaturated: badge.saturated,
4545
4557
  settings: true,
4546
4558
  ...(store.isDemo() ? { demo: true } : {}),
4559
+ ...(() => { const signIn = signInNotices(store); return signIn.length === 0 ? {} : { signIn }; })(),
4547
4560
  ...(liveMode === null || liveModeTerms === null
4548
4561
  ? {}
4549
4562
  : {
@@ -5729,6 +5742,18 @@ export function createDecisionServer(options) {
5729
5742
  const denied = authorizeMutation(request, who, body);
5730
5743
  if (denied !== null)
5731
5744
  return refuse(response, who, denied.status, denied.message);
5745
+ // A person says a provider's sign-in works again: its sign-in pause
5746
+ // lifts, its tasks may start, and one short message says so.
5747
+ const resumeProvider = /^\/providers\/([a-z]+)\/resume$/.exec(url.pathname);
5748
+ if (resumeProvider !== null) {
5749
+ const provider = resumeProvider[1];
5750
+ if (!isProviderId(provider))
5751
+ return refuse(response, who, 400, "unknown provider", "/work");
5752
+ if (who.role !== "approver")
5753
+ return refuse(response, who, 403, "Only an operator can resume an agent's work.", "/work");
5754
+ liftAuthPause(store, provider, "person", who.name, clock());
5755
+ return redirect(response, "/work");
5756
+ }
5732
5757
  if (url.pathname === '/code' || url.pathname.startsWith('/code/')) {
5733
5758
  const wantsJson = request.headers.accept?.includes('application/json') === true;
5734
5759
  const fail = (status, message, delivery = 'rejected', sessionId) => wantsJson
@@ -6634,7 +6659,7 @@ export function createDecisionServer(options) {
6634
6659
  if (accentField !== null) {
6635
6660
  const accent = normalHex(accentField);
6636
6661
  if (accent === null)
6637
- return refuse(response, who, 400, "Choose a colour as six hex digits, like #c0267e.", "/settings");
6662
+ return refuse(response, who, 400, "Choose a colour as six hex digits, like #6e56cf.", "/settings");
6638
6663
  response.setHeader("Set-Cookie", accent === DEFAULT_ACCENT
6639
6664
  ? "so-accent=; SameSite=Lax; Path=/; Max-Age=0"
6640
6665
  : `so-accent=${accent.slice(1)}; SameSite=Lax; Path=/; Max-Age=31536000`);
@@ -10641,7 +10666,7 @@ function page(response, status, html, nonce, fetches) {
10641
10666
  * can start a sign-in and have someone else finish it into their project.
10642
10667
  */
10643
10668
  /** A moment's page on the way to or back from another site's sign-in: no stylesheet may load there, so the palette rides inline. */
10644
- const HANDOFF_STYLE = `<style>body{font:15px/1.5 "Geist",system-ui,sans-serif;margin:2rem;background:#efefef;color:#171717}a{color:#171717;text-decoration-color:#c0267e;text-underline-offset:3px}@media(prefers-color-scheme:dark){body{background:#0b0b0b;color:#ededed}a{color:#ededed;text-decoration-color:#ff6fb5}}</style>`;
10669
+ const HANDOFF_STYLE = `<style>body{font:15px/1.5 "Geist",system-ui,sans-serif;margin:2rem;background:#efefef;color:#171717}a{color:#171717;text-decoration-color:#8f8f8f;text-underline-offset:3px}@media(prefers-color-scheme:dark){body{background:#0b0b0b;color:#ededed}a{color:#ededed;text-decoration-color:#ff6fb5}}</style>`;
10645
10670
  const SIGN_IN_COOKIE = "so-sign-in";
10646
10671
  function startedHere(request, state) {
10647
10672
  const held = new RegExp(`(?:^|;\\s*)${SIGN_IN_COOKIE}=([A-Za-z0-9_-]{16,128})`).exec(request.headers.cookie ?? "")?.[1];
@@ -11255,7 +11280,7 @@ const THEME_LIGHT = `
11255
11280
  --so-ink: #171717; --so-muted: #666666; --so-line: #e6e6e6; --so-input-line: #d4d4d4;
11256
11281
  --so-accent: #171717; --so-accent-hover: #383838; --so-accent-text: #171717; --so-on-accent: #ffffff; --so-soft: #f2f2f2;
11257
11282
  --so-nav-ink: #525252; --so-nav-hover: #e4e4e4; --so-nav-current: #ffffff; --so-nav-current-ink: #171717;
11258
- --so-signal: #c0267e; --so-signal-hover: #a81f6d; --so-on-signal: #ffffff; --so-signal-soft: #fbeaf3;
11283
+ --so-signal: #171717; --so-signal-hover: #383838; --so-on-signal: #ffffff; --so-signal-soft: #e8e8e8;
11259
11284
  --so-danger: #c4320a; --so-danger-soft: #feebe7; --so-success: #218358; --so-success-soft: #e6f6eb;
11260
11285
  --so-warning: #ab6400; --so-warning-soft: #fff4d5; --so-info: #0d74ce; --so-info-soft: #e6f4fe;
11261
11286
  --so-neutral-ink: #525252; --so-neutral-soft: #f0f0f0; --so-live: #0d74ce;
@@ -11263,13 +11288,13 @@ const THEME_LIGHT = `
11263
11288
  --so-sheet-shadow: 0 0 0 1px rgb(0 0 0 / .06), 0 1px 2px rgb(0 0 0 / .04), 0 4px 12px -6px rgb(0 0 0 / .06);
11264
11289
  --so-pill-shadow: 0 0 0 1px rgb(0 0 0 / .06), 0 1px 2px rgb(0 0 0 / .06);
11265
11290
  --so-overlay: rgb(0 0 0 / .32); --so-shadow-overlay: 0 0 0 1px rgb(0 0 0 / .08), 0 24px 48px -12px rgb(0 0 0 / .22);
11266
- --so-selection: #f6d3e6; --so-scroll: #cfcfcf; --so-code-bg: #fafafa; --so-user-bubble: #f2f2f2;`;
11291
+ --so-selection: #d4d4d4; --so-scroll: #cfcfcf; --so-code-bg: #fafafa; --so-user-bubble: #f2f2f2;`;
11267
11292
  const THEME_DARK = `
11268
11293
  --so-ground: #0b0b0b; --so-paper: #161616; --so-sidebar: #0b0b0b; --so-raised: #1c1c1c;
11269
11294
  --so-ink: #ededed; --so-muted: #a1a1a1; --so-line: #262626; --so-input-line: #363636;
11270
11295
  --so-accent: #ededed; --so-accent-hover: #ffffff; --so-accent-text: #ededed; --so-on-accent: #0a0a0a; --so-soft: #1f1f1f;
11271
11296
  --so-nav-ink: #a1a1a1; --so-nav-hover: #171717; --so-nav-current: #1f1f1f; --so-nav-current-ink: #ededed;
11272
- --so-signal: #ff6fb5; --so-signal-hover: #ff8cc4; --so-on-signal: #0a0a0a; --so-signal-soft: rgb(255 111 181 / .13);
11297
+ --so-signal: #ededed; --so-signal-hover: #ffffff; --so-on-signal: #0a0a0a; --so-signal-soft: #2e2e2e;
11273
11298
  --so-danger: #ff977d; --so-danger-soft: rgb(255 151 125 / .12); --so-success: #3dd68c; --so-success-soft: rgb(61 214 140 / .12);
11274
11299
  --so-warning: #ffca16; --so-warning-soft: rgb(255 202 22 / .12); --so-info: #70b8ff; --so-info-soft: rgb(112 184 255 / .12);
11275
11300
  --so-neutral-ink: #b4b4b4; --so-neutral-soft: #1f1f1f; --so-live: #70b8ff;
@@ -11277,7 +11302,7 @@ const THEME_DARK = `
11277
11302
  --so-sheet-shadow: 0 0 0 1px #262626, 0 1px 2px rgb(0 0 0 / .4);
11278
11303
  --so-pill-shadow: 0 0 0 1px #2a2a2a, 0 1px 2px rgb(0 0 0 / .5);
11279
11304
  --so-overlay: rgb(0 0 0 / .6); --so-shadow-overlay: 0 0 0 1px #2e2e2e, 0 24px 48px -12px rgb(0 0 0 / .7);
11280
- --so-selection: #4a2138; --so-scroll: #333333; --so-code-bg: #111111; --so-user-bubble: #202020;`;
11305
+ --so-selection: #3a3a3a; --so-scroll: #333333; --so-code-bg: #111111; --so-user-bubble: #202020;`;
11281
11306
  /** The console's original token names, now views onto the palette. */
11282
11307
  const THEME_MAPPING = `
11283
11308
  --background: var(--so-ground); --foreground: var(--so-ink); --card: var(--so-paper);
@@ -11296,7 +11321,7 @@ const STYLE = `
11296
11321
  /* The Console — the design system, v4 "Signal" (2026-09-27). A neutral
11297
11322
  frame with paper sheets inset into it (Arc, Linear), compact Raycast
11298
11323
  density, Geist for words and Geist Mono for machine facts. Ink is every
11299
- act a person can take; chart magenta means "waits on you" and nothing
11324
+ act a person can take; the accent (ink by default) means "waits on you" and nothing
11300
11325
  else; blue means live. Flat surfaces: hairlines and one soft sheet
11301
11326
  shadow, no glass. Zero dependencies, zero page JS beyond the nonce'd
11302
11327
  chrome layer. */
@@ -11334,6 +11359,7 @@ const STYLE = `
11334
11359
  ${THEME_LIGHT}
11335
11360
  ${THEME_MAPPING}
11336
11361
  --radius: 0.625rem;
11362
+ --so-ease-out: cubic-bezier(.23, 1, .32, 1);
11337
11363
  --font-sans: "Geist", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
11338
11364
  --font-mono: "Geist Mono", ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
11339
11365
  }
@@ -11348,6 +11374,11 @@ ${THEME_DARK}
11348
11374
  ${THEME_DARK}
11349
11375
  }
11350
11376
  * { box-sizing: border-box; }
11377
+ /* Touch: no grey flash on a tap, no double-tap zoom wait on a control,
11378
+ and a long press never selects a control's label. Text stays selectable. */
11379
+ html { -webkit-tap-highlight-color: transparent; }
11380
+ a, button, summary, [role=button], [role=tab] { touch-action: manipulation; }
11381
+ button, [role=button], [role=tab], .task-context-chip, .approval-chip, .verdict-chip { -webkit-user-select: none; user-select: none; }
11351
11382
  ::selection { background: var(--so-selection); color: var(--so-ink); }
11352
11383
  ::placeholder { color: var(--muted-foreground); }
11353
11384
  body {
@@ -11378,7 +11409,7 @@ ${THEME_DARK}
11378
11409
  color: var(--muted-foreground); text-decoration: none; font-size: 0.8125rem; font-weight: 500;
11379
11410
  display: flex; align-items: center; padding: 0 .625rem; transition: color .15s;
11380
11411
  }
11381
- .topbar nav a:hover { color: var(--foreground); }
11412
+ @media (hover: hover) and (pointer: fine) { .topbar nav a:hover { color: var(--foreground); } }
11382
11413
  main { max-width: 44rem; margin-inline: auto; padding: 1.75rem 1.25rem 4rem; }
11383
11414
  h1 { font-size: 1.25rem; font-weight: 600; letter-spacing: -0.02em; margin: 0 0 .25rem; line-height: 1.3; }
11384
11415
  h1 .meta { font-weight: 400; letter-spacing: 0; }
@@ -11389,7 +11420,7 @@ ${THEME_DARK}
11389
11420
  color: var(--muted-foreground); margin: 2rem 0 .5rem; font-family: var(--font-sans);
11390
11421
  }
11391
11422
  a { color: var(--foreground); text-decoration: underline; text-decoration-color: var(--border); text-underline-offset: 3px; }
11392
- a:hover { text-decoration-color: var(--muted-foreground); }
11423
+ @media (hover: hover) and (pointer: fine) { a:hover { text-decoration-color: var(--muted-foreground); } }
11393
11424
  p { margin: .4rem 0; }
11394
11425
  code { background: var(--muted); border-radius: .3rem; padding: .1rem .35rem; font-family: var(--font-mono); font-size: .8125rem; }
11395
11426
  .mono { font-family: var(--font-mono); font-size: .8125rem; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
@@ -11497,7 +11528,7 @@ ${THEME_DARK}
11497
11528
  .row:last-of-type { border-bottom: none; }
11498
11529
  .row .right { margin-left: auto; }
11499
11530
  a.row { text-decoration: none; }
11500
- a.row:hover { background: var(--muted); }
11531
+ @media (hover: hover) and (pointer: fine) { a.row:hover { background: var(--muted); } }
11501
11532
 
11502
11533
  /* A parked decision: the question in full weight, the whole card the
11503
11534
  tap target, the neutral border — the "needs you" header above it
@@ -11508,38 +11539,38 @@ ${THEME_DARK}
11508
11539
  background: var(--card); padding: .875rem 1.125rem; margin: .625rem 0;
11509
11540
  text-decoration: none; transition: border-color .15s;
11510
11541
  }
11511
- .decide-card:hover { border-color: color-mix(in srgb, var(--border) 55%, var(--muted-foreground)); }
11542
+ @media (hover: hover) and (pointer: fine) { .decide-card:hover { border-color: color-mix(in srgb, var(--border) 55%, var(--muted-foreground)); } }
11512
11543
  .decide-card .q { font-weight: 600; margin: 0 0 .25rem; }
11513
11544
 
11514
11545
  /* Buttons: secondary by default (paper + hairline); a form's one
11515
11546
  submit is primary (ink on paper, paper on ink); the approve act is
11516
- magenta; danger is red and outlined. 2.125rem at a desk, 2.75rem to a thumb. */
11547
+ the accent; danger is red and outlined. 2.125rem at a desk, 2.75rem to a thumb. */
11517
11548
  button {
11518
11549
  font: 500 0.8125rem/1.4 var(--font-sans); cursor: pointer; border-radius: calc(var(--radius) - 3px);
11519
11550
  border: 1px solid var(--input); background: var(--card); color: var(--foreground);
11520
11551
  padding: .35rem .75rem; min-height: 2.125rem;
11521
- transition: background .12s ease-out, border-color .12s ease-out, color .12s ease-out;
11552
+ transition: background .12s var(--so-ease-out), border-color .12s var(--so-ease-out), color .12s var(--so-ease-out);
11522
11553
  }
11523
- button:hover { background: var(--so-soft); }
11554
+ @media (hover: hover) and (pointer: fine) { button:hover { background: var(--so-soft); } }
11524
11555
  button:active { background: var(--so-nav-hover); }
11525
11556
  form.card > button[type=submit], .sticky-actions button[type=submit], form.card .sticky-actions button {
11526
11557
  background: var(--primary); color: var(--primary-foreground); border-color: var(--primary); font-weight: 600;
11527
11558
  }
11528
- form.card > button[type=submit]:hover, .sticky-actions button[type=submit]:hover {
11559
+ @media (hover: hover) and (pointer: fine) { form.card > button[type=submit]:hover, .sticky-actions button[type=submit]:hover {
11529
11560
  background: color-mix(in srgb, var(--primary) 85%, var(--background)); border-color: color-mix(in srgb, var(--primary) 85%, var(--background));
11530
- }
11561
+ } }
11531
11562
  /* The approve act is the one magenta verb: it resolves what waits on you.
11532
11563
  The ceremony's frame is neutral so the button is the only coloured thing
11533
11564
  in it; a danger act stays red even inside one. */
11534
11565
  .approve-form button[type=submit], .approve-form .sticky-actions button[type=submit] {
11535
11566
  background: var(--brand); color: var(--brand-foreground); border-color: var(--brand); font-weight: 600;
11536
11567
  }
11537
- .approve-form button[type=submit]:hover, .approve-form .sticky-actions button[type=submit]:hover { background: color-mix(in srgb, var(--brand) 85%, var(--foreground)); border-color: color-mix(in srgb, var(--brand) 85%, var(--foreground)); }
11568
+ @media (hover: hover) and (pointer: fine) { .approve-form button[type=submit]:hover, .approve-form .sticky-actions button[type=submit]:hover { background: color-mix(in srgb, var(--brand) 85%, var(--foreground)); border-color: color-mix(in srgb, var(--brand) 85%, var(--foreground)); } }
11538
11569
  button.danger, .approve-form button[type=submit].danger {
11539
11570
  color: var(--destructive); border-color: color-mix(in srgb, var(--destructive) 50%, transparent);
11540
11571
  background: transparent; font-weight: 500;
11541
11572
  }
11542
- button.danger:hover, .approve-form button[type=submit].danger:hover { background: var(--destructive-soft); }
11573
+ @media (hover: hover) and (pointer: fine) { button.danger:hover, .approve-form button[type=submit].danger:hover { background: var(--destructive-soft); } }
11543
11574
  /* Removing a credential takes a second, deliberate tap. */
11544
11575
  details.confirm-remove { display: inline-block; margin: 0 0 0 .5rem; vertical-align: top; }
11545
11576
  details.confirm-remove > summary { cursor: pointer; color: var(--destructive); font-size: .8125rem; min-height: 2.5rem; display: inline-flex; align-items: center; }
@@ -11553,7 +11584,7 @@ ${THEME_DARK}
11553
11584
  border: 1px solid var(--input); border-radius: calc(var(--radius) - 3px);
11554
11585
  transition: border-color .15s, box-shadow .15s;
11555
11586
  }
11556
- input:hover, textarea:hover, select:hover { border-color: var(--muted-foreground); }
11587
+ @media (hover: hover) and (pointer: fine) { input:hover, textarea:hover, select:hover { border-color: var(--muted-foreground); } }
11557
11588
  input[type=number] { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
11558
11589
  input[type=radio], input[type=checkbox] { accent-color: var(--ring); }
11559
11590
  .permission-field { border: 0; padding: 0; margin: 1rem 0 0; min-width: 0; }
@@ -11565,7 +11596,7 @@ ${THEME_DARK}
11565
11596
  border-radius: calc(var(--radius) - 3px); background: color-mix(in srgb, var(--card) 66%, transparent);
11566
11597
  cursor: pointer; transition: border-color .15s, background .15s, box-shadow .15s;
11567
11598
  }
11568
- .permission-choice:hover { background: var(--muted); }
11599
+ @media (hover: hover) and (pointer: fine) { .permission-choice:hover { background: var(--muted); } }
11569
11600
  .permission-choice:has(input:checked) {
11570
11601
  border-color: color-mix(in srgb, var(--foreground) 42%, var(--border));
11571
11602
  background: var(--card); box-shadow: 0 0 0 1px color-mix(in srgb, var(--foreground) 8%, transparent), var(--shadow);
@@ -11597,7 +11628,8 @@ ${THEME_DARK}
11597
11628
  min-height: 8.5rem; max-height: 18rem; margin: 0; padding: .9rem 1rem; resize: vertical;
11598
11629
  border: 0; background: transparent; box-shadow: none; font-size: 1.05rem; line-height: 1.55;
11599
11630
  }
11600
- .task-prompt textarea:hover, .task-prompt textarea:focus-visible { border: 0; box-shadow: none; }
11631
+ .task-prompt textarea:focus-visible { border: 0; box-shadow: none; }
11632
+ @media (hover: hover) and (pointer: fine) { .task-prompt textarea:hover { border: 0; box-shadow: none; } }
11601
11633
  .task-repo { margin: .25rem .45rem .7rem; }
11602
11634
  .task-composer-footer { display: flex; align-items: center; gap: .5rem; padding: .25rem; }
11603
11635
  .task-context { display: flex; align-items: center; gap: .4rem; flex: 1 1 auto; min-width: 0; }
@@ -11616,7 +11648,7 @@ ${THEME_DARK}
11616
11648
  flex: none; min-height: 2.45rem; padding: .45rem .95rem; border-radius: 999px;
11617
11649
  background: var(--primary); color: var(--primary-foreground); border-color: var(--primary); font-weight: 600;
11618
11650
  }
11619
- .task-submit:hover { background: color-mix(in srgb, var(--primary) 85%, var(--background)); border-color: transparent; }
11651
+ @media (hover: hover) and (pointer: fine) { .task-submit:hover { background: color-mix(in srgb, var(--primary) 85%, var(--background)); border-color: transparent; } }
11620
11652
  details.task-options {
11621
11653
  margin: .65rem .25rem 0; padding: .15rem .5rem 0; border: 0; border-top: 1px solid var(--glass-border);
11622
11654
  border-radius: 0; background: transparent;
@@ -11703,7 +11735,7 @@ ${THEME_DARK}
11703
11735
  .receipt-visuals { display: grid; grid-template-columns: repeat(auto-fill, minmax(8rem, 14rem)); gap: .55rem; margin-top: .75rem; }
11704
11736
  .receipt-shot { display: grid; gap: .35rem; color: var(--muted-foreground); font-size: .7rem; text-decoration: none; }
11705
11737
  .receipt-shot img { display: block; width: 100%; aspect-ratio: 16 / 10; object-fit: cover; border: 1px solid var(--glass-border); border-radius: calc(var(--radius) - 3px); background: var(--muted); }
11706
- .receipt-shot:hover { color: var(--foreground); }
11738
+ @media (hover: hover) and (pointer: fine) { .receipt-shot:hover { color: var(--foreground); } }
11707
11739
  .receipt-caveats, .receipt-coverage { margin-top: .8rem; padding: .7rem .8rem; border-left: 1px solid var(--border); border-radius: 0 calc(var(--radius) - 3px) calc(var(--radius) - 3px) 0; background: color-mix(in srgb, var(--muted) 62%, transparent); font-size: .78rem; }
11708
11740
  .receipt-caveats ul, .receipt-coverage ul { margin: .3rem 0 0; padding-left: 1.15rem; }
11709
11741
  /* Secondary receipt detail (concise pass, 2026-09-13): native
@@ -11735,7 +11767,7 @@ ${THEME_DARK}
11735
11767
  display: grid; gap: .2rem; padding: .55rem .65rem; margin-bottom: .2rem; min-width: 0;
11736
11768
  border: 1px solid transparent; border-radius: calc(var(--radius) - 3px); text-decoration: none; color: var(--foreground);
11737
11769
  }
11738
- .cockpit-row:hover { background: var(--card); }
11770
+ @media (hover: hover) and (pointer: fine) { .cockpit-row:hover { background: var(--card); } }
11739
11771
  .cockpit-row.current { background: var(--muted); border-color: color-mix(in srgb, var(--foreground) 12%, var(--border)); }
11740
11772
  .cockpit-row-head { display: flex; align-items: flex-start; justify-content: space-between; gap: .5rem; min-width: 0; }
11741
11773
  .cockpit-row-head strong { min-width: 0; overflow-wrap: anywhere; font-size: .8125rem; font-weight: 550; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
@@ -11812,7 +11844,7 @@ ${THEME_DARK}
11812
11844
  min-height: 1.75rem; padding: .2rem .7rem; border: 0; border-radius: 999px;
11813
11845
  background: transparent; box-shadow: none; color: var(--muted-foreground); font-size: .7rem;
11814
11846
  }
11815
- .diff-modes button:hover { transform: none; color: var(--foreground); }
11847
+ @media (hover: hover) and (pointer: fine) { .diff-modes button:hover { transform: none; color: var(--foreground); } }
11816
11848
  .diff-modes button[aria-pressed="true"] { background: var(--card); color: var(--foreground); box-shadow: 0 1px 3px color-mix(in srgb, var(--background) 20%, transparent); }
11817
11849
  .diff-review-help {
11818
11850
  margin: 0; padding: .62rem .85rem; border-bottom: 1px solid var(--glass-border);
@@ -11849,7 +11881,7 @@ ${THEME_DARK}
11849
11881
  display: grid; grid-template-columns: 2rem 3.2rem 3.2rem minmax(max-content, 1fr); align-items: stretch;
11850
11882
  min-width: max-content; min-height: 1.8rem; font: 400 .72rem/1.55 var(--font-mono);
11851
11883
  }
11852
- .diff-line:hover { background: color-mix(in srgb, var(--foreground) 4%, transparent); }
11884
+ @media (hover: hover) and (pointer: fine) { .diff-line:hover { background: color-mix(in srgb, var(--foreground) 4%, transparent); } }
11853
11885
  .diff-line code { display: flex; min-width: 0; padding: .3rem .75rem .3rem .6rem; color: inherit; white-space: pre; }
11854
11886
  .diff-line code b { display: inline-block; width: 1rem; flex: none; font-weight: 500; opacity: .72; }
11855
11887
  .diff-gutter {
@@ -11865,7 +11897,7 @@ ${THEME_DARK}
11865
11897
  }
11866
11898
  .diff-annotate { padding: 0; background: color-mix(in srgb, var(--card) 94%, transparent); color: var(--muted-foreground); box-shadow: none; opacity: .35; }
11867
11899
  .diff-annotate svg { width: .78rem; height: .78rem; }
11868
- .diff-annotate:hover { transform: none; background: color-mix(in srgb, var(--running) 15%, var(--card)); color: var(--running); opacity: 1; }
11900
+ @media (hover: hover) and (pointer: fine) { .diff-annotate:hover { transform: none; background: color-mix(in srgb, var(--running) 15%, var(--card)); color: var(--running); opacity: 1; } }
11869
11901
  .diff-annotate-space { background: color-mix(in srgb, var(--card) 94%, transparent); }
11870
11902
  .diff-review[data-mode="view"] .diff-line { grid-template-columns: 0 3.2rem 3.2rem minmax(max-content, 1fr); }
11871
11903
  .diff-review[data-mode="view"] .diff-annotate,
@@ -11935,11 +11967,11 @@ ${THEME_DARK}
11935
11967
  details[open] { padding-bottom: .875rem; }
11936
11968
  details.arm-danger { border-color: color-mix(in srgb, var(--destructive) 30%, transparent); }
11937
11969
  summary { padding: .5rem 0; cursor: pointer; font-weight: 500; font-size: 0.8125rem; color: var(--muted-foreground); min-height: 2.25rem; }
11938
- summary:hover { color: var(--foreground); }
11970
+ @media (hover: hover) and (pointer: fine) { summary:hover { color: var(--foreground); } }
11939
11971
  details form.option { border: none; padding: .25rem 0 0; margin: 0; }
11940
11972
  .evidence { margin-top: 1.5rem; font-size: 0.8125rem; }
11941
11973
  .evidence a { display: block; padding: .55rem 0; border-bottom: 1px solid var(--border); text-decoration: none; }
11942
- .evidence a:hover { color: var(--muted-foreground); }
11974
+ @media (hover: hover) and (pointer: fine) { .evidence a:hover { color: var(--muted-foreground); } }
11943
11975
  .evidence strong { display: block; font-size: 0.6875rem; text-transform: uppercase; letter-spacing: .08em; color: var(--muted-foreground); font-family: var(--font-mono); }
11944
11976
 
11945
11977
  .filters { font-size: 0.8125rem; color: var(--muted-foreground); }
@@ -11948,7 +11980,7 @@ ${THEME_DARK}
11948
11980
  color: var(--muted-foreground); font-weight: 500;
11949
11981
  }
11950
11982
  .filters strong { background: var(--muted); color: var(--foreground); }
11951
- .filters a:hover { color: var(--foreground); }
11983
+ @media (hover: hover) and (pointer: fine) { .filters a:hover { color: var(--foreground); } }
11952
11984
 
11953
11985
  /* A picked tournament result: marked in the built green, not magenta. */
11954
11986
  .card.picked { border-color: color-mix(in srgb, var(--success) 40%, var(--border)); }
@@ -11976,7 +12008,7 @@ ${THEME_DARK}
11976
12008
  display: grid; place-items: center; flex: 0 0 2rem; width: 2rem; min-height: 2rem; padding: 0;
11977
12009
  border-color: transparent; background: transparent; color: var(--muted-foreground); box-shadow: none;
11978
12010
  }
11979
- .side-toggle:hover { background: var(--glass); color: var(--foreground); transform: none; }
12011
+ @media (hover: hover) and (pointer: fine) { .side-toggle:hover { background: var(--glass); color: var(--foreground); transform: none; } }
11980
12012
  .side-toggle svg { width: 1rem; height: 1rem; }
11981
12013
  /* The scope bar: one hairline row, the single scope truth on every
11982
12014
  * screen; its name is the switcher. Magenta never appears here except
@@ -12012,7 +12044,7 @@ ${THEME_DARK}
12012
12044
  border-right: 1.75px solid var(--foreground); border-bottom: 1.75px solid var(--foreground);
12013
12045
  transform: rotate(45deg) translateY(-.125rem);
12014
12046
  }
12015
- .switcher-menu button:hover { background: var(--muted); }
12047
+ @media (hover: hover) and (pointer: fine) { .switcher-menu button:hover { background: var(--muted); } }
12016
12048
  .switcher-menu .manage {
12017
12049
  display: block; margin-top: .25rem; padding: .625rem .75rem; border-top: 1px solid var(--border);
12018
12050
  font-size: .75rem; color: var(--muted-foreground); text-decoration: none;
@@ -12024,14 +12056,14 @@ ${THEME_DARK}
12024
12056
  }
12025
12057
  .scope-status .hot { color: var(--brand); font-weight: 500; }
12026
12058
  .scope-status a { color: inherit; text-decoration: none; }
12027
- .scope-status a:hover { text-decoration: underline; }
12059
+ @media (hover: hover) and (pointer: fine) { .scope-status a:hover { text-decoration: underline; } }
12028
12060
  /* A project card's name and counts are forms or links dressed as text and chips. */
12029
12061
  .project-card button.project-name, .project-card a.project-name {
12030
12062
  all: unset; cursor: pointer; font-weight: 600; color: var(--foreground);
12031
12063
  }
12032
- .project-card a.project-name:hover, .project-card button.project-name:hover { text-decoration: underline; }
12064
+ @media (hover: hover) and (pointer: fine) { .project-card a.project-name:hover, .project-card button.project-name:hover { text-decoration: underline; } }
12033
12065
  .project-card button.badge { min-height: auto; box-shadow: none; cursor: pointer; }
12034
- .project-card button.badge:hover, .project-card a.badge:hover { border-color: var(--input); }
12066
+ @media (hover: hover) and (pointer: fine) { .project-card button.badge:hover, .project-card a.badge:hover { border-color: var(--input); } }
12035
12067
  /* Adding a project is the page's primary job, not badge-sized metadata.
12036
12068
  * Two roomy action tiles make both roads obvious on a desk and give each
12037
12069
  * one a generous thumb target on a phone. The manual path stays tertiary. */
@@ -12054,11 +12086,11 @@ ${THEME_DARK}
12054
12086
 
12055
12087
  transition: transform .15s ease, background .15s, border-color .15s, box-shadow .15s;
12056
12088
  }
12057
- .project-add-action:hover {
12089
+ @media (hover: hover) and (pointer: fine) { .project-add-action:hover {
12058
12090
  border-color: color-mix(in srgb, var(--border) 50%, var(--muted-foreground));
12059
12091
  background: var(--card); text-decoration: none;
12060
12092
  box-shadow: var(--shadow);
12061
- }
12093
+ } }
12062
12094
  .project-add-action:active { transform: translateY(0); }
12063
12095
  .project-add-icon {
12064
12096
  display: grid; place-items: center; width: 2.75rem; height: 2.75rem;
@@ -12078,7 +12110,7 @@ ${THEME_DARK}
12078
12110
  display: flex; align-items: center; min-height: 2.75rem; width: fit-content;
12079
12111
  color: var(--muted-foreground); cursor: pointer; font-size: .8125rem; font-weight: 500;
12080
12112
  }
12081
- .project-add-more > summary:hover { color: var(--foreground); }
12113
+ @media (hover: hover) and (pointer: fine) { .project-add-more > summary:hover { color: var(--foreground); } }
12082
12114
  .project-add-more > .card { margin: 0 0 .25rem; }
12083
12115
  .side nav { display: flex; flex-direction: column; gap: .125rem; }
12084
12116
  /* Inline decision options: neutral buttons — the card's magenta outline is
@@ -12101,7 +12133,7 @@ ${THEME_DARK}
12101
12133
  font-family: var(--font-sans);
12102
12134
  }
12103
12135
  .nav-group > summary::-webkit-details-marker { display: none; }
12104
- .nav-group > summary:hover { background: var(--glass); color: var(--foreground); }
12136
+ @media (hover: hover) and (pointer: fine) { .nav-group > summary:hover { background: var(--glass); color: var(--foreground); } }
12105
12137
  .nav-group > summary .chevron { width: .875rem; height: .875rem; flex: none; transition: transform .15s; }
12106
12138
  .nav-group[open] > summary .chevron { transform: rotate(180deg); }
12107
12139
  .nav-group .nav-group-items { display: flex; flex-direction: column; gap: .125rem; margin: .125rem 0 .25rem; }
@@ -12115,7 +12147,8 @@ ${THEME_DARK}
12115
12147
  }
12116
12148
  .side nav a .glyph { display: inline-flex; width: 1rem; height: 1rem; color: var(--muted-foreground); flex: none; }
12117
12149
  .side nav a .glyph svg { width: 1rem; height: 1rem; }
12118
- .side nav a:hover { background: var(--glass); color: var(--foreground); transform: translateX(2px); }
12150
+ @media (hover: hover) and (pointer: fine) { .side nav a:hover { background: var(--glass); color: var(--foreground); transform: translateX(2px); } }
12151
+ .side nav a:active { background: var(--glass); color: var(--foreground); }
12119
12152
  .app.sidebar-collapsed { grid-template-columns: 64px minmax(0, 1fr); }
12120
12153
  .app.sidebar-collapsed .side { padding-inline: .625rem; }
12121
12154
  .app.sidebar-collapsed .side-head { flex-direction: column; gap: .2rem; margin-bottom: .55rem; }
@@ -12148,14 +12181,14 @@ ${THEME_DARK}
12148
12181
  border-radius: calc(var(--radius) - 3px); padding: .525rem; margin: .75rem 0 .125rem;
12149
12182
  box-shadow: 0 10px 28px -18px rgb(255 255 255 / .5);
12150
12183
  }
12151
- .side .new-task:hover { background: color-mix(in srgb, var(--primary) 85%, var(--background)); }
12184
+ @media (hover: hover) and (pointer: fine) { .side .new-task:hover { background: color-mix(in srgb, var(--primary) 85%, var(--background)); } }
12152
12185
  /* The same action link outside the sidebar reads as a real button. */
12153
12186
  .content .new-task {
12154
12187
  display: inline-block; text-decoration: none; font-weight: 500; font-size: .8125rem;
12155
12188
  background: var(--secondary); color: var(--foreground); border: 1px solid var(--border);
12156
12189
  border-radius: calc(var(--radius) - 2px); padding: .5rem .875rem;
12157
12190
  }
12158
- .content .new-task:hover { background: color-mix(in srgb, var(--secondary) 70%, var(--border)); }
12191
+ @media (hover: hover) and (pointer: fine) { .content .new-task:hover { background: color-mix(in srgb, var(--secondary) 70%, var(--border)); } }
12159
12192
  .content { min-width: 0; }
12160
12193
  .content > main { max-width: 54rem; margin: 0; padding: 2rem 2.5rem 4rem; }
12161
12194
 
@@ -12166,6 +12199,7 @@ ${THEME_DARK}
12166
12199
  }
12167
12200
  .banner .badge { margin-right: .5rem; }
12168
12201
  .banner a { color: var(--muted-foreground); }
12202
+ .sign-in-banner form { display: inline; margin: 0 0 0 .5rem; padding: 0; border: 0; background: transparent; }
12169
12203
 
12170
12204
  .split { display: grid; grid-template-columns: minmax(250px, 320px) minmax(0, 1fr); min-height: 100vh; }
12171
12205
  .list-pane {
@@ -12177,7 +12211,7 @@ ${THEME_DARK}
12177
12211
  display: block; padding: .5rem .625rem; border-radius: calc(var(--radius) - 4px);
12178
12212
  text-decoration: none; font-size: .8125rem; margin-bottom: .125rem;
12179
12213
  }
12180
- .list-pane a.item:hover { background: var(--card); }
12214
+ @media (hover: hover) and (pointer: fine) { .list-pane a.item:hover { background: var(--card); } }
12181
12215
  .list-pane a.item.current { background: var(--muted); }
12182
12216
  .list-pane a.item .t { display: block; font-weight: 500; color: var(--foreground);
12183
12217
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@@ -12206,13 +12240,13 @@ ${THEME_DARK}
12206
12240
  min-width: 4.6rem; padding: .4rem .72rem; border-radius: .52rem; color: var(--muted-foreground);
12207
12241
  font-size: .72rem; font-weight: 550; text-align: center; text-decoration: none;
12208
12242
  }
12209
- .task-view-switch a:hover { color: var(--foreground); background: color-mix(in srgb, var(--muted) 70%, transparent); }
12243
+ @media (hover: hover) and (pointer: fine) { .task-view-switch a:hover { color: var(--foreground); background: color-mix(in srgb, var(--muted) 70%, transparent); } }
12210
12244
  .task-view-switch a.active { color: var(--foreground); background: var(--glass-strong); box-shadow: 0 1px 5px rgb(0 0 0 / .1); }
12211
12245
  .acts-bar { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin: .75rem 0 .25rem; }
12212
12246
  .acts-bar form.inline { margin: 0; display: inline-flex; align-items: center; gap: .375rem; }
12213
12247
  .acts-bar form.inline button { width: auto; }
12214
12248
  .acts-bar .primary button { background: var(--primary); color: var(--primary-foreground); border-color: var(--primary); font-weight: 600; }
12215
- .acts-bar .primary button:hover { background: color-mix(in srgb, var(--primary) 85%, var(--background)); }
12249
+ @media (hover: hover) and (pointer: fine) { .acts-bar .primary button:hover { background: color-mix(in srgb, var(--primary) 85%, var(--background)); } }
12216
12250
  .acts-bar .act-hold input[type=text] { width: 10rem; min-height: 2.25rem; margin: 0; font-size: .8125rem; }
12217
12251
  .acts-why { margin: 0 0 .5rem; }
12218
12252
  .dispatch-status { padding: .8rem .9rem; border-radius: var(--radius); overflow: hidden; }
@@ -12491,7 +12525,7 @@ ${THEME_DARK}
12491
12525
  transform: rotate(45deg) translateY(-.125rem); transition: transform .15s;
12492
12526
  }
12493
12527
  details.section[open] > summary::after { transform: rotate(225deg) translateY(-.125rem); }
12494
- details.section > summary:hover h2 { color: var(--foreground); }
12528
+ @media (hover: hover) and (pointer: fine) { details.section > summary:hover h2 { color: var(--foreground); } }
12495
12529
  details.more-agents { margin: .75rem 0 0; }
12496
12530
  .task-layout > .task-main { min-width: 0; }
12497
12531
  .task-rail { position: sticky; top: 1rem; }
@@ -12558,7 +12592,7 @@ ${THEME_DARK}
12558
12592
  background: var(--card); box-shadow: var(--shadow);
12559
12593
  }
12560
12594
  .work-tools-menu a { display: block; padding: .5rem .625rem; border-radius: .5rem; text-decoration: none; color: var(--foreground); font-size: .875rem; }
12561
- .work-tools-menu a:hover { background: var(--muted); }
12595
+ @media (hover: hover) and (pointer: fine) { .work-tools-menu a:hover { background: var(--muted); } }
12562
12596
  /* The result panel (workspace package 3): one presentation of a finished
12563
12597
  result for the run page, the review cockpit, and the chat's result
12564
12598
  detail — the deliverable first, problems ahead of readiness words,
@@ -12584,7 +12618,7 @@ ${THEME_DARK}
12584
12618
  .result-notes > summary::-webkit-details-marker, .result-details > summary::-webkit-details-marker { display: none; }
12585
12619
  .result-notes > summary::before, .result-details > summary::before { content: "▸"; }
12586
12620
  .result-notes[open] > summary::before, .result-details[open] > summary::before { content: "▾"; }
12587
- .result-notes > summary:hover, .result-details > summary:hover { color: var(--foreground); }
12621
+ @media (hover: hover) and (pointer: fine) { .result-notes > summary:hover, .result-details > summary:hover { color: var(--foreground); } }
12588
12622
  .result-details > summary .meta { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--font-mono); font-size: .68rem; font-weight: 400; }
12589
12623
  .result-notes .recap { margin: .25rem 0 .4rem; font-size: .875rem; }
12590
12624
  .result-attention { margin: .75rem 0 .25rem; padding: .7rem .85rem; border-left: 1px solid var(--warning); border-radius: 0 calc(var(--radius) - 3px) calc(var(--radius) - 3px) 0; background: var(--warning-soft); font-size: .8125rem; }
@@ -12695,9 +12729,9 @@ ${THEME_DARK}
12695
12729
  .work-details > summary::-webkit-details-marker { display: none; }
12696
12730
  .work-details > summary::before { content: "▸"; }
12697
12731
  .work-details[open] > summary::before { content: "▾"; }
12698
- .work-details > summary:hover { color: var(--foreground); }
12732
+ @media (hover: hover) and (pointer: fine) { .work-details > summary:hover { color: var(--foreground); } }
12699
12733
  .work-title { display: block; font-weight: 600; font-size: .9375rem; line-height: 1.35; color: var(--foreground); text-decoration: none; overflow-wrap: anywhere; }
12700
- .work-title:hover { text-decoration: underline; }
12734
+ @media (hover: hover) and (pointer: fine) { .work-title:hover { text-decoration: underline; } }
12701
12735
  .work-meta { display: flex; flex-wrap: wrap; gap: .25rem .625rem; margin: .25rem 0 0; font-size: .75rem; color: var(--muted-foreground); }
12702
12736
  .work-meta .mono { overflow-wrap: anywhere; }
12703
12737
  .project-label { display: inline-block; padding: 0 .4rem; border: 1px solid var(--border); border-radius: 999px; font-size: .6875rem; line-height: 1.5; color: var(--foreground); }
@@ -12852,7 +12886,7 @@ ${THEME_DARK}
12852
12886
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--card);
12853
12887
  padding: .75rem .875rem; color: var(--foreground); min-height: 44px; justify-content: center;
12854
12888
  }
12855
- .menu-row:hover { border-color: color-mix(in srgb, var(--border) 60%, var(--muted-foreground)); }
12889
+ @media (hover: hover) and (pointer: fine) { .menu-row:hover { border-color: color-mix(in srgb, var(--border) 60%, var(--muted-foreground)); } }
12856
12890
 
12857
12891
  .cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(13.5rem, 1fr)); gap: .625rem; margin: .5rem 0; }
12858
12892
  .stat-card {
@@ -12887,7 +12921,7 @@ ${THEME_DARK}
12887
12921
  width: 100%; margin-top: 1.25rem;
12888
12922
  background: var(--so-accent); color: var(--so-on-accent); border-color: var(--so-accent); font-weight: 600;
12889
12923
  }
12890
- .login-shell button:hover { background: var(--so-accent-hover); border-color: var(--so-accent-hover); }
12924
+ @media (hover: hover) and (pointer: fine) { .login-shell button:hover { background: var(--so-accent-hover); border-color: var(--so-accent-hover); } }
12891
12925
  .login-foot { text-align: center; margin: 1.5rem 0 0; font-size: 0.75rem; color: var(--muted-foreground); line-height: 1.9; }
12892
12926
  .login-foot code { background: none; padding: 0; color: var(--muted-foreground); white-space: nowrap; }
12893
12927
  .so-wordmark { display: flex; align-items: center; gap: 9px; font-size: 13px; font-weight: 600; text-decoration: none; white-space: nowrap; letter-spacing: -.02em; color: var(--foreground); }
@@ -12899,7 +12933,7 @@ ${THEME_DARK}
12899
12933
  .sso-step-up[data-sso-step-up="confirmed"] { color: var(--so-success); }
12900
12934
  .sso-step-up[data-sso-step-up="confirmed"]::before { content: "✓"; margin-right: 6px; }
12901
12935
  .login-shell .login-sso { display: flex; justify-content: center; align-items: center; min-height: 44px; border-radius: 8px; background: var(--so-accent); color: var(--so-on-accent); font-weight: 600; text-decoration: none; margin: 0 0 1rem; }
12902
- .login-shell .login-sso:hover { background: var(--so-accent-hover); }
12936
+ @media (hover: hover) and (pointer: fine) { .login-shell .login-sso:hover { background: var(--so-accent-hover); } }
12903
12937
  .login-shell .login-password > summary { text-align: center; font-size: .875rem; color: var(--muted-foreground); cursor: pointer; margin: 0 0 .75rem; }
12904
12938
  .focus-page { max-width: 40rem; margin: 0 auto; padding: 2rem 1.25rem 3rem; }
12905
12939
  .focus-page .focus-brand { display: inline-flex; margin: 0 0 2.5rem; }
@@ -12952,7 +12986,7 @@ ${THEME_DARK}
12952
12986
  .lane > summary::-webkit-details-marker { display: none; }
12953
12987
  .lane h2 { display: flex; align-items: center; gap: .4rem; margin: 0; font-size: .6875rem; }
12954
12988
  .lane h2 a { color: inherit; text-decoration: none; }
12955
- .lane h2 a:hover { text-decoration: underline; }
12989
+ @media (hover: hover) and (pointer: fine) { .lane h2 a:hover { text-decoration: underline; } }
12956
12990
  .lane .hint { margin-top: 0; }
12957
12991
  .lane-count { color: var(--muted-foreground); font-weight: 400; font-variant-numeric: tabular-nums; }
12958
12992
  .lane h2::before {
@@ -12967,7 +13001,7 @@ ${THEME_DARK}
12967
13001
  background: var(--card); border: 1px solid var(--border);
12968
13002
  border-radius: calc(var(--radius) - 2px); padding: .5rem .625rem; margin-top: .5rem;
12969
13003
  }
12970
- .lane-card:hover { border-color: color-mix(in srgb, var(--border) 55%, var(--muted-foreground)); }
13004
+ @media (hover: hover) and (pointer: fine) { .lane-card:hover { border-color: color-mix(in srgb, var(--border) 55%, var(--muted-foreground)); } }
12971
13005
  .lane-card .id { display: block; font-family: var(--font-mono); font-size: .6875rem; color: var(--muted-foreground); margin-bottom: .125rem; overflow-wrap: anywhere; }
12972
13006
  .lane-card .t { display: block; font-size: .8125rem; font-weight: 500; line-height: 1.35; }
12973
13007
  .lane-card .dot { margin-right: .4rem; }
@@ -13165,7 +13199,7 @@ ${THEME_DARK}
13165
13199
  border: 1px solid var(--glass-border); border-radius: calc(var(--radius) - 3px);
13166
13200
  background: color-mix(in srgb, var(--glass-strong) 64%, transparent); text-decoration: none;
13167
13201
  }
13168
- .chat-overview-stat:hover { background: var(--glass-strong); }
13202
+ @media (hover: hover) and (pointer: fine) { .chat-overview-stat:hover { background: var(--glass-strong); } }
13169
13203
  .chat-overview-stat b { color: var(--foreground); font: 600 1.2rem/1.2 var(--font-mono); font-variant-numeric: tabular-nums; }
13170
13204
  .chat-overview-stat span { overflow: hidden; color: var(--muted-foreground); font-size: .65rem; text-overflow: ellipsis; white-space: nowrap; }
13171
13205
  .chat-overview-stat.attention b { color: var(--warning); }
@@ -13175,7 +13209,7 @@ ${THEME_DARK}
13175
13209
  display: grid; grid-template-columns: 1.75rem minmax(0, 1fr) auto; align-items: center; gap: .6rem;
13176
13210
  padding: .48rem .55rem; border-radius: calc(var(--radius) - 4px); color: inherit; text-decoration: none;
13177
13211
  }
13178
- .chat-overview-item:hover { background: color-mix(in srgb, var(--muted) 72%, transparent); }
13212
+ @media (hover: hover) and (pointer: fine) { .chat-overview-item:hover { background: color-mix(in srgb, var(--muted) 72%, transparent); } }
13179
13213
  .chat-overview-icon { display: grid; place-items: center; width: 1.75rem; height: 1.75rem; border-radius: .55rem; background: var(--muted); color: var(--muted-foreground); }
13180
13214
  .chat-overview-icon svg { width: .9rem; height: .9rem; }
13181
13215
  .chat-overview-item.decision .chat-overview-icon { color: var(--warning); background: var(--warning-soft); }
@@ -13202,10 +13236,10 @@ ${THEME_DARK}
13202
13236
  background: color-mix(in srgb, var(--muted) 58%, transparent);
13203
13237
  transition: transform .16s ease, background .16s, border-color .16s, box-shadow .16s;
13204
13238
  }
13205
- .chat-project-card:hover {
13239
+ @media (hover: hover) and (pointer: fine) { .chat-project-card:hover {
13206
13240
  border-color: var(--glass-border); background: color-mix(in srgb, var(--muted) 82%, transparent);
13207
13241
  box-shadow: 0 12px 28px -24px rgb(0 0 0 / .8);
13208
- }
13242
+ } }
13209
13243
  .chat-project-name { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: .45rem; }
13210
13244
  .chat-project-name strong { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .8125rem; }
13211
13245
  .chat-project-name .mono { color: var(--running); font-size: .6875rem; }
@@ -13277,7 +13311,7 @@ ${THEME_DARK}
13277
13311
  .proposal-actions form { margin: 0; }
13278
13312
  /* The confirm is the card's one primary; dismiss stays quiet (UI polish 2026-09-13). */
13279
13313
  .proposal-actions .acts form:first-child button[type=submit] { background: var(--primary); color: var(--primary-foreground); border-color: var(--primary); font-weight: 600; }
13280
- .proposal-actions .acts form:first-child button[type=submit]:hover { background: color-mix(in srgb, var(--primary) 85%, var(--background)); border-color: color-mix(in srgb, var(--primary) 85%, var(--background)); }
13314
+ @media (hover: hover) and (pointer: fine) { .proposal-actions .acts form:first-child button[type=submit]:hover { background: color-mix(in srgb, var(--primary) 85%, var(--background)); border-color: color-mix(in srgb, var(--primary) 85%, var(--background)); } }
13281
13315
  .proposal-actions .done, .proposal-actions .refused, .proposal-wait { margin: 0; padding: .55rem .65rem; border-radius: calc(var(--radius) - 5px); font-size: .72rem; }
13282
13316
  .proposal-actions .done { color: var(--success); background: var(--success-soft); }
13283
13317
  .proposal-actions .refused { color: var(--destructive); background: var(--destructive-soft); }
@@ -13358,7 +13392,8 @@ ${THEME_DARK}
13358
13392
  width: 100%; min-height: 3.5rem; max-height: 13rem; margin: 0; padding: .75rem .85rem;
13359
13393
  resize: vertical; border: 0; background: transparent; box-shadow: none; font-size: 1rem;
13360
13394
  }
13361
- .composer textarea:hover, .composer textarea:focus-visible { border: 0; box-shadow: none; }
13395
+ .composer textarea:focus-visible { border: 0; box-shadow: none; }
13396
+ @media (hover: hover) and (pointer: fine) { .composer textarea:hover { border: 0; box-shadow: none; } }
13362
13397
  .composer button {
13363
13398
  flex: 0 0 2.75rem; width: 2.75rem; min-height: 2.75rem; padding: 0; border-radius: 999px;
13364
13399
  font-size: 0; box-shadow: 0 10px 24px -16px rgb(255 255 255 / .65);
@@ -13536,7 +13571,7 @@ ${THEME_DARK}
13536
13571
  .mate-mint form { border-top: 1px solid var(--glass-border); padding-top: .5rem; }
13537
13572
  /* The start act is the page's one primary (UI polish 2026-09-13). */
13538
13573
  .mate-mint form > button[type=submit] { background: var(--primary); color: var(--primary-foreground); border-color: var(--primary); font-weight: 600; }
13539
- .mate-mint form > button[type=submit]:hover { background: color-mix(in srgb, var(--primary) 85%, var(--background)); border-color: color-mix(in srgb, var(--primary) 85%, var(--background)); }
13574
+ @media (hover: hover) and (pointer: fine) { .mate-mint form > button[type=submit]:hover { background: color-mix(in srgb, var(--primary) 85%, var(--background)); border-color: color-mix(in srgb, var(--primary) 85%, var(--background)); } }
13540
13575
  .mate-terms { display: flex; flex-wrap: wrap; gap: 1rem; align-items: baseline; padding: .35rem 0; }
13541
13576
  .mate-terms .inline-field { white-space: nowrap; }
13542
13577
  button.quiet { background: transparent; color: var(--fg-muted); border-color: var(--border); }
@@ -13587,7 +13622,7 @@ ${THEME_DARK}
13587
13622
  display: block; padding: .58rem .65rem; margin: .16rem 0; border: 1px solid transparent;
13588
13623
  border-radius: calc(var(--radius) - 4px); color: inherit; text-decoration: none;
13589
13624
  }
13590
- .wb-row:hover { background: var(--card); border-color: var(--border); }
13625
+ @media (hover: hover) and (pointer: fine) { .wb-row:hover { background: var(--card); border-color: var(--border); } }
13591
13626
  .wb-row.wb-selected { background: var(--muted); border-color: var(--border); }
13592
13627
  .wb-row .wb-title { display: block; font-size: .8125rem; font-weight: 500; line-height: 1.35; }
13593
13628
  .wb-row .wb-meta { display: flex; align-items: center; gap: .3rem; flex-wrap: wrap; margin-top: .22rem; }
@@ -13649,7 +13684,7 @@ ${THEME_DARK}
13649
13684
  .icon-button svg { width: 1rem; height: 1rem; }
13650
13685
  .queue-card p { margin: 0; }
13651
13686
  .queue-card a { text-decoration: none; }
13652
- .queue-card a:hover { text-decoration: underline; }
13687
+ @media (hover: hover) and (pointer: fine) { .queue-card a:hover { text-decoration: underline; } }
13653
13688
  .queue-card .row + .row { margin-top: .125rem; border-bottom: none; }
13654
13689
  .queue-card p.row { padding: 0; border-bottom: none; }
13655
13690
  .tracks { margin-top: 1.5rem; }
@@ -13658,7 +13693,7 @@ ${THEME_DARK}
13658
13693
  .track-row p { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
13659
13694
  .track-row p .right { margin-left: auto; }
13660
13695
  .track-row a { text-decoration: none; }
13661
- .track-row a:hover { text-decoration: underline; }
13696
+ @media (hover: hover) and (pointer: fine) { .track-row a:hover { text-decoration: underline; } }
13662
13697
  .track-strip { display: inline-flex; gap: .3rem; align-items: center; vertical-align: middle; }
13663
13698
  .fire {
13664
13699
  display: inline-block; width: .65rem; height: .65rem; border-radius: 50%;
@@ -13777,7 +13812,7 @@ button { min-height: 44px; }
13777
13812
  padding: 0 .875rem; border: 1px solid var(--border); border-radius: 999px;
13778
13813
  text-decoration: none; color: var(--foreground); background: var(--card);
13779
13814
  }
13780
- .next-pager .skip:hover { border-color: color-mix(in srgb, var(--border) 60%, var(--muted-foreground)); }
13815
+ @media (hover: hover) and (pointer: fine) { .next-pager .skip:hover { border-color: color-mix(in srgb, var(--border) 60%, var(--muted-foreground)); } }
13781
13816
 
13782
13817
  /* Motion: only where a human caused the change — navigation, presses,
13783
13818
  overlays. Liveness swaps stay instant; the pulse dot is the one "alive"
@@ -13806,7 +13841,10 @@ button { min-height: 44px; }
13806
13841
  @media (prefers-reduced-motion: no-preference) {
13807
13842
  .tabbar a, .side nav a { transition: color .15s, background .15s; }
13808
13843
  button:active { transform: scale(.985); }
13809
- .palette, .kbd-help { animation: rise 120ms ease-out; }
13844
+ /* Anchor buttons press like buttons; nav links fill instead. The palette
13845
+ and shortcuts overlay are keyboard-summoned, so they appear at once. */
13846
+ .button-link, .side .new-task, .content .new-task, .result-feedback-link, .next-pager .skip { transition: transform 160ms var(--so-ease-out); }
13847
+ :is(.button-link, .side .new-task, .content .new-task, .result-feedback-link, .next-pager .skip):active { transform: scale(.985); }
13810
13848
  .chat-workspace.projects-open .chat-projects { animation: rise 200ms ease-out; }
13811
13849
  .chat-workspace.projects-open::before { animation: fade 180ms ease-out; }
13812
13850
  .switcher[open] .switcher-menu { animation: rise 160ms ease-out; }
@@ -13823,7 +13861,8 @@ button { min-height: 44px; }
13823
13861
  @media (prefers-reduced-motion: reduce) {
13824
13862
  *, *::before, *::after { animation: none !important; transition: none !important; }
13825
13863
  ::view-transition-group(*), ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
13826
- button:active, button:hover, .side nav a:hover, .chat-project-card:hover, .lane-card:hover, .decide-card:hover, .menu-row:hover { transform: none; }
13864
+ button:active, :is(.button-link, .side .new-task, .content .new-task, .result-feedback-link, .next-pager .skip):active { transform: none; }
13865
+ @media (hover: hover) and (pointer: fine) { button:hover, .side nav a:hover, .chat-project-card:hover, .lane-card:hover, .decide-card:hover, .menu-row:hover { transform: none; } }
13827
13866
  }
13828
13867
 
13829
13868
  /* The shortcuts overlay: display-only, toggled by the chrome layer, absent
@@ -13878,7 +13917,9 @@ button.pick-file { min-height: 1.75rem; padding: 0 .55rem; font-size: .75rem; }
13878
13917
  }
13879
13918
  `;
13880
13919
  /** Appearance: a three-way segmented switch, one tap per choice. */
13881
- const THEME_CONTROLS_CSS = `.task-repo select{width:100%;min-height:2.75rem;font-size:1rem}.task-repo-add{margin:.35rem .1rem .5rem}.task-repo-add a{display:inline-flex;align-items:center;min-height:2.25rem}details.result-request-open.result-request-form>summary{border:0;background:transparent;padding:.5rem 0;min-height:2.75rem;font-weight:600;display:list-item;list-style:revert}details.result-request-open.result-request-form>summary::-webkit-details-marker{display:revert}form.js-autosave button[type=submit]{display:none}.provider-row{border-bottom:1px solid var(--so-line);padding:.35rem 0}.provider-row:first-of-type{border-top:1px solid var(--so-line)}.provider-head{display:flex;align-items:center;gap:.75rem;margin:.4rem 0 0}.provider-status{display:inline-flex;align-items:center;gap:.4rem;color:var(--so-muted);font-size:.875rem}.provider-status i{width:.5rem;height:.5rem;border-radius:50%;background:var(--so-muted)}.provider-status--ok i{background:var(--so-success)}.provider-status--warn i{background:var(--so-attention)}.provider-status--off i{background:transparent;border:1.5px solid var(--so-muted)}details.provider-manage>summary{cursor:pointer;color:var(--so-accent-text);font-size:.875rem;min-height:2.5rem;display:list-item;padding-block:.5rem}.card.props .row{display:grid;gap:.1rem;margin:0 0 .75rem}.card.props .row>.meta{display:block;font-size:.75rem}.card.props .row>.meta::first-letter{text-transform:uppercase}.card.props .row>.mono{font-family:var(--font-sans);font-size:.875rem}.card.props .row>.mono .seal{font-family:var(--font-mono);font-size:.8125rem}details.evidence-files{margin:1rem 0}details.evidence-files>summary{cursor:pointer;min-height:2.75rem;display:list-item;padding-block:.7rem;font-weight:600}details.evidence-files ul{list-style:none;margin:0;padding:0}details.evidence-files li{display:flex;justify-content:space-between;gap:1rem;padding:.5rem 0;border-bottom:1px solid var(--so-line)}.result-action .result-feedback-link{display:inline-flex;align-items:center;min-height:2.5rem;padding:.5rem 1rem;border:1px solid var(--so-input-line);border-radius:.5rem;background:var(--so-paper);color:var(--so-ink);font-weight:600;text-decoration:none}.result-action .result-feedback-link:hover{background:var(--so-raised)}.so-sr-only{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.verdict{margin:.5rem 0 .75rem}.verdict-chips{display:flex;flex-wrap:wrap;gap:.4rem;list-style:none;padding:0;margin:0}.verdict-chip{display:inline-flex;align-items:center;gap:.3rem;min-height:1.75rem;padding:.2rem .65rem;border-radius:999px;font-size:.8125rem;font-weight:600;background:var(--so-neutral-soft);color:var(--so-neutral-ink)}.verdict-chip svg{width:.9rem;height:.9rem}.verdict-chip--success{background:var(--so-success-soft);color:var(--so-success)}.verdict-chip--danger{background:var(--so-danger-soft);color:var(--so-danger)}.verdict-chip--warning{background:var(--so-warning-soft);color:var(--so-warning)}.verdict-chip--info{background:var(--so-info-soft);color:var(--so-info)}.verdict-by{margin:.4rem 0 0}details.result-request-open{margin:.5rem 0}details.result-request-open>summary{display:inline-flex;align-items:center;min-height:2.5rem;padding:.5rem 1rem;border:1px solid var(--so-input-line);border-radius:.5rem;background:var(--so-paper);color:var(--so-ink);font-weight:600;cursor:pointer;list-style:none}details.result-request-open>summary::-webkit-details-marker{display:none}details.result-request-open[open]>summary{margin-bottom:.75rem}.settings-tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(8.5rem,1fr));gap:.5rem;margin:0 0 2rem}.settings-tiles a{display:flex;align-items:center;gap:.6rem;min-height:3rem;padding:.65rem .8rem;border:1px solid var(--so-line);border-radius:.625rem;background:var(--so-paper);color:var(--so-ink);text-decoration:none;font-weight:550;font-size:.875rem}.settings-tiles a:hover{border-color:var(--so-input-line);background:var(--so-raised)}.settings-tiles svg{width:1.1rem;height:1.1rem;flex-shrink:0;color:var(--so-accent-text)}details.settings-more{margin:.25rem 0 1.25rem}details.settings-more>summary{cursor:pointer;min-height:2.75rem;display:list-item;padding-block:.7rem;font-weight:550}details.settings-more>summary .meta{font-weight:400;margin-left:.35rem}.settings-changed{margin-top:-.25rem}.appearance{margin:0 0 28px}.appearance h2{margin:0 0 10px}.theme-switch{display:inline-flex;flex-wrap:nowrap;max-width:100%;gap:4px;padding:4px;margin:0;border:1px solid var(--so-line);border-radius:10px;background:var(--so-raised)}.theme-switch .theme-choice,.so-native-region .theme-switch .theme-choice{flex:1 1 0;width:auto;white-space:nowrap;min-height:40px;padding:8px 16px;border:0;border-radius:7px;background:transparent;color:var(--so-muted);font:inherit;font-weight:550;box-shadow:none;cursor:pointer}.theme-switch .theme-choice:hover{color:var(--so-ink)}.theme-switch .theme-choice[aria-pressed="true"]{background:var(--so-paper);color:var(--so-ink);box-shadow:0 1px 2px rgb(0 0 0 / .1)}.appearance .meta{margin:8px 0 0}@media(max-width:600px){.theme-switch .theme-choice{min-height:44px}}`;
13920
+ const THEME_CONTROLS_CSS = `.task-repo select{width:100%;min-height:2.75rem;font-size:1rem}.task-repo-add{margin:.35rem .1rem .5rem}.task-repo-add a{display:inline-flex;align-items:center;min-height:2.25rem}details.result-request-open.result-request-form>summary{border:0;background:transparent;padding:.5rem 0;min-height:2.75rem;font-weight:600;display:list-item;list-style:revert}details.result-request-open.result-request-form>summary::-webkit-details-marker{display:revert}form.js-autosave button[type=submit]{display:none}.provider-row{border-bottom:1px solid var(--so-line);padding:.35rem 0}.provider-row:first-of-type{border-top:1px solid var(--so-line)}.provider-head{display:flex;align-items:center;gap:.75rem;margin:.4rem 0 0}.provider-status{display:inline-flex;align-items:center;gap:.4rem;color:var(--so-muted);font-size:.875rem}.provider-status i{width:.5rem;height:.5rem;border-radius:50%;background:var(--so-muted)}.provider-status--ok i{background:var(--so-success)}.provider-status--warn i{background:var(--so-attention)}.provider-status--off i{background:transparent;border:1.5px solid var(--so-muted)}details.provider-manage>summary{cursor:pointer;color:var(--so-accent-text);font-size:.875rem;min-height:2.5rem;display:list-item;padding-block:.5rem}.card.props .row{display:grid;gap:.1rem;margin:0 0 .75rem}.card.props .row>.meta{display:block;font-size:.75rem}.card.props .row>.meta::first-letter{text-transform:uppercase}.card.props .row>.mono{font-family:var(--font-sans);font-size:.875rem}.card.props .row>.mono .seal{font-family:var(--font-mono);font-size:.8125rem}details.evidence-files{margin:1rem 0}details.evidence-files>summary{cursor:pointer;min-height:2.75rem;display:list-item;padding-block:.7rem;font-weight:600}details.evidence-files ul{list-style:none;margin:0;padding:0}details.evidence-files li{display:flex;justify-content:space-between;gap:1rem;padding:.5rem 0;border-bottom:1px solid var(--so-line)}.result-action .result-feedback-link{display:inline-flex;align-items:center;min-height:2.5rem;padding:.5rem 1rem;border:1px solid var(--so-input-line);border-radius:.5rem;background:var(--so-paper);color:var(--so-ink);font-weight:600;text-decoration:none}@media(hover:hover) and (pointer:fine){.result-action .result-feedback-link:hover{background:var(--so-raised)}}.so-sr-only{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.verdict{margin:.5rem 0 .75rem}.verdict-chips{display:flex;flex-wrap:wrap;gap:.4rem;list-style:none;padding:0;margin:0}.verdict-chip{display:inline-flex;align-items:center;gap:.3rem;min-height:1.75rem;padding:.2rem .65rem;border-radius:999px;font-size:.8125rem;font-weight:600;background:var(--so-neutral-soft);color:var(--so-neutral-ink)}.verdict-chip svg{width:.9rem;height:.9rem}.verdict-chip--success{background:var(--so-success-soft);color:var(--so-success)}.verdict-chip--danger{background:var(--so-danger-soft);color:var(--so-danger)}.verdict-chip--warning{background:var(--so-warning-soft);color:var(--so-warning)}.verdict-chip--info{background:var(--so-info-soft);color:var(--so-info)}.verdict-by{margin:.4rem 0 0}details.result-request-open{margin:.5rem 0}details.result-request-open>summary{display:inline-flex;align-items:center;min-height:2.5rem;padding:.5rem 1rem;border:1px solid var(--so-input-line);border-radius:.5rem;background:var(--so-paper);color:var(--so-ink);font-weight:600;cursor:pointer;list-style:none}details.result-request-open>summary::-webkit-details-marker{display:none}details.result-request-open[open]>summary{margin-bottom:.75rem}.settings-tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(8.5rem,1fr));gap:.5rem;margin:0 0 2rem}.settings-tiles a{display:flex;align-items:center;gap:.6rem;min-height:3rem;padding:.65rem .8rem;border:1px solid var(--so-line);border-radius:.625rem;background:var(--so-paper);color:var(--so-ink);text-decoration:none;font-weight:550;font-size:.875rem}@media(hover:hover) and (pointer:fine){.settings-tiles a:hover{border-color:var(--so-input-line);background:var(--so-raised)}}.settings-tiles svg{width:1.1rem;height:1.1rem;flex-shrink:0;color:var(--so-accent-text)}details.settings-more{margin:.25rem 0 1.25rem}details.settings-more>summary{cursor:pointer;min-height:2.75rem;display:list-item;padding-block:.7rem;font-weight:550}details.settings-more>summary .meta{font-weight:400;margin-left:.35rem}.settings-changed{margin-top:-.25rem}.appearance{margin:0 0 28px}.appearance h2{margin:0 0 10px}.theme-switch{display:inline-flex;flex-wrap:nowrap;max-width:100%;gap:4px;padding:4px;margin:0;border:1px solid var(--so-line);border-radius:10px;background:var(--so-raised)}.theme-switch .theme-choice,.so-native-region .theme-switch .theme-choice{flex:1 1 0;width:auto;white-space:nowrap;min-height:40px;padding:8px 16px;border:0;border-radius:7px;background:transparent;color:var(--so-muted);font:inherit;font-weight:550;box-shadow:none;cursor:pointer}@media(hover:hover) and (pointer:fine){.theme-switch .theme-choice:hover{color:var(--so-ink)}}.theme-switch .theme-choice[aria-pressed="true"]{background:var(--so-paper);color:var(--so-ink);box-shadow:0 1px 2px rgb(0 0 0 / .1)}.appearance .meta{margin:8px 0 0}@media(max-width:600px){.theme-switch .theme-choice{min-height:44px}}`;
13921
+ /** The page CSS this module writes itself (not the imported modules'), for the stylesheet contract tests. */
13922
+ export const PAGE_CSS = STYLE + THEME_CONTROLS_CSS;
13882
13923
  const WORKSPACE_STYLE = styleAsset(STYLE + APPROVAL_RULES_CSS + SPEND_CSS + RETENTION_CSS + LIMITS_CSS + MONITORING_CSS + BACKUP_CSS + EXPORT_CSS + PROJECT_DELETE_CSS + POLICY_CSS + EVIDENCE_PACK_CSS + THEME_CONTROLS_CSS + CODING_CSS + CODING_SHIPPING_CSS + RECIPE_CSS + SKILLS_CSS + TOOLS_CSS + FLOWS_CSS + TEAMMATE_CSS + KITS_CSS + SSO_CSS + CREDENTIALS_CSS + KNOWLEDGE_CSS + MODELS_CSS + CHAT_POLISH_CSS + TRANSITIONS_CSS + WORKSPACE_MOTION_CSS + ASSIGNMENT_CSS + LEAD_CONTEXT_CSS + '.learning{min-width:0;overflow-wrap:anywhere}.learning .card{min-width:0}.learning code,.learning blockquote,.learning pre{white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word}.learning button,.learning summary,.learning .button-link{min-height:44px}.learning button{white-space:nowrap}.learning summary{padding:12px 0;cursor:pointer}.learning form{margin:12px 0}.learning select{max-width:100%}.learning blockquote{margin:8px 0}.learning ul{padding-left:20px}');
13883
13924
  /**
13884
13925
  * The board's liveness: fetch this page's own fragment on a timer and swap
@@ -14126,8 +14167,8 @@ export const SENSITIVE_INPUT = /<input\b[^>]*[\s"']type\s*=\s*["']?password/i;
14126
14167
  /** The design contract every page carries (impeccable direction, 2026-09-27). */
14127
14168
  const DESIGN_CONTRACT = `<!-- THESIS: a control plane that stays quiet until a person is needed; it refuses the dashboard default of coloured status everywhere and an accent on every button.
14128
14169
  OWN-WORLD: a neutral grey frame with paper sheets inset into it (Arc, Linear), Geist for words and Geist Mono for machine facts, ink for every act a person can take, one chart magenta only for what waits on a person plus focus and selection; hairlines and one soft sheet shadow, no glass, no gradients.
14129
- STORY: glance, see the magenta count, open the one thing that needs you, act with the one magenta verb, leave.
14130
- FIRST VIEWPORT: sidebar on the frame (magenta mark, ink New task, the current page as a raised pill, the magenta needs-you count); the main sheet with a 52px header over compact 13px rows; the Crew sheet beside it.
14170
+ STORY: glance, see the accent count, open the one thing that needs you, act with the one accent verb, leave.
14171
+ FIRST VIEWPORT: sidebar on the frame (accent mark, ink New task, the current page as a raised pill, the accent needs-you count); the main sheet with a 52px header over compact 13px rows; the Crew sheet beside it.
14131
14172
  FORM: the Raycast and Arc canon, user-pinned; seed 9c849086.
14132
14173
  FINISH: unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, and DESIGN.md -->`;
14133
14174
  /** The shortcuts overlay: display-only, toggled by the chrome layer,
@@ -14284,7 +14325,9 @@ function shell(title, body, options = {}) {
14284
14325
  : "") +
14285
14326
  (chrome.modeBanner === undefined
14286
14327
  ? ""
14287
- : `<div class="banner"><span class="badge badge-running">mode</span>${escape(chrome.modeBanner.words)} \u00b7 <a href="/mode">the terms \u00b7 end it</a></div>`);
14328
+ : `<div class="banner"><span class="badge badge-running">mode</span>${escape(chrome.modeBanner.words)} \u00b7 <a href="/mode">the terms \u00b7 end it</a></div>`) +
14329
+ (chrome.signIn ?? []).map(one => `<div class="banner sign-in-banner" data-sign-in="${escape(one.provider)}"><strong>${escape(one.title)}</strong> \u00b7 run <code>${escape(one.command)}</code> on this computer, then resume.${one.detail === "" ? "" : ` ${escape(one.detail)}`}` +
14330
+ `<form method="post" action="${escape(one.resumeHref)}" class="inline"><input type="hidden" name="csrf" value="${escape(chrome.csrf ?? "")}"><button type="submit">${escape(one.resumeLabel)}</button></form></div>`).join("");
14288
14331
  // The scope bar sits between the banners and the main/split body, so it
14289
14332
  // can never disappear with a responsive pane (portfolio arc §1).
14290
14333
  const content = chrome.listPane === undefined
@@ -19744,6 +19787,7 @@ const REASON_WORDS = {
19744
19787
  agent: "the agent failed",
19745
19788
  "agent-reported": "the agent reported it could not finish",
19746
19789
  "no-op": "nothing changed when something should have",
19790
+ "no-handoff": "the agent stopped before handing off; its work was kept and it is being resumed",
19747
19791
  "moved-head": "the branch moved underneath the build",
19748
19792
  "moved-branch": "the branch moved underneath the build",
19749
19793
  timeout: "ran out of time",