@flemo/devtools 0.7.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
- }, R = (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
- }, le = (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), R(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
- R(e, n);
223
+ z(e, n);
224
224
  }
225
- }, ue = (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
- }), z = 200, de = (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(de(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 >= z)) 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 >= z) 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, H = (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
- }, U = (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
- }, be = (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 = H(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: U(t)
345
+ orphanedHolds: W(t)
346
346
  };
347
- }, xe = E.map((e) => `[${b}="${e}"]`).join(","), Se = A(d), Ce = (e) => Math.round(e * 10) / 10, we = (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
- }, Te = (e) => {
350
+ }, we = (e) => {
351
351
  let t = e.getAttribute(b);
352
352
  return t !== null && E.includes(t);
353
- }, Ee = () => {
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
- }, De = (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: Ee()
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 = we(e);
373
+ let a = Ce(e);
374
374
  if (a === null) continue;
375
- if (Te(e)) {
375
+ if (we(e)) {
376
376
  t.flew.add(a);
377
377
  continue;
378
378
  }
379
- let o = e.closest(Se);
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
- }, Oe = (e, t) => {
393
- if (t.hasAttribute("data-flemo-morph-camera") && (e.camera = !0), !Te(t)) return;
394
- let n = we(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
- }, ke = (e, t, n) => {
397
- for (let r of Array.from(t.addedNodes)) if (r instanceof Element) for (let t of Ae(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 Ae(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
- }, Ae = (e) => [...e.hasAttribute("data-flemo-morph-ghost") ? [e] : [], ...Array.from(e.querySelectorAll(A(w)))], je = (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: Ce(t),
410
- detail: `a morph ghost was removed ${Ce(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
- }, Me = (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(xe).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, Ee() - 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
- }, Ne = "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: Ne,
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 = [], Ie = [...Fe, ...Pe], W = [
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",
@@ -572,53 +570,53 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
572
570
  storage: "session",
573
571
  retiredWith: "the Low Power Mode release-latency probe (2026-08-22)"
574
572
  }
575
- ], Le = "(retired — the library no longer reads this)", Re = (e) => {
573
+ ], Ie = "(retired — the library no longer reads this)", Le = (e) => {
576
574
  try {
577
575
  let t = e === "session" ? sessionStorage : localStorage;
578
576
  return t.length, t;
579
577
  } catch {
580
578
  return null;
581
579
  }
582
- }, ze = (e, t) => {
580
+ }, Re = (e, t) => {
583
581
  try {
584
582
  return e ? e.getItem(t) : null;
585
583
  } catch {
586
584
  return null;
587
585
  }
588
- }, Be = new Set(Ie.map((e) => e.key)), Ve = new Set(W.map((e) => e.key)), He = () => {
589
- let e = {}, t = Re("session"), n = Re("local");
590
- for (let r of Ie) {
591
- let i = ze(r.storage === "session" ? t : n, r.key);
586
+ }, ze = new Set(Fe.map((e) => e.key)), Be = new Set(G.map((e) => e.key)), Ve = () => {
587
+ let e = {}, t = Le("session"), n = Le("local");
588
+ for (let r of Fe) {
589
+ let i = Re(r.storage === "session" ? t : n, r.key);
592
590
  i !== null && (e[r.key] = i);
593
591
  }
594
- for (let r of W) for (let [i, a] of [[t, "sessionStorage"], [n, "localStorage"]]) {
595
- let t = ze(i, r.key);
596
- t !== null && (e[`${r.key} (${a}) ${Le}`] = t);
592
+ for (let r of G) for (let [i, a] of [[t, "sessionStorage"], [n, "localStorage"]]) {
593
+ let t = Re(i, r.key);
594
+ t !== null && (e[`${r.key} (${a}) ${Ie}`] = t);
597
595
  }
598
596
  for (let [r, i] of [[t, "sessionStorage"], [n, "localStorage"]]) if (r) try {
599
597
  for (let t = 0; t < r.length; t += 1) {
600
598
  let n = r.key(t);
601
- !n || !n.startsWith("flemo:") || Be.has(n) || Ve.has(n) || (e[`${n} (${i}, unknown key)`] = r.getItem(n) ?? "");
599
+ !n || !n.startsWith("flemo:") || ze.has(n) || Be.has(n) || (e[`${n} (${i}, unknown key)`] = r.getItem(n) ?? "");
602
600
  }
603
601
  } catch {}
604
602
  return e;
605
- }, Ue = (e) => {
603
+ }, He = (e) => {
606
604
  let t = [];
607
605
  for (let [n, r] of Object.entries(e)) if (n.includes("(retired — the library no longer reads this)")) {
608
- let e = n.slice(0, n.indexOf(" (")), i = W.find((t) => t.key === e);
606
+ let e = n.slice(0, n.indexOf(" (")), i = G.find((t) => t.key === e);
609
607
  t.push(`${n}=${r} — RETIRED residue: this key went with ${i?.retiredWith ?? "a removed feature"}. The library never reads it, so it cannot explain anything you are seeing. Safe to delete; it is listed only so it does not read as an unexplained lead.`);
610
608
  continue;
611
609
  }
612
610
  return t;
613
- }, We = "flemo:devtools-trace", Ge = () => {
611
+ }, Ue = "flemo:devtools-trace", We = () => {
614
612
  try {
615
613
  let e = sessionStorage;
616
614
  return e.length, e;
617
615
  } catch {
618
616
  return null;
619
617
  }
620
- }, Ke = (e, t) => {
621
- let n = Ge();
618
+ }, Ge = (e, t) => {
619
+ let n = We();
622
620
  if (!n) return;
623
621
  let r = e.slice(-10);
624
622
  for (; r.length > 0;) {
@@ -629,23 +627,23 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
629
627
  });
630
628
  if (e.length <= 64e3) {
631
629
  try {
632
- n.setItem(We, e);
630
+ n.setItem(Ue, e);
633
631
  } catch {}
634
632
  return;
635
633
  }
636
634
  r = r.slice(1);
637
635
  }
638
- qe();
639
- }, qe = () => {
636
+ Ke();
637
+ }, Ke = () => {
640
638
  try {
641
- Ge()?.removeItem(We);
639
+ We()?.removeItem(Ue);
642
640
  } catch {}
643
- }, Je = (e) => {
644
- let t = Ge();
641
+ }, qe = (e) => {
642
+ let t = We();
645
643
  if (!t) return null;
646
644
  let n = null;
647
645
  try {
648
- n = t.getItem(We);
646
+ n = t.getItem(Ue);
649
647
  } catch {
650
648
  return null;
651
649
  }
@@ -654,14 +652,14 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
654
652
  try {
655
653
  r = JSON.parse(n);
656
654
  } catch {
657
- return qe(), null;
655
+ return Ke(), null;
658
656
  }
659
- return !r || r.version !== e || !Array.isArray(r.flights) ? (qe(), null) : {
657
+ return !r || r.version !== e || !Array.isArray(r.flights) ? (Ke(), null) : {
660
658
  savedAt: typeof r.savedAt == "string" ? r.savedAt : "",
661
659
  flights: r.flights,
662
660
  note: "These flights were recorded by the page instance BEFORE the last full load. They are kept apart from the live ones because they may have come from a different build."
663
661
  };
664
- }, Ye = 12, Xe = 20, Ze = 40, Qe = 500, $e = 200, et = (e) => {
662
+ }, Je = 12, Ye = 20, Xe = 40, Ze = 500, Qe = 200, $e = (e) => {
665
663
  let t = e.rafCadence.medianGapMs;
666
664
  if (t === null) return {
667
665
  id: "display-cadence",
@@ -669,17 +667,17 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
669
667
  detail: "the idle frame cadence could not be sampled, so the display's rate is unknown"
670
668
  };
671
669
  let n = { medianIdleFrameMs: t };
672
- return t < Ye ? {
670
+ return t < Je ? {
673
671
  id: "display-cadence",
674
672
  status: "ok",
675
673
  detail: `idle frames arrive every ${t}ms — a display above 60Hz. Frame budgets in this report are still quoted against 60Hz (a gap of 30ms or more)`,
676
674
  metrics: n
677
- } : t <= Xe ? {
675
+ } : t <= Ye ? {
678
676
  id: "display-cadence",
679
677
  status: "ok",
680
678
  detail: `idle frames arrive every ${t}ms — a 60Hz clock`,
681
679
  metrics: n
682
- } : t <= Ze ? {
680
+ } : t <= Xe ? {
683
681
  id: "display-cadence",
684
682
  status: "violated",
685
683
  detail: `idle frames arrive every ${t}ms — the page is being served roughly HALF rate. On iOS this is Low Power Mode, whose main-thread ceiling is ~30Hz while the compositor keeps 60: motion judged here is judged against a clock no transition can beat, and the ceiling is not a library defect. Turn it off, or judge elsewhere`,
@@ -690,7 +688,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
690
688
  detail: `idle frames arrive every ${t}ms — the page is barely being served frames at all while idle. Something outside the transition owns this machine; no motion verdict taken here means anything`,
691
689
  metrics: n
692
690
  };
693
- }, tt = (e) => {
691
+ }, et = (e) => {
694
692
  if (!e.environment.observation.longTasks) return {
695
693
  id: "machine-idle",
696
694
  status: "unknown",
@@ -701,7 +699,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
701
699
  idleLongTaskMs: n,
702
700
  worstIdleTaskMs: r
703
701
  };
704
- return n >= Qe || r >= $e ? {
702
+ return n >= Ze || r >= Qe ? {
705
703
  id: "machine-idle",
706
704
  status: "violated",
707
705
  detail: `${t} long task(s) totalling ${n}ms ran while NO navigation was in flight (worst ${r}ms). Something else on this page or this machine was busy, and a motion verdict taken under someone else's load measures the load. A whole tremble campaign was invalidated by exactly this, with a build running in another window`,
@@ -712,7 +710,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
712
710
  detail: `${t} idle long task(s), ${n}ms total — the page was quiet between navigations`,
713
711
  metrics: i
714
712
  };
715
- }, nt = (e) => {
713
+ }, tt = (e) => {
716
714
  let { trusted: t, synthetic: n, pointerTypes: r } = e.input;
717
715
  return n > 0 ? {
718
716
  id: "real-input",
@@ -739,7 +737,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
739
737
  synthetic: n
740
738
  }
741
739
  };
742
- }, rt = (e) => e.input.pointerTypes.includes("touch") ? {
740
+ }, nt = (e) => e.input.pointerTypes.includes("touch") ? {
743
741
  id: "touch-path",
744
742
  status: "ok",
745
743
  detail: "at least one navigation was driven by touch"
@@ -751,7 +749,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
751
749
  id: "touch-path",
752
750
  status: "unknown",
753
751
  detail: "no touch-driven navigation was recorded on a touch-capable device. The swipe and pointer-capture paths are only reached by a finger; a build that had broken them outright once passed every automated layer green because every probe used a mouse"
754
- }, it = [
752
+ }, rt = [
755
753
  {
756
754
  id: "devtools-closed",
757
755
  status: "unknown",
@@ -767,7 +765,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
767
765
  status: "unknown",
768
766
  detail: "which physical display this window is on, its refresh rate and scaling, cannot be read from the page. Establish it with the user before believing any verdict"
769
767
  }
770
- ], at = (e) => {
768
+ ], it = (e) => {
771
769
  let { environment: t } = e, n = [];
772
770
  return n.push(t.emulationSuspected ? {
773
771
  id: "device-emulation",
@@ -777,7 +775,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
777
775
  id: "device-emulation",
778
776
  status: "ok",
779
777
  detail: "no device-emulation signature on this session"
780
- }), n.push(et(t)), n.push(e.documentHidden || e.wentHidden ? {
778
+ }), n.push($e(t)), n.push(e.documentHidden || e.wentHidden ? {
781
779
  id: "page-foreground",
782
780
  status: "violated",
783
781
  detail: e.documentHidden ? "this document is HIDDEN right now — a backgrounded page is throttled to a fraction of its frames" : "this document was hidden at least once while recording; any flight that ran then was throttled"
@@ -785,7 +783,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
785
783
  id: "page-foreground",
786
784
  status: "ok",
787
785
  detail: "the document stayed visible throughout"
788
- }), n.push(tt(e)), n.push(t.developmentHints.length > 0 ? {
786
+ }), n.push(et(e)), n.push(t.developmentHints.length > 0 ? {
789
787
  id: "build-mode",
790
788
  status: "violated",
791
789
  detail: `development-server globals are present (${t.developmentHints.join(", ")}). A development build is a different program: unminified, double-invoking, and hot-reload instrumented. A day of ladder measurements once turned out to be measuring the build itself`
@@ -793,7 +791,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
793
791
  id: "build-mode",
794
792
  status: "unknown",
795
793
  detail: "no development-server global was found. That is consistent with a production build but does not prove one — confirm how this page was built"
796
- }), n.push(nt(e)), n.push(rt(e)), n.push(t.reducedMotion ? {
794
+ }), n.push(tt(e)), n.push(nt(e)), n.push(t.reducedMotion ? {
797
795
  id: "reduced-motion",
798
796
  status: "violated",
799
797
  detail: "this session prefers reduced motion, so the transitions under test are being suppressed or shortened. Whatever is on screen is not the motion being judged"
@@ -801,8 +799,8 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
801
799
  id: "reduced-motion",
802
800
  status: "ok",
803
801
  detail: "reduced motion is not requested"
804
- }), [...n, ...it];
805
- }, ot = 2e3, st = 40, ct = (e) => Math.round(e * 10) / 10, lt = (e) => typeof e.animationName == "string" && e.animationName.startsWith("flemo-"), ut = (e) => e instanceof Element ? `<${e.tagName.toLowerCase()}>${e.getAttribute("data-flemo-screen") === null ? "" : " (screen)"}` : "an unidentified node", dt = (e) => {
802
+ }), [...n, ...rt];
803
+ }, at = 2e3, ot = 40, st = (e) => Math.round(e * 10) / 10, ct = (e) => typeof e.animationName == "string" && e.animationName.startsWith("flemo-"), lt = (e) => e instanceof Element ? `<${e.tagName.toLowerCase()}>${e.getAttribute("data-flemo-screen") === null ? "" : " (screen)"}` : "an unidentified node", ut = (e) => {
806
804
  if (typeof document > "u") return {
807
805
  detach: () => {},
808
806
  sawAnimationEvent: () => !1,
@@ -813,18 +811,18 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
813
811
  })
814
812
  };
815
813
  let t = [], n = !1, r = (t) => {
816
- lt(t) && (n = !0, e.onAnimationStart(performance.now()));
814
+ ct(t) && (n = !0, e.onAnimationStart(performance.now()));
817
815
  }, i = (t) => {
818
- lt(t) && (n = !0, e.onHit({
816
+ ct(t) && (n = !0, e.onHit({
819
817
  kind: "animation-cancel",
820
818
  atMs: performance.now(),
821
- detail: `${t.animationName} was CANCELLED on ${ut(t.target)} — the element was re-parented, re-styled or removed mid-flight. A cancelled animation loses its start time, and whatever restarts it is free to overwrite the authored delay`
819
+ detail: `${t.animationName} was CANCELLED on ${lt(t.target)} — the element was re-parented, re-styled or removed mid-flight. A cancelled animation loses its start time, and whatever restarts it is free to overwrite the authored delay`
822
820
  }));
823
821
  }, a = (t) => {
824
- lt(t) && (n = !0, t.elapsedTime === 0 && e.onHit({
822
+ ct(t) && (n = !0, t.elapsedTime === 0 && e.onHit({
825
823
  kind: "zero-length-animation-end",
826
824
  atMs: performance.now(),
827
- detail: `${t.animationName} reported animationend with elapsedTime 0 on ${ut(t.target)} — the animation ended without ever running. Anything landing on this event lands before the motion it was waiting for`
825
+ detail: `${t.animationName} reported animationend with elapsedTime 0 on ${lt(t.target)} — the animation ended without ever running. Anything landing on this event lands before the motion it was waiting for`
828
826
  }));
829
827
  }, o = (e) => {
830
828
  let n = e.pointerType ?? "";
@@ -832,7 +830,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
832
830
  atMs: performance.now(),
833
831
  trusted: e.isTrusted === !0,
834
832
  pointerType: n === "" ? e.type : n
835
- }), t.length > st && t.splice(0, t.length - st);
833
+ }), t.length > ot && t.splice(0, t.length - ot);
836
834
  }, s = {
837
835
  capture: !0,
838
836
  passive: !0
@@ -843,7 +841,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
843
841
  },
844
842
  sawAnimationEvent: () => n,
845
843
  inputBetween: (e, n) => {
846
- let r = e - ot, i = t.filter((e) => e.atMs >= r && e.atMs <= n), a = i.filter((e) => e.trusted).length, o = new Set(i.map((e) => e.pointerType));
844
+ let r = e - at, i = t.filter((e) => e.atMs >= r && e.atMs <= n), a = i.filter((e) => e.trusted).length, o = new Set(i.map((e) => e.pointerType));
847
845
  return {
848
846
  trusted: a,
849
847
  synthetic: i.length - a,
@@ -851,22 +849,22 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
851
849
  };
852
850
  }
853
851
  };
854
- }, ft = (e, t) => ({
852
+ }, dt = (e, t) => ({
855
853
  kind: e.kind,
856
- atMs: ct(e.atMs - t),
854
+ atMs: st(e.atMs - t),
857
855
  detail: e.detail
858
- }), pt = (e) => {
856
+ }), ft = (e) => {
859
857
  /* v8 ignore next -- unreachable: deriveVerdict returns before this on an
860
858
  empty flight list, so nothing ever asks for the median of nothing. */
861
859
  if (e.length === 0) return 0;
862
860
  let t = [...e].sort((e, t) => e - t);
863
861
  return t[Math.floor(t.length / 2)];
864
- }, mt = (e) => {
862
+ }, pt = (e) => {
865
863
  let t = [], n = e.preconditions.filter((e) => e.status === "violated");
866
864
  if (n.length > 0 && t.push(`NOT EVIDENCE: ${n.length} judging precondition(s) failed — ${n.map((e) => e.id).join(", ")}. Everything below was measured under those conditions; fix them and measure again before drawing a conclusion from it.`), e.flights.length === 0) return t.push("No flights were recorded. Either no navigation happened while the recorder was attached, or it attached after the one you meant to measure — the recorder only sees flights that start after it does."), t;
867
865
  e.observation.animationEvents || t.push("The animation channel observed NOTHING across this whole session: not one flemo keyframe reported a start, an end or a cancel, though flights were recorded. Treat every animation-derived field here as unmeasured rather than as clean — a probe that never fires reads exactly like a page with nothing to report.");
868
866
  let r = e.flights, i = r.reduce((e, t) => Math.max(e, t.frameSamples.released.maxGapMs), 0), a = r.filter((e) => e.anomalies.length > 0).length;
869
- t.push(`${r.length} flight(s) recorded. Median duration ${pt(r.map((e) => e.durationMs))}ms, worst frame gap during visible motion ${i}ms, ${a} flight(s) carrying at least one anomaly.`);
867
+ t.push(`${r.length} flight(s) recorded. Median duration ${ft(r.map((e) => e.durationMs))}ms, worst frame gap during visible motion ${i}ms, ${a} flight(s) carrying at least one anomaly.`);
870
868
  let o = r.filter((e) => e.motion.longestStallMs >= 48);
871
869
  o.length > 0 && t.push(`${o.length} flight(s) STOPPED MOVING mid-flight (longest ${Math.max(...o.map((e) => e.motion.longestStallMs))}ms). Frames kept arriving; the picture did not change. Look at the hold and the animation's play state, not at the frame budget.`);
872
870
  let s = r.filter((e) => e.morphs.skipped.length > 0);
@@ -882,7 +880,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
882
880
  t.push(`${l.length} tripwire hit(s) across the session (${e.join(", ")}). These are one-frame events reported by the browser itself, not sampled — read the flights' \`tripwires\` arrays for the exact animations.`);
883
881
  }
884
882
  return r.filter((e) => e.frameSamples.released.over30Count > 0).length === 0 && a === 0 && n.length === 0 && t.push("No flight dropped a frame during visible motion (nothing at or over 30ms) and no anomaly fired. Under the preconditions above, this session is clean — what remains is in `blindSpots`, and none of it is reachable from page code."), t;
885
- }, ht = "3", gt = new Set(O), _t = new Set(k), vt = A(d), yt = 2e3, bt = 1e3, xt = 4e3, G = (e) => Math.round(e * 10) / 10, St = null, Ct = () => ({
883
+ }, mt = "3", ht = new Set(O), gt = new Set(k), _t = A(d), vt = 2e3, yt = 1e3, bt = 4e3, K = (e) => Math.round(e * 10) / 10, xt = null, St = () => ({
886
884
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
887
885
  version: "3",
888
886
  verdict: ["No DOM was available, so nothing could be observed. The recorder ran inert."],
@@ -900,15 +898,15 @@ 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]
904
- }), wt = (e = {}) => {
905
- if (St) return St;
901
+ judgingProtocol: [...pe]
902
+ }), Ct = (e = {}) => {
903
+ if (xt) return xt;
906
904
  if (typeof window > "u" || typeof document > "u") return {
907
905
  detach: () => {},
908
- report: Ct,
906
+ report: St,
909
907
  mark: () => null
910
908
  };
911
- let n = e.maxFlights ?? 50, r = e.log ?? !1, i = e.installGlobal ?? !0, a = e.persist ?? !0, l = He(), d = performance.now(), h = a ? Je("3") : null, g = {
909
+ let n = e.maxFlights ?? 50, r = e.log ?? !1, i = e.installGlobal ?? !0, a = e.persist ?? !0, l = Ve(), d = performance.now(), h = a ? qe("3") : null, g = {
912
910
  medianGapMs: null,
913
911
  sampleCount: 0
914
912
  };
@@ -919,10 +917,10 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
919
917
  try {
920
918
  typeof PerformanceObserver < "u" && PerformanceObserver.supportedEntryTypes?.includes("longtask") && (S = new PerformanceObserver((e) => {
921
919
  for (let t of e.getEntries()) x.push({
922
- startMs: G(t.startTime),
923
- durationMs: G(t.duration)
920
+ startMs: K(t.startTime),
921
+ durationMs: K(t.duration)
924
922
  });
925
- x.length > bt && x.splice(0, x.length - bt);
923
+ x.length > yt && x.splice(0, x.length - yt);
926
924
  }), S.observe({
927
925
  type: "longtask",
928
926
  buffered: !0
@@ -930,50 +928,50 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
930
928
  } catch {
931
929
  S = null;
932
930
  }
933
- let C = [], w = 0, E = null, D = null, O = [], k = !1, j = !1, M = document.visibilityState === "hidden", N = 0, P = () => Array.from(document.querySelectorAll(vt)).filter((e) => gt.has(e.getAttribute("data-flemo-status") ?? "")), te = () => E !== null || P().length > 0, F = (e) => {
934
- let t = Array.from(document.querySelectorAll(A(y))).filter((e) => gt.has(e.getAttribute("data-flemo-bar-status") ?? "") || e.getAttribute("data-flemo-bar-riding") === "true").length, n = Array.from(document.querySelectorAll(A(v))).filter((e) => gt.has(e.getAttribute("data-flemo-status") ?? "")).length, r = Array.from(document.querySelectorAll(A(_))).filter((e) => gt.has(e.getAttribute("data-flemo-status") ?? "")).length;
931
+ let C = [], w = 0, E = null, D = null, O = [], k = !1, j = !1, M = document.visibilityState === "hidden", N = 0, P = () => Array.from(document.querySelectorAll(_t)).filter((e) => ht.has(e.getAttribute("data-flemo-status") ?? "")), te = () => E !== null || P().length > 0, F = (e) => {
932
+ let t = Array.from(document.querySelectorAll(A(y))).filter((e) => ht.has(e.getAttribute("data-flemo-bar-status") ?? "") || e.getAttribute("data-flemo-bar-riding") === "true").length, n = Array.from(document.querySelectorAll(A(v))).filter((e) => ht.has(e.getAttribute("data-flemo-status") ?? "")).length, r = Array.from(document.querySelectorAll(A(_))).filter((e) => ht.has(e.getAttribute("data-flemo-status") ?? "")).length;
935
933
  return {
936
934
  screens: e.length,
937
935
  bars: t,
938
936
  decorators: n,
939
937
  parts: r
940
938
  };
941
- }, I = dt({
939
+ }, I = ut({
942
940
  onHit: (e) => {
943
941
  let t = E;
944
- t && t.tripwires.push(ft(e, t.t0Ms));
942
+ t && t.tripwires.push(dt(e, t.t0Ms));
945
943
  },
946
944
  onAnimationStart: (e) => {
947
945
  let t = E;
948
- !t || t.firstAnimationAtMs !== null || (t.firstAnimationAtMs = G(e - t.t0Ms));
946
+ !t || t.firstAnimationAtMs !== null || (t.firstAnimationAtMs = K(e - t.t0Ms));
949
947
  }
950
948
  }), re = (e) => {
951
949
  let t = /* @__PURE__ */ new Set();
952
950
  for (let n of e.elements) {
953
951
  let e = n.getAttribute("data-flemo-status") ?? "";
954
- gt.has(e) && t.add(e);
952
+ ht.has(e) && t.add(e);
955
953
  }
956
954
  return [...t];
957
955
  }, L = () => {
958
956
  let e = E;
959
957
  if (!e || k) return;
960
958
  let t = performance.now(), n = e.frames;
961
- if (n.lastFrameAt !== null && n.heldGaps.length + n.releasedGaps.length < yt) {
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, le(n, e.elements), t - e.t0Ms > 1e4) {
966
- O = [...e.elements], de(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
- if (e !== null && _t.has(e)) {
974
+ if (e !== null && gt.has(e)) {
977
975
  i = e;
978
976
  break;
979
977
  }
@@ -991,61 +989,61 @@ 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: De(e),
992
+ images: le(e),
993
+ morphs: Ee(e),
996
994
  tripwires: [],
997
995
  rafId: null
998
- }, le(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 = be(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
- }, R = (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 = Me(t.morphs, te());
1015
+ e.morphs = je(t.morphs, te());
1018
1016
  }
1019
1017
  };
1020
1018
  requestAnimationFrame(r);
1021
- }, z = (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 },
1025
1023
  kind: e.kind,
1026
1024
  t0: {
1027
- ms: G(e.t0Ms),
1025
+ ms: K(e.t0Ms),
1028
1026
  iso: e.t0Iso
1029
1027
  },
1030
1028
  t1: {
1031
- ms: G(t),
1029
+ ms: K(t),
1032
1030
  iso: (/* @__PURE__ */ new Date()).toISOString()
1033
1031
  },
1034
- durationMs: G(t - e.t0Ms),
1035
- driver: ve(e.frames.evidence),
1032
+ durationMs: K(t - e.t0Ms),
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
- ...ue(e.frames),
1041
+ ...ce(e.frames),
1044
1042
  firstAnimationAtMs: e.firstAnimationAtMs
1045
1043
  },
1046
- images: he(e.images),
1047
- morphs: Me(e.morphs, !0),
1048
- tripwires: [...e.tripwires, ...je(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,29 +1054,29 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1056
1054
  orphanedHolds: []
1057
1055
  },
1058
1056
  anomalies: []
1059
- }), de = (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 = z(i, e, t, !1);
1067
- C.push(a), C.length > n && C.splice(0, C.length - n), t.length === 0 && (se(a, i.elements), R(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);
1072
- if (n !== null && _t.has(n) && t.holdKind === null && (t.holdKind = n), n !== null && _t.has(n) && t.holdReleasedAtMs !== null && t.frames.holdReassertedAtMs === null) {
1073
- let e = G(performance.now() - t.t0Ms);
1070
+ if (n !== null && gt.has(n) && t.holdKind === null && (t.holdKind = n), n !== null && gt.has(n) && t.holdReleasedAtMs !== null && t.frames.holdReassertedAtMs === null) {
1071
+ let e = K(performance.now() - t.t0Ms);
1074
1072
  t.frames.holdReassertedAtMs = e, t.tripwires.push({
1075
1073
  kind: "hold-reassert",
1076
1074
  atMs: e,
1077
1075
  detail: "an animation hold was re-asserted after this flight had already released it — the motion pauses here while every timing metric stays clean"
1078
1076
  });
1079
1077
  }
1080
- (n === "false" || n === null) && e.oldValue !== null && _t.has(e.oldValue) && t.holdReleasedAtMs === null && !oe(t.elements) && (t.holdReleasedAtMs = G(performance.now() - t.t0Ms));
1081
- }, V = () => {
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));
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
- de(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
- }, H = null, U = null, xe = () => {
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 && Oe(E.morphs, n.target) : (E && ke(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 H = t, V(), !0;
1120
+ return ve = t, me(), !0;
1123
1121
  };
1124
- if (!xe()) {
1122
+ if (!be()) {
1125
1123
  let e = () => {
1126
- U = null, k || xe();
1124
+ W = null, k || be();
1127
1125
  };
1128
- U = e, document.addEventListener("DOMContentLoaded", e, { once: !0 });
1126
+ W = e, document.addEventListener("DOMContentLoaded", e, { once: !0 });
1129
1127
  }
1130
- let Se = () => {
1131
- document.visibilityState === "hidden" && (M = !0, a && E === null && Ke(C, "3"));
1128
+ let xe = () => {
1129
+ document.visibilityState === "hidden" && (M = !0, a && E === null && Ge(C, "3"));
1132
1130
  };
1133
- document.addEventListener("visibilitychange", Se);
1134
- let Ce = () => {
1135
- N = 0, !k && (E === null && Ke(C, "3"), N = window.setTimeout(Ce, xt));
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(Ce, xt));
1138
- let we = (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
- }, Te = (e) => x.filter((t) => t.startMs >= d && !e.some((e) => t.startMs + t.durationMs >= e.t0.ms && t.startMs <= e.t1.ms)), Ee = (e) => {
1145
- let t = we(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
- }, Ae = () => {
1173
- let e = C.map(Ee), 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, Ee(z(n, r, i ? re(n) : [], !0))];
1177
- }, Ne = (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,21 +1183,21 @@ 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 = () => {
1189
- let e = He(), t = { ...e };
1186
+ }, Ne = () => {
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 = Ue(t), r = ne(g, I.sawAnimationEvent()), i = Ae(), a = E, o = at({
1189
+ let n = He(t), r = ne(g, I.sawAnimationEvent()), i = ke(), a = E, o = it({
1192
1190
  environment: r,
1193
- idleLongTasks: Te(i),
1191
+ idleLongTasks: we(i),
1194
1192
  observedMs: performance.now() - d,
1195
1193
  wentHidden: M,
1196
1194
  documentHidden: document.visibilityState === "hidden",
1197
- input: Ne(i)
1195
+ input: Me(i)
1198
1196
  });
1199
1197
  return {
1200
1198
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1201
1199
  version: "3",
1202
- verdict: mt({
1200
+ verdict: pt({
1203
1201
  preconditions: o,
1204
1202
  flights: i,
1205
1203
  observation: r.observation
@@ -1220,37 +1218,37 @@ 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), Ie = () => {
1223
+ }, Pe = (e) => (D = e === null || e === "" ? null : e, D), Fe = () => {
1226
1224
  if (!k) {
1227
- if (k = !0, H?.disconnect(), U !== null && (document.removeEventListener("DOMContentLoaded", U), U = null), document.removeEventListener("visibilitychange", Se), 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
- St = null;
1229
+ xt = null;
1232
1230
  }
1233
- }, W = {
1234
- detach: Ie,
1235
- report: Pe,
1236
- mark: Fe
1231
+ }, G = {
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: Ae,
1244
- mark: Fe,
1245
- detach: Ie
1240
+ report: Ne,
1241
+ flights: ke,
1242
+ mark: Pe,
1243
+ detach: Fe
1246
1244
  }, j = !0);
1247
1245
  }
1248
- return St = W, W;
1249
- }, Tt = O.map((e) => A(d) + j(f, e)).join(","), Et = () => document.querySelector(Tt) !== null, Dt = (e) => {
1246
+ return xt = G, G;
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,
@@ -1270,10 +1268,10 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1270
1268
  },
1271
1269
  ownsRecorder: !1
1272
1270
  } : {
1273
- recorder: wt(),
1271
+ recorder: Ct(),
1274
1272
  ownsRecorder: !0
1275
1273
  };
1276
- }, At = "http://www.w3.org/2000/svg", K = (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
1277
  }, jt = (e, t) => {
@@ -1284,13 +1282,13 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1284
1282
  for (; e.firstChild !== null;) e.removeChild(e.firstChild);
1285
1283
  }, Nt = (e, t) => {
1286
1284
  e.textContent !== t && (e.textContent = t);
1287
- }, q = (e) => e == null || e === "" ? "—" : String(e), J = (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` : "—", Y = (e) => typeof e == "number" && Number.isFinite(e) ? String(e) : "—", Ft = (e) => e === !0 ? "yes" : e === !1 ? "no" : "—", It = (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)}` : "—";
1291
1289
  return [
1292
- q(t.engine),
1293
- `dpr ${q(t.devicePixelRatio)}`,
1290
+ J(t.engine),
1291
+ `dpr ${J(t.devicePixelRatio)}`,
1294
1292
  r,
1295
1293
  `rAF ${Pt(t.rafCadence?.medianGapMs)}`
1296
1294
  ].join(" · ");
@@ -1299,43 +1297,43 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
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
- }, zt = "\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", Bt = 48, X = (e, t, n, r) => {
1303
- let i = K("div", "kv");
1304
- i.appendChild(K("span", "k", t)), i.appendChild(K("span", r ? `v ${r}` : "v", n)), e.appendChild(i);
1305
- }, Z = (e, t) => {
1306
- let n = K("section", "section");
1307
- return n.appendChild(K("h2", void 0, t)), e.appendChild(n), n;
1308
- }, Q = (e, t, n = "li") => {
1309
- e.appendChild(K("div", n, t));
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) => {
1301
+ let i = q("div", "kv");
1302
+ i.appendChild(q("span", "k", t)), i.appendChild(q("span", r ? `v ${r}` : "v", n)), e.appendChild(i);
1303
+ }, Q = (e, t) => {
1304
+ let n = q("section", "section");
1305
+ return n.appendChild(q("h2", void 0, t)), e.appendChild(n), n;
1306
+ }, $ = (e, t, n = "li") => {
1307
+ e.appendChild(q("div", n, t));
1310
1308
  }, Vt = (e, t) => {
1311
1309
  Mt(e);
1312
- for (let n of t?.verdict ?? []) e.appendChild(K("span", "chip lead", q(n)));
1313
- for (let n of t?.preconditions ?? []) n?.status === "violated" && e.appendChild(K("span", "chip bad", `${n.id}: ${q(n.detail)}`));
1314
- for (let n of t?.overrides?.warnings ?? []) e.appendChild(K("span", "chip warn", q(n)));
1315
- for (let n of t?.anomalies ?? []) e.appendChild(K("span", "chip bad", q(n)));
1316
- for (let [n, r] of Object.entries(t?.overrides?.active ?? {})) e.appendChild(K("span", "chip", `${n}=${String(r)}`));
1310
+ for (let n of t?.verdict ?? []) e.appendChild(q("span", "chip lead", J(n)));
1311
+ for (let n of t?.preconditions ?? []) n?.status === "violated" && e.appendChild(q("span", "chip bad", `${n.id}: ${J(n.detail)}`));
1312
+ for (let n of t?.overrides?.warnings ?? []) e.appendChild(q("span", "chip warn", J(n)));
1313
+ for (let n of t?.anomalies ?? []) e.appendChild(q("span", "chip bad", J(n)));
1314
+ for (let [n, r] of Object.entries(t?.overrides?.active ?? {})) e.appendChild(q("span", "chip", `${n}=${String(r)}`));
1317
1315
  }, Ht = (e, t, n, r) => {
1318
1316
  if (Mt(e), t.length === 0) {
1319
- Q(e, "no flights recorded yet — navigate once", "li dim");
1317
+ $(e, "no flights recorded yet — navigate once", "li dim");
1320
1318
  return;
1321
1319
  }
1322
1320
  for (let i = t.length - 1; i >= 0; --i) {
1323
- let a = t[i], o = q(a?.id), s = K("button", "row");
1324
- s.type = "button", s.setAttribute("data-flight-id", o), s.setAttribute("aria-selected", String(o === n)), s.appendChild(K("span", "kind", q(a?.kind))), s.appendChild(K("span", "driver", q(a?.driver))), s.appendChild(K("span", "dur", J(a?.durationMs))), s.appendChild(K("span", "screens", `${Y(a?.participants?.screens)} scr`));
1321
+ let a = t[i], o = J(a?.id), s = q("button", "row");
1322
+ s.type = "button", s.setAttribute("data-flight-id", o), s.setAttribute("aria-selected", String(o === n)), s.appendChild(q("span", "kind", J(a?.kind))), s.appendChild(q("span", "driver", J(a?.driver))), s.appendChild(q("span", "dur", Y(a?.durationMs))), s.appendChild(q("span", "screens", `${X(a?.participants?.screens)} scr`));
1325
1323
  let c = a?.anomalies?.length ?? 0;
1326
- s.appendChild(K("span", c > 0 ? "n bad" : "n", String(c))), s.addEventListener("click", () => r(o)), e.appendChild(s);
1324
+ s.appendChild(q("span", c > 0 ? "n bad" : "n", String(c))), s.addEventListener("click", () => r(o)), e.appendChild(s);
1327
1325
  }
1328
1326
  }, Ut = (e, t, n) => {
1329
1327
  if (!n) {
1330
- X(e, t, "—");
1328
+ Z(e, t, "—");
1331
1329
  return;
1332
1330
  }
1333
1331
  let r = [
1334
- `${Y(n.count)} frames`,
1332
+ `${X(n.count)} frames`,
1335
1333
  `median ${Pt(n.medianGapMs)}`,
1336
1334
  `max ${Pt(n.maxGapMs)}`
1337
1335
  ];
1338
- typeof n.over30Count == "number" && r.push(`>30ms ×${n.over30Count}`), X(e, t, r.join(" · "));
1336
+ typeof n.over30Count == "number" && r.push(`>30ms ×${n.over30Count}`), Z(e, t, r.join(" · "));
1339
1337
  }, Wt = (e) => {
1340
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",
@@ -1353,96 +1351,96 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1353
1351
  }, Gt = (e, t) => {
1354
1352
  let n = t.longTasks ?? [], r = t.holdLongTasks ?? [];
1355
1353
  if (n.length === 0 && r.length === 0) {
1356
- Q(e, "none", "li dim");
1354
+ $(e, "none", "li dim");
1357
1355
  return;
1358
1356
  }
1359
- let i = (e) => `${J(e?.startMs)} + ${J(e?.durationMs)}`;
1360
- for (let t of n) Q(e, i(t), "li bad");
1361
- for (let t of r) Q(e, `${i(t)} (absorbed by hold)`, "li dim");
1357
+ let i = (e) => `${Y(e?.startMs)} + ${Y(e?.durationMs)}`;
1358
+ for (let t of n) $(e, i(t), "li bad");
1359
+ for (let t of r) $(e, `${i(t)} (absorbed by hold)`, "li dim");
1362
1360
  }, Kt = (e, t) => {
1363
1361
  if (Mt(e), !t) {
1364
- Q(e, "select a flight", "li dim");
1362
+ $(e, "select a flight", "li dim");
1365
1363
  return;
1366
1364
  }
1367
- let n = Z(e, "timing");
1368
- X(n, "id", q(t.id)), X(n, "kind / driver", `${q(t.kind)} · ${q(t.driver)}`), X(n, "router", q(t.routerId)), X(n, "t0", q(t.t0?.iso)), X(n, "duration", J(t.durationMs)), X(n, "participants", `${Y(t.participants?.screens)} screens · ${Y(t.participants?.bars)} bars · ${Y(t.participants?.decorators)} decorators · ${Y(t.participants?.parts)} parts`), X(n, "hold", `${q(t.holds?.kind)} · released ${J(t.holds?.releasedAtMs)}`);
1369
- let r = Z(e, "frames");
1365
+ let n = Q(e, "timing");
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)}`);
1367
+ let r = Q(e, "frames");
1370
1368
  Ut(r, "held (absorbed)", t.frameSamples?.held), Ut(r, "released (visible)", t.frameSamples?.released);
1371
1369
  let i = Rt(t.frameSamples);
1372
1370
  i && r.appendChild(Wt(i));
1373
- let a = Z(e, "motion (did it move)"), o = t.motion?.longestStallMs, s = t.motion?.holdReassertedAtMs;
1374
- X(a, "released frames", Y(t.motion?.sampledFrames)), X(a, "stalled frames", Y(t.motion?.stalledFrames), (t.motion?.stalledFrames ?? 0) > 0 ? "bad" : void 0), X(a, "longest stall", J(o), (o ?? 0) >= Bt ? "bad" : void 0), X(a, "paused after release", Ft(t.motion?.pausedAfterRelease), t.motion?.pausedAfterRelease === !0 ? "bad" : void 0), X(a, "hold re-asserted", s == null ? "no" : J(s), typeof s == "number" ? "bad" : void 0), X(a, "first animation", t.motion?.firstAnimationAtMs === null || t.motion?.firstAnimationAtMs === void 0 ? "not observed" : `+${J(t.motion.firstAnimationAtMs)} after t0`);
1371
+ let a = Q(e, "motion (did it move)"), o = t.motion?.longestStallMs, s = t.motion?.holdReassertedAtMs;
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
- let t = Z(e, "shared elements");
1378
- X(t, "registered", Y(c.registered)), X(t, "pairable / flew", `${Y(c.pairable?.length)} · ${Y(c.flew?.length)}`);
1375
+ let t = Q(e, "shared elements");
1376
+ Z(t, "registered", X(c.registered)), Z(t, "pairable / flew", `${X(c.pairable?.length)} · ${X(c.flew?.length)}`);
1379
1377
  let n = c.skipped ?? [];
1380
- X(t, "did not fly", n.length === 0 ? "none" : n.join(", "), n.length > 0 ? "bad" : void 0);
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 && X(t, "duplicate keys in one screen", r.join(", "), "bad"), X(t, "camera", Ft(c.camera)), X(t, "ghosts", Y(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
- X(t, "residue at rest", i === 0 ? "clean" : `${Y(c.strandedRoles)} roles · ${Y(c.strandedStandIns)} stand-ins · ${Y(c.strandedGhosts)} ghosts · ${Y(c.layerResidue)} in layer · ${Y(c.leakedSheetRules)} rules`, i > 0 ? "bad" : void 0);
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
  }
1386
1384
  let l = t.tripwires ?? [];
1387
1385
  if (l.length > 0) {
1388
- let t = Z(e, "tripwires (one-frame events)");
1389
- for (let e of l) Q(t, `+${J(e.atMs)} ${e.kind}: ${e.detail}`, "li bad");
1386
+ let t = Q(e, "tripwires (one-frame events)");
1387
+ for (let e of l) $(t, `+${Y(e.atMs)} ${e.kind}: ${e.detail}`, "li bad");
1390
1388
  }
1391
1389
  let u = t.input;
1392
1390
  if (u) {
1393
- let t = Z(e, "what drove it");
1394
- X(t, "input", `${Y(u.trusted)} trusted · ${Y(u.synthetic)} synthetic`, u.synthetic > 0 ? "bad" : void 0), X(t, "pointer types", u.pointerTypes?.join(", ") || "none observed");
1391
+ let t = Q(e, "what drove it");
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
- let d = Z(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
- X(d, "loading at t0", Y(t.images?.loadingAtStart)), X(d, "added mid-flight", Y(t.images?.addedDuringFlight)), X(d, "completed mid-flight", Y(t.images?.completedDuringFlight), h ? "bad" : void 0), X(d, "held by the engine", Y(t.images?.heldDuringFlight)), X(d, "completed without hold", Y(m), h ? "bad" : void 0), Gt(Z(e, "long tasks"), t);
1398
- let g = Z(e, "landing"), _ = t.landing?.residualInlineTransforms ?? [];
1399
- if (_.length === 0) X(g, "inline residue", "clean");
1400
- else for (let e of _) X(g, "inline residue", q(e));
1401
- X(g, "off-viewport at rest", Ft(t.landing?.offViewportAtRest));
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;
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);
1396
+ let g = Q(e, "landing"), _ = t.landing?.residualInlineTransforms ?? [];
1397
+ if (_.length === 0) Z(g, "inline residue", "clean");
1398
+ else for (let e of _) Z(g, "inline residue", J(e));
1399
+ Z(g, "off-viewport at rest", Ft(t.landing?.offViewportAtRest));
1402
1400
  let v = t.landing?.stuckStatuses ?? [];
1403
- X(g, "stuck statuses", v.length === 0 ? "none" : v.join(", "));
1401
+ Z(g, "stuck statuses", v.length === 0 ? "none" : v.join(", "));
1404
1402
  let y = t.landing?.orphanedHolds ?? [];
1405
- if (y.length === 0) X(g, "orphaned holds", "none");
1406
- else for (let e of y) X(g, "orphaned holds", q(e), "bad");
1407
- let b = Z(e, "anomalies"), x = t.anomalies ?? [];
1403
+ if (y.length === 0) Z(g, "orphaned holds", "none");
1404
+ else for (let e of y) Z(g, "orphaned holds", J(e), "bad");
1405
+ let b = Q(e, "anomalies"), x = t.anomalies ?? [];
1408
1406
  if (x.length === 0) {
1409
- Q(b, "none", "li dim");
1407
+ $(b, "none", "li dim");
1410
1408
  return;
1411
1409
  }
1412
- for (let e of x) Q(b, q(e), "li bad");
1410
+ for (let e of x) $(b, J(e), "li bad");
1413
1411
  }, qt = (e, t) => {
1414
1412
  Mt(e);
1415
- for (let n of t ?? []) Q(e, q(n));
1413
+ for (let n of t ?? []) $(e, J(n));
1416
1414
  }, Jt = 320, Yt = 2e3, Xt = 120, Zt = "Copy report JSON", Qt = () => {}, $t = null, en = (e = {}) => {
1417
1415
  if ($t) return $t;
1418
1416
  if (typeof document > "u") return { detach: Qt };
1419
- let { recorder: t, ownsRecorder: n } = kt(e.recorder), { host: r, root: i } = Dt(zt), a = K("button", "toggle");
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
- let o = K("span", "count", "0"), s = K("span", "dot");
1422
- s.hidden = !0, a.appendChild(K("span", "mark", "flemo")), a.appendChild(o), a.appendChild(s);
1423
- let c = K("section", "panel");
1419
+ let o = q("span", "count", "0"), s = q("span", "dot");
1420
+ s.hidden = !0, a.appendChild(q("span", "mark", "flemo")), a.appendChild(o), a.appendChild(s);
1421
+ let c = q("section", "panel");
1424
1422
  c.hidden = !0;
1425
- let l = K("div", "grip");
1423
+ let l = q("div", "grip");
1426
1424
  l.setAttribute("role", "separator"), l.setAttribute("aria-label", "Resize flemo devtools panel");
1427
- let u = K("header", "head"), d = K("div", "env", "—"), f = K("button", "act", Zt);
1425
+ let u = q("header", "head"), d = q("div", "env", "—"), f = q("button", "act", Zt);
1428
1426
  f.type = "button";
1429
- let p = K("button", "act", "Close");
1427
+ let p = q("button", "act", "Close");
1430
1428
  p.type = "button";
1431
- let m = K("button", "act", "Detach");
1429
+ let m = q("button", "act", "Detach");
1432
1430
  m.type = "button";
1433
- let h = K("button", "act", "A/B: off");
1431
+ let h = q("button", "act", "A/B: off");
1434
1432
  h.type = "button";
1435
- let g = K("div", "chips");
1436
- u.appendChild(d), u.appendChild(K("div", "spacer")), u.appendChild(h), u.appendChild(f), u.appendChild(p), u.appendChild(m), u.appendChild(g);
1437
- let _ = K("div", "body"), v = K("div", "list"), y = K("div", "detail");
1433
+ let g = q("div", "chips");
1434
+ u.appendChild(d), u.appendChild(q("div", "spacer")), u.appendChild(h), u.appendChild(f), u.appendChild(p), u.appendChild(m), u.appendChild(g);
1435
+ let _ = q("div", "body"), v = q("div", "list"), y = q("div", "detail");
1438
1436
  _.appendChild(v), _.appendChild(y);
1439
- let b = K("div", "foot"), x = K("details");
1440
- x.appendChild(K("summary", void 0, "What this cannot see"));
1441
- let S = K("div");
1437
+ let b = q("div", "foot"), x = q("details");
1438
+ x.appendChild(q("summary", void 0, "What this cannot see"));
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
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(Ne);
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(Ne, 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`;
@@ -1481,7 +1479,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1481
1479
  l !== D && (D = l, Kt(y, a)), k || (k = !0, qt(S, e?.blindSpots));
1482
1480
  };
1483
1481
  function L() {
1484
- C || Et() || re();
1482
+ C || Tt() || re();
1485
1483
  }
1486
1484
  function ie() {
1487
1485
  A = 0, L(), ae();
@@ -1491,117 +1489,141 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
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", () => de()), 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
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
- if (Et()) {
1505
- window.clearTimeout(j), j = window.setTimeout(ce, Jt);
1502
+ if (Tt()) {
1503
+ window.clearTimeout(j), j = window.setTimeout(se, Jt);
1506
1504
  return;
1507
1505
  }
1508
- Nt(f, "Copied ✓"), window.clearTimeout(j), j = window.setTimeout(R, 1200);
1506
+ Nt(f, "Copied ✓"), window.clearTimeout(j), j = window.setTimeout(z, 1200);
1509
1507
  }
1510
1508
  };
1511
- function R() {
1512
- if (Et()) {
1513
- j = window.setTimeout(R, Jt);
1509
+ function z() {
1510
+ if (Tt()) {
1511
+ j = window.setTimeout(z, Jt);
1514
1512
  return;
1515
1513
  }
1516
1514
  j = 0, Nt(f, Zt);
1517
1515
  }
1518
- let le = (e) => {
1516
+ let B = (e) => {
1519
1517
  if (C) return;
1520
- if (Et()) {
1521
- window.clearTimeout(j), j = window.setTimeout(() => le(e), Jt);
1518
+ if (Tt()) {
1519
+ window.clearTimeout(j), j = window.setTimeout(() => B(e), Jt);
1522
1520
  return;
1523
1521
  }
1524
- let t = K("textarea");
1522
+ let t = q("textarea");
1525
1523
  t.value = e, t.setAttribute("aria-hidden", "true"), t.style.position = "fixed", t.style.opacity = "0", t.style.pointerEvents = "none", document.body.appendChild(t), t.select();
1526
1524
  let n = document;
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, () => le(e));
1533
+ t.writeText(e).then(se, () => B(e));
1536
1534
  return;
1537
1535
  }
1538
- le(e);
1536
+ B(e);
1539
1537
  });
1540
- let ue = (e) => {
1538
+ let ce = (e) => {
1541
1539
  F = P(window.innerHeight - e.clientY), c.style.height = `${Math.round(F)}px`;
1542
- }, z = () => {
1543
- window.removeEventListener("pointermove", ue), window.removeEventListener("pointerup", z), 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", ue), window.addEventListener("pointerup", z);
1544
+ e.preventDefault(), window.addEventListener("pointermove", ce), window.addEventListener("pointerup", V);
1547
1545
  });
1548
- function de() {
1549
- C || (C = !0, window.clearTimeout(A), A = 0, window.clearTimeout(j), j = 0, window.removeEventListener("pointermove", ue), window.removeEventListener("pointerup", z), r.remove(), n && t.detach(), $t = 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: de };
1553
- return $t = fe, fe;
1554
- }, tn = 500, nn = 450, rn = "\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", an = (e) => Math.round(e * 10) / 10, on = (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 ${an(t?.maxGapMs ?? 0)} drop ${t?.over30Count ?? 0}` + (n > 0 ? ` !${n}` : " ok") + (e.bucket ? ` [${e.bucket}]` : "");
1558
- }, sn = (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 ${an(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 ${an(i?.released?.medianGapMs ?? 0)} max ${an(i?.released?.maxGapMs ?? 0)}`), n.push(`motion stall ${an(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
- }, cn = null, ln = (e = {}) => {
1570
- if (cn) return cn;
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 } = kt(e.recorder), r = e.buckets && e.buckets.length > 0 ? e.buckets : ["A", "B"], { host: i, root: a } = Dt(rn), 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 || Et()) return;
1582
- let e = m(), t = e?.flights ?? [], n = t[t.length - 1], r = [on(n)];
1583
- c && r.push(...sn(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, tn);
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, _();
1611
+ s.addEventListener("pointerdown", () => {
1612
+ _ = !1, window.clearTimeout(g), g = window.setTimeout(() => {
1613
+ _ = !0, C();
1594
1614
  }, nn);
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(), cn = null);
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, tn);
1602
- let y = { detach: v };
1603
- return cn = y, y;
1604
- }, un = 1200, dn = 2, fn = () => [...document.querySelectorAll(`[${d}]`)], pn = (e) => H(getComputedStyle(e).transform) ?? 0, mn = (e) => {
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) => {
1605
1627
  let t = [];
1606
1628
  for (let n of e) {
1607
1629
  let e = n;
@@ -1611,22 +1633,22 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1611
1633
  }
1612
1634
  }
1613
1635
  return t;
1614
- }, hn = (e) => e.length === 0 ? 0 : e.reduce((e, t) => e + t, 0) / e.length, $ = (e) => Math.round(e * 100) / 100, gn = (e) => {
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) => {
1615
1637
  /* v8 ignore next -- SSR guard: there is nothing to watch without a document. */
1616
1638
  if (typeof document > "u") return { detach: () => {} };
1617
1639
  let t = e.now ?? (() => performance.now()), n = e.schedule ?? ((e) => {
1618
1640
  requestAnimationFrame(e);
1619
1641
  }), r = () => {
1620
- let r = fn();
1642
+ let r = hn();
1621
1643
  if (r.length === 0) return;
1622
- let i = Math.max(...r.map((e) => Math.abs(pn(e))));
1623
- if (i < dn) return;
1644
+ let i = Math.max(...r.map((e) => Math.abs(gn(e))));
1645
+ if (i < mn) return;
1624
1646
  let a = t(), o = [], s = () => {
1625
- let r = fn();
1647
+ let r = hn();
1626
1648
  if (o.push({
1627
1649
  t: Math.round(t() - a),
1628
- x: r.map((e) => $(pn(e))),
1629
- animations: mn(r)
1650
+ x: r.map((e) => yn(gn(e))),
1651
+ animations: _n(r)
1630
1652
  }), t() - a < 1200) {
1631
1653
  n(s);
1632
1654
  return;
@@ -1638,13 +1660,13 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1638
1660
  let t = Math.abs(u[e] - u[e - 1]);
1639
1661
  t > 0 && d.push(t);
1640
1662
  }
1641
- let f = hn(d.slice(0, 3)), p = hn(d.slice(-3));
1663
+ let f = vn(d.slice(0, 3)), p = vn(d.slice(-3));
1642
1664
  e.onRelease({
1643
1665
  samples: o,
1644
- travelAtReleasePx: $(i),
1645
- biggestStepPx: $(Math.max(0, ...d)),
1646
- openingStepPx: $(f),
1647
- closingStepPx: $(p),
1666
+ travelAtReleasePx: yn(i),
1667
+ biggestStepPx: yn(Math.max(0, ...d)),
1668
+ openingStepPx: yn(f),
1669
+ closingStepPx: yn(p),
1648
1670
  eased: d.length > 3 && p < f * .5,
1649
1671
  teleported: Math.max(0, ...d) > i * .5
1650
1672
  });
@@ -1660,4 +1682,4 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = 48, o = (e) => {
1660
1682
  } };
1661
1683
  };
1662
1684
  //#endregion
1663
- export { c as BLIND_SPOTS, Fe as CORE_FLAGS, Pe as DEVTOOLS_OWNED_FLAGS, Ie 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, Ne as PANEL_HEIGHT_KEY, ht as REPORT_SCHEMA_VERSION, W as RETIRED_FLAGS, Le as RETIRED_MARKER, a as STALL_MS, t as STUCK_STATUS_MS, un as SWIPE_PROBE_MS, We as TRACE_KEY, ln as attachDevtoolsHud, en as attachDevtoolsPanel, wt as attachFlightRecorder, gn as attachSwipeProbe, ne as captureEnvironment, ve as classifyDriver, qe as clearTrace, _e as computeFrameStats, V as computePhaseStats, o as deriveFlightAnomalies, Ue as deriveOverrideWarnings, at as derivePreconditions, s as deriveReportAnomalies, mt as deriveVerdict, N as detectEngine, F as developmentHints, P as isEmulationSuspected, ye as kindFromStatus, Je as loadTrace, H as parseTranslateX, ee as sampleRafCadence, Ke as saveTrace, He 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 };