@flemo/devtools 0.2.1 → 0.3.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", ee = "data-flemo-part-name", m = "data-flemo-decorator", h = "data-flemo-bar", g = "data-flemo-devtools-panel", _ = [
25
+ "PUSHING",
26
+ "POPPING",
27
+ "REPLACING"
28
+ ], v = [
29
+ "true",
30
+ "park",
31
+ "park-under",
32
+ "park-over"
33
+ ], y = (e) => `[${e}]`, te = (e, t) => `[${e}="${t}"]`, b = () => {
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
+ }, x = () => {
32
41
  if (typeof navigator > "u") return "unknown";
33
- let e = c();
42
+ let e = b();
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
+ }, S = () => {
47
+ if (typeof navigator > "u" || x() !== "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
+ }, ne = (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
+ }), C = () => {
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
+ }, w = (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: b(),
88
+ engine: x(),
80
89
  platform: t?.platform ?? "",
81
90
  maxTouchPoints: t?.maxTouchPoints ?? 0,
82
91
  devicePixelRatio: n?.devicePixelRatio ?? 1,
@@ -91,175 +100,226 @@ 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: S(),
95
104
  observation: {
96
- longTasks: f(),
105
+ longTasks: C(),
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
+ }, T = [
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
+ ], E = "flemo:devtools-panel-height", D = [{
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: E,
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
+ }], O = [
107
130
  {
108
- key: "flemo:motion-driver",
109
- storage: "local",
131
+ key: "flemo:sixty",
132
+ storage: "session",
110
133
  kind: "production-state",
111
- description: "learned driver ledger ('css' = player demoted on this device, 'raf' = clean probe)"
134
+ values: "\"high\" / a streak count",
135
+ fallback: "(learned)",
136
+ effect: "steady-60 desktop verdict seed — owned by steadySixtyCadence.ts"
112
137
  },
113
138
  {
114
- key: "flemo:motion-driver-force",
139
+ key: "flemo:settle-gate",
115
140
  storage: "session",
116
- kind: "opt-in-diagnostic",
117
- description: "hard driver pin ('css@<epoch-ms>' / 'raf@<epoch-ms>', 24h TTL) — pins EVERY transition"
141
+ kind: "production-default-with-override",
142
+ values: "\"on\" / \"off\"",
143
+ fallback: "touch WebKit + touch Blink + desktop macOS WebKit + steady-60 desktop",
144
+ effect: "render-settle entry gate, shared by the engine's routing and the binding"
118
145
  },
119
146
  {
120
- key: "flemo:lpm",
147
+ key: "flemo:arrivalhold",
121
148
  storage: "session",
122
- kind: "production-state",
123
- description: "low-power-mode cadence seed (learned)"
149
+ kind: "production-default-with-override",
150
+ values: "\"off\"",
151
+ fallback: "on",
152
+ effect: "the whole in-flight hold set (arrival, response, invisible animations, images)"
124
153
  },
125
154
  {
126
- key: "flemo:sixty",
155
+ key: "flemo:deskflip",
127
156
  storage: "session",
128
- kind: "production-state",
129
- description: "steady-60 display verdict seed ('high' latches, a count seeds the streak)"
157
+ kind: "production-default-with-override",
158
+ values: "\"on\" / \"off\"",
159
+ fallback: "desktop macOS WebKit",
160
+ effect: "atomic release flip: the hold attribute flips on the DOM inside the readiness rAF"
130
161
  },
131
162
  {
132
- key: "flemo:lat",
163
+ key: "flemo:deskhead",
133
164
  storage: "session",
134
- kind: "production-state",
135
- description: "LPM release-latency seed (learned)"
165
+ kind: "production-default-with-override",
166
+ values: "\"on\" / \"off\"",
167
+ fallback: "desktop macOS WebKit",
168
+ effect: "desktop flat-head keyframes; arming it retires the desktop birth anchor"
136
169
  },
137
170
  {
138
- key: "flemo:landing-snap",
171
+ key: "flemo:creep",
139
172
  storage: "session",
140
- kind: "opt-in-diagnostic",
141
- description: "Blink landing pixel-snap easing A/B"
173
+ kind: "production-default-with-override",
174
+ values: "\"on\" / \"off\"",
175
+ fallback: "touch WebKit",
176
+ effect: "creep head: its end keyframe carries a hair of motion, so the compositor is already carrying the animation at the boundary"
142
177
  },
143
178
  {
144
- key: "flemo:imghold",
179
+ key: "flemo:relcommit",
145
180
  storage: "session",
146
- kind: "opt-in-diagnostic",
147
- description: "flight-scoped <img> reveal hold"
181
+ kind: "production-default-with-override",
182
+ values: "\"defer\" / \"sync\"",
183
+ fallback: "touch WebKit",
184
+ effect: "the release's reconcile lands next frame instead of synchronously"
148
185
  },
149
186
  {
150
- key: "flemo:settle-gate",
187
+ key: "flemo:imgoffload",
151
188
  storage: "session",
152
189
  kind: "production-default-with-override",
153
- description: "render-settle entry gate override"
190
+ values: "\"on\" / \"off\"",
191
+ fallback: "on — the offloader decides per image, from the source's own size",
192
+ effect: "image decode offloader: an oversized source is fetched and downscaled in a worker so its decode never lands in a paint"
154
193
  },
155
194
  {
156
- key: "flemo:handoff",
195
+ key: "flemo:governed",
157
196
  storage: "session",
158
- kind: "opt-in-diagnostic",
159
- description: "anchored-opening handoff (POP-scoped)"
197
+ kind: "production-default-with-override",
198
+ values: "\"on\" / \"off\"",
199
+ fallback: "legacy Android Blink (an old browser, not a slow device)",
200
+ effect: "the governed head kit on touch Blink — a flat head covering a compiled flight's opening. The auto-detection reads browser AGE, so a modern-but-weak phone falls through it; this is how such a device gets measured"
160
201
  },
161
202
  {
162
- key: "flemo:handoffms",
203
+ key: "flemo:imghold",
163
204
  storage: "session",
164
205
  kind: "opt-in-diagnostic",
165
- description: "handoff point override (ms)"
206
+ values: "\"on\" / \"off\"",
207
+ fallback: "off",
208
+ effect: "flight-scoped <img> reveal hold"
166
209
  },
167
210
  {
168
- key: "flemo:apply",
211
+ key: "flemo:preraster",
169
212
  storage: "session",
170
213
  kind: "opt-in-diagnostic",
171
- description: "force the scrub-WAAPI value-application tier"
214
+ values: "\"on\"",
215
+ fallback: "off",
216
+ effect: "REST-time scope promotion, and the park-over hold variant. Flight-time promotion is the engine's own stamp and needs no flag"
172
217
  },
173
218
  {
174
- key: "flemo:snap",
219
+ key: "flemo:layers",
175
220
  storage: "session",
176
- kind: "production-default-with-override",
177
- description: "player device-pixel snap policy override"
221
+ kind: "opt-in-diagnostic",
222
+ values: "\"resident\" / \"off\"",
223
+ fallback: "off",
224
+ effect: "keep screen layers resident at rest — a resident layer is a PERMANENT stacking context over the consumer's screen"
178
225
  },
179
226
  {
180
- key: "flemo:snapband",
227
+ key: "flemo:freeze",
181
228
  storage: "session",
182
229
  kind: "opt-in-diagnostic",
183
- description: "'hybrid' snap jitter-band width (device px)"
230
+ values: "\"shallow\"",
231
+ fallback: "off",
232
+ effect: "keep the direct prev screen live instead of freezing it"
233
+ }
234
+ ], k = [...O, ...D], A = [
235
+ {
236
+ key: "flemo:motion-driver",
237
+ storage: "local",
238
+ retiredWith: "the per-origin driver demotion ledger (2026-08-19)"
184
239
  },
185
240
  {
186
- key: "flemo:layers",
241
+ key: "flemo:motion-driver-force",
187
242
  storage: "session",
188
- kind: "opt-in-diagnostic",
189
- description: "resident screen layers at rest"
243
+ retiredWith: "the hard driver pin, with the rAF player (2026-08-22)"
190
244
  },
191
245
  {
192
- key: "flemo:freeze",
246
+ key: "flemo:landing-snap",
193
247
  storage: "session",
194
- kind: "opt-in-diagnostic",
195
- description: "keep the direct prev screen live"
248
+ retiredWith: "the integer-device-pixel landing snap, falsified on device (2026-08-22)"
196
249
  },
197
250
  {
198
- key: "flemo:preraster",
251
+ key: "flemo:handoff",
199
252
  storage: "session",
200
- kind: "opt-in-diagnostic",
201
- description: "promote the entering content layer through the hold"
253
+ retiredWith: "the player's anchored-opening handoff (2026-08-22)"
202
254
  },
203
255
  {
204
- key: "flemo:imgoffload",
256
+ key: "flemo:handoffms",
205
257
  storage: "session",
206
- kind: "production-default-with-override",
207
- description: "image decode offloader override"
258
+ retiredWith: "the player's anchored-opening handoff (2026-08-22)"
208
259
  },
209
260
  {
210
- key: "flemo:devtools",
261
+ key: "flemo:apply",
211
262
  storage: "session",
212
- kind: "opt-in-diagnostic",
213
- description: "arms this flight recorder in the playground (?devtools=on)"
263
+ retiredWith: "the scrub-WAAPI value-application tier (2026-08-22)"
264
+ },
265
+ {
266
+ key: "flemo:snap",
267
+ storage: "session",
268
+ retiredWith: "the player's device-pixel snap policy (2026-08-22)"
269
+ },
270
+ {
271
+ key: "flemo:snapband",
272
+ storage: "session",
273
+ retiredWith: "the player's device-pixel snap policy (2026-08-22)"
274
+ },
275
+ {
276
+ key: "flemo:lat",
277
+ storage: "session",
278
+ retiredWith: "the Low Power Mode release-latency probe (2026-08-22)"
214
279
  }
215
- ], g = "flemo:motion-driver-force", _ = `${g} (localStorage legacy location)`, v = (e) => {
280
+ ], j = "(retired the library no longer reads this)", M = (e) => {
216
281
  try {
217
282
  let t = e === "session" ? sessionStorage : localStorage;
218
283
  return t.length, t;
219
284
  } catch {
220
285
  return null;
221
286
  }
222
- }, y = (e, t) => {
287
+ }, N = (e, t) => {
223
288
  try {
224
289
  return e ? e.getItem(t) : null;
225
290
  } catch {
226
291
  return null;
227
292
  }
228
- }, b = new Set(h.map((e) => e.key)), x = () => {
229
- let e = {}, t = v("session"), n = v("local");
230
- for (let r of h) {
231
- let i = y(r.storage === "session" ? t : n, r.key);
293
+ }, re = new Set(k.map((e) => e.key)), ie = new Set(A.map((e) => e.key)), P = new Set(D.map((e) => e.key)), F = () => {
294
+ let e = {}, t = M("session"), n = M("local");
295
+ for (let r of k) {
296
+ let i = N(r.storage === "session" ? t : n, r.key);
232
297
  i !== null && (e[r.key] = i);
233
298
  }
234
- let r = y(n, g);
235
- r !== null && (e[_] = r);
299
+ for (let r of A) for (let [i, a] of [[t, "sessionStorage"], [n, "localStorage"]]) {
300
+ let t = N(i, r.key);
301
+ t !== null && (e[`${r.key} (${a}) ${j}`] = t);
302
+ }
236
303
  for (let [r, i] of [[t, "sessionStorage"], [n, "localStorage"]]) if (r) try {
237
304
  for (let t = 0; t < r.length; t += 1) {
238
305
  let n = r.key(t);
239
- !n || !n.startsWith("flemo:") || b.has(n) || (e[`${n} (${i}, unknown key)`] = r.getItem(n) ?? "");
306
+ !n || !n.startsWith("flemo:") || re.has(n) || ie.has(n) || (e[`${n} (${i}, unknown key)`] = r.getItem(n) ?? "");
240
307
  }
241
308
  } catch {}
242
309
  return e;
243
- }, S = (e) => {
310
+ }, ae = (e) => {
244
311
  let t = [];
245
312
  for (let [n, r] of Object.entries(e)) {
246
- if (n === g) {
247
- 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.`);
248
- continue;
249
- }
250
- if (n === _) {
251
- 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.`);
252
- continue;
253
- }
254
- if (n.startsWith(`${g} `)) {
255
- 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.`);
313
+ if (n.includes("(retired the library no longer reads this)")) {
314
+ let e = n.slice(0, n.indexOf(" (")), i = A.find((t) => t.key === e);
315
+ 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.`);
256
316
  continue;
257
317
  }
258
- let e = h.find((e) => n === e.key || n.startsWith(`${e.key} `));
259
- !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}).`));
318
+ let e = k.find((e) => n === e.key || n.startsWith(`${e.key} `));
319
+ !e || P.has(e.key) || (e.kind === "opt-in-diagnostic" ? t.push(`${n}=${r} — opt-in diagnostic active (${e.effect}); 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.effect}). Stock behavior here is ${e.fallback}.`));
260
320
  }
261
321
  return t;
262
- }, C = (e) => Math.round(e * 10) / 10, w = (e) => {
322
+ }, I = (e) => Math.round(e * 10) / 10, L = (e) => {
263
323
  if (e.length === 0) return {
264
324
  count: 0,
265
325
  medianGapMs: 0,
@@ -269,11 +329,11 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
269
329
  let t = [...e].sort((e, t) => e - t);
270
330
  return {
271
331
  count: e.length,
272
- medianGapMs: C(t[Math.floor(t.length / 2)]),
273
- maxGapMs: C(t[t.length - 1]),
332
+ medianGapMs: I(t[Math.floor(t.length / 2)]),
333
+ maxGapMs: I(t[t.length - 1]),
274
334
  over30Count: e.filter((e) => e >= 30).length
275
335
  };
276
- }, T = (e, t = []) => {
336
+ }, R = (e, t = []) => {
277
337
  let n = [...e, ...t];
278
338
  return {
279
339
  ...n.length === 0 ? {
@@ -284,21 +344,21 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
284
344
  let e = [...n].sort((e, t) => e - t);
285
345
  return {
286
346
  count: n.length,
287
- medianGapMs: C(e[Math.floor(e.length / 2)]),
288
- maxGapMs: C(e[e.length - 1])
347
+ medianGapMs: I(e[Math.floor(e.length / 2)]),
348
+ maxGapMs: I(e[e.length - 1])
289
349
  };
290
350
  })(),
291
- longGaps: n.filter((e) => e >= 30).map(C),
292
- held: w(e),
293
- released: w(t)
351
+ longGaps: n.filter((e) => e >= 30).map(I),
352
+ held: L(e),
353
+ released: L(t)
294
354
  };
295
- }, E = (e) => e.length === 0 ? null : {
296
- maxMs: C(Math.max(...e)),
355
+ }, oe = (e) => e.length === 0 ? null : {
356
+ maxMs: I(Math.max(...e)),
297
357
  over30Count: e.filter((e) => e >= 30).length
298
- }, D = (e) => {
358
+ }, z = (e) => {
299
359
  let t = e.playerSuppression || e.playerAdvance;
300
360
  return t && e.compiledAnimation ? "mixed" : t ? "player" : e.compiledAnimation ? "compiled" : "unknown";
301
- }, O = (e) => e === "PUSHING" ? "PUSH" : e === "POPPING" ? "POP" : e === "REPLACING" ? "REPLACE" : null, ee = (e) => {
361
+ }, se = (e) => e === "PUSHING" ? "PUSH" : e === "POPPING" ? "POP" : e === "REPLACING" ? "REPLACE" : null, ce = (e) => {
302
362
  let t = /^matrix3d\(([^)]+)\)$/.exec(e.trim());
303
363
  if (t) {
304
364
  let e = t[1].split(",").map((e) => Number(e.trim()));
@@ -310,23 +370,14 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
310
370
  return e.length === 6 && Number.isFinite(e[4]) ? e[4] : null;
311
371
  }
312
372
  return null;
313
- }, k = "2", A = /* @__PURE__ */ new Set([
314
- "PUSHING",
315
- "POPPING",
316
- "REPLACING"
317
- ]), j = /* @__PURE__ */ new Set([
318
- "true",
319
- "park",
320
- "park-under",
321
- "park-over"
322
- ]), 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 = {}) => {
323
- if (B) return B;
373
+ }, le = "2", B = new Set(_), V = new Set(v), ue = y(c), H = d, de = 2, fe = 2e3, pe = 2, me = 200, he = 1e3, U = (e) => Math.round(e * 10) / 10, ge = null, _e = () => window, ve = (e = {}) => {
374
+ if (ge) return ge;
324
375
  if (typeof window > "u" || typeof document > "u") return {
325
376
  detach: () => {},
326
377
  report: () => ({
327
378
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
328
379
  version: "2",
329
- environment: p({
380
+ environment: w({
330
381
  medianGapMs: null,
331
382
  sampleCount: 0
332
383
  }),
@@ -334,51 +385,47 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
334
385
  active: {},
335
386
  warnings: ["no DOM available — recorder ran inert"]
336
387
  },
337
- driverPolicy: {
338
- demotion: null,
339
- forcePin: null
340
- },
341
388
  flights: [],
342
389
  anomalies: [],
343
390
  blindSpots: [...s],
344
- judgingProtocol: [...m]
391
+ judgingProtocol: [...T]
345
392
  })
346
393
  };
347
- let n = e.maxFlights ?? 50, r = e.log ?? !1, i = e.installGlobal ?? !0, c = x(), l = {
394
+ let n = e.maxFlights ?? 50, r = e.log ?? !1, i = e.installGlobal ?? !0, c = F(), d = {
348
395
  medianGapMs: null,
349
396
  sampleCount: 0
350
397
  };
351
- d().then((e) => {
352
- l = e;
398
+ ne().then((e) => {
399
+ d = e;
353
400
  });
354
- let u = [], f = null;
401
+ let g = [], _ = null;
355
402
  try {
356
- typeof PerformanceObserver < "u" && PerformanceObserver.supportedEntryTypes?.includes("longtask") && (f = new PerformanceObserver((e) => {
357
- for (let t of e.getEntries()) u.push({
358
- startMs: z(t.startTime),
359
- durationMs: z(t.duration)
403
+ typeof PerformanceObserver < "u" && PerformanceObserver.supportedEntryTypes?.includes("longtask") && (_ = new PerformanceObserver((e) => {
404
+ for (let t of e.getEntries()) g.push({
405
+ startMs: U(t.startTime),
406
+ durationMs: U(t.duration)
360
407
  });
361
- u.length > ie && u.splice(0, u.length - ie);
362
- }), f.observe({
408
+ g.length > he && g.splice(0, g.length - he);
409
+ }), _.observe({
363
410
  type: "longtask",
364
411
  buffered: !0
365
412
  }));
366
413
  } catch {
367
- f = null;
414
+ _ = null;
368
415
  }
369
- 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) => {
370
- 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;
416
+ let v = [], te = 0, b = null, x = [], S = !1, C = !1, E = () => Array.from(document.querySelectorAll(ue)).filter((e) => B.has(e.getAttribute("data-flemo-status") ?? "")), D = (e) => {
417
+ let t = Array.from(document.querySelectorAll(y(h))).filter((e) => B.has(e.getAttribute("data-flemo-bar-status") ?? "") || e.getAttribute("data-flemo-bar-riding") === "true").length, n = Array.from(document.querySelectorAll(y(m))).filter((e) => B.has(e.getAttribute("data-flemo-status") ?? "")).length, r = Array.from(document.querySelectorAll(y(ee))).filter((e) => B.has(e.getAttribute("data-flemo-status") ?? "")).length;
371
418
  return {
372
419
  screens: e.length,
373
420
  bars: t,
374
421
  decorators: n,
375
422
  parts: r
376
423
  };
377
- }, ae = (e) => {
424
+ }, O = (e) => {
378
425
  let t = [];
379
426
  for (let n of e) for (let e of Array.from(n.querySelectorAll("img"))) t.push(e);
380
427
  return t;
381
- }, H = (e) => {
428
+ }, k = (e) => {
382
429
  let t = 0, n = 0;
383
430
  for (let r of e.imagesTracked) r.complete && (t += 1, e.imagesHeld.has(r) || (n += 1));
384
431
  return {
@@ -388,20 +435,20 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
388
435
  heldDuringFlight: e.imagesHeld.size,
389
436
  completedUnheld: n
390
437
  };
391
- }, U = (e) => {
392
- let t = v;
393
- if (!(!t || t.imagesTracked.size >= R)) for (let n of Array.from(e)) {
438
+ }, A = (e) => {
439
+ let t = b;
440
+ if (!(!t || t.imagesTracked.size >= me)) for (let n of Array.from(e)) {
394
441
  if (!(n instanceof Element) || !t.elements.some((e) => e === n || e.contains(n))) continue;
395
442
  let e = n instanceof HTMLImageElement ? [n] : Array.from(n.querySelectorAll("img"));
396
443
  for (let n of e) if (!(n.complete || t.imagesTracked.has(n))) {
397
- if (t.imagesTracked.size >= R) return;
444
+ if (t.imagesTracked.size >= me) return;
398
445
  t.imagesTracked.add(n), t.imagesAddedDuringFlight += 1;
399
446
  }
400
447
  }
401
- }, W = (e) => {
402
- for (let t of e.elements) for (let n of Array.from(t.querySelectorAll(`img[${L}]`))) e.imagesHeld.add(n);
403
- for (let t of e.imagesTracked) t.hasAttribute(L) && e.imagesHeld.add(t);
404
- }, G = (e, t) => {
448
+ }, j = (e) => {
449
+ for (let t of e.elements) for (let n of Array.from(t.querySelectorAll(`img[${f}]`))) e.imagesHeld.add(n);
450
+ for (let t of e.imagesTracked) t.hasAttribute("data-flemo-img-hold") && e.imagesHeld.add(t);
451
+ }, M = (e, t) => {
405
452
  e.releasedFrames += 1;
406
453
  let n = !1, r = !1;
407
454
  for (let t of e.elements) {
@@ -420,7 +467,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
420
467
  e.lastPose.get(t) !== r && (n = !0);
421
468
  }
422
469
  }
423
- if (!(e.releasedFrames < re)) {
470
+ if (!(e.releasedFrames < pe)) {
424
471
  if (n) {
425
472
  e.stallRunMs = 0;
426
473
  return;
@@ -431,7 +478,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
431
478
  }
432
479
  e.stalledFrames += 1, e.stallRunMs += t, e.stallRunMs > e.longestStallMs && (e.longestStallMs = e.stallRunMs);
433
480
  }
434
- }, K = (e) => {
481
+ }, N = (e) => {
435
482
  for (let t of e.elements) {
436
483
  let n = t.style, r = t.getAnimations, i = e.clocks.get(t);
437
484
  if (i !== void 0 && i.playState !== "finished") {
@@ -454,51 +501,51 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
454
501
  i !== void 0 && i !== r && (e.evidence.playerAdvance = !0), e.lastPose.set(t, r);
455
502
  }
456
503
  }
457
- }, q = (e) => e.elements.some((e) => {
458
- let t = e.getAttribute(P);
459
- return t !== null && j.has(t);
460
- }), J = () => {
461
- let e = v;
462
- if (!e || b) return;
504
+ }, re = (e) => e.elements.some((e) => {
505
+ let t = e.getAttribute(H);
506
+ return t !== null && V.has(t);
507
+ }), ie = () => {
508
+ let e = b;
509
+ if (!e || S) return;
463
510
  let t = performance.now();
464
- if (e.lastFrameAt !== null && e.heldGaps.length + e.releasedGaps.length < I) {
465
- let n = t - e.lastFrameAt, r = q(e);
466
- (r ? e.heldGaps : e.releasedGaps).push(n), r || (G(e, n), e.releasedFrames === 1 && W(e));
511
+ if (e.lastFrameAt !== null && e.heldGaps.length + e.releasedGaps.length < fe) {
512
+ let n = t - e.lastFrameAt, r = re(e);
513
+ (r ? e.heldGaps : e.releasedGaps).push(n), r || (M(e, n), e.releasedFrames === 1 && j(e));
467
514
  }
468
- if (e.lastFrameAt = t, K(e), t - e.t0Ms > 1e4) {
469
- y = [...e.elements], le(t, Y(e));
515
+ if (e.lastFrameAt = t, N(e), t - e.t0Ms > 1e4) {
516
+ x = [...e.elements], ye(t, P(e));
470
517
  return;
471
518
  }
472
- e.rafId = requestAnimationFrame(J);
473
- }, Y = (e) => {
519
+ e.rafId = requestAnimationFrame(ie);
520
+ }, P = (e) => {
474
521
  let t = /* @__PURE__ */ new Set();
475
522
  for (let n of e.elements) {
476
- let e = n.getAttribute(N) ?? "";
477
- A.has(e) && t.add(e);
523
+ let e = n.getAttribute("data-flemo-status") ?? "";
524
+ B.has(e) && t.add(e);
478
525
  }
479
526
  return [...t];
480
- }, X = (e) => {
527
+ }, I = (e) => {
481
528
  let t = performance.now();
482
- g += 1;
483
- let n = e.find((e) => e.getAttribute(te) === "true") ?? e[0], r = O(n.getAttribute(N) ?? "") ?? "PUSH", i = null;
529
+ te += 1;
530
+ let n = e.find((e) => e.getAttribute("data-flemo-active") === "true") ?? e[0], r = se(n.getAttribute("data-flemo-status") ?? "") ?? "PUSH", i = null;
484
531
  for (let t of e) {
485
- let e = t.getAttribute(P);
486
- if (e !== null && j.has(e)) {
532
+ let e = t.getAttribute(H);
533
+ if (e !== null && V.has(e)) {
487
534
  i = e;
488
535
  break;
489
536
  }
490
537
  }
491
- v = {
492
- id: `flight-${g}`,
538
+ b = {
539
+ id: `flight-${te}`,
493
540
  kind: r,
494
541
  routerId: n.getAttribute("data-flemo-router") ?? void 0,
495
542
  t0Ms: t,
496
543
  t0Iso: (/* @__PURE__ */ new Date()).toISOString(),
497
544
  elements: [...e],
498
- participants: k(e),
545
+ participants: D(e),
499
546
  holdKind: i,
500
547
  holdReleasedAtMs: null,
501
- playerGapStartIndex: V().__flemoPlayerGaps?.length ?? 0,
548
+ playerGapStartIndex: _e().__flemoPlayerGaps?.length ?? 0,
502
549
  heldGaps: [],
503
550
  releasedGaps: [],
504
551
  lastFrameAt: null,
@@ -517,32 +564,32 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
517
564
  longestStallMs: 0,
518
565
  pausedAfterRelease: !1,
519
566
  holdReassertedAtMs: null,
520
- imagesTracked: new Set(ae(e).filter((e) => !e.complete)),
567
+ imagesTracked: new Set(O(e).filter((e) => !e.complete)),
521
568
  imagesLoadingAtStart: 0,
522
569
  imagesAddedDuringFlight: 0,
523
570
  imagesHeld: /* @__PURE__ */ new Set(),
524
571
  rafId: null
525
- }, v.imagesLoadingAtStart = v.imagesTracked.size, K(v), v.rafId = requestAnimationFrame(J);
526
- }, oe = (e, t) => {
527
- let n = F, r = () => {
528
- if (!b) {
572
+ }, b.imagesLoadingAtStart = b.imagesTracked.size, N(b), b.rafId = requestAnimationFrame(ie);
573
+ }, L = (e, t) => {
574
+ let n = de, r = () => {
575
+ if (!S) {
529
576
  if (--n, n > 0) {
530
577
  requestAnimationFrame(r);
531
578
  return;
532
579
  }
533
- ce(e, t);
580
+ ve(e, t);
534
581
  }
535
582
  };
536
583
  requestAnimationFrame(r);
537
- }, se = () => {
538
- if (v !== null || w().length > 0) return [];
584
+ }, le = () => {
585
+ if (b !== null || E().length > 0) return [];
539
586
  let e = [];
540
- for (let [t, n] of [[L, "image reveal hold"], [ne, "arrival hold"]]) {
587
+ for (let [t, n] of [[f, "image reveal hold"], [p, "arrival hold"]]) {
541
588
  let r = document.querySelectorAll(`[${t}]`).length;
542
589
  r > 0 && e.push(`${r} × ${n} (${t}) still marked at rest`);
543
590
  }
544
591
  return e;
545
- }, ce = (e, t) => {
592
+ }, ve = (e, t) => {
546
593
  let n = [], r = !1, i = window.visualViewport?.width ?? window.innerWidth ?? 0;
547
594
  t.forEach((e, t) => {
548
595
  if (!(e instanceof HTMLElement) || !e.isConnected) return;
@@ -552,45 +599,45 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
552
599
  a = t.transform ?? "", o = t.display ?? "";
553
600
  } catch {}
554
601
  if (o === "none") return;
555
- let s = e.getAttribute(te) === "true", c = `screen[${t}]${s ? " (active)" : ""}`;
556
- 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) {
557
- let e = ee(a);
602
+ let s = e.getAttribute(u) === "true", c = `screen[${t}]${s ? " (active)" : ""}`;
603
+ 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) {
604
+ let e = ce(a);
558
605
  e !== null && Math.abs(e) >= i * .5 && (r = !0);
559
606
  }
560
- }), e.landing.residualInlineTransforms = n, e.landing.offViewportAtRest = r, e.landing.orphanedHolds = se();
561
- }, le = (e, t) => {
562
- let i = v;
607
+ }), e.landing.residualInlineTransforms = n, e.landing.offViewportAtRest = r, e.landing.orphanedHolds = le();
608
+ }, ye = (e, t) => {
609
+ let i = b;
563
610
  if (!i) return;
564
- W(i), v = null, i.rafId !== null && cancelAnimationFrame(i.rafId);
565
- let a = E((V().__flemoPlayerGaps ?? []).slice(i.playerGapStartIndex)), o = {
611
+ j(i), b = null, i.rafId !== null && cancelAnimationFrame(i.rafId);
612
+ let a = oe((_e().__flemoPlayerGaps ?? []).slice(i.playerGapStartIndex)), o = {
566
613
  id: i.id,
567
614
  ...i.routerId === void 0 ? {} : { routerId: i.routerId },
568
615
  kind: i.kind,
569
616
  t0: {
570
- ms: z(i.t0Ms),
617
+ ms: U(i.t0Ms),
571
618
  iso: i.t0Iso
572
619
  },
573
620
  t1: {
574
- ms: z(e),
621
+ ms: U(e),
575
622
  iso: (/* @__PURE__ */ new Date()).toISOString()
576
623
  },
577
- durationMs: z(e - i.t0Ms),
578
- driver: D(i.evidence),
624
+ durationMs: U(e - i.t0Ms),
625
+ driver: z(i.evidence),
579
626
  participants: i.participants,
580
627
  holds: {
581
628
  kind: i.holdKind,
582
629
  releasedAtMs: i.holdReleasedAtMs
583
630
  },
584
- frameSamples: T(i.heldGaps, i.releasedGaps),
631
+ frameSamples: R(i.heldGaps, i.releasedGaps),
585
632
  motion: {
586
633
  sampledFrames: i.releasedFrames,
587
634
  stalledFrames: i.stalledFrames,
588
- longestStallMs: z(i.longestStallMs),
635
+ longestStallMs: U(i.longestStallMs),
589
636
  pausedAfterRelease: i.pausedAfterRelease,
590
637
  holdReassertedAtMs: i.holdReassertedAtMs,
591
638
  tailFrames: i.tailFrames
592
639
  },
593
- images: H(i),
640
+ images: k(i),
594
641
  ...a ? { playerGaps: a } : {},
595
642
  longTasks: [],
596
643
  holdLongTasks: [],
@@ -602,34 +649,34 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
602
649
  },
603
650
  anomalies: []
604
651
  };
605
- 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}`);
606
- }, ue = (e) => {
607
- let t = v;
652
+ v.push(o), v.length > n && v.splice(0, v.length - n), t.length === 0 && L(o, i.elements), r && console.info(`[flemo devtools] ${o.id} ${o.kind} driver=${o.driver} ${o.durationMs}ms screens=${o.participants.screens}`);
653
+ }, W = (e) => {
654
+ let t = b;
608
655
  if (!t || !(e.target instanceof Element)) return;
609
- let n = e.target.getAttribute(P);
610
- 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));
611
- }, de = () => {
612
- let e = w();
613
- if (y.length > 0) {
614
- if (e.some((e) => y.includes(e))) return;
615
- y = [];
656
+ let n = e.target.getAttribute(H);
657
+ 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 && !re(t) && (t.holdReleasedAtMs = U(performance.now() - t.t0Ms));
658
+ }, be = () => {
659
+ let e = E();
660
+ if (x.length > 0) {
661
+ if (e.some((e) => x.includes(e))) return;
662
+ x = [];
616
663
  }
617
- if (!v && e.length > 0) {
618
- X(e);
664
+ if (!b && e.length > 0) {
665
+ I(e);
619
666
  return;
620
667
  }
621
- if (v && e.length === 0) {
622
- le(performance.now(), []);
668
+ if (b && e.length === 0) {
669
+ ye(performance.now(), []);
623
670
  return;
624
671
  }
625
- if (v) for (let t of e) v.elements.includes(t) || (v.elements.push(t), U(t.querySelectorAll("img")), v.participants = k(v.elements));
626
- }, Z = null, Q = null, $ = () => {
672
+ if (b) for (let t of e) b.elements.includes(t) || (b.elements.push(t), A(t.querySelectorAll("img")), b.participants = D(b.elements));
673
+ }, G = null, K = null, q = () => {
627
674
  let e = document.documentElement;
628
675
  if (!e) return !1;
629
676
  let t = new MutationObserver((e) => {
630
- if (!b) {
631
- for (let t of e) t.type === "attributes" && t.attributeName === P ? ue(t) : t.type === "childList" && t.addedNodes.length > 0 && U(t.addedNodes);
632
- de();
677
+ if (!S) {
678
+ for (let t of e) t.type === "attributes" && t.attributeName === H ? W(t) : t.type === "childList" && t.addedNodes.length > 0 && A(t.addedNodes);
679
+ be();
633
680
  }
634
681
  });
635
682
  try {
@@ -639,31 +686,31 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
639
686
  attributes: !0,
640
687
  attributeOldValue: !0,
641
688
  attributeFilter: [
642
- N,
643
- te,
644
- P
689
+ l,
690
+ u,
691
+ H
645
692
  ]
646
693
  });
647
694
  } catch {
648
695
  return !1;
649
696
  }
650
- return Z = t, de(), !0;
697
+ return G = t, be(), !0;
651
698
  };
652
- if (!$()) {
699
+ if (!q()) {
653
700
  let e = () => {
654
- Q = null, b || $();
701
+ K = null, S || q();
655
702
  };
656
- Q = e, document.addEventListener("DOMContentLoaded", e, { once: !0 });
703
+ K = e, document.addEventListener("DOMContentLoaded", e, { once: !0 });
657
704
  }
658
- let fe = (e) => {
659
- 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;
705
+ let J = (e) => {
706
+ let t = g.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;
660
707
  return {
661
708
  released: t.filter((e) => e.startMs + e.durationMs > n),
662
709
  held: t.filter((e) => e.startMs + e.durationMs <= n)
663
710
  };
664
- }, pe = () => {
665
- let e = performance.now(), n = h.map((e) => {
666
- let t = fe(e), n = {
711
+ }, Y = () => {
712
+ let e = performance.now(), n = v.map((e) => {
713
+ let t = J(e), n = {
667
714
  ...e,
668
715
  longTasks: t.released,
669
716
  holdLongTasks: t.held,
@@ -687,47 +734,47 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
687
734
  motion: n.motion,
688
735
  images: n.images
689
736
  }), n;
690
- }), r = v;
737
+ }), r = b;
691
738
  if (!r) return n;
692
739
  let i = e - r.t0Ms > t, o = {
693
740
  id: `${r.id} (in flight)`,
694
741
  ...r.routerId === void 0 ? {} : { routerId: r.routerId },
695
742
  kind: r.kind,
696
743
  t0: {
697
- ms: z(r.t0Ms),
744
+ ms: U(r.t0Ms),
698
745
  iso: r.t0Iso
699
746
  },
700
747
  t1: {
701
- ms: z(e),
748
+ ms: U(e),
702
749
  iso: (/* @__PURE__ */ new Date()).toISOString()
703
750
  },
704
- durationMs: z(e - r.t0Ms),
705
- driver: D(r.evidence),
751
+ durationMs: U(e - r.t0Ms),
752
+ driver: z(r.evidence),
706
753
  participants: r.participants,
707
754
  holds: {
708
755
  kind: r.holdKind,
709
756
  releasedAtMs: r.holdReleasedAtMs
710
757
  },
711
- frameSamples: T(r.heldGaps, r.releasedGaps),
758
+ frameSamples: R(r.heldGaps, r.releasedGaps),
712
759
  motion: {
713
760
  sampledFrames: r.releasedFrames,
714
761
  stalledFrames: r.stalledFrames,
715
- longestStallMs: z(r.longestStallMs),
762
+ longestStallMs: U(r.longestStallMs),
716
763
  pausedAfterRelease: r.pausedAfterRelease,
717
764
  holdReassertedAtMs: r.holdReassertedAtMs,
718
765
  tailFrames: r.tailFrames
719
766
  },
720
- images: H(r),
767
+ images: k(r),
721
768
  longTasks: [],
722
769
  holdLongTasks: [],
723
770
  landing: {
724
771
  residualInlineTransforms: [],
725
772
  offViewportAtRest: !1,
726
- stuckStatuses: i ? Y(r) : [],
773
+ stuckStatuses: i ? P(r) : [],
727
774
  orphanedHolds: []
728
775
  },
729
776
  anomalies: []
730
- }, s = fe(o);
777
+ }, s = J(o);
731
778
  return o.longTasks = s.released, o.holdLongTasks = s.held, o.anomalies = a({
732
779
  t0Ms: o.t0.ms,
733
780
  t1Ms: o.t1.ms,
@@ -741,16 +788,10 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
741
788
  motion: o.motion,
742
789
  images: o.images
743
790
  }), [...n, o];
744
- }, me = (e, t) => {
745
- try {
746
- return (e === "session" ? sessionStorage : localStorage).getItem(t);
747
- } catch {
748
- return null;
749
- }
750
- }, he = () => {
751
- let e = x(), t = { ...e };
791
+ }, X = () => {
792
+ let e = F(), t = { ...e };
752
793
  for (let [n, r] of Object.entries(c)) n in e || (t[`${n} (at attach, since cleared)`] = r);
753
- 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;
794
+ let n = ae(t), r = w(d), i = Y(), a = b;
754
795
  return {
755
796
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
756
797
  version: "2",
@@ -759,57 +800,50 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
759
800
  active: t,
760
801
  warnings: n
761
802
  },
762
- driverPolicy: {
763
- demotion: me("local", "flemo:motion-driver"),
764
- forcePin: i
765
- },
766
- flights: u,
803
+ flights: i,
767
804
  anomalies: o({
768
- forcePin: i,
769
- legacyLocalForcePin: t[_] ?? null,
770
- clearedForcePin: a,
771
805
  emulationSuspected: r.emulationSuspected,
772
806
  platform: r.platform,
773
- stuckFlightOpen: d !== null && performance.now() - d.t0Ms > 1e4,
774
- flightAnomalies: u.map((e) => e.anomalies)
807
+ stuckFlightOpen: a !== null && performance.now() - a.t0Ms > 1e4,
808
+ flightAnomalies: i.map((e) => e.anomalies)
775
809
  }),
776
810
  blindSpots: [...s],
777
- judgingProtocol: [...m]
811
+ judgingProtocol: [...T]
778
812
  };
779
- }, ge = () => {
780
- if (!b) {
781
- if (b = !0, Z?.disconnect(), Q !== null && (document.removeEventListener("DOMContentLoaded", Q), Q = null), f?.disconnect(), v?.rafId != null && cancelAnimationFrame(v.rafId), v = null, C) {
782
- let e = V();
813
+ }, xe = () => {
814
+ if (!S) {
815
+ if (S = !0, G?.disconnect(), K !== null && (document.removeEventListener("DOMContentLoaded", K), K = null), _?.disconnect(), b?.rafId != null && cancelAnimationFrame(b.rafId), b = null, C) {
816
+ let e = _e();
783
817
  e.flemo?.__flemoDevtools === !0 && delete e.flemo;
784
818
  }
785
- B = null;
819
+ ge = null;
786
820
  }
787
- }, _e = {
788
- detach: ge,
789
- report: he
821
+ }, Se = {
822
+ detach: xe,
823
+ report: X
790
824
  };
791
825
  if (i) {
792
- let e = V(), t = e.flemo;
826
+ let e = _e(), t = e.flemo;
793
827
  (t === void 0 || t?.__flemoDevtools === !0) && (e.flemo = {
794
828
  __flemoDevtools: !0,
795
- report: he,
796
- flights: pe,
797
- detach: ge
829
+ report: X,
830
+ flights: Y,
831
+ detach: xe
798
832
  }, C = !0);
799
833
  }
800
- return B = _e, _e;
801
- }, H = "http://www.w3.org/2000/svg", U = (e, t, n) => {
834
+ return ge = Se, Se;
835
+ }, ye = "http://www.w3.org/2000/svg", W = (e, t, n) => {
802
836
  let r = document.createElement(e);
803
837
  return t !== void 0 && (r.className = t), n !== void 0 && (r.textContent = n), r;
804
- }, W = (e, t) => {
805
- let n = document.createElementNS(H, e);
838
+ }, be = (e, t) => {
839
+ let n = document.createElementNS(ye, e);
806
840
  for (let [e, r] of Object.entries(t)) n.setAttribute(e, r);
807
841
  return n;
808
842
  }, G = (e) => {
809
843
  for (; e.firstChild !== null;) e.removeChild(e.firstChild);
810
844
  }, K = (e, t) => {
811
845
  e.textContent !== t && (e.textContent = t);
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) : "—", oe = (e) => e === !0 ? "yes" : e === !1 ? "no" : "—", se = (e) => {
846
+ }, 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) : "—", xe = (e) => e === !0 ? "yes" : e === !1 ? "no" : "—", Se = (e) => {
813
847
  let t = e?.environment;
814
848
  if (!t) return "—";
815
849
  let n = t.viewport, r = n && typeof n.width == "number" && typeof n.height == "number" ? `${Math.round(n.width)}×${Math.round(n.height)}` : "—";
@@ -819,36 +853,36 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
819
853
  r,
820
854
  `rAF ${Y(t.rafCadence?.medianGapMs)}`
821
855
  ].join(" · ");
822
- }, 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) => {
856
+ }, 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(",")}`, we = (e) => {
823
857
  let t = e?.released?.gaps;
824
858
  if (!Array.isArray(t)) return null;
825
859
  let n = t.filter((e) => typeof e == "number" && Number.isFinite(e));
826
860
  return n.length >= 2 ? n : null;
827
- }, 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) => {
828
- let i = U("div", "kv");
829
- i.appendChild(U("span", "k", t)), i.appendChild(U("span", r ? `v ${r}` : "v", n)), e.appendChild(i);
861
+ }, Te = "\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", Ee = 48, Z = (e, t, n, r) => {
862
+ let i = W("div", "kv");
863
+ i.appendChild(W("span", "k", t)), i.appendChild(W("span", r ? `v ${r}` : "v", n)), e.appendChild(i);
830
864
  }, Q = (e, t) => {
831
- let n = U("section", "section");
832
- return n.appendChild(U("h2", void 0, t)), e.appendChild(n), n;
865
+ let n = W("section", "section");
866
+ return n.appendChild(W("h2", void 0, t)), e.appendChild(n), n;
833
867
  }, $ = (e, t, n = "li") => {
834
- e.appendChild(U("div", n, t));
835
- }, fe = (e, t) => {
868
+ e.appendChild(W("div", n, t));
869
+ }, De = (e, t) => {
836
870
  G(e);
837
- for (let n of t?.overrides?.warnings ?? []) e.appendChild(U("span", "chip warn", q(n)));
838
- for (let n of t?.anomalies ?? []) e.appendChild(U("span", "chip bad", q(n)));
839
- for (let [n, r] of Object.entries(t?.overrides?.active ?? {})) e.appendChild(U("span", "chip", `${n}=${String(r)}`));
840
- }, pe = (e, t, n, r) => {
871
+ for (let n of t?.overrides?.warnings ?? []) e.appendChild(W("span", "chip warn", q(n)));
872
+ for (let n of t?.anomalies ?? []) e.appendChild(W("span", "chip bad", q(n)));
873
+ for (let [n, r] of Object.entries(t?.overrides?.active ?? {})) e.appendChild(W("span", "chip", `${n}=${String(r)}`));
874
+ }, Oe = (e, t, n, r) => {
841
875
  if (G(e), t.length === 0) {
842
876
  $(e, "no flights recorded yet — navigate once", "li dim");
843
877
  return;
844
878
  }
845
879
  for (let i = t.length - 1; i >= 0; --i) {
846
- let a = t[i], o = q(a?.id), s = U("button", "row");
847
- 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`));
880
+ let a = t[i], o = q(a?.id), s = W("button", "row");
881
+ 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`));
848
882
  let c = a?.anomalies?.length ?? 0;
849
- s.appendChild(U("span", c > 0 ? "n bad" : "n", String(c))), s.addEventListener("click", () => r(o)), e.appendChild(s);
883
+ s.appendChild(W("span", c > 0 ? "n bad" : "n", String(c))), s.addEventListener("click", () => r(o)), e.appendChild(s);
850
884
  }
851
- }, me = (e, t, n) => {
885
+ }, ke = (e, t, n) => {
852
886
  if (!n) {
853
887
  Z(e, t, "—");
854
888
  return;
@@ -859,21 +893,21 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
859
893
  `max ${Y(n.maxGapMs)}`
860
894
  ];
861
895
  typeof n.over30Count == "number" && r.push(`>30ms ×${n.over30Count}`), Z(e, t, r.join(" · "));
862
- }, he = (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 = W("svg", {
896
+ }, Ae = (e) => {
897
+ 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 = be("svg", {
864
898
  class: "spark",
865
899
  viewBox: "0 0 100 28",
866
900
  preserveAspectRatio: "none",
867
901
  "aria-hidden": "true"
868
902
  });
869
- return a.appendChild(W("polyline", {
903
+ return a.appendChild(be("polyline", {
870
904
  points: i,
871
905
  fill: "none",
872
906
  stroke: "currentColor",
873
907
  "stroke-width": "1",
874
908
  "vector-effect": "non-scaling-stroke"
875
909
  })), a;
876
- }, ge = (e, t) => {
910
+ }, je = (e, t) => {
877
911
  let n = t.longTasks ?? [], r = t.holdLongTasks ?? [];
878
912
  if (n.length === 0 && r.length === 0) {
879
913
  $(e, "none", "li dim");
@@ -882,7 +916,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
882
916
  let i = (e) => `${J(e?.startMs)} + ${J(e?.durationMs)}`;
883
917
  for (let t of n) $(e, i(t), "li bad");
884
918
  for (let t of r) $(e, `${i(t)} (absorbed by hold)`, "li dim");
885
- }, _e = (e, t) => {
919
+ }, Me = (e, t) => {
886
920
  if (G(e), !t) {
887
921
  $(e, "select a flight", "li dim");
888
922
  return;
@@ -890,174 +924,174 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
890
924
  let n = Q(e, "timing");
891
925
  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)}`);
892
926
  let r = Q(e, "frames");
893
- 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)}`);
894
- let i = le(t.frameSamples);
895
- i && r.appendChild(he(i));
927
+ ke(r, "held (absorbed)", t.frameSamples?.held), ke(r, "released (visible)", t.frameSamples?.released), t.playerGaps && Z(r, "player mirror", `max ${Y(t.playerGaps.maxMs)} · >30ms ×${X(t.playerGaps.over30Count)}`);
928
+ let i = we(t.frameSamples);
929
+ i && r.appendChild(Ae(i));
896
930
  let a = Q(e, "motion (did it move)"), o = t.motion?.longestStallMs, s = t.motion?.holdReassertedAtMs;
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) >= 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);
931
+ 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) >= Ee ? "bad" : void 0), Z(a, "paused after release", xe(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);
898
932
  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;
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), ge(Q(e, "long tasks"), t);
900
- let p = Q(e, "landing"), m = t.landing?.residualInlineTransforms ?? [];
901
- if (m.length === 0) Z(p, "inline residue", "clean");
902
- else for (let e of m) Z(p, "inline residue", q(e));
903
- Z(p, "off-viewport at rest", oe(t.landing?.offViewportAtRest));
904
- let h = t.landing?.stuckStatuses ?? [];
905
- Z(p, "stuck statuses", h.length === 0 ? "none" : h.join(", "));
906
- let g = t.landing?.orphanedHolds ?? [];
907
- if (g.length === 0) Z(p, "orphaned holds", "none");
908
- else for (let e of g) Z(p, "orphaned holds", q(e), "bad");
909
- let _ = Q(e, "anomalies"), v = t.anomalies ?? [];
910
- if (v.length === 0) {
911
- $(_, "none", "li dim");
933
+ 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), je(Q(e, "long tasks"), t);
934
+ let p = Q(e, "landing"), ee = t.landing?.residualInlineTransforms ?? [];
935
+ if (ee.length === 0) Z(p, "inline residue", "clean");
936
+ else for (let e of ee) Z(p, "inline residue", q(e));
937
+ Z(p, "off-viewport at rest", xe(t.landing?.offViewportAtRest));
938
+ let m = t.landing?.stuckStatuses ?? [];
939
+ Z(p, "stuck statuses", m.length === 0 ? "none" : m.join(", "));
940
+ let h = t.landing?.orphanedHolds ?? [];
941
+ if (h.length === 0) Z(p, "orphaned holds", "none");
942
+ else for (let e of h) Z(p, "orphaned holds", q(e), "bad");
943
+ let g = Q(e, "anomalies"), _ = t.anomalies ?? [];
944
+ if (_.length === 0) {
945
+ $(g, "none", "li dim");
912
946
  return;
913
947
  }
914
- for (let e of v) $(_, q(e), "li bad");
915
- }, ve = (e, t) => {
948
+ for (let e of _) $(g, q(e), "li bad");
949
+ }, Ne = (e, t) => {
916
950
  G(e);
917
951
  for (let n of t ?? []) $(e, q(n));
918
- }, 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 = {}) => {
919
- if (Ee) return Ee;
920
- if (typeof document > "u") return { detach: Te };
952
+ }, Pe = _.map((e) => y(c) + te(l, e)).join(","), Fe = 320, Ie = 2e3, Le = 120, Re = "Copy report JSON", ze = () => {}, Be = null, Ve = (e = {}) => {
953
+ if (Be) return Be;
954
+ if (typeof document > "u") return { detach: ze };
921
955
  let t = !1, n, r = window.flemo;
922
956
  e.recorder ? n = e.recorder : r?.__flemoDevtools === !0 && typeof r.report == "function" ? n = {
923
957
  report: r.report,
924
- detach: Te
925
- } : (n = ae(), t = !0);
926
- let i = U("div");
927
- 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";
928
- let a = i.attachShadow({ mode: "open" }), o = U("style");
929
- o.textContent = ue, a.appendChild(o);
930
- let s = U("div", "root");
958
+ detach: ze
959
+ } : (n = ve(), t = !0);
960
+ let i = W("div");
961
+ i.setAttribute(g, ""), i.style.position = "fixed", i.style.top = "0", i.style.left = "0", i.style.width = "0", i.style.height = "0", i.style.zIndex = "2147483000";
962
+ let a = i.attachShadow({ mode: "open" }), o = W("style");
963
+ o.textContent = Te, a.appendChild(o);
964
+ let s = W("div", "root");
931
965
  a.appendChild(s);
932
- let c = U("button", "toggle");
966
+ let c = W("button", "toggle");
933
967
  c.type = "button", c.setAttribute("data-corner", e.position ?? "bottom-right"), c.setAttribute("aria-label", "flemo devtools");
934
- let l = U("span", "count", "0"), u = U("span", "dot");
935
- u.hidden = !0, c.appendChild(U("span", "mark", "flemo")), c.appendChild(l), c.appendChild(u);
936
- let d = U("section", "panel");
968
+ let l = W("span", "count", "0"), u = W("span", "dot");
969
+ u.hidden = !0, c.appendChild(W("span", "mark", "flemo")), c.appendChild(l), c.appendChild(u);
970
+ let d = W("section", "panel");
937
971
  d.hidden = !0;
938
- let f = U("div", "grip");
972
+ let f = W("div", "grip");
939
973
  f.setAttribute("role", "separator"), f.setAttribute("aria-label", "Resize flemo devtools panel");
940
- let p = U("header", "head"), m = U("div", "env", "—"), h = U("button", "act", we);
974
+ let p = W("header", "head"), ee = W("div", "env", "—"), m = W("button", "act", Re);
975
+ m.type = "button";
976
+ let h = W("button", "act", "Close");
941
977
  h.type = "button";
942
- let g = U("button", "act", "Close");
943
- g.type = "button";
944
- let _ = U("button", "act", "Detach");
978
+ let _ = W("button", "act", "Detach");
945
979
  _.type = "button";
946
- let v = U("div", "chips");
947
- p.appendChild(m), p.appendChild(U("div", "spacer")), p.appendChild(h), p.appendChild(g), p.appendChild(_), p.appendChild(v);
948
- let y = U("div", "body"), b = U("div", "list"), x = U("div", "detail");
949
- y.appendChild(b), y.appendChild(x);
950
- let S = U("div", "foot"), C = U("details");
951
- C.appendChild(U("summary", void 0, "What this cannot see"));
952
- let w = U("div");
953
- C.appendChild(w), S.appendChild(C), d.appendChild(f), d.appendChild(p), d.appendChild(y), d.appendChild(S), s.appendChild(c), s.appendChild(d);
954
- 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 = () => {
980
+ let v = W("div", "chips");
981
+ p.appendChild(ee), p.appendChild(W("div", "spacer")), p.appendChild(m), p.appendChild(h), p.appendChild(_), p.appendChild(v);
982
+ let y = W("div", "body"), te = W("div", "list"), b = W("div", "detail");
983
+ y.appendChild(te), y.appendChild(b);
984
+ let x = W("div", "foot"), S = W("details");
985
+ S.appendChild(W("summary", void 0, "What this cannot see"));
986
+ let ne = W("div");
987
+ S.appendChild(ne), x.appendChild(S), d.appendChild(f), d.appendChild(p), d.appendChild(y), d.appendChild(x), s.appendChild(c), s.appendChild(d);
988
+ let C = !1, w = e.initialOpen === !0, T = null, D = "", O = "", k = "", A = !1, j = 0, M = 0, N = (e) => Math.min(Math.max(e, Le), Math.max(Le, window.innerHeight * .9)), re = () => {
955
989
  try {
956
- let e = sessionStorage.getItem(be);
990
+ let e = sessionStorage.getItem(E);
957
991
  if (e === null) return null;
958
992
  let t = Number.parseFloat(e);
959
993
  return Number.isFinite(t) ? t : null;
960
994
  } catch {
961
995
  return null;
962
996
  }
963
- }, P = (e) => {
997
+ }, ie = (e) => {
964
998
  try {
965
- sessionStorage.setItem(be, String(Math.round(e)));
999
+ sessionStorage.setItem(E, String(Math.round(e)));
966
1000
  } catch {}
967
- }, F = N(te() ?? window.innerHeight * .4);
968
- d.style.height = `${Math.round(F)}px`;
969
- let I = () => document.querySelector(ye) !== null, L = () => {
1001
+ }, P = N(re() ?? window.innerHeight * .4);
1002
+ d.style.height = `${Math.round(P)}px`;
1003
+ let F = () => document.querySelector(Pe) !== null, ae = () => {
970
1004
  try {
971
1005
  return n.report();
972
1006
  } catch {
973
1007
  return null;
974
1008
  }
975
- }, ne = (e) => {
976
- e !== D && (D = e, R());
977
- }, re = () => {
978
- let e = L(), t = e?.flights ?? [];
1009
+ }, I = (e) => {
1010
+ e !== T && (T = e, R());
1011
+ }, L = () => {
1012
+ let e = ae(), t = e?.flights ?? [];
979
1013
  K(l, String(t.length));
980
1014
  let n = t.some((e) => (e?.anomalies?.length ?? 0) > 0);
981
- if (u.hidden = !n, d.hidden = !E, !E) return;
982
- K(m, se(e));
1015
+ if (u.hidden = !n, d.hidden = !w, !w) return;
1016
+ K(ee, Se(e));
983
1017
  let r = JSON.stringify([
984
1018
  e?.overrides?.warnings ?? [],
985
1019
  e?.anomalies ?? [],
986
1020
  e?.overrides?.active ?? {}
987
1021
  ]);
988
- r !== k && (k = r, fe(v, e)), D === null && t.length > 0 && (D = t[t.length - 1]?.id ?? null);
989
- let i = ce(t, D);
990
- i !== O && (O = i, pe(b, t, D, ne));
991
- let a = t.find((e) => e?.id === D) ?? null, o = JSON.stringify(a);
992
- o !== ee && (ee = o, _e(x, a)), A || (A = !0, ve(w, e?.blindSpots));
1022
+ r !== k && (k = r, De(v, e)), T === null && t.length > 0 && (T = t[t.length - 1]?.id ?? null);
1023
+ let i = Ce(t, T);
1024
+ i !== D && (D = i, Oe(te, t, T, I));
1025
+ let a = t.find((e) => e?.id === T) ?? null, o = JSON.stringify(a);
1026
+ o !== O && (O = o, Me(b, a)), A || (A = !0, Ne(ne, e?.blindSpots));
993
1027
  };
994
1028
  function R() {
995
- T || I() || re();
1029
+ C || F() || L();
996
1030
  }
997
- function ie() {
1031
+ function oe() {
998
1032
  j = 0, R(), z();
999
1033
  }
1000
1034
  function z() {
1001
- j = window.setTimeout(ie, E ? xe : Se);
1035
+ j = window.setTimeout(oe, w ? Fe : Ie);
1002
1036
  }
1003
- let B = () => {
1037
+ let se = () => {
1004
1038
  window.clearTimeout(j), z();
1005
- }, V = (e) => {
1006
- E = e, B(), R();
1039
+ }, ce = (e) => {
1040
+ w = e, se(), R();
1007
1041
  };
1008
- c.addEventListener("click", () => V(!E)), g.addEventListener("click", () => V(!1)), _.addEventListener("click", () => Y());
1009
- let H = () => {
1010
- if (!T) {
1011
- if (I()) {
1012
- window.clearTimeout(M), M = window.setTimeout(H, xe);
1042
+ c.addEventListener("click", () => ce(!w)), h.addEventListener("click", () => ce(!1)), _.addEventListener("click", () => de());
1043
+ let le = () => {
1044
+ if (!C) {
1045
+ if (F()) {
1046
+ window.clearTimeout(M), M = window.setTimeout(le, Fe);
1013
1047
  return;
1014
1048
  }
1015
- K(h, "Copied ✓"), window.clearTimeout(M), M = window.setTimeout(W, 1200);
1049
+ K(m, "Copied ✓"), window.clearTimeout(M), M = window.setTimeout(B, 1200);
1016
1050
  }
1017
1051
  };
1018
- function W() {
1019
- if (I()) {
1020
- M = window.setTimeout(W, xe);
1052
+ function B() {
1053
+ if (F()) {
1054
+ M = window.setTimeout(B, Fe);
1021
1055
  return;
1022
1056
  }
1023
- M = 0, K(h, we);
1057
+ M = 0, K(m, Re);
1024
1058
  }
1025
- let G = (e) => {
1026
- if (T) return;
1027
- if (I()) {
1028
- window.clearTimeout(M), M = window.setTimeout(() => G(e), xe);
1059
+ let V = (e) => {
1060
+ if (C) return;
1061
+ if (F()) {
1062
+ window.clearTimeout(M), M = window.setTimeout(() => V(e), Fe);
1029
1063
  return;
1030
1064
  }
1031
- let t = U("textarea");
1065
+ let t = W("textarea");
1032
1066
  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();
1033
1067
  let n = document;
1034
1068
  try {
1035
1069
  n.execCommand?.("copy");
1036
1070
  } catch {}
1037
- t.remove(), H();
1071
+ t.remove(), le();
1038
1072
  };
1039
- h.addEventListener("click", () => {
1040
- let e = JSON.stringify(L(), null, 2), t = navigator.clipboard;
1073
+ m.addEventListener("click", () => {
1074
+ let e = JSON.stringify(ae(), null, 2), t = navigator.clipboard;
1041
1075
  if (t && typeof t.writeText == "function") {
1042
- t.writeText(e).then(H, () => G(e));
1076
+ t.writeText(e).then(le, () => V(e));
1043
1077
  return;
1044
1078
  }
1045
- G(e);
1079
+ V(e);
1046
1080
  });
1047
- let q = (e) => {
1048
- F = N(window.innerHeight - e.clientY), d.style.height = `${Math.round(F)}px`;
1049
- }, J = () => {
1050
- window.removeEventListener("pointermove", q), window.removeEventListener("pointerup", J), P(F);
1081
+ let ue = (e) => {
1082
+ P = N(window.innerHeight - e.clientY), d.style.height = `${Math.round(P)}px`;
1083
+ }, H = () => {
1084
+ window.removeEventListener("pointermove", ue), window.removeEventListener("pointerup", H), ie(P);
1051
1085
  };
1052
1086
  f.addEventListener("pointerdown", (e) => {
1053
- e.preventDefault(), window.addEventListener("pointermove", q), window.addEventListener("pointerup", J);
1087
+ e.preventDefault(), window.addEventListener("pointermove", ue), window.addEventListener("pointerup", H);
1054
1088
  });
1055
- function Y() {
1056
- 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);
1089
+ function de() {
1090
+ C || (C = !0, window.clearTimeout(j), j = 0, window.clearTimeout(M), M = 0, window.removeEventListener("pointermove", ue), window.removeEventListener("pointerup", H), i.remove(), t && n.detach(), Be = null);
1057
1091
  }
1058
1092
  document.body.appendChild(i), R(), z();
1059
- let X = { detach: Y };
1060
- return Ee = X, X;
1093
+ let fe = { detach: de };
1094
+ return Be = fe, fe;
1061
1095
  };
1062
1096
  //#endregion
1063
- 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 };
1097
+ export { s as BLIND_SPOTS, O as CORE_FLAGS, D as DEVTOOLS_OWNED_FLAGS, k 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, E as PANEL_HEIGHT_KEY, le as REPORT_SCHEMA_VERSION, A as RETIRED_FLAGS, j as RETIRED_MARKER, t as STUCK_STATUS_MS, Ve as attachDevtoolsPanel, ve as attachFlightRecorder, w as captureEnvironment, z as classifyDriver, R as computeFrameStats, L as computePhaseStats, oe as computePlayerGapStats, a as deriveFlightAnomalies, ae as deriveOverrideWarnings, o as deriveReportAnomalies, x as detectEngine, S as isEmulationSuspected, se as kindFromStatus, ce as parseTranslateX, ne as sampleRafCadence, F as snapshotOverrides };