@flemo/devtools 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -174,7 +174,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
174
174
  }), oe = (e) => e.some((e) => {
175
175
  let t = e.getAttribute(m);
176
176
  return t !== null && L.has(t);
177
- }), se = (e) => `${e.transform}/${e.opacity}`, ce = (e, t, n) => {
177
+ }), R = (e) => `${e.transform}/${e.opacity}`, se = (e, t, n) => {
178
178
  e.releasedFrames += 1;
179
179
  let r = !1, i = !1;
180
180
  for (let n of t) {
@@ -188,7 +188,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
188
188
  }
189
189
  }
190
190
  let a = n.style;
191
- a && a.animation !== "" && e.lastPose.get(n) !== se(a) && (r = !0);
191
+ a && a.animation !== "" && e.lastPose.get(n) !== R(a) && (r = !0);
192
192
  }
193
193
  if (!(e.releasedFrames < re)) {
194
194
  if (r) {
@@ -201,17 +201,17 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
201
201
  }
202
202
  e.stalledFrames += 1, e.stallRunMs += n, e.stallRunMs > e.longestStallMs && (e.longestStallMs = e.stallRunMs);
203
203
  }
204
- }, le = (e, t) => {
204
+ }, z = (e, t) => {
205
205
  let n = t.style;
206
206
  if (!n || n.animation === "") return;
207
207
  e.evidence.inlineSuppression = !0;
208
- let r = se(n), i = e.lastPose.get(t);
208
+ let r = R(n), i = e.lastPose.get(t);
209
209
  i !== void 0 && i !== r && (e.evidence.inlineAdvance = !0), e.lastPose.set(t, r);
210
- }, ue = (e, t) => {
210
+ }, B = (e, t) => {
211
211
  for (let n of t) {
212
212
  let t = n.getAnimations, r = e.clocks.get(n);
213
213
  if (r !== void 0 && r.playState !== "finished") {
214
- r.playState === "running" && (e.evidence.compiledAnimation = !0), le(e, n);
214
+ r.playState === "running" && (e.evidence.compiledAnimation = !0), z(e, n);
215
215
  continue;
216
216
  }
217
217
  if (typeof t == "function") try {
@@ -220,40 +220,40 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
220
220
  typeof t == "string" && t.startsWith("flemo-") && (e.clocks.set(n, r), r.playState === "running" && (e.evidence.compiledAnimation = !0));
221
221
  }
222
222
  } catch {}
223
- le(e, n);
223
+ z(e, n);
224
224
  }
225
- }, de = (e) => ({
225
+ }, ce = (e) => ({
226
226
  sampledFrames: e.releasedFrames,
227
227
  stalledFrames: e.stalledFrames,
228
228
  longestStallMs: ie(e.longestStallMs),
229
229
  pausedAfterRelease: e.pausedAfterRelease,
230
230
  holdReassertedAtMs: e.holdReassertedAtMs,
231
231
  tailFrames: e.tailFrames
232
- }), R = 200, z = (e) => {
232
+ }), V = 200, H = (e) => {
233
233
  let t = [];
234
234
  for (let n of e) for (let e of Array.from(n.querySelectorAll("img"))) t.push(e);
235
235
  return t;
236
- }, fe = (e) => {
237
- let t = new Set(z(e).filter((e) => !e.complete));
236
+ }, le = (e) => {
237
+ let t = new Set(H(e).filter((e) => !e.complete));
238
238
  return {
239
239
  tracked: t,
240
240
  loadingAtStart: t.size,
241
241
  addedDuringFlight: 0,
242
242
  held: /* @__PURE__ */ new Set()
243
243
  };
244
- }, pe = (e, t, n) => {
245
- if (!(e.tracked.size >= R)) for (let r of Array.from(n)) {
244
+ }, ue = (e, t, n) => {
245
+ if (!(e.tracked.size >= V)) for (let r of Array.from(n)) {
246
246
  if (!(r instanceof Element) || !t.some((e) => e === r || e.contains(r))) continue;
247
247
  let n = r instanceof HTMLImageElement ? [r] : Array.from(r.querySelectorAll("img"));
248
248
  for (let t of n) if (!(t.complete || e.tracked.has(t))) {
249
- if (e.tracked.size >= R) return;
249
+ if (e.tracked.size >= V) return;
250
250
  e.tracked.add(t), e.addedDuringFlight += 1;
251
251
  }
252
252
  }
253
- }, me = (e, t) => {
253
+ }, de = (e, t) => {
254
254
  for (let n of t) for (let t of Array.from(n.querySelectorAll(`img[${h}]`))) e.held.add(t);
255
255
  for (let t of e.tracked) t.hasAttribute("data-flemo-img-hold") && e.held.add(t);
256
- }, he = (e) => {
256
+ }, fe = (e) => {
257
257
  let t = 0, n = 0;
258
258
  for (let r of e.tracked) r.complete && (t += 1, e.held.has(r) || (n += 1));
259
259
  return {
@@ -263,12 +263,12 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
263
263
  heldDuringFlight: e.held.size,
264
264
  completedUnheld: n
265
265
  };
266
- }, ge = [
266
+ }, pe = [
267
267
  "DevTools must be CLOSED while judging motion. An open inspector serializes requests and repaints its own panels on the same machine; the 2026-08 campaign's entire residual 'stutter' was this, and it is invisible to every in-page metric.",
268
268
  "No screen recording or display capture while judging. A capture client forces WindowServer to composite every vsync, which SUPPRESSES the symptom — a capture that looks smooth proves nothing about the uncaptured session.",
269
269
  "Judge with real input (a finger, a mouse). Synthetic dispatch — evaluate().click() and friends — never fires pointerdown, so it bypasses the swipe/gesture machinery that a real navigation goes through.",
270
270
  "Establish the viewing configuration before believing any verdict: device emulation off, which physical display, its refresh rate and HiDPI scaling, Low Power Mode. Ask for a photo of the setup if it is not certain."
271
- ], B = (e) => Math.round(e * 10) / 10, V = (e) => {
271
+ ], U = (e) => Math.round(e * 10) / 10, me = (e) => {
272
272
  if (e.length === 0) return {
273
273
  count: 0,
274
274
  medianGapMs: 0,
@@ -278,11 +278,11 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
278
278
  let t = [...e].sort((e, t) => e - t);
279
279
  return {
280
280
  count: e.length,
281
- medianGapMs: B(t[Math.floor(t.length / 2)]),
282
- maxGapMs: B(t[t.length - 1]),
281
+ medianGapMs: U(t[Math.floor(t.length / 2)]),
282
+ maxGapMs: U(t[t.length - 1]),
283
283
  over30Count: e.filter((e) => e >= 30).length
284
284
  };
285
- }, _e = (e, t = []) => {
285
+ }, he = (e, t = []) => {
286
286
  let n = [...e, ...t];
287
287
  return {
288
288
  ...n.length === 0 ? {
@@ -293,18 +293,18 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
293
293
  let e = [...n].sort((e, t) => e - t);
294
294
  return {
295
295
  count: n.length,
296
- medianGapMs: B(e[Math.floor(e.length / 2)]),
297
- maxGapMs: B(e[e.length - 1])
296
+ medianGapMs: U(e[Math.floor(e.length / 2)]),
297
+ maxGapMs: U(e[e.length - 1])
298
298
  };
299
299
  })(),
300
- longGaps: n.filter((e) => e >= 30).map(B),
301
- held: V(e),
302
- released: V(t)
300
+ longGaps: n.filter((e) => e >= 30).map(U),
301
+ held: me(e),
302
+ released: me(t)
303
303
  };
304
- }, ve = (e) => {
304
+ }, ge = (e) => {
305
305
  let t = e.inlineSuppression || e.inlineAdvance;
306
306
  return t && e.compiledAnimation ? "mixed" : t ? "inline" : e.compiledAnimation ? "compiled" : "unknown";
307
- }, ye = (e) => e === "PUSHING" ? "PUSH" : e === "POPPING" ? "POP" : e === "REPLACING" ? "REPLACE" : null, be = (e) => {
307
+ }, _e = (e) => e === "PUSHING" ? "PUSH" : e === "POPPING" ? "POP" : e === "REPLACING" ? "REPLACE" : null, ve = (e) => {
308
308
  let t = /^matrix3d\(([^)]+)\)$/.exec(e.trim());
309
309
  if (t) {
310
310
  let e = t[1].split(",").map((e) => Number(e.trim()));
@@ -316,7 +316,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
316
316
  return e.length === 6 && Number.isFinite(e[4]) ? e[4] : null;
317
317
  }
318
318
  return null;
319
- }, H = (e) => {
319
+ }, W = (e) => {
320
320
  if (e) return [];
321
321
  let t = [];
322
322
  for (let [e, n] of [[h, "image reveal hold"], [g, "arrival hold"]]) {
@@ -324,7 +324,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
324
324
  r > 0 && t.push(`${r} × ${n} (${e}) still marked at rest`);
325
325
  }
326
326
  return t;
327
- }, xe = (e, t) => {
327
+ }, ye = (e, t) => {
328
328
  let n = [], r = !1, i = window.visualViewport?.width ?? window.innerWidth ?? 0;
329
329
  return e.forEach((e, t) => {
330
330
  if (!(e instanceof HTMLElement) || !e.isConnected) return;
@@ -336,27 +336,27 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
336
336
  if (o === "none") return;
337
337
  let s = e.getAttribute(p) === "true", c = `screen[${t}]${s ? " (active)" : ""}`;
338
338
  if (e.style.transform !== "" && e.style.transform !== "none" && n.push(`${c} transform=${e.style.transform}`), e.style.opacity !== "" && e.style.opacity !== "1" && n.push(`${c} opacity=${e.style.opacity}`), s && e.getAttribute("data-flemo-status") === "COMPLETED" && i > 0) {
339
- let e = be(a);
339
+ let e = ve(a);
340
340
  e !== null && Math.abs(e) >= i * .5 && (r = !0);
341
341
  }
342
342
  }), {
343
343
  residualInlineTransforms: n,
344
344
  offViewportAtRest: r,
345
- orphanedHolds: H(t)
345
+ orphanedHolds: W(t)
346
346
  };
347
- }, Se = E.map((e) => `[${b}="${e}"]`).join(","), Ce = A(d), we = (e) => Math.round(e * 10) / 10, Te = (e) => {
347
+ }, be = E.map((e) => `[${b}="${e}"]`).join(","), xe = A(d), Se = (e) => Math.round(e * 10) / 10, Ce = (e) => {
348
348
  let t = e.getAttribute(x);
349
349
  return t === null || t === "" ? null : t;
350
- }, Ee = (e) => {
350
+ }, we = (e) => {
351
351
  let t = e.getAttribute(b);
352
352
  return t !== null && E.includes(t);
353
- }, De = () => {
353
+ }, Te = () => {
354
354
  try {
355
355
  return document.querySelector("style[data-flemo-morph-sheet]")?.sheet?.cssRules.length ?? 0;
356
356
  } catch {
357
357
  return 0;
358
358
  }
359
- }, Oe = (e) => {
359
+ }, Ee = (e) => {
360
360
  let t = {
361
361
  registered: 0,
362
362
  pairable: /* @__PURE__ */ new Set(),
@@ -366,17 +366,17 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
366
366
  ghosts: 0,
367
367
  ghostBornAt: /* @__PURE__ */ new Map(),
368
368
  shortestGhostLifeMs: null,
369
- sheetRulesAtStart: De()
369
+ sheetRulesAtStart: Te()
370
370
  }, n = new Set(e), r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map();
371
371
  for (let e of Array.from(document.querySelectorAll(A(b)))) {
372
372
  t.registered += 1;
373
- let a = Te(e);
373
+ let a = Ce(e);
374
374
  if (a === null) continue;
375
- if (Ee(e)) {
375
+ if (we(e)) {
376
376
  t.flew.add(a);
377
377
  continue;
378
378
  }
379
- let o = e.closest(Ce);
379
+ let o = e.closest(xe);
380
380
  if (o !== null && !n.has(o)) continue;
381
381
  let s = o, c = r.get(a);
382
382
  c || r.set(a, c = /* @__PURE__ */ new Set()), c.add(s);
@@ -389,27 +389,27 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
389
389
  r && [...r.values()].some((e) => e > 1) && t.duplicated.add(e);
390
390
  }
391
391
  return t;
392
- }, ke = (e, t) => {
393
- if (t.hasAttribute("data-flemo-morph-camera") && (e.camera = !0), !Ee(t)) return;
394
- let n = Te(t);
392
+ }, De = (e, t) => {
393
+ if (t.hasAttribute("data-flemo-morph-camera") && (e.camera = !0), !we(t)) return;
394
+ let n = Ce(t);
395
395
  n !== null && e.flew.add(n);
396
- }, Ae = (e, t, n) => {
397
- for (let r of Array.from(t.addedNodes)) if (r instanceof Element) for (let t of je(r)) e.ghostBornAt.has(t) || (e.ghosts += 1, e.ghostBornAt.set(t, n));
398
- for (let r of Array.from(t.removedNodes)) if (r instanceof Element) for (let t of je(r)) {
396
+ }, Oe = (e, t, n) => {
397
+ for (let r of Array.from(t.addedNodes)) if (r instanceof Element) for (let t of ke(r)) e.ghostBornAt.has(t) || (e.ghosts += 1, e.ghostBornAt.set(t, n));
398
+ for (let r of Array.from(t.removedNodes)) if (r instanceof Element) for (let t of ke(r)) {
399
399
  let r = e.ghostBornAt.get(t);
400
400
  if (r === void 0) continue;
401
401
  e.ghostBornAt.delete(t);
402
402
  let i = n - r;
403
403
  (e.shortestGhostLifeMs === null || i < e.shortestGhostLifeMs) && (e.shortestGhostLifeMs = i);
404
404
  }
405
- }, je = (e) => [...e.hasAttribute("data-flemo-morph-ghost") ? [e] : [], ...Array.from(e.querySelectorAll(A(w)))], Me = (e) => {
405
+ }, ke = (e) => [...e.hasAttribute("data-flemo-morph-ghost") ? [e] : [], ...Array.from(e.querySelectorAll(A(w)))], Ae = (e) => {
406
406
  let t = e.shortestGhostLifeMs;
407
407
  return t === null || t >= 34 ? [] : [{
408
408
  kind: "ghost-cut",
409
- atMs: we(t),
410
- detail: `a morph ghost was removed ${we(t)}ms after it was created (under one frame) — the departing content it stands for was never presented; this is the first-frame blade signature`
409
+ atMs: Se(t),
410
+ detail: `a morph ghost was removed ${Se(t)}ms after it was created (under one frame) — the departing content it stands for was never presented; this is the first-frame blade signature`
411
411
  }];
412
- }, Ne = (e, t) => {
412
+ }, je = (e, t) => {
413
413
  let n = [...e.pairable].sort(), r = [...e.flew].sort(), i = new Set(r), a = t ? {
414
414
  strandedRoles: 0,
415
415
  strandedStandIns: 0,
@@ -417,11 +417,11 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
417
417
  layerResidue: 0,
418
418
  leaked: 0
419
419
  } : {
420
- strandedRoles: document.querySelectorAll(Se).length,
420
+ strandedRoles: document.querySelectorAll(be).length,
421
421
  strandedStandIns: document.querySelectorAll(A(C)).length,
422
422
  strandedGhosts: document.querySelectorAll(A(w)).length,
423
423
  layerResidue: Array.from(document.querySelectorAll(A(S))).reduce((e, t) => e + t.childElementCount, 0),
424
- leaked: Math.max(0, De() - e.sheetRulesAtStart)
424
+ leaked: Math.max(0, Te() - e.sheetRulesAtStart)
425
425
  };
426
426
  return {
427
427
  registered: e.registered,
@@ -437,21 +437,19 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
437
437
  layerResidue: a.layerResidue,
438
438
  duplicatedKeys: [...e.duplicated].sort()
439
439
  };
440
- }, U = "flemo:devtools-panel-height", Pe = [{
441
- key: "flemo:devtools",
442
- storage: "session",
443
- kind: "opt-in-diagnostic",
444
- values: "\"on\" / \"off\"",
445
- fallback: "off",
446
- effect: "arms this flight recorder in the playground (?devtools=on)"
447
- }, {
448
- key: U,
440
+ }, Me = "flemo:devtools-panel-height", Ne = [{
441
+ key: Me,
449
442
  storage: "session",
450
443
  kind: "production-state",
451
444
  values: "a pixel height",
452
445
  fallback: "(the panel's default height)",
453
446
  effect: "the drawer height this panel was last dragged to"
454
- }], Fe = [], W = [...Fe, ...Pe], G = [
447
+ }], Pe = [], Fe = [...Pe, ...Ne], G = [
448
+ {
449
+ key: "flemo:devtools",
450
+ storage: "session",
451
+ retiredWith: "the playground's opt-in. `<FlemoDevtools />` mounts unconditionally and a production build resolves it to the inert entry, so there is nothing to arm (2026-09-07)"
452
+ },
455
453
  {
456
454
  key: "flemo:sixty",
457
455
  storage: "session",
@@ -585,9 +583,9 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
585
583
  } catch {
586
584
  return null;
587
585
  }
588
- }, ze = new Set(W.map((e) => e.key)), Be = new Set(G.map((e) => e.key)), Ve = () => {
586
+ }, ze = new Set(Fe.map((e) => e.key)), Be = new Set(G.map((e) => e.key)), Ve = () => {
589
587
  let e = {}, t = Le("session"), n = Le("local");
590
- for (let r of W) {
588
+ for (let r of Fe) {
591
589
  let i = Re(r.storage === "session" ? t : n, r.key);
592
590
  i !== null && (e[r.key] = i);
593
591
  }
@@ -900,7 +898,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
900
898
  previousSession: null,
901
899
  anomalies: [],
902
900
  blindSpots: [...c],
903
- judgingProtocol: [...ge]
901
+ judgingProtocol: [...pe]
904
902
  }), Ct = (e = {}) => {
905
903
  if (xt) return xt;
906
904
  if (typeof window > "u" || typeof document > "u") return {
@@ -960,17 +958,17 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
960
958
  let t = performance.now(), n = e.frames;
961
959
  if (n.lastFrameAt !== null && n.heldGaps.length + n.releasedGaps.length < vt) {
962
960
  let r = t - n.lastFrameAt, i = oe(e.elements);
963
- (i ? n.heldGaps : n.releasedGaps).push(r), i || (ce(n, e.elements, r), n.releasedFrames === 1 && me(e.images, e.elements));
961
+ (i ? n.heldGaps : n.releasedGaps).push(r), i || (se(n, e.elements, r), n.releasedFrames === 1 && de(e.images, e.elements));
964
962
  }
965
- if (n.lastFrameAt = t, ue(n, e.elements), t - e.t0Ms > 1e4) {
966
- O = [...e.elements], z(t, re(e));
963
+ if (n.lastFrameAt = t, B(n, e.elements), t - e.t0Ms > 1e4) {
964
+ O = [...e.elements], H(t, re(e));
967
965
  return;
968
966
  }
969
967
  e.rafId = requestAnimationFrame(L);
970
968
  }, ie = (e) => {
971
969
  let t = performance.now();
972
970
  w += 1;
973
- let n = e.find((e) => e.getAttribute("data-flemo-active") === "true") ?? e[0], r = ye(n.getAttribute("data-flemo-status") ?? "") ?? "PUSH", i = null;
971
+ let n = e.find((e) => e.getAttribute("data-flemo-active") === "true") ?? e[0], r = _e(n.getAttribute("data-flemo-status") ?? "") ?? "PUSH", i = null;
974
972
  for (let t of e) {
975
973
  let e = t.getAttribute(m);
976
974
  if (e !== null && gt.has(e)) {
@@ -991,34 +989,34 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
991
989
  holdReleasedAtMs: null,
992
990
  firstAnimationAtMs: null,
993
991
  frames: ae(),
994
- images: fe(e),
995
- morphs: Oe(e),
992
+ images: le(e),
993
+ morphs: Ee(e),
996
994
  tripwires: [],
997
995
  rafId: null
998
- }, ue(E.frames, E.elements), E.rafId = requestAnimationFrame(L);
999
- }, se = (e, t) => {
996
+ }, B(E.frames, E.elements), E.rafId = requestAnimationFrame(L);
997
+ }, R = (e, t) => {
1000
998
  let n = 2, r = () => {
1001
999
  if (k) return;
1002
1000
  if (--n, n > 0) {
1003
1001
  requestAnimationFrame(r);
1004
1002
  return;
1005
1003
  }
1006
- let i = xe(t, te());
1004
+ let i = ye(t, te());
1007
1005
  e.landing.residualInlineTransforms = i.residualInlineTransforms, e.landing.offViewportAtRest = i.offViewportAtRest, e.landing.orphanedHolds = i.orphanedHolds;
1008
1006
  };
1009
1007
  requestAnimationFrame(r);
1010
- }, le = (e, t) => {
1008
+ }, z = (e, t) => {
1011
1009
  let n = 2, r = () => {
1012
1010
  if (!k) {
1013
1011
  if (--n, n > 0) {
1014
1012
  requestAnimationFrame(r);
1015
1013
  return;
1016
1014
  }
1017
- e.morphs = Ne(t.morphs, te());
1015
+ e.morphs = je(t.morphs, te());
1018
1016
  }
1019
1017
  };
1020
1018
  requestAnimationFrame(r);
1021
- }, R = (e, t, n, r) => ({
1019
+ }, V = (e, t, n, r) => ({
1022
1020
  id: r ? `${e.id} (in flight)` : e.id,
1023
1021
  ...e.routerId === void 0 ? {} : { routerId: e.routerId },
1024
1022
  ...e.bucket === null ? {} : { bucket: e.bucket },
@@ -1032,20 +1030,20 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1032
1030
  iso: (/* @__PURE__ */ new Date()).toISOString()
1033
1031
  },
1034
1032
  durationMs: K(t - e.t0Ms),
1035
- driver: ve(e.frames.evidence),
1033
+ driver: ge(e.frames.evidence),
1036
1034
  participants: e.participants,
1037
1035
  holds: {
1038
1036
  kind: e.holdKind,
1039
1037
  releasedAtMs: e.holdReleasedAtMs
1040
1038
  },
1041
- frameSamples: _e(e.frames.heldGaps, e.frames.releasedGaps),
1039
+ frameSamples: he(e.frames.heldGaps, e.frames.releasedGaps),
1042
1040
  motion: {
1043
- ...de(e.frames),
1041
+ ...ce(e.frames),
1044
1042
  firstAnimationAtMs: e.firstAnimationAtMs
1045
1043
  },
1046
- images: he(e.images),
1047
- morphs: Ne(e.morphs, !0),
1048
- tripwires: [...e.tripwires, ...Me(e.morphs)],
1044
+ images: fe(e.images),
1045
+ morphs: je(e.morphs, !0),
1046
+ tripwires: [...e.tripwires, ...Ae(e.morphs)],
1049
1047
  input: I.inputBetween(e.t0Ms, t),
1050
1048
  longTasks: [],
1051
1049
  holdLongTasks: [],
@@ -1056,16 +1054,16 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1056
1054
  orphanedHolds: []
1057
1055
  },
1058
1056
  anomalies: []
1059
- }), z = (e, t) => {
1057
+ }), H = (e, t) => {
1060
1058
  let i = E;
1061
1059
  /* v8 ignore next -- unreachable: both callers hold a flight. sampleFrame
1062
1060
  returns at its own top when `current` is null, and evaluate only calls
1063
1061
  this inside `if (current && ...)`. The narrowing stays for the type. */
1064
1062
  if (!i) return;
1065
- me(i.images, i.elements), E = null, i.rafId !== null && cancelAnimationFrame(i.rafId);
1066
- let a = R(i, e, t, !1);
1067
- C.push(a), C.length > n && C.splice(0, C.length - n), t.length === 0 && (se(a, i.elements), le(a, i)), r && console.info(`[flemo devtools] ${a.id} ${a.kind} driver=${a.driver} ${a.durationMs}ms screens=${a.participants.screens}`);
1068
- }, B = (e) => {
1063
+ de(i.images, i.elements), E = null, i.rafId !== null && cancelAnimationFrame(i.rafId);
1064
+ let a = V(i, e, t, !1);
1065
+ C.push(a), C.length > n && C.splice(0, C.length - n), t.length === 0 && (R(a, i.elements), z(a, i)), r && console.info(`[flemo devtools] ${a.id} ${a.kind} driver=${a.driver} ${a.durationMs}ms screens=${a.participants.screens}`);
1066
+ }, U = (e) => {
1069
1067
  let t = E;
1070
1068
  if (!t || !(e.target instanceof Element)) return;
1071
1069
  let n = e.target.getAttribute(m);
@@ -1078,7 +1076,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1078
1076
  });
1079
1077
  }
1080
1078
  (n === "false" || n === null) && e.oldValue !== null && gt.has(e.oldValue) && t.holdReleasedAtMs === null && !oe(t.elements) && (t.holdReleasedAtMs = K(performance.now() - t.t0Ms));
1081
- }, V = () => {
1079
+ }, me = () => {
1082
1080
  let e = P();
1083
1081
  if (O.length > 0) {
1084
1082
  if (e.some((e) => O.includes(e))) return;
@@ -1089,18 +1087,18 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1089
1087
  return;
1090
1088
  }
1091
1089
  if (E && e.length === 0) {
1092
- z(performance.now(), []);
1090
+ H(performance.now(), []);
1093
1091
  return;
1094
1092
  }
1095
- if (E) for (let t of e) E.elements.includes(t) || (E.elements.push(t), pe(E.images, E.elements, t.querySelectorAll("img")), E.participants = F(E.elements));
1096
- }, be = null, H = null, Se = () => {
1093
+ if (E) for (let t of e) E.elements.includes(t) || (E.elements.push(t), ue(E.images, E.elements, t.querySelectorAll("img")), E.participants = F(E.elements));
1094
+ }, ve = null, W = null, be = () => {
1097
1095
  let e = document.documentElement;
1098
1096
  if (!e) return !1;
1099
1097
  let t = new MutationObserver((e) => {
1100
1098
  if (k) return;
1101
1099
  let t = performance.now();
1102
- for (let n of e) n.type === "attributes" ? n.attributeName === "data-flemo-anim-hold" ? B(n) : E && (n.attributeName === "data-flemo-morph" || n.attributeName === "data-flemo-morph-camera") && n.target instanceof Element && ke(E.morphs, n.target) : (E && Ae(E.morphs, n, t), E && n.addedNodes.length > 0 && pe(E.images, E.elements, n.addedNodes));
1103
- V();
1100
+ for (let n of e) n.type === "attributes" ? n.attributeName === "data-flemo-anim-hold" ? U(n) : E && (n.attributeName === "data-flemo-morph" || n.attributeName === "data-flemo-morph-camera") && n.target instanceof Element && De(E.morphs, n.target) : (E && Oe(E.morphs, n, t), E && n.addedNodes.length > 0 && ue(E.images, E.elements, n.addedNodes));
1101
+ me();
1104
1102
  });
1105
1103
  try {
1106
1104
  t.observe(e, {
@@ -1119,30 +1117,30 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1119
1117
  } catch {
1120
1118
  return !1;
1121
1119
  }
1122
- return be = t, V(), !0;
1120
+ return ve = t, me(), !0;
1123
1121
  };
1124
- if (!Se()) {
1122
+ if (!be()) {
1125
1123
  let e = () => {
1126
- H = null, k || Se();
1124
+ W = null, k || be();
1127
1125
  };
1128
- H = e, document.addEventListener("DOMContentLoaded", e, { once: !0 });
1126
+ W = e, document.addEventListener("DOMContentLoaded", e, { once: !0 });
1129
1127
  }
1130
- let Ce = () => {
1128
+ let xe = () => {
1131
1129
  document.visibilityState === "hidden" && (M = !0, a && E === null && Ge(C, "3"));
1132
1130
  };
1133
- document.addEventListener("visibilitychange", Ce);
1134
- let we = () => {
1135
- N = 0, !k && (E === null && Ge(C, "3"), N = window.setTimeout(we, bt));
1131
+ document.addEventListener("visibilitychange", xe);
1132
+ let Se = () => {
1133
+ N = 0, !k && (E === null && Ge(C, "3"), N = window.setTimeout(Se, bt));
1136
1134
  };
1137
- a && (N = window.setTimeout(we, bt));
1138
- let Te = (e) => {
1135
+ a && (N = window.setTimeout(Se, bt));
1136
+ let Ce = (e) => {
1139
1137
  let t = x.filter((t) => t.startMs + t.durationMs >= e.t0.ms - 120 && t.startMs <= e.t1.ms), n = e.holds.kind === null ? e.t0.ms : e.holds.releasedAtMs === null ? e.t1.ms : e.t0.ms + e.holds.releasedAtMs;
1140
1138
  return {
1141
1139
  released: t.filter((e) => e.startMs + e.durationMs > n),
1142
1140
  held: t.filter((e) => e.startMs + e.durationMs <= n)
1143
1141
  };
1144
- }, Ee = (e) => x.filter((t) => t.startMs >= d && !e.some((e) => t.startMs + t.durationMs >= e.t0.ms && t.startMs <= e.t1.ms)), De = (e) => {
1145
- let t = Te(e), n = {
1142
+ }, we = (e) => x.filter((t) => t.startMs >= d && !e.some((e) => t.startMs + t.durationMs >= e.t0.ms && t.startMs <= e.t1.ms)), Te = (e) => {
1143
+ let t = Ce(e), n = {
1146
1144
  ...e,
1147
1145
  longTasks: t.released,
1148
1146
  holdLongTasks: t.held,
@@ -1169,12 +1167,12 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1169
1167
  morphs: n.morphs,
1170
1168
  tripwires: n.tripwires
1171
1169
  }), n;
1172
- }, je = () => {
1173
- let e = C.map(De), n = E;
1170
+ }, ke = () => {
1171
+ let e = C.map(Te), n = E;
1174
1172
  if (!n) return e;
1175
1173
  let r = performance.now(), i = r - n.t0Ms > t;
1176
- return [...e, De(R(n, r, i ? re(n) : [], !0))];
1177
- }, U = (e) => {
1174
+ return [...e, Te(V(n, r, i ? re(n) : [], !0))];
1175
+ }, Me = (e) => {
1178
1176
  let t = /* @__PURE__ */ new Set(), n = 0, r = 0;
1179
1177
  for (let i of e) {
1180
1178
  n += i.input.trusted, r += i.input.synthetic;
@@ -1185,16 +1183,16 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1185
1183
  synthetic: r,
1186
1184
  pointerTypes: [...t].sort()
1187
1185
  };
1188
- }, Pe = () => {
1186
+ }, Ne = () => {
1189
1187
  let e = Ve(), t = { ...e };
1190
1188
  for (let [n, r] of Object.entries(l)) n in e || (t[`${n} (at attach, since cleared)`] = r);
1191
- let n = He(t), r = ne(g, I.sawAnimationEvent()), i = je(), a = E, o = it({
1189
+ let n = He(t), r = ne(g, I.sawAnimationEvent()), i = ke(), a = E, o = it({
1192
1190
  environment: r,
1193
- idleLongTasks: Ee(i),
1191
+ idleLongTasks: we(i),
1194
1192
  observedMs: performance.now() - d,
1195
1193
  wentHidden: M,
1196
1194
  documentHidden: document.visibilityState === "hidden",
1197
- input: U(i)
1195
+ input: Me(i)
1198
1196
  });
1199
1197
  return {
1200
1198
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -1220,43 +1218,43 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1220
1218
  flightAnomalies: i.map((e) => e.anomalies)
1221
1219
  }),
1222
1220
  blindSpots: [...c],
1223
- judgingProtocol: [...ge]
1221
+ judgingProtocol: [...pe]
1224
1222
  };
1225
- }, Fe = (e) => (D = e === null || e === "" ? null : e, D), W = () => {
1223
+ }, Pe = (e) => (D = e === null || e === "" ? null : e, D), Fe = () => {
1226
1224
  if (!k) {
1227
- if (k = !0, be?.disconnect(), H !== null && (document.removeEventListener("DOMContentLoaded", H), H = null), document.removeEventListener("visibilitychange", Ce), I.detach(), S?.disconnect(), window.clearTimeout(N), N = 0, E?.rafId != null && cancelAnimationFrame(E.rafId), E = null, j) {
1225
+ if (k = !0, ve?.disconnect(), W !== null && (document.removeEventListener("DOMContentLoaded", W), W = null), document.removeEventListener("visibilitychange", xe), I.detach(), S?.disconnect(), window.clearTimeout(N), N = 0, E?.rafId != null && cancelAnimationFrame(E.rafId), E = null, j) {
1228
1226
  let e = window;
1229
1227
  e.flemo?.__flemoDevtools === !0 && delete e.flemo;
1230
1228
  }
1231
1229
  xt = null;
1232
1230
  }
1233
1231
  }, G = {
1234
- detach: W,
1235
- report: Pe,
1236
- mark: Fe
1232
+ detach: Fe,
1233
+ report: Ne,
1234
+ mark: Pe
1237
1235
  };
1238
1236
  if (i) {
1239
1237
  let e = window, t = e.flemo;
1240
1238
  (t === void 0 || t?.__flemoDevtools === !0) && (e.flemo = {
1241
1239
  __flemoDevtools: !0,
1242
- report: Pe,
1243
- flights: je,
1244
- mark: Fe,
1245
- detach: W
1240
+ report: Ne,
1241
+ flights: ke,
1242
+ mark: Pe,
1243
+ detach: Fe
1246
1244
  }, j = !0);
1247
1245
  }
1248
1246
  return xt = G, G;
1249
- }, wt = O.map((e) => A(d) + j(f, e)).join(","), Tt = () => document.querySelector(wt) !== null, Et = (e) => {
1247
+ }, wt = O.map((e) => A(d) + j(f, e)).join(","), Tt = () => document.querySelector(wt) !== null, Et = "\n:host {\n all: initial;\n color-scheme: dark;\n}\n* { box-sizing: border-box; }\n.root {\n --bg: #14161a;\n --bg-soft: #1b1e24;\n --line: #2b3038;\n --fg: #e6e9ef;\n --fg-dim: #99a1b0;\n --accent: #7cc4ff;\n --warn: #ffb454;\n --bad: #ff6b6b;\n font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n color: var(--fg);\n}\n@media (prefers-color-scheme: light) {\n .root {\n --bg: #ffffff;\n --bg-soft: #f4f6f9;\n --line: #dde1e8;\n --fg: #1a1d22;\n --fg-dim: #5c6472;\n --accent: #0b6bcb;\n --warn: #a35a00;\n --bad: #c2261f;\n }\n}\n", Dt = (e) => {
1250
1248
  let t = document.createElement("div");
1251
1249
  t.setAttribute(D, ""), t.style.position = "fixed", t.style.top = "0", t.style.left = "0", t.style.width = "0", t.style.height = "0", t.style.zIndex = "2147483000";
1252
1250
  let n = t.attachShadow({ mode: "open" }), r = document.createElement("style");
1253
- r.textContent = e, n.appendChild(r);
1251
+ r.textContent = Et + e, n.appendChild(r);
1254
1252
  let i = document.createElement("div");
1255
1253
  return i.className = "root", n.appendChild(i), {
1256
1254
  host: t,
1257
1255
  root: i
1258
1256
  };
1259
- }, Dt = () => {}, Ot = (e) => {
1257
+ }, Ot = () => {}, kt = (e) => {
1260
1258
  if (e) return {
1261
1259
  recorder: e,
1262
1260
  ownsRecorder: !1
@@ -1265,7 +1263,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1265
1263
  return t?.__flemoDevtools === !0 && typeof t.report == "function" ? {
1266
1264
  recorder: {
1267
1265
  report: t.report,
1268
- detach: Dt,
1266
+ detach: Ot,
1269
1267
  mark: t.mark ?? (() => null)
1270
1268
  },
1271
1269
  ownsRecorder: !1
@@ -1273,18 +1271,18 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1273
1271
  recorder: Ct(),
1274
1272
  ownsRecorder: !0
1275
1273
  };
1276
- }, kt = "http://www.w3.org/2000/svg", q = (e, t, n) => {
1274
+ }, At = "http://www.w3.org/2000/svg", q = (e, t, n) => {
1277
1275
  let r = document.createElement(e);
1278
1276
  return t !== void 0 && (r.className = t), n !== void 0 && (r.textContent = n), r;
1279
- }, At = (e, t) => {
1280
- let n = document.createElementNS(kt, e);
1277
+ }, jt = (e, t) => {
1278
+ let n = document.createElementNS(At, e);
1281
1279
  for (let [e, r] of Object.entries(t)) n.setAttribute(e, r);
1282
1280
  return n;
1283
- }, jt = (e) => {
1281
+ }, Mt = (e) => {
1284
1282
  for (; e.firstChild !== null;) e.removeChild(e.firstChild);
1285
- }, Mt = (e, t) => {
1283
+ }, Nt = (e, t) => {
1286
1284
  e.textContent !== t && (e.textContent = t);
1287
- }, J = (e) => e == null || e === "" ? "—" : String(e), Y = (e) => typeof e == "number" && Number.isFinite(e) ? `${Math.round(e)}ms` : "—", Nt = (e) => typeof e == "number" && Number.isFinite(e) ? `${Math.round(e * 10) / 10}ms` : "—", X = (e) => typeof e == "number" && Number.isFinite(e) ? String(e) : "—", Pt = (e) => e === !0 ? "yes" : e === !1 ? "no" : "—", Ft = (e) => {
1285
+ }, J = (e) => e == null || e === "" ? "—" : String(e), Y = (e) => typeof e == "number" && Number.isFinite(e) ? `${Math.round(e)}ms` : "—", Pt = (e) => typeof e == "number" && Number.isFinite(e) ? `${Math.round(e * 10) / 10}ms` : "—", X = (e) => typeof e == "number" && Number.isFinite(e) ? String(e) : "—", Ft = (e) => e === !0 ? "yes" : e === !1 ? "no" : "—", It = (e) => {
1288
1286
  let t = e?.environment;
1289
1287
  if (!t) return "—";
1290
1288
  let n = t.viewport, r = n && typeof n.width == "number" && typeof n.height == "number" ? `${Math.round(n.width)}×${Math.round(n.height)}` : "—";
@@ -1292,14 +1290,14 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1292
1290
  J(t.engine),
1293
1291
  `dpr ${J(t.devicePixelRatio)}`,
1294
1292
  r,
1295
- `rAF ${Nt(t.rafCadence?.medianGapMs)}`
1293
+ `rAF ${Pt(t.rafCadence?.medianGapMs)}`
1296
1294
  ].join(" · ");
1297
- }, It = (e, t) => `${t ?? ""}#${e.map((e) => `${e?.id ?? ""}|${e?.kind ?? ""}|${e?.driver ?? ""}|${Math.round(e?.durationMs ?? 0)}|${e?.participants?.screens ?? 0}|${e?.anomalies?.length ?? 0}`).join(",")}`, Lt = (e) => {
1295
+ }, Lt = (e, t) => `${t ?? ""}#${e.map((e) => `${e?.id ?? ""}|${e?.kind ?? ""}|${e?.driver ?? ""}|${Math.round(e?.durationMs ?? 0)}|${e?.participants?.screens ?? 0}|${e?.anomalies?.length ?? 0}`).join(",")}`, Rt = (e) => {
1298
1296
  let t = e?.released?.gaps;
1299
1297
  if (!Array.isArray(t)) return null;
1300
1298
  let n = t.filter((e) => typeof e == "number" && Number.isFinite(e));
1301
1299
  return n.length >= 2 ? n : null;
1302
- }, Rt = "\n:host {\n all: initial;\n color-scheme: dark;\n}\n* { box-sizing: border-box; }\n.root {\n --bg: #14161a;\n --bg-soft: #1b1e24;\n --line: #2b3038;\n --fg: #e6e9ef;\n --fg-dim: #99a1b0;\n --accent: #7cc4ff;\n --warn: #ffb454;\n --bad: #ff6b6b;\n font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n color: var(--fg);\n}\n@media (prefers-color-scheme: light) {\n .root {\n --bg: #ffffff;\n --bg-soft: #f4f6f9;\n --line: #dde1e8;\n --fg: #1a1d22;\n --fg-dim: #5c6472;\n --accent: #0b6bcb;\n --warn: #a35a00;\n --bad: #c2261f;\n }\n}\n.toggle {\n position: fixed;\n bottom: 12px;\n z-index: 2147483000;\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 0;\n padding: 6px 10px;\n border: 1px solid var(--line);\n border-radius: 999px;\n background: var(--bg);\n color: var(--fg);\n font: inherit;\n cursor: pointer;\n}\n.toggle:hover { background: var(--bg-soft); }\n.toggle[data-corner=\"bottom-right\"] { right: 12px; }\n.toggle[data-corner=\"bottom-left\"] { left: 12px; }\n.mark { font-weight: 700; letter-spacing: 0.04em; }\n.count {\n padding: 0 6px;\n border-radius: 999px;\n background: var(--bg-soft);\n color: var(--fg-dim);\n}\n.dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--bad);\n}\n.dot[hidden] { display: none; }\n.panel {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 2147482999;\n display: flex;\n flex-direction: column;\n max-width: 100%;\n border-top: 1px solid var(--line);\n background: var(--bg);\n overflow: hidden;\n}\n.panel[hidden] { display: none; }\n.grip {\n flex: 0 0 6px;\n height: 6px;\n background: var(--line);\n cursor: ns-resize;\n touch-action: none;\n}\n.head {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n border-bottom: 1px solid var(--line);\n}\n.env { color: var(--fg-dim); }\n.spacer { flex: 1 1 auto; }\n.act {\n padding: 4px 8px;\n border: 1px solid var(--line);\n border-radius: 4px;\n background: var(--bg-soft);\n color: var(--fg);\n font: inherit;\n cursor: pointer;\n}\n.chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n flex: 1 1 100%;\n}\n.chips:empty { display: none; }\n.chip {\n padding: 2px 8px;\n border: 1px solid var(--line);\n border-radius: 999px;\n background: var(--bg-soft);\n color: var(--fg-dim);\n max-width: 100%;\n overflow-wrap: anywhere;\n}\n/* The verdict reads as prose, not as a tag: it is a sentence about the whole\n session and it is the first thing anybody should read. */\n.chip.lead {\n border-color: var(--fg);\n color: var(--fg);\n white-space: normal;\n max-width: 100%;\n line-height: 1.5;\n}\n.chip.warn { border-color: var(--warn); color: var(--warn); }\n.chip.bad { border-color: var(--bad); color: var(--bad); }\n.body {\n display: flex;\n flex: 1 1 auto;\n min-height: 0;\n}\n.list {\n flex: 0 0 40%;\n max-width: 340px;\n min-width: 180px;\n overflow: auto;\n border-right: 1px solid var(--line);\n}\n.row {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 6px 10px;\n border: 0;\n border-bottom: 1px solid var(--line);\n background: none;\n color: var(--fg);\n font: inherit;\n text-align: left;\n cursor: pointer;\n}\n.row[aria-selected=\"true\"] { background: var(--bg-soft); }\n.row .kind { font-weight: 700; }\n.row .driver { color: var(--accent); }\n.row .dur, .row .screens { color: var(--fg-dim); }\n.row .n {\n margin-left: auto;\n padding: 0 6px;\n border-radius: 999px;\n background: var(--bg-soft);\n color: var(--fg-dim);\n}\n.row .n.bad { background: var(--bad); color: #fff; }\n.detail { flex: 1 1 auto; overflow: auto; padding: 8px 10px; }\n.section { margin: 0 0 10px; }\n.section > h2 {\n margin: 0 0 4px;\n font: inherit;\n font-weight: 700;\n color: var(--fg-dim);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n.kv { display: flex; gap: 8px; }\n.kv > .k { flex: 0 0 34%; max-width: 180px; color: var(--fg-dim); }\n.kv > .v { flex: 1 1 auto; overflow-wrap: anywhere; }\n/* A value that IS the finding — a stall, a re-asserted hold, an orphan. */\n.kv > .v.bad { color: var(--bad); }\n.li { overflow-wrap: anywhere; }\n.li.bad { color: var(--bad); }\n.dim { color: var(--fg-dim); }\n.spark { display: block; width: 100%; height: 28px; }\n.foot { border-top: 1px solid var(--line); padding: 6px 10px; color: var(--fg-dim); }\n.foot summary { cursor: pointer; }\n.foot .li { margin-top: 4px; }\n", zt = 48, Z = (e, t, n, r) => {
1300
+ }, zt = "\n.toggle {\n position: fixed;\n bottom: 12px;\n z-index: 2147483000;\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 0;\n padding: 6px 10px;\n border: 1px solid var(--line);\n border-radius: 999px;\n background: var(--bg);\n color: var(--fg);\n font: inherit;\n cursor: pointer;\n}\n.toggle:hover { background: var(--bg-soft); }\n.toggle[data-corner=\"bottom-right\"] { right: 12px; }\n.toggle[data-corner=\"bottom-left\"] { left: 12px; }\n.mark { font-weight: 700; letter-spacing: 0.04em; }\n.count {\n padding: 0 6px;\n border-radius: 999px;\n background: var(--bg-soft);\n color: var(--fg-dim);\n}\n.dot {\n width: 7px;\n height: 7px;\n border-radius: 50%;\n background: var(--bad);\n}\n.dot[hidden] { display: none; }\n.panel {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 2147482999;\n display: flex;\n flex-direction: column;\n max-width: 100%;\n border-top: 1px solid var(--line);\n background: var(--bg);\n overflow: hidden;\n}\n.panel[hidden] { display: none; }\n.grip {\n flex: 0 0 6px;\n height: 6px;\n background: var(--line);\n cursor: ns-resize;\n touch-action: none;\n}\n.head {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n border-bottom: 1px solid var(--line);\n}\n.env { color: var(--fg-dim); }\n.spacer { flex: 1 1 auto; }\n.act {\n padding: 4px 8px;\n border: 1px solid var(--line);\n border-radius: 4px;\n background: var(--bg-soft);\n color: var(--fg);\n font: inherit;\n cursor: pointer;\n}\n.chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n flex: 1 1 100%;\n}\n.chips:empty { display: none; }\n.chip {\n padding: 2px 8px;\n border: 1px solid var(--line);\n border-radius: 999px;\n background: var(--bg-soft);\n color: var(--fg-dim);\n max-width: 100%;\n overflow-wrap: anywhere;\n}\n/* The verdict reads as prose, not as a tag: it is a sentence about the whole\n session and it is the first thing anybody should read. */\n.chip.lead {\n border-color: var(--fg);\n color: var(--fg);\n white-space: normal;\n max-width: 100%;\n line-height: 1.5;\n}\n.chip.warn { border-color: var(--warn); color: var(--warn); }\n.chip.bad { border-color: var(--bad); color: var(--bad); }\n.body {\n display: flex;\n flex: 1 1 auto;\n min-height: 0;\n}\n.list {\n flex: 0 0 40%;\n max-width: 340px;\n min-width: 180px;\n overflow: auto;\n border-right: 1px solid var(--line);\n}\n.row {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 6px 10px;\n border: 0;\n border-bottom: 1px solid var(--line);\n background: none;\n color: var(--fg);\n font: inherit;\n text-align: left;\n cursor: pointer;\n}\n.row[aria-selected=\"true\"] { background: var(--bg-soft); }\n.row .kind { font-weight: 700; }\n.row .driver { color: var(--accent); }\n.row .dur, .row .screens { color: var(--fg-dim); }\n.row .n {\n margin-left: auto;\n padding: 0 6px;\n border-radius: 999px;\n background: var(--bg-soft);\n color: var(--fg-dim);\n}\n.row .n.bad { background: var(--bad); color: #fff; }\n.detail { flex: 1 1 auto; overflow: auto; padding: 8px 10px; }\n.section { margin: 0 0 10px; }\n.section > h2 {\n margin: 0 0 4px;\n font: inherit;\n font-weight: 700;\n color: var(--fg-dim);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n.kv { display: flex; gap: 8px; }\n.kv > .k { flex: 0 0 34%; max-width: 180px; color: var(--fg-dim); }\n.kv > .v { flex: 1 1 auto; overflow-wrap: anywhere; }\n/* A value that IS the finding — a stall, a re-asserted hold, an orphan. */\n.kv > .v.bad { color: var(--bad); }\n.li { overflow-wrap: anywhere; }\n.li.bad { color: var(--bad); }\n.dim { color: var(--fg-dim); }\n.spark { display: block; width: 100%; height: 28px; }\n.foot { border-top: 1px solid var(--line); padding: 6px 10px; color: var(--fg-dim); }\n.foot summary { cursor: pointer; }\n.foot .li { margin-top: 4px; }\n", Bt = 48, Z = (e, t, n, r) => {
1303
1301
  let i = q("div", "kv");
1304
1302
  i.appendChild(q("span", "k", t)), i.appendChild(q("span", r ? `v ${r}` : "v", n)), e.appendChild(i);
1305
1303
  }, Q = (e, t) => {
@@ -1307,15 +1305,15 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1307
1305
  return n.appendChild(q("h2", void 0, t)), e.appendChild(n), n;
1308
1306
  }, $ = (e, t, n = "li") => {
1309
1307
  e.appendChild(q("div", n, t));
1310
- }, Bt = (e, t) => {
1311
- jt(e);
1308
+ }, Vt = (e, t) => {
1309
+ Mt(e);
1312
1310
  for (let n of t?.verdict ?? []) e.appendChild(q("span", "chip lead", J(n)));
1313
1311
  for (let n of t?.preconditions ?? []) n?.status === "violated" && e.appendChild(q("span", "chip bad", `${n.id}: ${J(n.detail)}`));
1314
1312
  for (let n of t?.overrides?.warnings ?? []) e.appendChild(q("span", "chip warn", J(n)));
1315
1313
  for (let n of t?.anomalies ?? []) e.appendChild(q("span", "chip bad", J(n)));
1316
1314
  for (let [n, r] of Object.entries(t?.overrides?.active ?? {})) e.appendChild(q("span", "chip", `${n}=${String(r)}`));
1317
- }, Vt = (e, t, n, r) => {
1318
- if (jt(e), t.length === 0) {
1315
+ }, Ht = (e, t, n, r) => {
1316
+ if (Mt(e), t.length === 0) {
1319
1317
  $(e, "no flights recorded yet — navigate once", "li dim");
1320
1318
  return;
1321
1319
  }
@@ -1325,32 +1323,32 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1325
1323
  let c = a?.anomalies?.length ?? 0;
1326
1324
  s.appendChild(q("span", c > 0 ? "n bad" : "n", String(c))), s.addEventListener("click", () => r(o)), e.appendChild(s);
1327
1325
  }
1328
- }, Ht = (e, t, n) => {
1326
+ }, Ut = (e, t, n) => {
1329
1327
  if (!n) {
1330
1328
  Z(e, t, "—");
1331
1329
  return;
1332
1330
  }
1333
1331
  let r = [
1334
1332
  `${X(n.count)} frames`,
1335
- `median ${Nt(n.medianGapMs)}`,
1336
- `max ${Nt(n.maxGapMs)}`
1333
+ `median ${Pt(n.medianGapMs)}`,
1334
+ `max ${Pt(n.maxGapMs)}`
1337
1335
  ];
1338
1336
  typeof n.over30Count == "number" && r.push(`>30ms ×${n.over30Count}`), Z(e, t, r.join(" · "));
1339
- }, Ut = (e) => {
1340
- let t = Math.max(...e), n = t > 0 ? t : 1, r = 100 / (e.length - 1), i = e.map((e, t) => `${Math.round(t * r * 10) / 10},${Math.round((27 - e / n * 26) * 10) / 10}`).join(" "), a = At("svg", {
1337
+ }, Wt = (e) => {
1338
+ let t = Math.max(...e), n = t > 0 ? t : 1, r = 100 / (e.length - 1), i = e.map((e, t) => `${Math.round(t * r * 10) / 10},${Math.round((27 - e / n * 26) * 10) / 10}`).join(" "), a = jt("svg", {
1341
1339
  class: "spark",
1342
1340
  viewBox: "0 0 100 28",
1343
1341
  preserveAspectRatio: "none",
1344
1342
  "aria-hidden": "true"
1345
1343
  });
1346
- return a.appendChild(At("polyline", {
1344
+ return a.appendChild(jt("polyline", {
1347
1345
  points: i,
1348
1346
  fill: "none",
1349
1347
  stroke: "currentColor",
1350
1348
  "stroke-width": "1",
1351
1349
  "vector-effect": "non-scaling-stroke"
1352
1350
  })), a;
1353
- }, Wt = (e, t) => {
1351
+ }, Gt = (e, t) => {
1354
1352
  let n = t.longTasks ?? [], r = t.holdLongTasks ?? [];
1355
1353
  if (n.length === 0 && r.length === 0) {
1356
1354
  $(e, "none", "li dim");
@@ -1359,19 +1357,19 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1359
1357
  let i = (e) => `${Y(e?.startMs)} + ${Y(e?.durationMs)}`;
1360
1358
  for (let t of n) $(e, i(t), "li bad");
1361
1359
  for (let t of r) $(e, `${i(t)} (absorbed by hold)`, "li dim");
1362
- }, Gt = (e, t) => {
1363
- if (jt(e), !t) {
1360
+ }, Kt = (e, t) => {
1361
+ if (Mt(e), !t) {
1364
1362
  $(e, "select a flight", "li dim");
1365
1363
  return;
1366
1364
  }
1367
1365
  let n = Q(e, "timing");
1368
1366
  Z(n, "id", J(t.id)), Z(n, "kind / driver", `${J(t.kind)} · ${J(t.driver)}`), Z(n, "router", J(t.routerId)), Z(n, "t0", J(t.t0?.iso)), Z(n, "duration", Y(t.durationMs)), Z(n, "participants", `${X(t.participants?.screens)} screens · ${X(t.participants?.bars)} bars · ${X(t.participants?.decorators)} decorators · ${X(t.participants?.parts)} parts`), Z(n, "hold", `${J(t.holds?.kind)} · released ${Y(t.holds?.releasedAtMs)}`);
1369
1367
  let r = Q(e, "frames");
1370
- Ht(r, "held (absorbed)", t.frameSamples?.held), Ht(r, "released (visible)", t.frameSamples?.released);
1371
- let i = Lt(t.frameSamples);
1372
- i && r.appendChild(Ut(i));
1368
+ Ut(r, "held (absorbed)", t.frameSamples?.held), Ut(r, "released (visible)", t.frameSamples?.released);
1369
+ let i = Rt(t.frameSamples);
1370
+ i && r.appendChild(Wt(i));
1373
1371
  let a = Q(e, "motion (did it move)"), o = t.motion?.longestStallMs, s = t.motion?.holdReassertedAtMs;
1374
- Z(a, "released frames", X(t.motion?.sampledFrames)), Z(a, "stalled frames", X(t.motion?.stalledFrames), (t.motion?.stalledFrames ?? 0) > 0 ? "bad" : void 0), Z(a, "longest stall", Y(o), (o ?? 0) >= zt ? "bad" : void 0), Z(a, "paused after release", Pt(t.motion?.pausedAfterRelease), t.motion?.pausedAfterRelease === !0 ? "bad" : void 0), Z(a, "hold re-asserted", s == null ? "no" : Y(s), typeof s == "number" ? "bad" : void 0), Z(a, "first animation", t.motion?.firstAnimationAtMs === null || t.motion?.firstAnimationAtMs === void 0 ? "not observed" : `+${Y(t.motion.firstAnimationAtMs)} after t0`);
1372
+ Z(a, "released frames", X(t.motion?.sampledFrames)), Z(a, "stalled frames", X(t.motion?.stalledFrames), (t.motion?.stalledFrames ?? 0) > 0 ? "bad" : void 0), Z(a, "longest stall", Y(o), (o ?? 0) >= Bt ? "bad" : void 0), Z(a, "paused after release", Ft(t.motion?.pausedAfterRelease), t.motion?.pausedAfterRelease === !0 ? "bad" : void 0), Z(a, "hold re-asserted", s == null ? "no" : Y(s), typeof s == "number" ? "bad" : void 0), Z(a, "first animation", t.motion?.firstAnimationAtMs === null || t.motion?.firstAnimationAtMs === void 0 ? "not observed" : `+${Y(t.motion.firstAnimationAtMs)} after t0`);
1375
1373
  let c = t.morphs;
1376
1374
  if (c) {
1377
1375
  let t = Q(e, "shared elements");
@@ -1379,7 +1377,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1379
1377
  let n = c.skipped ?? [];
1380
1378
  Z(t, "did not fly", n.length === 0 ? "none" : n.join(", "), n.length > 0 ? "bad" : void 0);
1381
1379
  let r = c.duplicatedKeys ?? [];
1382
- r.length > 0 && Z(t, "duplicate keys in one screen", r.join(", "), "bad"), Z(t, "camera", Pt(c.camera)), Z(t, "ghosts", X(c.ghosts));
1380
+ r.length > 0 && Z(t, "duplicate keys in one screen", r.join(", "), "bad"), Z(t, "camera", Ft(c.camera)), Z(t, "ghosts", X(c.ghosts));
1383
1381
  let i = (c.strandedRoles ?? 0) + (c.strandedStandIns ?? 0) + (c.strandedGhosts ?? 0) + (c.layerResidue ?? 0) + (c.leakedSheetRules ?? 0);
1384
1382
  Z(t, "residue at rest", i === 0 ? "clean" : `${X(c.strandedRoles)} roles · ${X(c.strandedStandIns)} stand-ins · ${X(c.strandedGhosts)} ghosts · ${X(c.layerResidue)} in layer · ${X(c.leakedSheetRules)} rules`, i > 0 ? "bad" : void 0);
1385
1383
  }
@@ -1394,11 +1392,11 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1394
1392
  Z(t, "input", `${X(u.trusted)} trusted · ${X(u.synthetic)} synthetic`, u.synthetic > 0 ? "bad" : void 0), Z(t, "pointer types", u.pointerTypes?.join(", ") || "none observed");
1395
1393
  }
1396
1394
  let d = Q(e, "images"), f = t.images?.completedDuringFlight ?? 0, p = t.images?.heldDuringFlight ?? 0, m = t.images?.completedUnheld, h = typeof m == "number" ? m > 0 : f > p;
1397
- Z(d, "loading at t0", X(t.images?.loadingAtStart)), Z(d, "added mid-flight", X(t.images?.addedDuringFlight)), Z(d, "completed mid-flight", X(t.images?.completedDuringFlight), h ? "bad" : void 0), Z(d, "held by the engine", X(t.images?.heldDuringFlight)), Z(d, "completed without hold", X(m), h ? "bad" : void 0), Wt(Q(e, "long tasks"), t);
1395
+ Z(d, "loading at t0", X(t.images?.loadingAtStart)), Z(d, "added mid-flight", X(t.images?.addedDuringFlight)), Z(d, "completed mid-flight", X(t.images?.completedDuringFlight), h ? "bad" : void 0), Z(d, "held by the engine", X(t.images?.heldDuringFlight)), Z(d, "completed without hold", X(m), h ? "bad" : void 0), Gt(Q(e, "long tasks"), t);
1398
1396
  let g = Q(e, "landing"), _ = t.landing?.residualInlineTransforms ?? [];
1399
1397
  if (_.length === 0) Z(g, "inline residue", "clean");
1400
1398
  else for (let e of _) Z(g, "inline residue", J(e));
1401
- Z(g, "off-viewport at rest", Pt(t.landing?.offViewportAtRest));
1399
+ Z(g, "off-viewport at rest", Ft(t.landing?.offViewportAtRest));
1402
1400
  let v = t.landing?.stuckStatuses ?? [];
1403
1401
  Z(g, "stuck statuses", v.length === 0 ? "none" : v.join(", "));
1404
1402
  let y = t.landing?.orphanedHolds ?? [];
@@ -1410,13 +1408,13 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1410
1408
  return;
1411
1409
  }
1412
1410
  for (let e of x) $(b, J(e), "li bad");
1413
- }, Kt = (e, t) => {
1414
- jt(e);
1411
+ }, qt = (e, t) => {
1412
+ Mt(e);
1415
1413
  for (let n of t ?? []) $(e, J(n));
1416
- }, qt = 320, Jt = 2e3, Yt = 120, Xt = "Copy report JSON", Zt = () => {}, Qt = null, $t = (e = {}) => {
1417
- if (Qt) return Qt;
1418
- if (typeof document > "u") return { detach: Zt };
1419
- let { recorder: t, ownsRecorder: n } = Ot(e.recorder), { host: r, root: i } = Et(Rt), a = q("button", "toggle");
1414
+ }, Jt = 320, Yt = 2e3, Xt = 120, Zt = "Copy report JSON", Qt = () => {}, $t = null, en = (e = {}) => {
1415
+ if ($t) return $t;
1416
+ if (typeof document > "u") return { detach: Qt };
1417
+ let { recorder: t, ownsRecorder: n } = kt(e.recorder), { host: r, root: i } = Dt(zt), a = q("button", "toggle");
1420
1418
  a.type = "button", a.setAttribute("data-corner", e.position ?? "bottom-right"), a.setAttribute("aria-label", "flemo devtools");
1421
1419
  let o = q("span", "count", "0"), s = q("span", "dot");
1422
1420
  s.hidden = !0, a.appendChild(q("span", "mark", "flemo")), a.appendChild(o), a.appendChild(s);
@@ -1424,7 +1422,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1424
1422
  c.hidden = !0;
1425
1423
  let l = q("div", "grip");
1426
1424
  l.setAttribute("role", "separator"), l.setAttribute("aria-label", "Resize flemo devtools panel");
1427
- let u = q("header", "head"), d = q("div", "env", "—"), f = q("button", "act", Xt);
1425
+ let u = q("header", "head"), d = q("div", "env", "—"), f = q("button", "act", Zt);
1428
1426
  f.type = "button";
1429
1427
  let p = q("button", "act", "Close");
1430
1428
  p.type = "button";
@@ -1440,9 +1438,9 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1440
1438
  x.appendChild(q("summary", void 0, "What this cannot see"));
1441
1439
  let S = q("div");
1442
1440
  x.appendChild(S), b.appendChild(x), c.appendChild(l), c.appendChild(u), c.appendChild(_), c.appendChild(b), i.appendChild(a), i.appendChild(c);
1443
- let C = !1, w = e.initialOpen === !0, T = null, E = "", D = "", O = "", k = !1, A = 0, j = 0, M = -1, N = e.buckets && e.buckets.length > 0 ? e.buckets : ["A", "B"], P = (e) => Math.min(Math.max(e, Yt), Math.max(Yt, window.innerHeight * .9)), ee = () => {
1441
+ let C = !1, w = e.initialOpen === !0, T = null, E = "", D = "", O = "", k = !1, A = 0, j = 0, M = -1, N = e.buckets && e.buckets.length > 0 ? e.buckets : ["A", "B"], P = (e) => Math.min(Math.max(e, Xt), Math.max(Xt, window.innerHeight * .9)), ee = () => {
1444
1442
  try {
1445
- let e = sessionStorage.getItem(U);
1443
+ let e = sessionStorage.getItem(Me);
1446
1444
  if (e === null) return null;
1447
1445
  let t = Number.parseFloat(e);
1448
1446
  return Number.isFinite(t) ? t : null;
@@ -1451,7 +1449,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1451
1449
  }
1452
1450
  }, te = (e) => {
1453
1451
  try {
1454
- sessionStorage.setItem(U, String(Math.round(e)));
1452
+ sessionStorage.setItem(Me, String(Math.round(e)));
1455
1453
  } catch {}
1456
1454
  }, F = P(ee() ?? window.innerHeight * .4);
1457
1455
  c.style.height = `${Math.round(F)}px`;
@@ -1465,20 +1463,20 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1465
1463
  e !== T && (T = e, L());
1466
1464
  }, re = () => {
1467
1465
  let e = I(), t = e?.flights ?? [];
1468
- Mt(o, String(t.length));
1466
+ Nt(o, String(t.length));
1469
1467
  let n = t.some((e) => (e?.anomalies?.length ?? 0) > 0);
1470
1468
  if (s.hidden = !n, c.hidden = !w, !w) return;
1471
- Mt(d, Ft(e));
1469
+ Nt(d, It(e));
1472
1470
  let r = JSON.stringify([
1473
1471
  e?.overrides?.warnings ?? [],
1474
1472
  e?.anomalies ?? [],
1475
1473
  e?.overrides?.active ?? {}
1476
1474
  ]);
1477
- r !== O && (O = r, Bt(g, e)), T === null && t.length > 0 && (T = t[t.length - 1]?.id ?? null);
1478
- let i = It(t, T);
1479
- i !== E && (E = i, Vt(v, t, T, ne));
1475
+ r !== O && (O = r, Vt(g, e)), T === null && t.length > 0 && (T = t[t.length - 1]?.id ?? null);
1476
+ let i = Lt(t, T);
1477
+ i !== E && (E = i, Ht(v, t, T, ne));
1480
1478
  let a = t.find((e) => e?.id === T) ?? null, l = JSON.stringify(a);
1481
- l !== D && (D = l, Gt(y, a)), k || (k = !0, Kt(S, e?.blindSpots));
1479
+ l !== D && (D = l, Kt(y, a)), k || (k = !0, qt(S, e?.blindSpots));
1482
1480
  };
1483
1481
  function L() {
1484
1482
  C || Tt() || re();
@@ -1487,38 +1485,38 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1487
1485
  A = 0, L(), ae();
1488
1486
  }
1489
1487
  function ae() {
1490
- A = window.setTimeout(ie, w ? qt : Jt);
1488
+ A = window.setTimeout(ie, w ? Jt : Yt);
1491
1489
  }
1492
1490
  let oe = () => {
1493
1491
  window.clearTimeout(A), ae();
1494
- }, se = (e) => {
1492
+ }, R = (e) => {
1495
1493
  w = e, oe(), L();
1496
1494
  };
1497
- a.addEventListener("click", () => se(!w)), p.addEventListener("click", () => se(!1)), m.addEventListener("click", () => z()), h.addEventListener("click", () => {
1495
+ a.addEventListener("click", () => R(!w)), p.addEventListener("click", () => R(!1)), m.addEventListener("click", () => H()), h.addEventListener("click", () => {
1498
1496
  M = M + 1 >= N.length ? -1 : M + 1;
1499
1497
  let e = M === -1 ? null : N[M];
1500
- t.mark(e), Mt(h, `A/B: ${e ?? "off"}`), O = "", L();
1498
+ t.mark(e), Nt(h, `A/B: ${e ?? "off"}`), O = "", L();
1501
1499
  });
1502
- let ce = () => {
1500
+ let se = () => {
1503
1501
  if (!C) {
1504
1502
  if (Tt()) {
1505
- window.clearTimeout(j), j = window.setTimeout(ce, qt);
1503
+ window.clearTimeout(j), j = window.setTimeout(se, Jt);
1506
1504
  return;
1507
1505
  }
1508
- Mt(f, "Copied ✓"), window.clearTimeout(j), j = window.setTimeout(le, 1200);
1506
+ Nt(f, "Copied ✓"), window.clearTimeout(j), j = window.setTimeout(z, 1200);
1509
1507
  }
1510
1508
  };
1511
- function le() {
1509
+ function z() {
1512
1510
  if (Tt()) {
1513
- j = window.setTimeout(le, qt);
1511
+ j = window.setTimeout(z, Jt);
1514
1512
  return;
1515
1513
  }
1516
- j = 0, Mt(f, Xt);
1514
+ j = 0, Nt(f, Zt);
1517
1515
  }
1518
- let ue = (e) => {
1516
+ let B = (e) => {
1519
1517
  if (C) return;
1520
1518
  if (Tt()) {
1521
- window.clearTimeout(j), j = window.setTimeout(() => ue(e), qt);
1519
+ window.clearTimeout(j), j = window.setTimeout(() => B(e), Jt);
1522
1520
  return;
1523
1521
  }
1524
1522
  let t = q("textarea");
@@ -1527,80 +1525,161 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1527
1525
  try {
1528
1526
  n.execCommand?.("copy");
1529
1527
  } catch {}
1530
- t.remove(), ce();
1528
+ t.remove(), se();
1531
1529
  };
1532
1530
  f.addEventListener("click", () => {
1533
1531
  let e = JSON.stringify(I(), null, 2), t = navigator.clipboard;
1534
1532
  if (t && typeof t.writeText == "function") {
1535
- t.writeText(e).then(ce, () => ue(e));
1533
+ t.writeText(e).then(se, () => B(e));
1536
1534
  return;
1537
1535
  }
1538
- ue(e);
1536
+ B(e);
1539
1537
  });
1540
- let de = (e) => {
1538
+ let ce = (e) => {
1541
1539
  F = P(window.innerHeight - e.clientY), c.style.height = `${Math.round(F)}px`;
1542
- }, R = () => {
1543
- window.removeEventListener("pointermove", de), window.removeEventListener("pointerup", R), te(F);
1540
+ }, V = () => {
1541
+ window.removeEventListener("pointermove", ce), window.removeEventListener("pointerup", V), te(F);
1544
1542
  };
1545
1543
  l.addEventListener("pointerdown", (e) => {
1546
- e.preventDefault(), window.addEventListener("pointermove", de), window.addEventListener("pointerup", R);
1544
+ e.preventDefault(), window.addEventListener("pointermove", ce), window.addEventListener("pointerup", V);
1547
1545
  });
1548
- function z() {
1549
- C || (C = !0, window.clearTimeout(A), A = 0, window.clearTimeout(j), j = 0, window.removeEventListener("pointermove", de), window.removeEventListener("pointerup", R), r.remove(), n && t.detach(), Qt = null);
1546
+ function H() {
1547
+ C || (C = !0, window.clearTimeout(A), A = 0, window.clearTimeout(j), j = 0, window.removeEventListener("pointermove", ce), window.removeEventListener("pointerup", V), r.remove(), n && t.detach(), $t = null);
1550
1548
  }
1551
1549
  document.body.appendChild(r), L(), ae();
1552
- let fe = { detach: z };
1553
- return Qt = fe, fe;
1554
- }, en = 500, tn = 450, nn = "\n:host { all: initial; }\n.root { all: initial; }\n.hud {\n position: fixed;\n left: 50%;\n transform: translateX(-50%);\n max-width: calc(100vw - 16px);\n box-sizing: border-box;\n padding: 6px 10px;\n border-radius: 8px;\n background: #0b0f14;\n color: #e8f0f8;\n border: 1px solid #2b3a4a;\n font: 500 12px/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n white-space: pre;\n text-align: left;\n overflow-x: auto;\n -webkit-user-select: none;\n user-select: none;\n touch-action: manipulation;\n /* No transition and no keyframe anywhere in this sheet: the readout must\n never be a moving thing on a screen whose motion is under test. */\n}\n.hud[data-edge=\"top\"] { top: max(8px, env(safe-area-inset-top)); }\n.hud[data-edge=\"bottom\"] { bottom: max(8px, env(safe-area-inset-bottom)); }\n.hud[data-alarm=\"true\"] { border-color: #ff6b6b; color: #ffd9d9; }\n.hud[data-blocked=\"true\"] { border-color: #ffb020; color: #ffe9c2; }\n", rn = (e) => Math.round(e * 10) / 10, an = (e) => {
1550
+ let le = { detach: H };
1551
+ return $t = le, le;
1552
+ }, tn = 500, nn = 450, rn = "flemo:devtools-hud-hidden", an = "\n.dock {\n position: fixed;\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 6px;\n max-width: calc(100vw - 16px);\n}\n.dock[data-edge^=\"top\"] {\n top: max(8px, env(safe-area-inset-top));\n /* The control sits nearest the edge the dock is anchored to, whichever that\n is, so it does not MOVE when the readout it hides collapses under it. A\n control that walks across the screen as you use it is one you have to look\n for, and the whole point of it is to be found with a thumb. */\n flex-direction: column-reverse;\n}\n.dock[data-edge^=\"bottom\"] { bottom: max(12px, env(safe-area-inset-bottom)); }\n.dock[data-edge=\"top\"],\n.dock[data-edge=\"bottom\"] {\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n}\n.dock[data-edge$=\"-left\"] {\n left: max(12px, env(safe-area-inset-left));\n align-items: flex-start;\n}\n.dock[data-edge$=\"-right\"] { right: max(12px, env(safe-area-inset-right)); }\n.hud {\n max-width: 100%;\n padding: 6px 10px;\n border: 1px solid var(--line);\n border-radius: 10px;\n background: var(--bg);\n color: var(--fg);\n font-weight: 500;\n white-space: pre;\n text-align: left;\n overflow-x: auto;\n -webkit-user-select: none;\n user-select: none;\n touch-action: manipulation;\n /* No transition and no keyframe anywhere in this sheet: the readout must\n never be a moving thing on a screen whose motion is under test. */\n}\n.hud[hidden] { display: none; }\n.hud[data-alarm=\"true\"] { border-color: var(--bad); color: var(--bad); }\n.hud[data-blocked=\"true\"] { border-color: var(--warn); color: var(--warn); }\n/* The panel's toggle, in the opposite corner: same pill, same mark-and-chip,\n so the two controls read as one instrument rather than two. */\n.eye {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 0;\n padding: 6px 10px;\n border: 1px solid var(--line);\n border-radius: 999px;\n background: var(--bg);\n color: var(--fg);\n font: inherit;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n touch-action: manipulation;\n}\n.eye:hover { background: var(--bg-soft); }\n.mark { font-weight: 700; letter-spacing: 0.04em; }\n.state {\n padding: 0 6px;\n border-radius: 999px;\n background: var(--bg-soft);\n color: var(--fg-dim);\n}\n", on = (e) => Math.round(e * 10) / 10, sn = (e) => {
1555
1553
  if (!e) return "flemo no flight yet";
1556
1554
  let t = e.frameSamples?.released, n = e.anomalies?.length ?? 0;
1557
- return `${e.kind} ${Math.round(e.durationMs)}ms gap ${rn(t?.maxGapMs ?? 0)} drop ${t?.over30Count ?? 0}` + (n > 0 ? ` !${n}` : " ok") + (e.bucket ? ` [${e.bucket}]` : "");
1558
- }, on = (e, t) => {
1555
+ return `${e.kind} ${Math.round(e.durationMs)}ms gap ${on(t?.maxGapMs ?? 0)} drop ${t?.over30Count ?? 0}` + (n > 0 ? ` !${n}` : " ok") + (e.bucket ? ` [${e.bucket}]` : "");
1556
+ }, cn = (e, t) => {
1559
1557
  let n = [], r = (e?.preconditions ?? []).filter((e) => e.status === "violated");
1560
- if (r.length > 0 && n.push(`BLOCKED ${r.map((e) => e.id).join(" ")}`), !t) return n.push(`rAF ${rn(e?.environment?.rafCadence?.medianGapMs ?? 0)}ms`), n;
1558
+ if (r.length > 0 && n.push(`BLOCKED ${r.map((e) => e.id).join(" ")}`), !t) return n.push(`rAF ${on(e?.environment?.rafCadence?.medianGapMs ?? 0)}ms`), n;
1561
1559
  let i = t.frameSamples;
1562
- n.push(`frames n${i?.released?.count ?? 0} med ${rn(i?.released?.medianGapMs ?? 0)} max ${rn(i?.released?.maxGapMs ?? 0)}`), n.push(`motion stall ${rn(t.motion?.longestStallMs ?? 0)}ms tail ${t.motion?.tailFrames ?? 0} start +${t.motion?.firstAnimationAtMs ?? "?"}ms`), n.push(`hold ${t.holds?.kind ?? "none"} rel ${t.holds?.releasedAtMs ?? "-"}ms task ${t.longTasks?.length ?? 0}`);
1560
+ n.push(`frames n${i?.released?.count ?? 0} med ${on(i?.released?.medianGapMs ?? 0)} max ${on(i?.released?.maxGapMs ?? 0)}`), n.push(`motion stall ${on(t.motion?.longestStallMs ?? 0)}ms tail ${t.motion?.tailFrames ?? 0} start +${t.motion?.firstAnimationAtMs ?? "?"}ms`), n.push(`hold ${t.holds?.kind ?? "none"} rel ${t.holds?.releasedAtMs ?? "-"}ms task ${t.longTasks?.length ?? 0}`);
1563
1561
  let a = t.morphs;
1564
1562
  a && (a.pairable.length > 0 || a.flew.length > 0) && n.push(`morph ${a.flew.length} flew` + (a.camera ? " cam" : "") + (a.skipped.length > 0 ? ` SKIPPED ${a.skipped.length} (${a.skipped.join(",")})` : ""));
1565
1563
  let o = t.input;
1566
1564
  o && n.push(`input ${o.pointerTypes.join("/") || "none"}` + (o.synthetic > 0 ? ` SYNTHETIC ${o.synthetic}` : ""));
1567
1565
  for (let e of t.anomalies ?? []) n.push(`! ${e.slice(0, 120)}`);
1568
1566
  return n;
1569
- }, sn = null, cn = (e = {}) => {
1570
- if (sn) return sn;
1567
+ }, ln = () => {
1568
+ try {
1569
+ return sessionStorage.getItem(rn) === "1";
1570
+ } catch {
1571
+ return !1;
1572
+ }
1573
+ }, un = (e) => {
1574
+ try {
1575
+ sessionStorage.setItem(rn, e ? "1" : "0");
1576
+ } catch {}
1577
+ }, dn = null, fn = (e = {}) => {
1578
+ if (dn) return dn;
1571
1579
  if (typeof document > "u") return { detach: () => {} };
1572
- let { recorder: t, ownsRecorder: n } = Ot(e.recorder), r = e.buckets && e.buckets.length > 0 ? e.buckets : ["A", "B"], { host: i, root: a } = Et(nn), o = document.createElement("div");
1573
- o.className = "hud", o.setAttribute("data-edge", e.position ?? "top"), o.setAttribute("role", "status"), o.textContent = "flemo attaching", a.appendChild(o);
1574
- let s = !1, c = e.initialExpanded === !0, l = -1, u = 0, d = 0, f = !1, p = "", m = () => {
1580
+ let { recorder: t, ownsRecorder: n } = kt(e.recorder), r = e.buckets && e.buckets.length > 0 ? e.buckets : ["A", "B"], { host: i, root: a } = Dt(an);
1581
+ i.style.zIndex = "2147482998";
1582
+ let o = document.createElement("div");
1583
+ o.className = "dock", o.setAttribute("data-edge", e.position ?? "bottom-right");
1584
+ let s = document.createElement("div");
1585
+ s.className = "hud", s.setAttribute("role", "status"), s.textContent = "flemo attaching";
1586
+ let c = document.createElement("button");
1587
+ c.className = "eye", c.type = "button";
1588
+ let l = document.createElement("span");
1589
+ l.className = "mark", l.textContent = "hud";
1590
+ let u = document.createElement("span");
1591
+ u.className = "state", c.appendChild(l), c.appendChild(u), o.appendChild(s), o.appendChild(c), a.appendChild(o);
1592
+ let d = !1, f = e.initialExpanded === !0, p = e.initialHidden ?? ln(), m = -1, h = 0, g = 0, _ = !1, v = "", y = () => {
1575
1593
  try {
1576
1594
  return t.report();
1577
1595
  } catch {
1578
1596
  return null;
1579
1597
  }
1580
- }, h = () => {
1581
- if (s || Tt()) return;
1582
- let e = m(), t = e?.flights ?? [], n = t[t.length - 1], r = [an(n)];
1583
- c && r.push(...on(e, n));
1584
- let i = r.join("\n"), a = (e?.preconditions ?? []).some((e) => e.status === "violated"), l = (n?.anomalies?.length ?? 0) > 0;
1585
- i !== p && (p = i, o.textContent = i), o.setAttribute("data-alarm", l ? "true" : "false"), o.setAttribute("data-blocked", a ? "true" : "false");
1586
- }, g = () => {
1587
- u = 0, h(), u = window.setTimeout(g, en);
1588
- }, _ = () => {
1589
- l = l + 1 >= r.length ? -1 : l + 1, t.mark(l === -1 ? null : r[l]), p = "", h();
1598
+ }, b = () => {
1599
+ if (d || p || Tt()) return;
1600
+ let e = y(), t = e?.flights ?? [], n = t[t.length - 1], r = [sn(n)];
1601
+ f && r.push(...cn(e, n));
1602
+ let i = r.join("\n"), a = (e?.preconditions ?? []).some((e) => e.status === "violated"), o = (n?.anomalies?.length ?? 0) > 0;
1603
+ i !== v && (v = i, s.textContent = i), s.setAttribute("data-alarm", o ? "true" : "false"), s.setAttribute("data-blocked", a ? "true" : "false");
1604
+ }, x = () => {
1605
+ h = 0, b(), h = window.setTimeout(x, tn);
1606
+ }, S = (e) => {
1607
+ p = e, s.hidden = e, u.textContent = e ? "show" : "hide", c.setAttribute("data-hidden", e ? "true" : "false"), c.setAttribute("aria-label", e ? "show the flemo readout" : "hide the flemo readout"), c.setAttribute("aria-expanded", e ? "false" : "true"), window.clearTimeout(h), h = 0, !e && (v = "", b(), h = window.setTimeout(x, tn));
1608
+ }, C = () => {
1609
+ m = m + 1 >= r.length ? -1 : m + 1, t.mark(m === -1 ? null : r[m]), v = "", b();
1590
1610
  };
1591
- o.addEventListener("pointerdown", () => {
1592
- f = !1, window.clearTimeout(d), d = window.setTimeout(() => {
1593
- f = !0, _();
1594
- }, tn);
1595
- }), o.addEventListener("pointerup", () => {
1596
- window.clearTimeout(d), d = 0, !f && (c = !c, p = "", h());
1597
- }), o.addEventListener("pointercancel", () => window.clearTimeout(d));
1598
- let v = () => {
1599
- s || (s = !0, window.clearTimeout(u), u = 0, window.clearTimeout(d), d = 0, i.remove(), n && t.detach(), sn = null);
1611
+ s.addEventListener("pointerdown", () => {
1612
+ _ = !1, window.clearTimeout(g), g = window.setTimeout(() => {
1613
+ _ = !0, C();
1614
+ }, nn);
1615
+ }), s.addEventListener("pointerup", () => {
1616
+ window.clearTimeout(g), g = 0, !_ && (f = !f, v = "", b());
1617
+ }), s.addEventListener("pointercancel", () => window.clearTimeout(g)), c.addEventListener("click", () => {
1618
+ S(!p), un(p);
1619
+ });
1620
+ let w = () => {
1621
+ d || (d = !0, window.clearTimeout(h), h = 0, window.clearTimeout(g), g = 0, i.remove(), n && t.detach(), dn = null);
1600
1622
  };
1601
- document.body.appendChild(i), h(), u = window.setTimeout(g, en);
1602
- let y = { detach: v };
1603
- return sn = y, y;
1623
+ document.body.appendChild(i), S(p);
1624
+ let T = { detach: w };
1625
+ return dn = T, T;
1626
+ }, pn = 1200, mn = 2, hn = () => [...document.querySelectorAll(`[${d}]`)], gn = (e) => ve(getComputedStyle(e).transform) ?? 0, _n = (e) => {
1627
+ let t = [];
1628
+ for (let n of e) {
1629
+ let e = n;
1630
+ if (typeof e.getAnimations == "function") for (let n of e.getAnimations()) {
1631
+ let e = n, r = n.currentTime, i = typeof r == "number" ? Math.round(r) : 0;
1632
+ t.push(`${e.animationName ?? "waapi"}|${n.playState}|ct=${i}|rate=${n.playbackRate}`);
1633
+ }
1634
+ }
1635
+ return t;
1636
+ }, vn = (e) => e.length === 0 ? 0 : e.reduce((e, t) => e + t, 0) / e.length, yn = (e) => Math.round(e * 100) / 100, bn = (e) => {
1637
+ /* v8 ignore next -- SSR guard: there is nothing to watch without a document. */
1638
+ if (typeof document > "u") return { detach: () => {} };
1639
+ let t = e.now ?? (() => performance.now()), n = e.schedule ?? ((e) => {
1640
+ requestAnimationFrame(e);
1641
+ }), r = () => {
1642
+ let r = hn();
1643
+ if (r.length === 0) return;
1644
+ let i = Math.max(...r.map((e) => Math.abs(gn(e))));
1645
+ if (i < mn) return;
1646
+ let a = t(), o = [], s = () => {
1647
+ let r = hn();
1648
+ if (o.push({
1649
+ t: Math.round(t() - a),
1650
+ x: r.map((e) => yn(gn(e))),
1651
+ animations: _n(r)
1652
+ }), t() - a < 1200) {
1653
+ n(s);
1654
+ return;
1655
+ }
1656
+ let c = o[0].x, l = 0;
1657
+ for (let [e, t] of c.entries()) Math.abs(t) > Math.abs(c[l]) && (l = e);
1658
+ let u = o.map((e) => e.x[l] ?? 0), d = [];
1659
+ for (let e = 1; e < u.length; e += 1) {
1660
+ let t = Math.abs(u[e] - u[e - 1]);
1661
+ t > 0 && d.push(t);
1662
+ }
1663
+ let f = vn(d.slice(0, 3)), p = vn(d.slice(-3));
1664
+ e.onRelease({
1665
+ samples: o,
1666
+ travelAtReleasePx: yn(i),
1667
+ biggestStepPx: yn(Math.max(0, ...d)),
1668
+ openingStepPx: yn(f),
1669
+ closingStepPx: yn(p),
1670
+ eased: d.length > 3 && p < f * .5,
1671
+ teleported: Math.max(0, ...d) > i * .5
1672
+ });
1673
+ };
1674
+ n(s);
1675
+ }, i = ["pointerup", "pointercancel"];
1676
+ for (let e of i) document.addEventListener(e, r, {
1677
+ capture: !0,
1678
+ passive: !0
1679
+ });
1680
+ return { detach: () => {
1681
+ for (let e of i) document.removeEventListener(e, r, { capture: !0 });
1682
+ } };
1604
1683
  };
1605
1684
  //#endregion
1606
- export { c as BLIND_SPOTS, Fe as CORE_FLAGS, Pe as DEVTOOLS_OWNED_FLAGS, W as FLAG_REGISTRY, ge as JUDGING_PROTOCOL, e as LONG_GAP_MS, i as MID_FLIGHT_TASK_MS, n as OPENING_WINDOW_LEAD_MS, r as OPENING_WINDOW_TAIL_MS, U as PANEL_HEIGHT_KEY, mt as REPORT_SCHEMA_VERSION, G as RETIRED_FLAGS, Ie as RETIRED_MARKER, a as STALL_MS, t as STUCK_STATUS_MS, Ue as TRACE_KEY, cn as attachDevtoolsHud, $t as attachDevtoolsPanel, Ct as attachFlightRecorder, ne as captureEnvironment, ve as classifyDriver, Ke as clearTrace, _e as computeFrameStats, V as computePhaseStats, o as deriveFlightAnomalies, He as deriveOverrideWarnings, it as derivePreconditions, s as deriveReportAnomalies, pt as deriveVerdict, N as detectEngine, F as developmentHints, P as isEmulationSuspected, ye as kindFromStatus, qe as loadTrace, be as parseTranslateX, ee as sampleRafCadence, Ge as saveTrace, Ve as snapshotOverrides, u as summariseBuckets };
1685
+ export { c as BLIND_SPOTS, Pe as CORE_FLAGS, Ne as DEVTOOLS_OWNED_FLAGS, Fe as FLAG_REGISTRY, pe as JUDGING_PROTOCOL, e as LONG_GAP_MS, i as MID_FLIGHT_TASK_MS, n as OPENING_WINDOW_LEAD_MS, r as OPENING_WINDOW_TAIL_MS, Me as PANEL_HEIGHT_KEY, mt as REPORT_SCHEMA_VERSION, G as RETIRED_FLAGS, Ie as RETIRED_MARKER, a as STALL_MS, t as STUCK_STATUS_MS, pn as SWIPE_PROBE_MS, Ue as TRACE_KEY, fn as attachDevtoolsHud, en as attachDevtoolsPanel, Ct as attachFlightRecorder, bn as attachSwipeProbe, ne as captureEnvironment, ge as classifyDriver, Ke as clearTrace, he as computeFrameStats, me as computePhaseStats, o as deriveFlightAnomalies, He as deriveOverrideWarnings, it as derivePreconditions, s as deriveReportAnomalies, pt as deriveVerdict, N as detectEngine, F as developmentHints, P as isEmulationSuspected, _e as kindFromStatus, qe as loadTrace, ve as parseTranslateX, ee as sampleRafCadence, Ge as saveTrace, Ve as snapshotOverrides, u as summariseBuckets };