File size: 73,851 Bytes
6f1f9d5
0700dee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f6dd8b8
637f1d4
 
 
 
 
62858ad
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6f1f9d5
62858ad
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6f1f9d5
f6dd8b8
0700dee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6f1f9d5
0700dee
 
 
 
 
 
6f1f9d5
 
0700dee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6f1f9d5
 
 
 
0700dee
6f1f9d5
 
 
 
0700dee
 
 
 
 
6f1f9d5
0700dee
6f1f9d5
0700dee
 
6f1f9d5
0700dee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
\<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <title>Copilot Quest — Adventure Quiz</title>
  <style>
    :root {
      --bg: #0b1020;
      --panel: rgba(255,255,255,.06);
      --text: rgba(255,255,255,.92);
      --muted: rgba(255,255,255,.70);
      --border: rgba(255,255,255,.12);
      --shadow: 0 12px 30px rgba(0,0,0,.35);
      --radius: 18px;
      --mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
      --sans: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
    }
    html, body {
      height: 100%;
      margin: 0;
      background: radial-gradient(1200px 900px at 20% 10%, rgba(120,200,255,.15), transparent 60%),
                  radial-gradient(900px 700px at 80% 40%, rgba(200,120,255,.12), transparent 60%),
                  radial-gradient(900px 700px at 40% 90%, rgba(120,255,200,.10), transparent 60%),
                  var(--bg);
      color: var(--text);
      font-family: var(--sans);
    }
    .wrap { max-width: 1100px; margin: 0 auto; padding: 18px; box-sizing: border-box; }
    header { display:flex; gap:12px; align-items:center; justify-content:space-between; margin-bottom:14px; }
    .brand { display:flex; gap:12px; align-items:center; }
    .logo {
      width: 44px; height: 44px; border-radius: 14px;
      background: linear-gradient(135deg, rgba(120,200,255,.35), rgba(200,120,255,.25));
      border: 1px solid var(--border); box-shadow: var(--shadow);
      display:grid; place-items:center; font-weight:800; letter-spacing:.5px;
    }
    h1 { font-size: 18px; margin: 0; line-height: 1.1; }
    .subtitle { font-size: 12px; color: var(--muted); margin-top: 2px; }
    .grid { display:grid; grid-template-columns: 1.6fr .9fr; gap:14px; }
    @media (max-width: 980px) { .grid { grid-template-columns: 1fr; } }
    .card { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); overflow:hidden; }
    .card .hd { padding: 14px 16px; background: rgba(255,255,255,.04); border-bottom: 1px solid var(--border); display:flex; gap:10px; align-items:center; justify-content:space-between; }
    .card .bd { padding: 16px; }
    .btnrow { display:flex; gap:8px; flex-wrap:wrap; justify-content:flex-end; }
    button {
      border: 1px solid var(--border); background: rgba(255,255,255,.06); color: var(--text);
      border-radius: 14px; padding: 10px 12px; cursor: pointer; transition: transform .06s ease, background .12s ease;
      font-weight: 600;
    }
    button:hover { background: rgba(255,255,255,.10); }
    button:active { transform: translateY(1px); }
    button.primary { background: rgba(120,200,255,.18); border-color: rgba(120,200,255,.30); }
    button.danger { background: rgba(255,120,140,.12); border-color: rgba(255,120,140,.26); }
    button.small { padding: 7px 10px; border-radius: 12px; font-size: 12px; }
    .stats { display:grid; grid-template-columns: 1fr 1fr; gap:10px; }
    .stat { padding: 12px; background: rgba(255,255,255,.05); border: 1px solid var(--border); border-radius: 16px; }
    .stat .k { font-size: 12px; color: var(--muted); }
    .stat .v { font-size: 18px; font-weight: 800; margin-top: 2px; font-family: var(--mono); }
    .hearts { letter-spacing: 2px; font-size: 16px; margin-top: 4px; font-family: var(--mono); }
    .pill { display:inline-flex; align-items:center; gap:6px; padding:6px 10px; border-radius:999px; border:1px solid var(--border); background: rgba(255,255,255,.05); font-size:12px; color: var(--muted); }
    .question { font-size: 15px; line-height: 1.45; white-space: pre-wrap; margin: 0 0 14px 0; }
    .hint { color: var(--muted); font-size: 12px; margin-top: -4px; margin-bottom: 10px; }
    .choices { display:grid; gap: 10px; }
    label.choice {
      display:flex; gap:10px; align-items:flex-start; padding: 12px;
      border-radius: 16px; border: 1px solid var(--border); background: rgba(255,255,255,.04);
      cursor: pointer;
    }
    label.choice:hover { background: rgba(255,255,255,.07); }
    .choice .letter {
      width: 30px; height: 30px; border-radius: 12px;
      background: rgba(255,255,255,.07); border: 1px solid var(--border);
      display:grid; place-items:center; font-weight:800; font-family: var(--mono); flex: 0 0 auto;
    }
    .choice .txt { color: var(--text); line-height: 1.35; font-size: 14px; }
    .msg { margin-top: 12px; padding: 10px 12px; border-radius: 14px; border: 1px solid var(--border); background: rgba(255,255,255,.05); white-space: pre-wrap; }
    .msg.good { border-color: rgba(120,255,180,.35); }
    .msg.bad  { border-color: rgba(255,120,140,.35); }
    .msg.warn { border-color: rgba(255,210,120,.35); }
    .map { display:grid; gap: 10px; }
    .node { padding: 12px; border-radius: 16px; border: 1px solid var(--border); background: rgba(255,255,255,.04); }
    .node .t { font-weight: 800; margin-bottom: 4px; }
    .node .d { color: var(--muted); font-size: 12px; line-height: 1.35; }
    .node.active { border-color: rgba(120,200,255,.35); background: rgba(120,200,255,.10); }
    .node.done { border-color: rgba(120,255,180,.35); background: rgba(120,255,180,.08); }
    .inventory { display:grid; gap: 8px; margin-top: 10px; }
    .item { padding: 10px 12px; border-radius: 14px; border: 1px solid var(--border); background: rgba(255,255,255,.04); font-size: 13px; }
    .item .name { font-weight: 800; margin-bottom: 2px; }
    .item .desc { color: var(--muted); font-size: 12px; line-height: 1.35; }
    .foot { color: var(--muted); font-size: 12px; margin-top: 10px; line-height: 1.35; }
    .kbd { font-family: var(--mono); font-size: 12px; padding: 2px 6px; border-radius: 8px; border: 1px solid var(--border); background: rgba(255,255,255,.05); }

    /* --- music controls --- */
    #musicVol{
      width: 140px;
      height: 28px;
      vertical-align: middle;
      accent-color: rgba(120,200,255,.85);
      opacity: .92;
    }

  </style>
</head>
<body>
  <div class="wrap">
    <header>
      <div class="brand">
        <div class="logo">CQ</div>
        <div>
          <h1>Copilot Quest</h1>
          <div class="subtitle">Adventure-styled multiple-choice practice game (offline, single file)</div>
        </div>
      </div>
      <div class="btnrow">
        <button class="small" id="btnSound">Sound: On</button>
        <button class="small" id="btnMusic">Music: On</button>
        <input id="musicVol" type="range" min="0" max="100" value="25" title="Music volume" />
        <button class="small" id="btnSave">Save</button>
        <button class="small" id="btnLoad">Load</button>
        <button class="small danger" id="btnReset">Reset</button>
      </div>
    </header>

    <div class="grid">
      <section class="card">
        <div class="hd">
          <div>
            <span class="pill" id="badgeRegion">Region: —</span>
            <span class="pill" id="badgeProgress">Progress: —</span>
          </div>
          <div class="btnrow">
            <button class="primary" id="btnPrimary">Start</button>
          </div>
        </div>
        <div class="bd">
          <p class="question" id="story"></p>
          <div id="qArea" style="display:none;">
            <p class="question" id="qText"></p>
            <div class="hint" id="qHint"></div>
            <div class="choices" id="choices"></div>
          </div>
          <div class="msg" id="msg" style="display:none;"></div>

          <div class="foot">
            Tip: For multi-select questions, pick the exact set of answers (order doesn’t matter). Your state is saved to your browser via <span class="kbd">Save</span>/<span class="kbd">Load</span>.
          </div>
        </div>
      </section>

      <aside class="card">
        <div class="hd">
          <div><strong>Adventurer Sheet</strong></div>
          <div class="pill" id="badgeMode">Mode: —</div>
        </div>
        <div class="bd">
          <div class="stats">
            <div class="stat">
              <div class="k">HP</div>
              <div class="v hearts" id="hp"></div>
            </div>
            <div class="stat">
              <div class="k">Level</div>
              <div class="v" id="lvl"></div>
            </div>
            <div class="stat">
              <div class="k">XP</div>
              <div class="v" id="xp"></div>
            </div>
            <div class="stat">
              <div class="k">Gold</div>
              <div class="v" id="gold"></div>
            </div>
          </div>

          <h3 style="margin:14px 0 8px 0; font-size:14px;">Map</h3>
          <div class="map" id="map"></div>

          <h3 style="margin:14px 0 8px 0; font-size:14px;">Inventory</h3>
          <div class="inventory" id="inv"></div>
        </div>
      </aside>
    </div>
  </div>

<script>
  const QUESTION_BANK = [
    {"id": "T1-Q1", "topic": 1, "qnum": 1, "stem": "⚔️ The Excel Caverns Guardian challenges you!\n'Adventurer, you seek to harness Copilot's power within the sacred Excel Caverns. But which TWO of these magical abilities does the Excel spirit truly grant?'\nNOTE: Each correct choice is worth one point.", "options": [{"id": "A", "text": "Customize the conditional formatting rules for your data."}, {"id": "B", "text": "Insert a custom chart that has specific formatting."}, {"id": "C", "text": "Generate a summary of key insights from your data."}, {"id": "D", "text": "Build a pivot table based on your data."}], "answer": ["C", "D"], "multi": true},
    {"id": "T1-Q2", "topic": 1, "qnum": 2, "stem": "📜 The Word Citadel Scribe awaits!\n'Brave scholar, you enter the Word Citadel seeking Copilot's wisdom. Which TWO tasks can the Scribe's magic truly perform for your scrolls and documents?'\nNOTE: Each correct choice is worth one point.", "options": [{"id": "A", "text": "Insert a table of contents based on the headings in your document."}, {"id": "B", "text": "Customize the page margins to match your company's document standards."}, {"id": "C", "text": "Generate a summary of the key points in your document."}, {"id": "D", "text": "Insert a custom watermark that has specific text and formatting."}], "answer": ["A", "C"], "multi": true},
    {"id": "T1-Q3", "topic": 1, "qnum": 3, "stem": "⚓ The Outlook Docks Harbormaster calls out!\n'Sailor of messages, you seek Copilot's aid at the Outlook Docks. Which TWO powers can the Harbormaster's enchantment grant you in managing your message vessels?'\nNOTE: Each correct choice is worth one point.", "options": [{"id": "A", "text": "Insert a custom HTML signature that has specific formatting."}, {"id": "B", "text": "Generate a draft response to an email based on the context of the conversation."}, {"id": "C", "text": "Create a summary of unread emails in your inbox."}, {"id": "D", "text": "Customize the folder structure to organize your emails."}], "answer": ["B", "C"], "multi": true},
    {"id": "T1-Q4", "topic": 1, "qnum": 4, "stem": "🎭 The PowerPoint Peaks Oracle speaks!\n'Presenter of visions, you carry a Copilot license and climb the PowerPoint Peaks. Which TWO abilities does the Oracle's magic bestow upon your presentation slides?'\nNOTE: Each correct choice is worth one point.", "options": [{"id": "A", "text": "Insert a custom animation for a specific object on a slide."}, {"id": "B", "text": "Create a slide layout based on the content of your presentation."}, {"id": "C", "text": "Customize the design theme of your presentation to match your company's branding."}, {"id": "D", "text": "Produce a summary slide based on the key points in your presentation."}], "answer": ["B", "D"], "multi": true},
    {"id": "T1-Q5", "topic": 1, "qnum": 5, "stem": "🍺 The Teams Tavern Keeper tests you!\n'Gatherer of allies, you enter the Teams Tavern seeking Copilot's companionship. Which TWO services can the Tavern Keeper's enchanted assistance truly provide?'\nNOTE: Each correct choice is worth one point.", "options": [{"id": "A", "text": "Mute and unmute participants in a meeting based on their location."}, {"id": "B", "text": "Create a custom background and add the background to your video calls."}, {"id": "C", "text": "Create a meeting summary, including key decisions and action items."}, {"id": "D", "text": "Draft a response to a channel message based on the context of the conversation."}], "answer": ["C", "D"], "multi": true},
    {"id": "T1-Q6", "topic": 1, "qnum": 6, "stem": "🔮 A mysterious scroll arrives!\n'A merchant from a distant guild sends you a magical scroll with a prompt link. When you unfurl it, the runes fade: \"Prompt not found. Sorry, it looks like the prompt is no longer available.\" What curse causes this vanishing?'", "options": [{"id": "A", "text": "The prompt is outdated."}, {"id": "B", "text": "The prompt is outside of your organization."}, {"id": "C", "text": "The prompt contains a reference to a file that you do NOT have access to."}, {"id": "D", "text": "The prompt is a scheduled prompt."}, {"id": "E", "text": "The prompt contains a file that has a sensitivity label applied."}], "answer": ["B"], "multi": false},
    {"id": "T1-Q7", "topic": 1, "qnum": 7, "stem": "📂 The enchanted archive rejects your spell!\n'You cast a saved prompt seeking to summarize File.docx, but the archive spirit responds: \"You asked for a summary of File.docx. However, the file appears to be either empty, corrupted, or in a format that I cannot process.\" What barrier blocks your access?'", "options": [{"id": "A", "text": "You did NOT schedule the prompt to run."}, {"id": "B", "text": "You ran the prompt from a web app instead of a desktop app."}, {"id": "C", "text": "You used the wrong agent to run the prompt."}, {"id": "D", "text": "You do NOT have access to the file."}], "answer": ["D"], "multi": false},
    {"id": "T1-Q8", "topic": 1, "qnum": 8, "stem": "🖼️ Mysterious images appear in your pack!\n'A fellow adventurer sends you several curious images. You suspect these may be conjured by the AI spirits of Copilot. What magical signature can you examine to verify their true origin?'", "options": [{"id": "A", "text": "file names"}, {"id": "B", "text": "watermarks"}, {"id": "C", "text": "content credentials"}, {"id": "D", "text": "file descriptions"}], "answer": ["C"], "multi": false},
    {"id": "T1-Q9", "topic": 1, "qnum": 9, "stem": "⚠️ A cautionary tale of the Merchant!\n'A merchant planning for the harvest season asks Copilot's oracle to divine which goods to stock based on ancient sales ledgers. Without consulting the market or verifying the prophecy, the merchant orders vast quantities based solely on the oracle's vision. What perilous mistake has the merchant made?'", "options": [{"id": "A", "text": "verification"}, {"id": "B", "text": "overreliance"}, {"id": "C", "text": "fabrication"}, {"id": "D", "text": "prompt injection"}], "answer": ["B"], "multi": false},
    {"id": "T1-Q10", "topic": 1, "qnum": 10, "stem": "🔍 The Twin Spirits riddle!\n'Two powerful spirits exist in this realm: Microsoft 365 Copilot and Microsoft 365 Copilot Chat. A sage asks you: which magical artifact is blessed to BOTH spirits and accessible in either form?'", "options": [{"id": "A", "text": "the Researcher agent"}, {"id": "B", "text": "Copilot Pages"}, {"id": "C", "text": "Copilot Notebooks"}], "answer": ["B"], "multi": false},
    {"id": "T1-Q11", "topic": 1, "qnum": 11, "stem": "🏛️ The High Council's inquiry!\n'A fellow adventurer asks you about the mystical Work Scope: When Copilot searches within this sacred domain, what sources does it draw upon to answer your queries? Enlighten them with the truth!'", "options": [{"id": "A", "text": "Copilot provides responses based only on data that the user can access and the general knowledge that Copilot was trained on."}, {"id": "B", "text": "Copilot provides responses based on all the data in your organization's Microsoft 365 environment and the general knowledge that Copilot was trained on."}, {"id": "C", "text": "Copilot provides responses based only on data that the user can access."}, {"id": "D", "text": "Copilot provides responses based only on the general knowledge that Copilot was trained on."}], "answer": ["A"], "multi": false},
    {"id": "T1-Q12a", "topic": 1, "qnum": 121, "stem": "⚖️ Truth or False: The Teams Chat Mystery!\n'The spirits whisper a claim: Microsoft 365 Copilot can surface data from your Microsoft Teams chats. Does this power truly exist?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T1-Q12b", "topic": 1, "qnum": 122, "stem": "⚖️ Truth or False: The Automated Messenger!\n'A rumor spreads: Microsoft 365 Copilot can schedule, draft, AND automatically send emails based on certain conditions. Is this enchantment real?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["No"], "multi": false},
    {"id": "T1-Q12c", "topic": 1, "qnum": 123, "stem": "⚖️ Truth or False: The Meeting Chronicler!\n'Tales are told that Microsoft 365 Copilot can summarize, draft, and answer questions about content from your Microsoft Teams meetings. Is this power genuine?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T1-Q13a", "topic": 1, "qnum": 131, "stem": "⚖️ Truth or False: The Training Grounds!\n'A dangerous myth circulates: Microsoft 365 Copilot is trained on your organization's secret business data. Does this happen?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["No"], "multi": false},
    {"id": "T1-Q13b", "topic": 1, "qnum": 132, "stem": "⚖️ Truth or False: The Shared Mailbox Oracle!\n'Word spreads: Microsoft 365 Copilot can peer into and summarize emails from mailboxes that others have shared with you. Is this within its powers?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T1-Q13c", "topic": 1, "qnum": 133, "stem": "⚖️ Truth or False: The Security Ward!\n'They say Microsoft 365 Copilot leverages the protective security framework of Microsoft 365 itself, granting you access only to emails and documents you're already permitted to see. Is this safeguard true?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T1-Q14a", "topic": 1, "qnum": 141, "stem": "⚖️ Truth or False: The Administrator's Lock!\n'A nervous whisper claims: You can delete your conversation history ONLY if the realm's administrator grants you permission to do so. Is this restriction real?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["No"], "multi": false},
    {"id": "T1-Q14b", "topic": 1, "qnum": 142, "stem": "⚖️ Truth or False: The Cascading Deletion!\n'Fear grips the hall: When you erase a conversation, all associated files stored in the SharePoint vaults also vanish forever. Does deleting one destroy the other?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["No"], "multi": false},
    {"id": "T1-Q14c", "topic": 1, "qnum": 143, "stem": "⚖️ Truth or False: The Agent's Memory!\n'Legend tells: When you banish a Copilot agent by uninstalling it, all conversations you had with that agent remain preserved in the archives. Is this memory persistent?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T1-Q15a", "topic": 1, "qnum": 151, "stem": "⚖️ Truth or False: The Forbidden Training!\n'Dark rumors swirl: Microsoft 365 Copilot uses your precious business data to train its underlying AI models, absorbing your secrets. Does it consume your data this way?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["No"], "multi": false},
    {"id": "T1-Q15b", "topic": 1, "qnum": 152, "stem": "⚖️ Truth or False: The Permission Granter!\n'A dangerous claim emerges: Microsoft 365 Copilot automatically assigns permissions to resources, making information easier to find by granting access freely. Does it alter permissions?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["No"], "multi": false},
    {"id": "T1-Q15c", "topic": 1, "qnum": 153, "stem": "⚖️ Truth or False: The Sacred Access Controls!\n'The wise elders teach: Microsoft 365 Copilot uses the same underlying access controls as other Microsoft 365 services, showing you only information you already have permission to see. Is this protection in place?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T1-Q16a", "topic": 1, "qnum": 161, "stem": "⚖️ Truth or False: The Injection Threat!\n'Security scouts warn: Prompt injection can cause dangerous data exposure and make the system behave in unintended ways. Is this threat real?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T1-Q16b", "topic": 1, "qnum": 162, "stem": "⚖️ Truth or False: The Malicious Embedding!\n'Defenders caution: Prompt injection can be weaponized to embed malicious or harmful instructions into the AI's responses. Can it be used for evil?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T1-Q16c", "topic": 1, "qnum": 163, "stem": "⚖️ Truth or False: The Unique Vulnerability!\n'Scholars debate: Prompt injection is a security vulnerability that exists ONLY in generative AI systems that understand and respond to natural language. Is it unique to AI?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T1-Q18", "topic": 1, "qnum": 18, "stem": "📖 The Glowing Codex mystery!\n'You open your Copilot grimoire and notice the \"Standings\" conversation glows with a bold title and green icon. This magical marking indicates something special. What does this enchanted symbol mean?'", "options": [{"id": "A", "text": "The conversation contains only anonymous data."}, {"id": "B", "text": "The conversation contains a verified response."}, {"id": "C", "text": "The conversation was added to a notebook."}, {"id": "D", "text": "The conversation contains a scheduled prompt."}, {"id": "E", "text": "The conversation was shared."}], "answer": ["D"], "multi": false},
    {"id": "T1-Q19", "topic": 1, "qnum": 19, "stem": "🔒 The Great Protection Seal!\n'The realm's guardian spirits ask: What powerful enchantment ensures that your business data stays safely within your Microsoft 365 realm and is NEVER used to train the AI overlords?'", "options": [{"id": "A", "text": "The Common Data Model"}, {"id": "B", "text": "Enterprise data protection (EDP)"}, {"id": "C", "text": "Sensitivity labels"}, {"id": "D", "text": "Zero Trust"}], "answer": ["B"], "multi": false},
    {"id": "T1-Q20", "topic": 1, "qnum": 20, "stem": "🗑️ The Purging Portal!\n'You journey to the Microsoft 365 My Account portal to cleanse your Copilot activity history. When you invoke \"Delete history,\" what exactly is erased from existence?'", "options": [{"id": "A", "text": "a specific conversation."}, {"id": "B", "text": "a specific date range of activity."}, {"id": "C", "text": "all the Microsoft 365 Copilot activity."}, {"id": "D", "text": "all conversations with a specific agent."}], "answer": ["C"], "multi": false},
    {"id": "T1-QExtra1", "topic": 1, "qnum": 201, "stem": "🧪 The Productivity Philosophers!\n'The grand council debates: What are the TRUE ways that generative AI magic can enhance the productivity of business adventurers across the realm?'", "options": [{"id": "A", "text": "By automating repetitive tasks and providing creative suggestions"}, {"id": "B", "text": "By replacing all human decision-making"}, {"id": "C", "text": "By requiring advanced programming skills for every user"}, {"id": "D", "text": "By ignoring data privacy concerns"}], "answer": ["A"], "multi": false},
    {"id": "T1-QExtra2", "topic": 1, "qnum": 202, "stem": "🧑‍⚖️ The Ethics Inquisition!\n'The High Court of Responsible AI teaches four sacred principles. But one impostor hides among them! Which of these is NOT a true core principle of responsible AI?'", "options": [{"id": "A", "text": "Fairness"}, {"id": "B", "text": "Transparency"}, {"id": "C", "text": "Accountability"}, {"id": "D", "text": "Profitability"}], "answer": ["D"], "multi": false},
    {"id": "T1-QExtra3", "topic": 1, "qnum": 203, "stem": "🔐 The Trust Enchantment!\n'Security mages ask: How does Microsoft 365 Copilot ensure that its AI powers are wielded securely and responsibly, protecting the realm from chaos?'", "options": [{"id": "A", "text": "By providing grounded responses and privacy safeguards"}, {"id": "B", "text": "By sharing user data for model training"}, {"id": "C", "text": "By allowing unrestricted content generation"}, {"id": "D", "text": "By ignoring regional compliance"}], "answer": ["A"], "multi": false},
    {"id": "T1-QExtra4", "topic": 1, "qnum": 204, "stem": "👥 The Human Guardian's Role!\n'The ancient scrolls speak of human oversight in this age of AI enchantment. What sacred duty do humans hold in guiding AI-driven decisions?'", "options": [{"id": "A", "text": "Monitoring AI outputs for inaccuracies or biases"}, {"id": "B", "text": "Ensuring humans remain the final arbiters in critical decisions"}, {"id": "C", "text": "Providing feedback to improve AI systems"}, {"id": "D", "text": "All of the above"}], "answer": ["D"], "multi": false},
    {"id": "T2-Q21", "topic": 2, "qnum": 21, "stem": "🔥 The Ephemeral Chamber!\n'You enter the Notebook Labyrinth and start a temporary chat in a hidden chamber. When you exit to start a new chat elsewhere, what fate befalls all the prompts and responses from that temporary chamber?'", "options": [{"id": "A", "text": "deleted immediately."}, {"id": "B", "text": "deleted after one hour."}, {"id": "C", "text": "moved to a private notebook."}, {"id": "D", "text": "moved to your Microsoft OneDrive."}], "answer": ["A"], "multi": false},
    {"id": "T2-Q22", "topic": 2, "qnum": 22, "stem": "🧠 The Memory Eraser's Dilemma!\n'You used Copilot to plan an epic quest (a trip), asking it to remember many details. But the quest is cancelled! You need Copilot to forget everything. What spell must you cast?'", "options": [{"id": "A", "text": "From the My Account portal, delete the Copilot activity history."}, {"id": "B", "text": "From Copilot, delete memories."}, {"id": "C", "text": "From Copilot, delete custom instructions."}, {"id": "D", "text": "From Copilot, delete all the conversation about the trip."}], "answer": ["B"], "multi": false},
    {"id": "T2-Q23", "topic": 2, "qnum": 23, "stem": "📊 The Budget Battle Preparation!\n'As a marketing assistant, you face a crucial budget meeting. You must analyze spending trends and ROI from the past year's campaigns. Which Copilot companion should you summon for this analytical quest? Choose the BEST ally.'", "options": [{"id": "A", "text": "the Analyst agent"}, {"id": "B", "text": "Chat"}, {"id": "C", "text": "the Researcher agent"}, {"id": "D", "text": "a notebook"}], "answer": ["A"], "multi": false},
    {"id": "T2-Q24", "topic": 2, "qnum": 24, "stem": "📓 The Scattered Pages Mystery!\n'You possess several Copilot pages filled with research for a new product. They're scattered across the labyrinth! You need to organize them so you can have many conversations about them without losing your way. What's your first move?'", "options": [{"id": "A", "text": "Create a story."}, {"id": "B", "text": "Add the pages to a notebook."}, {"id": "C", "text": "Add the pages to a conversation."}, {"id": "D", "text": "Download the pages locally."}], "answer": ["B"], "multi": false},
    {"id": "T2-Q25", "topic": 2, "qnum": 25, "stem": "🧮 The Analytics Agent's Arsenal!\n'You're crafting a custom analytics agent to process Excel sales data within the labyrinth. This agent must create visualizations, perform calculations, and analyze patterns. What magical ability must you grant it?'", "options": [{"id": "A", "text": "a suggested prompt"}, {"id": "B", "text": "code interpreter"}, {"id": "C", "text": "image generator"}, {"id": "D", "text": "a template"}], "answer": ["B"], "multi": false},
    {"id": "T2-Q26", "topic": 2, "qnum": 26, "stem": "🎪 The Gallery of Famous Prompts!\n'You craft a brilliant prompt to draft project reports and dream of sharing it in the legendary Copilot Prompt Gallery for all to admire. What's your first step toward gallery fame?'", "options": [{"id": "A", "text": "Create a notebook."}, {"id": "B", "text": "Add an agent."}, {"id": "C", "text": "Create a page."}, {"id": "D", "text": "Run the prompt."}], "answer": ["C"], "multi": false},
    {"id": "T2-Q27", "topic": 2, "qnum": 27, "stem": "💾 The Frozen File Paradox!\n'You create a notebook and upload Process.docx from your local storage. Yesterday, you updated that same file locally. Now when you chat in the notebook, which version will the spirits reference?'", "options": [{"id": "A", "text": "The chat will reference the most recent version of Process.docx."}, {"id": "B", "text": "The chat will reference both versions of Process.docx."}, {"id": "C", "text": "The chat will reference only the original version of Process.docx."}], "answer": ["C"], "multi": false},
    {"id": "T2-Q28", "topic": 2, "qnum": 28, "stem": "🗂️ The Conversation Collector's Quest!\n'You have many separate Copilot conversations scattered throughout the labyrinth. You want to gather them together so they're easier to find and can all share the same reference scrolls. What's the BEST organizational tool?", "options": [{"id": "A", "text": "a notebook"}, {"id": "B", "text": "an agent"}, {"id": "C", "text": "an app"}, {"id": "D", "text": "a page"}], "answer": ["A"], "multi": false},
    {"id": "T2-Q29", "topic": 2, "qnum": 29, "stem": "📔 The Notebook's True Purpose!\n'A wise sage asks you: What is the sacred purpose of a notebook in this Microsoft 365 Copilot realm? What power does it truly hold?'", "options": [{"id": "A", "text": "to create a transcript of a conversation that you can easily email to other users"}, {"id": "B", "text": "to provide a private location that can be used to organize reference materials across related conversations"}, {"id": "C", "text": "to generate a summary of all the interactions you had with Copilot during a specific conversation"}], "answer": ["B"], "multi": false},
    {"id": "T2-Q30", "topic": 2, "qnum": 30, "stem": "📊 The Excel Summoning!\n'Your Excel workbook contains a table of sales data with OrderDate, OrderNumber, and Amount columns. You seek to summon Copilot to generate a monthly summary. Which ingredient is MOST essential in your summoning prompt?", "options": [{"id": "A", "text": "the desired format of the response"}, {"id": "B", "text": "a specific cell range from the worksheet"}, {"id": "C", "text": "the file name of the workbook"}, {"id": "D", "text": "the clear goal of the summary"}, {"id": "E", "text": "a formula to calculate monthly totals"}], "answer": ["D"], "multi": false},
    {"id": "T2-Q31", "topic": 2, "qnum": 31, "stem": "⚓ The Grounding Anchor!\n'You craft a prompt seeking information about a partnership proposal. You MUST ensure the response is firmly anchored (grounded) in the actual proposal data, not floating in the winds of speculation. What's the BEST way to anchor it?", "options": [{"id": "A", "text": "Add context about the intended audience."}, {"id": "B", "text": "Instruct Copilot to rely on its training data to infer proposal details."}, {"id": "C", "text": "Reference the proposal content in the prompt."}, {"id": "D", "text": "Add a specific goal that you want Copilot to accomplish."}], "answer": ["C"], "multi": false},
    {"id": "T2-Q32", "topic": 2, "qnum": 32, "stem": "🎯 The Master of Grounding!\n'You navigate the labyrinth's twisted paths and seek to improve prompt-grounding during your Copilot conversations. Which technique strengthens grounding MOST effectively?", "options": [{"id": "A", "text": "Use shorter prompts."}, {"id": "B", "text": "Provide the desired output format."}, {"id": "C", "text": "Avoid technical jargon."}, {"id": "D", "text": "Reference specific files."}], "answer": ["D"], "multi": false},
    {"id": "T2-Q33", "topic": 2, "qnum": 33, "stem": "🌐 The Living SharePoint Document!\n'You create a notebook and link Process.docx from a SharePoint site (not local storage). Yesterday, another sage updated that SharePoint file. When you chat in the notebook now, which version emerges?", "options": [{"id": "A", "text": "The chat will reference only the original version of Process.docx."}, {"id": "B", "text": "The chat will reference the most recent version of Process.docx."}, {"id": "C", "text": "The chat will reference both versions of Process.docx."}], "answer": ["B"], "multi": false},
    {"id": "T2-Q34", "topic": 2, "qnum": 34, "stem": "🔥 The Confidential Conversation Crisis!\n'Disaster! You had a conversation that referenced highly confidential knowledge sources. You need to delete it immediately without seeking administrator blessing, but you want to keep your other conversations safe. Where do you go?", "options": [{"id": "A", "text": "the Microsoft 365 admin center"}, {"id": "B", "text": "the My Account portal in Microsoft 365 Copilot"}, {"id": "C", "text": "the Microsoft Purview compliance portal"}, {"id": "D", "text": "the Microsoft 365 Copilot app"}], "answer": ["B"], "multi": false},
    {"id": "T2-Q35", "topic": 2, "qnum": 35, "stem": "🤖 The Agent Summoning Ritual!\n'You're mid-conversation in the labyrinth when you remember you need Agent1's specialized wisdom. What magical incantation (symbol) must you type to summon Agent1 into your current chat?'", "options": [{"id": "A", "text": "[Agent1]"}, {"id": "B", "text": "#Agent1"}, {"id": "C", "text": "/Agent1"}, {"id": "D", "text": "@Agent1"}], "answer": ["D"], "multi": false},
    {"id": "T2-Q36", "topic": 2, "qnum": 36, "stem": "📦 The Five Sacred Scrolls!\n'You carry five important files that you upload repeatedly to your Copilot chats. The repetition grows tiresome! Which TWO methods can simplify referencing these files forever?\nNOTE: Each correct selection is worth one point.", "options": [{"id": "A", "text": "Create an agent that has a knowledge source."}, {"id": "B", "text": "Send a prompt that includes the files, and then save the prompt."}, {"id": "C", "text": "Create a notebook that references the files."}, {"id": "D", "text": "Ask the data engineers to create a fine-tuned model."}, {"id": "E", "text": "Zip the documents and upload the ZIP file to the chats."}], "answer": ["A", "C"], "multi": true},
    {"id": "T2-Q37", "topic": 2, "qnum": 37, "stem": "🆓 The Unlicensed Wanderer's Sources!\n'You possess a Microsoft 365 subscription but NO Copilot license. When you send a prompt in Copilot Chat anyway, which THREE sources does the Chat spirit draw upon to answer you?\nNOTE: Each correct selection is worth one point.", "options": [{"id": "A", "text": "chat data in Microsoft Teams"}, {"id": "B", "text": "your organization's databases"}, {"id": "C", "text": "the prompt context"}, {"id": "D", "text": "organizational data in Microsoft 365"}, {"id": "E", "text": "internet search data"}, {"id": "F", "text": "the conversation history"}], "answer": ["C", "E", "F"], "multi": true},
    {"id": "T2-Q38", "topic": 2, "qnum": 38, "stem": "👥 The Project Agent's Reach!\n'You're a project coordinator who crafted a custom agent to track milestones and draft reports. The agent carries your Copilot license's power. With whom can you share this magical assistant?'", "options": [{"id": "A", "text": "only the people in your organization"}, {"id": "B", "text": "the people in your organization and people that have personal Microsoft accounts"}, {"id": "C", "text": "only Microsoft Teams channel members"}, {"id": "D", "text": "any person who has a valid email address"}], "answer": ["A"], "multi": false},
    {"id": "T2-Q39a", "topic": 2, "qnum": 391, "stem": "⚖️ Truth or False: Custom Instructions on New Chats!\n'You inscribe custom instructions into Copilot. The prophecy states: These instructions will guide all NEW chat conversations you start. Does this prophecy hold true?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T2-Q39b", "topic": 2, "qnum": 392, "stem": "⚖️ Truth or False: Instructions for Specialized Agents!\n'You add custom instructions to Copilot. Some claim these same instructions will automatically apply to conversations with the Researcher agent and Analyst agent. Is this extension of power real?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["No"], "multi": false},
    {"id": "T2-Q39c", "topic": 2, "qnum": 393, "stem": "⚖️ Truth or False: Retroactive Instruction Power!\n'You add custom instructions now. A tale spreads: These instructions will travel back in time and apply to previous responses in conversations you've already had. Can instructions rewrite history?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["No"], "multi": false},
    {"id": "T2-Q40a", "topic": 2, "qnum": 401, "stem": "⚖️ Truth or False: Sharing with Outsiders!\n'You forge an agent using a sacred template. A wanderer asks: Can you share this agent with external users beyond your organization's walls? Is this possible?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["No"], "multi": false},
    {"id": "T2-Q40b", "topic": 2, "qnum": 402, "stem": "⚖️ Truth or False: Choosing Agent Knowledge!\n'You create an agent from a template. The codex states: You can choose exactly which knowledge sources this agent may access and consult. Is this control granted to you?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T2-Q40c", "topic": 2, "qnum": 403, "stem": "⚖️ Truth or False: Internal Agent Sharing!\n'You create an agent from a template. The guild rules say: You can share this agent with other members inside your organization. Does this sharing power exist?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T2-Q41a", "topic": 2, "qnum": 411, "stem": "⚖️ Truth or False: The Activity Chronicle!\n'Archivists claim: You can review your complete Copilot activity history by visiting the My Account portal. Is this viewing chamber accessible?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T2-Q41b", "topic": 2, "qnum": 412, "stem": "⚖️ Truth or False: The Notebook Cascade!\n'Fear spreads: When you delete your Copilot activity history, all associated notebooks and pages are immediately obliterated alongside it. Does deletion cascade this way?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["No"], "multi": false},
    {"id": "T2-Q41c", "topic": 2, "qnum": 413, "stem": "⚖️ Truth or False: The Complete Purge!\n'The deletion scrolls state: Users can delete their ENTIRE Copilot activity history, including every prompt they sent and every response received. Is this total erasure possible?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T2-Q42a", "topic": 2, "qnum": 421, "stem": "⚖️ Truth or False: Identical Web Responses!\n'A test is proposed: Submit the same prompt to Copilot multiple times while grounded in the web. Will the responses ALWAYS be identical, word for word?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["No"], "multi": false},
    {"id": "T2-Q42b", "topic": 2, "qnum": 422, "stem": "⚖️ Truth or False: Identical Data Responses!\n'Another test: Submit the same prompt repeatedly while grounded in your own organization's data. Will you receive the exact same response every single time?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["No"], "multi": false},
    {"id": "T2-Q42c", "topic": 2, "qnum": 423, "stem": "⚖️ Truth or False: Identical Model-Only Responses!\n'The final test: Submit the same prompt multiple times, grounded ONLY in the model's inherent knowledge (no web, no data). Will the responses always be perfectly identical?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["No"], "multi": false},
    {"id": "T2-Q43a", "topic": 2, "qnum": 431, "stem": "⚖️ Truth or False: Context-Aware Suggestions!\n'The wise ones teach: Copilot uses contextual information from your organization to suggest helpful prompts. Does it possess this contextual awareness?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T2-Q43b", "topic": 2, "qnum": 432, "stem": "⚖️ Truth or False: Training the LLM!\n'A dangerous rumor: Copilot uses your organization's contextual information to actively train and improve the large language model itself. Does it feed the LLM this way?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["No"], "multi": false},
    {"id": "T2-Q43c", "topic": 2, "qnum": 433, "stem": "⚖️ Truth or False: Prompt Augmentation!\n'Knowledge keepers explain: Copilot uses your organization's contextual information to augment and enrich your prompt BEFORE sending it to the LLM. Is this augmentation ritual real?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T2-QExtra1", "topic": 2, "qnum": 501, "stem": "🌐 The Tale of Two Modes!\n'A scholar poses a riddle: What is the fundamental difference between Work mode and Web mode in the Copilot Chat realm? Which source does each draw upon?'", "options": [{"id": "A", "text": "Work mode uses public web data, while Web mode uses organizational work data."}, {"id": "B", "text": "Work mode is only available in Teams, while Web mode is available in Word."}, {"id": "C", "text": "Work mode grounds responses in your organizational work data, while Web mode grounds responses in public web data."}, {"id": "D", "text": "There is no difference; both modes use the same data sources."}], "answer": ["C"], "multi": false},
    {"id": "T2-QExtra2", "topic": 2, "qnum": 502, "stem": "🛑 The Anti-Pattern Trap!\n'The Prompt Masters teach best practices for crafting Chat prompts. But one practice is FALSE and leads to confusion! Which of these is NOT a recommended practice?'", "options": [{"id": "A", "text": "Be clear and specific"}, {"id": "B", "text": "Provide instructions on topic, purpose, tone, and required length"}, {"id": "C", "text": "Use slang or jargon"}, {"id": "D", "text": "Give examples"}], "answer": ["C"], "multi": false},
    {"id": "T2-QExtra3", "topic": 2, "qnum": 503, "stem": "✨ The Specificity Spell!\n'A novice asks: How can I make my Copilot Chat prompts more actionable and laser-focused? What technique brings clarity and precision?'", "options": [{"id": "A", "text": "By referencing files, people, or topics using special symbols like /"}, {"id": "B", "text": "By keeping prompts vague and general"}, {"id": "C", "text": "By using only one-word instructions"}, {"id": "D", "text": "By avoiding any references to files or people"}], "answer": ["A"], "multi": false},
    {"id": "T2-QExtra4", "topic": 2, "qnum": 504, "stem": "⏰ The Scheduling Enchantment!\n'Time mages speak of scheduling prompts in Copilot Chat. What magical benefit does this automation bring to your daily quests?'", "options": [{"id": "A", "text": "It allows you to automate recurring tasks, such as daily summaries, without manual input each time."}, {"id": "B", "text": "It deletes old conversations automatically."}, {"id": "C", "text": "It changes the Copilot Chat interface color."}, {"id": "D", "text": "It disables optional connected experiences."}], "answer": ["A"], "multi": false},
    {"id": "T3-Q44a", "topic": 3, "qnum": 441, "stem": "⚖️ Truth or False: The Forge's Model Knowledge!\n'At the Content Forge, smiths say: Copilot can call upon its own vast model knowledge to make prompt responses more specific and refined. Can it wield this internal wisdom?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T3-Q44b", "topic": 3, "qnum": 442, "stem": "⚖️ Truth or False: The Business Data Enhancement!\n'Forge masters teach: Copilot can weave your business data into responses, adding rich context to make them more specific. Does it have this power?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T3-Q44c", "topic": 3, "qnum": 443, "stem": "⚖️ Truth or False: The Web's Fresh Knowledge!\n'Artisans claim: Copilot can reach beyond your walls to fetch the latest information from the web, enriching prompts with current context. Is this web-reaching ability real?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T3-Q45", "topic": 3, "qnum": 45, "stem": "🎯 The Agent Introduction Tool!\n'You forge a custom agent at the Content Forge. To help users begin conversations and understand how to wield this agent effectively, what feature should you provide?'", "options": [{"id": "A", "text": "agent settings"}, {"id": "B", "text": "capabilities"}, {"id": "C", "text": "instructions"}, {"id": "D", "text": "suggested prompts"}], "answer": ["D"], "multi": false},
    {"id": "T3-Q46", "topic": 3, "qnum": 46, "stem": "📋 The Partnership Summary Challenge!\n'You must forge a summary of a partnership proposal as a bulleted list (3-5 points) for a kickoff meeting. Each point must be concise and simple. Which TWO ingredients are ESSENTIAL in your prompt recipe?\nNOTE: Each correct selection is worth one point.", "options": [{"id": "A", "text": "a list of contact details for key stakeholders of the partnership"}, {"id": "B", "text": "profiles of both companies generated by using the Researcher agent"}, {"id": "C", "text": "a specific knowledge source to ground the response"}, {"id": "D", "text": "concise instructions for what to do with the proposal"}], "answer": ["C", "D"], "multi": true},
    {"id": "T3-Q47", "topic": 3, "qnum": 47, "stem": "🤝 The Collaboration Forge!\n'You generate a report in a Copilot conversation, then edit it in a page. Now you need a colleague to join your crafting efforts. Which TWO methods open collaboration?\nNOTE: Each correct selection is worth one point.", "options": [{"id": "A", "text": "Mention the colleague in the page."}, {"id": "B", "text": "Open the page in Microsoft Word."}, {"id": "C", "text": "Share the page link."}, {"id": "D", "text": "Add the page to a notebook."}], "answer": ["A", "C"], "multi": true},
    {"id": "T3-Q48", "topic": 3, "qnum": 48, "stem": "📹 The Meeting Memory Keeper!\n'You attend countless Teams meetings at the Forge. After each gathering ends, you need to catch up on key points and next steps. Which Copilot feature is your ally?'", "options": [{"id": "A", "text": "Recap"}, {"id": "B", "text": "Meeting Whiteboard"}, {"id": "C", "text": "Meeting info"}, {"id": "D", "text": "Thread summaries"}], "answer": ["A"], "multi": false},
    {"id": "T3-Q49", "topic": 3, "qnum": 49, "stem": "🎨 The Marketing Agent's Arsenal!\n'You forge a custom agent for the marketing team to produce collateral: copy, logos, and artwork. Which ability is MOST essential to grant this creative agent?", "options": [{"id": "A", "text": "code interpreter"}, {"id": "B", "text": "image generator"}, {"id": "C", "text": "a suggested prompt"}, {"id": "D", "text": "a template"}], "answer": ["B"], "multi": false},
    {"id": "T3-Q50", "topic": 3, "qnum": 50, "stem": "🔍 The Citation Wraith's Warning!\n'You use Copilot to forge a proposal in Word based on a SharePoint document. The Citation Wraith warns: Verify your sources or face consequences! What is the BEST method to ensure citation accuracy?'", "options": [{"id": "A", "text": "Manually verify the citations in the generated content."}, {"id": "B", "text": "Use Copilot in Word to verify the citations."}, {"id": "C", "text": "Create an agent that contains your organization's editorial standards and use the agent to verify the citations."}, {"id": "D", "text": "Create a notebook that contains all the reference material and use the notebook to verify the citations."}], "answer": ["A"], "multi": false},
    {"id": "T3-Q51a", "topic": 3, "qnum": 511, "stem": "⚖️ Truth or False: The Forbidden Meetings!\n'A curious claim: Copilot can answer questions about Teams meetings that you were NOT even invited to attend. Can it peer into gatherings beyond your reach?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["No"], "multi": false},
    {"id": "T3-Q51b", "topic": 3, "qnum": 512, "stem": "⚖️ Truth or False: The Comprehensive Teams Assistant!\n'Forge workers say: Copilot can provide summaries and answer questions about chat messages, channel posts, AND Teams meetings alike. Does it master all three domains?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T3-Q51c", "topic": 3, "qnum": 513, "stem": "⚖️ Truth or False: The Future Meeting Summoner!\n'Time seers claim: Copilot can provide a summary of ALL upcoming Teams meetings you're invited to next week, showing details before they happen. Is this foresight possible?'", "options": [{"id": "Yes", "text": "Yes"}, {"id": "No", "text": "No"}], "answer": ["Yes"], "multi": false},
    {"id": "T3-Q52", "topic": 3, "qnum": 52, "stem": "🕵️ The Researcher Agent Mystery!\n'You sign into the Copilot app with your work credentials. A colleague mentions they have access to the legendary Researcher agent, but you don't see it! What spell unlocks this agent for you?'", "options": [{"id": "A", "text": "Request a Microsoft 365 Copilot license from an administrator."}, {"id": "B", "text": "Select Explore agents and then search for Researcher."}, {"id": "C", "text": "Sign in to the Copilot app by using a personal account."}, {"id": "D", "text": "From Microsoft Edge, use your work account to sign in to https://copilot.microsoft.com."}], "answer": ["B"], "multi": false},
    {"id": "T3-Q53", "topic": 3, "qnum": 53, "stem": "🤖 The AI-Assisted Agent Builder!\n'At the forge, you want to leverage generative AI itself to help you BUILD a custom agent. Which mystical tab harnesses this AI creation power?'", "options": [{"id": "A", "text": "the Configure tab"}, {"id": "B", "text": "a Copilot notebook"}, {"id": "C", "text": "a Copilot page"}, {"id": "D", "text": "the Describe tab"}], "answer": ["A"], "multi": false},
    {"id": "T3-Q54a", "topic": 3, "qnum": 541, "stem": "⏳ The Scheduling Limits - Frequency!\n'Master schedulers teach two limitations of prompt scheduling magic. FIRST: How often can you schedule a prompt to run at minimum intervals?'", "options": [{"id": "A", "text": "Once per hour"}, {"id": "B", "text": "Once per day"}, {"id": "C", "text": "Once per week"}], "answer": ["B"], "multi": false},
    {"id": "T3-Q54b", "topic": 3, "qnum": 542, "stem": "⏳ The Scheduling Limits - Maximum Count!\n'Master schedulers teach two limitations of prompt scheduling magic. SECOND: What is the maximum number of times a scheduled prompt can run before it expires?'", "options": [{"id": "A", "text": "15 times"}, {"id": "B", "text": "365 times"}, {"id": "C", "text": "Unlimited"}], "answer": ["A"], "multi": false}
  ];

  const REGIONS = [
    {
      id: 1,
      title: "The App Isles (Topic 1)",
      desc: "Excel Caverns, Word Citadel, Outlook Docks, PowerPoint Peaks, Teams Tavern… prove you can wield Copilot across Microsoft 365 apps.",
      reward: "Badge of Productivity"
    },
    {
      id: 2,
      title: "The Notebook Labyrinth (Topic 2)",
      desc: "Notebooks, agents, grounding, prompts, and sharing rules. Keep your answers anchored or the labyrinth loops forever.",
      reward: "Grounding Compass"
    },
    {
      id: 3,
      title: "The Content Forge (Topic 3)",
      desc: "Draft, analyze, cite, and collaborate. Beware: the Citation Wraith punishes lazy verification.",
      reward: "Quill of Clarity"
    },
  ];

  // ---------- helpers ----------
  const $ = (id) => document.getElementById(id);
  const clamp = (n, a, b) => Math.max(a, Math.min(b, n));
  const sortLetters = (arr) => [...arr].sort();
  const eqSet = (a,b) => JSON.stringify(sortLetters(a)) === JSON.stringify(sortLetters(b));
  const nowIso = () => new Date().toISOString();
  // ---------- audio (offline SFX via Web Audio) ----------
  let audioCtx = null;
  let sfxEnabled = true;
  const SFX_KEY = "copilot-quest-sfx-enabled-v1";

  function loadSfxPref() {
    try {
      const v = localStorage.getItem(SFX_KEY);
      if (v === "0" || v === "1") sfxEnabled = (v === "1");
    } catch (e) {}
  }

  function saveSfxPref() {
    try { localStorage.setItem(SFX_KEY, sfxEnabled ? "1" : "0"); } catch (e) {}
  }

  function setSoundButton() {
    const b = $("btnSound");
    if (!b) return;
    const supported = !!(window.AudioContext || window.webkitAudioContext);
    if (!supported) {
      b.textContent = "Sound: Unsupported";
      b.disabled = true;
      return;
    }
    b.textContent = sfxEnabled ? "Sound: On" : "Sound: Off";
  }

  function initAudio() {
    if (!sfxEnabled) return;
    if (!audioCtx) {
      const AC = window.AudioContext || window.webkitAudioContext;
      if (!AC) return;
      audioCtx = new AC();
    }
    if (audioCtx.state === "suspended") audioCtx.resume();
  }

  function playTone(freq, duration = 0.07, type = "sine", gain = 0.05, when = 0) {
    if (!sfxEnabled) return;
    initAudio();
    if (!audioCtx) return;

    const t0 = audioCtx.currentTime + when;
    const osc = audioCtx.createOscillator();
    const g = audioCtx.createGain();

    osc.type = type;
    osc.frequency.setValueAtTime(freq, t0);

    // Simple "blip" envelope
    g.gain.setValueAtTime(0.0001, t0);
    g.gain.exponentialRampToValueAtTime(gain, t0 + 0.01);
    g.gain.exponentialRampToValueAtTime(0.0001, t0 + duration);

    osc.connect(g);
    g.connect(audioCtx.destination);

    osc.start(t0);
    osc.stop(t0 + duration + 0.02);
  }

  function playPattern(notes) {
    // notes: [{ f:Hz, d:sec, w:sec, t:type, g:gain }]
    let offset = 0;
    notes.forEach(n => {
      playTone(n.f, n.d ?? 0.07, n.t ?? "sine", n.g ?? 0.05, offset);
      offset += (n.w ?? n.d ?? 0.07);
    });
  }

  function playSfx(name) {
    switch (name) {
      case "click":
        playTone(520, 0.03, "triangle", 0.035);
        break;
      case "start":
        playPattern([
          { f: 440, d: 0.05, w: 0.05, t: "triangle", g: 0.05 },
          { f: 660, d: 0.06, w: 0.06, t: "triangle", g: 0.05 },
          { f: 880, d: 0.08, w: 0.08, t: "sine",     g: 0.055 },
        ]);
        break;
      case "enter":
        playPattern([
          { f: 523, d: 0.05, w: 0.05, t: "triangle", g: 0.05 },
          { f: 784, d: 0.07, w: 0.07, t: "triangle", g: 0.05 },
        ]);
        break;
      case "correct":
        playPattern([
          { f: 784,  d: 0.06, w: 0.06, t: "sine", g: 0.055 },
          { f: 988,  d: 0.06, w: 0.06, t: "sine", g: 0.055 },
          { f: 1175, d: 0.08, w: 0.08, t: "sine", g: 0.060 },
        ]);
        break;
      case "wrong":
        playPattern([
          { f: 220, d: 0.08, w: 0.08, t: "sawtooth", g: 0.040 },
          { f: 180, d: 0.08, w: 0.08, t: "sawtooth", g: 0.040 },
          { f: 140, d: 0.10, w: 0.10, t: "sawtooth", g: 0.040 },
        ]);
        break;
      case "relic":
        playPattern([
          { f: 880,  d: 0.04, w: 0.04, t: "triangle", g: 0.050 },
          { f: 1320, d: 0.05, w: 0.05, t: "triangle", g: 0.050 },
        ]);
        break;
      case "region":
        playPattern([
          { f: 523, d: 0.07, w: 0.07, t: "triangle", g: 0.050 },
          { f: 659, d: 0.07, w: 0.07, t: "triangle", g: 0.050 },
          { f: 784, d: 0.09, w: 0.09, t: "sine",     g: 0.055 },
        ]);
        break;
      case "victory":
        playPattern([
          { f: 659,  d: 0.07, w: 0.07, t: "triangle", g: 0.050 },
          { f: 784,  d: 0.07, w: 0.07, t: "triangle", g: 0.050 },
          { f: 988,  d: 0.10, w: 0.10, t: "sine",     g: 0.060 },
          { f: 1319, d: 0.14, w: 0.14, t: "sine",     g: 0.060 },
        ]);
        break;
      case "gameover":
        playPattern([
          { f: 196, d: 0.10, w: 0.10, t: "sawtooth", g: 0.040 },
          { f: 165, d: 0.12, w: 0.12, t: "sawtooth", g: 0.040 },
          { f: 131, d: 0.16, w: 0.16, t: "sawtooth", g: 0.040 },
        ]);
        break;
      case "save":
        playPattern([
          { f: 660, d: 0.04, w: 0.04, t: "triangle", g: 0.040 },
          { f: 880, d: 0.05, w: 0.05, t: "triangle", g: 0.040 },
        ]);
        break;
      case "load":
        playPattern([
          { f: 880, d: 0.04, w: 0.04, t: "triangle", g: 0.040 },
          { f: 660, d: 0.05, w: 0.05, t: "triangle", g: 0.040 },
        ]);
        break;
      case "reset":
        playPattern([
          { f: 330, d: 0.06, w: 0.06, t: "triangle", g: 0.040 },
          { f: 220, d: 0.08, w: 0.08, t: "triangle", g: 0.040 },
        ]);
        break;
      default:
        break;
    }
  }

  // ---------- background music (embedded MP3; offline) ----------
  let bgm = null;
  let bgmEnabled = true; // default ON (toggle with button)
  let bgmVolume = 0.25;
  const BGM_KEY = "copilot-quest-bgm-enabled-v1";
  const BGM_VOL_KEY = "copilot-quest-bgm-vol-v1";
  const BGM_SRC = './rpgmusic.mp3';

  function initBgm() {
    if (!bgm) {
      bgm = new Audio(BGM_SRC);
      bgm.loop = true;
      bgm.preload = "auto";
      bgm.onerror = (e) => console.error("BGM loading error:", e);
      bgm.onloadeddata = () => console.log("BGM loaded successfully");
    }
  }

  function loadBgmPref() {
    try {
      const e = localStorage.getItem(BGM_KEY);
      if (e === "0" || e === "1") bgmEnabled = (e === "1");
      const v = localStorage.getItem(BGM_VOL_KEY);
      if (v !== null && v !== undefined && v !== "") {
        const n = Number(v);
        if (!Number.isNaN(n)) bgmVolume = clamp(n, 0, 1);
      }
    } catch (e) {}
  }

  function saveBgmPref() {
    try {
      localStorage.setItem(BGM_KEY, bgmEnabled ? "1" : "0");
      localStorage.setItem(BGM_VOL_KEY, String(bgmVolume));
    } catch (e) {}
  }

  function setMusicUi() {
    const b = $("btnMusic");
    const s = $("musicVol");
    if (b) b.textContent = bgmEnabled ? "Music: On" : "Music: Off";
    if (s) s.value = String(Math.round(bgmVolume * 100));
  }

  async function tryPlayBgm() {
    if (!bgmEnabled) {
      console.log("BGM disabled");
      return;
    }
    initBgm();
    if (!bgm) {
      console.log("BGM not initialized");
      return;
    }

    bgm.volume = clamp(bgmVolume, 0, 1);

    try {
      // Must be called during/after a user gesture in most browsers.
      console.log("Attempting to play BGM from:", BGM_SRC);
      await bgm.play();
      console.log("BGM playing successfully");
    } catch (e) {
      // Ignore autoplay blocks; we'll try again on the next user gesture.
      console.error("BGM play failed:", e.message);
    }
  }

  function pauseBgm() {
    if (bgm) bgm.pause();
  }

  // Try to start music on the first user gesture (Start button click, etc.)
  document.addEventListener("pointerdown", () => {
    // resume web-audio sfx if it exists & was suspended
    if (audioCtx && audioCtx.state === "suspended") audioCtx.resume();
    tryPlayBgm();
  }, { once: true });




  function regionIntroText(region) {
    return [
      "🧭 Welcome, Adventurer.",
      "",
      `You’ve stepped into ${region.title}.`,
      region.desc,
      "",
      "Rule of the realm: answer challenges to gain XP + gold + relics. Miss too many, and your HP hits zero…",
      "",
      "Press “Enter Region” when you’re ready."
    ].join("\n");
  }

  function flavorFor(question) {
    const t = question.topic;
    if (t === 1) return "A gatekeeper blocks the path. It speaks in app-terms and awaits your choice.";
    if (t === 2) return "The corridor walls are made of sticky notes and notebooks. Choose wisely or loop back.";
    return "The forge roars. A scroll demands precision. A wrong answer smudges the ink of fate.";
  }

  function relicFor(question) {
    const base = question.topic === 1 ? "App Rune" : question.topic === 2 ? "Notebook Sigil" : "Forge Charm";
    return {
      name: `${base} ${question.topic}-${question.qnum}`,
      desc: question.multi
        ? "A relic that rewards exact multi-select mastery."
        : "A relic that rewards decisive single-choice clarity."
    };
  }

  // ---------- state ----------
  const DEFAULT = {
    ver: 1,
    mode: "title",       // title | intro | question | feedback | regionDone | finished | gameOver
    regionId: 1,
    order: [],
    pos: 0,
    hp: 3,
    xp: 0,
    gold: 0,
    lvl: 1,
    inventory: [],
    last: null,
    startedAt: null,
  };

  let state = structuredClone(DEFAULT);

  function computeLevel(xp) {
    return 1 + Math.floor(Math.sqrt(xp / 40));
  }

  function regionQuestions(regionId) {
    return QUESTION_BANK.filter(q => q.topic === regionId);
  }

  function buildRunOrder() {
    function shuffle(arr) {
      const a = [...arr];
      for (let i = a.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [a[i], a[j]] = [a[j], a[i]];
      }
      return a;
    }
    const byRegion = REGIONS.map(r => shuffle(regionQuestions(r.id)));
    return byRegion.flat().map(q => q.id);
  }

  function getCurrentQuestion() {
    const qid = state.order[state.pos];
    return QUESTION_BANK.find(q => q.id === qid);
  }

  function regionProgress() {
    const regQ = regionQuestions(state.regionId);
    const completedInRegion = regQ.filter(q => {
      const idx = state.order.indexOf(q.id);
      return idx !== -1 && idx < state.pos;
    }).length;
    return { done: completedInRegion, total: regQ.length };
  }

  function fullProgress() {
    return { done: clamp(state.pos, 0, state.order.length), total: state.order.length };
  }

  // ---------- rendering ----------
  function renderMap() {
    const map = $("map");
    map.innerHTML = "";
    REGIONS.forEach(r => {
      const div = document.createElement("div");
      div.className = "node";
      if (r.id < state.regionId) div.classList.add("done");
      if (r.id === state.regionId) div.classList.add("active");
      const rQs = regionQuestions(r.id);
      const done = rQs.filter(q => {
        const idx = state.order.indexOf(q.id);
        return idx !== -1 && idx < state.pos;
      }).length;
      div.innerHTML = `<div class="t">${r.title}</div>
                       <div class="d">${r.desc}</div>
                       <div class="d" style="margin-top:6px;">Progress: <span class="kbd">${done}/${rQs.length}</span></div>`;
      map.appendChild(div);
    });
  }

  function renderStats() {
    $("hp").textContent = "♥".repeat(state.hp) + "·".repeat(Math.max(0, 3 - state.hp));
    $("xp").textContent = String(state.xp);
    $("gold").textContent = String(state.gold);
    $("lvl").textContent = String(state.lvl);
    $("badgeMode").textContent = `Mode: ${state.mode}`;
    const reg = REGIONS.find(r => r.id === state.regionId);
    $("badgeRegion").textContent = `Region: ${reg ? reg.title : "—"}`;
    const rp = regionProgress();
    const fp = fullProgress();
    $("badgeProgress").textContent = `Progress: ${rp.done}/${rp.total} (Total ${fp.done}/${fp.total})`;
  }

  function renderInventory() {
    const inv = $("inv");
    inv.innerHTML = "";
    if (!state.inventory.length) {
      const empty = document.createElement("div");
      empty.className = "item";
      empty.innerHTML = `<div class="name">Inventory empty</div>
                         <div class="desc">Win encounters to collect relics.</div>`;
      inv.appendChild(empty);
      return;
    }
    state.inventory.slice().reverse().slice(0, 8).forEach(it => {
      const div = document.createElement("div");
      div.className = "item";
      div.innerHTML = `<div class="name">${it.name}</div><div class="desc">${it.desc}</div>`;
      inv.appendChild(div);
    });
  }

  function setMsg(kind, text) {
    const box = $("msg");
    box.style.display = "block";
    box.className = `msg ${kind || ""}`;
    box.textContent = text;
  }

  function hideMsg() {
    const box = $("msg");
    box.style.display = "none";
    box.textContent = "";
    box.className = "msg";
  }

  function showQuestion(q) {
    $("qArea").style.display = "block";
    $("qText").textContent = q.stem;
    $("qHint").textContent = q.multi ? "Select ALL correct answers (multi-select)." : "Select ONE answer.";
    const choices = $("choices");
    choices.innerHTML = "";

    const inputType = q.multi ? "checkbox" : "radio";
    q.options.forEach(opt => {
      const id = `opt-${q.id}-${opt.id}`;
      const lab = document.createElement("label");
      lab.className = "choice";
      lab.setAttribute("for", id);
      lab.innerHTML = `
        <div class="letter">${opt.id}</div>
        <div style="display:flex; gap:10px; align-items:flex-start; width:100%;">
          <input id="${id}" name="answer" type="${inputType}" value="${opt.id}" style="margin-top:6px;">
          <div class="txt">${opt.text}</div>
        </div>
      `;
      choices.appendChild(lab);
    });
  }

  function getSelected() {
    const inputs = Array.from(document.querySelectorAll("input[name='answer']"));
    return inputs.filter(i => i.checked).map(i => i.value);
  }

  function clearSelected() {
    Array.from(document.querySelectorAll("input[name='answer']")).forEach(i => { i.checked = false; i.disabled = false; });
  }

  function render() {
    renderStats();
    renderMap();
    renderInventory();

    const primary = $("btnPrimary");
    const story = $("story");
    const qArea = $("qArea");

    if (state.mode === "title") {
      qArea.style.display = "none";
      hideMsg();
      story.textContent = [
        "⚔️ Copilot Quest is a practice adventure built from your question bank.",
        "",
        "Goal: clear all regions without losing all HP.",
        "",
        "Press Start to begin."
      ].join("\n");
      primary.textContent = "Start";
      primary.onclick = () => {
        playSfx('start');
        tryPlayBgm();
        state = structuredClone(DEFAULT);
        state.startedAt = nowIso();
        state.order = buildRunOrder();
        state.mode = "intro";
        state.regionId = 1;
        state.pos = 0;
        render();
      };
      return;
    }

    if (state.mode === "intro") {
      qArea.style.display = "none";
      hideMsg();
      const region = REGIONS.find(r => r.id === state.regionId);
      story.textContent = regionIntroText(region);
      primary.textContent = "Enter Region";
      primary.onclick = () => { playSfx('enter'); tryPlayBgm(); state.mode = "question"; render(); };
      return;
    }

    if (state.mode === "question") {
      hideMsg();
      const q = getCurrentQuestion();
      if (!q) { state.mode = "finished"; render(); return; }

      if (q.topic !== state.regionId) { state.mode = "regionDone"; render(); return; }

      story.textContent = "🗺️ " + flavorFor(q);
      showQuestion(q);
      primary.textContent = "Submit";
      primary.onclick = () => {
        playSfx('click');
        const chosen = getSelected();
        if (!chosen.length) { setMsg("warn", "Pick an answer first."); return; }

        const correct = q.answer;
        const ok = eqSet(chosen, correct);
        state.last = { qid: q.id, chosen, correct, ok };

        if (ok) {
          playSfx('correct');
          state.xp += q.multi ? 18 : 12;
          state.gold += q.multi ? 9 : 6;
          state.lvl = computeLevel(state.xp);
          state.inventory.push({ ...relicFor(q), gainedAt: nowIso() });
          playSfx('relic');
          setMsg("good", `✅ Correct!\nYou gained XP and gold, and found a relic.\n\nCorrect answer: ${correct.join(", ")}`);
        } else {
          playSfx('wrong');
          state.hp = clamp(state.hp - 1, 0, 3);
          setMsg("bad", `❌ Not quite.\n\nYour answer: ${chosen.join(", ")}\nCorrect answer: ${correct.join(", ")}\n\nHP -1`);
        }
        state.mode = state.hp <= 0 ? "gameOver" : "feedback";
        if (state.mode === "gameOver") playSfx('gameover');
        render();
      };
      return;
    }

    if (state.mode === "feedback") {
      primary.textContent = "Continue";
      primary.onclick = () => {
        playSfx('click');
        clearSelected();
        state.pos += 1;
        const next = state.order[state.pos];
        const nextQ = QUESTION_BANK.find(q => q.id === next);
        if (!nextQ) state.mode = "finished";
        if (!nextQ) playSfx('victory');
        else if (nextQ.topic !== state.regionId) state.mode = "regionDone";
        else state.mode = "question";
        render();
      };
      Array.from(document.querySelectorAll("input[name='answer']")).forEach(i => i.disabled = true);
      return;
    }

    if (state.mode === "regionDone") {
      qArea.style.display = "none";
      hideMsg();
      const region = REGIONS.find(r => r.id === state.regionId);
      const rp = regionProgress();
      story.textContent = [
        `🏁 Region cleared: ${region.title}`,
        `You overcame ${rp.total} encounters here.`,
        "",
        `Reward: ${region.reward}`,
        "",
        "Press Continue to travel onward."
      ].join("\n");
      primary.textContent = (state.regionId < REGIONS.length) ? "Continue" : "Finish";
      primary.onclick = () => {
        playSfx('region');
        state.regionId = clamp(state.regionId + 1, 1, REGIONS.length);
        state.mode = "intro";
        render();
      };
      return;
    }

    if (state.mode === "finished") {
      qArea.style.display = "none";
      hideMsg();
      const fp = fullProgress();
      const score = Math.round((state.xp / (fp.total * 18)) * 100);
      story.textContent = [
        "🏆 Victory!",
        "",
        `You cleared the realm with Level ${state.lvl}.`,
        `XP: ${state.xp}   Gold: ${state.gold}`,
        `Relics: ${state.inventory.length}`,
        "",
        `Completion: ${fp.done}/${fp.total}`,
        `Final Score (rough): ${clamp(score, 0, 100)}%`,
        "",
        "Replay to shuffle encounters and reinforce memory."
      ].join("\n");
      primary.textContent = "Play Again";
      primary.onclick = () => { playSfx('click'); state.mode = "title"; render(); };
      return;
    }

    if (state.mode === "gameOver") {
      qArea.style.display = "none";
      hideMsg();
      story.textContent = [
        "💀 Game Over.",
        "",
        "Your HP hit zero. The realm’s guardians demand more grounding and careful reading.",
        "",
        "Press Retry to start over."
      ].join("\n");
      primary.textContent = "Retry";
      primary.onclick = () => { playSfx('click'); state.mode = "title"; render(); };
      return;
    }
  }

  // ---------- persistence ----------
  const KEY = "copilot-quest-save-v1";
  function save() {
    playSfx('save');
    localStorage.setItem(KEY, JSON.stringify(state));
    setMsg("good", "Saved to this browser.");
  }
  function load() {
    playSfx('load');
    const raw = localStorage.getItem(KEY);
    if (!raw) { setMsg("warn", "No save found in this browser yet."); return; }
    try {
      const obj = JSON.parse(raw);
      state = Object.assign(structuredClone(DEFAULT), obj);
      setMsg("good", "Loaded!");
      render();
    } catch (e) {
      setMsg("bad", "Could not load save (corrupted).");
    }
  }
  function reset() {
    playSfx('reset');
    localStorage.removeItem(KEY);
    state = structuredClone(DEFAULT);
    render();
  }

  $("btnSave").onclick = save;
  $("btnLoad").onclick = load;
  $("btnReset").onclick = reset;


  loadSfxPref();
  setSoundButton();
  const btnSound = $("btnSound");

  loadBgmPref();
  setMusicUi();

  const btnMusic = $("btnMusic");
  if (btnMusic) {
    btnMusic.onclick = async () => {
      bgmEnabled = !bgmEnabled;
      saveBgmPref();
      setMusicUi();
      if (bgmEnabled) {
        await tryPlayBgm();
        playSfx("click");
      } else {
        pauseBgm();
        playSfx("click");
      }
    };
  }

  const musicVol = $("musicVol");
  if (musicVol) {
    musicVol.oninput = () => {
      bgmVolume = clamp(Number(musicVol.value) / 100, 0, 1);
      if (bgm) bgm.volume = bgmVolume;
      saveBgmPref();
    };
  }

  // Pause music when tab is hidden; resume when visible (if enabled)
  document.addEventListener("visibilitychange", () => {
    if (document.hidden) {
      pauseBgm();
    } else {
      tryPlayBgm();
    }
  });


  if (btnSound) {
    btnSound.onclick = () => {
      sfxEnabled = !sfxEnabled;
      saveSfxPref();
      setSoundButton();
      if (sfxEnabled) playSfx("click");
    };
  }

  render();
</script>
</body>
</html>