@flemo/devtools 0.2.2 → 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,169 +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:sixty",
147
+ key: "flemo:arrivalhold",
121
148
  storage: "session",
122
- kind: "production-state",
123
- description: "steady-60 display verdict seed ('high' latches, a count seeds the streak)"
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:lat",
155
+ key: "flemo:deskflip",
127
156
  storage: "session",
128
- kind: "production-state",
129
- description: "LPM release-latency seed (learned)"
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:landing-snap",
163
+ key: "flemo:deskhead",
133
164
  storage: "session",
134
- kind: "opt-in-diagnostic",
135
- description: "Blink landing pixel-snap easing A/B"
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:imghold",
171
+ key: "flemo:creep",
139
172
  storage: "session",
140
- kind: "opt-in-diagnostic",
141
- description: "flight-scoped <img> reveal hold"
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:settle-gate",
179
+ key: "flemo:relcommit",
145
180
  storage: "session",
146
181
  kind: "production-default-with-override",
147
- description: "render-settle entry gate 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:handoff",
187
+ key: "flemo:imgoffload",
151
188
  storage: "session",
152
- kind: "opt-in-diagnostic",
153
- description: "anchored-opening handoff (POP-scoped)"
189
+ kind: "production-default-with-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:handoffms",
195
+ key: "flemo:governed",
157
196
  storage: "session",
158
- kind: "opt-in-diagnostic",
159
- description: "handoff point override (ms)"
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:apply",
203
+ key: "flemo:imghold",
163
204
  storage: "session",
164
205
  kind: "opt-in-diagnostic",
165
- description: "force the scrub-WAAPI value-application tier"
206
+ values: "\"on\" / \"off\"",
207
+ fallback: "off",
208
+ effect: "flight-scoped <img> reveal hold"
166
209
  },
167
210
  {
168
- key: "flemo:snap",
169
- storage: "session",
170
- kind: "production-default-with-override",
171
- description: "player device-pixel snap policy override"
172
- },
173
- {
174
- key: "flemo:snapband",
211
+ key: "flemo:preraster",
175
212
  storage: "session",
176
213
  kind: "opt-in-diagnostic",
177
- description: "'hybrid' snap jitter-band width (device px)"
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"
178
217
  },
179
218
  {
180
219
  key: "flemo:layers",
181
220
  storage: "session",
182
221
  kind: "opt-in-diagnostic",
183
- description: "resident screen layers at rest"
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"
184
225
  },
185
226
  {
186
227
  key: "flemo:freeze",
187
228
  storage: "session",
188
229
  kind: "opt-in-diagnostic",
189
- description: "keep the direct prev screen live"
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)"
190
239
  },
191
240
  {
192
- key: "flemo:preraster",
241
+ key: "flemo:motion-driver-force",
193
242
  storage: "session",
194
- kind: "opt-in-diagnostic",
195
- description: "promote the entering content layer through the hold"
243
+ retiredWith: "the hard driver pin, with the rAF player (2026-08-22)"
196
244
  },
197
245
  {
198
- key: "flemo:imgoffload",
246
+ key: "flemo:landing-snap",
199
247
  storage: "session",
200
- kind: "production-default-with-override",
201
- description: "image decode offloader override"
248
+ retiredWith: "the integer-device-pixel landing snap, falsified on device (2026-08-22)"
202
249
  },
203
250
  {
204
- key: "flemo:devtools",
251
+ key: "flemo:handoff",
205
252
  storage: "session",
206
- kind: "opt-in-diagnostic",
207
- description: "arms this flight recorder in the playground (?devtools=on)"
253
+ retiredWith: "the player's anchored-opening handoff (2026-08-22)"
254
+ },
255
+ {
256
+ key: "flemo:handoffms",
257
+ storage: "session",
258
+ retiredWith: "the player's anchored-opening handoff (2026-08-22)"
259
+ },
260
+ {
261
+ key: "flemo:apply",
262
+ storage: "session",
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)"
208
279
  }
209
- ], g = "flemo:motion-driver-force", _ = `${g} (localStorage legacy location)`, v = (e) => {
280
+ ], j = "(retired the library no longer reads this)", M = (e) => {
210
281
  try {
211
282
  let t = e === "session" ? sessionStorage : localStorage;
212
283
  return t.length, t;
213
284
  } catch {
214
285
  return null;
215
286
  }
216
- }, y = (e, t) => {
287
+ }, N = (e, t) => {
217
288
  try {
218
289
  return e ? e.getItem(t) : null;
219
290
  } catch {
220
291
  return null;
221
292
  }
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);
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);
226
297
  i !== null && (e[r.key] = i);
227
298
  }
228
- let r = y(n, g);
229
- 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
+ }
230
303
  for (let [r, i] of [[t, "sessionStorage"], [n, "localStorage"]]) if (r) try {
231
304
  for (let t = 0; t < r.length; t += 1) {
232
305
  let n = r.key(t);
233
- !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) ?? "");
234
307
  }
235
308
  } catch {}
236
309
  return e;
237
- }, S = (e) => {
310
+ }, ae = (e) => {
238
311
  let t = [];
239
312
  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.`);
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.`);
250
316
  continue;
251
317
  }
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}).`));
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}.`));
254
320
  }
255
321
  return t;
256
- }, C = (e) => Math.round(e * 10) / 10, w = (e) => {
322
+ }, I = (e) => Math.round(e * 10) / 10, L = (e) => {
257
323
  if (e.length === 0) return {
258
324
  count: 0,
259
325
  medianGapMs: 0,
@@ -263,11 +329,11 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
263
329
  let t = [...e].sort((e, t) => e - t);
264
330
  return {
265
331
  count: e.length,
266
- medianGapMs: C(t[Math.floor(t.length / 2)]),
267
- maxGapMs: C(t[t.length - 1]),
332
+ medianGapMs: I(t[Math.floor(t.length / 2)]),
333
+ maxGapMs: I(t[t.length - 1]),
268
334
  over30Count: e.filter((e) => e >= 30).length
269
335
  };
270
- }, T = (e, t = []) => {
336
+ }, R = (e, t = []) => {
271
337
  let n = [...e, ...t];
272
338
  return {
273
339
  ...n.length === 0 ? {
@@ -278,21 +344,21 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
278
344
  let e = [...n].sort((e, t) => e - t);
279
345
  return {
280
346
  count: n.length,
281
- medianGapMs: C(e[Math.floor(e.length / 2)]),
282
- maxGapMs: C(e[e.length - 1])
347
+ medianGapMs: I(e[Math.floor(e.length / 2)]),
348
+ maxGapMs: I(e[e.length - 1])
283
349
  };
284
350
  })(),
285
- longGaps: n.filter((e) => e >= 30).map(C),
286
- held: w(e),
287
- released: w(t)
351
+ longGaps: n.filter((e) => e >= 30).map(I),
352
+ held: L(e),
353
+ released: L(t)
288
354
  };
289
- }, E = (e) => e.length === 0 ? null : {
290
- maxMs: C(Math.max(...e)),
355
+ }, oe = (e) => e.length === 0 ? null : {
356
+ maxMs: I(Math.max(...e)),
291
357
  over30Count: e.filter((e) => e >= 30).length
292
- }, D = (e) => {
358
+ }, z = (e) => {
293
359
  let t = e.playerSuppression || e.playerAdvance;
294
360
  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) => {
361
+ }, se = (e) => e === "PUSHING" ? "PUSH" : e === "POPPING" ? "POP" : e === "REPLACING" ? "REPLACE" : null, ce = (e) => {
296
362
  let t = /^matrix3d\(([^)]+)\)$/.exec(e.trim());
297
363
  if (t) {
298
364
  let e = t[1].split(",").map((e) => Number(e.trim()));
@@ -304,23 +370,14 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
304
370
  return e.length === 6 && Number.isFinite(e[4]) ? e[4] : null;
305
371
  }
306
372
  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;
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;
318
375
  if (typeof window > "u" || typeof document > "u") return {
319
376
  detach: () => {},
320
377
  report: () => ({
321
378
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
322
379
  version: "2",
323
- environment: p({
380
+ environment: w({
324
381
  medianGapMs: null,
325
382
  sampleCount: 0
326
383
  }),
@@ -328,51 +385,47 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
328
385
  active: {},
329
386
  warnings: ["no DOM available — recorder ran inert"]
330
387
  },
331
- driverPolicy: {
332
- demotion: null,
333
- forcePin: null
334
- },
335
388
  flights: [],
336
389
  anomalies: [],
337
390
  blindSpots: [...s],
338
- judgingProtocol: [...m]
391
+ judgingProtocol: [...T]
339
392
  })
340
393
  };
341
- 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 = {
342
395
  medianGapMs: null,
343
396
  sampleCount: 0
344
397
  };
345
- d().then((e) => {
346
- l = e;
398
+ ne().then((e) => {
399
+ d = e;
347
400
  });
348
- let u = [], f = null;
401
+ let g = [], _ = null;
349
402
  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)
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)
354
407
  });
355
- u.length > ie && u.splice(0, u.length - ie);
356
- }), f.observe({
408
+ g.length > he && g.splice(0, g.length - he);
409
+ }), _.observe({
357
410
  type: "longtask",
358
411
  buffered: !0
359
412
  }));
360
413
  } catch {
361
- f = null;
414
+ _ = null;
362
415
  }
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;
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;
365
418
  return {
366
419
  screens: e.length,
367
420
  bars: t,
368
421
  decorators: n,
369
422
  parts: r
370
423
  };
371
- }, ae = (e) => {
424
+ }, O = (e) => {
372
425
  let t = [];
373
426
  for (let n of e) for (let e of Array.from(n.querySelectorAll("img"))) t.push(e);
374
427
  return t;
375
- }, H = (e) => {
428
+ }, k = (e) => {
376
429
  let t = 0, n = 0;
377
430
  for (let r of e.imagesTracked) r.complete && (t += 1, e.imagesHeld.has(r) || (n += 1));
378
431
  return {
@@ -382,20 +435,20 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
382
435
  heldDuringFlight: e.imagesHeld.size,
383
436
  completedUnheld: n
384
437
  };
385
- }, U = (e) => {
386
- let t = v;
387
- 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)) {
388
441
  if (!(n instanceof Element) || !t.elements.some((e) => e === n || e.contains(n))) continue;
389
442
  let e = n instanceof HTMLImageElement ? [n] : Array.from(n.querySelectorAll("img"));
390
443
  for (let n of e) if (!(n.complete || t.imagesTracked.has(n))) {
391
- if (t.imagesTracked.size >= R) return;
444
+ if (t.imagesTracked.size >= me) return;
392
445
  t.imagesTracked.add(n), t.imagesAddedDuringFlight += 1;
393
446
  }
394
447
  }
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) => {
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) => {
399
452
  e.releasedFrames += 1;
400
453
  let n = !1, r = !1;
401
454
  for (let t of e.elements) {
@@ -414,7 +467,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
414
467
  e.lastPose.get(t) !== r && (n = !0);
415
468
  }
416
469
  }
417
- if (!(e.releasedFrames < re)) {
470
+ if (!(e.releasedFrames < pe)) {
418
471
  if (n) {
419
472
  e.stallRunMs = 0;
420
473
  return;
@@ -425,7 +478,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
425
478
  }
426
479
  e.stalledFrames += 1, e.stallRunMs += t, e.stallRunMs > e.longestStallMs && (e.longestStallMs = e.stallRunMs);
427
480
  }
428
- }, K = (e) => {
481
+ }, N = (e) => {
429
482
  for (let t of e.elements) {
430
483
  let n = t.style, r = t.getAnimations, i = e.clocks.get(t);
431
484
  if (i !== void 0 && i.playState !== "finished") {
@@ -448,51 +501,51 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
448
501
  i !== void 0 && i !== r && (e.evidence.playerAdvance = !0), e.lastPose.set(t, r);
449
502
  }
450
503
  }
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;
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;
457
510
  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));
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));
461
514
  }
462
- if (e.lastFrameAt = t, K(e), t - e.t0Ms > 1e4) {
463
- 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));
464
517
  return;
465
518
  }
466
- e.rafId = requestAnimationFrame(J);
467
- }, Y = (e) => {
519
+ e.rafId = requestAnimationFrame(ie);
520
+ }, P = (e) => {
468
521
  let t = /* @__PURE__ */ new Set();
469
522
  for (let n of e.elements) {
470
- let e = n.getAttribute(N) ?? "";
471
- A.has(e) && t.add(e);
523
+ let e = n.getAttribute("data-flemo-status") ?? "";
524
+ B.has(e) && t.add(e);
472
525
  }
473
526
  return [...t];
474
- }, X = (e) => {
527
+ }, I = (e) => {
475
528
  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;
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;
478
531
  for (let t of e) {
479
- let e = t.getAttribute(P);
480
- if (e !== null && j.has(e)) {
532
+ let e = t.getAttribute(H);
533
+ if (e !== null && V.has(e)) {
481
534
  i = e;
482
535
  break;
483
536
  }
484
537
  }
485
- v = {
486
- id: `flight-${g}`,
538
+ b = {
539
+ id: `flight-${te}`,
487
540
  kind: r,
488
541
  routerId: n.getAttribute("data-flemo-router") ?? void 0,
489
542
  t0Ms: t,
490
543
  t0Iso: (/* @__PURE__ */ new Date()).toISOString(),
491
544
  elements: [...e],
492
- participants: k(e),
545
+ participants: D(e),
493
546
  holdKind: i,
494
547
  holdReleasedAtMs: null,
495
- playerGapStartIndex: V().__flemoPlayerGaps?.length ?? 0,
548
+ playerGapStartIndex: _e().__flemoPlayerGaps?.length ?? 0,
496
549
  heldGaps: [],
497
550
  releasedGaps: [],
498
551
  lastFrameAt: null,
@@ -511,32 +564,32 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
511
564
  longestStallMs: 0,
512
565
  pausedAfterRelease: !1,
513
566
  holdReassertedAtMs: null,
514
- imagesTracked: new Set(ae(e).filter((e) => !e.complete)),
567
+ imagesTracked: new Set(O(e).filter((e) => !e.complete)),
515
568
  imagesLoadingAtStart: 0,
516
569
  imagesAddedDuringFlight: 0,
517
570
  imagesHeld: /* @__PURE__ */ new Set(),
518
571
  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) {
572
+ }, b.imagesLoadingAtStart = b.imagesTracked.size, N(b), b.rafId = requestAnimationFrame(ie);
573
+ }, L = (e, t) => {
574
+ let n = de, r = () => {
575
+ if (!S) {
523
576
  if (--n, n > 0) {
524
577
  requestAnimationFrame(r);
525
578
  return;
526
579
  }
527
- ce(e, t);
580
+ ve(e, t);
528
581
  }
529
582
  };
530
583
  requestAnimationFrame(r);
531
- }, se = () => {
532
- if (v !== null || w().length > 0) return [];
584
+ }, le = () => {
585
+ if (b !== null || E().length > 0) return [];
533
586
  let e = [];
534
- 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"]]) {
535
588
  let r = document.querySelectorAll(`[${t}]`).length;
536
589
  r > 0 && e.push(`${r} × ${n} (${t}) still marked at rest`);
537
590
  }
538
591
  return e;
539
- }, ce = (e, t) => {
592
+ }, ve = (e, t) => {
540
593
  let n = [], r = !1, i = window.visualViewport?.width ?? window.innerWidth ?? 0;
541
594
  t.forEach((e, t) => {
542
595
  if (!(e instanceof HTMLElement) || !e.isConnected) return;
@@ -546,45 +599,45 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
546
599
  a = t.transform ?? "", o = t.display ?? "";
547
600
  } catch {}
548
601
  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);
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);
552
605
  e !== null && Math.abs(e) >= i * .5 && (r = !0);
553
606
  }
554
- }), e.landing.residualInlineTransforms = n, e.landing.offViewportAtRest = r, e.landing.orphanedHolds = se();
555
- }, le = (e, t) => {
556
- let i = v;
607
+ }), e.landing.residualInlineTransforms = n, e.landing.offViewportAtRest = r, e.landing.orphanedHolds = le();
608
+ }, ye = (e, t) => {
609
+ let i = b;
557
610
  if (!i) return;
558
- W(i), v = null, i.rafId !== null && cancelAnimationFrame(i.rafId);
559
- 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 = {
560
613
  id: i.id,
561
614
  ...i.routerId === void 0 ? {} : { routerId: i.routerId },
562
615
  kind: i.kind,
563
616
  t0: {
564
- ms: z(i.t0Ms),
617
+ ms: U(i.t0Ms),
565
618
  iso: i.t0Iso
566
619
  },
567
620
  t1: {
568
- ms: z(e),
621
+ ms: U(e),
569
622
  iso: (/* @__PURE__ */ new Date()).toISOString()
570
623
  },
571
- durationMs: z(e - i.t0Ms),
572
- driver: D(i.evidence),
624
+ durationMs: U(e - i.t0Ms),
625
+ driver: z(i.evidence),
573
626
  participants: i.participants,
574
627
  holds: {
575
628
  kind: i.holdKind,
576
629
  releasedAtMs: i.holdReleasedAtMs
577
630
  },
578
- frameSamples: T(i.heldGaps, i.releasedGaps),
631
+ frameSamples: R(i.heldGaps, i.releasedGaps),
579
632
  motion: {
580
633
  sampledFrames: i.releasedFrames,
581
634
  stalledFrames: i.stalledFrames,
582
- longestStallMs: z(i.longestStallMs),
635
+ longestStallMs: U(i.longestStallMs),
583
636
  pausedAfterRelease: i.pausedAfterRelease,
584
637
  holdReassertedAtMs: i.holdReassertedAtMs,
585
638
  tailFrames: i.tailFrames
586
639
  },
587
- images: H(i),
640
+ images: k(i),
588
641
  ...a ? { playerGaps: a } : {},
589
642
  longTasks: [],
590
643
  holdLongTasks: [],
@@ -596,34 +649,34 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
596
649
  },
597
650
  anomalies: []
598
651
  };
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;
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;
602
655
  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 = [];
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 = [];
610
663
  }
611
- if (!v && e.length > 0) {
612
- X(e);
664
+ if (!b && e.length > 0) {
665
+ I(e);
613
666
  return;
614
667
  }
615
- if (v && e.length === 0) {
616
- le(performance.now(), []);
668
+ if (b && e.length === 0) {
669
+ ye(performance.now(), []);
617
670
  return;
618
671
  }
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, $ = () => {
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 = () => {
621
674
  let e = document.documentElement;
622
675
  if (!e) return !1;
623
676
  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();
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();
627
680
  }
628
681
  });
629
682
  try {
@@ -633,31 +686,31 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
633
686
  attributes: !0,
634
687
  attributeOldValue: !0,
635
688
  attributeFilter: [
636
- N,
637
- te,
638
- P
689
+ l,
690
+ u,
691
+ H
639
692
  ]
640
693
  });
641
694
  } catch {
642
695
  return !1;
643
696
  }
644
- return Z = t, de(), !0;
697
+ return G = t, be(), !0;
645
698
  };
646
- if (!$()) {
699
+ if (!q()) {
647
700
  let e = () => {
648
- Q = null, b || $();
701
+ K = null, S || q();
649
702
  };
650
- Q = e, document.addEventListener("DOMContentLoaded", e, { once: !0 });
703
+ K = e, document.addEventListener("DOMContentLoaded", e, { once: !0 });
651
704
  }
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;
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;
654
707
  return {
655
708
  released: t.filter((e) => e.startMs + e.durationMs > n),
656
709
  held: t.filter((e) => e.startMs + e.durationMs <= n)
657
710
  };
658
- }, pe = () => {
659
- let e = performance.now(), n = h.map((e) => {
660
- let t = fe(e), n = {
711
+ }, Y = () => {
712
+ let e = performance.now(), n = v.map((e) => {
713
+ let t = J(e), n = {
661
714
  ...e,
662
715
  longTasks: t.released,
663
716
  holdLongTasks: t.held,
@@ -681,47 +734,47 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
681
734
  motion: n.motion,
682
735
  images: n.images
683
736
  }), n;
684
- }), r = v;
737
+ }), r = b;
685
738
  if (!r) return n;
686
739
  let i = e - r.t0Ms > t, o = {
687
740
  id: `${r.id} (in flight)`,
688
741
  ...r.routerId === void 0 ? {} : { routerId: r.routerId },
689
742
  kind: r.kind,
690
743
  t0: {
691
- ms: z(r.t0Ms),
744
+ ms: U(r.t0Ms),
692
745
  iso: r.t0Iso
693
746
  },
694
747
  t1: {
695
- ms: z(e),
748
+ ms: U(e),
696
749
  iso: (/* @__PURE__ */ new Date()).toISOString()
697
750
  },
698
- durationMs: z(e - r.t0Ms),
699
- driver: D(r.evidence),
751
+ durationMs: U(e - r.t0Ms),
752
+ driver: z(r.evidence),
700
753
  participants: r.participants,
701
754
  holds: {
702
755
  kind: r.holdKind,
703
756
  releasedAtMs: r.holdReleasedAtMs
704
757
  },
705
- frameSamples: T(r.heldGaps, r.releasedGaps),
758
+ frameSamples: R(r.heldGaps, r.releasedGaps),
706
759
  motion: {
707
760
  sampledFrames: r.releasedFrames,
708
761
  stalledFrames: r.stalledFrames,
709
- longestStallMs: z(r.longestStallMs),
762
+ longestStallMs: U(r.longestStallMs),
710
763
  pausedAfterRelease: r.pausedAfterRelease,
711
764
  holdReassertedAtMs: r.holdReassertedAtMs,
712
765
  tailFrames: r.tailFrames
713
766
  },
714
- images: H(r),
767
+ images: k(r),
715
768
  longTasks: [],
716
769
  holdLongTasks: [],
717
770
  landing: {
718
771
  residualInlineTransforms: [],
719
772
  offViewportAtRest: !1,
720
- stuckStatuses: i ? Y(r) : [],
773
+ stuckStatuses: i ? P(r) : [],
721
774
  orphanedHolds: []
722
775
  },
723
776
  anomalies: []
724
- }, s = fe(o);
777
+ }, s = J(o);
725
778
  return o.longTasks = s.released, o.holdLongTasks = s.held, o.anomalies = a({
726
779
  t0Ms: o.t0.ms,
727
780
  t1Ms: o.t1.ms,
@@ -735,16 +788,10 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
735
788
  motion: o.motion,
736
789
  images: o.images
737
790
  }), [...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 };
791
+ }, X = () => {
792
+ let e = F(), t = { ...e };
746
793
  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;
794
+ let n = ae(t), r = w(d), i = Y(), a = b;
748
795
  return {
749
796
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
750
797
  version: "2",
@@ -753,57 +800,50 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
753
800
  active: t,
754
801
  warnings: n
755
802
  },
756
- driverPolicy: {
757
- demotion: me("local", "flemo:motion-driver"),
758
- forcePin: i
759
- },
760
- flights: u,
803
+ flights: i,
761
804
  anomalies: o({
762
- forcePin: i,
763
- legacyLocalForcePin: t[_] ?? null,
764
- clearedForcePin: a,
765
805
  emulationSuspected: r.emulationSuspected,
766
806
  platform: r.platform,
767
- stuckFlightOpen: d !== null && performance.now() - d.t0Ms > 1e4,
768
- flightAnomalies: u.map((e) => e.anomalies)
807
+ stuckFlightOpen: a !== null && performance.now() - a.t0Ms > 1e4,
808
+ flightAnomalies: i.map((e) => e.anomalies)
769
809
  }),
770
810
  blindSpots: [...s],
771
- judgingProtocol: [...m]
811
+ judgingProtocol: [...T]
772
812
  };
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();
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();
777
817
  e.flemo?.__flemoDevtools === !0 && delete e.flemo;
778
818
  }
779
- B = null;
819
+ ge = null;
780
820
  }
781
- }, _e = {
782
- detach: ge,
783
- report: he
821
+ }, Se = {
822
+ detach: xe,
823
+ report: X
784
824
  };
785
825
  if (i) {
786
- let e = V(), t = e.flemo;
826
+ let e = _e(), t = e.flemo;
787
827
  (t === void 0 || t?.__flemoDevtools === !0) && (e.flemo = {
788
828
  __flemoDevtools: !0,
789
- report: he,
790
- flights: pe,
791
- detach: ge
829
+ report: X,
830
+ flights: Y,
831
+ detach: xe
792
832
  }, C = !0);
793
833
  }
794
- return B = _e, _e;
795
- }, 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) => {
796
836
  let r = document.createElement(e);
797
837
  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);
838
+ }, be = (e, t) => {
839
+ let n = document.createElementNS(ye, e);
800
840
  for (let [e, r] of Object.entries(t)) n.setAttribute(e, r);
801
841
  return n;
802
842
  }, G = (e) => {
803
843
  for (; e.firstChild !== null;) e.removeChild(e.firstChild);
804
844
  }, K = (e, t) => {
805
845
  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) => {
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) => {
807
847
  let t = e?.environment;
808
848
  if (!t) return "—";
809
849
  let n = t.viewport, r = n && typeof n.width == "number" && typeof n.height == "number" ? `${Math.round(n.width)}×${Math.round(n.height)}` : "—";
@@ -813,36 +853,36 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
813
853
  r,
814
854
  `rAF ${Y(t.rafCadence?.medianGapMs)}`
815
855
  ].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) => {
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) => {
817
857
  let t = e?.released?.gaps;
818
858
  if (!Array.isArray(t)) return null;
819
859
  let n = t.filter((e) => typeof e == "number" && Number.isFinite(e));
820
860
  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);
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);
824
864
  }, Q = (e, t) => {
825
- let n = U("section", "section");
826
- 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;
827
867
  }, $ = (e, t, n = "li") => {
828
- e.appendChild(U("div", n, t));
829
- }, fe = (e, t) => {
868
+ e.appendChild(W("div", n, t));
869
+ }, De = (e, t) => {
830
870
  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) => {
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) => {
835
875
  if (G(e), t.length === 0) {
836
876
  $(e, "no flights recorded yet — navigate once", "li dim");
837
877
  return;
838
878
  }
839
879
  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`));
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`));
842
882
  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);
883
+ s.appendChild(W("span", c > 0 ? "n bad" : "n", String(c))), s.addEventListener("click", () => r(o)), e.appendChild(s);
844
884
  }
845
- }, me = (e, t, n) => {
885
+ }, ke = (e, t, n) => {
846
886
  if (!n) {
847
887
  Z(e, t, "—");
848
888
  return;
@@ -853,21 +893,21 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
853
893
  `max ${Y(n.maxGapMs)}`
854
894
  ];
855
895
  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", {
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", {
858
898
  class: "spark",
859
899
  viewBox: "0 0 100 28",
860
900
  preserveAspectRatio: "none",
861
901
  "aria-hidden": "true"
862
902
  });
863
- return a.appendChild(W("polyline", {
903
+ return a.appendChild(be("polyline", {
864
904
  points: i,
865
905
  fill: "none",
866
906
  stroke: "currentColor",
867
907
  "stroke-width": "1",
868
908
  "vector-effect": "non-scaling-stroke"
869
909
  })), a;
870
- }, ge = (e, t) => {
910
+ }, je = (e, t) => {
871
911
  let n = t.longTasks ?? [], r = t.holdLongTasks ?? [];
872
912
  if (n.length === 0 && r.length === 0) {
873
913
  $(e, "none", "li dim");
@@ -876,7 +916,7 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
876
916
  let i = (e) => `${J(e?.startMs)} + ${J(e?.durationMs)}`;
877
917
  for (let t of n) $(e, i(t), "li bad");
878
918
  for (let t of r) $(e, `${i(t)} (absorbed by hold)`, "li dim");
879
- }, _e = (e, t) => {
919
+ }, Me = (e, t) => {
880
920
  if (G(e), !t) {
881
921
  $(e, "select a flight", "li dim");
882
922
  return;
@@ -884,174 +924,174 @@ var e = 30, t = 1e4, n = 50, r = 120, i = 100, a = (e) => {
884
924
  let n = Q(e, "timing");
885
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)}`);
886
926
  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));
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));
890
930
  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);
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);
892
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;
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);
894
- let p = Q(e, "landing"), m = t.landing?.residualInlineTransforms ?? [];
895
- if (m.length === 0) Z(p, "inline residue", "clean");
896
- else for (let e of m) Z(p, "inline residue", q(e));
897
- Z(p, "off-viewport at rest", oe(t.landing?.offViewportAtRest));
898
- let h = t.landing?.stuckStatuses ?? [];
899
- Z(p, "stuck statuses", h.length === 0 ? "none" : h.join(", "));
900
- let g = t.landing?.orphanedHolds ?? [];
901
- if (g.length === 0) Z(p, "orphaned holds", "none");
902
- else for (let e of g) Z(p, "orphaned holds", q(e), "bad");
903
- let _ = Q(e, "anomalies"), v = t.anomalies ?? [];
904
- if (v.length === 0) {
905
- $(_, "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");
906
946
  return;
907
947
  }
908
- for (let e of v) $(_, q(e), "li bad");
909
- }, ve = (e, t) => {
948
+ for (let e of _) $(g, q(e), "li bad");
949
+ }, Ne = (e, t) => {
910
950
  G(e);
911
951
  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 };
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 };
915
955
  let t = !1, n, r = window.flemo;
916
956
  e.recorder ? n = e.recorder : r?.__flemoDevtools === !0 && typeof r.report == "function" ? n = {
917
957
  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");
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");
925
965
  a.appendChild(s);
926
- let c = U("button", "toggle");
966
+ let c = W("button", "toggle");
927
967
  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");
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");
931
971
  d.hidden = !0;
932
- let f = U("div", "grip");
972
+ let f = W("div", "grip");
933
973
  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);
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");
935
977
  h.type = "button";
936
- let g = U("button", "act", "Close");
937
- g.type = "button";
938
- let _ = U("button", "act", "Detach");
978
+ let _ = W("button", "act", "Detach");
939
979
  _.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 = () => {
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 = () => {
949
989
  try {
950
- let e = sessionStorage.getItem(be);
990
+ let e = sessionStorage.getItem(E);
951
991
  if (e === null) return null;
952
992
  let t = Number.parseFloat(e);
953
993
  return Number.isFinite(t) ? t : null;
954
994
  } catch {
955
995
  return null;
956
996
  }
957
- }, P = (e) => {
997
+ }, ie = (e) => {
958
998
  try {
959
- sessionStorage.setItem(be, String(Math.round(e)));
999
+ sessionStorage.setItem(E, String(Math.round(e)));
960
1000
  } catch {}
961
- }, F = N(te() ?? window.innerHeight * .4);
962
- d.style.height = `${Math.round(F)}px`;
963
- 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 = () => {
964
1004
  try {
965
1005
  return n.report();
966
1006
  } catch {
967
1007
  return null;
968
1008
  }
969
- }, ne = (e) => {
970
- e !== D && (D = e, R());
971
- }, re = () => {
972
- let e = L(), t = e?.flights ?? [];
1009
+ }, I = (e) => {
1010
+ e !== T && (T = e, R());
1011
+ }, L = () => {
1012
+ let e = ae(), t = e?.flights ?? [];
973
1013
  K(l, String(t.length));
974
1014
  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));
1015
+ if (u.hidden = !n, d.hidden = !w, !w) return;
1016
+ K(ee, Se(e));
977
1017
  let r = JSON.stringify([
978
1018
  e?.overrides?.warnings ?? [],
979
1019
  e?.anomalies ?? [],
980
1020
  e?.overrides?.active ?? {}
981
1021
  ]);
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));
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));
987
1027
  };
988
1028
  function R() {
989
- T || I() || re();
1029
+ C || F() || L();
990
1030
  }
991
- function ie() {
1031
+ function oe() {
992
1032
  j = 0, R(), z();
993
1033
  }
994
1034
  function z() {
995
- j = window.setTimeout(ie, E ? xe : Se);
1035
+ j = window.setTimeout(oe, w ? Fe : Ie);
996
1036
  }
997
- let B = () => {
1037
+ let se = () => {
998
1038
  window.clearTimeout(j), z();
999
- }, V = (e) => {
1000
- E = e, B(), R();
1039
+ }, ce = (e) => {
1040
+ w = e, se(), R();
1001
1041
  };
1002
- c.addEventListener("click", () => V(!E)), g.addEventListener("click", () => V(!1)), _.addEventListener("click", () => Y());
1003
- let H = () => {
1004
- if (!T) {
1005
- if (I()) {
1006
- 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);
1007
1047
  return;
1008
1048
  }
1009
- K(h, "Copied ✓"), window.clearTimeout(M), M = window.setTimeout(W, 1200);
1049
+ K(m, "Copied ✓"), window.clearTimeout(M), M = window.setTimeout(B, 1200);
1010
1050
  }
1011
1051
  };
1012
- function W() {
1013
- if (I()) {
1014
- M = window.setTimeout(W, xe);
1052
+ function B() {
1053
+ if (F()) {
1054
+ M = window.setTimeout(B, Fe);
1015
1055
  return;
1016
1056
  }
1017
- M = 0, K(h, we);
1057
+ M = 0, K(m, Re);
1018
1058
  }
1019
- let G = (e) => {
1020
- if (T) return;
1021
- if (I()) {
1022
- 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);
1023
1063
  return;
1024
1064
  }
1025
- let t = U("textarea");
1065
+ let t = W("textarea");
1026
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();
1027
1067
  let n = document;
1028
1068
  try {
1029
1069
  n.execCommand?.("copy");
1030
1070
  } catch {}
1031
- t.remove(), H();
1071
+ t.remove(), le();
1032
1072
  };
1033
- h.addEventListener("click", () => {
1034
- 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;
1035
1075
  if (t && typeof t.writeText == "function") {
1036
- t.writeText(e).then(H, () => G(e));
1076
+ t.writeText(e).then(le, () => V(e));
1037
1077
  return;
1038
1078
  }
1039
- G(e);
1079
+ V(e);
1040
1080
  });
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);
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);
1045
1085
  };
1046
1086
  f.addEventListener("pointerdown", (e) => {
1047
- e.preventDefault(), window.addEventListener("pointermove", q), window.addEventListener("pointerup", J);
1087
+ e.preventDefault(), window.addEventListener("pointermove", ue), window.addEventListener("pointerup", H);
1048
1088
  });
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);
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);
1051
1091
  }
1052
1092
  document.body.appendChild(i), R(), z();
1053
- let X = { detach: Y };
1054
- return Ee = X, X;
1093
+ let fe = { detach: de };
1094
+ return Be = fe, fe;
1055
1095
  };
1056
1096
  //#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 };
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 };