@pie-players/pie-section-player-tools-session-debugger 0.1.1 → 0.1.3

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.
@@ -1,7 +1,7 @@
1
1
  <svelte:options
2
2
  customElement={{
3
3
  tag: 'pie-section-player-tools-session-debugger',
4
- shadow: 'open',
4
+ shadow: 'none',
5
5
  props: {
6
6
  sectionId: { type: 'String', attribute: 'section-id' },
7
7
  attemptId: { type: 'String', attribute: 'attempt-id' },
@@ -11,6 +11,7 @@
11
11
  />
12
12
 
13
13
  <script lang="ts">
14
+ import '@pie-players/pie-theme/components.css';
14
15
  import { createEventDispatcher } from 'svelte';
15
16
  import { onMount } from 'svelte';
16
17
  const dispatch = createEventDispatcher<{ close: undefined }>();
@@ -39,6 +40,9 @@
39
40
 
40
41
  type ToolkitCoordinatorLike = {
41
42
  getSectionController?: (args: { sectionId: string; attemptId?: string }) => SectionControllerLike | undefined;
43
+ onSectionControllerLifecycle?: (
44
+ listener: (event: { type: 'ready' | 'disposed'; key?: { sectionId?: string; attemptId?: string } }) => void
45
+ ) => () => void;
42
46
  };
43
47
 
44
48
  let {
@@ -76,12 +80,22 @@
76
80
  lastChangedItemId: null,
77
81
  itemSessions: {}
78
82
  });
83
+ let activeController: SectionControllerLike | null = null;
84
+ let unsubscribeController: (() => void) | null = null;
85
+ let unsubscribeLifecycle: (() => void) | null = null;
86
+ let controllerAvailable = $state(false);
87
+ let refreshQueued = false;
79
88
 
80
89
  function cloneSessionSnapshot<T>(value: T): T {
81
90
  try {
82
91
  return structuredClone(value);
83
92
  } catch {
84
- return JSON.parse(JSON.stringify(value)) as T;
93
+ try {
94
+ return JSON.parse(JSON.stringify(value)) as T;
95
+ } catch {
96
+ // Keep debugger resilient if a session payload contains non-serializable values.
97
+ return value;
98
+ }
85
99
  }
86
100
  }
87
101
 
@@ -90,12 +104,18 @@
90
104
  return toolkitCoordinator.getSectionController?.({ sectionId, attemptId });
91
105
  }
92
106
 
93
- function refreshFromController(meta?: { itemId?: string; updatedAt?: number }) {
94
- const controller = getController();
107
+ function refreshFromController(
108
+ meta?: { itemId?: string; updatedAt?: number },
109
+ controllerOverride?: SectionControllerLike | null
110
+ ) {
111
+ const controller = controllerOverride || getController();
95
112
  const sectionSlice = controller?.getCurrentSectionAttemptSlice?.() || null;
113
+ controllerAvailable = Boolean(controller);
96
114
  sessionPanelSnapshot = {
97
115
  currentItemIndex:
98
- typeof sectionSlice?.currentItemIndex === 'number' ? sectionSlice.currentItemIndex : null,
116
+ typeof sectionSlice?.currentItemIndex === 'number' && sectionSlice.currentItemIndex >= 0
117
+ ? sectionSlice.currentItemIndex
118
+ : null,
99
119
  currentItemId:
100
120
  typeof sectionSlice?.currentItemId === 'string' && sectionSlice.currentItemId
101
121
  ? sectionSlice.currentItemId
@@ -107,18 +127,86 @@
107
127
  };
108
128
  }
109
129
 
130
+ function queueRefresh(meta?: { itemId?: string; updatedAt?: number }) {
131
+ if (refreshQueued) return;
132
+ refreshQueued = true;
133
+ queueMicrotask(() => {
134
+ refreshQueued = false;
135
+ ensureControllerSubscription();
136
+ refreshFromController(
137
+ meta || {
138
+ updatedAt: Date.now()
139
+ }
140
+ );
141
+ });
142
+ }
143
+
144
+ function detachControllerSubscription() {
145
+ unsubscribeController?.();
146
+ unsubscribeController = null;
147
+ activeController = null;
148
+ }
149
+
150
+ function detachLifecycleSubscription() {
151
+ unsubscribeLifecycle?.();
152
+ unsubscribeLifecycle = null;
153
+ }
154
+
155
+ function ensureControllerSubscription() {
156
+ const controller = getController() || null;
157
+ if (!controller) {
158
+ detachControllerSubscription();
159
+ controllerAvailable = false;
160
+ sessionPanelSnapshot = {
161
+ currentItemIndex: null,
162
+ currentItemId: null,
163
+ visitedItemIdentifiers: [],
164
+ updatedAt: Date.now(),
165
+ lastChangedItemId: null,
166
+ itemSessions: {}
167
+ };
168
+ return;
169
+ }
170
+ if (controller === activeController) return;
171
+ detachControllerSubscription();
172
+ activeController = controller;
173
+ const subscribe = typeof controller.subscribe === 'function' ? controller.subscribe.bind(controller) : null;
174
+ unsubscribeController =
175
+ subscribe?.((detail) => {
176
+ refreshFromController(
177
+ {
178
+ itemId: detail?.itemId,
179
+ updatedAt: detail?.timestamp || Date.now()
180
+ },
181
+ controller
182
+ );
183
+ }) || null;
184
+ refreshFromController(undefined, controller);
185
+ }
186
+
187
+ export function refreshFromHost(): void {
188
+ queueRefresh({
189
+ updatedAt: Date.now()
190
+ });
191
+ }
192
+
110
193
  $effect(() => {
111
194
  if (!toolkitCoordinator || !sectionId) return;
112
- refreshFromController();
113
- const controller = getController();
114
- const unsubscribe = controller?.subscribe?.((detail) => {
195
+ ensureControllerSubscription();
196
+ detachLifecycleSubscription();
197
+ unsubscribeLifecycle = toolkitCoordinator.onSectionControllerLifecycle?.((event) => {
198
+ const eventSectionId = event?.key?.sectionId || '';
199
+ const eventAttemptId = event?.key?.attemptId || undefined;
200
+ if (eventSectionId !== sectionId) return;
201
+ if ((eventAttemptId || undefined) !== (attemptId || undefined)) return;
202
+ ensureControllerSubscription();
115
203
  refreshFromController({
116
- itemId: detail?.itemId,
117
- updatedAt: detail?.timestamp || Date.now()
204
+ updatedAt: Date.now()
118
205
  });
119
- });
206
+ }) || null;
120
207
  return () => {
121
- unsubscribe?.();
208
+ detachControllerSubscription();
209
+ detachLifecycleSubscription();
122
210
  };
123
211
  });
124
212
 
@@ -130,6 +218,20 @@
130
218
  sessionWindowHeight = clamp(Math.round(viewportHeight * 0.72), 360, 860);
131
219
  sessionWindowX = Math.max(16, Math.round(viewportWidth * 0.08));
132
220
  sessionWindowY = Math.max(16, Math.round((viewportHeight - sessionWindowHeight) / 2));
221
+
222
+ const handleRuntimeSessionEvent = () => {
223
+ queueRefresh({
224
+ updatedAt: Date.now()
225
+ });
226
+ };
227
+ document.addEventListener('session-changed', handleRuntimeSessionEvent as EventListener, true);
228
+ document.addEventListener('item-session-changed', handleRuntimeSessionEvent as EventListener, true);
229
+ document.addEventListener('composition-changed', handleRuntimeSessionEvent as EventListener, true);
230
+ return () => {
231
+ document.removeEventListener('session-changed', handleRuntimeSessionEvent as EventListener, true);
232
+ document.removeEventListener('item-session-changed', handleRuntimeSessionEvent as EventListener, true);
233
+ document.removeEventListener('composition-changed', handleRuntimeSessionEvent as EventListener, true);
234
+ };
133
235
  });
134
236
 
135
237
  function startSessionDrag(e: MouseEvent) {
@@ -196,40 +298,64 @@
196
298
  </script>
197
299
 
198
300
  <div
199
- class="fixed z-100 bg-base-100 rounded-lg shadow-2xl border-2 border-base-300"
301
+ class="pie-section-player-tools-session-debugger"
200
302
  style="left: {sessionWindowX}px; top: {sessionWindowY}px; width: {sessionWindowWidth}px; {isSessionMinimized ? 'height: auto;' : `height: ${sessionWindowHeight}px;`}"
201
303
  >
202
304
  <div
203
- class="flex items-center justify-between px-4 py-2 bg-base-200 rounded-t-lg cursor-move select-none border-b border-base-300"
305
+ class="pie-section-player-tools-session-debugger__header"
204
306
  onmousedown={startSessionDrag}
205
307
  role="button"
206
308
  tabindex="0"
207
309
  aria-label="Drag session panel"
208
310
  >
209
- <div class="flex items-center gap-2">
210
- <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
311
+ <div class="pie-section-player-tools-session-debugger__header-title">
312
+ <svg
313
+ xmlns="http://www.w3.org/2000/svg"
314
+ class="pie-section-player-tools-session-debugger__icon-sm"
315
+ fill="none"
316
+ viewBox="0 0 24 24"
317
+ stroke="currentColor"
318
+ >
211
319
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
212
320
  </svg>
213
- <h3 class="font-bold text-sm">Session Data</h3>
321
+ <h3 class="pie-section-player-tools-session-debugger__title">Session Data</h3>
214
322
  </div>
215
- <div class="flex gap-1">
323
+ <div class="pie-section-player-tools-session-debugger__header-actions">
216
324
  <button
217
- class="btn btn-xs btn-ghost btn-circle"
325
+ class="pie-section-player-tools-session-debugger__icon-button"
218
326
  onclick={() => (isSessionMinimized = !isSessionMinimized)}
219
327
  title={isSessionMinimized ? 'Maximize' : 'Minimize'}
220
328
  >
221
329
  {#if isSessionMinimized}
222
- <svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
330
+ <svg
331
+ xmlns="http://www.w3.org/2000/svg"
332
+ class="pie-section-player-tools-session-debugger__icon-xs"
333
+ fill="none"
334
+ viewBox="0 0 24 24"
335
+ stroke="currentColor"
336
+ >
223
337
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7" />
224
338
  </svg>
225
339
  {:else}
226
- <svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
340
+ <svg
341
+ xmlns="http://www.w3.org/2000/svg"
342
+ class="pie-section-player-tools-session-debugger__icon-xs"
343
+ fill="none"
344
+ viewBox="0 0 24 24"
345
+ stroke="currentColor"
346
+ >
227
347
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
228
348
  </svg>
229
349
  {/if}
230
350
  </button>
231
- <button class="btn btn-xs btn-ghost btn-circle" onclick={() => dispatch('close')} title="Close">
232
- <svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
351
+ <button class="pie-section-player-tools-session-debugger__icon-button" onclick={() => dispatch('close')} title="Close">
352
+ <svg
353
+ xmlns="http://www.w3.org/2000/svg"
354
+ class="pie-section-player-tools-session-debugger__icon-xs"
355
+ fill="none"
356
+ viewBox="0 0 24 24"
357
+ stroke="currentColor"
358
+ >
233
359
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
234
360
  </svg>
235
361
  </button>
@@ -237,25 +363,42 @@
237
363
  </div>
238
364
 
239
365
  {#if !isSessionMinimized}
240
- <div class="p-4 flex flex-col min-h-0 overflow-hidden" style="height: {sessionWindowHeight - 60}px;">
241
- <div class="space-y-3 flex-1 min-h-0 flex flex-col">
242
- <div class="mb-2">
243
- <div class="text-sm font-bold mb-2">PIE Session Data (Persistent)</div>
366
+ <div class="pie-section-player-tools-session-debugger__content-shell" style="height: {sessionWindowHeight - 60}px;">
367
+ <div class="pie-section-player-tools-session-debugger__content">
368
+ <div class="pie-section-player-tools-session-debugger__section-intro">
369
+ <div class="pie-section-player-tools-session-debugger__heading">PIE Session Data (Persistent)</div>
244
370
  </div>
245
371
 
246
- {#if Object.keys(sessionPanelSnapshot.itemSessions || {}).length === 0}
247
- <div class="alert alert-info">
248
- <svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-5 w-5" fill="none" viewBox="0 0 24 24">
372
+ {#if !controllerAvailable}
373
+ <div class="pie-section-player-tools-session-debugger__alert pie-section-player-tools-session-debugger__alert--warning">
374
+ <svg
375
+ xmlns="http://www.w3.org/2000/svg"
376
+ class="pie-section-player-tools-session-debugger__icon-md"
377
+ fill="none"
378
+ viewBox="0 0 24 24"
379
+ >
380
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01M5.07 19h13.86c1.54 0 2.5-1.67 1.73-3L13.73 4c-.77-1.33-2.69-1.33-3.46 0L3.34 16c-.77 1.33.19 3 1.73 3z" />
381
+ </svg>
382
+ <span class="pie-section-player-tools-session-debugger__text-xs">Section controller not available for this section yet.</span>
383
+ </div>
384
+ {:else if Object.keys(sessionPanelSnapshot.itemSessions || {}).length === 0}
385
+ <div class="pie-section-player-tools-session-debugger__alert pie-section-player-tools-session-debugger__alert--info">
386
+ <svg
387
+ xmlns="http://www.w3.org/2000/svg"
388
+ class="pie-section-player-tools-session-debugger__icon-md"
389
+ fill="none"
390
+ viewBox="0 0 24 24"
391
+ >
249
392
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
250
393
  </svg>
251
- <span class="text-xs">No session data yet. Interact with the questions to see updates.</span>
394
+ <span class="pie-section-player-tools-session-debugger__text-xs">No section session data yet. Interact with the questions to see updates.</span>
252
395
  </div>
253
396
  {:else}
254
- <div class="bg-base-200 rounded p-3 flex-1 min-h-0 flex flex-col">
255
- <div class="text-xs font-semibold mb-2">
397
+ <div class="pie-section-player-tools-session-debugger__card">
398
+ <div class="pie-section-player-tools-session-debugger__card-title">
256
399
  Item Sessions Snapshot
257
400
  </div>
258
- <pre class="bg-base-300 p-2 rounded text-xs overflow-auto flex-1 min-h-0">{JSON.stringify(sessionPanelSnapshot, null, 2)}</pre>
401
+ <pre class="pie-section-player-tools-session-debugger__card-pre">{JSON.stringify(sessionPanelSnapshot, null, 2)}</pre>
259
402
  </div>
260
403
  {/if}
261
404
  </div>
@@ -264,13 +407,13 @@
264
407
 
265
408
  {#if !isSessionMinimized}
266
409
  <div
267
- class="absolute bottom-0 right-0 w-4 h-4 cursor-se-resize"
410
+ class="pie-section-player-tools-session-debugger__resize-handle"
268
411
  onmousedown={startSessionResize}
269
412
  role="button"
270
413
  tabindex="0"
271
414
  title="Resize window"
272
415
  >
273
- <svg class="w-full h-full text-base-content/30" viewBox="0 0 16 16" fill="currentColor">
416
+ <svg class="pie-section-player-tools-session-debugger__resize-icon" viewBox="0 0 16 16" fill="currentColor">
274
417
  <path d="M16 16V14H14V16H16Z" />
275
418
  <path d="M16 11V9H14V11H16Z" />
276
419
  <path d="M13 16V14H11V16H13Z" />
@@ -0,0 +1 @@
1
+ .pie-loading{position:absolute;height:100%;width:100%;background-color:#fff;inset:0;z-index:9999;opacity:.4}.pie-loading.fixed{position:fixed}.pie-loading:before{content:"";background-color:#0000;border:5px solid rgba(63,81,181,.9);opacity:.9;border-right:5px solid rgba(0,0,0,0);border-left:5px solid rgba(0,0,0,0);border-radius:50px;box-shadow:0 0 35px #3f51b5e6;width:50px;height:50px;-moz-animation:spinPulse 1s infinite ease-in-out;-webkit-animation:spinPulse 1s infinite linear;margin:-25px 0 0 -25px;position:absolute;top:50%;left:50%}.pie-loading:after{content:"";background-color:#0000;border:5px solid rgba(63,81,181,.9);opacity:.9;border-left:5px solid rgba(0,0,0,0);border-right:5px solid rgba(0,0,0,0);border-radius:50px;box-shadow:0 0 15px #3f51b5e6;width:30px;height:30px;-moz-animation:spinoffPulse 1s infinite linear;-webkit-animation:spinoffPulse 1s infinite linear;margin:-15px 0 0 -15px;position:absolute;top:50%;left:50%}@keyframes spinPulse{0%{transform:rotate(160deg);opacity:0;box-shadow:0 0 1px #3f51b5e6}50%{transform:rotate(145deg);opacity:1}to{transform:rotate(-320deg);opacity:0}}@keyframes spinoffPulse{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.pie-api-player img{max-width:inherit!important;max-height:inherit!important}.book-title-k5{text-decoration:underline}.book-title{font-style:italic}.block-quote,.text-block{font-family:serif;margin:5px 20%;width:60%;border:1px solid black;padding:2px;display:block}.short-quote{font-weight:700}span.short-quote:before{content:open-quote}span.short-quote:after{content:close-quote}.word-callout{text-decoration:underline}.relative-emphasis{text-transform:uppercase}.content-emphasis{font-weight:700;color:red}span.passage-title:before{content:open-quote}span.passage-title:after{content:close-quote}.proper-name,.variable{font-style:italic}.equation-block{text-align:center;margin:5px 20%;width:60%;padding:2px;display:block}.embedded-error{font-style:italic}div.passage-title,div.passage-subtitle{font-weight:700;text-align:center}div.passage-author{text-align:center}.p-number{float:left;font-size:.85em}.numbered-paragraph{margin-left:36px}@media print{.kds-noprint,.noprint{display:none}}.kds-absolute{border-left:1px solid black;border-right:1px solid black;padding:0 .3em}.abs{border-left:#000000 1px solid;border-right:#000000 1px solid;padding:0 .3em}.kds-border-1{border:1px solid black}.kds-border-2{border:2px solid black}.kds-center{margin:0;text-align:center}.center{text-align:center;margin:0}.kds-exponent{font-size:85%;margin-left:-.4em;position:relative;top:-1.4em}sup.frac{position:relative;top:-1.4em;font-size:70%;margin-left:-.4em}.kds-fillin{border:1px solid black;display:inline-block;margin:0 .2em;padding-left:1em}.fillin{margin:0 .2em;padding-left:1em;border:#000000 1px solid;display:inline-block}.kds-font-larger{font-size:larger}.kds-font-smaller{font-size:smaller}table.kds-fraction{border:0px;display:inline-block;font-size:85%;margin:0;padding:0;vertical-align:middle}table.kds-fraction>tbody>tr>td.kds-numerator{border-bottom:1px solid black;border-left:0px;border-right:0px;border-top:0px;text-align:center}table.kds-fraction>tbody>tr>td.kds-denominator{border:0px;text-align:center}table.frac{display:inline-block;vertical-align:middle;font-size:85%;border:0px;margin:0;padding:0}.frac .nu{border-left:0px;border-top:0px;border-right:0px;border-bottom:#000000 1px solid;text-align:center}.frac .de{border:0px;text-align:center}.kds-hanging-indent{margin:0;padding-left:3em;text-indent:-3em}.kds-image-caption{font-family:Verdana,Arial,sans-serif;text-align:center}.kds-image-left{float:left;margin-right:5px}.kds-image-right{float:right;margin-left:5px}.kds-indent,.indent{text-indent:3em}.kds-nowrap{display:inline-block;white-space:nowrap}.kds-overline{text-decoration:overline}.kds-parentheses{font-family:Arial Narrow,Arial,sans-serif;font-size:300%;font-weight:400;position:relative;top:8px}b.frac{font-weight:400;font-size:300%;font-family:arial narrow;position:relative;top:+8px}.kds-pi{font-family:Times New Roman,serif;font-size:1.2em}.newradical{border-collapse:collapse;display:inline-block;vertical-align:middle}.newradical td{border:0px;padding:0;vertical-align:top}.newradical td.vinculum{border-top:1px solid black;padding:0;vertical-align:top}.newradical div.exp{font-size:.7em;position:relative;left:7px;bottom:5px}.kds-underline,.under{text-decoration:underline}.kds-verdana2t{border:1px solid white;text-align:left;text-decoration:none;vertical-align:top}.Verdana2t{vertical-align:top;text-align:left;text-decoration:none;border:1px solid white}.kds-whole-number{display:inline-block;font-size:120%;margin:0 0 0 .2em}.whole{display:inline-block;margin:0 0 0 .2em;font-size:120%}table.KdsTable01{border:1px solid black;border-collapse:collapse;border-spacing:0px}table.KdsTable01>tbody>tr>th{background-color:#d3d3d3;border:1px solid black;font-weight:400;padding:2px;text-align:center}table.KdsTable01>tbody>tr>th.bold{background-color:#d3d3d3;border:1px solid black;font-weight:700;padding:2px;text-align:center}table.KdsTable01>tbody>tr>td{border:1px solid black;padding:2px;text-align:center}table.KdsTable01>tbody>tr>td.bold{border:1px solid black;font-weight:700;padding:2px;text-align:center}table.KdsTable02{border:1px solid black;border-collapse:collapse;border-spacing:0px}table.KdsTable02>tbody>tr>th{background-color:#d3d3d3;border:1px solid black;font-weight:400;padding:2px}table.KdsTable02>tbody>tr>td{border:1px solid black;padding:2px}.table{width:100%;margin-bottom:1em;background-color:transparent;border-collapse:collapse}.table th,.table td{padding:.75em;vertical-align:top;border-top:1px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}th{text-align:inherit}.table-bordered,.table-bordered th,.table-bordered td{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-striped tbody tr:nth-of-type(odd){background-color:#0000000d}.text-center{text-align:center!important}.h5,h5{font-size:1.25em}h1,h2,h3,h4,h5,h6{margin-top:0}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5em;font-family:inherit;font-weight:500;line-height:1.2;color:inherit}.lrn_feature h3{margin-top:0!important}#stimulus,#item{width:50%;float:left}.lrn_width_auto.table{width:auto}.TEX-S3{font-family:MJXZERO,MJXTEX-S3!important}.TEX-S2{font-family:MJXZERO,MJXTEX-S2!important}.TEX-S1{font-family:MJXZERO,MJXTEX-S1!important}.TEX-I{font-family:MJXZERO,MJXTEX-I!important}mjx-c.mjx-c2032{font-family:CerebriSans,serif!important}mjx-c.mjx-c22,mjx-c.mjx-c27{font-family:MJXZERO,serif!important}table{border-collapse:collapse}.evaluate-bottom-border>:first-child:after{content:"";display:block;border-bottom:1px solid #d3d3d3}.pie-section-player-tools-pnp-debugger,.pie-section-player-tools-session-debugger{position:fixed;z-index:100;overflow:hidden;background:var(--pie-white, #fff);border-radius:.5rem;box-shadow:0 25px 50px -12px #00000040;border:2px solid var(--pie-border-light, #d1d5db);color:var(--pie-text, #111827)}.pie-section-player-tools-pnp-debugger{display:flex;flex-direction:column}.pie-section-player-tools-pnp-debugger__header,.pie-section-player-tools-session-debugger__header{display:flex;align-items:center;justify-content:space-between;padding:.5rem 1rem;background:var(--pie-secondary-background, #f3f4f6);border-bottom:1px solid var(--pie-border-light, #d1d5db);cursor:move;user-select:none}.pie-section-player-tools-pnp-debugger__header-title,.pie-section-player-tools-session-debugger__header-title{display:flex;align-items:center;gap:.5rem}.pie-section-player-tools-pnp-debugger__title,.pie-section-player-tools-session-debugger__title{margin:0;font-size:.875rem;font-weight:700}.pie-section-player-tools-pnp-debugger__header-actions,.pie-section-player-tools-session-debugger__header-actions{display:flex;gap:.25rem}.pie-section-player-tools-pnp-debugger__icon-button,.pie-section-player-tools-session-debugger__icon-button{width:1.5rem;height:1.5rem;display:inline-flex;align-items:center;justify-content:center;border:none;border-radius:9999px;background:transparent;color:inherit;cursor:pointer}.pie-section-player-tools-pnp-debugger__icon-button:hover,.pie-section-player-tools-session-debugger__icon-button:hover{background:#11182714}.pie-section-player-tools-pnp-debugger__icon-button:focus-visible,.pie-section-player-tools-session-debugger__icon-button:focus-visible{outline:2px solid var(--pie-focus-checked-border, #1976d2);outline-offset:1px}.pie-section-player-tools-pnp-debugger__icon-sm,.pie-section-player-tools-session-debugger__icon-sm{width:1rem;height:1rem}.pie-section-player-tools-pnp-debugger__icon-xs,.pie-section-player-tools-session-debugger__icon-xs{width:.75rem;height:.75rem}.pie-section-player-tools-session-debugger__icon-md{width:1.25rem;height:1.25rem;flex-shrink:0}.pie-section-player-tools-pnp-debugger__content-shell,.pie-section-player-tools-session-debugger__content-shell{padding:1rem;display:flex;flex-direction:column;min-height:0;overflow:hidden}.pie-section-player-tools-pnp-debugger__content,.pie-section-player-tools-session-debugger__content{display:flex;flex-direction:column;gap:.75rem;flex:1;min-height:0}.pie-section-player-tools-pnp-debugger__card,.pie-section-player-tools-session-debugger__card{background:var(--pie-secondary-background, #f3f4f6);border-radius:.375rem;padding:.75rem}.pie-section-player-tools-pnp-debugger__card-title,.pie-section-player-tools-session-debugger__card-title{font-size:.75rem;font-weight:600;margin-bottom:.5rem}.pie-section-player-tools-pnp-debugger__card-pre,.pie-section-player-tools-session-debugger__card-pre{background:var(--pie-background-dark, #e5e7eb);padding:.5rem;border-radius:.375rem;font-size:.75rem;margin:0}.pie-section-player-tools-pnp-debugger__card-pre{overflow-x:auto}.pie-section-player-tools-session-debugger__card{display:flex;flex-direction:column;flex:1;min-height:0}.pie-section-player-tools-session-debugger__card-pre{overflow:auto;flex:1;min-height:0}.pie-section-player-tools-session-debugger__section-intro{margin-bottom:.25rem}.pie-section-player-tools-session-debugger__heading{font-size:.875rem;font-weight:700}.pie-section-player-tools-session-debugger__text-xs{font-size:.75rem}.pie-section-player-tools-session-debugger__alert{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;border-radius:.375rem;border:1px solid transparent}.pie-section-player-tools-session-debugger__alert--warning{background:#fef3c7;border-color:#f59e0b;color:#92400e}.pie-section-player-tools-session-debugger__alert--info{background:#e0f2fe;border-color:#38bdf8;color:#0c4a6e}.pie-section-player-tools-pnp-debugger__resize-handle,.pie-section-player-tools-session-debugger__resize-handle{position:absolute;bottom:0;right:0;width:1rem;height:1rem;cursor:se-resize}.pie-section-player-tools-pnp-debugger__resize-icon,.pie-section-player-tools-session-debugger__resize-icon{width:100%;height:100%;color:color-mix(in srgb,var(--pie-text, #111827) 30%,transparent)}.pie-answer-eliminator-toggle{width:28px;height:28px;padding:0;border:1px solid var(--pie-border, #ccc);border-radius:4px;background:var(--pie-white, #fff);cursor:pointer;font-size:18px;line-height:1;display:inline-flex;align-items:center;justify-content:center;color:var(--pie-border-gray, #666);transition:all .2s ease;z-index:10}.pie-answer-eliminator-toggle:hover{background:var(--pie-secondary-background, #f0f0f0);border-color:var(--pie-border-dark, #999);color:var(--pie-text, #333)}.pie-answer-eliminator-toggle--active,.pie-answer-eliminator-toggle--active:hover{background:var(--pie-incorrect, #ff9800);border-color:var(--pie-incorrect, #ff9800);color:var(--pie-white, #fff)}.pie-answer-eliminator-eliminated-fallback{text-decoration:line-through;text-decoration-thickness:2px;text-decoration-color:var(--pie-incorrect, #ff9800);opacity:.6}.pie-answer-masked-fallback{opacity:.2;filter:blur(2px)}.pie-answer-eliminator-sr-announcement{position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden}