inspector-ng 0.0.15 → 0.0.22

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, PLATFORM_ID, Inject, Injectable, signal, Optional, makeEnvironmentProviders, viewChild, inject, computed, HostListener, Input, ChangeDetectionStrategy, Component } from '@angular/core';
2
+ import { InjectionToken, PLATFORM_ID, Inject, Injectable, signal, Optional, makeEnvironmentProviders, viewChild, inject, computed, effect, HostListener, Input, ChangeDetectionStrategy, Component } from '@angular/core';
3
3
  import { isPlatformBrowser } from '@angular/common';
4
4
  import * as i2 from '@angular/router';
5
5
  import { Router } from '@angular/router';
@@ -14,6 +14,7 @@ const RESTORE_CHECKPOINT = '[Inspector Checkpoints] Restore';
14
14
  const DATABASE_NAME = 'inspector-ng';
15
15
  const DATABASE_VERSION = 1;
16
16
  const STORE_NAME = 'checkpoints';
17
+ const RESTORE_SETTLE_DELAY_MS = 100;
17
18
  const INSPECTOR_CHECKPOINT_REPOSITORY = new InjectionToken('INSPECTOR_CHECKPOINT_REPOSITORY');
18
19
  function inspectorCheckpointMetaReducer(reducer) {
19
20
  return (state, action) => {
@@ -168,6 +169,34 @@ class InspectorCheckpointService {
168
169
  this.busy.set(false);
169
170
  }
170
171
  }
172
+ async importCheckpoint(value) {
173
+ this.error.set(null);
174
+ if (!isCheckpointRecord(value)) {
175
+ this.error.set('The selected file is not a valid inspector-ng checkpoint. Expected a version 1 checkpoint JSON file.');
176
+ return null;
177
+ }
178
+ this.busy.set(true);
179
+ try {
180
+ const persisted = await this.repository.list();
181
+ const checkpoint = {
182
+ ...value,
183
+ id: createCheckpointId(),
184
+ name: nextAutomaticName(value.name, persisted.map(({ name }) => name)),
185
+ createdAt: new Date().toISOString(),
186
+ lastUsedAt: undefined,
187
+ };
188
+ await this.repository.put(checkpoint);
189
+ this.checkpoints.set([checkpoint, ...persisted].sort(recentActivityFirst));
190
+ return checkpoint;
191
+ }
192
+ catch (error) {
193
+ this.error.set(this.storageMessage(error, 'The checkpoint could not be imported.'));
194
+ return null;
195
+ }
196
+ finally {
197
+ this.busy.set(false);
198
+ }
199
+ }
171
200
  async restore(id) {
172
201
  this.error.set(null);
173
202
  if (!this.store) {
@@ -181,12 +210,14 @@ class InspectorCheckpointService {
181
210
  if (!checkpoint)
182
211
  throw new Error('Checkpoint not found. It may have been deleted in another tab.');
183
212
  const state = cloneJson(checkpoint.state, `“${checkpoint.name}” could not be decoded. Delete it and save a new checkpoint.`);
184
- this.store.dispatch({ type: RESTORE_CHECKPOINT, state });
213
+ this.restoreState(state);
185
214
  if (this.router &&
186
215
  this.router.url !== checkpoint.route &&
187
216
  !await this.router.navigateByUrl(checkpoint.route)) {
188
217
  throw new Error(`The state was restored, but navigation to “${checkpoint.route}” was cancelled.`);
189
218
  }
219
+ await delay(RESTORE_SETTLE_DELAY_MS);
220
+ this.restoreState(state);
190
221
  const recentlyUsedCheckpoint = {
191
222
  ...checkpoint,
192
223
  lastUsedAt: new Date().toISOString(),
@@ -205,6 +236,32 @@ class InspectorCheckpointService {
205
236
  this.busy.set(false);
206
237
  }
207
238
  }
239
+ async navigateToRoute(route) {
240
+ this.error.set(null);
241
+ if (!this.router) {
242
+ this.error.set('The Angular Router is unavailable, so the Inspector cannot navigate.');
243
+ return false;
244
+ }
245
+ this.busy.set(true);
246
+ try {
247
+ if (this.router.url !== route && !await this.router.navigateByUrl(route)) {
248
+ throw new Error(`Navigation to “${route}” was cancelled.`);
249
+ }
250
+ return true;
251
+ }
252
+ catch (error) {
253
+ this.error.set(this.messageFor(error, 'The route could not be opened.'));
254
+ return false;
255
+ }
256
+ finally {
257
+ this.busy.set(false);
258
+ }
259
+ }
260
+ resolveRoute(query) {
261
+ if (!isPlatformBrowser(this.platformId))
262
+ return null;
263
+ return resolveRouteQuery(query, this.currentPathname());
264
+ }
208
265
  async rename(id, name) {
209
266
  this.error.set(null);
210
267
  const nextName = name.trim();
@@ -252,6 +309,9 @@ class InspectorCheckpointService {
252
309
  clearError() {
253
310
  this.error.set(null);
254
311
  }
312
+ restoreState(state) {
313
+ this.store?.dispatch({ type: RESTORE_CHECKPOINT, state });
314
+ }
255
315
  currentRoute() {
256
316
  if (!isPlatformBrowser(this.platformId))
257
317
  return '/';
@@ -296,6 +356,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
296
356
  type: Inject,
297
357
  args: [PLATFORM_ID]
298
358
  }] }] });
359
+ function delay(milliseconds) {
360
+ return new Promise((resolve) => setTimeout(resolve, milliseconds));
361
+ }
299
362
  function provideInspectorCheckpoints() {
300
363
  return makeEnvironmentProviders([
301
364
  IndexedDbCheckpointRepository,
@@ -321,6 +384,25 @@ function nextAutomaticName(route, names) {
321
384
  return candidate;
322
385
  }
323
386
  }
387
+ function resolveRouteQuery(query, basePathname) {
388
+ const raw = query.trim();
389
+ if (!raw)
390
+ return null;
391
+ if (raw.startsWith('/'))
392
+ return raw;
393
+ if (raw === '.' || raw === '..' || raw.startsWith('./') || raw.startsWith('../')) {
394
+ const base = basePathname.startsWith('/') ? basePathname : `/${basePathname}`;
395
+ // Resolve against the current route as a directory: "./x" appends to it
396
+ // and "../x" moves up one route level, like Angular's relative navigation.
397
+ const directory = base.endsWith('/') ? base : `${base}/`;
398
+ const url = new URL(raw, `http://inspector.local${directory}`);
399
+ const pathname = url.pathname.length > 1 && url.pathname.endsWith('/')
400
+ ? url.pathname.slice(0, -1)
401
+ : url.pathname;
402
+ return `${pathname}${url.search}${url.hash}`;
403
+ }
404
+ return null;
405
+ }
324
406
  function cloneJson(value, failureMessage = 'The NgRx root state is not JSON-serializable. Remove circular or unsupported values and try again.') {
325
407
  try {
326
408
  const serialized = JSON.stringify(value);
@@ -386,7 +468,7 @@ const rectsEqual = (a, b, epsilon = 0.5) => {
386
468
  Math.abs(a.height - b.height) < epsilon);
387
469
  };
388
470
 
389
- const getDistanceOverlay = (rectA, rectB) => {
471
+ const getDistanceOverlay = (rectA, rectB, relation) => {
390
472
  const rightA = rectA.left + rectA.width;
391
473
  const bottomA = rectA.top + rectA.height;
392
474
  const rightB = rectB.left + rectB.width;
@@ -395,6 +477,8 @@ const getDistanceOverlay = (rectA, rectB) => {
395
477
  const centerAY = rectA.top + rectA.height / 2;
396
478
  let horizontal = null;
397
479
  let vertical = null;
480
+ let horizontalDistances = [];
481
+ let verticalDistances = [];
398
482
  const connectors = [];
399
483
  const separatedX = rightA <= rectB.left || rightB <= rectA.left;
400
484
  const separatedY = bottomA <= rectB.top || bottomB <= rectA.top;
@@ -404,6 +488,7 @@ const getDistanceOverlay = (rectA, rectB) => {
404
488
  const x2 = aIsLeft ? rectB.left : rectA.left;
405
489
  const y = centerAY;
406
490
  horizontal = { x1, x2, y, value: Math.abs(x2 - x1) };
491
+ horizontalDistances = [horizontal];
407
492
  const edgeBX = aIsLeft ? rectB.left : rightB;
408
493
  if (y < rectB.top) {
409
494
  connectors.push({ x1: edgeBX, y1: y, x2: edgeBX, y2: rectB.top });
@@ -418,6 +503,7 @@ const getDistanceOverlay = (rectA, rectB) => {
418
503
  const y2 = aIsTop ? rectB.top : rectA.top;
419
504
  const x = centerAX;
420
505
  vertical = { y1, y2, x, value: Math.abs(y2 - y1) };
506
+ verticalDistances = [vertical];
421
507
  const edgeBY = aIsTop ? rectB.top : bottomB;
422
508
  if (x < rectB.left) {
423
509
  connectors.push({ x1: x, y1: edgeBY, x2: rectB.left, y2: edgeBY });
@@ -426,12 +512,66 @@ const getDistanceOverlay = (rectA, rectB) => {
426
512
  connectors.push({ x1: x, y1: edgeBY, x2: rightB, y2: edgeBY });
427
513
  }
428
514
  }
515
+ if (!separatedX && !separatedY) {
516
+ const nestedRects = getNestedRects(rectA, rectB, relation);
517
+ if (nestedRects) {
518
+ const { inner, outer } = nestedRects;
519
+ const innerRight = inner.left + inner.width;
520
+ const innerBottom = inner.top + inner.height;
521
+ const outerRight = outer.left + outer.width;
522
+ const outerBottom = outer.top + outer.height;
523
+ const horizontalY = inner.top + inner.height / 2;
524
+ const verticalX = inner.left + inner.width / 2;
525
+ const startHorizontal = {
526
+ x1: outer.left,
527
+ x2: inner.left,
528
+ y: horizontalY,
529
+ value: inner.left - outer.left,
530
+ };
531
+ const endHorizontal = {
532
+ x1: innerRight,
533
+ x2: outerRight,
534
+ y: horizontalY,
535
+ value: outerRight - innerRight,
536
+ };
537
+ const startVertical = {
538
+ y1: outer.top,
539
+ y2: inner.top,
540
+ x: verticalX,
541
+ value: inner.top - outer.top,
542
+ };
543
+ const endVertical = {
544
+ y1: innerBottom,
545
+ y2: outerBottom,
546
+ x: verticalX,
547
+ value: outerBottom - innerBottom,
548
+ };
549
+ horizontalDistances = [startHorizontal, endHorizontal].filter(({ value }) => value > 0.5);
550
+ verticalDistances = [startVertical, endVertical].filter(({ value }) => value > 0.5);
551
+ const horizontalBoundary = nearestPositiveBoundary(startHorizontal.value, endHorizontal.value);
552
+ const verticalBoundary = nearestPositiveBoundary(startVertical.value, endVertical.value);
553
+ if (horizontalBoundary === 'start') {
554
+ horizontal = startHorizontal;
555
+ }
556
+ else if (horizontalBoundary === 'end') {
557
+ horizontal = endHorizontal;
558
+ }
559
+ if (verticalBoundary === 'start') {
560
+ vertical = startVertical;
561
+ }
562
+ else if (verticalBoundary === 'end') {
563
+ vertical = endVertical;
564
+ }
565
+ }
566
+ }
429
567
  const viewport = getViewportSize();
430
568
  return {
431
569
  rectA,
432
570
  rectB,
433
571
  horizontal,
434
572
  vertical,
573
+ horizontalDistances,
574
+ verticalDistances,
435
575
  connectors: connectors
436
576
  .map((segment) => ({
437
577
  x1: clamp(segment.x1, 0, viewport.width),
@@ -443,6 +583,30 @@ const getDistanceOverlay = (rectA, rectB) => {
443
583
  Math.abs(segment.y1 - segment.y2) > 0.5),
444
584
  };
445
585
  };
586
+ const getNestedRects = (rectA, rectB, relation) => {
587
+ if (relation === 'a-inside-b')
588
+ return { inner: rectA, outer: rectB };
589
+ if (relation === 'b-inside-a')
590
+ return { inner: rectB, outer: rectA };
591
+ if (containsRect(rectA, rectB))
592
+ return { inner: rectB, outer: rectA };
593
+ if (containsRect(rectB, rectA))
594
+ return { inner: rectA, outer: rectB };
595
+ return null;
596
+ };
597
+ const containsRect = (outer, inner) => inner.left >= outer.left &&
598
+ inner.top >= outer.top &&
599
+ inner.left + inner.width <= outer.left + outer.width &&
600
+ inner.top + inner.height <= outer.top + outer.height;
601
+ const nearestPositiveBoundary = (startDistance, endDistance) => {
602
+ const startIsPositive = startDistance > 0.5;
603
+ const endIsPositive = endDistance > 0.5;
604
+ if (!startIsPositive)
605
+ return endIsPositive ? 'end' : null;
606
+ if (!endIsPositive)
607
+ return 'start';
608
+ return startDistance <= endDistance ? 'start' : 'end';
609
+ };
446
610
 
447
611
  const getRectFromDom = (element) => {
448
612
  const rect = element.getBoundingClientRect();
@@ -771,11 +935,11 @@ const GENERATED_EXTRA_PET_SPRITES = {
771
935
 
772
936
  const INSPECTOR_COMMAND_ACTIONS = [
773
937
  { id: 'save', label: 'Save', ariaLabel: 'Save checkpoint', keywords: 'save checkpoint capture state' },
774
- { id: 'select', label: 'Select', ariaLabel: 'Select mode', keywords: 'select inspect pointer element' },
938
+ { id: 'import', label: 'Paste', ariaLabel: 'Import checkpoint from clipboard', keywords: 'import paste load open json checkpoint restore clipboard' },
775
939
  { id: 'type', label: 'Type', ariaLabel: 'Toggle typography overlay', keywords: 'type typography text overlay' },
776
940
  { id: 'vertical', label: 'V', ariaLabel: 'Vertical guides', keywords: 'vertical v guide guides' },
777
941
  { id: 'horizontal', label: 'H', ariaLabel: 'Horizontal guides', keywords: 'horizontal h guide guides' },
778
- { id: 'off', label: 'Off', ariaLabel: 'Disable inspector', keywords: 'off disable inspector power' },
942
+ { id: 'select', label: 'Inspect', ariaLabel: 'Inspect mode', keywords: 'inspect select pointer element alt i' },
779
943
  ];
780
944
  const INSPECTOR_PETS = [
781
945
  {
@@ -925,6 +1089,7 @@ class inspectorComponent {
925
1089
  this.overlayRoot = viewChild('overlayRoot');
926
1090
  this.checkpointDialog = viewChild('checkpointDialog');
927
1091
  this.checkpointSearch = viewChild('checkpointSearch');
1092
+ this.checkpointRename = viewChild('checkpointRename');
928
1093
  this.highlightColor = '#4f8cff';
929
1094
  this.guideColor = '#ff7a00';
930
1095
  this.hoverHighlightEnabled = true;
@@ -949,12 +1114,17 @@ class inspectorComponent {
949
1114
  return terms.every((term) => searchableText.includes(term));
950
1115
  });
951
1116
  });
952
- this.commandResultCount = computed(() => this.filteredCheckpoints().length + this.filteredInspectorActions().length);
1117
+ this.navigateTarget = computed(() => this.checkpointService?.resolveRoute(this.checkpointQuery()) ?? null);
1118
+ this.actionIndexOffset = computed(() => this.filteredCheckpoints().length + (this.navigateTarget() ? 1 : 0));
1119
+ this.commandResultCount = computed(() => this.actionIndexOffset() + this.filteredInspectorActions().length);
953
1120
  this.activeCommandResultId = computed(() => {
954
1121
  const checkpoint = this.filteredCheckpoints()[this.activeCommandIndex()];
955
1122
  if (checkpoint)
956
1123
  return `inspector-checkpoint-${checkpoint.id}`;
957
- const actionIndex = this.activeCommandIndex() - this.filteredCheckpoints().length;
1124
+ if (this.navigateTarget() && this.activeCommandIndex() === this.filteredCheckpoints().length) {
1125
+ return 'inspector-navigate';
1126
+ }
1127
+ const actionIndex = this.activeCommandIndex() - this.actionIndexOffset();
958
1128
  const action = this.filteredInspectorActions()[actionIndex];
959
1129
  return action ? `inspector-action-${action.id}` : null;
960
1130
  });
@@ -962,6 +1132,29 @@ class inspectorComponent {
962
1132
  this.toolMode = signal('none');
963
1133
  this.guideOrientation = signal('vertical');
964
1134
  this.guides = signal([]);
1135
+ this.guideDistances = computed(() => {
1136
+ const distances = [];
1137
+ const preview = this.guidePreview();
1138
+ const visibleGuides = preview
1139
+ ? [...this.guides(), preview]
1140
+ : this.guides();
1141
+ for (const orientation of ['vertical', 'horizontal']) {
1142
+ const positions = visibleGuides
1143
+ .filter((guide) => guide.orientation === orientation)
1144
+ .map((guide) => guide.position)
1145
+ .filter((position, index, allPositions) => allPositions.indexOf(position) === index)
1146
+ .sort((positionA, positionB) => positionA - positionB);
1147
+ for (let index = 1; index < positions.length; index += 1) {
1148
+ const start = positions[index - 1];
1149
+ const end = positions[index];
1150
+ const value = end - start;
1151
+ if (value > 0.5) {
1152
+ distances.push({ orientation, start, end, value });
1153
+ }
1154
+ }
1155
+ }
1156
+ return distances;
1157
+ });
965
1158
  this.hoverRect = signal(null);
966
1159
  this.selectedGuideId = signal(null);
967
1160
  this.selectedMeasurement = signal(null);
@@ -990,11 +1183,19 @@ class inspectorComponent {
990
1183
  this.draggingGuideId = null;
991
1184
  this.selectedElement = null;
992
1185
  this.hoverElement = null;
1186
+ this.hasSelectedPet = false;
993
1187
  this.toastTimer = null;
994
1188
  this.trackGuide = (_index, guide) => guide.id;
995
1189
  this.trackTextBlock = (_index, block) => block.id;
996
1190
  this.trackConnector = (_index, connector) => `${connector.x1}:${connector.y1}:${connector.x2}:${connector.y2}`;
997
1191
  this.isBrowser = isPlatformBrowser(platformId);
1192
+ effect(() => {
1193
+ if (!this.editingCheckpointId())
1194
+ return;
1195
+ const input = this.checkpointRename()?.nativeElement;
1196
+ input?.focus();
1197
+ input?.select();
1198
+ });
998
1199
  }
999
1200
  ngOnInit() {
1000
1201
  if (!this.isBrowser)
@@ -1050,9 +1251,57 @@ class inspectorComponent {
1050
1251
  this.showCheckpointToast(this.checkpointService.error(), true);
1051
1252
  }
1052
1253
  }
1254
+ downloadCheckpoint(checkpoint, event) {
1255
+ event?.stopPropagation();
1256
+ if (!this.isBrowser)
1257
+ return;
1258
+ const blob = new Blob([JSON.stringify(checkpoint, null, 2)], { type: 'application/json' });
1259
+ const url = URL.createObjectURL(blob);
1260
+ const anchor = document.createElement('a');
1261
+ anchor.href = url;
1262
+ anchor.download = this.checkpointFileName(checkpoint);
1263
+ document.body.appendChild(anchor);
1264
+ anchor.click();
1265
+ anchor.remove();
1266
+ URL.revokeObjectURL(url);
1267
+ this.showCheckpointToast(`Exported “${checkpoint.name}”.`);
1268
+ }
1269
+ async beginImport() {
1270
+ if (!this.checkpointService || this.checkpointService.busy())
1271
+ return;
1272
+ let text;
1273
+ try {
1274
+ text = await navigator.clipboard.readText();
1275
+ }
1276
+ catch {
1277
+ this.showCheckpointToast('Could not read clipboard.', true);
1278
+ return;
1279
+ }
1280
+ let parsed;
1281
+ try {
1282
+ parsed = JSON.parse(text);
1283
+ }
1284
+ catch {
1285
+ this.showCheckpointToast('The clipboard does not contain valid JSON.', true);
1286
+ return;
1287
+ }
1288
+ const checkpoint = await this.checkpointService.importCheckpoint(parsed);
1289
+ if (checkpoint) {
1290
+ this.showCheckpointToast(`Imported “${checkpoint.name}”.`);
1291
+ if (this.commandBarOpen()) {
1292
+ const index = this.filteredInspectorActions().findIndex(({ id }) => id === 'import');
1293
+ if (index >= 0)
1294
+ this.setActiveInspectorAction(index);
1295
+ }
1296
+ }
1297
+ else if (this.checkpointService.error()) {
1298
+ this.showCheckpointToast(this.checkpointService.error(), true);
1299
+ }
1300
+ }
1053
1301
  async openCheckpointCommandBar() {
1054
1302
  if (!this.checkpointService || !this.isBrowser || this.commandBarOpen())
1055
1303
  return;
1304
+ this.randomizePet();
1056
1305
  this.commandBarOpen.set(true);
1057
1306
  this.checkpointQuery.set('');
1058
1307
  this.activeCommandIndex.set(0);
@@ -1081,19 +1330,14 @@ class inspectorComponent {
1081
1330
  }
1082
1331
  cyclePet(event) {
1083
1332
  event?.stopPropagation();
1084
- this.petIndex.update((index) => (index + 1) % INSPECTOR_PETS.length);
1333
+ this.randomizePet();
1085
1334
  this.checkpointSearch()?.nativeElement.focus();
1086
1335
  }
1087
1336
  setActiveCheckpoint(index) {
1088
1337
  this.activeCommandIndex.set(index);
1089
1338
  }
1090
- shouldShowCheckpointRoute(checkpoint) {
1091
- if (!checkpoint.route.trim())
1092
- return false;
1093
- return this.normalizeCheckpointLabel(checkpoint.name) !== this.normalizeCheckpointLabel(checkpoint.route);
1094
- }
1095
1339
  setActiveInspectorAction(index) {
1096
- this.activeCommandIndex.set(this.filteredCheckpoints().length + index);
1340
+ this.activeCommandIndex.set(this.actionIndexOffset() + index);
1097
1341
  }
1098
1342
  async executeInspectorAction(action) {
1099
1343
  if (this.checkpointService?.busy())
@@ -1115,6 +1359,9 @@ class inspectorComponent {
1115
1359
  this.setActiveInspectorAction(index);
1116
1360
  }
1117
1361
  break;
1362
+ case 'import':
1363
+ await this.beginImport();
1364
+ break;
1118
1365
  case 'vertical':
1119
1366
  this.activateGuideOrientation('vertical');
1120
1367
  this.closeCheckpointCommandBar();
@@ -1123,10 +1370,6 @@ class inspectorComponent {
1123
1370
  this.activateGuideOrientation('horizontal');
1124
1371
  this.closeCheckpointCommandBar();
1125
1372
  break;
1126
- case 'off':
1127
- this.closeCheckpointCommandBar();
1128
- this.disableInspector();
1129
- break;
1130
1373
  }
1131
1374
  }
1132
1375
  async restoreCheckpoint(checkpoint) {
@@ -1139,6 +1382,37 @@ class inspectorComponent {
1139
1382
  this.commandBarOpen.set(false);
1140
1383
  this.showCheckpointToast(`Restored “${checkpoint.name}”.`);
1141
1384
  }
1385
+ activateCheckpoint(checkpoint, event) {
1386
+ if (this.deletingCheckpointId() === checkpoint.id ||
1387
+ this.editingCheckpointId() === checkpoint.id) {
1388
+ return;
1389
+ }
1390
+ if (event?.shiftKey) {
1391
+ void this.navigateToCheckpoint(checkpoint);
1392
+ }
1393
+ else {
1394
+ void this.restoreCheckpoint(checkpoint);
1395
+ }
1396
+ }
1397
+ async navigateToCheckpoint(checkpoint) {
1398
+ if (!this.checkpointService || this.checkpointService.busy())
1399
+ return;
1400
+ if (!await this.checkpointService.navigateToRoute(checkpoint.route))
1401
+ return;
1402
+ this.checkpointDialog()?.nativeElement.close();
1403
+ this.commandBarOpen.set(false);
1404
+ this.showCheckpointToast(`Navigated to “${checkpoint.route}” — state unchanged.`);
1405
+ }
1406
+ async navigateToQueryRoute() {
1407
+ const target = this.navigateTarget();
1408
+ if (!this.checkpointService || !target || this.checkpointService.busy())
1409
+ return;
1410
+ if (!await this.checkpointService.navigateToRoute(target))
1411
+ return;
1412
+ this.checkpointDialog()?.nativeElement.close();
1413
+ this.commandBarOpen.set(false);
1414
+ this.showCheckpointToast(`Navigated to “${target}” — state unchanged.`);
1415
+ }
1142
1416
  beginRename(checkpoint, event) {
1143
1417
  event?.stopPropagation();
1144
1418
  if (this.checkpointService?.busy())
@@ -1146,11 +1420,6 @@ class inspectorComponent {
1146
1420
  this.editingCheckpointId.set(checkpoint.id);
1147
1421
  this.deletingCheckpointId.set(null);
1148
1422
  this.renameDraft.set(checkpoint.name);
1149
- queueMicrotask(() => {
1150
- const input = this.checkpointDialog()?.nativeElement.querySelector('.inspector-command-row__rename');
1151
- input?.focus();
1152
- input?.select();
1153
- });
1154
1423
  }
1155
1424
  updateRenameDraft(event) {
1156
1425
  this.renameDraft.set(event.target.value);
@@ -1205,7 +1474,17 @@ class inspectorComponent {
1205
1474
  this.selectedGuideId.set(guide.id);
1206
1475
  }
1207
1476
  formatEdges(edges) {
1208
- return `${formatValue(edges.top)} ${formatValue(edges.right)} ${formatValue(edges.bottom)} ${formatValue(edges.left)}`;
1477
+ const top = String(formatValue(edges.top));
1478
+ const right = String(formatValue(edges.right));
1479
+ const bottom = String(formatValue(edges.bottom));
1480
+ const left = String(formatValue(edges.left));
1481
+ if (top === right && top === bottom && top === left)
1482
+ return top;
1483
+ if (top === bottom && right === left)
1484
+ return `${top} ${right}`;
1485
+ if (right === left)
1486
+ return `${top} ${right} ${bottom}`;
1487
+ return `${top} ${right} ${bottom} ${left}`;
1209
1488
  }
1210
1489
  formatGap(selected) {
1211
1490
  return `${formatValue(selected.gap.row)} / ${formatValue(selected.gap.column)}`;
@@ -1214,13 +1493,38 @@ class inspectorComponent {
1214
1493
  const key = event.key.toLowerCase();
1215
1494
  if (this.checkpointService &&
1216
1495
  !event.repeat &&
1217
- (event.metaKey || event.ctrlKey) &&
1218
- event.shiftKey &&
1496
+ event.altKey &&
1497
+ !event.ctrlKey &&
1498
+ !event.metaKey &&
1499
+ !event.shiftKey &&
1219
1500
  key === 'p') {
1220
1501
  event.preventDefault();
1221
1502
  this.commandBarOpen() ? this.closeCheckpointCommandBar() : void this.openCheckpointCommandBar();
1222
1503
  return;
1223
1504
  }
1505
+ if (!event.repeat &&
1506
+ event.altKey &&
1507
+ !event.ctrlKey &&
1508
+ !event.metaKey &&
1509
+ !event.shiftKey &&
1510
+ key === 'i') {
1511
+ event.preventDefault();
1512
+ this.setToolMode('select');
1513
+ if (this.commandBarOpen())
1514
+ this.closeCheckpointCommandBar();
1515
+ return;
1516
+ }
1517
+ if (this.checkpointService &&
1518
+ !event.repeat &&
1519
+ event.altKey &&
1520
+ !event.ctrlKey &&
1521
+ !event.metaKey &&
1522
+ !event.shiftKey &&
1523
+ key === 's') {
1524
+ event.preventDefault();
1525
+ void this.saveCheckpoint();
1526
+ return;
1527
+ }
1224
1528
  if (this.commandBarOpen()) {
1225
1529
  this.handleCommandBarKeydown(event, key);
1226
1530
  return;
@@ -1266,12 +1570,6 @@ class inspectorComponent {
1266
1570
  this.clearGuides();
1267
1571
  this.refreshTypographyBlocks();
1268
1572
  }
1269
- normalizeCheckpointLabel(value) {
1270
- return value
1271
- .trim()
1272
- .toLocaleLowerCase()
1273
- .replace(/^\/+|\/+$/g, '');
1274
- }
1275
1573
  handlePointerMove(event) {
1276
1574
  if (!this.enabled() || !this.isBrowser) {
1277
1575
  return;
@@ -1382,8 +1680,12 @@ class inspectorComponent {
1382
1680
  handleCommandBarKeydown(event, key) {
1383
1681
  const checkpoints = this.filteredCheckpoints();
1384
1682
  const actions = this.filteredInspectorActions();
1683
+ const navigateIndex = checkpoints.length;
1684
+ const hasNavigateRow = this.navigateTarget() !== null;
1385
1685
  const activeCheckpoint = checkpoints[this.activeCommandIndex()];
1386
- const activeActionIndex = this.activeCommandIndex() - checkpoints.length;
1686
+ const activeNavigateRow = hasNavigateRow && this.activeCommandIndex() === navigateIndex;
1687
+ const actionOffset = navigateIndex + (hasNavigateRow ? 1 : 0);
1688
+ const activeActionIndex = this.activeCommandIndex() - actionOffset;
1387
1689
  const activeAction = actions[activeActionIndex];
1388
1690
  const target = event.target;
1389
1691
  const isRenameInput = target?.classList?.contains('inspector-command-row__rename') ?? false;
@@ -1407,14 +1709,32 @@ class inspectorComponent {
1407
1709
  }
1408
1710
  if (isRenameInput)
1409
1711
  return;
1712
+ if (key === 'f2' && activeCheckpoint) {
1713
+ event.preventDefault();
1714
+ this.beginRename(activeCheckpoint);
1715
+ return;
1716
+ }
1717
+ if (key === 'delete' && activeCheckpoint) {
1718
+ event.preventDefault();
1719
+ void this.confirmDelete(activeCheckpoint);
1720
+ return;
1721
+ }
1410
1722
  if (key === 'arrowdown') {
1411
1723
  event.preventDefault();
1412
- if (activeCheckpoint) {
1724
+ if (activeAction && checkpoints.length) {
1725
+ this.activeCommandIndex.set(0);
1726
+ }
1727
+ else if (activeCheckpoint) {
1413
1728
  const nextIndex = this.activeCommandIndex() < checkpoints.length - 1
1414
1729
  ? this.activeCommandIndex() + 1
1415
- : actions.length ? checkpoints.length : this.activeCommandIndex();
1730
+ : hasNavigateRow
1731
+ ? navigateIndex
1732
+ : actions.length ? actionOffset : this.activeCommandIndex();
1416
1733
  this.activeCommandIndex.set(nextIndex);
1417
1734
  }
1735
+ else if (activeNavigateRow && actions.length) {
1736
+ this.activeCommandIndex.set(actionOffset);
1737
+ }
1418
1738
  this.scrollActiveCommandIntoView();
1419
1739
  return;
1420
1740
  }
@@ -1423,27 +1743,48 @@ class inspectorComponent {
1423
1743
  if (activeAction && checkpoints.length) {
1424
1744
  this.activeCommandIndex.set(checkpoints.length - 1);
1425
1745
  }
1746
+ else if (activeNavigateRow && checkpoints.length) {
1747
+ this.activeCommandIndex.set(checkpoints.length - 1);
1748
+ }
1426
1749
  else if (activeCheckpoint) {
1427
- this.activeCommandIndex.set(Math.max(0, this.activeCommandIndex() - 1));
1750
+ const nextIndex = this.activeCommandIndex() > 0
1751
+ ? this.activeCommandIndex() - 1
1752
+ : actions.length
1753
+ ? actionOffset + actions.length - 1
1754
+ : hasNavigateRow ? navigateIndex : 0;
1755
+ this.activeCommandIndex.set(nextIndex);
1428
1756
  }
1429
1757
  this.scrollActiveCommandIntoView();
1430
1758
  return;
1431
1759
  }
1432
- if (key === 'arrowright' && (activeCheckpoint || activeAction) && actions.length) {
1760
+ if (key === 'arrowright' && (activeCheckpoint || activeNavigateRow || activeAction) && actions.length) {
1433
1761
  event.preventDefault();
1434
1762
  const nextActionIndex = activeAction
1435
1763
  ? Math.min(activeActionIndex + 1, actions.length - 1)
1436
1764
  : 0;
1437
- this.activeCommandIndex.set(checkpoints.length + nextActionIndex);
1765
+ this.activeCommandIndex.set(actionOffset + nextActionIndex);
1438
1766
  this.scrollActiveCommandIntoView();
1439
1767
  return;
1440
1768
  }
1441
- if (key === 'arrowleft' && activeAction) {
1769
+ if (key === 'arrowleft' && (activeCheckpoint || activeNavigateRow || activeAction) && actions.length) {
1442
1770
  event.preventDefault();
1443
- this.activeCommandIndex.set(checkpoints.length + Math.max(0, activeActionIndex - 1));
1771
+ const nextActionIndex = activeAction
1772
+ ? (activeActionIndex - 1 + actions.length) % actions.length
1773
+ : actions.length - 1;
1774
+ this.activeCommandIndex.set(actionOffset + nextActionIndex);
1444
1775
  this.scrollActiveCommandIntoView();
1445
1776
  return;
1446
1777
  }
1778
+ if (key === 'enter' && event.shiftKey && activeCheckpoint && !this.deletingCheckpointId()) {
1779
+ event.preventDefault();
1780
+ void this.navigateToCheckpoint(activeCheckpoint);
1781
+ return;
1782
+ }
1783
+ if (key === 'enter' && activeNavigateRow) {
1784
+ event.preventDefault();
1785
+ void this.navigateToQueryRoute();
1786
+ return;
1787
+ }
1447
1788
  if (key === 'enter' && activeCheckpoint && !this.deletingCheckpointId()) {
1448
1789
  event.preventDefault();
1449
1790
  void this.restoreCheckpoint(activeCheckpoint);
@@ -1474,6 +1815,13 @@ class inspectorComponent {
1474
1815
  this.checkpointToastIsError.set(false);
1475
1816
  }, 2500);
1476
1817
  }
1818
+ checkpointFileName(checkpoint) {
1819
+ const safe = checkpoint.name
1820
+ .replace(/[\\/:*?"<>|]/g, '-')
1821
+ .replace(/^-+|-+$/g, '')
1822
+ .trim();
1823
+ return `${safe || 'checkpoint'}.json`;
1824
+ }
1477
1825
  selectElementAtPoint(event) {
1478
1826
  const overlay = this.overlayRoot()?.nativeElement ?? null;
1479
1827
  const target = getTargetElement({ x: event.clientX, y: event.clientY }, overlay);
@@ -1508,13 +1856,19 @@ class inspectorComponent {
1508
1856
  if (!this.altPressed() ||
1509
1857
  !this.selectedElement ||
1510
1858
  !this.hoverElement ||
1511
- this.selectedElement === this.hoverElement ||
1512
- this.selectedElement.contains(this.hoverElement) ||
1513
- this.hoverElement.contains(this.selectedElement)) {
1859
+ this.selectedElement === this.hoverElement) {
1514
1860
  this.distanceOverlay.set(null);
1515
1861
  return;
1516
1862
  }
1517
- this.distanceOverlay.set(getDistanceOverlay(getRectFromDom(this.selectedElement), getRectFromDom(this.hoverElement)));
1863
+ const relation = this.getDistanceRelation(this.selectedElement, this.hoverElement);
1864
+ this.distanceOverlay.set(getDistanceOverlay(getRectFromDom(this.selectedElement), getRectFromDom(this.hoverElement), relation));
1865
+ }
1866
+ getDistanceRelation(elementA, elementB) {
1867
+ if (elementB.contains(elementA))
1868
+ return 'a-inside-b';
1869
+ if (elementA.contains(elementB))
1870
+ return 'b-inside-a';
1871
+ return undefined;
1518
1872
  }
1519
1873
  refreshTypographyBlocks() {
1520
1874
  if (!this.isBrowser || !this.enabled() || !this.showTypography()) {
@@ -1536,6 +1890,17 @@ class inspectorComponent {
1536
1890
  },
1537
1891
  })));
1538
1892
  }
1893
+ randomizePet() {
1894
+ const currentIndex = this.hasSelectedPet ? this.petIndex() : null;
1895
+ const availableCount = currentIndex === null
1896
+ ? INSPECTOR_PETS.length
1897
+ : INSPECTOR_PETS.length - 1;
1898
+ const randomOffset = Math.floor(Math.random() * availableCount);
1899
+ this.petIndex.set(currentIndex === null
1900
+ ? randomOffset
1901
+ : (currentIndex + 1 + randomOffset) % INSPECTOR_PETS.length);
1902
+ this.hasSelectedPet = true;
1903
+ }
1539
1904
  addGuide(guide) {
1540
1905
  const nextGuides = [...this.guides(), guide];
1541
1906
  this.guides.set(nextGuides);
@@ -1592,11 +1957,11 @@ class inspectorComponent {
1592
1957
  return null;
1593
1958
  }
1594
1959
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: inspectorComponent, deps: [{ token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component }); }
1595
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: inspectorComponent, isStandalone: true, selector: "inspector-overlay", inputs: { highlightColor: "highlightColor", guideColor: "guideColor", hoverHighlightEnabled: "hoverHighlightEnabled" }, host: { listeners: { "window:keydown": "handleKeydown($event)", "window:keyup": "handleKeyup($event)", "window:pointermove": "handlePointerMove($event)", "window:pointerup": "handlePointerUp()", "window:click": "handleClick($event)", "window:resize": "handleViewportChange()", "window:scroll": "handleViewportChange()" } }, viewQueries: [{ propertyName: "overlayRoot", first: true, predicate: ["overlayRoot"], descendants: true, isSignal: true }, { propertyName: "checkpointDialog", first: true, predicate: ["checkpointDialog"], descendants: true, isSignal: true }, { propertyName: "checkpointSearch", first: true, predicate: ["checkpointSearch"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"inspector-root\" #overlayRoot>\n @if (checkpointService) {\n <dialog\n #checkpointDialog\n class=\"inspector-command-dialog\"\n aria-labelledby=\"inspector-command-title\"\n (cancel)=\"$event.preventDefault(); closeCheckpointCommandBar()\"\n (click)=\"handleCheckpointDialogClick($event)\"\n >\n <section class=\"inspector-command\" (click)=\"$event.stopPropagation()\">\n <header class=\"inspector-command__search\">\n <label\n id=\"inspector-command-title\"\n class=\"inspector-visually-hidden\"\n for=\"inspector-checkpoint-search\"\n >\n inspector-ng command palette\n </label>\n <button\n type=\"button\"\n class=\"inspector-command__pet-switcher\"\n [attr.aria-label]=\"'Change pet. Current pet: ' + activePet().name\"\n [title]=\"'Change pet: ' + activePet().name\"\n (click)=\"cyclePet($event)\"\n >\n <img\n class=\"inspector-command__pet-sprite\"\n [src]=\"activePet().spriteSrc\"\n alt=\"\"\n aria-hidden=\"true\"\n draggable=\"false\"\n />\n </button>\n <input\n #checkpointSearch\n id=\"inspector-checkpoint-search\"\n type=\"search\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n placeholder=\"inspector-ng\u2026\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"commandBarOpen()\"\n [value]=\"checkpointQuery()\"\n [attr.aria-controls]=\"'inspector-checkpoint-results inspector-command-actions'\"\n [attr.aria-activedescendant]=\"activeCommandResultId()\"\n (input)=\"updateCheckpointQuery($event)\"\n />\n </header>\n\n @if (checkpointService.error(); as error) {\n <p\n class=\"inspector-command__message inspector-command__message--error\"\n role=\"alert\"\n >\n {{ error }}\n </p>\n }\n\n <div\n id=\"inspector-checkpoint-results\"\n class=\"inspector-command__results\"\n role=\"listbox\"\n aria-label=\"Saved checkpoints\"\n >\n @if (checkpointService.loading()) {\n <p class=\"inspector-command__message\" role=\"status\">Loading\u2026</p>\n } @else if (\n !checkpointService.checkpoints().length && !checkpointQuery().trim()\n ) {\n <p class=\"inspector-command__message\" role=\"status\">\n No checkpoints yet\n </p>\n } @else if (\n !filteredCheckpoints().length && !filteredInspectorActions().length\n ) {\n <p class=\"inspector-command__message\" role=\"status\">No matches</p>\n } @else {\n @for (\n checkpoint of filteredCheckpoints();\n track checkpoint.id;\n let index = $index\n ) {\n <div\n class=\"inspector-command-row\"\n role=\"option\"\n [id]=\"'inspector-checkpoint-' + checkpoint.id\"\n [attr.data-command-index]=\"index\"\n [attr.aria-selected]=\"activeCommandIndex() === index\"\n [class.is-active]=\"activeCommandIndex() === index\"\n [class.is-busy]=\"\n checkpointService.busy() && activeCommandIndex() === index\n \"\n (mouseenter)=\"setActiveCheckpoint(index)\"\n (click)=\"\n deletingCheckpointId() === checkpoint.id ||\n editingCheckpointId() === checkpoint.id\n ? null\n : restoreCheckpoint(checkpoint)\n \"\n >\n @if (deletingCheckpointId() === checkpoint.id) {\n <span class=\"inspector-command-row__confirm\"\n >Delete \u201C{{ checkpoint.name }}\u201D?</span\n >\n <span class=\"inspector-command-row__confirm-actions\">\n <button\n type=\"button\"\n class=\"is-danger\"\n (click)=\"confirmDelete(checkpoint, $event)\"\n >\n Delete\n </button>\n <button type=\"button\" (click)=\"cancelDelete($event)\">\n Keep\n </button>\n </span>\n } @else if (editingCheckpointId() === checkpoint.id) {\n <input\n class=\"inspector-command-row__rename\"\n aria-label=\"Checkpoint name\"\n [value]=\"renameDraft()\"\n (input)=\"updateRenameDraft($event)\"\n (click)=\"$event.stopPropagation()\"\n />\n } @else {\n <span class=\"inspector-command-row__content\">\n <span class=\"inspector-command-row__name\">\n @if (\n checkpointService.busy() &&\n activeCommandIndex() === index\n ) {\n Restoring\u2026\n } @else {\n {{ checkpoint.name }}\n }\n </span>\n <span class=\"inspector-command-row__meta\">\n @if (shouldShowCheckpointRoute(checkpoint)) {\n <span class=\"inspector-command-row__route\">{{\n checkpoint.route\n }}</span>\n <span\n class=\"inspector-command-row__separator\"\n aria-hidden=\"true\"\n >\u00B7</span\n >\n }\n <span class=\"inspector-command-row__activity\">\n {{ checkpoint.lastUsedAt ? \"Used\" : \"Saved\" }}\n {{\n formatRelativeTime(checkpointActivityAt(checkpoint))\n }}\n </span>\n </span>\n </span>\n <span class=\"inspector-command-row__actions\">\n <button\n type=\"button\"\n (click)=\"beginRename(checkpoint, $event)\"\n [attr.aria-label]=\"'Rename ' + checkpoint.name\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"m11.8 1.8 2.4 2.4-8.3 8.3-3.1.7.7-3.1zm-8 10.4 1.5-.3-1.2-1.2z\"\n />\n </svg>\n </button>\n <button\n type=\"button\"\n (click)=\"beginDelete(checkpoint, $event)\"\n [attr.aria-label]=\"'Delete ' + checkpoint.name\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"M5.5 2h5l.5 1H14v1.25H2V3h3zm-2 3.25h9L12 14H4z\"\n />\n </svg>\n </button>\n </span>\n }\n </div>\n }\n }\n </div>\n\n @if (filteredInspectorActions().length) {\n <footer\n id=\"inspector-command-actions\"\n class=\"inspector-command__actions\"\n role=\"listbox\"\n aria-label=\"Inspector actions\"\n aria-orientation=\"horizontal\"\n >\n @for (\n action of filteredInspectorActions();\n track action.id;\n let index = $index\n ) {\n <button\n type=\"button\"\n role=\"option\"\n class=\"inspector-command-action\"\n [id]=\"'inspector-action-' + action.id\"\n [attr.data-command-index]=\"filteredCheckpoints().length + index\"\n [attr.aria-label]=\"action.ariaLabel\"\n [attr.aria-selected]=\"\n activeCommandIndex() === filteredCheckpoints().length + index\n \"\n [attr.aria-disabled]=\"checkpointService.busy()\"\n [class.is-selected]=\"\n activeCommandIndex() === filteredCheckpoints().length + index\n \"\n [class.is-active]=\"\n (action.id === 'select' && toolMode() === 'select') ||\n (action.id === 'type' && showTypography()) ||\n (action.id === 'vertical' &&\n toolMode() === 'guides' &&\n guideOrientation() === 'vertical') ||\n (action.id === 'horizontal' &&\n toolMode() === 'guides' &&\n guideOrientation() === 'horizontal')\n \"\n [class.inspector-command-action--danger]=\"action.id === 'off'\"\n [disabled]=\"checkpointService.busy()\"\n (mouseenter)=\"setActiveInspectorAction(index)\"\n (click)=\"executeInspectorAction(action)\"\n >\n @switch (action.id) {\n @case (\"select\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M3 2l8 8-3 .7L6.7 13 6 10 3 2z\" />\n </svg>\n }\n @case (\"type\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M3 4V2h10v2h-4v10H7V4z\" />\n </svg>\n }\n @case (\"save\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"M2.5 2h9.6l1.4 1.4V14h-11zm2 1.5v3h6v-3zm.5 6V12h6V9.5z\"\n />\n </svg>\n }\n @case (\"vertical\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M7.25 2h1.5v12h-1.5z\" />\n </svg>\n }\n @case (\"horizontal\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M2 7.25h12v1.5H2z\" />\n </svg>\n }\n @case (\"off\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"M7.25 1.5h1.5v6h-1.5zM4.1 3.35l.96 1.15A4.25 4.25 0 1 0 10.94 4.5l.96-1.15A5.75 5.75 0 1 1 4.1 3.35z\"\n />\n </svg>\n }\n }\n <span>{{ action.label }}</span>\n </button>\n }\n </footer>\n }\n </section>\n </dialog>\n }\n\n @if (checkpointToast(); as toast) {\n <p\n class=\"inspector-checkpoint-toast\"\n [class.inspector-checkpoint-toast--error]=\"checkpointToastIsError()\"\n [attr.role]=\"checkpointToastIsError() ? 'alert' : 'status'\"\n >\n {{ toast }}\n </p>\n }\n\n @if (enabled() && toolMode() === \"select\") {\n @if (hoverRect() && hoverHighlightEnabled) {\n <div\n class=\"inspector-box inspector-box--hover\"\n [style.left.px]=\"hoverRect()!.left\"\n [style.top.px]=\"hoverRect()!.top\"\n [style.width.px]=\"hoverRect()!.width\"\n [style.height.px]=\"hoverRect()!.height\"\n [style.--inspector-accent]=\"highlightColor\"\n ></div>\n }\n\n @if (selectedMeasurement(); as selected) {\n @if (selected.gap.active && selected.parentRect) {\n <div\n class=\"inspector-box inspector-box--gap\"\n [style.left.px]=\"selected.parentRect.left\"\n [style.top.px]=\"selected.parentRect.top\"\n [style.width.px]=\"selected.parentRect.width\"\n [style.height.px]=\"selected.parentRect.height\"\n ></div>\n <div\n class=\"inspector-box-tag inspector-box-tag--gap\"\n [style.left.px]=\"selected.parentRect.left\"\n [style.top.px]=\"selected.parentRect.top - 8\"\n >\n G {{ formatGap(selected) }}\n </div>\n }\n\n <div\n class=\"inspector-box inspector-box--margin\"\n [style.left.px]=\"selected.marginRect.left\"\n [style.top.px]=\"selected.marginRect.top\"\n [style.width.px]=\"selected.marginRect.width\"\n [style.height.px]=\"selected.marginRect.height\"\n ></div>\n <div\n class=\"inspector-box-tag inspector-box-tag--margin\"\n [style.left.px]=\"selected.marginRect.left\"\n [style.top.px]=\"selected.marginRect.top - 8\"\n >\n M {{ formatEdges(selected.margin) }}\n </div>\n\n <div\n class=\"inspector-box inspector-box--selected\"\n [style.left.px]=\"selected.rect.left\"\n [style.top.px]=\"selected.rect.top\"\n [style.width.px]=\"selected.rect.width\"\n [style.height.px]=\"selected.rect.height\"\n [style.--inspector-accent]=\"highlightColor\"\n >\n <div class=\"inspector-label\">{{ selectedMetaLine() }}</div>\n </div>\n\n <div\n class=\"inspector-box inspector-box--padding\"\n [style.left.px]=\"selected.paddingRect.left\"\n [style.top.px]=\"selected.paddingRect.top\"\n [style.width.px]=\"selected.paddingRect.width\"\n [style.height.px]=\"selected.paddingRect.height\"\n ></div>\n <div\n class=\"inspector-box-tag inspector-box-tag--padding\"\n [style.left.px]=\"selected.paddingRect.left\"\n [style.top.px]=\"\n selected.paddingRect.top + selected.paddingRect.height + 8\n \"\n >\n P {{ formatEdges(selected.padding) }}\n </div>\n }\n }\n\n @if (enabled() && showTypography()) {\n @for (block of textBlocks(); track block.id) {\n <div\n class=\"inspector-text-chip\"\n [style.left.px]=\"block.rect.left\"\n [style.top.px]=\"block.rect.top - 8\"\n >\n <span\n class=\"inspector-text-chip__swatch\"\n [style.background]=\"block.styles.color\"\n ></span>\n <span>{{ block.styles.fontSize }}</span>\n <span>{{ block.styles.lineHeight }}</span>\n <span>{{ block.styles.color }}</span>\n </div>\n }\n }\n\n @if (enabled() && altPressed() && distanceOverlay(); as distance) {\n <div\n class=\"inspector-box inspector-box--distance\"\n [style.left.px]=\"distance.rectA.left\"\n [style.top.px]=\"distance.rectA.top\"\n [style.width.px]=\"distance.rectA.width\"\n [style.height.px]=\"distance.rectA.height\"\n ></div>\n <div\n class=\"inspector-box inspector-box--distance\"\n [style.left.px]=\"distance.rectB.left\"\n [style.top.px]=\"distance.rectB.top\"\n [style.width.px]=\"distance.rectB.width\"\n [style.height.px]=\"distance.rectB.height\"\n ></div>\n\n @for (\n connector of distance.connectors;\n track trackConnector($index, connector)\n ) {\n <div\n class=\"inspector-connector\"\n [class.inspector-connector--vertical]=\"connector.x1 === connector.x2\"\n [class.inspector-connector--horizontal]=\"connector.y1 === connector.y2\"\n [style.left.px]=\"Math.min(connector.x1, connector.x2)\"\n [style.top.px]=\"Math.min(connector.y1, connector.y2)\"\n [style.width.px]=\"Math.max(1, Math.abs(connector.x2 - connector.x1))\"\n [style.height.px]=\"Math.max(1, Math.abs(connector.y2 - connector.y1))\"\n ></div>\n }\n\n @if (distance.horizontal && distance.horizontal.value > 0) {\n <div\n class=\"inspector-distance-line inspector-distance-line--horizontal\"\n [style.left.px]=\"\n Math.min(distance.horizontal.x1!, distance.horizontal.x2!)\n \"\n [style.top.px]=\"distance.horizontal.y!\"\n [style.width.px]=\"\n Math.abs(distance.horizontal.x2! - distance.horizontal.x1!)\n \"\n ></div>\n <div\n class=\"inspector-distance-tag\"\n [style.left.px]=\"\n (distance.horizontal.x1! + distance.horizontal.x2!) / 2\n \"\n [style.top.px]=\"distance.horizontal.y! + 10\"\n >\n {{ formatValue(distance.horizontal.value) }}\n </div>\n }\n\n @if (distance.vertical && distance.vertical.value > 0) {\n <div\n class=\"inspector-distance-line inspector-distance-line--vertical\"\n [style.left.px]=\"distance.vertical.x!\"\n [style.top.px]=\"Math.min(distance.vertical.y1!, distance.vertical.y2!)\"\n [style.height.px]=\"\n Math.abs(distance.vertical.y2! - distance.vertical.y1!)\n \"\n ></div>\n <div\n class=\"inspector-distance-tag inspector-distance-tag--vertical\"\n [style.left.px]=\"distance.vertical.x! + 10\"\n [style.top.px]=\"(distance.vertical.y1! + distance.vertical.y2!) / 2\"\n >\n {{ formatValue(distance.vertical.value) }}\n </div>\n }\n }\n\n @if (enabled()) {\n @if (toolMode() === \"guides\") {\n @if (guidePreview(); as preview) {\n <div\n class=\"inspector-guide inspector-guide--preview\"\n [class.inspector-guide--vertical]=\"preview.orientation === 'vertical'\"\n [class.inspector-guide--horizontal]=\"\n preview.orientation === 'horizontal'\n \"\n [style.left.px]=\"\n preview.orientation === 'vertical' ? preview.position : null\n \"\n [style.top.px]=\"\n preview.orientation === 'horizontal' ? preview.position : null\n \"\n [style.--inspector-guide]=\"guideColor\"\n >\n <span class=\"inspector-guide-line\"></span>\n </div>\n }\n }\n\n @for (guide of guides(); track guide.id) {\n <button\n type=\"button\"\n class=\"inspector-guide\"\n [class.inspector-guide--vertical]=\"guide.orientation === 'vertical'\"\n [class.inspector-guide--horizontal]=\"guide.orientation === 'horizontal'\"\n [class.inspector-guide--selected]=\"selectedGuideId() === guide.id\"\n [style.left.px]=\"\n guide.orientation === 'vertical' ? guide.position : null\n \"\n [style.top.px]=\"\n guide.orientation === 'horizontal' ? guide.position : null\n \"\n [style.--inspector-guide]=\"guideColor\"\n [attr.aria-label]=\"\n (guide.orientation === 'vertical' ? 'Vertical' : 'Horizontal') +\n ' guide at ' +\n formatValue(guide.position) +\n ' pixels'\n \"\n (pointerdown)=\"startGuideDrag($event, guide)\"\n >\n <span class=\"inspector-guide-line\"></span>\n </button>\n }\n }\n</div>\n", styles: [":host{--inspector-panel: oklch(20% .012 280 / .92);--inspector-panel-edge: oklch(100% 0 0 / .08);--inspector-text: oklch(96% .005 280);--inspector-muted: oklch(70% .014 280);--inspector-faint: oklch(56% .012 280);--inspector-blue: oklch(68% .15 255);--inspector-blue-soft: oklch(68% .15 255 / .14);--inspector-orange: oklch(78% .14 70);--inspector-green: oklch(74% .15 150);--inspector-violet: oklch(72% .15 305);--inspector-radius: 8px;--inspector-shadow: 0 12px 32px oklch(6% .02 280 / .5);--inspector-font: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;--inspector-ease: cubic-bezier(.16, 1, .3, 1);position:fixed;inset:0;z-index:2147;pointer-events:none;font-family:var(--inspector-font);color:var(--inspector-text);-webkit-font-smoothing:antialiased}.inspector-root{position:fixed;inset:0;pointer-events:none}.inspector-command-dialog{--command-surface: oklch(17.5% .012 280);--command-surface-active: oklch(25% .012 280);--command-edge: oklch(100% 0 0 / .08);--command-text: oklch(96% .005 280);--command-muted: oklch(68% .014 280);--command-faint: oklch(52% .012 280);--command-accent: oklch(72% .13 255);--command-danger: oklch(68% .17 25);box-sizing:border-box;inset-block-start:max(10vh,48px);width:min(420px,calc(100vw - 24px));max-width:none;max-height:min(360px,calc(100vh - 64px));margin:0 auto;padding:0;overflow:hidden;border:1px solid var(--command-edge);border-radius:var(--inspector-radius);background:var(--command-surface);color:var(--command-text);box-shadow:var(--inspector-shadow);opacity:0;pointer-events:auto;transform:translateY(-4px);transition:opacity .1s ease,transform .1s ease,overlay .1s allow-discrete,display .1s allow-discrete;font-family:var(--inspector-font);-webkit-font-smoothing:antialiased}.inspector-command-dialog[open]{opacity:1;transform:none;transition-duration:.14s;transition-timing-function:var(--inspector-ease)}@starting-style{.inspector-command-dialog[open]{opacity:0;transform:translateY(-4px)}}.inspector-command-dialog::backdrop{background:#01010266}.inspector-command{display:grid;grid-template-rows:auto auto 1fr auto;min-width:0;min-height:0;max-height:min(360px,calc(100vh - 64px))}.inspector-command__search{display:flex;align-items:center;gap:8px;min-height:40px;padding:0 11px;border-bottom:1px solid var(--command-edge)}.inspector-command__pet-switcher{display:block;width:28px;height:28px;flex:0 0 auto;padding:0;overflow:hidden;border:0;border-radius:4px;background:transparent;cursor:pointer;opacity:.72;transition:opacity .14s var(--inspector-ease),transform .1s var(--inspector-ease)}.inspector-command__pet-sprite{display:block;width:500%;height:100%;max-width:none;image-rendering:pixelated;-webkit-user-select:none;user-select:none;transform:translate(0)}.inspector-command__search:focus-within .inspector-command__pet-switcher,.inspector-command__pet-switcher:hover,.inspector-command__pet-switcher:focus-visible{opacity:1}.inspector-command__pet-switcher:hover,.inspector-command__pet-switcher:focus-visible{background:#6aa7f41f}.inspector-command__pet-switcher:active{transform:scale(.94)}.inspector-command__pet-switcher:focus-visible{outline:1px solid var(--command-accent);outline-offset:1px}@media (prefers-reduced-motion: no-preference){.inspector-command__search:focus-within .inspector-command__pet-sprite{animation:inspector-pet-cycle 1s steps(1,end) infinite}}@keyframes inspector-pet-cycle{0%,19.99%{transform:translate(0)}20%,39.99%{transform:translate(-20%)}40%,59.99%{transform:translate(-40%)}60%,79.99%{transform:translate(-60%)}80%,to{transform:translate(-80%)}}.inspector-command__search input,.inspector-command-row__rename{min-width:0;border:0;outline:0;background:transparent;color:var(--command-text);font:inherit}.inspector-command__search input{flex:1 1 auto;width:100%;height:39px;padding:0;font-size:13px;font-weight:450;line-height:1.3}.inspector-command__search input::placeholder{color:var(--command-faint);opacity:1}.inspector-command__search input::-webkit-search-cancel-button{display:none}.inspector-command__results{min-height:0;max-height:260px;overflow:auto;padding:5px;scrollbar-width:thin;scrollbar-color:oklch(100% 0 0 / .1) transparent}.inspector-command-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:6px;min-height:34px;padding:0 7px 0 9px;border-radius:5px;cursor:pointer;-webkit-user-select:none;user-select:none}.inspector-command-row.is-active{background:var(--command-surface-active);box-shadow:inset 0 0 0 1px #6aa7f49e}.inspector-command-row.is-busy{cursor:wait;pointer-events:none;opacity:.7}.inspector-command-row__content{display:flex;align-items:baseline;gap:8px;min-width:0;overflow:hidden}.inspector-command-row__name{flex:0 1 auto;min-width:3ch;overflow:hidden;color:var(--command-text);font-size:12px;font-weight:500;line-height:1.25;text-overflow:ellipsis;white-space:nowrap}.inspector-command-row__meta{display:inline-flex;flex:0 1 auto;align-items:baseline;gap:4px;min-width:0;overflow:hidden;color:var(--command-faint);font-size:11px;font-weight:400;line-height:1.25;text-overflow:ellipsis;white-space:nowrap}.inspector-command-row__route{min-width:0;overflow:hidden;text-overflow:ellipsis}.inspector-command-row__separator,.inspector-command-row__activity{flex:0 0 auto}.inspector-command-row.is-active .inspector-command-row__meta{color:#c2c3cc}.inspector-command-row__actions,.inspector-command-row__confirm-actions{display:flex;align-items:center;gap:1px}.inspector-command-row__actions{opacity:0;pointer-events:none}.inspector-command-row:hover .inspector-command-row__actions,.inspector-command-row:focus-within .inspector-command-row__actions{opacity:1;pointer-events:auto}.inspector-command-row button{display:inline-grid;width:22px;min-height:22px;padding:0;place-items:center;border:0;border-radius:4px;background:transparent;color:var(--command-muted);cursor:pointer;font-family:inherit;font-size:10px;font-weight:550;line-height:1.2}.inspector-command-row button svg{width:11px;height:11px;fill:currentColor}.inspector-command-row button:hover{background:#ffffff12;color:var(--command-text)}.inspector-command-row button.is-danger{width:auto;padding:0 7px;color:var(--command-danger);font-size:11px}.inspector-command-row button.is-danger:hover{background:#ef66611f}.inspector-command-row__confirm-actions button:not(.is-danger){width:auto;padding:0 7px;font-size:11px}.inspector-command-row button:focus-visible,.inspector-command-row__rename:focus-visible{outline:1px solid var(--command-accent);outline-offset:1px}.inspector-command-row__confirm{grid-column:1;color:var(--command-text);font-size:12px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.inspector-command-row__rename{grid-column:1 / -1;min-height:26px;padding-inline:6px;border:1px solid oklch(72% .13 255 / .4);border-radius:4px;background:#191a21;font-size:12px;font-weight:500}.inspector-command__message{margin:0;padding:16px 10px;color:var(--command-faint);font-size:12px;line-height:1.4;text-align:center}.inspector-command__message--error{padding:6px 10px;border-bottom:1px solid oklch(55% .08 25 / .3);background:#39191780;color:#f7cbc7;text-align:left;font-size:11px}.inspector-command__actions{display:flex;gap:2px;padding:4px;border-top:1px solid var(--command-edge)}.inspector-command-action{display:flex;flex:1 1 0;min-width:0;min-height:28px;align-items:center;justify-content:center;gap:4px;padding:0 4px;overflow:hidden;border:0;border-radius:5px;background:transparent;color:var(--command-muted);cursor:pointer;font:inherit;font-size:10px;font-weight:500;line-height:1;text-align:left}.inspector-command-action svg{width:11px;height:11px;flex:0 0 auto;fill:currentColor}.inspector-command-action span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.inspector-command-action:hover:not(:disabled){background:#ffffff0f;color:var(--command-text)}.inspector-command-action.is-active{background:#6aa7f421;color:#c2daf9}.inspector-command-action.is-selected,.inspector-command-action.is-selected:hover:not(:disabled){background:var(--command-surface-active);color:var(--command-text);box-shadow:inset 0 0 0 1px #6aa7f49e}.inspector-command-action--danger:hover:not(:disabled){background:#ef66611a;color:#f5b9b4}.inspector-command-action:disabled{cursor:wait;opacity:.45}.inspector-command-action:focus-visible{outline:1px solid var(--command-accent);outline-offset:-1px}.inspector-visually-hidden{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.inspector-checkpoint-toast{position:fixed;top:10px;left:50%;z-index:500;margin:0;padding:5px 10px;border:1px solid oklch(74% .12 150 / .25);border-radius:999px;background:#0e1f12f0;color:#cce6d0;box-shadow:var(--inspector-shadow);font-size:11px;font-weight:520;line-height:1.25;pointer-events:none;transform:translate(-50%)}.inspector-checkpoint-toast--error{border-color:#e2726b4d;background:#351311f0;color:#fed2cd}@media (prefers-reduced-motion: reduce){.inspector-command-dialog{transition-duration:.01ms!important}.inspector-command-dialog,.inspector-command-dialog[open]{transform:none}.inspector-command__pet-switcher{transition:none}.inspector-command__pet-sprite{animation:none;transform:translate(0)}}.inspector-box{position:fixed;box-sizing:border-box;pointer-events:none;border:1px solid var(--inspector-accent, var(--inspector-blue));background:color-mix(in srgb,var(--inspector-accent, var(--inspector-blue)) 8%,transparent)}.inspector-box--hover{opacity:.55}.inspector-box--selected{border-width:1.5px}.inspector-box--margin{border-color:#f0a646d1;background:#f0a64614}.inspector-box--padding{border-color:#5ac576d1;background:#5ac57614}.inspector-box--gap{border-color:#bb8aefb8;background:#bb8aef0d}.inspector-box--distance{border-style:dashed;border-color:#539af2b3;background:transparent}.inspector-label,.inspector-box-tag,.inspector-text-chip,.inspector-distance-tag{font-variant-numeric:tabular-nums}.inspector-label{position:absolute;left:0;top:0;transform:translateY(calc(-100% - 6px));max-width:min(380px,calc(100vw - 20px));padding:4px 7px;border-radius:999px;border:1px solid var(--inspector-panel-edge);background:var(--inspector-panel);color:var(--inspector-text);box-shadow:var(--inspector-shadow);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);font-size:10px;font-weight:500;line-height:1.2;white-space:nowrap}.inspector-box-tag{position:fixed;transform:translateY(-100%);padding:3px 5px;border-radius:999px;border:1px solid var(--inspector-panel-edge);background:#0e0f15f0;color:var(--inspector-text);font-size:9px;font-weight:520;line-height:1;pointer-events:none}.inspector-box-tag--margin{color:#f5c076}.inspector-box-tag--padding{color:#95dfa4;transform:translateY(0)}.inspector-box-tag--gap{color:oklch(86% .09 305)}.inspector-text-chip{position:fixed;transform:translateY(-100%);display:inline-flex;gap:5px;align-items:center;padding:3px 6px;border-radius:999px;border:1px solid var(--inspector-panel-edge);background:#0e0f15f0;color:#e4e4e9;font-size:9px;font-weight:500;line-height:1;white-space:nowrap;pointer-events:none}.inspector-text-chip__swatch{width:7px;height:7px;border-radius:999px;border:1px solid oklch(100% 0 0 / .16);flex:0 0 auto}.inspector-connector{position:fixed;border-color:#539af2b8;border-style:dashed;pointer-events:none}.inspector-connector--vertical{border-left-width:1px;width:0}.inspector-connector--horizontal{border-top-width:1px;height:0}.inspector-distance-line{position:fixed;background:var(--inspector-blue);pointer-events:none}.inspector-distance-line--horizontal{height:1px}.inspector-distance-line--vertical{width:1px}.inspector-distance-tag{position:fixed;transform:translate(-50%);padding:3px 6px;border-radius:999px;border:1px solid var(--inspector-panel-edge);background:#0e0f15f2;color:var(--inspector-text);font-size:9px;font-weight:520;line-height:1;pointer-events:none}.inspector-distance-tag--vertical{transform:translateY(-50%)}.inspector-guide{position:fixed;margin:0;padding:0;border:0;background:transparent;pointer-events:auto;cursor:grab}.inspector-guide--vertical{top:0;width:14px;height:100vh;transform:translate(-50%)}.inspector-guide--horizontal{left:0;width:100vw;height:14px;transform:translateY(-50%)}.inspector-guide--preview{opacity:.55;pointer-events:none;cursor:default}.inspector-guide--preview .inspector-guide-line{background:color-mix(in srgb,var(--inspector-guide, #ff7a00) 72%,transparent)}.inspector-guide-line{position:absolute;inset:0;pointer-events:none}.inspector-guide--vertical .inspector-guide-line{left:calc(50% - .5px);width:1px;height:100%;background:var(--inspector-guide, #ff7a00)}.inspector-guide--horizontal .inspector-guide-line{top:calc(50% - .5px);width:100%;height:1px;background:var(--inspector-guide, #ff7a00)}.inspector-guide--selected .inspector-guide-line{box-shadow:0 0 0 1px #ffffff80}@media (min-width: 769px) and (min-height: 769px){:host{--inspector-radius: 14px;--inspector-shadow: 0 21px 56px oklch(6% .02 280 / .5)}.inspector-command-dialog{inset-block-start:max(10vh,84px);width:min(735px,calc(100vw - 42px));max-height:min(630px,calc(100vh - 112px))}.inspector-command{max-height:min(630px,calc(100vh - 112px))}.inspector-command__search{gap:14px;min-height:70px;padding:0 19.25px}.inspector-command__pet-switcher{width:42px;height:42px}.inspector-command__search input{height:68.25px;font-size:22.75px}.inspector-command__results{max-height:455px;padding:8.75px}.inspector-command-row{gap:10.5px;min-height:59.5px;padding:0 12.25px 0 15.75px;border-radius:8.75px}.inspector-command-row__content{gap:14px}.inspector-command-row__name,.inspector-command-row__confirm{font-size:21px}.inspector-command-row__meta{gap:7px;font-size:19.25px}.inspector-command-row__actions,.inspector-command-row__confirm-actions{gap:1.75px}.inspector-command-row button{width:38.5px;min-height:38.5px;border-radius:7px;font-size:17.5px}.inspector-command-row button svg{width:19.25px;height:19.25px}.inspector-command-row button.is-danger,.inspector-command-row__confirm-actions button:not(.is-danger){padding:0 12.25px;font-size:19.25px}.inspector-command-row__rename{min-height:45.5px;padding-inline:10.5px;border-radius:7px;font-size:21px}.inspector-command__message{padding:28px 17.5px;font-size:21px}.inspector-command__message--error{padding:10.5px 17.5px;font-size:19.25px}.inspector-command__actions{gap:3.5px;padding:7px}.inspector-command-action{min-height:49px;gap:7px;padding:0 7px;border-radius:8.75px;font-size:17.5px}.inspector-command-action svg{width:19.25px;height:19.25px}.inspector-checkpoint-toast{top:17.5px;padding:8.75px 17.5px;font-size:19.25px}.inspector-label{transform:translateY(calc(-100% - 10.5px));max-width:min(665px,calc(100vw - 35px));padding:7px 12.25px;font-size:17.5px}.inspector-box-tag{padding:5.25px 8.75px;font-size:15.75px}.inspector-box-tag--padding{transform:translateY(0)}.inspector-text-chip{gap:8.75px;padding:5.25px 10.5px;font-size:15.75px}.inspector-text-chip__swatch{width:12.25px;height:12.25px}.inspector-distance-tag{padding:5.25px 10.5px;font-size:15.75px}.inspector-guide--vertical{width:24.5px}.inspector-guide--horizontal{height:24.5px}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1960
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: inspectorComponent, isStandalone: true, selector: "inspector-overlay", inputs: { highlightColor: "highlightColor", guideColor: "guideColor", hoverHighlightEnabled: "hoverHighlightEnabled" }, host: { listeners: { "window:keydown": "handleKeydown($event)", "window:keyup": "handleKeyup($event)", "window:pointermove": "handlePointerMove($event)", "window:pointerup": "handlePointerUp()", "window:click": "handleClick($event)", "window:resize": "handleViewportChange()", "window:scroll": "handleViewportChange()" } }, viewQueries: [{ propertyName: "overlayRoot", first: true, predicate: ["overlayRoot"], descendants: true, isSignal: true }, { propertyName: "checkpointDialog", first: true, predicate: ["checkpointDialog"], descendants: true, isSignal: true }, { propertyName: "checkpointSearch", first: true, predicate: ["checkpointSearch"], descendants: true, isSignal: true }, { propertyName: "checkpointRename", first: true, predicate: ["checkpointRename"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"inspector-root\" #overlayRoot>\n @if (checkpointService) {\n <dialog\n #checkpointDialog\n class=\"inspector-command-dialog\"\n aria-labelledby=\"inspector-command-title\"\n (cancel)=\"$event.preventDefault(); closeCheckpointCommandBar()\"\n (click)=\"handleCheckpointDialogClick($event)\"\n >\n <section class=\"inspector-command\" (click)=\"$event.stopPropagation()\">\n <header class=\"inspector-command__search\">\n <label\n id=\"inspector-command-title\"\n class=\"inspector-visually-hidden\"\n for=\"inspector-checkpoint-search\"\n >\n inspector-ng command palette\n </label>\n <button\n type=\"button\"\n class=\"inspector-command__pet-switcher\"\n [attr.aria-label]=\"'Change pet. Current pet: ' + activePet().name\"\n [title]=\"'Change pet: ' + activePet().name\"\n (click)=\"cyclePet($event)\"\n >\n <img\n class=\"inspector-command__pet-sprite\"\n [src]=\"activePet().spriteSrc\"\n alt=\"\"\n aria-hidden=\"true\"\n draggable=\"false\"\n />\n </button>\n <input\n #checkpointSearch\n id=\"inspector-checkpoint-search\"\n type=\"search\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n placeholder=\"inspector-ng\u2026\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"commandBarOpen()\"\n [value]=\"checkpointQuery()\"\n [attr.aria-controls]=\"'inspector-checkpoint-results inspector-command-actions'\"\n [attr.aria-activedescendant]=\"activeCommandResultId()\"\n (input)=\"updateCheckpointQuery($event)\"\n />\n </header>\n\n @if (checkpointService.error(); as error) {\n <p\n class=\"inspector-command__message inspector-command__message--error\"\n role=\"alert\"\n >\n {{ error }}\n </p>\n }\n\n <div\n id=\"inspector-checkpoint-results\"\n class=\"inspector-command__results\"\n role=\"listbox\"\n aria-label=\"Saved checkpoints\"\n >\n @if (checkpointService.loading()) {\n <p class=\"inspector-command__message\" role=\"status\">Loading\u2026</p>\n } @else if (\n !checkpointService.checkpoints().length && !checkpointQuery().trim()\n ) {\n <p class=\"inspector-command__message\" role=\"status\">\n No checkpoints yet\n </p>\n } @else if (\n !filteredCheckpoints().length &&\n !filteredInspectorActions().length &&\n !navigateTarget()\n ) {\n <p class=\"inspector-command__message\" role=\"status\">No matches</p>\n } @else {\n @for (\n checkpoint of filteredCheckpoints();\n track checkpoint.id;\n let index = $index\n ) {\n <div\n class=\"inspector-command-row\"\n role=\"option\"\n [id]=\"'inspector-checkpoint-' + checkpoint.id\"\n [attr.data-command-index]=\"index\"\n [attr.aria-selected]=\"activeCommandIndex() === index\"\n [class.is-active]=\"activeCommandIndex() === index\"\n [class.is-busy]=\"\n checkpointService.busy() && activeCommandIndex() === index\n \"\n (mouseenter)=\"setActiveCheckpoint(index)\"\n (click)=\"activateCheckpoint(checkpoint, $event)\"\n >\n @if (deletingCheckpointId() === checkpoint.id) {\n <span class=\"inspector-command-row__confirm\"\n >Delete \u201C{{ checkpoint.name }}\u201D?</span\n >\n <span class=\"inspector-command-row__confirm-actions\">\n <button\n type=\"button\"\n class=\"is-danger\"\n (click)=\"confirmDelete(checkpoint, $event)\"\n >\n Delete\n </button>\n <button type=\"button\" (click)=\"cancelDelete($event)\">\n Keep\n </button>\n </span>\n } @else if (editingCheckpointId() === checkpoint.id) {\n <input\n #checkpointRename\n class=\"inspector-command-row__rename\"\n aria-label=\"Checkpoint name\"\n [value]=\"renameDraft()\"\n (input)=\"updateRenameDraft($event)\"\n (click)=\"$event.stopPropagation()\"\n />\n } @else {\n <span class=\"inspector-command-row__content\">\n <span\n class=\"inspector-command-row__name\"\n [title]=\"checkpoint.name\"\n >\n <bdi dir=\"ltr\">\n @if (\n checkpointService.busy() &&\n activeCommandIndex() === index\n ) {\n Restoring\u2026\n } @else {\n {{ checkpoint.name }}\n }\n </bdi>\n </span>\n <span class=\"inspector-command-row__activity\">\n {{ checkpoint.lastUsedAt ? \"Used\" : \"Saved\" }}\n {{\n formatRelativeTime(checkpointActivityAt(checkpoint))\n }}\n </span>\n </span>\n <span class=\"inspector-command-row__actions\">\n <button\n type=\"button\"\n (click)=\"beginRename(checkpoint, $event)\"\n [attr.aria-label]=\"'Rename ' + checkpoint.name\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"m11.8 1.8 2.4 2.4-8.3 8.3-3.1.7.7-3.1zm-8 10.4 1.5-.3-1.2-1.2z\"\n />\n </svg>\n </button>\n <button\n type=\"button\"\n (click)=\"downloadCheckpoint(checkpoint, $event)\"\n [attr.aria-label]=\"'Export ' + checkpoint.name\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"M7.25 2h1.5v5.44l1.72-1.72L11.53 6.78 8 10.31 4.47 6.78l1.06-1.06 1.72 1.72zM2.5 12h11v1.5h-11z\"\n />\n </svg>\n </button>\n <button\n type=\"button\"\n (click)=\"beginDelete(checkpoint, $event)\"\n [attr.aria-label]=\"'Delete ' + checkpoint.name\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"M5.5 2h5l.5 1H14v1.25H2V3h3zm-2 3.25h9L12 14H4z\"\n />\n </svg>\n </button>\n </span>\n }\n </div>\n }\n @if (navigateTarget(); as target) {\n <div\n class=\"inspector-command-row inspector-command-row--navigate\"\n role=\"option\"\n id=\"inspector-navigate\"\n [attr.data-command-index]=\"filteredCheckpoints().length\"\n [attr.aria-selected]=\"\n activeCommandIndex() === filteredCheckpoints().length\n \"\n [class.is-active]=\"\n activeCommandIndex() === filteredCheckpoints().length\n \"\n [class.is-busy]=\"\n checkpointService.busy() &&\n activeCommandIndex() === filteredCheckpoints().length\n \"\n (mouseenter)=\"setActiveCheckpoint(filteredCheckpoints().length)\"\n (click)=\"navigateToQueryRoute()\"\n >\n <span class=\"inspector-command-row__content\">\n <span\n class=\"inspector-command-row__name\"\n [title]=\"'Navigate to ' + target\"\n >\n <bdi dir=\"ltr\">\n @if (\n checkpointService.busy() &&\n activeCommandIndex() === filteredCheckpoints().length\n ) {\n Navigating\u2026\n } @else {\n Go to {{ target }}\n }\n </bdi>\n </span>\n <span class=\"inspector-command-row__activity\">\n navigate \u00B7 keeps state\n </span>\n </span>\n </div>\n }\n }\n </div>\n\n @if (filteredInspectorActions().length) {\n <footer\n id=\"inspector-command-actions\"\n class=\"inspector-command__actions\"\n role=\"listbox\"\n aria-label=\"Inspector actions\"\n aria-orientation=\"horizontal\"\n >\n @for (\n action of filteredInspectorActions();\n track action.id;\n let index = $index\n ) {\n <button\n type=\"button\"\n role=\"option\"\n class=\"inspector-command-action\"\n [id]=\"'inspector-action-' + action.id\"\n [attr.data-command-index]=\"actionIndexOffset() + index\"\n [attr.aria-label]=\"action.ariaLabel\"\n [attr.aria-selected]=\"\n activeCommandIndex() === actionIndexOffset() + index\n \"\n [attr.aria-disabled]=\"checkpointService.busy()\"\n [class.is-selected]=\"\n activeCommandIndex() === actionIndexOffset() + index\n \"\n [class.is-active]=\"\n (action.id === 'select' && toolMode() === 'select') ||\n (action.id === 'type' && showTypography()) ||\n (action.id === 'vertical' &&\n toolMode() === 'guides' &&\n guideOrientation() === 'vertical') ||\n (action.id === 'horizontal' &&\n toolMode() === 'guides' &&\n guideOrientation() === 'horizontal')\n \"\n [disabled]=\"checkpointService.busy()\"\n (mouseenter)=\"setActiveInspectorAction(index)\"\n (click)=\"executeInspectorAction(action)\"\n >\n @switch (action.id) {\n @case (\"select\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M3 2l8 8-3 .7L6.7 13 6 10 3 2z\" />\n </svg>\n }\n @case (\"type\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M3 4V2h10v2h-4v10H7V4z\" />\n </svg>\n }\n @case (\"save\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"M2.5 2h9.6l1.4 1.4V14h-11zm2 1.5v3h6v-3zm.5 6V12h6V9.5z\"\n />\n </svg>\n }\n @case (\"import\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"M8 2l3.53 3.53-1.06 1.06L8.75 4.87V9.5h-1.5V4.87L5.53 6.59 4.47 5.53zM2.5 11h11v1.5h-11z\"\n />\n </svg>\n }\n @case (\"vertical\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M7.25 2h1.5v12h-1.5z\" />\n </svg>\n }\n @case (\"horizontal\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M2 7.25h12v1.5H2z\" />\n </svg>\n }\n }\n <span>{{ action.label }}</span>\n </button>\n }\n </footer>\n }\n </section>\n </dialog>\n }\n\n @if (checkpointToast(); as toast) {\n <p\n class=\"inspector-checkpoint-toast\"\n [class.inspector-checkpoint-toast--error]=\"checkpointToastIsError()\"\n [attr.role]=\"checkpointToastIsError() ? 'alert' : 'status'\"\n >\n {{ toast }}\n </p>\n }\n\n @if (enabled() && toolMode() === \"select\") {\n @if (hoverRect() && hoverHighlightEnabled) {\n <div\n class=\"inspector-box inspector-box--hover\"\n [style.left.px]=\"hoverRect()!.left\"\n [style.top.px]=\"hoverRect()!.top\"\n [style.width.px]=\"hoverRect()!.width\"\n [style.height.px]=\"hoverRect()!.height\"\n [style.--inspector-accent]=\"highlightColor\"\n ></div>\n }\n\n @if (selectedMeasurement(); as selected) {\n @if (selected.gap.active && selected.parentRect) {\n <div\n class=\"inspector-box inspector-box--gap\"\n [style.left.px]=\"selected.parentRect.left\"\n [style.top.px]=\"selected.parentRect.top\"\n [style.width.px]=\"selected.parentRect.width\"\n [style.height.px]=\"selected.parentRect.height\"\n ></div>\n <div\n class=\"inspector-box-tag inspector-box-tag--gap\"\n [style.left.px]=\"selected.parentRect.left\"\n [style.top.px]=\"selected.parentRect.top - 8\"\n >\n G {{ formatGap(selected) }}\n </div>\n }\n\n <div\n class=\"inspector-box inspector-box--margin\"\n [style.left.px]=\"selected.marginRect.left\"\n [style.top.px]=\"selected.marginRect.top\"\n [style.width.px]=\"selected.marginRect.width\"\n [style.height.px]=\"selected.marginRect.height\"\n ></div>\n\n <div\n class=\"inspector-box inspector-box--selected\"\n [style.left.px]=\"selected.rect.left\"\n [style.top.px]=\"selected.rect.top\"\n [style.width.px]=\"selected.rect.width\"\n [style.height.px]=\"selected.rect.height\"\n [style.--inspector-accent]=\"highlightColor\"\n >\n <div class=\"inspector-label\">{{ selectedMetaLine() }}</div>\n </div>\n\n <div\n class=\"inspector-box inspector-box--padding\"\n [style.left.px]=\"selected.paddingRect.left\"\n [style.top.px]=\"selected.paddingRect.top\"\n [style.width.px]=\"selected.paddingRect.width\"\n [style.height.px]=\"selected.paddingRect.height\"\n ></div>\n <div\n class=\"inspector-box-tag inspector-box-tag--spacing\"\n [style.left.px]=\"selected.rect.left\"\n [style.top.px]=\"selected.rect.top + selected.rect.height + 8\"\n >\n <span class=\"inspector-box-tag__margin\">M</span>\n <span>{{ formatEdges(selected.margin) }}</span>\n <span class=\"inspector-box-tag__separator\">\u00B7</span>\n <span class=\"inspector-box-tag__padding\">P</span>\n <span>{{ formatEdges(selected.padding) }}</span>\n </div>\n }\n }\n\n @if (enabled() && showTypography()) {\n @for (block of textBlocks(); track block.id) {\n <div\n class=\"inspector-text-chip\"\n [style.left.px]=\"block.rect.left\"\n [style.top.px]=\"block.rect.top - 8\"\n >\n <span\n class=\"inspector-text-chip__swatch\"\n [style.background]=\"block.styles.color\"\n ></span>\n <span>{{ block.styles.fontSize }}</span>\n <span>{{ block.styles.lineHeight }}</span>\n <span>{{ block.styles.color }}</span>\n </div>\n }\n }\n\n @if (enabled() && altPressed() && distanceOverlay(); as distance) {\n <div\n class=\"inspector-box inspector-box--distance\"\n [style.left.px]=\"distance.rectA.left\"\n [style.top.px]=\"distance.rectA.top\"\n [style.width.px]=\"distance.rectA.width\"\n [style.height.px]=\"distance.rectA.height\"\n ></div>\n <div\n class=\"inspector-box inspector-box--distance\"\n [style.left.px]=\"distance.rectB.left\"\n [style.top.px]=\"distance.rectB.top\"\n [style.width.px]=\"distance.rectB.width\"\n [style.height.px]=\"distance.rectB.height\"\n ></div>\n\n @for (\n connector of distance.connectors;\n track trackConnector($index, connector)\n ) {\n <div\n class=\"inspector-connector\"\n [class.inspector-connector--vertical]=\"connector.x1 === connector.x2\"\n [class.inspector-connector--horizontal]=\"connector.y1 === connector.y2\"\n [style.left.px]=\"Math.min(connector.x1, connector.x2)\"\n [style.top.px]=\"Math.min(connector.y1, connector.y2)\"\n [style.width.px]=\"Math.max(1, Math.abs(connector.x2 - connector.x1))\"\n [style.height.px]=\"Math.max(1, Math.abs(connector.y2 - connector.y1))\"\n ></div>\n }\n\n @for (horizontal of distance.horizontalDistances; track $index) {\n @if (horizontal.value > 0) {\n <div\n class=\"inspector-distance-line inspector-distance-line--horizontal\"\n [style.left.px]=\"Math.min(horizontal.x1!, horizontal.x2!)\"\n [style.top.px]=\"horizontal.y!\"\n [style.width.px]=\"Math.abs(horizontal.x2! - horizontal.x1!)\"\n ></div>\n <div\n class=\"inspector-distance-tag\"\n [style.left.px]=\"(horizontal.x1! + horizontal.x2!) / 2\"\n [style.top.px]=\"horizontal.y!\"\n >\n {{ formatValue(horizontal.value) }}\n </div>\n }\n }\n\n @for (vertical of distance.verticalDistances; track $index) {\n @if (vertical.value > 0) {\n <div\n class=\"inspector-distance-line inspector-distance-line--vertical\"\n [style.left.px]=\"vertical.x!\"\n [style.top.px]=\"Math.min(vertical.y1!, vertical.y2!)\"\n [style.height.px]=\"Math.abs(vertical.y2! - vertical.y1!)\"\n ></div>\n <div\n class=\"inspector-distance-tag inspector-distance-tag--vertical\"\n [style.left.px]=\"vertical.x!\"\n [style.top.px]=\"(vertical.y1! + vertical.y2!) / 2\"\n >\n {{ formatValue(vertical.value) }}\n </div>\n }\n }\n }\n\n @if (enabled()) {\n @if (toolMode() === \"guides\") {\n @if (guidePreview(); as preview) {\n <div\n class=\"inspector-guide inspector-guide--preview\"\n [class.inspector-guide--vertical]=\"preview.orientation === 'vertical'\"\n [class.inspector-guide--horizontal]=\"\n preview.orientation === 'horizontal'\n \"\n [style.left.px]=\"\n preview.orientation === 'vertical' ? preview.position : null\n \"\n [style.top.px]=\"\n preview.orientation === 'horizontal' ? preview.position : null\n \"\n [style.--inspector-guide]=\"guideColor\"\n >\n <span class=\"inspector-guide-line\"></span>\n </div>\n }\n }\n\n @for (guide of guides(); track guide.id) {\n <button\n type=\"button\"\n class=\"inspector-guide\"\n [class.inspector-guide--vertical]=\"guide.orientation === 'vertical'\"\n [class.inspector-guide--horizontal]=\"guide.orientation === 'horizontal'\"\n [class.inspector-guide--selected]=\"selectedGuideId() === guide.id\"\n [style.left.px]=\"\n guide.orientation === 'vertical' ? guide.position : null\n \"\n [style.top.px]=\"\n guide.orientation === 'horizontal' ? guide.position : null\n \"\n [style.--inspector-guide]=\"guideColor\"\n [attr.aria-label]=\"\n (guide.orientation === 'vertical' ? 'Vertical' : 'Horizontal') +\n ' guide at ' +\n formatValue(guide.position) +\n ' pixels'\n \"\n (pointerdown)=\"startGuideDrag($event, guide)\"\n >\n <span class=\"inspector-guide-line\"></span>\n </button>\n }\n\n @for (distance of guideDistances(); track distance.orientation + \"-\" + distance.start + \"-\" + distance.end) {\n <div\n class=\"inspector-guide-distance\"\n [class.inspector-guide-distance--vertical]=\"distance.orientation === 'vertical'\"\n [class.inspector-guide-distance--horizontal]=\"distance.orientation === 'horizontal'\"\n [style.left.px]=\"distance.orientation === 'vertical' ? distance.start : null\"\n [style.top.px]=\"distance.orientation === 'horizontal' ? distance.start : null\"\n [style.width.px]=\"distance.orientation === 'vertical' ? distance.value : null\"\n [style.height.px]=\"distance.orientation === 'horizontal' ? distance.value : null\"\n [style.--inspector-guide]=\"guideColor\"\n aria-hidden=\"true\"\n >\n <span class=\"inspector-guide-distance__line\"></span>\n <span class=\"inspector-guide-distance__tag\">\n {{ formatValue(distance.value) }} px\n </span>\n </div>\n }\n }\n</div>\n", styles: [":host{--inspector-panel: oklch(20% .012 280 / .92);--inspector-panel-edge: oklch(100% 0 0 / .08);--inspector-text: oklch(96% .005 280);--inspector-muted: oklch(70% .014 280);--inspector-faint: oklch(56% .012 280);--inspector-blue: oklch(68% .15 255);--inspector-blue-soft: oklch(68% .15 255 / .14);--inspector-orange: oklch(78% .14 70);--inspector-green: oklch(74% .15 150);--inspector-violet: oklch(72% .15 305);--inspector-radius: 8px;--inspector-shadow: 0 12px 32px oklch(6% .02 280 / .5);--inspector-font: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;--inspector-ease: cubic-bezier(.16, 1, .3, 1);position:fixed;inset:0;z-index:2147;pointer-events:none;font-family:var(--inspector-font);color:var(--inspector-text);-webkit-font-smoothing:antialiased}.inspector-root{position:fixed;inset:0;pointer-events:none}.inspector-command-dialog{--command-surface: oklch(17.5% .012 280);--command-surface-active: oklch(25% .012 280);--command-edge: oklch(100% 0 0 / .08);--command-text: oklch(96% .005 280);--command-muted: oklch(68% .014 280);--command-faint: oklch(52% .012 280);--command-accent: oklch(72% .13 255);--command-danger: oklch(68% .17 25);box-sizing:border-box;inset-block-start:max(10vh,48px);width:min(420px,calc(100vw - 24px));max-width:none;max-height:min(360px,calc(100vh - 64px));margin:0 auto;padding:0;overflow:hidden;border:1px solid var(--command-edge);border-radius:var(--inspector-radius);background:var(--command-surface);color:var(--command-text);box-shadow:var(--inspector-shadow);opacity:0;pointer-events:auto;transform:translateY(-4px);transition:opacity .1s ease,transform .1s ease,overlay .1s allow-discrete,display .1s allow-discrete;font-family:var(--inspector-font);-webkit-font-smoothing:antialiased}.inspector-command-dialog[open]{opacity:1;transform:none;transition-duration:.14s;transition-timing-function:var(--inspector-ease)}@starting-style{.inspector-command-dialog[open]{opacity:0;transform:translateY(-4px)}}.inspector-command-dialog::backdrop{background:#01010266}.inspector-command{display:grid;grid-template-rows:auto auto 1fr auto;min-width:0;min-height:0;max-height:min(360px,calc(100vh - 64px))}.inspector-command__search{display:flex;align-items:center;gap:8px;min-height:40px;padding:0 11px;border-bottom:1px solid var(--command-edge)}.inspector-command__pet-switcher{display:block;width:28px;height:28px;flex:0 0 auto;padding:0;overflow:hidden;border:0;border-radius:4px;background:transparent;cursor:pointer;opacity:.72;transition:opacity .14s var(--inspector-ease),transform .1s var(--inspector-ease)}.inspector-command__pet-sprite{display:block;width:500%;height:100%;max-width:none;image-rendering:pixelated;-webkit-user-select:none;user-select:none;transform:translate(0)}.inspector-command__search:focus-within .inspector-command__pet-switcher,.inspector-command__pet-switcher:hover,.inspector-command__pet-switcher:focus-visible{opacity:1}.inspector-command__pet-switcher:hover,.inspector-command__pet-switcher:focus-visible{background:#6aa7f41f}.inspector-command__pet-switcher:active{transform:scale(.94)}.inspector-command__pet-switcher:focus-visible{outline:1px solid var(--command-accent);outline-offset:1px}@media (prefers-reduced-motion: no-preference){.inspector-command__pet-sprite{animation:inspector-pet-cycle 1s steps(1,end) infinite}}@keyframes inspector-pet-cycle{0%,19.99%{transform:translate(0)}20%,39.99%{transform:translate(-20%)}40%,59.99%{transform:translate(-40%)}60%,79.99%{transform:translate(-60%)}80%,to{transform:translate(-80%)}}.inspector-command__search input,.inspector-command-row__rename{min-width:0;border:0;outline:0;background:transparent;color:var(--command-text);font:inherit}.inspector-command__search input{flex:1 1 auto;width:100%;height:39px;padding:0;font-size:13px;font-weight:450;line-height:1.3}.inspector-command__search input::placeholder{color:var(--command-faint);opacity:1}.inspector-command__search input::-webkit-search-cancel-button{display:none}.inspector-command__results{min-height:0;max-height:260px;overflow:auto;padding:5px;scrollbar-width:thin;scrollbar-color:oklch(100% 0 0 / .1) transparent}.inspector-command-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:6px;min-height:34px;padding:0 7px 0 9px;border-radius:5px;cursor:pointer;-webkit-user-select:none;user-select:none}.inspector-command-row.is-active{background:color-mix(in oklch,var(--command-surface-active) 92%,var(--command-accent));box-shadow:inset 0 0 0 1px #6aa7f452}.inspector-command-row.is-busy{cursor:wait;pointer-events:none;opacity:.7}.inspector-command-row__content{display:flex;align-items:baseline;gap:6px;min-width:0;overflow:hidden}.inspector-command-row__name{flex:0 1 auto;min-width:3ch;overflow:hidden;color:var(--command-text);font-size:12px;font-weight:500;line-height:1.25;text-overflow:ellipsis;white-space:nowrap;direction:rtl;text-align:left}.inspector-command-row__name bdi{direction:ltr;unicode-bidi:isolate}.inspector-command-row__activity{flex:0 0 auto;color:var(--command-faint);font-size:9px;font-weight:450;line-height:1;white-space:nowrap}.inspector-command-row.is-active .inspector-command-row__activity{color:#c2c3cc}.inspector-command-row--navigate{margin-top:4px;padding-top:5px;border-top:1px dashed var(--command-edge)}.inspector-command-row--navigate .inspector-command-row__name{color:color-mix(in oklch,var(--command-text) 78%,var(--command-accent))}.inspector-command-row--navigate .inspector-command-row__name:before{content:\"\\2192 \";color:var(--command-accent)}.inspector-command-row__actions,.inspector-command-row__confirm-actions{display:flex;align-items:center;gap:1px}.inspector-command-row__actions{opacity:0;pointer-events:none}.inspector-command-row.is-active .inspector-command-row__actions,.inspector-command-row:hover .inspector-command-row__actions,.inspector-command-row:focus-within .inspector-command-row__actions{opacity:1;pointer-events:auto}.inspector-command-row button{display:inline-grid;width:22px;min-height:22px;padding:0;place-items:center;border:0;border-radius:4px;background:transparent;color:var(--command-muted);cursor:pointer;font-family:inherit;font-size:10px;font-weight:550;line-height:1.2}.inspector-command-row button svg{width:11px;height:11px;fill:currentColor}.inspector-command-row button:hover{background:#ffffff12;color:var(--command-text)}.inspector-command-row button.is-danger{width:auto;padding:0 7px;color:var(--command-danger);font-size:11px}.inspector-command-row button.is-danger:hover{background:#ef66611f}.inspector-command-row__confirm-actions button:not(.is-danger){width:auto;padding:0 7px;font-size:11px}.inspector-command-row button:focus-visible,.inspector-command-row__rename:focus-visible{outline:1px solid var(--command-accent);outline-offset:1px}.inspector-command-row__confirm{grid-column:1;color:var(--command-text);font-size:12px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.inspector-command-row__rename{grid-column:1 / -1;min-height:26px;padding-inline:6px;border:1px solid oklch(72% .13 255 / .4);border-radius:4px;background:#191a21;font-size:12px;font-weight:500}.inspector-command__message{margin:0;padding:16px 10px;color:var(--command-faint);font-size:12px;line-height:1.4;text-align:center}.inspector-command__message--error{padding:6px 10px;border-bottom:1px solid oklch(55% .08 25 / .3);background:#39191780;color:#f7cbc7;text-align:left;font-size:11px}.inspector-command__actions{display:flex;gap:2px;padding:4px;border-top:1px solid var(--command-edge)}.inspector-command-action{display:flex;flex:1 1 0;min-width:0;min-height:28px;align-items:center;justify-content:center;gap:4px;padding:0 4px;overflow:hidden;border:0;border-radius:5px;background:transparent;color:var(--command-muted);cursor:pointer;font:inherit;font-size:10px;font-weight:500;line-height:1;text-align:left}.inspector-command-action svg{width:11px;height:11px;flex:0 0 auto;fill:currentColor}.inspector-command-action span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.inspector-command-action:hover:not(:disabled){background:#ffffff0f;color:var(--command-text)}.inspector-command-action.is-active{background:#6aa7f421;color:#c2daf9}.inspector-command-action.is-selected,.inspector-command-action.is-selected:hover:not(:disabled){background:var(--command-surface-active);color:var(--command-text);box-shadow:inset 0 0 0 1px #6aa7f49e}.inspector-command-action:disabled{cursor:wait;opacity:.45}.inspector-command-action:focus-visible{outline:1px solid var(--command-accent);outline-offset:-1px}.inspector-visually-hidden{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.inspector-checkpoint-toast{position:fixed;top:10px;left:50%;z-index:500;margin:0;display:flex;align-items:center;gap:6px;padding:6px 9px;border:1px solid var(--inspector-panel-edge);border-radius:6px;background:#0f1016f5;color:var(--inspector-text);box-shadow:0 8px 24px #01000352;font-size:11px;font-weight:500;line-height:1.3;pointer-events:none;transform:translate(-50%);animation:inspector-toast-in .16s var(--inspector-ease) both}.inspector-checkpoint-toast:before{width:5px;height:5px;flex:0 0 auto;border-radius:50%;background:var(--inspector-blue);content:\"\"}.inspector-checkpoint-toast--error{border-color:#e2726b4d;background:#351311f0;color:#fed2cd}.inspector-checkpoint-toast--error:before{background:var(--command-danger, oklch(68% .17 25))}@keyframes inspector-toast-in{0%{opacity:0;transform:translate(-50%,-4px)}to{opacity:1;transform:translate(-50%)}}@media (prefers-reduced-motion: reduce){.inspector-command-dialog{transition-duration:.01ms!important}.inspector-command-dialog,.inspector-command-dialog[open]{transform:none}.inspector-command__pet-switcher{transition:none}.inspector-command__pet-sprite{animation:none;transform:translate(0)}.inspector-checkpoint-toast{animation:none}}.inspector-box{position:fixed;box-sizing:border-box;pointer-events:none;border:1px solid var(--inspector-accent, var(--inspector-blue));background:color-mix(in srgb,var(--inspector-accent, var(--inspector-blue)) 8%,transparent)}.inspector-box--hover{opacity:.55}.inspector-box--selected{border-width:1.5px}.inspector-box--margin{border-color:#f0a646d1;background:#f0a64614}.inspector-box--padding{border-color:#5ac576d1;background:#5ac57614}.inspector-box--gap{border-color:#bb8aefb8;background:#bb8aef0d}.inspector-box--distance{border-style:dashed;border-color:#539af2b3;background:transparent}.inspector-label,.inspector-box-tag,.inspector-text-chip,.inspector-distance-tag,.inspector-guide-distance__tag{border:1px solid var(--inspector-panel-edge);border-radius:4px;background:#0e0f15c2;font-variant-numeric:tabular-nums;text-shadow:none}.inspector-label{position:absolute;left:0;top:0;transform:translateY(calc(-100% - 6px));max-width:min(380px,calc(100vw - 20px));padding:1px 3px;color:var(--inspector-text);box-shadow:none;backdrop-filter:none;-webkit-backdrop-filter:none;font-size:9px;font-weight:500;line-height:1.2;white-space:nowrap}.inspector-box-tag{position:fixed;transform:translateY(-100%);padding:2px 4px;color:var(--inspector-text);font-size:9px;font-weight:520;line-height:1;pointer-events:none}.inspector-box-tag__margin{color:#f5c076}.inspector-box-tag__padding{color:#95dfa4}.inspector-box-tag--gap{color:oklch(86% .09 305)}.inspector-box-tag--spacing{display:inline-flex;align-items:center;gap:3px;transform:translateY(0);white-space:nowrap}.inspector-box-tag__separator{color:var(--inspector-faint)}.inspector-text-chip{position:fixed;transform:translateY(-100%);display:inline-flex;gap:5px;align-items:center;padding:2px 4px;color:#e4e4e9;font-size:9px;font-weight:500;line-height:1;white-space:nowrap;pointer-events:none}.inspector-text-chip__swatch{width:7px;height:7px;border-radius:999px;border:1px solid oklch(100% 0 0 / .16);flex:0 0 auto}.inspector-connector{position:fixed;border-color:#539af2b8;border-style:dashed;pointer-events:none}.inspector-connector--vertical{border-left-width:1px;width:0}.inspector-connector--horizontal{border-top-width:1px;height:0}.inspector-distance-line{position:fixed;background:var(--inspector-blue);pointer-events:none}.inspector-distance-line--horizontal{height:1px}.inspector-distance-line--vertical{width:1px}.inspector-distance-tag{position:fixed;transform:translate(-50%,-50%);padding:2px 4px;border-color:#539af247;background:#0e0f15b8;color:var(--inspector-text);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);font-size:9px;font-weight:520;line-height:1;pointer-events:none}.inspector-guide{position:fixed;margin:0;padding:0;border:0;background:transparent;pointer-events:auto;cursor:grab}.inspector-guide--vertical{top:0;width:14px;height:100vh;transform:translate(-50%)}.inspector-guide--horizontal{left:0;width:100vw;height:14px;transform:translateY(-50%)}.inspector-guide--preview{opacity:.55;pointer-events:none;cursor:default}.inspector-guide--preview .inspector-guide-line{background:color-mix(in srgb,var(--inspector-guide, #ff7a00) 72%,transparent)}.inspector-guide-line{position:absolute;inset:0;pointer-events:none}.inspector-guide--vertical .inspector-guide-line{left:calc(50% - .5px);width:1px;height:100%;background:var(--inspector-guide, #ff7a00)}.inspector-guide--horizontal .inspector-guide-line{top:calc(50% - .5px);width:100%;height:1px;background:var(--inspector-guide, #ff7a00)}.inspector-guide--selected .inspector-guide-line{box-shadow:0 0 0 1px #ffffff80}.inspector-guide-distance{position:fixed;z-index:2;pointer-events:none}.inspector-guide-distance--vertical{top:50%;height:1px}.inspector-guide-distance--horizontal{left:50%;width:1px}.inspector-guide-distance__line{position:absolute;background:color-mix(in srgb,var(--inspector-guide, #ff7a00) 72%,transparent)}.inspector-guide-distance--vertical .inspector-guide-distance__line{inset:0;height:1px}.inspector-guide-distance--horizontal .inspector-guide-distance__line{inset:0;width:1px}.inspector-guide-distance__line:before,.inspector-guide-distance__line:after{position:absolute;content:\"\";background:var(--inspector-guide, #ff7a00)}.inspector-guide-distance--vertical .inspector-guide-distance__line:before,.inspector-guide-distance--vertical .inspector-guide-distance__line:after{top:-2px;width:1px;height:5px}.inspector-guide-distance--vertical .inspector-guide-distance__line:before{left:0}.inspector-guide-distance--vertical .inspector-guide-distance__line:after{right:0}.inspector-guide-distance--horizontal .inspector-guide-distance__line:before,.inspector-guide-distance--horizontal .inspector-guide-distance__line:after{left:-2px;width:5px;height:1px}.inspector-guide-distance--horizontal .inspector-guide-distance__line:before{top:0}.inspector-guide-distance--horizontal .inspector-guide-distance__line:after{bottom:0}.inspector-guide-distance__tag{position:absolute;padding:2px 4px;border-color:color-mix(in srgb,var(--inspector-guide, #ff7a00) 48%,transparent);background:#0e0f15eb;color:var(--inspector-text);box-shadow:0 1px 4px #01000357;font-size:9px;font-weight:520;line-height:1;white-space:nowrap}.inspector-guide-distance--vertical .inspector-guide-distance__tag{left:50%;top:0;transform:translate(-50%,-50%)}.inspector-guide-distance--horizontal .inspector-guide-distance__tag{left:0;top:50%;transform:translate(-50%,-50%)}@media (min-width: 769px) and (min-height: 769px){:host{--inspector-radius: 14px;--inspector-shadow: 0 21px 56px oklch(6% .02 280 / .5)}.inspector-command-dialog{inset-block-start:max(10vh,84px);width:min(735px,calc(100vw - 42px));max-height:min(630px,calc(100vh - 112px))}.inspector-command{max-height:min(630px,calc(100vh - 112px))}.inspector-command__search{gap:14px;min-height:70px;padding:0 19.25px}.inspector-command__pet-switcher{width:42px;height:42px}.inspector-command__search input{height:68.25px;font-size:22.75px}.inspector-command__results{max-height:455px;padding:8.75px}.inspector-command-row{gap:10.5px;min-height:59.5px;padding:0 12.25px 0 15.75px;border-radius:8.75px}.inspector-command-row__content{gap:10.5px}.inspector-command-row__name,.inspector-command-row__confirm{font-size:21px}.inspector-command-row__activity{font-size:15.75px}.inspector-command-row__actions,.inspector-command-row__confirm-actions{gap:1.75px}.inspector-command-row button{width:38.5px;min-height:38.5px;border-radius:7px;font-size:17.5px}.inspector-command-row button svg{width:19.25px;height:19.25px}.inspector-command-row button.is-danger,.inspector-command-row__confirm-actions button:not(.is-danger){padding:0 12.25px;font-size:19.25px}.inspector-command-row__rename{min-height:45.5px;padding-inline:10.5px;border-radius:7px;font-size:21px}.inspector-command__message{padding:28px 17.5px;font-size:21px}.inspector-command__message--error{padding:10.5px 17.5px;font-size:19.25px}.inspector-command__actions{gap:3.5px;padding:7px}.inspector-command-action{min-height:49px;gap:7px;padding:0 7px;border-radius:8.75px;font-size:17.5px}.inspector-command-action svg{width:19.25px;height:19.25px}.inspector-checkpoint-toast{top:14px;padding:7px 10px;font-size:13px}.inspector-label{transform:translateY(calc(-100% - 10.5px));max-width:min(665px,calc(100vw - 35px));padding:2px 4px;font-size:13px}.inspector-box-tag{padding:3px 5px;font-size:15.75px}.inspector-box-tag--spacing{gap:5px;transform:translateY(0)}.inspector-text-chip{gap:8.75px;padding:3px 5px;font-size:15.75px}.inspector-text-chip__swatch{width:12.25px;height:12.25px}.inspector-distance-tag,.inspector-guide-distance__tag{padding:3px 5px;font-size:15.75px}.inspector-guide--vertical{width:24.5px}.inspector-guide--horizontal{height:24.5px}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1596
1961
  }
1597
1962
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: inspectorComponent, decorators: [{
1598
1963
  type: Component,
1599
- args: [{ selector: 'inspector-overlay', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"inspector-root\" #overlayRoot>\n @if (checkpointService) {\n <dialog\n #checkpointDialog\n class=\"inspector-command-dialog\"\n aria-labelledby=\"inspector-command-title\"\n (cancel)=\"$event.preventDefault(); closeCheckpointCommandBar()\"\n (click)=\"handleCheckpointDialogClick($event)\"\n >\n <section class=\"inspector-command\" (click)=\"$event.stopPropagation()\">\n <header class=\"inspector-command__search\">\n <label\n id=\"inspector-command-title\"\n class=\"inspector-visually-hidden\"\n for=\"inspector-checkpoint-search\"\n >\n inspector-ng command palette\n </label>\n <button\n type=\"button\"\n class=\"inspector-command__pet-switcher\"\n [attr.aria-label]=\"'Change pet. Current pet: ' + activePet().name\"\n [title]=\"'Change pet: ' + activePet().name\"\n (click)=\"cyclePet($event)\"\n >\n <img\n class=\"inspector-command__pet-sprite\"\n [src]=\"activePet().spriteSrc\"\n alt=\"\"\n aria-hidden=\"true\"\n draggable=\"false\"\n />\n </button>\n <input\n #checkpointSearch\n id=\"inspector-checkpoint-search\"\n type=\"search\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n placeholder=\"inspector-ng\u2026\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"commandBarOpen()\"\n [value]=\"checkpointQuery()\"\n [attr.aria-controls]=\"'inspector-checkpoint-results inspector-command-actions'\"\n [attr.aria-activedescendant]=\"activeCommandResultId()\"\n (input)=\"updateCheckpointQuery($event)\"\n />\n </header>\n\n @if (checkpointService.error(); as error) {\n <p\n class=\"inspector-command__message inspector-command__message--error\"\n role=\"alert\"\n >\n {{ error }}\n </p>\n }\n\n <div\n id=\"inspector-checkpoint-results\"\n class=\"inspector-command__results\"\n role=\"listbox\"\n aria-label=\"Saved checkpoints\"\n >\n @if (checkpointService.loading()) {\n <p class=\"inspector-command__message\" role=\"status\">Loading\u2026</p>\n } @else if (\n !checkpointService.checkpoints().length && !checkpointQuery().trim()\n ) {\n <p class=\"inspector-command__message\" role=\"status\">\n No checkpoints yet\n </p>\n } @else if (\n !filteredCheckpoints().length && !filteredInspectorActions().length\n ) {\n <p class=\"inspector-command__message\" role=\"status\">No matches</p>\n } @else {\n @for (\n checkpoint of filteredCheckpoints();\n track checkpoint.id;\n let index = $index\n ) {\n <div\n class=\"inspector-command-row\"\n role=\"option\"\n [id]=\"'inspector-checkpoint-' + checkpoint.id\"\n [attr.data-command-index]=\"index\"\n [attr.aria-selected]=\"activeCommandIndex() === index\"\n [class.is-active]=\"activeCommandIndex() === index\"\n [class.is-busy]=\"\n checkpointService.busy() && activeCommandIndex() === index\n \"\n (mouseenter)=\"setActiveCheckpoint(index)\"\n (click)=\"\n deletingCheckpointId() === checkpoint.id ||\n editingCheckpointId() === checkpoint.id\n ? null\n : restoreCheckpoint(checkpoint)\n \"\n >\n @if (deletingCheckpointId() === checkpoint.id) {\n <span class=\"inspector-command-row__confirm\"\n >Delete \u201C{{ checkpoint.name }}\u201D?</span\n >\n <span class=\"inspector-command-row__confirm-actions\">\n <button\n type=\"button\"\n class=\"is-danger\"\n (click)=\"confirmDelete(checkpoint, $event)\"\n >\n Delete\n </button>\n <button type=\"button\" (click)=\"cancelDelete($event)\">\n Keep\n </button>\n </span>\n } @else if (editingCheckpointId() === checkpoint.id) {\n <input\n class=\"inspector-command-row__rename\"\n aria-label=\"Checkpoint name\"\n [value]=\"renameDraft()\"\n (input)=\"updateRenameDraft($event)\"\n (click)=\"$event.stopPropagation()\"\n />\n } @else {\n <span class=\"inspector-command-row__content\">\n <span class=\"inspector-command-row__name\">\n @if (\n checkpointService.busy() &&\n activeCommandIndex() === index\n ) {\n Restoring\u2026\n } @else {\n {{ checkpoint.name }}\n }\n </span>\n <span class=\"inspector-command-row__meta\">\n @if (shouldShowCheckpointRoute(checkpoint)) {\n <span class=\"inspector-command-row__route\">{{\n checkpoint.route\n }}</span>\n <span\n class=\"inspector-command-row__separator\"\n aria-hidden=\"true\"\n >\u00B7</span\n >\n }\n <span class=\"inspector-command-row__activity\">\n {{ checkpoint.lastUsedAt ? \"Used\" : \"Saved\" }}\n {{\n formatRelativeTime(checkpointActivityAt(checkpoint))\n }}\n </span>\n </span>\n </span>\n <span class=\"inspector-command-row__actions\">\n <button\n type=\"button\"\n (click)=\"beginRename(checkpoint, $event)\"\n [attr.aria-label]=\"'Rename ' + checkpoint.name\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"m11.8 1.8 2.4 2.4-8.3 8.3-3.1.7.7-3.1zm-8 10.4 1.5-.3-1.2-1.2z\"\n />\n </svg>\n </button>\n <button\n type=\"button\"\n (click)=\"beginDelete(checkpoint, $event)\"\n [attr.aria-label]=\"'Delete ' + checkpoint.name\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"M5.5 2h5l.5 1H14v1.25H2V3h3zm-2 3.25h9L12 14H4z\"\n />\n </svg>\n </button>\n </span>\n }\n </div>\n }\n }\n </div>\n\n @if (filteredInspectorActions().length) {\n <footer\n id=\"inspector-command-actions\"\n class=\"inspector-command__actions\"\n role=\"listbox\"\n aria-label=\"Inspector actions\"\n aria-orientation=\"horizontal\"\n >\n @for (\n action of filteredInspectorActions();\n track action.id;\n let index = $index\n ) {\n <button\n type=\"button\"\n role=\"option\"\n class=\"inspector-command-action\"\n [id]=\"'inspector-action-' + action.id\"\n [attr.data-command-index]=\"filteredCheckpoints().length + index\"\n [attr.aria-label]=\"action.ariaLabel\"\n [attr.aria-selected]=\"\n activeCommandIndex() === filteredCheckpoints().length + index\n \"\n [attr.aria-disabled]=\"checkpointService.busy()\"\n [class.is-selected]=\"\n activeCommandIndex() === filteredCheckpoints().length + index\n \"\n [class.is-active]=\"\n (action.id === 'select' && toolMode() === 'select') ||\n (action.id === 'type' && showTypography()) ||\n (action.id === 'vertical' &&\n toolMode() === 'guides' &&\n guideOrientation() === 'vertical') ||\n (action.id === 'horizontal' &&\n toolMode() === 'guides' &&\n guideOrientation() === 'horizontal')\n \"\n [class.inspector-command-action--danger]=\"action.id === 'off'\"\n [disabled]=\"checkpointService.busy()\"\n (mouseenter)=\"setActiveInspectorAction(index)\"\n (click)=\"executeInspectorAction(action)\"\n >\n @switch (action.id) {\n @case (\"select\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M3 2l8 8-3 .7L6.7 13 6 10 3 2z\" />\n </svg>\n }\n @case (\"type\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M3 4V2h10v2h-4v10H7V4z\" />\n </svg>\n }\n @case (\"save\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"M2.5 2h9.6l1.4 1.4V14h-11zm2 1.5v3h6v-3zm.5 6V12h6V9.5z\"\n />\n </svg>\n }\n @case (\"vertical\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M7.25 2h1.5v12h-1.5z\" />\n </svg>\n }\n @case (\"horizontal\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M2 7.25h12v1.5H2z\" />\n </svg>\n }\n @case (\"off\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"M7.25 1.5h1.5v6h-1.5zM4.1 3.35l.96 1.15A4.25 4.25 0 1 0 10.94 4.5l.96-1.15A5.75 5.75 0 1 1 4.1 3.35z\"\n />\n </svg>\n }\n }\n <span>{{ action.label }}</span>\n </button>\n }\n </footer>\n }\n </section>\n </dialog>\n }\n\n @if (checkpointToast(); as toast) {\n <p\n class=\"inspector-checkpoint-toast\"\n [class.inspector-checkpoint-toast--error]=\"checkpointToastIsError()\"\n [attr.role]=\"checkpointToastIsError() ? 'alert' : 'status'\"\n >\n {{ toast }}\n </p>\n }\n\n @if (enabled() && toolMode() === \"select\") {\n @if (hoverRect() && hoverHighlightEnabled) {\n <div\n class=\"inspector-box inspector-box--hover\"\n [style.left.px]=\"hoverRect()!.left\"\n [style.top.px]=\"hoverRect()!.top\"\n [style.width.px]=\"hoverRect()!.width\"\n [style.height.px]=\"hoverRect()!.height\"\n [style.--inspector-accent]=\"highlightColor\"\n ></div>\n }\n\n @if (selectedMeasurement(); as selected) {\n @if (selected.gap.active && selected.parentRect) {\n <div\n class=\"inspector-box inspector-box--gap\"\n [style.left.px]=\"selected.parentRect.left\"\n [style.top.px]=\"selected.parentRect.top\"\n [style.width.px]=\"selected.parentRect.width\"\n [style.height.px]=\"selected.parentRect.height\"\n ></div>\n <div\n class=\"inspector-box-tag inspector-box-tag--gap\"\n [style.left.px]=\"selected.parentRect.left\"\n [style.top.px]=\"selected.parentRect.top - 8\"\n >\n G {{ formatGap(selected) }}\n </div>\n }\n\n <div\n class=\"inspector-box inspector-box--margin\"\n [style.left.px]=\"selected.marginRect.left\"\n [style.top.px]=\"selected.marginRect.top\"\n [style.width.px]=\"selected.marginRect.width\"\n [style.height.px]=\"selected.marginRect.height\"\n ></div>\n <div\n class=\"inspector-box-tag inspector-box-tag--margin\"\n [style.left.px]=\"selected.marginRect.left\"\n [style.top.px]=\"selected.marginRect.top - 8\"\n >\n M {{ formatEdges(selected.margin) }}\n </div>\n\n <div\n class=\"inspector-box inspector-box--selected\"\n [style.left.px]=\"selected.rect.left\"\n [style.top.px]=\"selected.rect.top\"\n [style.width.px]=\"selected.rect.width\"\n [style.height.px]=\"selected.rect.height\"\n [style.--inspector-accent]=\"highlightColor\"\n >\n <div class=\"inspector-label\">{{ selectedMetaLine() }}</div>\n </div>\n\n <div\n class=\"inspector-box inspector-box--padding\"\n [style.left.px]=\"selected.paddingRect.left\"\n [style.top.px]=\"selected.paddingRect.top\"\n [style.width.px]=\"selected.paddingRect.width\"\n [style.height.px]=\"selected.paddingRect.height\"\n ></div>\n <div\n class=\"inspector-box-tag inspector-box-tag--padding\"\n [style.left.px]=\"selected.paddingRect.left\"\n [style.top.px]=\"\n selected.paddingRect.top + selected.paddingRect.height + 8\n \"\n >\n P {{ formatEdges(selected.padding) }}\n </div>\n }\n }\n\n @if (enabled() && showTypography()) {\n @for (block of textBlocks(); track block.id) {\n <div\n class=\"inspector-text-chip\"\n [style.left.px]=\"block.rect.left\"\n [style.top.px]=\"block.rect.top - 8\"\n >\n <span\n class=\"inspector-text-chip__swatch\"\n [style.background]=\"block.styles.color\"\n ></span>\n <span>{{ block.styles.fontSize }}</span>\n <span>{{ block.styles.lineHeight }}</span>\n <span>{{ block.styles.color }}</span>\n </div>\n }\n }\n\n @if (enabled() && altPressed() && distanceOverlay(); as distance) {\n <div\n class=\"inspector-box inspector-box--distance\"\n [style.left.px]=\"distance.rectA.left\"\n [style.top.px]=\"distance.rectA.top\"\n [style.width.px]=\"distance.rectA.width\"\n [style.height.px]=\"distance.rectA.height\"\n ></div>\n <div\n class=\"inspector-box inspector-box--distance\"\n [style.left.px]=\"distance.rectB.left\"\n [style.top.px]=\"distance.rectB.top\"\n [style.width.px]=\"distance.rectB.width\"\n [style.height.px]=\"distance.rectB.height\"\n ></div>\n\n @for (\n connector of distance.connectors;\n track trackConnector($index, connector)\n ) {\n <div\n class=\"inspector-connector\"\n [class.inspector-connector--vertical]=\"connector.x1 === connector.x2\"\n [class.inspector-connector--horizontal]=\"connector.y1 === connector.y2\"\n [style.left.px]=\"Math.min(connector.x1, connector.x2)\"\n [style.top.px]=\"Math.min(connector.y1, connector.y2)\"\n [style.width.px]=\"Math.max(1, Math.abs(connector.x2 - connector.x1))\"\n [style.height.px]=\"Math.max(1, Math.abs(connector.y2 - connector.y1))\"\n ></div>\n }\n\n @if (distance.horizontal && distance.horizontal.value > 0) {\n <div\n class=\"inspector-distance-line inspector-distance-line--horizontal\"\n [style.left.px]=\"\n Math.min(distance.horizontal.x1!, distance.horizontal.x2!)\n \"\n [style.top.px]=\"distance.horizontal.y!\"\n [style.width.px]=\"\n Math.abs(distance.horizontal.x2! - distance.horizontal.x1!)\n \"\n ></div>\n <div\n class=\"inspector-distance-tag\"\n [style.left.px]=\"\n (distance.horizontal.x1! + distance.horizontal.x2!) / 2\n \"\n [style.top.px]=\"distance.horizontal.y! + 10\"\n >\n {{ formatValue(distance.horizontal.value) }}\n </div>\n }\n\n @if (distance.vertical && distance.vertical.value > 0) {\n <div\n class=\"inspector-distance-line inspector-distance-line--vertical\"\n [style.left.px]=\"distance.vertical.x!\"\n [style.top.px]=\"Math.min(distance.vertical.y1!, distance.vertical.y2!)\"\n [style.height.px]=\"\n Math.abs(distance.vertical.y2! - distance.vertical.y1!)\n \"\n ></div>\n <div\n class=\"inspector-distance-tag inspector-distance-tag--vertical\"\n [style.left.px]=\"distance.vertical.x! + 10\"\n [style.top.px]=\"(distance.vertical.y1! + distance.vertical.y2!) / 2\"\n >\n {{ formatValue(distance.vertical.value) }}\n </div>\n }\n }\n\n @if (enabled()) {\n @if (toolMode() === \"guides\") {\n @if (guidePreview(); as preview) {\n <div\n class=\"inspector-guide inspector-guide--preview\"\n [class.inspector-guide--vertical]=\"preview.orientation === 'vertical'\"\n [class.inspector-guide--horizontal]=\"\n preview.orientation === 'horizontal'\n \"\n [style.left.px]=\"\n preview.orientation === 'vertical' ? preview.position : null\n \"\n [style.top.px]=\"\n preview.orientation === 'horizontal' ? preview.position : null\n \"\n [style.--inspector-guide]=\"guideColor\"\n >\n <span class=\"inspector-guide-line\"></span>\n </div>\n }\n }\n\n @for (guide of guides(); track guide.id) {\n <button\n type=\"button\"\n class=\"inspector-guide\"\n [class.inspector-guide--vertical]=\"guide.orientation === 'vertical'\"\n [class.inspector-guide--horizontal]=\"guide.orientation === 'horizontal'\"\n [class.inspector-guide--selected]=\"selectedGuideId() === guide.id\"\n [style.left.px]=\"\n guide.orientation === 'vertical' ? guide.position : null\n \"\n [style.top.px]=\"\n guide.orientation === 'horizontal' ? guide.position : null\n \"\n [style.--inspector-guide]=\"guideColor\"\n [attr.aria-label]=\"\n (guide.orientation === 'vertical' ? 'Vertical' : 'Horizontal') +\n ' guide at ' +\n formatValue(guide.position) +\n ' pixels'\n \"\n (pointerdown)=\"startGuideDrag($event, guide)\"\n >\n <span class=\"inspector-guide-line\"></span>\n </button>\n }\n }\n</div>\n", styles: [":host{--inspector-panel: oklch(20% .012 280 / .92);--inspector-panel-edge: oklch(100% 0 0 / .08);--inspector-text: oklch(96% .005 280);--inspector-muted: oklch(70% .014 280);--inspector-faint: oklch(56% .012 280);--inspector-blue: oklch(68% .15 255);--inspector-blue-soft: oklch(68% .15 255 / .14);--inspector-orange: oklch(78% .14 70);--inspector-green: oklch(74% .15 150);--inspector-violet: oklch(72% .15 305);--inspector-radius: 8px;--inspector-shadow: 0 12px 32px oklch(6% .02 280 / .5);--inspector-font: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;--inspector-ease: cubic-bezier(.16, 1, .3, 1);position:fixed;inset:0;z-index:2147;pointer-events:none;font-family:var(--inspector-font);color:var(--inspector-text);-webkit-font-smoothing:antialiased}.inspector-root{position:fixed;inset:0;pointer-events:none}.inspector-command-dialog{--command-surface: oklch(17.5% .012 280);--command-surface-active: oklch(25% .012 280);--command-edge: oklch(100% 0 0 / .08);--command-text: oklch(96% .005 280);--command-muted: oklch(68% .014 280);--command-faint: oklch(52% .012 280);--command-accent: oklch(72% .13 255);--command-danger: oklch(68% .17 25);box-sizing:border-box;inset-block-start:max(10vh,48px);width:min(420px,calc(100vw - 24px));max-width:none;max-height:min(360px,calc(100vh - 64px));margin:0 auto;padding:0;overflow:hidden;border:1px solid var(--command-edge);border-radius:var(--inspector-radius);background:var(--command-surface);color:var(--command-text);box-shadow:var(--inspector-shadow);opacity:0;pointer-events:auto;transform:translateY(-4px);transition:opacity .1s ease,transform .1s ease,overlay .1s allow-discrete,display .1s allow-discrete;font-family:var(--inspector-font);-webkit-font-smoothing:antialiased}.inspector-command-dialog[open]{opacity:1;transform:none;transition-duration:.14s;transition-timing-function:var(--inspector-ease)}@starting-style{.inspector-command-dialog[open]{opacity:0;transform:translateY(-4px)}}.inspector-command-dialog::backdrop{background:#01010266}.inspector-command{display:grid;grid-template-rows:auto auto 1fr auto;min-width:0;min-height:0;max-height:min(360px,calc(100vh - 64px))}.inspector-command__search{display:flex;align-items:center;gap:8px;min-height:40px;padding:0 11px;border-bottom:1px solid var(--command-edge)}.inspector-command__pet-switcher{display:block;width:28px;height:28px;flex:0 0 auto;padding:0;overflow:hidden;border:0;border-radius:4px;background:transparent;cursor:pointer;opacity:.72;transition:opacity .14s var(--inspector-ease),transform .1s var(--inspector-ease)}.inspector-command__pet-sprite{display:block;width:500%;height:100%;max-width:none;image-rendering:pixelated;-webkit-user-select:none;user-select:none;transform:translate(0)}.inspector-command__search:focus-within .inspector-command__pet-switcher,.inspector-command__pet-switcher:hover,.inspector-command__pet-switcher:focus-visible{opacity:1}.inspector-command__pet-switcher:hover,.inspector-command__pet-switcher:focus-visible{background:#6aa7f41f}.inspector-command__pet-switcher:active{transform:scale(.94)}.inspector-command__pet-switcher:focus-visible{outline:1px solid var(--command-accent);outline-offset:1px}@media (prefers-reduced-motion: no-preference){.inspector-command__search:focus-within .inspector-command__pet-sprite{animation:inspector-pet-cycle 1s steps(1,end) infinite}}@keyframes inspector-pet-cycle{0%,19.99%{transform:translate(0)}20%,39.99%{transform:translate(-20%)}40%,59.99%{transform:translate(-40%)}60%,79.99%{transform:translate(-60%)}80%,to{transform:translate(-80%)}}.inspector-command__search input,.inspector-command-row__rename{min-width:0;border:0;outline:0;background:transparent;color:var(--command-text);font:inherit}.inspector-command__search input{flex:1 1 auto;width:100%;height:39px;padding:0;font-size:13px;font-weight:450;line-height:1.3}.inspector-command__search input::placeholder{color:var(--command-faint);opacity:1}.inspector-command__search input::-webkit-search-cancel-button{display:none}.inspector-command__results{min-height:0;max-height:260px;overflow:auto;padding:5px;scrollbar-width:thin;scrollbar-color:oklch(100% 0 0 / .1) transparent}.inspector-command-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:6px;min-height:34px;padding:0 7px 0 9px;border-radius:5px;cursor:pointer;-webkit-user-select:none;user-select:none}.inspector-command-row.is-active{background:var(--command-surface-active);box-shadow:inset 0 0 0 1px #6aa7f49e}.inspector-command-row.is-busy{cursor:wait;pointer-events:none;opacity:.7}.inspector-command-row__content{display:flex;align-items:baseline;gap:8px;min-width:0;overflow:hidden}.inspector-command-row__name{flex:0 1 auto;min-width:3ch;overflow:hidden;color:var(--command-text);font-size:12px;font-weight:500;line-height:1.25;text-overflow:ellipsis;white-space:nowrap}.inspector-command-row__meta{display:inline-flex;flex:0 1 auto;align-items:baseline;gap:4px;min-width:0;overflow:hidden;color:var(--command-faint);font-size:11px;font-weight:400;line-height:1.25;text-overflow:ellipsis;white-space:nowrap}.inspector-command-row__route{min-width:0;overflow:hidden;text-overflow:ellipsis}.inspector-command-row__separator,.inspector-command-row__activity{flex:0 0 auto}.inspector-command-row.is-active .inspector-command-row__meta{color:#c2c3cc}.inspector-command-row__actions,.inspector-command-row__confirm-actions{display:flex;align-items:center;gap:1px}.inspector-command-row__actions{opacity:0;pointer-events:none}.inspector-command-row:hover .inspector-command-row__actions,.inspector-command-row:focus-within .inspector-command-row__actions{opacity:1;pointer-events:auto}.inspector-command-row button{display:inline-grid;width:22px;min-height:22px;padding:0;place-items:center;border:0;border-radius:4px;background:transparent;color:var(--command-muted);cursor:pointer;font-family:inherit;font-size:10px;font-weight:550;line-height:1.2}.inspector-command-row button svg{width:11px;height:11px;fill:currentColor}.inspector-command-row button:hover{background:#ffffff12;color:var(--command-text)}.inspector-command-row button.is-danger{width:auto;padding:0 7px;color:var(--command-danger);font-size:11px}.inspector-command-row button.is-danger:hover{background:#ef66611f}.inspector-command-row__confirm-actions button:not(.is-danger){width:auto;padding:0 7px;font-size:11px}.inspector-command-row button:focus-visible,.inspector-command-row__rename:focus-visible{outline:1px solid var(--command-accent);outline-offset:1px}.inspector-command-row__confirm{grid-column:1;color:var(--command-text);font-size:12px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.inspector-command-row__rename{grid-column:1 / -1;min-height:26px;padding-inline:6px;border:1px solid oklch(72% .13 255 / .4);border-radius:4px;background:#191a21;font-size:12px;font-weight:500}.inspector-command__message{margin:0;padding:16px 10px;color:var(--command-faint);font-size:12px;line-height:1.4;text-align:center}.inspector-command__message--error{padding:6px 10px;border-bottom:1px solid oklch(55% .08 25 / .3);background:#39191780;color:#f7cbc7;text-align:left;font-size:11px}.inspector-command__actions{display:flex;gap:2px;padding:4px;border-top:1px solid var(--command-edge)}.inspector-command-action{display:flex;flex:1 1 0;min-width:0;min-height:28px;align-items:center;justify-content:center;gap:4px;padding:0 4px;overflow:hidden;border:0;border-radius:5px;background:transparent;color:var(--command-muted);cursor:pointer;font:inherit;font-size:10px;font-weight:500;line-height:1;text-align:left}.inspector-command-action svg{width:11px;height:11px;flex:0 0 auto;fill:currentColor}.inspector-command-action span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.inspector-command-action:hover:not(:disabled){background:#ffffff0f;color:var(--command-text)}.inspector-command-action.is-active{background:#6aa7f421;color:#c2daf9}.inspector-command-action.is-selected,.inspector-command-action.is-selected:hover:not(:disabled){background:var(--command-surface-active);color:var(--command-text);box-shadow:inset 0 0 0 1px #6aa7f49e}.inspector-command-action--danger:hover:not(:disabled){background:#ef66611a;color:#f5b9b4}.inspector-command-action:disabled{cursor:wait;opacity:.45}.inspector-command-action:focus-visible{outline:1px solid var(--command-accent);outline-offset:-1px}.inspector-visually-hidden{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.inspector-checkpoint-toast{position:fixed;top:10px;left:50%;z-index:500;margin:0;padding:5px 10px;border:1px solid oklch(74% .12 150 / .25);border-radius:999px;background:#0e1f12f0;color:#cce6d0;box-shadow:var(--inspector-shadow);font-size:11px;font-weight:520;line-height:1.25;pointer-events:none;transform:translate(-50%)}.inspector-checkpoint-toast--error{border-color:#e2726b4d;background:#351311f0;color:#fed2cd}@media (prefers-reduced-motion: reduce){.inspector-command-dialog{transition-duration:.01ms!important}.inspector-command-dialog,.inspector-command-dialog[open]{transform:none}.inspector-command__pet-switcher{transition:none}.inspector-command__pet-sprite{animation:none;transform:translate(0)}}.inspector-box{position:fixed;box-sizing:border-box;pointer-events:none;border:1px solid var(--inspector-accent, var(--inspector-blue));background:color-mix(in srgb,var(--inspector-accent, var(--inspector-blue)) 8%,transparent)}.inspector-box--hover{opacity:.55}.inspector-box--selected{border-width:1.5px}.inspector-box--margin{border-color:#f0a646d1;background:#f0a64614}.inspector-box--padding{border-color:#5ac576d1;background:#5ac57614}.inspector-box--gap{border-color:#bb8aefb8;background:#bb8aef0d}.inspector-box--distance{border-style:dashed;border-color:#539af2b3;background:transparent}.inspector-label,.inspector-box-tag,.inspector-text-chip,.inspector-distance-tag{font-variant-numeric:tabular-nums}.inspector-label{position:absolute;left:0;top:0;transform:translateY(calc(-100% - 6px));max-width:min(380px,calc(100vw - 20px));padding:4px 7px;border-radius:999px;border:1px solid var(--inspector-panel-edge);background:var(--inspector-panel);color:var(--inspector-text);box-shadow:var(--inspector-shadow);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);font-size:10px;font-weight:500;line-height:1.2;white-space:nowrap}.inspector-box-tag{position:fixed;transform:translateY(-100%);padding:3px 5px;border-radius:999px;border:1px solid var(--inspector-panel-edge);background:#0e0f15f0;color:var(--inspector-text);font-size:9px;font-weight:520;line-height:1;pointer-events:none}.inspector-box-tag--margin{color:#f5c076}.inspector-box-tag--padding{color:#95dfa4;transform:translateY(0)}.inspector-box-tag--gap{color:oklch(86% .09 305)}.inspector-text-chip{position:fixed;transform:translateY(-100%);display:inline-flex;gap:5px;align-items:center;padding:3px 6px;border-radius:999px;border:1px solid var(--inspector-panel-edge);background:#0e0f15f0;color:#e4e4e9;font-size:9px;font-weight:500;line-height:1;white-space:nowrap;pointer-events:none}.inspector-text-chip__swatch{width:7px;height:7px;border-radius:999px;border:1px solid oklch(100% 0 0 / .16);flex:0 0 auto}.inspector-connector{position:fixed;border-color:#539af2b8;border-style:dashed;pointer-events:none}.inspector-connector--vertical{border-left-width:1px;width:0}.inspector-connector--horizontal{border-top-width:1px;height:0}.inspector-distance-line{position:fixed;background:var(--inspector-blue);pointer-events:none}.inspector-distance-line--horizontal{height:1px}.inspector-distance-line--vertical{width:1px}.inspector-distance-tag{position:fixed;transform:translate(-50%);padding:3px 6px;border-radius:999px;border:1px solid var(--inspector-panel-edge);background:#0e0f15f2;color:var(--inspector-text);font-size:9px;font-weight:520;line-height:1;pointer-events:none}.inspector-distance-tag--vertical{transform:translateY(-50%)}.inspector-guide{position:fixed;margin:0;padding:0;border:0;background:transparent;pointer-events:auto;cursor:grab}.inspector-guide--vertical{top:0;width:14px;height:100vh;transform:translate(-50%)}.inspector-guide--horizontal{left:0;width:100vw;height:14px;transform:translateY(-50%)}.inspector-guide--preview{opacity:.55;pointer-events:none;cursor:default}.inspector-guide--preview .inspector-guide-line{background:color-mix(in srgb,var(--inspector-guide, #ff7a00) 72%,transparent)}.inspector-guide-line{position:absolute;inset:0;pointer-events:none}.inspector-guide--vertical .inspector-guide-line{left:calc(50% - .5px);width:1px;height:100%;background:var(--inspector-guide, #ff7a00)}.inspector-guide--horizontal .inspector-guide-line{top:calc(50% - .5px);width:100%;height:1px;background:var(--inspector-guide, #ff7a00)}.inspector-guide--selected .inspector-guide-line{box-shadow:0 0 0 1px #ffffff80}@media (min-width: 769px) and (min-height: 769px){:host{--inspector-radius: 14px;--inspector-shadow: 0 21px 56px oklch(6% .02 280 / .5)}.inspector-command-dialog{inset-block-start:max(10vh,84px);width:min(735px,calc(100vw - 42px));max-height:min(630px,calc(100vh - 112px))}.inspector-command{max-height:min(630px,calc(100vh - 112px))}.inspector-command__search{gap:14px;min-height:70px;padding:0 19.25px}.inspector-command__pet-switcher{width:42px;height:42px}.inspector-command__search input{height:68.25px;font-size:22.75px}.inspector-command__results{max-height:455px;padding:8.75px}.inspector-command-row{gap:10.5px;min-height:59.5px;padding:0 12.25px 0 15.75px;border-radius:8.75px}.inspector-command-row__content{gap:14px}.inspector-command-row__name,.inspector-command-row__confirm{font-size:21px}.inspector-command-row__meta{gap:7px;font-size:19.25px}.inspector-command-row__actions,.inspector-command-row__confirm-actions{gap:1.75px}.inspector-command-row button{width:38.5px;min-height:38.5px;border-radius:7px;font-size:17.5px}.inspector-command-row button svg{width:19.25px;height:19.25px}.inspector-command-row button.is-danger,.inspector-command-row__confirm-actions button:not(.is-danger){padding:0 12.25px;font-size:19.25px}.inspector-command-row__rename{min-height:45.5px;padding-inline:10.5px;border-radius:7px;font-size:21px}.inspector-command__message{padding:28px 17.5px;font-size:21px}.inspector-command__message--error{padding:10.5px 17.5px;font-size:19.25px}.inspector-command__actions{gap:3.5px;padding:7px}.inspector-command-action{min-height:49px;gap:7px;padding:0 7px;border-radius:8.75px;font-size:17.5px}.inspector-command-action svg{width:19.25px;height:19.25px}.inspector-checkpoint-toast{top:17.5px;padding:8.75px 17.5px;font-size:19.25px}.inspector-label{transform:translateY(calc(-100% - 10.5px));max-width:min(665px,calc(100vw - 35px));padding:7px 12.25px;font-size:17.5px}.inspector-box-tag{padding:5.25px 8.75px;font-size:15.75px}.inspector-box-tag--padding{transform:translateY(0)}.inspector-text-chip{gap:8.75px;padding:5.25px 10.5px;font-size:15.75px}.inspector-text-chip__swatch{width:12.25px;height:12.25px}.inspector-distance-tag{padding:5.25px 10.5px;font-size:15.75px}.inspector-guide--vertical{width:24.5px}.inspector-guide--horizontal{height:24.5px}}\n"] }]
1964
+ args: [{ selector: 'inspector-overlay', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"inspector-root\" #overlayRoot>\n @if (checkpointService) {\n <dialog\n #checkpointDialog\n class=\"inspector-command-dialog\"\n aria-labelledby=\"inspector-command-title\"\n (cancel)=\"$event.preventDefault(); closeCheckpointCommandBar()\"\n (click)=\"handleCheckpointDialogClick($event)\"\n >\n <section class=\"inspector-command\" (click)=\"$event.stopPropagation()\">\n <header class=\"inspector-command__search\">\n <label\n id=\"inspector-command-title\"\n class=\"inspector-visually-hidden\"\n for=\"inspector-checkpoint-search\"\n >\n inspector-ng command palette\n </label>\n <button\n type=\"button\"\n class=\"inspector-command__pet-switcher\"\n [attr.aria-label]=\"'Change pet. Current pet: ' + activePet().name\"\n [title]=\"'Change pet: ' + activePet().name\"\n (click)=\"cyclePet($event)\"\n >\n <img\n class=\"inspector-command__pet-sprite\"\n [src]=\"activePet().spriteSrc\"\n alt=\"\"\n aria-hidden=\"true\"\n draggable=\"false\"\n />\n </button>\n <input\n #checkpointSearch\n id=\"inspector-checkpoint-search\"\n type=\"search\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n placeholder=\"inspector-ng\u2026\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"commandBarOpen()\"\n [value]=\"checkpointQuery()\"\n [attr.aria-controls]=\"'inspector-checkpoint-results inspector-command-actions'\"\n [attr.aria-activedescendant]=\"activeCommandResultId()\"\n (input)=\"updateCheckpointQuery($event)\"\n />\n </header>\n\n @if (checkpointService.error(); as error) {\n <p\n class=\"inspector-command__message inspector-command__message--error\"\n role=\"alert\"\n >\n {{ error }}\n </p>\n }\n\n <div\n id=\"inspector-checkpoint-results\"\n class=\"inspector-command__results\"\n role=\"listbox\"\n aria-label=\"Saved checkpoints\"\n >\n @if (checkpointService.loading()) {\n <p class=\"inspector-command__message\" role=\"status\">Loading\u2026</p>\n } @else if (\n !checkpointService.checkpoints().length && !checkpointQuery().trim()\n ) {\n <p class=\"inspector-command__message\" role=\"status\">\n No checkpoints yet\n </p>\n } @else if (\n !filteredCheckpoints().length &&\n !filteredInspectorActions().length &&\n !navigateTarget()\n ) {\n <p class=\"inspector-command__message\" role=\"status\">No matches</p>\n } @else {\n @for (\n checkpoint of filteredCheckpoints();\n track checkpoint.id;\n let index = $index\n ) {\n <div\n class=\"inspector-command-row\"\n role=\"option\"\n [id]=\"'inspector-checkpoint-' + checkpoint.id\"\n [attr.data-command-index]=\"index\"\n [attr.aria-selected]=\"activeCommandIndex() === index\"\n [class.is-active]=\"activeCommandIndex() === index\"\n [class.is-busy]=\"\n checkpointService.busy() && activeCommandIndex() === index\n \"\n (mouseenter)=\"setActiveCheckpoint(index)\"\n (click)=\"activateCheckpoint(checkpoint, $event)\"\n >\n @if (deletingCheckpointId() === checkpoint.id) {\n <span class=\"inspector-command-row__confirm\"\n >Delete \u201C{{ checkpoint.name }}\u201D?</span\n >\n <span class=\"inspector-command-row__confirm-actions\">\n <button\n type=\"button\"\n class=\"is-danger\"\n (click)=\"confirmDelete(checkpoint, $event)\"\n >\n Delete\n </button>\n <button type=\"button\" (click)=\"cancelDelete($event)\">\n Keep\n </button>\n </span>\n } @else if (editingCheckpointId() === checkpoint.id) {\n <input\n #checkpointRename\n class=\"inspector-command-row__rename\"\n aria-label=\"Checkpoint name\"\n [value]=\"renameDraft()\"\n (input)=\"updateRenameDraft($event)\"\n (click)=\"$event.stopPropagation()\"\n />\n } @else {\n <span class=\"inspector-command-row__content\">\n <span\n class=\"inspector-command-row__name\"\n [title]=\"checkpoint.name\"\n >\n <bdi dir=\"ltr\">\n @if (\n checkpointService.busy() &&\n activeCommandIndex() === index\n ) {\n Restoring\u2026\n } @else {\n {{ checkpoint.name }}\n }\n </bdi>\n </span>\n <span class=\"inspector-command-row__activity\">\n {{ checkpoint.lastUsedAt ? \"Used\" : \"Saved\" }}\n {{\n formatRelativeTime(checkpointActivityAt(checkpoint))\n }}\n </span>\n </span>\n <span class=\"inspector-command-row__actions\">\n <button\n type=\"button\"\n (click)=\"beginRename(checkpoint, $event)\"\n [attr.aria-label]=\"'Rename ' + checkpoint.name\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"m11.8 1.8 2.4 2.4-8.3 8.3-3.1.7.7-3.1zm-8 10.4 1.5-.3-1.2-1.2z\"\n />\n </svg>\n </button>\n <button\n type=\"button\"\n (click)=\"downloadCheckpoint(checkpoint, $event)\"\n [attr.aria-label]=\"'Export ' + checkpoint.name\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"M7.25 2h1.5v5.44l1.72-1.72L11.53 6.78 8 10.31 4.47 6.78l1.06-1.06 1.72 1.72zM2.5 12h11v1.5h-11z\"\n />\n </svg>\n </button>\n <button\n type=\"button\"\n (click)=\"beginDelete(checkpoint, $event)\"\n [attr.aria-label]=\"'Delete ' + checkpoint.name\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"M5.5 2h5l.5 1H14v1.25H2V3h3zm-2 3.25h9L12 14H4z\"\n />\n </svg>\n </button>\n </span>\n }\n </div>\n }\n @if (navigateTarget(); as target) {\n <div\n class=\"inspector-command-row inspector-command-row--navigate\"\n role=\"option\"\n id=\"inspector-navigate\"\n [attr.data-command-index]=\"filteredCheckpoints().length\"\n [attr.aria-selected]=\"\n activeCommandIndex() === filteredCheckpoints().length\n \"\n [class.is-active]=\"\n activeCommandIndex() === filteredCheckpoints().length\n \"\n [class.is-busy]=\"\n checkpointService.busy() &&\n activeCommandIndex() === filteredCheckpoints().length\n \"\n (mouseenter)=\"setActiveCheckpoint(filteredCheckpoints().length)\"\n (click)=\"navigateToQueryRoute()\"\n >\n <span class=\"inspector-command-row__content\">\n <span\n class=\"inspector-command-row__name\"\n [title]=\"'Navigate to ' + target\"\n >\n <bdi dir=\"ltr\">\n @if (\n checkpointService.busy() &&\n activeCommandIndex() === filteredCheckpoints().length\n ) {\n Navigating\u2026\n } @else {\n Go to {{ target }}\n }\n </bdi>\n </span>\n <span class=\"inspector-command-row__activity\">\n navigate \u00B7 keeps state\n </span>\n </span>\n </div>\n }\n }\n </div>\n\n @if (filteredInspectorActions().length) {\n <footer\n id=\"inspector-command-actions\"\n class=\"inspector-command__actions\"\n role=\"listbox\"\n aria-label=\"Inspector actions\"\n aria-orientation=\"horizontal\"\n >\n @for (\n action of filteredInspectorActions();\n track action.id;\n let index = $index\n ) {\n <button\n type=\"button\"\n role=\"option\"\n class=\"inspector-command-action\"\n [id]=\"'inspector-action-' + action.id\"\n [attr.data-command-index]=\"actionIndexOffset() + index\"\n [attr.aria-label]=\"action.ariaLabel\"\n [attr.aria-selected]=\"\n activeCommandIndex() === actionIndexOffset() + index\n \"\n [attr.aria-disabled]=\"checkpointService.busy()\"\n [class.is-selected]=\"\n activeCommandIndex() === actionIndexOffset() + index\n \"\n [class.is-active]=\"\n (action.id === 'select' && toolMode() === 'select') ||\n (action.id === 'type' && showTypography()) ||\n (action.id === 'vertical' &&\n toolMode() === 'guides' &&\n guideOrientation() === 'vertical') ||\n (action.id === 'horizontal' &&\n toolMode() === 'guides' &&\n guideOrientation() === 'horizontal')\n \"\n [disabled]=\"checkpointService.busy()\"\n (mouseenter)=\"setActiveInspectorAction(index)\"\n (click)=\"executeInspectorAction(action)\"\n >\n @switch (action.id) {\n @case (\"select\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M3 2l8 8-3 .7L6.7 13 6 10 3 2z\" />\n </svg>\n }\n @case (\"type\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M3 4V2h10v2h-4v10H7V4z\" />\n </svg>\n }\n @case (\"save\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"M2.5 2h9.6l1.4 1.4V14h-11zm2 1.5v3h6v-3zm.5 6V12h6V9.5z\"\n />\n </svg>\n }\n @case (\"import\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"M8 2l3.53 3.53-1.06 1.06L8.75 4.87V9.5h-1.5V4.87L5.53 6.59 4.47 5.53zM2.5 11h11v1.5h-11z\"\n />\n </svg>\n }\n @case (\"vertical\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M7.25 2h1.5v12h-1.5z\" />\n </svg>\n }\n @case (\"horizontal\") {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M2 7.25h12v1.5H2z\" />\n </svg>\n }\n }\n <span>{{ action.label }}</span>\n </button>\n }\n </footer>\n }\n </section>\n </dialog>\n }\n\n @if (checkpointToast(); as toast) {\n <p\n class=\"inspector-checkpoint-toast\"\n [class.inspector-checkpoint-toast--error]=\"checkpointToastIsError()\"\n [attr.role]=\"checkpointToastIsError() ? 'alert' : 'status'\"\n >\n {{ toast }}\n </p>\n }\n\n @if (enabled() && toolMode() === \"select\") {\n @if (hoverRect() && hoverHighlightEnabled) {\n <div\n class=\"inspector-box inspector-box--hover\"\n [style.left.px]=\"hoverRect()!.left\"\n [style.top.px]=\"hoverRect()!.top\"\n [style.width.px]=\"hoverRect()!.width\"\n [style.height.px]=\"hoverRect()!.height\"\n [style.--inspector-accent]=\"highlightColor\"\n ></div>\n }\n\n @if (selectedMeasurement(); as selected) {\n @if (selected.gap.active && selected.parentRect) {\n <div\n class=\"inspector-box inspector-box--gap\"\n [style.left.px]=\"selected.parentRect.left\"\n [style.top.px]=\"selected.parentRect.top\"\n [style.width.px]=\"selected.parentRect.width\"\n [style.height.px]=\"selected.parentRect.height\"\n ></div>\n <div\n class=\"inspector-box-tag inspector-box-tag--gap\"\n [style.left.px]=\"selected.parentRect.left\"\n [style.top.px]=\"selected.parentRect.top - 8\"\n >\n G {{ formatGap(selected) }}\n </div>\n }\n\n <div\n class=\"inspector-box inspector-box--margin\"\n [style.left.px]=\"selected.marginRect.left\"\n [style.top.px]=\"selected.marginRect.top\"\n [style.width.px]=\"selected.marginRect.width\"\n [style.height.px]=\"selected.marginRect.height\"\n ></div>\n\n <div\n class=\"inspector-box inspector-box--selected\"\n [style.left.px]=\"selected.rect.left\"\n [style.top.px]=\"selected.rect.top\"\n [style.width.px]=\"selected.rect.width\"\n [style.height.px]=\"selected.rect.height\"\n [style.--inspector-accent]=\"highlightColor\"\n >\n <div class=\"inspector-label\">{{ selectedMetaLine() }}</div>\n </div>\n\n <div\n class=\"inspector-box inspector-box--padding\"\n [style.left.px]=\"selected.paddingRect.left\"\n [style.top.px]=\"selected.paddingRect.top\"\n [style.width.px]=\"selected.paddingRect.width\"\n [style.height.px]=\"selected.paddingRect.height\"\n ></div>\n <div\n class=\"inspector-box-tag inspector-box-tag--spacing\"\n [style.left.px]=\"selected.rect.left\"\n [style.top.px]=\"selected.rect.top + selected.rect.height + 8\"\n >\n <span class=\"inspector-box-tag__margin\">M</span>\n <span>{{ formatEdges(selected.margin) }}</span>\n <span class=\"inspector-box-tag__separator\">\u00B7</span>\n <span class=\"inspector-box-tag__padding\">P</span>\n <span>{{ formatEdges(selected.padding) }}</span>\n </div>\n }\n }\n\n @if (enabled() && showTypography()) {\n @for (block of textBlocks(); track block.id) {\n <div\n class=\"inspector-text-chip\"\n [style.left.px]=\"block.rect.left\"\n [style.top.px]=\"block.rect.top - 8\"\n >\n <span\n class=\"inspector-text-chip__swatch\"\n [style.background]=\"block.styles.color\"\n ></span>\n <span>{{ block.styles.fontSize }}</span>\n <span>{{ block.styles.lineHeight }}</span>\n <span>{{ block.styles.color }}</span>\n </div>\n }\n }\n\n @if (enabled() && altPressed() && distanceOverlay(); as distance) {\n <div\n class=\"inspector-box inspector-box--distance\"\n [style.left.px]=\"distance.rectA.left\"\n [style.top.px]=\"distance.rectA.top\"\n [style.width.px]=\"distance.rectA.width\"\n [style.height.px]=\"distance.rectA.height\"\n ></div>\n <div\n class=\"inspector-box inspector-box--distance\"\n [style.left.px]=\"distance.rectB.left\"\n [style.top.px]=\"distance.rectB.top\"\n [style.width.px]=\"distance.rectB.width\"\n [style.height.px]=\"distance.rectB.height\"\n ></div>\n\n @for (\n connector of distance.connectors;\n track trackConnector($index, connector)\n ) {\n <div\n class=\"inspector-connector\"\n [class.inspector-connector--vertical]=\"connector.x1 === connector.x2\"\n [class.inspector-connector--horizontal]=\"connector.y1 === connector.y2\"\n [style.left.px]=\"Math.min(connector.x1, connector.x2)\"\n [style.top.px]=\"Math.min(connector.y1, connector.y2)\"\n [style.width.px]=\"Math.max(1, Math.abs(connector.x2 - connector.x1))\"\n [style.height.px]=\"Math.max(1, Math.abs(connector.y2 - connector.y1))\"\n ></div>\n }\n\n @for (horizontal of distance.horizontalDistances; track $index) {\n @if (horizontal.value > 0) {\n <div\n class=\"inspector-distance-line inspector-distance-line--horizontal\"\n [style.left.px]=\"Math.min(horizontal.x1!, horizontal.x2!)\"\n [style.top.px]=\"horizontal.y!\"\n [style.width.px]=\"Math.abs(horizontal.x2! - horizontal.x1!)\"\n ></div>\n <div\n class=\"inspector-distance-tag\"\n [style.left.px]=\"(horizontal.x1! + horizontal.x2!) / 2\"\n [style.top.px]=\"horizontal.y!\"\n >\n {{ formatValue(horizontal.value) }}\n </div>\n }\n }\n\n @for (vertical of distance.verticalDistances; track $index) {\n @if (vertical.value > 0) {\n <div\n class=\"inspector-distance-line inspector-distance-line--vertical\"\n [style.left.px]=\"vertical.x!\"\n [style.top.px]=\"Math.min(vertical.y1!, vertical.y2!)\"\n [style.height.px]=\"Math.abs(vertical.y2! - vertical.y1!)\"\n ></div>\n <div\n class=\"inspector-distance-tag inspector-distance-tag--vertical\"\n [style.left.px]=\"vertical.x!\"\n [style.top.px]=\"(vertical.y1! + vertical.y2!) / 2\"\n >\n {{ formatValue(vertical.value) }}\n </div>\n }\n }\n }\n\n @if (enabled()) {\n @if (toolMode() === \"guides\") {\n @if (guidePreview(); as preview) {\n <div\n class=\"inspector-guide inspector-guide--preview\"\n [class.inspector-guide--vertical]=\"preview.orientation === 'vertical'\"\n [class.inspector-guide--horizontal]=\"\n preview.orientation === 'horizontal'\n \"\n [style.left.px]=\"\n preview.orientation === 'vertical' ? preview.position : null\n \"\n [style.top.px]=\"\n preview.orientation === 'horizontal' ? preview.position : null\n \"\n [style.--inspector-guide]=\"guideColor\"\n >\n <span class=\"inspector-guide-line\"></span>\n </div>\n }\n }\n\n @for (guide of guides(); track guide.id) {\n <button\n type=\"button\"\n class=\"inspector-guide\"\n [class.inspector-guide--vertical]=\"guide.orientation === 'vertical'\"\n [class.inspector-guide--horizontal]=\"guide.orientation === 'horizontal'\"\n [class.inspector-guide--selected]=\"selectedGuideId() === guide.id\"\n [style.left.px]=\"\n guide.orientation === 'vertical' ? guide.position : null\n \"\n [style.top.px]=\"\n guide.orientation === 'horizontal' ? guide.position : null\n \"\n [style.--inspector-guide]=\"guideColor\"\n [attr.aria-label]=\"\n (guide.orientation === 'vertical' ? 'Vertical' : 'Horizontal') +\n ' guide at ' +\n formatValue(guide.position) +\n ' pixels'\n \"\n (pointerdown)=\"startGuideDrag($event, guide)\"\n >\n <span class=\"inspector-guide-line\"></span>\n </button>\n }\n\n @for (distance of guideDistances(); track distance.orientation + \"-\" + distance.start + \"-\" + distance.end) {\n <div\n class=\"inspector-guide-distance\"\n [class.inspector-guide-distance--vertical]=\"distance.orientation === 'vertical'\"\n [class.inspector-guide-distance--horizontal]=\"distance.orientation === 'horizontal'\"\n [style.left.px]=\"distance.orientation === 'vertical' ? distance.start : null\"\n [style.top.px]=\"distance.orientation === 'horizontal' ? distance.start : null\"\n [style.width.px]=\"distance.orientation === 'vertical' ? distance.value : null\"\n [style.height.px]=\"distance.orientation === 'horizontal' ? distance.value : null\"\n [style.--inspector-guide]=\"guideColor\"\n aria-hidden=\"true\"\n >\n <span class=\"inspector-guide-distance__line\"></span>\n <span class=\"inspector-guide-distance__tag\">\n {{ formatValue(distance.value) }} px\n </span>\n </div>\n }\n }\n</div>\n", styles: [":host{--inspector-panel: oklch(20% .012 280 / .92);--inspector-panel-edge: oklch(100% 0 0 / .08);--inspector-text: oklch(96% .005 280);--inspector-muted: oklch(70% .014 280);--inspector-faint: oklch(56% .012 280);--inspector-blue: oklch(68% .15 255);--inspector-blue-soft: oklch(68% .15 255 / .14);--inspector-orange: oklch(78% .14 70);--inspector-green: oklch(74% .15 150);--inspector-violet: oklch(72% .15 305);--inspector-radius: 8px;--inspector-shadow: 0 12px 32px oklch(6% .02 280 / .5);--inspector-font: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;--inspector-ease: cubic-bezier(.16, 1, .3, 1);position:fixed;inset:0;z-index:2147;pointer-events:none;font-family:var(--inspector-font);color:var(--inspector-text);-webkit-font-smoothing:antialiased}.inspector-root{position:fixed;inset:0;pointer-events:none}.inspector-command-dialog{--command-surface: oklch(17.5% .012 280);--command-surface-active: oklch(25% .012 280);--command-edge: oklch(100% 0 0 / .08);--command-text: oklch(96% .005 280);--command-muted: oklch(68% .014 280);--command-faint: oklch(52% .012 280);--command-accent: oklch(72% .13 255);--command-danger: oklch(68% .17 25);box-sizing:border-box;inset-block-start:max(10vh,48px);width:min(420px,calc(100vw - 24px));max-width:none;max-height:min(360px,calc(100vh - 64px));margin:0 auto;padding:0;overflow:hidden;border:1px solid var(--command-edge);border-radius:var(--inspector-radius);background:var(--command-surface);color:var(--command-text);box-shadow:var(--inspector-shadow);opacity:0;pointer-events:auto;transform:translateY(-4px);transition:opacity .1s ease,transform .1s ease,overlay .1s allow-discrete,display .1s allow-discrete;font-family:var(--inspector-font);-webkit-font-smoothing:antialiased}.inspector-command-dialog[open]{opacity:1;transform:none;transition-duration:.14s;transition-timing-function:var(--inspector-ease)}@starting-style{.inspector-command-dialog[open]{opacity:0;transform:translateY(-4px)}}.inspector-command-dialog::backdrop{background:#01010266}.inspector-command{display:grid;grid-template-rows:auto auto 1fr auto;min-width:0;min-height:0;max-height:min(360px,calc(100vh - 64px))}.inspector-command__search{display:flex;align-items:center;gap:8px;min-height:40px;padding:0 11px;border-bottom:1px solid var(--command-edge)}.inspector-command__pet-switcher{display:block;width:28px;height:28px;flex:0 0 auto;padding:0;overflow:hidden;border:0;border-radius:4px;background:transparent;cursor:pointer;opacity:.72;transition:opacity .14s var(--inspector-ease),transform .1s var(--inspector-ease)}.inspector-command__pet-sprite{display:block;width:500%;height:100%;max-width:none;image-rendering:pixelated;-webkit-user-select:none;user-select:none;transform:translate(0)}.inspector-command__search:focus-within .inspector-command__pet-switcher,.inspector-command__pet-switcher:hover,.inspector-command__pet-switcher:focus-visible{opacity:1}.inspector-command__pet-switcher:hover,.inspector-command__pet-switcher:focus-visible{background:#6aa7f41f}.inspector-command__pet-switcher:active{transform:scale(.94)}.inspector-command__pet-switcher:focus-visible{outline:1px solid var(--command-accent);outline-offset:1px}@media (prefers-reduced-motion: no-preference){.inspector-command__pet-sprite{animation:inspector-pet-cycle 1s steps(1,end) infinite}}@keyframes inspector-pet-cycle{0%,19.99%{transform:translate(0)}20%,39.99%{transform:translate(-20%)}40%,59.99%{transform:translate(-40%)}60%,79.99%{transform:translate(-60%)}80%,to{transform:translate(-80%)}}.inspector-command__search input,.inspector-command-row__rename{min-width:0;border:0;outline:0;background:transparent;color:var(--command-text);font:inherit}.inspector-command__search input{flex:1 1 auto;width:100%;height:39px;padding:0;font-size:13px;font-weight:450;line-height:1.3}.inspector-command__search input::placeholder{color:var(--command-faint);opacity:1}.inspector-command__search input::-webkit-search-cancel-button{display:none}.inspector-command__results{min-height:0;max-height:260px;overflow:auto;padding:5px;scrollbar-width:thin;scrollbar-color:oklch(100% 0 0 / .1) transparent}.inspector-command-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:6px;min-height:34px;padding:0 7px 0 9px;border-radius:5px;cursor:pointer;-webkit-user-select:none;user-select:none}.inspector-command-row.is-active{background:color-mix(in oklch,var(--command-surface-active) 92%,var(--command-accent));box-shadow:inset 0 0 0 1px #6aa7f452}.inspector-command-row.is-busy{cursor:wait;pointer-events:none;opacity:.7}.inspector-command-row__content{display:flex;align-items:baseline;gap:6px;min-width:0;overflow:hidden}.inspector-command-row__name{flex:0 1 auto;min-width:3ch;overflow:hidden;color:var(--command-text);font-size:12px;font-weight:500;line-height:1.25;text-overflow:ellipsis;white-space:nowrap;direction:rtl;text-align:left}.inspector-command-row__name bdi{direction:ltr;unicode-bidi:isolate}.inspector-command-row__activity{flex:0 0 auto;color:var(--command-faint);font-size:9px;font-weight:450;line-height:1;white-space:nowrap}.inspector-command-row.is-active .inspector-command-row__activity{color:#c2c3cc}.inspector-command-row--navigate{margin-top:4px;padding-top:5px;border-top:1px dashed var(--command-edge)}.inspector-command-row--navigate .inspector-command-row__name{color:color-mix(in oklch,var(--command-text) 78%,var(--command-accent))}.inspector-command-row--navigate .inspector-command-row__name:before{content:\"\\2192 \";color:var(--command-accent)}.inspector-command-row__actions,.inspector-command-row__confirm-actions{display:flex;align-items:center;gap:1px}.inspector-command-row__actions{opacity:0;pointer-events:none}.inspector-command-row.is-active .inspector-command-row__actions,.inspector-command-row:hover .inspector-command-row__actions,.inspector-command-row:focus-within .inspector-command-row__actions{opacity:1;pointer-events:auto}.inspector-command-row button{display:inline-grid;width:22px;min-height:22px;padding:0;place-items:center;border:0;border-radius:4px;background:transparent;color:var(--command-muted);cursor:pointer;font-family:inherit;font-size:10px;font-weight:550;line-height:1.2}.inspector-command-row button svg{width:11px;height:11px;fill:currentColor}.inspector-command-row button:hover{background:#ffffff12;color:var(--command-text)}.inspector-command-row button.is-danger{width:auto;padding:0 7px;color:var(--command-danger);font-size:11px}.inspector-command-row button.is-danger:hover{background:#ef66611f}.inspector-command-row__confirm-actions button:not(.is-danger){width:auto;padding:0 7px;font-size:11px}.inspector-command-row button:focus-visible,.inspector-command-row__rename:focus-visible{outline:1px solid var(--command-accent);outline-offset:1px}.inspector-command-row__confirm{grid-column:1;color:var(--command-text);font-size:12px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.inspector-command-row__rename{grid-column:1 / -1;min-height:26px;padding-inline:6px;border:1px solid oklch(72% .13 255 / .4);border-radius:4px;background:#191a21;font-size:12px;font-weight:500}.inspector-command__message{margin:0;padding:16px 10px;color:var(--command-faint);font-size:12px;line-height:1.4;text-align:center}.inspector-command__message--error{padding:6px 10px;border-bottom:1px solid oklch(55% .08 25 / .3);background:#39191780;color:#f7cbc7;text-align:left;font-size:11px}.inspector-command__actions{display:flex;gap:2px;padding:4px;border-top:1px solid var(--command-edge)}.inspector-command-action{display:flex;flex:1 1 0;min-width:0;min-height:28px;align-items:center;justify-content:center;gap:4px;padding:0 4px;overflow:hidden;border:0;border-radius:5px;background:transparent;color:var(--command-muted);cursor:pointer;font:inherit;font-size:10px;font-weight:500;line-height:1;text-align:left}.inspector-command-action svg{width:11px;height:11px;flex:0 0 auto;fill:currentColor}.inspector-command-action span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.inspector-command-action:hover:not(:disabled){background:#ffffff0f;color:var(--command-text)}.inspector-command-action.is-active{background:#6aa7f421;color:#c2daf9}.inspector-command-action.is-selected,.inspector-command-action.is-selected:hover:not(:disabled){background:var(--command-surface-active);color:var(--command-text);box-shadow:inset 0 0 0 1px #6aa7f49e}.inspector-command-action:disabled{cursor:wait;opacity:.45}.inspector-command-action:focus-visible{outline:1px solid var(--command-accent);outline-offset:-1px}.inspector-visually-hidden{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.inspector-checkpoint-toast{position:fixed;top:10px;left:50%;z-index:500;margin:0;display:flex;align-items:center;gap:6px;padding:6px 9px;border:1px solid var(--inspector-panel-edge);border-radius:6px;background:#0f1016f5;color:var(--inspector-text);box-shadow:0 8px 24px #01000352;font-size:11px;font-weight:500;line-height:1.3;pointer-events:none;transform:translate(-50%);animation:inspector-toast-in .16s var(--inspector-ease) both}.inspector-checkpoint-toast:before{width:5px;height:5px;flex:0 0 auto;border-radius:50%;background:var(--inspector-blue);content:\"\"}.inspector-checkpoint-toast--error{border-color:#e2726b4d;background:#351311f0;color:#fed2cd}.inspector-checkpoint-toast--error:before{background:var(--command-danger, oklch(68% .17 25))}@keyframes inspector-toast-in{0%{opacity:0;transform:translate(-50%,-4px)}to{opacity:1;transform:translate(-50%)}}@media (prefers-reduced-motion: reduce){.inspector-command-dialog{transition-duration:.01ms!important}.inspector-command-dialog,.inspector-command-dialog[open]{transform:none}.inspector-command__pet-switcher{transition:none}.inspector-command__pet-sprite{animation:none;transform:translate(0)}.inspector-checkpoint-toast{animation:none}}.inspector-box{position:fixed;box-sizing:border-box;pointer-events:none;border:1px solid var(--inspector-accent, var(--inspector-blue));background:color-mix(in srgb,var(--inspector-accent, var(--inspector-blue)) 8%,transparent)}.inspector-box--hover{opacity:.55}.inspector-box--selected{border-width:1.5px}.inspector-box--margin{border-color:#f0a646d1;background:#f0a64614}.inspector-box--padding{border-color:#5ac576d1;background:#5ac57614}.inspector-box--gap{border-color:#bb8aefb8;background:#bb8aef0d}.inspector-box--distance{border-style:dashed;border-color:#539af2b3;background:transparent}.inspector-label,.inspector-box-tag,.inspector-text-chip,.inspector-distance-tag,.inspector-guide-distance__tag{border:1px solid var(--inspector-panel-edge);border-radius:4px;background:#0e0f15c2;font-variant-numeric:tabular-nums;text-shadow:none}.inspector-label{position:absolute;left:0;top:0;transform:translateY(calc(-100% - 6px));max-width:min(380px,calc(100vw - 20px));padding:1px 3px;color:var(--inspector-text);box-shadow:none;backdrop-filter:none;-webkit-backdrop-filter:none;font-size:9px;font-weight:500;line-height:1.2;white-space:nowrap}.inspector-box-tag{position:fixed;transform:translateY(-100%);padding:2px 4px;color:var(--inspector-text);font-size:9px;font-weight:520;line-height:1;pointer-events:none}.inspector-box-tag__margin{color:#f5c076}.inspector-box-tag__padding{color:#95dfa4}.inspector-box-tag--gap{color:oklch(86% .09 305)}.inspector-box-tag--spacing{display:inline-flex;align-items:center;gap:3px;transform:translateY(0);white-space:nowrap}.inspector-box-tag__separator{color:var(--inspector-faint)}.inspector-text-chip{position:fixed;transform:translateY(-100%);display:inline-flex;gap:5px;align-items:center;padding:2px 4px;color:#e4e4e9;font-size:9px;font-weight:500;line-height:1;white-space:nowrap;pointer-events:none}.inspector-text-chip__swatch{width:7px;height:7px;border-radius:999px;border:1px solid oklch(100% 0 0 / .16);flex:0 0 auto}.inspector-connector{position:fixed;border-color:#539af2b8;border-style:dashed;pointer-events:none}.inspector-connector--vertical{border-left-width:1px;width:0}.inspector-connector--horizontal{border-top-width:1px;height:0}.inspector-distance-line{position:fixed;background:var(--inspector-blue);pointer-events:none}.inspector-distance-line--horizontal{height:1px}.inspector-distance-line--vertical{width:1px}.inspector-distance-tag{position:fixed;transform:translate(-50%,-50%);padding:2px 4px;border-color:#539af247;background:#0e0f15b8;color:var(--inspector-text);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);font-size:9px;font-weight:520;line-height:1;pointer-events:none}.inspector-guide{position:fixed;margin:0;padding:0;border:0;background:transparent;pointer-events:auto;cursor:grab}.inspector-guide--vertical{top:0;width:14px;height:100vh;transform:translate(-50%)}.inspector-guide--horizontal{left:0;width:100vw;height:14px;transform:translateY(-50%)}.inspector-guide--preview{opacity:.55;pointer-events:none;cursor:default}.inspector-guide--preview .inspector-guide-line{background:color-mix(in srgb,var(--inspector-guide, #ff7a00) 72%,transparent)}.inspector-guide-line{position:absolute;inset:0;pointer-events:none}.inspector-guide--vertical .inspector-guide-line{left:calc(50% - .5px);width:1px;height:100%;background:var(--inspector-guide, #ff7a00)}.inspector-guide--horizontal .inspector-guide-line{top:calc(50% - .5px);width:100%;height:1px;background:var(--inspector-guide, #ff7a00)}.inspector-guide--selected .inspector-guide-line{box-shadow:0 0 0 1px #ffffff80}.inspector-guide-distance{position:fixed;z-index:2;pointer-events:none}.inspector-guide-distance--vertical{top:50%;height:1px}.inspector-guide-distance--horizontal{left:50%;width:1px}.inspector-guide-distance__line{position:absolute;background:color-mix(in srgb,var(--inspector-guide, #ff7a00) 72%,transparent)}.inspector-guide-distance--vertical .inspector-guide-distance__line{inset:0;height:1px}.inspector-guide-distance--horizontal .inspector-guide-distance__line{inset:0;width:1px}.inspector-guide-distance__line:before,.inspector-guide-distance__line:after{position:absolute;content:\"\";background:var(--inspector-guide, #ff7a00)}.inspector-guide-distance--vertical .inspector-guide-distance__line:before,.inspector-guide-distance--vertical .inspector-guide-distance__line:after{top:-2px;width:1px;height:5px}.inspector-guide-distance--vertical .inspector-guide-distance__line:before{left:0}.inspector-guide-distance--vertical .inspector-guide-distance__line:after{right:0}.inspector-guide-distance--horizontal .inspector-guide-distance__line:before,.inspector-guide-distance--horizontal .inspector-guide-distance__line:after{left:-2px;width:5px;height:1px}.inspector-guide-distance--horizontal .inspector-guide-distance__line:before{top:0}.inspector-guide-distance--horizontal .inspector-guide-distance__line:after{bottom:0}.inspector-guide-distance__tag{position:absolute;padding:2px 4px;border-color:color-mix(in srgb,var(--inspector-guide, #ff7a00) 48%,transparent);background:#0e0f15eb;color:var(--inspector-text);box-shadow:0 1px 4px #01000357;font-size:9px;font-weight:520;line-height:1;white-space:nowrap}.inspector-guide-distance--vertical .inspector-guide-distance__tag{left:50%;top:0;transform:translate(-50%,-50%)}.inspector-guide-distance--horizontal .inspector-guide-distance__tag{left:0;top:50%;transform:translate(-50%,-50%)}@media (min-width: 769px) and (min-height: 769px){:host{--inspector-radius: 14px;--inspector-shadow: 0 21px 56px oklch(6% .02 280 / .5)}.inspector-command-dialog{inset-block-start:max(10vh,84px);width:min(735px,calc(100vw - 42px));max-height:min(630px,calc(100vh - 112px))}.inspector-command{max-height:min(630px,calc(100vh - 112px))}.inspector-command__search{gap:14px;min-height:70px;padding:0 19.25px}.inspector-command__pet-switcher{width:42px;height:42px}.inspector-command__search input{height:68.25px;font-size:22.75px}.inspector-command__results{max-height:455px;padding:8.75px}.inspector-command-row{gap:10.5px;min-height:59.5px;padding:0 12.25px 0 15.75px;border-radius:8.75px}.inspector-command-row__content{gap:10.5px}.inspector-command-row__name,.inspector-command-row__confirm{font-size:21px}.inspector-command-row__activity{font-size:15.75px}.inspector-command-row__actions,.inspector-command-row__confirm-actions{gap:1.75px}.inspector-command-row button{width:38.5px;min-height:38.5px;border-radius:7px;font-size:17.5px}.inspector-command-row button svg{width:19.25px;height:19.25px}.inspector-command-row button.is-danger,.inspector-command-row__confirm-actions button:not(.is-danger){padding:0 12.25px;font-size:19.25px}.inspector-command-row__rename{min-height:45.5px;padding-inline:10.5px;border-radius:7px;font-size:21px}.inspector-command__message{padding:28px 17.5px;font-size:21px}.inspector-command__message--error{padding:10.5px 17.5px;font-size:19.25px}.inspector-command__actions{gap:3.5px;padding:7px}.inspector-command-action{min-height:49px;gap:7px;padding:0 7px;border-radius:8.75px;font-size:17.5px}.inspector-command-action svg{width:19.25px;height:19.25px}.inspector-checkpoint-toast{top:14px;padding:7px 10px;font-size:13px}.inspector-label{transform:translateY(calc(-100% - 10.5px));max-width:min(665px,calc(100vw - 35px));padding:2px 4px;font-size:13px}.inspector-box-tag{padding:3px 5px;font-size:15.75px}.inspector-box-tag--spacing{gap:5px;transform:translateY(0)}.inspector-text-chip{gap:8.75px;padding:3px 5px;font-size:15.75px}.inspector-text-chip__swatch{width:12.25px;height:12.25px}.inspector-distance-tag,.inspector-guide-distance__tag{padding:3px 5px;font-size:15.75px}.inspector-guide--vertical{width:24.5px}.inspector-guide--horizontal{height:24.5px}}\n"] }]
1600
1965
  }], ctorParameters: () => [{ type: undefined, decorators: [{
1601
1966
  type: Inject,
1602
1967
  args: [PLATFORM_ID]