inspector-ng 0.0.9 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,4 +2,35 @@ export const createId = () => typeof crypto !== 'undefined' && 'randomUUID' in c
2
2
  ? crypto.randomUUID()
3
3
  : `${Date.now()}-${Math.random()}`;
4
4
  export const formatValue = (value) => Math.round(value);
5
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9pbnNwZWN0b3Itbmcvc3JjL2xpYi91dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxNQUFNLENBQUMsTUFBTSxRQUFRLEdBQUcsR0FBRyxFQUFFLENBQzNCLE9BQU8sTUFBTSxLQUFLLFdBQVcsSUFBSSxZQUFZLElBQUksTUFBTTtJQUNyRCxDQUFDLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRTtJQUNyQixDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7QUFFdkMsTUFBTSxDQUFDLE1BQU0sV0FBVyxHQUFHLENBQUMsS0FBYSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGNvbnN0IGNyZWF0ZUlkID0gKCkgPT5cbiAgdHlwZW9mIGNyeXB0byAhPT0gJ3VuZGVmaW5lZCcgJiYgJ3JhbmRvbVVVSUQnIGluIGNyeXB0b1xuICAgID8gY3J5cHRvLnJhbmRvbVVVSUQoKVxuICAgIDogYCR7RGF0ZS5ub3coKX0tJHtNYXRoLnJhbmRvbSgpfWA7XG5cbmV4cG9ydCBjb25zdCBmb3JtYXRWYWx1ZSA9ICh2YWx1ZTogbnVtYmVyKSA9PiBNYXRoLnJvdW5kKHZhbHVlKTtcbiJdfQ==
5
+ /** Compact relative time for Raycast-style list subtitles. */
6
+ export const formatRelativeTime = (iso, now = Date.now()) => {
7
+ const then = Date.parse(iso);
8
+ if (Number.isNaN(then)) {
9
+ return '';
10
+ }
11
+ const seconds = Math.round((now - then) / 1000);
12
+ if (seconds < 45) {
13
+ return 'just now';
14
+ }
15
+ if (seconds < 90) {
16
+ return '1m ago';
17
+ }
18
+ const minutes = Math.round(seconds / 60);
19
+ if (minutes < 60) {
20
+ return `${minutes}m ago`;
21
+ }
22
+ const hours = Math.round(minutes / 60);
23
+ if (hours < 24) {
24
+ return `${hours}h ago`;
25
+ }
26
+ const days = Math.round(hours / 24);
27
+ if (days < 30) {
28
+ return `${days}d ago`;
29
+ }
30
+ const months = Math.round(days / 30);
31
+ if (months < 12) {
32
+ return `${months}mo ago`;
33
+ }
34
+ return `${Math.round(months / 12)}y ago`;
35
+ };
36
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9pbnNwZWN0b3Itbmcvc3JjL2xpYi91dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxNQUFNLENBQUMsTUFBTSxRQUFRLEdBQUcsR0FBRyxFQUFFLENBQzNCLE9BQU8sTUFBTSxLQUFLLFdBQVcsSUFBSSxZQUFZLElBQUksTUFBTTtJQUNyRCxDQUFDLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRTtJQUNyQixDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7QUFFdkMsTUFBTSxDQUFDLE1BQU0sV0FBVyxHQUFHLENBQUMsS0FBYSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBRWhFLDhEQUE4RDtBQUM5RCxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLEdBQVcsRUFBRSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFVLEVBQUU7SUFDMUUsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM3QixJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUN2QixPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUFFRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ2hELElBQUksT0FBTyxHQUFHLEVBQUUsRUFBRSxDQUFDO1FBQ2pCLE9BQU8sVUFBVSxDQUFDO0lBQ3BCLENBQUM7SUFDRCxJQUFJLE9BQU8sR0FBRyxFQUFFLEVBQUUsQ0FBQztRQUNqQixPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDO0lBRUQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDekMsSUFBSSxPQUFPLEdBQUcsRUFBRSxFQUFFLENBQUM7UUFDakIsT0FBTyxHQUFHLE9BQU8sT0FBTyxDQUFDO0lBQzNCLENBQUM7SUFFRCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxFQUFFLENBQUMsQ0FBQztJQUN2QyxJQUFJLEtBQUssR0FBRyxFQUFFLEVBQUUsQ0FBQztRQUNmLE9BQU8sR0FBRyxLQUFLLE9BQU8sQ0FBQztJQUN6QixDQUFDO0lBRUQsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDcEMsSUFBSSxJQUFJLEdBQUcsRUFBRSxFQUFFLENBQUM7UUFDZCxPQUFPLEdBQUcsSUFBSSxPQUFPLENBQUM7SUFDeEIsQ0FBQztJQUVELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQ3JDLElBQUksTUFBTSxHQUFHLEVBQUUsRUFBRSxDQUFDO1FBQ2hCLE9BQU8sR0FBRyxNQUFNLFFBQVEsQ0FBQztJQUMzQixDQUFDO0lBRUQsT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUM7QUFDM0MsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGNvbnN0IGNyZWF0ZUlkID0gKCkgPT5cbiAgdHlwZW9mIGNyeXB0byAhPT0gJ3VuZGVmaW5lZCcgJiYgJ3JhbmRvbVVVSUQnIGluIGNyeXB0b1xuICAgID8gY3J5cHRvLnJhbmRvbVVVSUQoKVxuICAgIDogYCR7RGF0ZS5ub3coKX0tJHtNYXRoLnJhbmRvbSgpfWA7XG5cbmV4cG9ydCBjb25zdCBmb3JtYXRWYWx1ZSA9ICh2YWx1ZTogbnVtYmVyKSA9PiBNYXRoLnJvdW5kKHZhbHVlKTtcblxuLyoqIENvbXBhY3QgcmVsYXRpdmUgdGltZSBmb3IgUmF5Y2FzdC1zdHlsZSBsaXN0IHN1YnRpdGxlcy4gKi9cbmV4cG9ydCBjb25zdCBmb3JtYXRSZWxhdGl2ZVRpbWUgPSAoaXNvOiBzdHJpbmcsIG5vdyA9IERhdGUubm93KCkpOiBzdHJpbmcgPT4ge1xuICBjb25zdCB0aGVuID0gRGF0ZS5wYXJzZShpc28pO1xuICBpZiAoTnVtYmVyLmlzTmFOKHRoZW4pKSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgY29uc3Qgc2Vjb25kcyA9IE1hdGgucm91bmQoKG5vdyAtIHRoZW4pIC8gMTAwMCk7XG4gIGlmIChzZWNvbmRzIDwgNDUpIHtcbiAgICByZXR1cm4gJ2p1c3Qgbm93JztcbiAgfVxuICBpZiAoc2Vjb25kcyA8IDkwKSB7XG4gICAgcmV0dXJuICcxbSBhZ28nO1xuICB9XG5cbiAgY29uc3QgbWludXRlcyA9IE1hdGgucm91bmQoc2Vjb25kcyAvIDYwKTtcbiAgaWYgKG1pbnV0ZXMgPCA2MCkge1xuICAgIHJldHVybiBgJHttaW51dGVzfW0gYWdvYDtcbiAgfVxuXG4gIGNvbnN0IGhvdXJzID0gTWF0aC5yb3VuZChtaW51dGVzIC8gNjApO1xuICBpZiAoaG91cnMgPCAyNCkge1xuICAgIHJldHVybiBgJHtob3Vyc31oIGFnb2A7XG4gIH1cblxuICBjb25zdCBkYXlzID0gTWF0aC5yb3VuZChob3VycyAvIDI0KTtcbiAgaWYgKGRheXMgPCAzMCkge1xuICAgIHJldHVybiBgJHtkYXlzfWQgYWdvYDtcbiAgfVxuXG4gIGNvbnN0IG1vbnRocyA9IE1hdGgucm91bmQoZGF5cyAvIDMwKTtcbiAgaWYgKG1vbnRocyA8IDEyKSB7XG4gICAgcmV0dXJuIGAke21vbnRoc31tbyBhZ29gO1xuICB9XG5cbiAgcmV0dXJuIGAke01hdGgucm91bmQobW9udGhzIC8gMTIpfXkgYWdvYDtcbn07XG4iXX0=
@@ -38,7 +38,7 @@ class IndexedDbCheckpointRepository extends InspectorCheckpointRepository {
38
38
  const values = await this.request(database.transaction(STORE_NAME, 'readonly').objectStore(STORE_NAME).getAll());
39
39
  return values
40
40
  .filter(isCheckpointRecord)
41
- .sort(newestFirst$1);
41
+ .sort(recentActivityFirst);
42
42
  }
43
43
  async put(checkpoint) {
44
44
  const database = await this.database();
@@ -108,7 +108,7 @@ class InspectorCheckpointService {
108
108
  this.error.set(null);
109
109
  this.loading.set(true);
110
110
  try {
111
- this.checkpoints.set((await this.repository.list()).sort(newestFirst$1));
111
+ this.checkpoints.set((await this.repository.list()).sort(recentActivityFirst));
112
112
  }
113
113
  catch (error) {
114
114
  this.error.set(this.messageFor(error, 'Saved checkpoints could not be loaded. Try reloading the page.'));
@@ -139,7 +139,7 @@ class InspectorCheckpointService {
139
139
  state,
140
140
  };
141
141
  await this.repository.put(checkpoint);
142
- this.checkpoints.set([checkpoint, ...persisted].sort(newestFirst$1));
142
+ this.checkpoints.set([checkpoint, ...persisted].sort(recentActivityFirst));
143
143
  return checkpoint;
144
144
  }
145
145
  catch (error) {
@@ -158,7 +158,8 @@ class InspectorCheckpointService {
158
158
  }
159
159
  this.busy.set(true);
160
160
  try {
161
- const checkpoint = (await this.repository.list()).find((item) => item.id === id);
161
+ const checkpoints = await this.repository.list();
162
+ const checkpoint = checkpoints.find((item) => item.id === id);
162
163
  if (!checkpoint)
163
164
  throw new Error('Checkpoint not found. It may have been deleted in another tab.');
164
165
  const state = cloneJson(checkpoint.state, `“${checkpoint.name}” could not be decoded. Delete it and save a new checkpoint.`);
@@ -166,6 +167,14 @@ class InspectorCheckpointService {
166
167
  if (this.router && !await this.router.navigateByUrl(checkpoint.route)) {
167
168
  throw new Error(`The state was restored, but navigation to “${checkpoint.route}” was cancelled.`);
168
169
  }
170
+ const recentlyUsedCheckpoint = {
171
+ ...checkpoint,
172
+ lastUsedAt: new Date().toISOString(),
173
+ };
174
+ await this.repository.put(recentlyUsedCheckpoint);
175
+ this.checkpoints.set(checkpoints
176
+ .map((item) => item.id === id ? recentlyUsedCheckpoint : item)
177
+ .sort(recentActivityFirst));
169
178
  return true;
170
179
  }
171
180
  catch (error) {
@@ -193,7 +202,7 @@ class InspectorCheckpointService {
193
202
  if (!checkpoint)
194
203
  throw new Error('Checkpoint not found. It may have been deleted in another tab.');
195
204
  await this.repository.put({ ...checkpoint, name: nextName });
196
- this.checkpoints.set(checkpoints.map((item) => item.id === id ? { ...item, name: nextName } : item).sort(newestFirst$1));
205
+ this.checkpoints.set(checkpoints.map((item) => item.id === id ? { ...item, name: nextName } : item).sort(recentActivityFirst));
197
206
  return true;
198
207
  }
199
208
  catch (error) {
@@ -312,8 +321,15 @@ function createCheckpointId() {
312
321
  function isQuotaError(error) {
313
322
  return error instanceof DOMException && (error.name === 'QuotaExceededError' || error.name === 'NS_ERROR_DOM_QUOTA_REACHED');
314
323
  }
315
- function newestFirst$1(a, b) {
316
- return b.createdAt.localeCompare(a.createdAt) || b.id.localeCompare(a.id);
324
+ function checkpointActivityAt(checkpoint) {
325
+ return checkpoint.lastUsedAt && checkpoint.lastUsedAt > checkpoint.createdAt
326
+ ? checkpoint.lastUsedAt
327
+ : checkpoint.createdAt;
328
+ }
329
+ function recentActivityFirst(a, b) {
330
+ return checkpointActivityAt(b).localeCompare(checkpointActivityAt(a)) ||
331
+ b.createdAt.localeCompare(a.createdAt) ||
332
+ b.id.localeCompare(a.id);
317
333
  }
318
334
  function isCheckpointRecord(value) {
319
335
  if (!value || typeof value !== 'object')
@@ -324,6 +340,7 @@ function isCheckpointRecord(value) {
324
340
  typeof checkpoint.name === 'string' &&
325
341
  typeof checkpoint.route === 'string' &&
326
342
  typeof checkpoint.createdAt === 'string' &&
343
+ (checkpoint.lastUsedAt === undefined || typeof checkpoint.lastUsedAt === 'string') &&
327
344
  'state' in checkpoint;
328
345
  }
329
346
 
@@ -590,14 +607,14 @@ const getTargetElement = (point, overlayElement) => {
590
607
  function fuzzyCheckpoints(checkpoints, query) {
591
608
  const normalizedQuery = normalize(query.trim());
592
609
  if (!normalizedQuery)
593
- return [...checkpoints].sort(newestFirst);
610
+ return [...checkpoints].sort(recentActivityFirst);
594
611
  return checkpoints
595
612
  .map((checkpoint) => {
596
613
  const score = fuzzyScore(checkpoint.name, normalizedQuery);
597
614
  return score === null ? null : { checkpoint, score };
598
615
  })
599
616
  .filter((item) => item !== null)
600
- .sort((a, b) => b.score - a.score || newestFirst(a.checkpoint, b.checkpoint))
617
+ .sort((a, b) => b.score - a.score || recentActivityFirst(a.checkpoint, b.checkpoint))
601
618
  .map(({ checkpoint }) => checkpoint);
602
619
  }
603
620
  function fuzzyScore(value, normalizedQuery) {
@@ -633,19 +650,49 @@ function normalize(value) {
633
650
  .replace(/[\u0300-\u036f]/g, '')
634
651
  .toLocaleLowerCase();
635
652
  }
636
- function newestFirst(a, b) {
637
- return b.createdAt.localeCompare(a.createdAt) || b.id.localeCompare(a.id);
638
- }
639
653
 
640
654
  const createId = () => typeof crypto !== 'undefined' && 'randomUUID' in crypto
641
655
  ? crypto.randomUUID()
642
656
  : `${Date.now()}-${Math.random()}`;
643
657
  const formatValue = (value) => Math.round(value);
658
+ /** Compact relative time for Raycast-style list subtitles. */
659
+ const formatRelativeTime = (iso, now = Date.now()) => {
660
+ const then = Date.parse(iso);
661
+ if (Number.isNaN(then)) {
662
+ return '';
663
+ }
664
+ const seconds = Math.round((now - then) / 1000);
665
+ if (seconds < 45) {
666
+ return 'just now';
667
+ }
668
+ if (seconds < 90) {
669
+ return '1m ago';
670
+ }
671
+ const minutes = Math.round(seconds / 60);
672
+ if (minutes < 60) {
673
+ return `${minutes}m ago`;
674
+ }
675
+ const hours = Math.round(minutes / 60);
676
+ if (hours < 24) {
677
+ return `${hours}h ago`;
678
+ }
679
+ const days = Math.round(hours / 24);
680
+ if (days < 30) {
681
+ return `${days}d ago`;
682
+ }
683
+ const months = Math.round(days / 30);
684
+ if (months < 12) {
685
+ return `${months}mo ago`;
686
+ }
687
+ return `${Math.round(months / 12)}y ago`;
688
+ };
644
689
 
645
690
  class inspectorComponent {
646
691
  constructor(platformId) {
647
692
  this.Math = Math;
693
+ this.checkpointActivityAt = checkpointActivityAt;
648
694
  this.formatValue = formatValue;
695
+ this.formatRelativeTime = formatRelativeTime;
649
696
  this.guideHitboxSize = GUIDE_HITBOX_SIZE;
650
697
  this.overlayRoot = viewChild('overlayRoot');
651
698
  this.checkpointDialog = viewChild('checkpointDialog');
@@ -1326,11 +1373,11 @@ class inspectorComponent {
1326
1373
  return null;
1327
1374
  }
1328
1375
  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 }); }
1329
- 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", persistOnReload: "persistOnReload" }, 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 (enabled()) {\n <div class=\"inspector-toolbar\">\n <div class=\"inspector-toolbar__rail\">\n <button\n type=\"button\"\n class=\"inspector-icon-button\"\n [class.is-active]=\"toolMode() === 'select'\"\n (click)=\"setToolMode('select')\"\n aria-label=\"Select mode\"\n >\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 <span class=\"inspector-tooltip\" role=\"tooltip\">Select</span>\n </button>\n\n @if (checkpointService) {\n <button\n type=\"button\"\n class=\"inspector-icon-button\"\n (click)=\"saveCheckpoint()\"\n [disabled]=\"checkpointService.busy()\"\n aria-label=\"Save checkpoint\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M2.5 2h9.6l1.4 1.4V14h-11zm2 1.5v3h6v-3zm.5 6V12h6V9.5z\" />\n </svg>\n <span class=\"inspector-tooltip\" role=\"tooltip\">Save checkpoint</span>\n </button>\n }\n\n <div class=\"inspector-toolbar__secondary\">\n <div class=\"inspector-toolbar__reveal\">\n <div class=\"inspector-toolbar__reveal-inner\">\n <button\n type=\"button\"\n class=\"inspector-icon-button\"\n [class.is-active]=\"showTypography()\"\n (click)=\"toggleTypography()\"\n aria-label=\"Typography overlay\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M3 4V2h10v2h-4v10H7V4z\" />\n </svg>\n <span class=\"inspector-tooltip\" role=\"tooltip\">Typography</span>\n </button>\n\n <button\n type=\"button\"\n class=\"inspector-icon-button\"\n [class.is-active]=\"toolMode() === 'guides' && guideOrientation() === 'vertical'\"\n (click)=\"activateGuideOrientation('vertical')\"\n aria-label=\"Vertical guides\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M7.25 2h1.5v12h-1.5z\" />\n </svg>\n <span class=\"inspector-tooltip\" role=\"tooltip\">Vertical guides</span>\n </button>\n\n <button\n type=\"button\"\n class=\"inspector-icon-button\"\n [class.is-active]=\"toolMode() === 'guides' && guideOrientation() === 'horizontal'\"\n (click)=\"activateGuideOrientation('horizontal')\"\n aria-label=\"Horizontal guides\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M2 7.25h12v1.5H2z\" />\n </svg>\n <span class=\"inspector-tooltip\" role=\"tooltip\">Horizontal guides</span>\n </button>\n </div>\n </div>\n </div>\n\n <span class=\"inspector-toolbar__divider\" aria-hidden=\"true\"></span>\n <button\n type=\"button\"\n class=\"inspector-icon-button inspector-icon-button--power\"\n (click)=\"disableInspector()\"\n aria-label=\"Disable inspector; press M to enable\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path 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 </svg>\n <span class=\"inspector-tooltip\" role=\"tooltip\">Disable</span>\n </button>\n </div>\n </div>\n }\n\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 id=\"inspector-command-title\" class=\"inspector-visually-hidden\" for=\"inspector-checkpoint-search\">\n Search checkpoints\n </label>\n <input\n #checkpointSearch\n id=\"inspector-checkpoint-search\"\n type=\"search\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n placeholder=\"Find a checkpoint\u2026\"\n [value]=\"checkpointQuery()\"\n [attr.aria-controls]=\"'inspector-checkpoint-results'\"\n [attr.aria-activedescendant]=\"filteredCheckpoints().length ? 'inspector-checkpoint-' + filteredCheckpoints()[activeCheckpointIndex()].id : null\"\n (input)=\"updateCheckpointQuery($event)\"\n />\n </header>\n\n @if (checkpointService.error(); as error) {\n <p class=\"inspector-command__message inspector-command__message--error\" role=\"alert\">{{ error }}</p>\n }\n\n <div id=\"inspector-checkpoint-results\" class=\"inspector-command__results\" role=\"listbox\" aria-label=\"Saved checkpoints\">\n @if (checkpointService.loading()) {\n <p class=\"inspector-command__message\" role=\"status\">Loading checkpoints\u2026</p>\n } @else if (!checkpointService.checkpoints().length) {\n <p class=\"inspector-command__message\" role=\"status\">No checkpoints yet. Save one from the Inspector toolbar.</p>\n } @else if (!filteredCheckpoints().length) {\n <p class=\"inspector-command__message\" role=\"status\">No checkpoint matches \u201C{{ checkpointQuery() }}\u201D.</p>\n } @else {\n @for (checkpoint of filteredCheckpoints(); track checkpoint.id; let index = $index) {\n <div\n class=\"inspector-command-row\"\n role=\"option\"\n [id]=\"'inspector-checkpoint-' + checkpoint.id\"\n [attr.data-checkpoint-index]=\"index\"\n [attr.aria-selected]=\"activeCheckpointIndex() === index\"\n [class.is-active]=\"activeCheckpointIndex() === index\"\n [class.is-busy]=\"checkpointService.busy() && activeCheckpointIndex() === index\"\n (mouseenter)=\"setActiveCheckpoint(index)\"\n (click)=\"deletingCheckpointId() === checkpoint.id || editingCheckpointId() === checkpoint.id ? null : restoreCheckpoint(checkpoint)\"\n >\n @if (deletingCheckpointId() === checkpoint.id) {\n <span class=\"inspector-command-row__confirm\">Delete \u201C{{ checkpoint.name }}\u201D?</span>\n <span class=\"inspector-command-row__confirm-actions\">\n <button type=\"button\" class=\"is-danger\" (click)=\"confirmDelete(checkpoint, $event)\">Delete checkpoint</button>\n <button type=\"button\" (click)=\"cancelDelete($event)\">Keep checkpoint</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__name\">\n @if (checkpointService.busy() && activeCheckpointIndex() === index) {\n Restoring \u201C{{ checkpoint.name }}\u201D\u2026\n } @else {\n {{ checkpoint.name }}\n }\n </span>\n <span class=\"inspector-command-row__actions\">\n <button type=\"button\" (click)=\"beginRename(checkpoint, $event)\" [attr.aria-label]=\"'Rename ' + checkpoint.name\">\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path 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\" /></svg>\n </button>\n <button type=\"button\" (click)=\"beginDelete(checkpoint, $event)\" [attr.aria-label]=\"'Delete ' + checkpoint.name\">\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M5.5 2h5l.5 1H14v1.25H2V3h3zm-2 3.25h9L12 14H4z\" /></svg>\n </button>\n </span>\n }\n </div>\n }\n }\n </div>\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 >{{ toast }}</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 (pointerdown)=\"startGuideDrag($event, guide)\"\n >\n <span class=\"inspector-guide-line\"></span>\n </button>\n }\n }\n</div>\n", styles: [":host{--inspector-panel: rgba(27, 29, 36, .94);--inspector-panel-edge: rgba(255, 255, 255, .08);--inspector-text: #f3f4f6;--inspector-muted: #9ca3af;--inspector-blue: #4f8cff;--inspector-orange: #f59e0b;--inspector-green: #22c55e;--inspector-violet: #a855f7;position:fixed;inset:0;z-index:2147;pointer-events:none;font-family:SF Pro Display,Segoe UI,sans-serif}.inspector-root{position:fixed;inset:0;pointer-events:none}.inspector-toolbar{position:fixed;top:12px;right:12px;display:block;pointer-events:auto;z-index:10000}.inspector-toolbar__rail{display:flex;flex-direction:column;align-items:center;gap:2px;width:30px;padding:2px;border-radius:4px;border:1px solid var(--inspector-panel-edge);background:var(--inspector-panel);box-shadow:0 18px 40px #00000052;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.inspector-toolbar__divider{width:16px;height:1px;margin-block:2px;background:var(--inspector-panel-edge)}.inspector-toolbar__secondary{display:grid;width:24px}.inspector-toolbar__reveal{display:grid;grid-template-rows:0fr;opacity:0;transform:translateY(-4px);transition:grid-template-rows .18s cubic-bezier(.16,1,.3,1),opacity .12s cubic-bezier(.16,1,.3,1),transform .18s cubic-bezier(.16,1,.3,1)}.inspector-toolbar__reveal-inner{display:grid;gap:2px;min-height:0;overflow:hidden}.inspector-toolbar__rail:hover .inspector-toolbar__reveal,.inspector-toolbar__rail:focus-within .inspector-toolbar__reveal{grid-template-rows:1fr;opacity:1;transform:translateY(2px)}.inspector-command-dialog{--command-surface: oklch(20% .012 270);--command-surface-raised: oklch(25% .014 270);--command-surface-active: oklch(27% .018 270);--command-edge: oklch(39% .014 270);--command-text: oklch(95% .008 270);--command-muted: oklch(73% .018 270);--command-accent: oklch(76% .08 260);--command-danger: oklch(71% .17 25);box-sizing:border-box;inset-block-start:max(40px,10vh);width:min(480px,calc(100vw - 24px));max-width:none;max-height:min(400px,calc(100vh - 64px));margin:0 auto;padding:0;overflow:hidden;border:1px solid var(--command-edge);border-radius:4px;background:var(--command-surface);color:var(--command-text);box-shadow:0 20px 56px #0102038f;opacity:0;pointer-events:auto;transform:translateY(-6px);transition:opacity .12s cubic-bezier(.7,0,.84,0),transform .12s cubic-bezier(.7,0,.84,0),overlay .12s allow-discrete,display .12s allow-discrete}.inspector-command-dialog[open]{opacity:1;transform:translateY(0);transition-duration:.16s;transition-timing-function:cubic-bezier(.16,1,.3,1)}@starting-style{.inspector-command-dialog[open]{opacity:0;transform:translateY(-6px)}}.inspector-command-dialog::backdrop{background:#0102037a}.inspector-command{display:grid;min-width:0}.inspector-command__search{min-height:44px;padding-inline:12px;border-bottom:1px solid var(--command-edge)}.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{width:100%;height:43px;padding:0;font-size:14px;line-height:1.45}.inspector-command__search:has(input:focus-visible){box-shadow:inset 0 -2px var(--command-accent)}.inspector-command__search input::placeholder{color:var(--command-muted);opacity:1}.inspector-command__search input::-webkit-search-cancel-button{display:none}.inspector-command__results{max-height:304px;overflow:auto;padding-block:3px;scrollbar-color:var(--command-edge) transparent}.inspector-command-row{position:relative;display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:6px;min-height:38px;padding-inline:12px 6px;cursor:pointer;-webkit-user-select:none;user-select:none}.inspector-command-row.is-active{background:var(--command-surface-active)}.inspector-command-row.is-busy{cursor:wait;pointer-events:none}.inspector-command-row__name{overflow:hidden;color:var(--command-text);font-size:12px;font-weight:540;line-height:1.45;text-overflow:ellipsis;white-space:nowrap}.inspector-command-row.is-active .inspector-command-row__name{font-weight:700}.inspector-command-row__actions,.inspector-command-row__confirm-actions{display:flex;align-items:center;gap:4px}.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:26px;min-height:26px;padding:5px;place-items:center;border:1px solid transparent;border-radius:3px;background:transparent;color:var(--command-muted);cursor:pointer;font-family:inherit;font-size:10px;font-weight:600;line-height:1.3}.inspector-command-row button svg{width:12px;height:12px;fill:currentColor}.inspector-command-row button:hover{border-color:var(--command-edge);background:var(--command-surface-raised);color:var(--command-text)}.inspector-command-row button.is-danger{color:var(--command-danger)}.inspector-command-row button:focus-visible,.inspector-command-row__rename:focus-visible{outline:2px solid var(--command-accent);outline-offset:2px}.inspector-command-row__confirm{grid-column:1;color:var(--command-text);font-size:12px;font-weight:620}.inspector-command-row__rename{grid-column:1 / -1;min-height:30px;padding-inline:8px;border:1px solid var(--command-accent);border-radius:3px;background:var(--command-surface-raised);font-size:12px}.inspector-command__message{margin:0;padding:20px 12px;color:var(--command-muted);font-size:12px;line-height:1.55;text-align:center}.inspector-command__message--error{padding-block:9px;border-bottom:1px solid oklch(45% .1 25);background:#3f1917;color:oklch(89% .06 25);text-align:left}.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:12px;left:50%;z-index:500;margin:0;padding:8px 12px;border:1px solid oklch(48% .04 150);border-radius:4px;background:#152619;color:#cfe9d4;box-shadow:0 16px 40px #01020375;font-size:11px;font-weight:620;line-height:1.35;pointer-events:none;transform:translate(-50%)}.inspector-checkpoint-toast--error{border-color:#9c433f;background:#431614;color:oklch(92% .05 25)}.inspector-icon-button{display:inline-flex;align-items:center;justify-content:center;height:24px;border:0;border-radius:3px;background:transparent;color:var(--inspector-muted);cursor:pointer;transition:background .1s cubic-bezier(.16,1,.3,1),color .1s cubic-bezier(.16,1,.3,1),transform .1s cubic-bezier(.16,1,.3,1);font:inherit;font-size:11px;letter-spacing:.02em}.inspector-icon-button{position:relative;width:24px}.inspector-icon-button svg{width:13px;height:13px;fill:currentColor}.inspector-icon-button:active{transform:translateY(1px)}.inspector-icon-button:focus-visible{outline:2px solid var(--inspector-blue);outline-offset:2px}.inspector-icon-button:hover{background:#ffffff14;color:var(--inspector-text)}.inspector-icon-button.is-active{background:#4f8cff2e;color:#dbeafe}.inspector-icon-button--power:hover{background:#ef444429;color:#fecaca}.inspector-tooltip{position:absolute;top:50%;right:calc(100% + 7px);z-index:20;width:max-content;padding:4px 6px;border:1px solid var(--inspector-panel-edge);border-radius:3px;background:#111318fa;color:var(--inspector-text);font-size:10px;font-weight:600;line-height:1.2;opacity:0;pointer-events:none;transform:translate(3px,-50%);transition:opacity .12s cubic-bezier(.16,1,.3,1),transform .12s cubic-bezier(.16,1,.3,1);white-space:nowrap}.inspector-icon-button:hover .inspector-tooltip,.inspector-icon-button:focus-visible .inspector-tooltip{opacity:1;transform:translateY(-50%)}@media (prefers-reduced-motion: reduce){.inspector-toolbar__reveal,.inspector-icon-button,.inspector-tooltip,.inspector-command-dialog,.inspector-command-row__marker{transition-duration:.01ms}.inspector-command-dialog,.inspector-command-dialog[open]{transform: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:#f59e0bd1;background:#f59e0b14}.inspector-box--padding{border-color:#22c55ed1;background:#22c55e14}.inspector-box--gap{border-color:#a855f7b8;background:#a855f70a}.inspector-box--distance{border-style:dashed;border-color:#4f8cffb3;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% - 8px));max-width:min(420px,calc(100vw - 24px));padding:6px 9px;border-radius:999px;border:1px solid var(--inspector-panel-edge);background:var(--inspector-panel);color:var(--inspector-text);box-shadow:0 18px 40px #00000042;font-size:11px;line-height:1;white-space:nowrap}.inspector-box-tag{position:fixed;transform:translateY(-100%);padding:4px 6px;border-radius:999px;border:1px solid var(--inspector-panel-edge);background:#111827f0;color:var(--inspector-text);box-shadow:0 12px 24px #0003;font-size:10px;line-height:1;pointer-events:none}.inspector-box-tag--margin{color:#fbbf24}.inspector-box-tag--padding{color:#86efac;transform:translateY(0)}.inspector-box-tag--gap{color:#d8b4fe}.inspector-text-chip{position:fixed;transform:translateY(-100%);display:inline-flex;gap:6px;align-items:center;padding:4px 6px;border-radius:999px;border:1px solid var(--inspector-panel-edge);background:#111827f0;color:#e5e7eb;box-shadow:0 12px 24px #00000038;font-size:10px;line-height:1;white-space:nowrap;pointer-events:none}.inspector-text-chip__swatch{width:8px;height:8px;border-radius:999px;border:1px solid rgba(255,255,255,.18);flex:0 0 auto}.inspector-connector{position:fixed;border-color:#4f8cffb8;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:5px 7px;border-radius:999px;border:1px solid var(--inspector-panel-edge);background:#111827f2;color:var(--inspector-text);font-size:10px;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}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1376
+ 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", persistOnReload: "persistOnReload" }, 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 id=\"inspector-command-title\" class=\"inspector-visually-hidden\" for=\"inspector-checkpoint-search\">\n Search checkpoints\n </label>\n <svg class=\"inspector-command__search-icon\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M7 2.25a4.75 4.75 0 1 0 2.94 8.48l2.91 2.92.8-.8-2.92-2.91A4.75 4.75 0 0 0 7 2.25Zm-3.62 4.75a3.62 3.62 0 1 1 7.24 0 3.62 3.62 0 0 1-7.24 0Z\" />\n </svg>\n <input\n #checkpointSearch\n id=\"inspector-checkpoint-search\"\n type=\"search\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n placeholder=\"Search checkpoints\u2026\"\n [value]=\"checkpointQuery()\"\n [attr.aria-controls]=\"'inspector-checkpoint-results'\"\n [attr.aria-activedescendant]=\"filteredCheckpoints().length ? 'inspector-checkpoint-' + filteredCheckpoints()[activeCheckpointIndex()].id : null\"\n (input)=\"updateCheckpointQuery($event)\"\n />\n </header>\n\n @if (checkpointService.error(); as error) {\n <p class=\"inspector-command__message inspector-command__message--error\" role=\"alert\">{{ error }}</p>\n }\n\n <div id=\"inspector-checkpoint-results\" class=\"inspector-command__results\" role=\"listbox\" aria-label=\"Saved checkpoints\">\n @if (checkpointService.loading()) {\n <p class=\"inspector-command__message\" role=\"status\">Loading\u2026</p>\n } @else if (!checkpointService.checkpoints().length) {\n <p class=\"inspector-command__message\" role=\"status\">No checkpoints yet</p>\n } @else if (!filteredCheckpoints().length) {\n <p class=\"inspector-command__message\" role=\"status\">No matches</p>\n } @else {\n @for (checkpoint of filteredCheckpoints(); track checkpoint.id; let index = $index) {\n <div\n class=\"inspector-command-row\"\n role=\"option\"\n [id]=\"'inspector-checkpoint-' + checkpoint.id\"\n [attr.data-checkpoint-index]=\"index\"\n [attr.aria-selected]=\"activeCheckpointIndex() === index\"\n [class.is-active]=\"activeCheckpointIndex() === index\"\n [class.is-busy]=\"checkpointService.busy() && activeCheckpointIndex() === index\"\n (mouseenter)=\"setActiveCheckpoint(index)\"\n (click)=\"deletingCheckpointId() === checkpoint.id || editingCheckpointId() === checkpoint.id ? null : restoreCheckpoint(checkpoint)\"\n >\n @if (deletingCheckpointId() === checkpoint.id) {\n <span class=\"inspector-command-row__confirm\">Delete \u201C{{ checkpoint.name }}\u201D?</span>\n <span class=\"inspector-command-row__confirm-actions\">\n <button type=\"button\" class=\"is-danger\" (click)=\"confirmDelete(checkpoint, $event)\">Delete</button>\n <button type=\"button\" (click)=\"cancelDelete($event)\">Keep</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 (checkpointService.busy() && activeCheckpointIndex() === index) {\n Restoring\u2026\n } @else {\n {{ checkpoint.name }}\n }\n </span>\n <span class=\"inspector-command-row__meta\">\n <span class=\"inspector-command-row__route\">{{ checkpoint.route || '/' }}</span>\n <span class=\"inspector-command-row__separator\" aria-hidden=\"true\">\u00B7</span>\n <span class=\"inspector-command-row__activity\">\n {{ checkpoint.lastUsedAt ? 'Used' : 'Saved' }} {{ formatRelativeTime(checkpointActivityAt(checkpoint)) }}\n </span>\n </span>\n </span>\n <span class=\"inspector-command-row__actions\">\n <button type=\"button\" (click)=\"beginRename(checkpoint, $event)\" [attr.aria-label]=\"'Rename ' + checkpoint.name\">\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path 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\" /></svg>\n </button>\n <button type=\"button\" (click)=\"beginDelete(checkpoint, $event)\" [attr.aria-label]=\"'Delete ' + checkpoint.name\">\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M5.5 2h5l.5 1H14v1.25H2V3h3zm-2 3.25h9L12 14H4z\" /></svg>\n </button>\n </span>\n }\n </div>\n }\n }\n </div>\n\n <footer class=\"inspector-command__actions\" aria-label=\"Inspector actions\">\n <button\n type=\"button\"\n class=\"inspector-command-action\"\n [class.is-active]=\"toolMode() === 'select'\"\n (click)=\"setToolMode('select'); closeCheckpointCommandBar()\"\n aria-label=\"Select mode\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M3 2l8 8-3 .7L6.7 13 6 10 3 2z\" /></svg>\n <span>Select</span>\n </button>\n <button\n type=\"button\"\n class=\"inspector-command-action\"\n [class.is-active]=\"showTypography()\"\n (click)=\"toggleTypography(); closeCheckpointCommandBar()\"\n aria-label=\"Toggle typography overlay\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M3 4V2h10v2h-4v10H7V4z\" /></svg>\n <span>Type</span>\n </button>\n <button\n type=\"button\"\n class=\"inspector-command-action\"\n (click)=\"saveCheckpoint()\"\n [disabled]=\"checkpointService.busy()\"\n aria-label=\"Save checkpoint\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M2.5 2h9.6l1.4 1.4V14h-11zm2 1.5v3h6v-3zm.5 6V12h6V9.5z\" /></svg>\n <span>Save</span>\n </button>\n <button\n type=\"button\"\n class=\"inspector-command-action\"\n [class.is-active]=\"toolMode() === 'guides' && guideOrientation() === 'vertical'\"\n (click)=\"activateGuideOrientation('vertical'); closeCheckpointCommandBar()\"\n aria-label=\"Vertical guides\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M7.25 2h1.5v12h-1.5z\" /></svg>\n <span>V</span>\n </button>\n <button\n type=\"button\"\n class=\"inspector-command-action\"\n [class.is-active]=\"toolMode() === 'guides' && guideOrientation() === 'horizontal'\"\n (click)=\"activateGuideOrientation('horizontal'); closeCheckpointCommandBar()\"\n aria-label=\"Horizontal guides\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M2 7.25h12v1.5H2z\" /></svg>\n <span>H</span>\n </button>\n <button\n type=\"button\"\n class=\"inspector-command-action inspector-command-action--danger\"\n (click)=\"closeCheckpointCommandBar(); disableInspector()\"\n aria-label=\"Disable inspector; press M to enable\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path 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\" /></svg>\n <span>Off</span>\n </button>\n </footer>\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 >{{ toast }}</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 (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(26% .02 265);--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__search-icon{width:14px;height:14px;flex:0 0 auto;fill:var(--command-faint)}.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)}.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__activity{color:var(--command-muted)}.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:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:2px;padding:4px;border-top:1px solid var(--command-edge)}.inspector-command-action{display:flex;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--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-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}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1330
1377
  }
1331
1378
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: inspectorComponent, decorators: [{
1332
1379
  type: Component,
1333
- args: [{ selector: 'inspector-overlay', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"inspector-root\" #overlayRoot>\n @if (enabled()) {\n <div class=\"inspector-toolbar\">\n <div class=\"inspector-toolbar__rail\">\n <button\n type=\"button\"\n class=\"inspector-icon-button\"\n [class.is-active]=\"toolMode() === 'select'\"\n (click)=\"setToolMode('select')\"\n aria-label=\"Select mode\"\n >\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 <span class=\"inspector-tooltip\" role=\"tooltip\">Select</span>\n </button>\n\n @if (checkpointService) {\n <button\n type=\"button\"\n class=\"inspector-icon-button\"\n (click)=\"saveCheckpoint()\"\n [disabled]=\"checkpointService.busy()\"\n aria-label=\"Save checkpoint\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M2.5 2h9.6l1.4 1.4V14h-11zm2 1.5v3h6v-3zm.5 6V12h6V9.5z\" />\n </svg>\n <span class=\"inspector-tooltip\" role=\"tooltip\">Save checkpoint</span>\n </button>\n }\n\n <div class=\"inspector-toolbar__secondary\">\n <div class=\"inspector-toolbar__reveal\">\n <div class=\"inspector-toolbar__reveal-inner\">\n <button\n type=\"button\"\n class=\"inspector-icon-button\"\n [class.is-active]=\"showTypography()\"\n (click)=\"toggleTypography()\"\n aria-label=\"Typography overlay\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M3 4V2h10v2h-4v10H7V4z\" />\n </svg>\n <span class=\"inspector-tooltip\" role=\"tooltip\">Typography</span>\n </button>\n\n <button\n type=\"button\"\n class=\"inspector-icon-button\"\n [class.is-active]=\"toolMode() === 'guides' && guideOrientation() === 'vertical'\"\n (click)=\"activateGuideOrientation('vertical')\"\n aria-label=\"Vertical guides\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M7.25 2h1.5v12h-1.5z\" />\n </svg>\n <span class=\"inspector-tooltip\" role=\"tooltip\">Vertical guides</span>\n </button>\n\n <button\n type=\"button\"\n class=\"inspector-icon-button\"\n [class.is-active]=\"toolMode() === 'guides' && guideOrientation() === 'horizontal'\"\n (click)=\"activateGuideOrientation('horizontal')\"\n aria-label=\"Horizontal guides\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M2 7.25h12v1.5H2z\" />\n </svg>\n <span class=\"inspector-tooltip\" role=\"tooltip\">Horizontal guides</span>\n </button>\n </div>\n </div>\n </div>\n\n <span class=\"inspector-toolbar__divider\" aria-hidden=\"true\"></span>\n <button\n type=\"button\"\n class=\"inspector-icon-button inspector-icon-button--power\"\n (click)=\"disableInspector()\"\n aria-label=\"Disable inspector; press M to enable\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path 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 </svg>\n <span class=\"inspector-tooltip\" role=\"tooltip\">Disable</span>\n </button>\n </div>\n </div>\n }\n\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 id=\"inspector-command-title\" class=\"inspector-visually-hidden\" for=\"inspector-checkpoint-search\">\n Search checkpoints\n </label>\n <input\n #checkpointSearch\n id=\"inspector-checkpoint-search\"\n type=\"search\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n placeholder=\"Find a checkpoint\u2026\"\n [value]=\"checkpointQuery()\"\n [attr.aria-controls]=\"'inspector-checkpoint-results'\"\n [attr.aria-activedescendant]=\"filteredCheckpoints().length ? 'inspector-checkpoint-' + filteredCheckpoints()[activeCheckpointIndex()].id : null\"\n (input)=\"updateCheckpointQuery($event)\"\n />\n </header>\n\n @if (checkpointService.error(); as error) {\n <p class=\"inspector-command__message inspector-command__message--error\" role=\"alert\">{{ error }}</p>\n }\n\n <div id=\"inspector-checkpoint-results\" class=\"inspector-command__results\" role=\"listbox\" aria-label=\"Saved checkpoints\">\n @if (checkpointService.loading()) {\n <p class=\"inspector-command__message\" role=\"status\">Loading checkpoints\u2026</p>\n } @else if (!checkpointService.checkpoints().length) {\n <p class=\"inspector-command__message\" role=\"status\">No checkpoints yet. Save one from the Inspector toolbar.</p>\n } @else if (!filteredCheckpoints().length) {\n <p class=\"inspector-command__message\" role=\"status\">No checkpoint matches \u201C{{ checkpointQuery() }}\u201D.</p>\n } @else {\n @for (checkpoint of filteredCheckpoints(); track checkpoint.id; let index = $index) {\n <div\n class=\"inspector-command-row\"\n role=\"option\"\n [id]=\"'inspector-checkpoint-' + checkpoint.id\"\n [attr.data-checkpoint-index]=\"index\"\n [attr.aria-selected]=\"activeCheckpointIndex() === index\"\n [class.is-active]=\"activeCheckpointIndex() === index\"\n [class.is-busy]=\"checkpointService.busy() && activeCheckpointIndex() === index\"\n (mouseenter)=\"setActiveCheckpoint(index)\"\n (click)=\"deletingCheckpointId() === checkpoint.id || editingCheckpointId() === checkpoint.id ? null : restoreCheckpoint(checkpoint)\"\n >\n @if (deletingCheckpointId() === checkpoint.id) {\n <span class=\"inspector-command-row__confirm\">Delete \u201C{{ checkpoint.name }}\u201D?</span>\n <span class=\"inspector-command-row__confirm-actions\">\n <button type=\"button\" class=\"is-danger\" (click)=\"confirmDelete(checkpoint, $event)\">Delete checkpoint</button>\n <button type=\"button\" (click)=\"cancelDelete($event)\">Keep checkpoint</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__name\">\n @if (checkpointService.busy() && activeCheckpointIndex() === index) {\n Restoring \u201C{{ checkpoint.name }}\u201D\u2026\n } @else {\n {{ checkpoint.name }}\n }\n </span>\n <span class=\"inspector-command-row__actions\">\n <button type=\"button\" (click)=\"beginRename(checkpoint, $event)\" [attr.aria-label]=\"'Rename ' + checkpoint.name\">\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path 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\" /></svg>\n </button>\n <button type=\"button\" (click)=\"beginDelete(checkpoint, $event)\" [attr.aria-label]=\"'Delete ' + checkpoint.name\">\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M5.5 2h5l.5 1H14v1.25H2V3h3zm-2 3.25h9L12 14H4z\" /></svg>\n </button>\n </span>\n }\n </div>\n }\n }\n </div>\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 >{{ toast }}</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 (pointerdown)=\"startGuideDrag($event, guide)\"\n >\n <span class=\"inspector-guide-line\"></span>\n </button>\n }\n }\n</div>\n", styles: [":host{--inspector-panel: rgba(27, 29, 36, .94);--inspector-panel-edge: rgba(255, 255, 255, .08);--inspector-text: #f3f4f6;--inspector-muted: #9ca3af;--inspector-blue: #4f8cff;--inspector-orange: #f59e0b;--inspector-green: #22c55e;--inspector-violet: #a855f7;position:fixed;inset:0;z-index:2147;pointer-events:none;font-family:SF Pro Display,Segoe UI,sans-serif}.inspector-root{position:fixed;inset:0;pointer-events:none}.inspector-toolbar{position:fixed;top:12px;right:12px;display:block;pointer-events:auto;z-index:10000}.inspector-toolbar__rail{display:flex;flex-direction:column;align-items:center;gap:2px;width:30px;padding:2px;border-radius:4px;border:1px solid var(--inspector-panel-edge);background:var(--inspector-panel);box-shadow:0 18px 40px #00000052;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.inspector-toolbar__divider{width:16px;height:1px;margin-block:2px;background:var(--inspector-panel-edge)}.inspector-toolbar__secondary{display:grid;width:24px}.inspector-toolbar__reveal{display:grid;grid-template-rows:0fr;opacity:0;transform:translateY(-4px);transition:grid-template-rows .18s cubic-bezier(.16,1,.3,1),opacity .12s cubic-bezier(.16,1,.3,1),transform .18s cubic-bezier(.16,1,.3,1)}.inspector-toolbar__reveal-inner{display:grid;gap:2px;min-height:0;overflow:hidden}.inspector-toolbar__rail:hover .inspector-toolbar__reveal,.inspector-toolbar__rail:focus-within .inspector-toolbar__reveal{grid-template-rows:1fr;opacity:1;transform:translateY(2px)}.inspector-command-dialog{--command-surface: oklch(20% .012 270);--command-surface-raised: oklch(25% .014 270);--command-surface-active: oklch(27% .018 270);--command-edge: oklch(39% .014 270);--command-text: oklch(95% .008 270);--command-muted: oklch(73% .018 270);--command-accent: oklch(76% .08 260);--command-danger: oklch(71% .17 25);box-sizing:border-box;inset-block-start:max(40px,10vh);width:min(480px,calc(100vw - 24px));max-width:none;max-height:min(400px,calc(100vh - 64px));margin:0 auto;padding:0;overflow:hidden;border:1px solid var(--command-edge);border-radius:4px;background:var(--command-surface);color:var(--command-text);box-shadow:0 20px 56px #0102038f;opacity:0;pointer-events:auto;transform:translateY(-6px);transition:opacity .12s cubic-bezier(.7,0,.84,0),transform .12s cubic-bezier(.7,0,.84,0),overlay .12s allow-discrete,display .12s allow-discrete}.inspector-command-dialog[open]{opacity:1;transform:translateY(0);transition-duration:.16s;transition-timing-function:cubic-bezier(.16,1,.3,1)}@starting-style{.inspector-command-dialog[open]{opacity:0;transform:translateY(-6px)}}.inspector-command-dialog::backdrop{background:#0102037a}.inspector-command{display:grid;min-width:0}.inspector-command__search{min-height:44px;padding-inline:12px;border-bottom:1px solid var(--command-edge)}.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{width:100%;height:43px;padding:0;font-size:14px;line-height:1.45}.inspector-command__search:has(input:focus-visible){box-shadow:inset 0 -2px var(--command-accent)}.inspector-command__search input::placeholder{color:var(--command-muted);opacity:1}.inspector-command__search input::-webkit-search-cancel-button{display:none}.inspector-command__results{max-height:304px;overflow:auto;padding-block:3px;scrollbar-color:var(--command-edge) transparent}.inspector-command-row{position:relative;display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:6px;min-height:38px;padding-inline:12px 6px;cursor:pointer;-webkit-user-select:none;user-select:none}.inspector-command-row.is-active{background:var(--command-surface-active)}.inspector-command-row.is-busy{cursor:wait;pointer-events:none}.inspector-command-row__name{overflow:hidden;color:var(--command-text);font-size:12px;font-weight:540;line-height:1.45;text-overflow:ellipsis;white-space:nowrap}.inspector-command-row.is-active .inspector-command-row__name{font-weight:700}.inspector-command-row__actions,.inspector-command-row__confirm-actions{display:flex;align-items:center;gap:4px}.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:26px;min-height:26px;padding:5px;place-items:center;border:1px solid transparent;border-radius:3px;background:transparent;color:var(--command-muted);cursor:pointer;font-family:inherit;font-size:10px;font-weight:600;line-height:1.3}.inspector-command-row button svg{width:12px;height:12px;fill:currentColor}.inspector-command-row button:hover{border-color:var(--command-edge);background:var(--command-surface-raised);color:var(--command-text)}.inspector-command-row button.is-danger{color:var(--command-danger)}.inspector-command-row button:focus-visible,.inspector-command-row__rename:focus-visible{outline:2px solid var(--command-accent);outline-offset:2px}.inspector-command-row__confirm{grid-column:1;color:var(--command-text);font-size:12px;font-weight:620}.inspector-command-row__rename{grid-column:1 / -1;min-height:30px;padding-inline:8px;border:1px solid var(--command-accent);border-radius:3px;background:var(--command-surface-raised);font-size:12px}.inspector-command__message{margin:0;padding:20px 12px;color:var(--command-muted);font-size:12px;line-height:1.55;text-align:center}.inspector-command__message--error{padding-block:9px;border-bottom:1px solid oklch(45% .1 25);background:#3f1917;color:oklch(89% .06 25);text-align:left}.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:12px;left:50%;z-index:500;margin:0;padding:8px 12px;border:1px solid oklch(48% .04 150);border-radius:4px;background:#152619;color:#cfe9d4;box-shadow:0 16px 40px #01020375;font-size:11px;font-weight:620;line-height:1.35;pointer-events:none;transform:translate(-50%)}.inspector-checkpoint-toast--error{border-color:#9c433f;background:#431614;color:oklch(92% .05 25)}.inspector-icon-button{display:inline-flex;align-items:center;justify-content:center;height:24px;border:0;border-radius:3px;background:transparent;color:var(--inspector-muted);cursor:pointer;transition:background .1s cubic-bezier(.16,1,.3,1),color .1s cubic-bezier(.16,1,.3,1),transform .1s cubic-bezier(.16,1,.3,1);font:inherit;font-size:11px;letter-spacing:.02em}.inspector-icon-button{position:relative;width:24px}.inspector-icon-button svg{width:13px;height:13px;fill:currentColor}.inspector-icon-button:active{transform:translateY(1px)}.inspector-icon-button:focus-visible{outline:2px solid var(--inspector-blue);outline-offset:2px}.inspector-icon-button:hover{background:#ffffff14;color:var(--inspector-text)}.inspector-icon-button.is-active{background:#4f8cff2e;color:#dbeafe}.inspector-icon-button--power:hover{background:#ef444429;color:#fecaca}.inspector-tooltip{position:absolute;top:50%;right:calc(100% + 7px);z-index:20;width:max-content;padding:4px 6px;border:1px solid var(--inspector-panel-edge);border-radius:3px;background:#111318fa;color:var(--inspector-text);font-size:10px;font-weight:600;line-height:1.2;opacity:0;pointer-events:none;transform:translate(3px,-50%);transition:opacity .12s cubic-bezier(.16,1,.3,1),transform .12s cubic-bezier(.16,1,.3,1);white-space:nowrap}.inspector-icon-button:hover .inspector-tooltip,.inspector-icon-button:focus-visible .inspector-tooltip{opacity:1;transform:translateY(-50%)}@media (prefers-reduced-motion: reduce){.inspector-toolbar__reveal,.inspector-icon-button,.inspector-tooltip,.inspector-command-dialog,.inspector-command-row__marker{transition-duration:.01ms}.inspector-command-dialog,.inspector-command-dialog[open]{transform: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:#f59e0bd1;background:#f59e0b14}.inspector-box--padding{border-color:#22c55ed1;background:#22c55e14}.inspector-box--gap{border-color:#a855f7b8;background:#a855f70a}.inspector-box--distance{border-style:dashed;border-color:#4f8cffb3;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% - 8px));max-width:min(420px,calc(100vw - 24px));padding:6px 9px;border-radius:999px;border:1px solid var(--inspector-panel-edge);background:var(--inspector-panel);color:var(--inspector-text);box-shadow:0 18px 40px #00000042;font-size:11px;line-height:1;white-space:nowrap}.inspector-box-tag{position:fixed;transform:translateY(-100%);padding:4px 6px;border-radius:999px;border:1px solid var(--inspector-panel-edge);background:#111827f0;color:var(--inspector-text);box-shadow:0 12px 24px #0003;font-size:10px;line-height:1;pointer-events:none}.inspector-box-tag--margin{color:#fbbf24}.inspector-box-tag--padding{color:#86efac;transform:translateY(0)}.inspector-box-tag--gap{color:#d8b4fe}.inspector-text-chip{position:fixed;transform:translateY(-100%);display:inline-flex;gap:6px;align-items:center;padding:4px 6px;border-radius:999px;border:1px solid var(--inspector-panel-edge);background:#111827f0;color:#e5e7eb;box-shadow:0 12px 24px #00000038;font-size:10px;line-height:1;white-space:nowrap;pointer-events:none}.inspector-text-chip__swatch{width:8px;height:8px;border-radius:999px;border:1px solid rgba(255,255,255,.18);flex:0 0 auto}.inspector-connector{position:fixed;border-color:#4f8cffb8;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:5px 7px;border-radius:999px;border:1px solid var(--inspector-panel-edge);background:#111827f2;color:var(--inspector-text);font-size:10px;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}\n"] }]
1380
+ 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 id=\"inspector-command-title\" class=\"inspector-visually-hidden\" for=\"inspector-checkpoint-search\">\n Search checkpoints\n </label>\n <svg class=\"inspector-command__search-icon\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M7 2.25a4.75 4.75 0 1 0 2.94 8.48l2.91 2.92.8-.8-2.92-2.91A4.75 4.75 0 0 0 7 2.25Zm-3.62 4.75a3.62 3.62 0 1 1 7.24 0 3.62 3.62 0 0 1-7.24 0Z\" />\n </svg>\n <input\n #checkpointSearch\n id=\"inspector-checkpoint-search\"\n type=\"search\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n placeholder=\"Search checkpoints\u2026\"\n [value]=\"checkpointQuery()\"\n [attr.aria-controls]=\"'inspector-checkpoint-results'\"\n [attr.aria-activedescendant]=\"filteredCheckpoints().length ? 'inspector-checkpoint-' + filteredCheckpoints()[activeCheckpointIndex()].id : null\"\n (input)=\"updateCheckpointQuery($event)\"\n />\n </header>\n\n @if (checkpointService.error(); as error) {\n <p class=\"inspector-command__message inspector-command__message--error\" role=\"alert\">{{ error }}</p>\n }\n\n <div id=\"inspector-checkpoint-results\" class=\"inspector-command__results\" role=\"listbox\" aria-label=\"Saved checkpoints\">\n @if (checkpointService.loading()) {\n <p class=\"inspector-command__message\" role=\"status\">Loading\u2026</p>\n } @else if (!checkpointService.checkpoints().length) {\n <p class=\"inspector-command__message\" role=\"status\">No checkpoints yet</p>\n } @else if (!filteredCheckpoints().length) {\n <p class=\"inspector-command__message\" role=\"status\">No matches</p>\n } @else {\n @for (checkpoint of filteredCheckpoints(); track checkpoint.id; let index = $index) {\n <div\n class=\"inspector-command-row\"\n role=\"option\"\n [id]=\"'inspector-checkpoint-' + checkpoint.id\"\n [attr.data-checkpoint-index]=\"index\"\n [attr.aria-selected]=\"activeCheckpointIndex() === index\"\n [class.is-active]=\"activeCheckpointIndex() === index\"\n [class.is-busy]=\"checkpointService.busy() && activeCheckpointIndex() === index\"\n (mouseenter)=\"setActiveCheckpoint(index)\"\n (click)=\"deletingCheckpointId() === checkpoint.id || editingCheckpointId() === checkpoint.id ? null : restoreCheckpoint(checkpoint)\"\n >\n @if (deletingCheckpointId() === checkpoint.id) {\n <span class=\"inspector-command-row__confirm\">Delete \u201C{{ checkpoint.name }}\u201D?</span>\n <span class=\"inspector-command-row__confirm-actions\">\n <button type=\"button\" class=\"is-danger\" (click)=\"confirmDelete(checkpoint, $event)\">Delete</button>\n <button type=\"button\" (click)=\"cancelDelete($event)\">Keep</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 (checkpointService.busy() && activeCheckpointIndex() === index) {\n Restoring\u2026\n } @else {\n {{ checkpoint.name }}\n }\n </span>\n <span class=\"inspector-command-row__meta\">\n <span class=\"inspector-command-row__route\">{{ checkpoint.route || '/' }}</span>\n <span class=\"inspector-command-row__separator\" aria-hidden=\"true\">\u00B7</span>\n <span class=\"inspector-command-row__activity\">\n {{ checkpoint.lastUsedAt ? 'Used' : 'Saved' }} {{ formatRelativeTime(checkpointActivityAt(checkpoint)) }}\n </span>\n </span>\n </span>\n <span class=\"inspector-command-row__actions\">\n <button type=\"button\" (click)=\"beginRename(checkpoint, $event)\" [attr.aria-label]=\"'Rename ' + checkpoint.name\">\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path 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\" /></svg>\n </button>\n <button type=\"button\" (click)=\"beginDelete(checkpoint, $event)\" [attr.aria-label]=\"'Delete ' + checkpoint.name\">\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M5.5 2h5l.5 1H14v1.25H2V3h3zm-2 3.25h9L12 14H4z\" /></svg>\n </button>\n </span>\n }\n </div>\n }\n }\n </div>\n\n <footer class=\"inspector-command__actions\" aria-label=\"Inspector actions\">\n <button\n type=\"button\"\n class=\"inspector-command-action\"\n [class.is-active]=\"toolMode() === 'select'\"\n (click)=\"setToolMode('select'); closeCheckpointCommandBar()\"\n aria-label=\"Select mode\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M3 2l8 8-3 .7L6.7 13 6 10 3 2z\" /></svg>\n <span>Select</span>\n </button>\n <button\n type=\"button\"\n class=\"inspector-command-action\"\n [class.is-active]=\"showTypography()\"\n (click)=\"toggleTypography(); closeCheckpointCommandBar()\"\n aria-label=\"Toggle typography overlay\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M3 4V2h10v2h-4v10H7V4z\" /></svg>\n <span>Type</span>\n </button>\n <button\n type=\"button\"\n class=\"inspector-command-action\"\n (click)=\"saveCheckpoint()\"\n [disabled]=\"checkpointService.busy()\"\n aria-label=\"Save checkpoint\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M2.5 2h9.6l1.4 1.4V14h-11zm2 1.5v3h6v-3zm.5 6V12h6V9.5z\" /></svg>\n <span>Save</span>\n </button>\n <button\n type=\"button\"\n class=\"inspector-command-action\"\n [class.is-active]=\"toolMode() === 'guides' && guideOrientation() === 'vertical'\"\n (click)=\"activateGuideOrientation('vertical'); closeCheckpointCommandBar()\"\n aria-label=\"Vertical guides\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M7.25 2h1.5v12h-1.5z\" /></svg>\n <span>V</span>\n </button>\n <button\n type=\"button\"\n class=\"inspector-command-action\"\n [class.is-active]=\"toolMode() === 'guides' && guideOrientation() === 'horizontal'\"\n (click)=\"activateGuideOrientation('horizontal'); closeCheckpointCommandBar()\"\n aria-label=\"Horizontal guides\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M2 7.25h12v1.5H2z\" /></svg>\n <span>H</span>\n </button>\n <button\n type=\"button\"\n class=\"inspector-command-action inspector-command-action--danger\"\n (click)=\"closeCheckpointCommandBar(); disableInspector()\"\n aria-label=\"Disable inspector; press M to enable\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path 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\" /></svg>\n <span>Off</span>\n </button>\n </footer>\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 >{{ toast }}</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 (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(26% .02 265);--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__search-icon{width:14px;height:14px;flex:0 0 auto;fill:var(--command-faint)}.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)}.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__activity{color:var(--command-muted)}.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:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:2px;padding:4px;border-top:1px solid var(--command-edge)}.inspector-command-action{display:flex;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--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-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}\n"] }]
1334
1381
  }], ctorParameters: () => [{ type: undefined, decorators: [{
1335
1382
  type: Inject,
1336
1383
  args: [PLATFORM_ID]
@@ -1369,5 +1416,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
1369
1416
  * Generated bundle index. Do not edit.
1370
1417
  */
1371
1418
 
1372
- export { GUIDE_HITBOX_SIZE, GUIDE_SNAP_DISTANCE, clamp, createId, formatValue, getDistanceOverlay, getElementLabel, getInspectMeasurement, getRectFromDom, getTargetElement, getTextInspection, getViewportSize, getVisibleTextBlocks, inspectorComponent, inspector_STATE_VERSION, inspector_STORAGE_KEY, provideInspectorCheckpoints, rectContainsPoint, rectsEqual };
1419
+ export { GUIDE_HITBOX_SIZE, GUIDE_SNAP_DISTANCE, clamp, createId, formatRelativeTime, formatValue, getDistanceOverlay, getElementLabel, getInspectMeasurement, getRectFromDom, getTargetElement, getTextInspection, getViewportSize, getVisibleTextBlocks, inspectorComponent, inspector_STATE_VERSION, inspector_STORAGE_KEY, provideInspectorCheckpoints, rectContainsPoint, rectsEqual };
1373
1420
  //# sourceMappingURL=inspector-ng.mjs.map