@flemo/devtools 0.2.2 → 0.4.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
@@ -11,7 +11,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
11
11
  return d.holdReassertedAtMs !== null && n.push(`hold re-asserted ${d.holdReassertedAtMs}ms into the flight, after it had already released (an interleaved commit wrote the stale paused hold attribute over a running flight — the flemo 2026-08-18 release-race signature; the motion pauses while every timing metric stays clean)`), d.pausedAfterRelease && n.push("compiled animation reported playState=paused after its release (the flight was posed and then stopped mid-motion, not merely starved of frames)"), d.longestStallMs >= 48 && n.push(`motion stalled ${d.longestStallMs}ms mid-flight (${d.stalledFrames}/${d.sampledFrames} released frames advanced neither the animation clock nor the pose — freeze, or freeze-then-leap if the flight still landed on time)`), d.sampledFrames === 0 && e.releasedAtMs !== null && n.push("no released frames were sampled (the flight ended at or before its own hold release — the visible motion, if any, was never observed)"), f.completedUnheld > 0 && n.push(`${f.completedUnheld} image(s) finished loading mid-flight without a hold (${f.completedDuringFlight} completed, ${f.heldDuringFlight} held; ${f.loadingAtStart} were loading at t0, ${f.addedDuringFlight} arrived mid-flight) — each decode rasters on the moving layer and costs a present; this is the warm-side image-hold regression`), l.orphanedHolds.length > 0 && n.push(`hold markers left on the page at rest: ${l.orphanedHolds.join("; ")} (whatever they hide has no owner left to reveal it — the permanently-blank-avatar class)`), l.residualInlineTransforms.length > 0 && n.push(`residual inline style after COMPLETED: ${l.residualInlineTransforms.join("; ")} (landing cleanup failure — the landed scope belongs to the compiled rest rules)`), l.offViewportAtRest && n.push("screen resting at from-pose while COMPLETED+active (blank-viewport signature — the flemo PR #259 class: a residual pose left the landed screen parked off-viewport)"), l.stuckStatuses.length > 0 && n.push(`transitional status stuck >${t / 1e3}s: ${l.stuckStatuses.join(", ")} (navigation queue lock or missed animationend — later navigations will be swallowed)`), i === "unknown" && n.push("driver could not be classified (no running flemo-* CSSAnimation and no player inline-style signature observed — zero-duration flight, or the sampler attached after motion ended)"), n;
12
12
  }, o = (e) => {
13
13
  let n = [];
14
- if (e.forcePin !== null && n.push(`active force pin flemo:motion-driver-force=${e.forcePin} — every transition this session is pinned to one driver (A/B residue? pins expire after 24h; clear the key before judging behavior)`), e.clearedForcePin !== null && e.forcePin === null && n.push(`force pin flemo:motion-driver-force=${e.clearedForcePin} was present at attach and has since been cleared (the library strips malformed/expired pins on sight) — early driver decisions in this session may still have been shaped by it`), e.legacyLocalForcePin !== null && n.push(`legacy localStorage driver pin present (flemo:motion-driver-force=${e.legacyLocalForcePin}) — never honored, but it marks A/B residue on this profile`), e.emulationSuspected) {
14
+ if (e.emulationSuspected) {
15
15
  let t = /Win/i.test(e.platform) ? " (Windows touch hardware makes this signal ambiguous — confirm the DevTools device toolbar state)" : "";
16
16
  n.push("DevTools device emulation suspected — the page composites to a rescaled surface, so visual reports from this session are untrustworthy; judge motion in a plain window or on a real device" + t);
17
17
  }
@@ -21,24 +21,33 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
21
21
  "Display-hardware effects: local dimming, backlight modulation, and panel overdrive alter perceived motion and are invisible to every web API.",
22
22
  "Compositor-internal present skips: a frame can be produced on time (clean rAF, clean player gaps) yet dropped or delayed inside the compositor's present queue; only platform tools (about:tracing, Instruments) see that layer.",
23
23
  "DevTools device emulation composites the page to a rescaled surface: every in-page instrument reads the pre-scale surface and reports clean while the eye watches the post-scale one, so emulated sessions grow shimmer/flash artifacts that do not exist in a plain window or on a real device."
24
- ], c = () => {
24
+ ], c = "data-flemo-screen", l = "data-flemo-status", u = "data-flemo-active", d = "data-flemo-anim-hold", f = "data-flemo-img-hold", p = "data-flemo-held-arrival", m = "data-flemo-part-name", h = "data-flemo-decorator", g = "data-flemo-bar", _ = "data-flemo-devtools-panel", v = [
25
+ "PUSHING",
26
+ "POPPING",
27
+ "REPLACING"
28
+ ], y = [
29
+ "true",
30
+ "park",
31
+ "park-under",
32
+ "park-over"
33
+ ], b = (e) => `[${e}]`, ee = (e, t) => `[${e}="${t}"]`, x = () => {
25
34
  if (typeof navigator > "u") return null;
26
35
  let e = navigator.userAgentData;
27
36
  return !e || !Array.isArray(e.brands) ? null : e.brands.map((e) => ({
28
37
  brand: String(e.brand ?? ""),
29
38
  version: String(e.version ?? "")
30
39
  }));
31
- }, l = () => {
40
+ }, S = () => {
32
41
  if (typeof navigator > "u") return "unknown";
33
- let e = c();
42
+ let e = x();
34
43
  if (e?.some((e) => /Chromium/i.test(e.brand))) return "blink";
35
44
  let t = navigator.userAgent ?? "";
36
45
  return /Firefox|FxiOS/i.test(t) ? "gecko" : e || /AppleWebKit/i.test(t) && !/Chrome|Chromium|Android/i.test(t) ? "webkit" : /Android/i.test(t) ? "blink" : "unknown";
37
- }, u = () => {
38
- if (typeof navigator > "u" || l() !== "blink") return !1;
46
+ }, C = () => {
47
+ if (typeof navigator > "u" || S() !== "blink") return !1;
39
48
  let e = navigator.platform ?? "";
40
49
  return /Mac|Win|Linux/i.test(e) ? /Android/i.test(navigator.userAgent ?? "") && !/Mac|Win/i.test(e) ? /Linux (x86_64|i686)/i.test(e) : (navigator.maxTouchPoints ?? 0) > 0 : !1;
41
- }, d = (e = 20) => new Promise((t) => {
50
+ }, te = (e = 20) => new Promise((t) => {
42
51
  let n = Number.isFinite(e) ? Math.max(1, Math.floor(e)) : 20;
43
52
  if (typeof requestAnimationFrame != "function" || typeof performance > "u") {
44
53
  t({
@@ -60,13 +69,13 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
60
69
  requestAnimationFrame(a);
61
70
  };
62
71
  requestAnimationFrame(a);
63
- }), f = () => {
72
+ }), w = () => {
64
73
  try {
65
74
  return typeof PerformanceObserver < "u" && Array.isArray(PerformanceObserver.supportedEntryTypes) && PerformanceObserver.supportedEntryTypes.includes("longtask");
66
75
  } catch {
67
76
  return !1;
68
77
  }
69
- }, p = (e) => {
78
+ }, T = (e) => {
70
79
  let t = typeof navigator < "u" ? navigator : null, n = typeof window < "u" ? window : null, r = !1;
71
80
  try {
72
81
  r = n?.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? !1;
@@ -75,8 +84,8 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
75
84
  }
76
85
  return {
77
86
  userAgent: t?.userAgent ?? "",
78
- uaBrands: c(),
79
- engine: l(),
87
+ uaBrands: x(),
88
+ engine: S(),
80
89
  platform: t?.platform ?? "",
81
90
  maxTouchPoints: t?.maxTouchPoints ?? 0,
82
91
  devicePixelRatio: n?.devicePixelRatio ?? 1,
@@ -91,169 +100,192 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
91
100
  visualViewportScale: n?.visualViewport?.scale ?? null,
92
101
  rafCadence: e,
93
102
  reducedMotion: r,
94
- emulationSuspected: u(),
103
+ emulationSuspected: C(),
95
104
  observation: {
96
- longTasks: f(),
105
+ longTasks: w(),
97
106
  elementAnimations: typeof Element < "u" && typeof Element.prototype.getAnimations == "function",
98
107
  playerGapMirror: Array.isArray(n?.__flemoPlayerGaps)
99
108
  }
100
109
  };
101
- }, m = [
110
+ }, E = [
102
111
  "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.",
103
112
  "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.",
104
113
  "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.",
105
114
  "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."
106
- ], h = [
115
+ ], D = "flemo:devtools-panel-height", O = [{
116
+ key: "flemo:devtools",
117
+ storage: "session",
118
+ kind: "opt-in-diagnostic",
119
+ values: "\"on\" / \"off\"",
120
+ fallback: "off",
121
+ effect: "arms this flight recorder in the playground (?devtools=on)"
122
+ }, {
123
+ key: D,
124
+ storage: "session",
125
+ kind: "production-state",
126
+ values: "a pixel height",
127
+ fallback: "(the panel's default height)",
128
+ effect: "the drawer height this panel was last dragged to"
129
+ }], k = [], A = [...k, ...O], j = [
107
130
  {
108
- key: "flemo:motion-driver",
109
- storage: "local",
110
- kind: "production-state",
111
- description: "learned driver ledger ('css' = player demoted on this device, 'raf' = clean probe)"
131
+ key: "flemo:sixty",
132
+ storage: "session",
133
+ retiredWith: "the steady-60 verdict seed, now document-scoped module state (2026-08-31)"
112
134
  },
113
135
  {
114
- key: "flemo:motion-driver-force",
136
+ key: "flemo:settle-gate",
115
137
  storage: "session",
116
- kind: "opt-in-diagnostic",
117
- description: "hard driver pin ('css@<epoch-ms>' / 'raf@<epoch-ms>', 24h TTL) — pins EVERY transition"
138
+ retiredWith: "the engine diagnostic surface (2026-08-31)"
118
139
  },
119
140
  {
120
- key: "flemo:sixty",
141
+ key: "flemo:arrivalhold",
121
142
  storage: "session",
122
- kind: "production-state",
123
- description: "steady-60 display verdict seed ('high' latches, a count seeds the streak)"
143
+ retiredWith: "the engine diagnostic surface (2026-08-31)"
124
144
  },
125
145
  {
126
- key: "flemo:lat",
146
+ key: "flemo:deskflip",
127
147
  storage: "session",
128
- kind: "production-state",
129
- description: "LPM release-latency seed (learned)"
148
+ retiredWith: "the engine diagnostic surface (2026-08-31)"
130
149
  },
131
150
  {
132
- key: "flemo:landing-snap",
151
+ key: "flemo:deskhead",
133
152
  storage: "session",
134
- kind: "opt-in-diagnostic",
135
- description: "Blink landing pixel-snap easing A/B"
153
+ retiredWith: "the engine diagnostic surface (2026-08-31)"
136
154
  },
137
155
  {
138
- key: "flemo:imghold",
156
+ key: "flemo:creep",
139
157
  storage: "session",
140
- kind: "opt-in-diagnostic",
141
- description: "flight-scoped <img> reveal hold"
158
+ retiredWith: "the engine diagnostic surface (2026-08-31)"
142
159
  },
143
160
  {
144
- key: "flemo:settle-gate",
161
+ key: "flemo:relcommit",
145
162
  storage: "session",
146
- kind: "production-default-with-override",
147
- description: "render-settle entry gate override"
163
+ retiredWith: "the engine diagnostic surface (2026-08-31)"
148
164
  },
149
165
  {
150
- key: "flemo:handoff",
166
+ key: "flemo:imgoffload",
151
167
  storage: "session",
152
- kind: "opt-in-diagnostic",
153
- description: "anchored-opening handoff (POP-scoped)"
168
+ retiredWith: "the engine diagnostic surface (2026-08-31)"
154
169
  },
155
170
  {
156
- key: "flemo:handoffms",
171
+ key: "flemo:governed",
157
172
  storage: "session",
158
- kind: "opt-in-diagnostic",
159
- description: "handoff point override (ms)"
173
+ retiredWith: "the engine diagnostic surface (2026-08-31)"
160
174
  },
161
175
  {
162
- key: "flemo:apply",
176
+ key: "flemo:imghold",
163
177
  storage: "session",
164
- kind: "opt-in-diagnostic",
165
- description: "force the scrub-WAAPI value-application tier"
178
+ retiredWith: "the image reveal hold, whose only arming path it was (2026-08-31)"
166
179
  },
167
180
  {
168
- key: "flemo:snap",
181
+ key: "flemo:preraster",
169
182
  storage: "session",
170
- kind: "production-default-with-override",
171
- description: "player device-pixel snap policy override"
183
+ retiredWith: "the REST-time scope promotion, whose only arming path it was (2026-08-31)"
172
184
  },
173
185
  {
174
- key: "flemo:snapband",
186
+ key: "flemo:parkhead",
175
187
  storage: "session",
176
- kind: "opt-in-diagnostic",
177
- description: "'hybrid' snap jitter-band width (device px)"
188
+ retiredWith: "the engine diagnostic surface — the park head is unconditional (2026-08-31)"
178
189
  },
179
190
  {
180
191
  key: "flemo:layers",
181
192
  storage: "session",
182
- kind: "opt-in-diagnostic",
183
- description: "resident screen layers at rest"
193
+ retiredWith: "the resident-layer experiment (2026-08-31)"
194
+ },
195
+ {
196
+ key: "flemo:morph",
197
+ storage: "session",
198
+ retiredWith: "the morph decision trace (2026-08-31)"
184
199
  },
185
200
  {
186
201
  key: "flemo:freeze",
187
202
  storage: "session",
188
- kind: "opt-in-diagnostic",
189
- description: "keep the direct prev screen live"
203
+ retiredWith: "the shallow-freeze experiment (2026-08-31)"
190
204
  },
191
205
  {
192
- key: "flemo:preraster",
206
+ key: "flemo:motion-driver",
207
+ storage: "local",
208
+ retiredWith: "the per-origin driver demotion ledger (2026-08-19)"
209
+ },
210
+ {
211
+ key: "flemo:motion-driver-force",
193
212
  storage: "session",
194
- kind: "opt-in-diagnostic",
195
- description: "promote the entering content layer through the hold"
213
+ retiredWith: "the hard driver pin, with the rAF player (2026-08-22)"
196
214
  },
197
215
  {
198
- key: "flemo:imgoffload",
216
+ key: "flemo:landing-snap",
199
217
  storage: "session",
200
- kind: "production-default-with-override",
201
- description: "image decode offloader override"
218
+ retiredWith: "the integer-device-pixel landing snap, falsified on device (2026-08-22)"
202
219
  },
203
220
  {
204
- key: "flemo:devtools",
221
+ key: "flemo:handoff",
222
+ storage: "session",
223
+ retiredWith: "the player's anchored-opening handoff (2026-08-22)"
224
+ },
225
+ {
226
+ key: "flemo:handoffms",
205
227
  storage: "session",
206
- kind: "opt-in-diagnostic",
207
- description: "arms this flight recorder in the playground (?devtools=on)"
228
+ retiredWith: "the player's anchored-opening handoff (2026-08-22)"
229
+ },
230
+ {
231
+ key: "flemo:apply",
232
+ storage: "session",
233
+ retiredWith: "the scrub-WAAPI value-application tier (2026-08-22)"
234
+ },
235
+ {
236
+ key: "flemo:snap",
237
+ storage: "session",
238
+ retiredWith: "the player's device-pixel snap policy (2026-08-22)"
239
+ },
240
+ {
241
+ key: "flemo:snapband",
242
+ storage: "session",
243
+ retiredWith: "the player's device-pixel snap policy (2026-08-22)"
244
+ },
245
+ {
246
+ key: "flemo:lat",
247
+ storage: "session",
248
+ retiredWith: "the Low Power Mode release-latency probe (2026-08-22)"
208
249
  }
209
- ], g = "flemo:motion-driver-force", _ = `${g} (localStorage legacy location)`, v = (e) => {
250
+ ], M = "(retired the library no longer reads this)", N = (e) => {
210
251
  try {
211
252
  let t = e === "session" ? sessionStorage : localStorage;
212
253
  return t.length, t;
213
254
  } catch {
214
255
  return null;
215
256
  }
216
- }, y = (e, t) => {
257
+ }, P = (e, t) => {
217
258
  try {
218
259
  return e ? e.getItem(t) : null;
219
260
  } catch {
220
261
  return null;
221
262
  }
222
- }, b = new Set(h.map((e) => e.key)), x = () => {
223
- let e = {}, t = v("session"), n = v("local");
224
- for (let r of h) {
225
- let i = y(r.storage === "session" ? t : n, r.key);
263
+ }, ne = new Set(A.map((e) => e.key)), re = new Set(j.map((e) => e.key)), F = () => {
264
+ let e = {}, t = N("session"), n = N("local");
265
+ for (let r of A) {
266
+ let i = P(r.storage === "session" ? t : n, r.key);
226
267
  i !== null && (e[r.key] = i);
227
268
  }
228
- let r = y(n, g);
229
- r !== null && (e[_] = r);
269
+ for (let r of j) for (let [i, a] of [[t, "sessionStorage"], [n, "localStorage"]]) {
270
+ let t = P(i, r.key);
271
+ t !== null && (e[`${r.key} (${a}) ${M}`] = t);
272
+ }
230
273
  for (let [r, i] of [[t, "sessionStorage"], [n, "localStorage"]]) if (r) try {
231
274
  for (let t = 0; t < r.length; t += 1) {
232
275
  let n = r.key(t);
233
- !n || !n.startsWith("flemo:") || b.has(n) || (e[`${n} (${i}, unknown key)`] = r.getItem(n) ?? "");
276
+ !n || !n.startsWith("flemo:") || ne.has(n) || re.has(n) || (e[`${n} (${i}, unknown key)`] = r.getItem(n) ?? "");
234
277
  }
235
278
  } catch {}
236
279
  return e;
237
- }, S = (e) => {
280
+ }, I = (e) => {
238
281
  let t = [];
239
- for (let [n, r] of Object.entries(e)) {
240
- if (n === g) {
241
- t.push(`${n}=${r} — A DRIVER PIN IS ACTIVE: every transition this session is forced onto one driver, bypassing measurement and demotion. If you did not set it deliberately just now, it is A/B residue (mobile tab restoration resurrects sessionStorage across days; pins expire after 24h). This exact residue once burned a multi-day investigation — clear the key before judging any behavior.`);
242
- continue;
243
- }
244
- if (n === _) {
245
- t.push(`${n}=${r} — legacy localStorage driver pin present. The library removes it on sight and never honors it, but its existence means an old A/B session left residue on this profile.`);
246
- continue;
247
- }
248
- if (n.startsWith(`${g} `)) {
249
- t.push(`${n}=${r} — a driver force pin was observed this session (see marker in the key). Even a since-cleared pin may have shaped early driver decisions; treat this session's routing as suspect.`);
250
- continue;
251
- }
252
- let e = h.find((e) => n === e.key || n.startsWith(`${e.key} `));
253
- !e || e.key === "flemo:devtools" || (e.kind === "opt-in-diagnostic" ? t.push(`${n}=${r} — opt-in diagnostic active (${e.description}); behavior differs from stock. Possible left-over A/B toggle from an earlier debugging session.`) : e.kind === "production-default-with-override" && t.push(`${n}=${r} — production default overridden for this session (${e.description}).`));
282
+ for (let [n, r] of Object.entries(e)) if (n.includes("(retired — the library no longer reads this)")) {
283
+ let e = n.slice(0, n.indexOf(" (")), i = j.find((t) => t.key === e);
284
+ 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.`);
285
+ continue;
254
286
  }
255
287
  return t;
256
- }, C = (e) => Math.round(e * 10) / 10, w = (e) => {
288
+ }, L = (e) => Math.round(e * 10) / 10, R = (e) => {
257
289
  if (e.length === 0) return {
258
290
  count: 0,
259
291
  medianGapMs: 0,
@@ -263,11 +295,11 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
263
295
  let t = [...e].sort((e, t) => e - t);
264
296
  return {
265
297
  count: e.length,
266
- medianGapMs: C(t[Math.floor(t.length / 2)]),
267
- maxGapMs: C(t[t.length - 1]),
298
+ medianGapMs: L(t[Math.floor(t.length / 2)]),
299
+ maxGapMs: L(t[t.length - 1]),
268
300
  over30Count: e.filter((e) => e >= 30).length
269
301
  };
270
- }, T = (e, t = []) => {
302
+ }, ie = (e, t = []) => {
271
303
  let n = [...e, ...t];
272
304
  return {
273
305
  ...n.length === 0 ? {
@@ -278,21 +310,21 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
278
310
  let e = [...n].sort((e, t) => e - t);
279
311
  return {
280
312
  count: n.length,
281
- medianGapMs: C(e[Math.floor(e.length / 2)]),
282
- maxGapMs: C(e[e.length - 1])
313
+ medianGapMs: L(e[Math.floor(e.length / 2)]),
314
+ maxGapMs: L(e[e.length - 1])
283
315
  };
284
316
  })(),
285
- longGaps: n.filter((e) => e >= 30).map(C),
286
- held: w(e),
287
- released: w(t)
317
+ longGaps: n.filter((e) => e >= 30).map(L),
318
+ held: R(e),
319
+ released: R(t)
288
320
  };
289
- }, E = (e) => e.length === 0 ? null : {
290
- maxMs: C(Math.max(...e)),
321
+ }, z = (e) => e.length === 0 ? null : {
322
+ maxMs: L(Math.max(...e)),
291
323
  over30Count: e.filter((e) => e >= 30).length
292
- }, D = (e) => {
324
+ }, ae = (e) => {
293
325
  let t = e.playerSuppression || e.playerAdvance;
294
326
  return t && e.compiledAnimation ? "mixed" : t ? "player" : e.compiledAnimation ? "compiled" : "unknown";
295
- }, O = (e) => e === "PUSHING" ? "PUSH" : e === "POPPING" ? "POP" : e === "REPLACING" ? "REPLACE" : null, ee = (e) => {
327
+ }, oe = (e) => e === "PUSHING" ? "PUSH" : e === "POPPING" ? "POP" : e === "REPLACING" ? "REPLACE" : null, se = (e) => {
296
328
  let t = /^matrix3d\(([^)]+)\)$/.exec(e.trim());
297
329
  if (t) {
298
330
  let e = t[1].split(",").map((e) => Number(e.trim()));
@@ -304,23 +336,14 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
304
336
  return e.length === 6 && Number.isFinite(e[4]) ? e[4] : null;
305
337
  }
306
338
  return null;
307
- }, k = "2", A = /* @__PURE__ */ new Set([
308
- "PUSHING",
309
- "POPPING",
310
- "REPLACING"
311
- ]), j = /* @__PURE__ */ new Set([
312
- "true",
313
- "park",
314
- "park-under",
315
- "park-over"
316
- ]), M = "[data-flemo-screen]", N = "data-flemo-status", te = "data-flemo-active", P = "data-flemo-anim-hold", F = 2, I = 2e3, L = "data-flemo-img-hold", ne = "data-flemo-held-arrival", re = 2, R = 200, ie = 1e3, z = (e) => Math.round(e * 10) / 10, B = null, V = () => window, ae = (e = {}) => {
317
- if (B) return B;
339
+ }, ce = "2", B = new Set(v), V = new Set(y), le = b(c), H = d, ue = 2, de = 2e3, fe = 2, pe = 200, me = 1e3, U = (e) => Math.round(e * 10) / 10, he = null, ge = () => window, _e = (e = {}) => {
340
+ if (he) return he;
318
341
  if (typeof window > "u" || typeof document > "u") return {
319
342
  detach: () => {},
320
343
  report: () => ({
321
344
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
322
345
  version: "2",
323
- environment: p({
346
+ environment: T({
324
347
  medianGapMs: null,
325
348
  sampleCount: 0
326
349
  }),
@@ -328,51 +351,47 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
328
351
  active: {},
329
352
  warnings: ["no DOM available — recorder ran inert"]
330
353
  },
331
- driverPolicy: {
332
- demotion: null,
333
- forcePin: null
334
- },
335
354
  flights: [],
336
355
  anomalies: [],
337
356
  blindSpots: [...s],
338
- judgingProtocol: [...m]
357
+ judgingProtocol: [...E]
339
358
  })
340
359
  };
341
- let n = e.maxFlights ?? 50, r = e.log ?? !1, i = e.installGlobal ?? !0, c = x(), l = {
360
+ let n = e.maxFlights ?? 50, r = e.log ?? !1, i = e.installGlobal ?? !0, c = F(), d = {
342
361
  medianGapMs: null,
343
362
  sampleCount: 0
344
363
  };
345
- d().then((e) => {
346
- l = e;
364
+ te().then((e) => {
365
+ d = e;
347
366
  });
348
- let u = [], f = null;
367
+ let _ = [], v = null;
349
368
  try {
350
- typeof PerformanceObserver < "u" && PerformanceObserver.supportedEntryTypes?.includes("longtask") && (f = new PerformanceObserver((e) => {
351
- for (let t of e.getEntries()) u.push({
352
- startMs: z(t.startTime),
353
- durationMs: z(t.duration)
369
+ typeof PerformanceObserver < "u" && PerformanceObserver.supportedEntryTypes?.includes("longtask") && (v = new PerformanceObserver((e) => {
370
+ for (let t of e.getEntries()) _.push({
371
+ startMs: U(t.startTime),
372
+ durationMs: U(t.duration)
354
373
  });
355
- u.length > ie && u.splice(0, u.length - ie);
356
- }), f.observe({
374
+ _.length > me && _.splice(0, _.length - me);
375
+ }), v.observe({
357
376
  type: "longtask",
358
377
  buffered: !0
359
378
  }));
360
379
  } catch {
361
- f = null;
380
+ v = null;
362
381
  }
363
- let h = [], g = 0, v = null, y = [], b = !1, C = !1, w = () => Array.from(document.querySelectorAll(M)).filter((e) => A.has(e.getAttribute(N) ?? "")), k = (e) => {
364
- let t = Array.from(document.querySelectorAll("[data-flemo-bar]")).filter((e) => A.has(e.getAttribute("data-flemo-bar-status") ?? "") || e.getAttribute("data-flemo-bar-riding") === "true").length, n = Array.from(document.querySelectorAll("[data-flemo-decorator]")).filter((e) => A.has(e.getAttribute(N) ?? "")).length, r = Array.from(document.querySelectorAll("[data-flemo-part-name]")).filter((e) => A.has(e.getAttribute(N) ?? "")).length;
382
+ let y = [], ee = 0, x = null, S = [], C = !1, w = !1, D = () => Array.from(document.querySelectorAll(le)).filter((e) => B.has(e.getAttribute("data-flemo-status") ?? "")), O = (e) => {
383
+ let t = Array.from(document.querySelectorAll(b(g))).filter((e) => B.has(e.getAttribute("data-flemo-bar-status") ?? "") || e.getAttribute("data-flemo-bar-riding") === "true").length, n = Array.from(document.querySelectorAll(b(h))).filter((e) => B.has(e.getAttribute("data-flemo-status") ?? "")).length, r = Array.from(document.querySelectorAll(b(m))).filter((e) => B.has(e.getAttribute("data-flemo-status") ?? "")).length;
365
384
  return {
366
385
  screens: e.length,
367
386
  bars: t,
368
387
  decorators: n,
369
388
  parts: r
370
389
  };
371
- }, ae = (e) => {
390
+ }, k = (e) => {
372
391
  let t = [];
373
392
  for (let n of e) for (let e of Array.from(n.querySelectorAll("img"))) t.push(e);
374
393
  return t;
375
- }, H = (e) => {
394
+ }, A = (e) => {
376
395
  let t = 0, n = 0;
377
396
  for (let r of e.imagesTracked) r.complete && (t += 1, e.imagesHeld.has(r) || (n += 1));
378
397
  return {
@@ -382,20 +401,20 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
382
401
  heldDuringFlight: e.imagesHeld.size,
383
402
  completedUnheld: n
384
403
  };
385
- }, U = (e) => {
386
- let t = v;
387
- if (!(!t || t.imagesTracked.size >= R)) for (let n of Array.from(e)) {
404
+ }, j = (e) => {
405
+ let t = x;
406
+ if (!(!t || t.imagesTracked.size >= pe)) for (let n of Array.from(e)) {
388
407
  if (!(n instanceof Element) || !t.elements.some((e) => e === n || e.contains(n))) continue;
389
408
  let e = n instanceof HTMLImageElement ? [n] : Array.from(n.querySelectorAll("img"));
390
409
  for (let n of e) if (!(n.complete || t.imagesTracked.has(n))) {
391
- if (t.imagesTracked.size >= R) return;
410
+ if (t.imagesTracked.size >= pe) return;
392
411
  t.imagesTracked.add(n), t.imagesAddedDuringFlight += 1;
393
412
  }
394
413
  }
395
- }, W = (e) => {
396
- for (let t of e.elements) for (let n of Array.from(t.querySelectorAll(`img[${L}]`))) e.imagesHeld.add(n);
397
- for (let t of e.imagesTracked) t.hasAttribute(L) && e.imagesHeld.add(t);
398
- }, G = (e, t) => {
414
+ }, M = (e) => {
415
+ for (let t of e.elements) for (let n of Array.from(t.querySelectorAll(`img[${f}]`))) e.imagesHeld.add(n);
416
+ for (let t of e.imagesTracked) t.hasAttribute("data-flemo-img-hold") && e.imagesHeld.add(t);
417
+ }, N = (e, t) => {
399
418
  e.releasedFrames += 1;
400
419
  let n = !1, r = !1;
401
420
  for (let t of e.elements) {
@@ -414,7 +433,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
414
433
  e.lastPose.get(t) !== r && (n = !0);
415
434
  }
416
435
  }
417
- if (!(e.releasedFrames < re)) {
436
+ if (!(e.releasedFrames < fe)) {
418
437
  if (n) {
419
438
  e.stallRunMs = 0;
420
439
  return;
@@ -425,7 +444,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
425
444
  }
426
445
  e.stalledFrames += 1, e.stallRunMs += t, e.stallRunMs > e.longestStallMs && (e.longestStallMs = e.stallRunMs);
427
446
  }
428
- }, K = (e) => {
447
+ }, P = (e) => {
429
448
  for (let t of e.elements) {
430
449
  let n = t.style, r = t.getAnimations, i = e.clocks.get(t);
431
450
  if (i !== void 0 && i.playState !== "finished") {
@@ -448,51 +467,51 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
448
467
  i !== void 0 && i !== r && (e.evidence.playerAdvance = !0), e.lastPose.set(t, r);
449
468
  }
450
469
  }
451
- }, q = (e) => e.elements.some((e) => {
452
- let t = e.getAttribute(P);
453
- return t !== null && j.has(t);
454
- }), J = () => {
455
- let e = v;
456
- if (!e || b) return;
470
+ }, ne = (e) => e.elements.some((e) => {
471
+ let t = e.getAttribute(H);
472
+ return t !== null && V.has(t);
473
+ }), re = () => {
474
+ let e = x;
475
+ if (!e || C) return;
457
476
  let t = performance.now();
458
- if (e.lastFrameAt !== null && e.heldGaps.length + e.releasedGaps.length < I) {
459
- let n = t - e.lastFrameAt, r = q(e);
460
- (r ? e.heldGaps : e.releasedGaps).push(n), r || (G(e, n), e.releasedFrames === 1 && W(e));
477
+ if (e.lastFrameAt !== null && e.heldGaps.length + e.releasedGaps.length < de) {
478
+ let n = t - e.lastFrameAt, r = ne(e);
479
+ (r ? e.heldGaps : e.releasedGaps).push(n), r || (N(e, n), e.releasedFrames === 1 && M(e));
461
480
  }
462
- if (e.lastFrameAt = t, K(e), t - e.t0Ms > 1e4) {
463
- y = [...e.elements], le(t, Y(e));
481
+ if (e.lastFrameAt = t, P(e), t - e.t0Ms > 1e4) {
482
+ S = [...e.elements], W(t, L(e));
464
483
  return;
465
484
  }
466
- e.rafId = requestAnimationFrame(J);
467
- }, Y = (e) => {
485
+ e.rafId = requestAnimationFrame(re);
486
+ }, L = (e) => {
468
487
  let t = /* @__PURE__ */ new Set();
469
488
  for (let n of e.elements) {
470
- let e = n.getAttribute(N) ?? "";
471
- A.has(e) && t.add(e);
489
+ let e = n.getAttribute("data-flemo-status") ?? "";
490
+ B.has(e) && t.add(e);
472
491
  }
473
492
  return [...t];
474
- }, X = (e) => {
493
+ }, R = (e) => {
475
494
  let t = performance.now();
476
- g += 1;
477
- let n = e.find((e) => e.getAttribute(te) === "true") ?? e[0], r = O(n.getAttribute(N) ?? "") ?? "PUSH", i = null;
495
+ ee += 1;
496
+ let n = e.find((e) => e.getAttribute("data-flemo-active") === "true") ?? e[0], r = oe(n.getAttribute("data-flemo-status") ?? "") ?? "PUSH", i = null;
478
497
  for (let t of e) {
479
- let e = t.getAttribute(P);
480
- if (e !== null && j.has(e)) {
498
+ let e = t.getAttribute(H);
499
+ if (e !== null && V.has(e)) {
481
500
  i = e;
482
501
  break;
483
502
  }
484
503
  }
485
- v = {
486
- id: `flight-${g}`,
504
+ x = {
505
+ id: `flight-${ee}`,
487
506
  kind: r,
488
507
  routerId: n.getAttribute("data-flemo-router") ?? void 0,
489
508
  t0Ms: t,
490
509
  t0Iso: (/* @__PURE__ */ new Date()).toISOString(),
491
510
  elements: [...e],
492
- participants: k(e),
511
+ participants: O(e),
493
512
  holdKind: i,
494
513
  holdReleasedAtMs: null,
495
- playerGapStartIndex: V().__flemoPlayerGaps?.length ?? 0,
514
+ playerGapStartIndex: ge().__flemoPlayerGaps?.length ?? 0,
496
515
  heldGaps: [],
497
516
  releasedGaps: [],
498
517
  lastFrameAt: null,
@@ -511,32 +530,32 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
511
530
  longestStallMs: 0,
512
531
  pausedAfterRelease: !1,
513
532
  holdReassertedAtMs: null,
514
- imagesTracked: new Set(ae(e).filter((e) => !e.complete)),
533
+ imagesTracked: new Set(k(e).filter((e) => !e.complete)),
515
534
  imagesLoadingAtStart: 0,
516
535
  imagesAddedDuringFlight: 0,
517
536
  imagesHeld: /* @__PURE__ */ new Set(),
518
537
  rafId: null
519
- }, v.imagesLoadingAtStart = v.imagesTracked.size, K(v), v.rafId = requestAnimationFrame(J);
520
- }, oe = (e, t) => {
521
- let n = F, r = () => {
522
- if (!b) {
538
+ }, x.imagesLoadingAtStart = x.imagesTracked.size, P(x), x.rafId = requestAnimationFrame(re);
539
+ }, ce = (e, t) => {
540
+ let n = ue, r = () => {
541
+ if (!C) {
523
542
  if (--n, n > 0) {
524
543
  requestAnimationFrame(r);
525
544
  return;
526
545
  }
527
- ce(e, t);
546
+ ve(e, t);
528
547
  }
529
548
  };
530
549
  requestAnimationFrame(r);
531
- }, se = () => {
532
- if (v !== null || w().length > 0) return [];
550
+ }, _e = () => {
551
+ if (x !== null || D().length > 0) return [];
533
552
  let e = [];
534
- for (let [t, n] of [[L, "image reveal hold"], [ne, "arrival hold"]]) {
553
+ for (let [t, n] of [[f, "image reveal hold"], [p, "arrival hold"]]) {
535
554
  let r = document.querySelectorAll(`[${t}]`).length;
536
555
  r > 0 && e.push(`${r} × ${n} (${t}) still marked at rest`);
537
556
  }
538
557
  return e;
539
- }, ce = (e, t) => {
558
+ }, ve = (e, t) => {
540
559
  let n = [], r = !1, i = window.visualViewport?.width ?? window.innerWidth ?? 0;
541
560
  t.forEach((e, t) => {
542
561
  if (!(e instanceof HTMLElement) || !e.isConnected) return;
@@ -546,45 +565,45 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
546
565
  a = t.transform ?? "", o = t.display ?? "";
547
566
  } catch {}
548
567
  if (o === "none") return;
549
- let s = e.getAttribute(te) === "true", c = `screen[${t}]${s ? " (active)" : ""}`;
550
- 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(N) === "COMPLETED" && i > 0) {
551
- let e = ee(a);
568
+ let s = e.getAttribute(u) === "true", c = `screen[${t}]${s ? " (active)" : ""}`;
569
+ 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) {
570
+ let e = se(a);
552
571
  e !== null && Math.abs(e) >= i * .5 && (r = !0);
553
572
  }
554
- }), e.landing.residualInlineTransforms = n, e.landing.offViewportAtRest = r, e.landing.orphanedHolds = se();
555
- }, le = (e, t) => {
556
- let i = v;
573
+ }), e.landing.residualInlineTransforms = n, e.landing.offViewportAtRest = r, e.landing.orphanedHolds = _e();
574
+ }, W = (e, t) => {
575
+ let i = x;
557
576
  if (!i) return;
558
- W(i), v = null, i.rafId !== null && cancelAnimationFrame(i.rafId);
559
- let a = E((V().__flemoPlayerGaps ?? []).slice(i.playerGapStartIndex)), o = {
577
+ M(i), x = null, i.rafId !== null && cancelAnimationFrame(i.rafId);
578
+ let a = z((ge().__flemoPlayerGaps ?? []).slice(i.playerGapStartIndex)), o = {
560
579
  id: i.id,
561
580
  ...i.routerId === void 0 ? {} : { routerId: i.routerId },
562
581
  kind: i.kind,
563
582
  t0: {
564
- ms: z(i.t0Ms),
583
+ ms: U(i.t0Ms),
565
584
  iso: i.t0Iso
566
585
  },
567
586
  t1: {
568
- ms: z(e),
587
+ ms: U(e),
569
588
  iso: (/* @__PURE__ */ new Date()).toISOString()
570
589
  },
571
- durationMs: z(e - i.t0Ms),
572
- driver: D(i.evidence),
590
+ durationMs: U(e - i.t0Ms),
591
+ driver: ae(i.evidence),
573
592
  participants: i.participants,
574
593
  holds: {
575
594
  kind: i.holdKind,
576
595
  releasedAtMs: i.holdReleasedAtMs
577
596
  },
578
- frameSamples: T(i.heldGaps, i.releasedGaps),
597
+ frameSamples: ie(i.heldGaps, i.releasedGaps),
579
598
  motion: {
580
599
  sampledFrames: i.releasedFrames,
581
600
  stalledFrames: i.stalledFrames,
582
- longestStallMs: z(i.longestStallMs),
601
+ longestStallMs: U(i.longestStallMs),
583
602
  pausedAfterRelease: i.pausedAfterRelease,
584
603
  holdReassertedAtMs: i.holdReassertedAtMs,
585
604
  tailFrames: i.tailFrames
586
605
  },
587
- images: H(i),
606
+ images: A(i),
588
607
  ...a ? { playerGaps: a } : {},
589
608
  longTasks: [],
590
609
  holdLongTasks: [],
@@ -596,34 +615,34 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
596
615
  },
597
616
  anomalies: []
598
617
  };
599
- h.push(o), h.length > n && h.splice(0, h.length - n), t.length === 0 && oe(o, i.elements), r && console.info(`[flemo devtools] ${o.id} ${o.kind} driver=${o.driver} ${o.durationMs}ms screens=${o.participants.screens}`);
600
- }, ue = (e) => {
601
- let t = v;
618
+ y.push(o), y.length > n && y.splice(0, y.length - n), t.length === 0 && ce(o, i.elements), r && console.info(`[flemo devtools] ${o.id} ${o.kind} driver=${o.driver} ${o.durationMs}ms screens=${o.participants.screens}`);
619
+ }, ye = (e) => {
620
+ let t = x;
602
621
  if (!t || !(e.target instanceof Element)) return;
603
- let n = e.target.getAttribute(P);
604
- n !== null && j.has(n) && t.holdKind === null && (t.holdKind = n), n !== null && j.has(n) && t.holdReleasedAtMs !== null && t.holdReassertedAtMs === null && (t.holdReassertedAtMs = z(performance.now() - t.t0Ms)), (n === "false" || n === null) && e.oldValue !== null && j.has(e.oldValue) && t.holdReleasedAtMs === null && !q(t) && (t.holdReleasedAtMs = z(performance.now() - t.t0Ms));
605
- }, de = () => {
606
- let e = w();
607
- if (y.length > 0) {
608
- if (e.some((e) => y.includes(e))) return;
609
- y = [];
622
+ let n = e.target.getAttribute(H);
623
+ n !== null && V.has(n) && t.holdKind === null && (t.holdKind = n), n !== null && V.has(n) && t.holdReleasedAtMs !== null && t.holdReassertedAtMs === null && (t.holdReassertedAtMs = U(performance.now() - t.t0Ms)), (n === "false" || n === null) && e.oldValue !== null && V.has(e.oldValue) && t.holdReleasedAtMs === null && !ne(t) && (t.holdReleasedAtMs = U(performance.now() - t.t0Ms));
624
+ }, G = () => {
625
+ let e = D();
626
+ if (S.length > 0) {
627
+ if (e.some((e) => S.includes(e))) return;
628
+ S = [];
610
629
  }
611
- if (!v && e.length > 0) {
612
- X(e);
630
+ if (!x && e.length > 0) {
631
+ R(e);
613
632
  return;
614
633
  }
615
- if (v && e.length === 0) {
616
- le(performance.now(), []);
634
+ if (x && e.length === 0) {
635
+ W(performance.now(), []);
617
636
  return;
618
637
  }
619
- if (v) for (let t of e) v.elements.includes(t) || (v.elements.push(t), U(t.querySelectorAll("img")), v.participants = k(v.elements));
620
- }, Z = null, Q = null, $ = () => {
638
+ if (x) for (let t of e) x.elements.includes(t) || (x.elements.push(t), j(t.querySelectorAll("img")), x.participants = O(x.elements));
639
+ }, K = null, q = null, J = () => {
621
640
  let e = document.documentElement;
622
641
  if (!e) return !1;
623
642
  let t = new MutationObserver((e) => {
624
- if (!b) {
625
- for (let t of e) t.type === "attributes" && t.attributeName === P ? ue(t) : t.type === "childList" && t.addedNodes.length > 0 && U(t.addedNodes);
626
- de();
643
+ if (!C) {
644
+ for (let t of e) t.type === "attributes" && t.attributeName === H ? ye(t) : t.type === "childList" && t.addedNodes.length > 0 && j(t.addedNodes);
645
+ G();
627
646
  }
628
647
  });
629
648
  try {
@@ -633,31 +652,31 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
633
652
  attributes: !0,
634
653
  attributeOldValue: !0,
635
654
  attributeFilter: [
636
- N,
637
- te,
638
- P
655
+ l,
656
+ u,
657
+ H
639
658
  ]
640
659
  });
641
660
  } catch {
642
661
  return !1;
643
662
  }
644
- return Z = t, de(), !0;
663
+ return K = t, G(), !0;
645
664
  };
646
- if (!$()) {
665
+ if (!J()) {
647
666
  let e = () => {
648
- Q = null, b || $();
667
+ q = null, C || J();
649
668
  };
650
- Q = e, document.addEventListener("DOMContentLoaded", e, { once: !0 });
669
+ q = e, document.addEventListener("DOMContentLoaded", e, { once: !0 });
651
670
  }
652
- let fe = (e) => {
653
- let t = u.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;
671
+ let Y = (e) => {
672
+ let t = _.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;
654
673
  return {
655
674
  released: t.filter((e) => e.startMs + e.durationMs > n),
656
675
  held: t.filter((e) => e.startMs + e.durationMs <= n)
657
676
  };
658
- }, pe = () => {
659
- let e = performance.now(), n = h.map((e) => {
660
- let t = fe(e), n = {
677
+ }, X = () => {
678
+ let e = performance.now(), n = y.map((e) => {
679
+ let t = Y(e), n = {
661
680
  ...e,
662
681
  longTasks: t.released,
663
682
  holdLongTasks: t.held,
@@ -681,47 +700,47 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
681
700
  motion: n.motion,
682
701
  images: n.images
683
702
  }), n;
684
- }), r = v;
703
+ }), r = x;
685
704
  if (!r) return n;
686
705
  let i = e - r.t0Ms > t, o = {
687
706
  id: `${r.id} (in flight)`,
688
707
  ...r.routerId === void 0 ? {} : { routerId: r.routerId },
689
708
  kind: r.kind,
690
709
  t0: {
691
- ms: z(r.t0Ms),
710
+ ms: U(r.t0Ms),
692
711
  iso: r.t0Iso
693
712
  },
694
713
  t1: {
695
- ms: z(e),
714
+ ms: U(e),
696
715
  iso: (/* @__PURE__ */ new Date()).toISOString()
697
716
  },
698
- durationMs: z(e - r.t0Ms),
699
- driver: D(r.evidence),
717
+ durationMs: U(e - r.t0Ms),
718
+ driver: ae(r.evidence),
700
719
  participants: r.participants,
701
720
  holds: {
702
721
  kind: r.holdKind,
703
722
  releasedAtMs: r.holdReleasedAtMs
704
723
  },
705
- frameSamples: T(r.heldGaps, r.releasedGaps),
724
+ frameSamples: ie(r.heldGaps, r.releasedGaps),
706
725
  motion: {
707
726
  sampledFrames: r.releasedFrames,
708
727
  stalledFrames: r.stalledFrames,
709
- longestStallMs: z(r.longestStallMs),
728
+ longestStallMs: U(r.longestStallMs),
710
729
  pausedAfterRelease: r.pausedAfterRelease,
711
730
  holdReassertedAtMs: r.holdReassertedAtMs,
712
731
  tailFrames: r.tailFrames
713
732
  },
714
- images: H(r),
733
+ images: A(r),
715
734
  longTasks: [],
716
735
  holdLongTasks: [],
717
736
  landing: {
718
737
  residualInlineTransforms: [],
719
738
  offViewportAtRest: !1,
720
- stuckStatuses: i ? Y(r) : [],
739
+ stuckStatuses: i ? L(r) : [],
721
740
  orphanedHolds: []
722
741
  },
723
742
  anomalies: []
724
- }, s = fe(o);
743
+ }, s = Y(o);
725
744
  return o.longTasks = s.released, o.holdLongTasks = s.held, o.anomalies = a({
726
745
  t0Ms: o.t0.ms,
727
746
  t1Ms: o.t1.ms,
@@ -735,16 +754,10 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
735
754
  motion: o.motion,
736
755
  images: o.images
737
756
  }), [...n, o];
738
- }, me = (e, t) => {
739
- try {
740
- return (e === "session" ? sessionStorage : localStorage).getItem(t);
741
- } catch {
742
- return null;
743
- }
744
- }, he = () => {
745
- let e = x(), t = { ...e };
757
+ }, be = () => {
758
+ let e = F(), t = { ...e };
746
759
  for (let [n, r] of Object.entries(c)) n in e || (t[`${n} (at attach, since cleared)`] = r);
747
- let n = S(t), r = p(l), i = me("session", "flemo:motion-driver-force"), a = i === null ? c["flemo:motion-driver-force"] ?? null : null, u = pe(), d = v;
760
+ let n = I(t), r = T(d), i = X(), a = x;
748
761
  return {
749
762
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
750
763
  version: "2",
@@ -753,57 +766,50 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
753
766
  active: t,
754
767
  warnings: n
755
768
  },
756
- driverPolicy: {
757
- demotion: me("local", "flemo:motion-driver"),
758
- forcePin: i
759
- },
760
- flights: u,
769
+ flights: i,
761
770
  anomalies: o({
762
- forcePin: i,
763
- legacyLocalForcePin: t[_] ?? null,
764
- clearedForcePin: a,
765
771
  emulationSuspected: r.emulationSuspected,
766
772
  platform: r.platform,
767
- stuckFlightOpen: d !== null && performance.now() - d.t0Ms > 1e4,
768
- flightAnomalies: u.map((e) => e.anomalies)
773
+ stuckFlightOpen: a !== null && performance.now() - a.t0Ms > 1e4,
774
+ flightAnomalies: i.map((e) => e.anomalies)
769
775
  }),
770
776
  blindSpots: [...s],
771
- judgingProtocol: [...m]
777
+ judgingProtocol: [...E]
772
778
  };
773
- }, ge = () => {
774
- if (!b) {
775
- if (b = !0, Z?.disconnect(), Q !== null && (document.removeEventListener("DOMContentLoaded", Q), Q = null), f?.disconnect(), v?.rafId != null && cancelAnimationFrame(v.rafId), v = null, C) {
776
- let e = V();
779
+ }, xe = () => {
780
+ if (!C) {
781
+ if (C = !0, K?.disconnect(), q !== null && (document.removeEventListener("DOMContentLoaded", q), q = null), v?.disconnect(), x?.rafId != null && cancelAnimationFrame(x.rafId), x = null, w) {
782
+ let e = ge();
777
783
  e.flemo?.__flemoDevtools === !0 && delete e.flemo;
778
784
  }
779
- B = null;
785
+ he = null;
780
786
  }
781
- }, _e = {
782
- detach: ge,
783
- report: he
787
+ }, Se = {
788
+ detach: xe,
789
+ report: be
784
790
  };
785
791
  if (i) {
786
- let e = V(), t = e.flemo;
792
+ let e = ge(), t = e.flemo;
787
793
  (t === void 0 || t?.__flemoDevtools === !0) && (e.flemo = {
788
794
  __flemoDevtools: !0,
789
- report: he,
790
- flights: pe,
791
- detach: ge
792
- }, C = !0);
795
+ report: be,
796
+ flights: X,
797
+ detach: xe
798
+ }, w = !0);
793
799
  }
794
- return B = _e, _e;
795
- }, H = "http://www.w3.org/2000/svg", U = (e, t, n) => {
800
+ return he = Se, Se;
801
+ }, ve = "http://www.w3.org/2000/svg", W = (e, t, n) => {
796
802
  let r = document.createElement(e);
797
803
  return t !== void 0 && (r.className = t), n !== void 0 && (r.textContent = n), r;
798
- }, W = (e, t) => {
799
- let n = document.createElementNS(H, e);
804
+ }, ye = (e, t) => {
805
+ let n = document.createElementNS(ve, e);
800
806
  for (let [e, r] of Object.entries(t)) n.setAttribute(e, r);
801
807
  return n;
802
808
  }, G = (e) => {
803
809
  for (; e.firstChild !== null;) e.removeChild(e.firstChild);
804
810
  }, K = (e, t) => {
805
811
  e.textContent !== t && (e.textContent = t);
806
- }, q = (e) => e == null || e === "" ? "—" : String(e), J = (e) => typeof e == "number" && Number.isFinite(e) ? `${Math.round(e)}ms` : "—", Y = (e) => typeof e == "number" && Number.isFinite(e) ? `${Math.round(e * 10) / 10}ms` : "—", X = (e) => typeof e == "number" && Number.isFinite(e) ? String(e) : "—", oe = (e) => e === !0 ? "yes" : e === !1 ? "no" : "—", se = (e) => {
812
+ }, q = (e) => e == null || e === "" ? "—" : String(e), J = (e) => typeof e == "number" && Number.isFinite(e) ? `${Math.round(e)}ms` : "—", Y = (e) => typeof e == "number" && Number.isFinite(e) ? `${Math.round(e * 10) / 10}ms` : "—", X = (e) => typeof e == "number" && Number.isFinite(e) ? String(e) : "—", be = (e) => e === !0 ? "yes" : e === !1 ? "no" : "—", xe = (e) => {
807
813
  let t = e?.environment;
808
814
  if (!t) return "—";
809
815
  let n = t.viewport, r = n && typeof n.width == "number" && typeof n.height == "number" ? `${Math.round(n.width)}×${Math.round(n.height)}` : "—";
@@ -813,36 +819,36 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
813
819
  r,
814
820
  `rAF ${Y(t.rafCadence?.medianGapMs)}`
815
821
  ].join(" · ");
816
- }, ce = (e, t) => `${t ?? ""}#${e.map((e) => `${e?.id ?? ""}|${e?.kind ?? ""}|${e?.driver ?? ""}|${Math.round(e?.durationMs ?? 0)}|${e?.participants?.screens ?? 0}|${e?.anomalies?.length ?? 0}`).join(",")}`, le = (e) => {
822
+ }, Se = (e, t) => `${t ?? ""}#${e.map((e) => `${e?.id ?? ""}|${e?.kind ?? ""}|${e?.driver ?? ""}|${Math.round(e?.durationMs ?? 0)}|${e?.participants?.screens ?? 0}|${e?.anomalies?.length ?? 0}`).join(",")}`, Ce = (e) => {
817
823
  let t = e?.released?.gaps;
818
824
  if (!Array.isArray(t)) return null;
819
825
  let n = t.filter((e) => typeof e == "number" && Number.isFinite(e));
820
826
  return n.length >= 2 ? n : null;
821
- }, ue = "\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.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", de = 48, Z = (e, t, n, r) => {
822
- let i = U("div", "kv");
823
- i.appendChild(U("span", "k", t)), i.appendChild(U("span", r ? `v ${r}` : "v", n)), e.appendChild(i);
827
+ }, we = "\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.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", Te = 48, Z = (e, t, n, r) => {
828
+ let i = W("div", "kv");
829
+ i.appendChild(W("span", "k", t)), i.appendChild(W("span", r ? `v ${r}` : "v", n)), e.appendChild(i);
824
830
  }, Q = (e, t) => {
825
- let n = U("section", "section");
826
- return n.appendChild(U("h2", void 0, t)), e.appendChild(n), n;
831
+ let n = W("section", "section");
832
+ return n.appendChild(W("h2", void 0, t)), e.appendChild(n), n;
827
833
  }, $ = (e, t, n = "li") => {
828
- e.appendChild(U("div", n, t));
829
- }, fe = (e, t) => {
834
+ e.appendChild(W("div", n, t));
835
+ }, Ee = (e, t) => {
830
836
  G(e);
831
- for (let n of t?.overrides?.warnings ?? []) e.appendChild(U("span", "chip warn", q(n)));
832
- for (let n of t?.anomalies ?? []) e.appendChild(U("span", "chip bad", q(n)));
833
- for (let [n, r] of Object.entries(t?.overrides?.active ?? {})) e.appendChild(U("span", "chip", `${n}=${String(r)}`));
834
- }, pe = (e, t, n, r) => {
837
+ for (let n of t?.overrides?.warnings ?? []) e.appendChild(W("span", "chip warn", q(n)));
838
+ for (let n of t?.anomalies ?? []) e.appendChild(W("span", "chip bad", q(n)));
839
+ for (let [n, r] of Object.entries(t?.overrides?.active ?? {})) e.appendChild(W("span", "chip", `${n}=${String(r)}`));
840
+ }, De = (e, t, n, r) => {
835
841
  if (G(e), t.length === 0) {
836
842
  $(e, "no flights recorded yet — navigate once", "li dim");
837
843
  return;
838
844
  }
839
845
  for (let i = t.length - 1; i >= 0; --i) {
840
- let a = t[i], o = q(a?.id), s = U("button", "row");
841
- s.type = "button", s.setAttribute("data-flight-id", o), s.setAttribute("aria-selected", String(o === n)), s.appendChild(U("span", "kind", q(a?.kind))), s.appendChild(U("span", "driver", q(a?.driver))), s.appendChild(U("span", "dur", J(a?.durationMs))), s.appendChild(U("span", "screens", `${X(a?.participants?.screens)} scr`));
846
+ let a = t[i], o = q(a?.id), s = W("button", "row");
847
+ s.type = "button", s.setAttribute("data-flight-id", o), s.setAttribute("aria-selected", String(o === n)), s.appendChild(W("span", "kind", q(a?.kind))), s.appendChild(W("span", "driver", q(a?.driver))), s.appendChild(W("span", "dur", J(a?.durationMs))), s.appendChild(W("span", "screens", `${X(a?.participants?.screens)} scr`));
842
848
  let c = a?.anomalies?.length ?? 0;
843
- s.appendChild(U("span", c > 0 ? "n bad" : "n", String(c))), s.addEventListener("click", () => r(o)), e.appendChild(s);
849
+ s.appendChild(W("span", c > 0 ? "n bad" : "n", String(c))), s.addEventListener("click", () => r(o)), e.appendChild(s);
844
850
  }
845
- }, me = (e, t, n) => {
851
+ }, Oe = (e, t, n) => {
846
852
  if (!n) {
847
853
  Z(e, t, "—");
848
854
  return;
@@ -853,21 +859,21 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
853
859
  `max ${Y(n.maxGapMs)}`
854
860
  ];
855
861
  typeof n.over30Count == "number" && r.push(`>30ms ×${n.over30Count}`), Z(e, t, r.join(" · "));
856
- }, he = (e) => {
857
- 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 = W("svg", {
862
+ }, ke = (e) => {
863
+ 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 = ye("svg", {
858
864
  class: "spark",
859
865
  viewBox: "0 0 100 28",
860
866
  preserveAspectRatio: "none",
861
867
  "aria-hidden": "true"
862
868
  });
863
- return a.appendChild(W("polyline", {
869
+ return a.appendChild(ye("polyline", {
864
870
  points: i,
865
871
  fill: "none",
866
872
  stroke: "currentColor",
867
873
  "stroke-width": "1",
868
874
  "vector-effect": "non-scaling-stroke"
869
875
  })), a;
870
- }, ge = (e, t) => {
876
+ }, Ae = (e, t) => {
871
877
  let n = t.longTasks ?? [], r = t.holdLongTasks ?? [];
872
878
  if (n.length === 0 && r.length === 0) {
873
879
  $(e, "none", "li dim");
@@ -876,7 +882,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
876
882
  let i = (e) => `${J(e?.startMs)} + ${J(e?.durationMs)}`;
877
883
  for (let t of n) $(e, i(t), "li bad");
878
884
  for (let t of r) $(e, `${i(t)} (absorbed by hold)`, "li dim");
879
- }, _e = (e, t) => {
885
+ }, je = (e, t) => {
880
886
  if (G(e), !t) {
881
887
  $(e, "select a flight", "li dim");
882
888
  return;
@@ -884,17 +890,17 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
884
890
  let n = Q(e, "timing");
885
891
  Z(n, "id", q(t.id)), Z(n, "kind / driver", `${q(t.kind)} · ${q(t.driver)}`), Z(n, "router", q(t.routerId)), Z(n, "t0", q(t.t0?.iso)), Z(n, "duration", J(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", `${q(t.holds?.kind)} · released ${J(t.holds?.releasedAtMs)}`);
886
892
  let r = Q(e, "frames");
887
- me(r, "held (absorbed)", t.frameSamples?.held), me(r, "released (visible)", t.frameSamples?.released), t.playerGaps && Z(r, "player mirror", `max ${Y(t.playerGaps.maxMs)} · >30ms ×${X(t.playerGaps.over30Count)}`);
888
- let i = le(t.frameSamples);
889
- i && r.appendChild(he(i));
893
+ Oe(r, "held (absorbed)", t.frameSamples?.held), Oe(r, "released (visible)", t.frameSamples?.released), t.playerGaps && Z(r, "player mirror", `max ${Y(t.playerGaps.maxMs)} · >30ms ×${X(t.playerGaps.over30Count)}`);
894
+ let i = Ce(t.frameSamples);
895
+ i && r.appendChild(ke(i));
890
896
  let a = Q(e, "motion (did it move)"), o = t.motion?.longestStallMs, s = t.motion?.holdReassertedAtMs;
891
- 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", J(o), (o ?? 0) >= de ? "bad" : void 0), Z(a, "paused after release", oe(t.motion?.pausedAfterRelease), t.motion?.pausedAfterRelease === !0 ? "bad" : void 0), Z(a, "hold re-asserted", s == null ? "no" : J(s), typeof s == "number" ? "bad" : void 0);
897
+ 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", J(o), (o ?? 0) >= Te ? "bad" : void 0), Z(a, "paused after release", be(t.motion?.pausedAfterRelease), t.motion?.pausedAfterRelease === !0 ? "bad" : void 0), Z(a, "hold re-asserted", s == null ? "no" : J(s), typeof s == "number" ? "bad" : void 0);
892
898
  let c = Q(e, "images"), l = t.images?.completedDuringFlight ?? 0, u = t.images?.heldDuringFlight ?? 0, d = t.images?.completedUnheld, f = typeof d == "number" ? d > 0 : l > u;
893
- Z(c, "loading at t0", X(t.images?.loadingAtStart)), Z(c, "added mid-flight", X(t.images?.addedDuringFlight)), Z(c, "completed mid-flight", X(t.images?.completedDuringFlight), f ? "bad" : void 0), Z(c, "held by the engine", X(t.images?.heldDuringFlight)), Z(c, "completed without hold", X(d), f ? "bad" : void 0), ge(Q(e, "long tasks"), t);
899
+ Z(c, "loading at t0", X(t.images?.loadingAtStart)), Z(c, "added mid-flight", X(t.images?.addedDuringFlight)), Z(c, "completed mid-flight", X(t.images?.completedDuringFlight), f ? "bad" : void 0), Z(c, "held by the engine", X(t.images?.heldDuringFlight)), Z(c, "completed without hold", X(d), f ? "bad" : void 0), Ae(Q(e, "long tasks"), t);
894
900
  let p = Q(e, "landing"), m = t.landing?.residualInlineTransforms ?? [];
895
901
  if (m.length === 0) Z(p, "inline residue", "clean");
896
902
  else for (let e of m) Z(p, "inline residue", q(e));
897
- Z(p, "off-viewport at rest", oe(t.landing?.offViewportAtRest));
903
+ Z(p, "off-viewport at rest", be(t.landing?.offViewportAtRest));
898
904
  let h = t.landing?.stuckStatuses ?? [];
899
905
  Z(p, "stuck statuses", h.length === 0 ? "none" : h.join(", "));
900
906
  let g = t.landing?.orphanedHolds ?? [];
@@ -906,152 +912,152 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
906
912
  return;
907
913
  }
908
914
  for (let e of v) $(_, q(e), "li bad");
909
- }, ve = (e, t) => {
915
+ }, Me = (e, t) => {
910
916
  G(e);
911
917
  for (let n of t ?? []) $(e, q(n));
912
- }, ye = "[data-flemo-screen][data-flemo-status=\"PUSHING\"],[data-flemo-screen][data-flemo-status=\"POPPING\"],[data-flemo-screen][data-flemo-status=\"REPLACING\"]", be = "flemo:devtools-panel-height", xe = 320, Se = 2e3, Ce = 120, we = "Copy report JSON", Te = () => {}, Ee = null, De = (e = {}) => {
913
- if (Ee) return Ee;
914
- if (typeof document > "u") return { detach: Te };
918
+ }, Ne = v.map((e) => b(c) + ee(l, e)).join(","), Pe = 320, Fe = 2e3, Ie = 120, Le = "Copy report JSON", Re = () => {}, ze = null, Be = (e = {}) => {
919
+ if (ze) return ze;
920
+ if (typeof document > "u") return { detach: Re };
915
921
  let t = !1, n, r = window.flemo;
916
922
  e.recorder ? n = e.recorder : r?.__flemoDevtools === !0 && typeof r.report == "function" ? n = {
917
923
  report: r.report,
918
- detach: Te
919
- } : (n = ae(), t = !0);
920
- let i = U("div");
921
- i.setAttribute("data-flemo-devtools-panel", ""), i.style.position = "fixed", i.style.top = "0", i.style.left = "0", i.style.width = "0", i.style.height = "0", i.style.zIndex = "2147483000";
922
- let a = i.attachShadow({ mode: "open" }), o = U("style");
923
- o.textContent = ue, a.appendChild(o);
924
- let s = U("div", "root");
924
+ detach: Re
925
+ } : (n = _e(), t = !0);
926
+ let i = W("div");
927
+ i.setAttribute(_, ""), i.style.position = "fixed", i.style.top = "0", i.style.left = "0", i.style.width = "0", i.style.height = "0", i.style.zIndex = "2147483000";
928
+ let a = i.attachShadow({ mode: "open" }), o = W("style");
929
+ o.textContent = we, a.appendChild(o);
930
+ let s = W("div", "root");
925
931
  a.appendChild(s);
926
- let c = U("button", "toggle");
932
+ let c = W("button", "toggle");
927
933
  c.type = "button", c.setAttribute("data-corner", e.position ?? "bottom-right"), c.setAttribute("aria-label", "flemo devtools");
928
- let l = U("span", "count", "0"), u = U("span", "dot");
929
- u.hidden = !0, c.appendChild(U("span", "mark", "flemo")), c.appendChild(l), c.appendChild(u);
930
- let d = U("section", "panel");
934
+ let l = W("span", "count", "0"), u = W("span", "dot");
935
+ u.hidden = !0, c.appendChild(W("span", "mark", "flemo")), c.appendChild(l), c.appendChild(u);
936
+ let d = W("section", "panel");
931
937
  d.hidden = !0;
932
- let f = U("div", "grip");
938
+ let f = W("div", "grip");
933
939
  f.setAttribute("role", "separator"), f.setAttribute("aria-label", "Resize flemo devtools panel");
934
- let p = U("header", "head"), m = U("div", "env", "—"), h = U("button", "act", we);
940
+ let p = W("header", "head"), m = W("div", "env", "—"), h = W("button", "act", Le);
935
941
  h.type = "button";
936
- let g = U("button", "act", "Close");
942
+ let g = W("button", "act", "Close");
937
943
  g.type = "button";
938
- let _ = U("button", "act", "Detach");
939
- _.type = "button";
940
- let v = U("div", "chips");
941
- p.appendChild(m), p.appendChild(U("div", "spacer")), p.appendChild(h), p.appendChild(g), p.appendChild(_), p.appendChild(v);
942
- let y = U("div", "body"), b = U("div", "list"), x = U("div", "detail");
943
- y.appendChild(b), y.appendChild(x);
944
- let S = U("div", "foot"), C = U("details");
945
- C.appendChild(U("summary", void 0, "What this cannot see"));
946
- let w = U("div");
947
- C.appendChild(w), S.appendChild(C), d.appendChild(f), d.appendChild(p), d.appendChild(y), d.appendChild(S), s.appendChild(c), s.appendChild(d);
948
- let T = !1, E = e.initialOpen === !0, D = null, O = "", ee = "", k = "", A = !1, j = 0, M = 0, N = (e) => Math.min(Math.max(e, Ce), Math.max(Ce, window.innerHeight * .9)), te = () => {
944
+ let v = W("button", "act", "Detach");
945
+ v.type = "button";
946
+ let y = W("div", "chips");
947
+ p.appendChild(m), p.appendChild(W("div", "spacer")), p.appendChild(h), p.appendChild(g), p.appendChild(v), p.appendChild(y);
948
+ let b = W("div", "body"), ee = W("div", "list"), x = W("div", "detail");
949
+ b.appendChild(ee), b.appendChild(x);
950
+ let S = W("div", "foot"), C = W("details");
951
+ C.appendChild(W("summary", void 0, "What this cannot see"));
952
+ let te = W("div");
953
+ C.appendChild(te), S.appendChild(C), d.appendChild(f), d.appendChild(p), d.appendChild(b), d.appendChild(S), s.appendChild(c), s.appendChild(d);
954
+ let w = !1, T = e.initialOpen === !0, E = null, O = "", k = "", A = "", j = !1, M = 0, N = 0, P = (e) => Math.min(Math.max(e, Ie), Math.max(Ie, window.innerHeight * .9)), ne = () => {
949
955
  try {
950
- let e = sessionStorage.getItem(be);
956
+ let e = sessionStorage.getItem(D);
951
957
  if (e === null) return null;
952
958
  let t = Number.parseFloat(e);
953
959
  return Number.isFinite(t) ? t : null;
954
960
  } catch {
955
961
  return null;
956
962
  }
957
- }, P = (e) => {
963
+ }, re = (e) => {
958
964
  try {
959
- sessionStorage.setItem(be, String(Math.round(e)));
965
+ sessionStorage.setItem(D, String(Math.round(e)));
960
966
  } catch {}
961
- }, F = N(te() ?? window.innerHeight * .4);
967
+ }, F = P(ne() ?? window.innerHeight * .4);
962
968
  d.style.height = `${Math.round(F)}px`;
963
- let I = () => document.querySelector(ye) !== null, L = () => {
969
+ let I = () => document.querySelector(Ne) !== null, L = () => {
964
970
  try {
965
971
  return n.report();
966
972
  } catch {
967
973
  return null;
968
974
  }
969
- }, ne = (e) => {
970
- e !== D && (D = e, R());
971
- }, re = () => {
975
+ }, R = (e) => {
976
+ e !== E && (E = e, z());
977
+ }, ie = () => {
972
978
  let e = L(), t = e?.flights ?? [];
973
979
  K(l, String(t.length));
974
980
  let n = t.some((e) => (e?.anomalies?.length ?? 0) > 0);
975
- if (u.hidden = !n, d.hidden = !E, !E) return;
976
- K(m, se(e));
981
+ if (u.hidden = !n, d.hidden = !T, !T) return;
982
+ K(m, xe(e));
977
983
  let r = JSON.stringify([
978
984
  e?.overrides?.warnings ?? [],
979
985
  e?.anomalies ?? [],
980
986
  e?.overrides?.active ?? {}
981
987
  ]);
982
- r !== k && (k = r, fe(v, e)), D === null && t.length > 0 && (D = t[t.length - 1]?.id ?? null);
983
- let i = ce(t, D);
984
- i !== O && (O = i, pe(b, t, D, ne));
985
- let a = t.find((e) => e?.id === D) ?? null, o = JSON.stringify(a);
986
- o !== ee && (ee = o, _e(x, a)), A || (A = !0, ve(w, e?.blindSpots));
988
+ r !== A && (A = r, Ee(y, e)), E === null && t.length > 0 && (E = t[t.length - 1]?.id ?? null);
989
+ let i = Se(t, E);
990
+ i !== O && (O = i, De(ee, t, E, R));
991
+ let a = t.find((e) => e?.id === E) ?? null, o = JSON.stringify(a);
992
+ o !== k && (k = o, je(x, a)), j || (j = !0, Me(te, e?.blindSpots));
987
993
  };
988
- function R() {
989
- T || I() || re();
994
+ function z() {
995
+ w || I() || ie();
990
996
  }
991
- function ie() {
992
- j = 0, R(), z();
997
+ function ae() {
998
+ M = 0, z(), oe();
993
999
  }
994
- function z() {
995
- j = window.setTimeout(ie, E ? xe : Se);
1000
+ function oe() {
1001
+ M = window.setTimeout(ae, T ? Pe : Fe);
996
1002
  }
997
- let B = () => {
998
- window.clearTimeout(j), z();
999
- }, V = (e) => {
1000
- E = e, B(), R();
1003
+ let se = () => {
1004
+ window.clearTimeout(M), oe();
1005
+ }, ce = (e) => {
1006
+ T = e, se(), z();
1001
1007
  };
1002
- c.addEventListener("click", () => V(!E)), g.addEventListener("click", () => V(!1)), _.addEventListener("click", () => Y());
1003
- let H = () => {
1004
- if (!T) {
1008
+ c.addEventListener("click", () => ce(!T)), g.addEventListener("click", () => ce(!1)), v.addEventListener("click", () => de());
1009
+ let B = () => {
1010
+ if (!w) {
1005
1011
  if (I()) {
1006
- window.clearTimeout(M), M = window.setTimeout(H, xe);
1012
+ window.clearTimeout(N), N = window.setTimeout(B, Pe);
1007
1013
  return;
1008
1014
  }
1009
- K(h, "Copied ✓"), window.clearTimeout(M), M = window.setTimeout(W, 1200);
1015
+ K(h, "Copied ✓"), window.clearTimeout(N), N = window.setTimeout(V, 1200);
1010
1016
  }
1011
1017
  };
1012
- function W() {
1018
+ function V() {
1013
1019
  if (I()) {
1014
- M = window.setTimeout(W, xe);
1020
+ N = window.setTimeout(V, Pe);
1015
1021
  return;
1016
1022
  }
1017
- M = 0, K(h, we);
1023
+ N = 0, K(h, Le);
1018
1024
  }
1019
- let G = (e) => {
1020
- if (T) return;
1025
+ let le = (e) => {
1026
+ if (w) return;
1021
1027
  if (I()) {
1022
- window.clearTimeout(M), M = window.setTimeout(() => G(e), xe);
1028
+ window.clearTimeout(N), N = window.setTimeout(() => le(e), Pe);
1023
1029
  return;
1024
1030
  }
1025
- let t = U("textarea");
1031
+ let t = W("textarea");
1026
1032
  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();
1027
1033
  let n = document;
1028
1034
  try {
1029
1035
  n.execCommand?.("copy");
1030
1036
  } catch {}
1031
- t.remove(), H();
1037
+ t.remove(), B();
1032
1038
  };
1033
1039
  h.addEventListener("click", () => {
1034
1040
  let e = JSON.stringify(L(), null, 2), t = navigator.clipboard;
1035
1041
  if (t && typeof t.writeText == "function") {
1036
- t.writeText(e).then(H, () => G(e));
1042
+ t.writeText(e).then(B, () => le(e));
1037
1043
  return;
1038
1044
  }
1039
- G(e);
1045
+ le(e);
1040
1046
  });
1041
- let q = (e) => {
1042
- F = N(window.innerHeight - e.clientY), d.style.height = `${Math.round(F)}px`;
1043
- }, J = () => {
1044
- window.removeEventListener("pointermove", q), window.removeEventListener("pointerup", J), P(F);
1047
+ let H = (e) => {
1048
+ F = P(window.innerHeight - e.clientY), d.style.height = `${Math.round(F)}px`;
1049
+ }, ue = () => {
1050
+ window.removeEventListener("pointermove", H), window.removeEventListener("pointerup", ue), re(F);
1045
1051
  };
1046
1052
  f.addEventListener("pointerdown", (e) => {
1047
- e.preventDefault(), window.addEventListener("pointermove", q), window.addEventListener("pointerup", J);
1053
+ e.preventDefault(), window.addEventListener("pointermove", H), window.addEventListener("pointerup", ue);
1048
1054
  });
1049
- function Y() {
1050
- T || (T = !0, window.clearTimeout(j), j = 0, window.clearTimeout(M), M = 0, window.removeEventListener("pointermove", q), window.removeEventListener("pointerup", J), i.remove(), t && n.detach(), Ee = null);
1055
+ function de() {
1056
+ w || (w = !0, window.clearTimeout(M), M = 0, window.clearTimeout(N), N = 0, window.removeEventListener("pointermove", H), window.removeEventListener("pointerup", ue), i.remove(), t && n.detach(), ze = null);
1051
1057
  }
1052
- document.body.appendChild(i), R(), z();
1053
- let X = { detach: Y };
1054
- return Ee = X, X;
1058
+ document.body.appendChild(i), z(), oe();
1059
+ let fe = { detach: de };
1060
+ return ze = fe, fe;
1055
1061
  };
1056
1062
  //#endregion
1057
- export { s as BLIND_SPOTS, h as FLAG_REGISTRY, _ as LEGACY_LOCAL_PIN_KEY, e as LONG_GAP_MS, i as MID_FLIGHT_TASK_MS, n as OPENING_WINDOW_LEAD_MS, r as OPENING_WINDOW_TAIL_MS, k as REPORT_SCHEMA_VERSION, t as STUCK_STATUS_MS, De as attachDevtoolsPanel, ae as attachFlightRecorder, p as captureEnvironment, D as classifyDriver, T as computeFrameStats, w as computePhaseStats, E as computePlayerGapStats, a as deriveFlightAnomalies, S as deriveOverrideWarnings, o as deriveReportAnomalies, l as detectEngine, u as isEmulationSuspected, O as kindFromStatus, ee as parseTranslateX, d as sampleRafCadence, x as snapshotOverrides };
1063
+ export { s as BLIND_SPOTS, k as CORE_FLAGS, O as DEVTOOLS_OWNED_FLAGS, A as FLAG_REGISTRY, e as LONG_GAP_MS, i as MID_FLIGHT_TASK_MS, n as OPENING_WINDOW_LEAD_MS, r as OPENING_WINDOW_TAIL_MS, D as PANEL_HEIGHT_KEY, ce as REPORT_SCHEMA_VERSION, j as RETIRED_FLAGS, M as RETIRED_MARKER, t as STUCK_STATUS_MS, Be as attachDevtoolsPanel, _e as attachFlightRecorder, T as captureEnvironment, ae as classifyDriver, ie as computeFrameStats, R as computePhaseStats, z as computePlayerGapStats, a as deriveFlightAnomalies, I as deriveOverrideWarnings, o as deriveReportAnomalies, S as detectEngine, C as isEmulationSuspected, oe as kindFromStatus, se as parseTranslateX, te as sampleRafCadence, F as snapshotOverrides };