databricksedu 0.1.0__py3-none-any.whl

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.
Files changed (158) hide show
  1. databricksedu/__init__.py +24 -0
  2. databricksedu/_content/catalog.json +1923 -0
  3. databricksedu/_content/nb/agents-tools.json.gz +0 -0
  4. databricksedu/_content/nb/ai-bi-dashboards.json.gz +0 -0
  5. databricksedu/_content/nb/ai-functions-gateway.json.gz +0 -0
  6. databricksedu/_content/nb/asset-bundles-cicd.json.gz +0 -0
  7. databricksedu/_content/nb/asset-bundles-recap.json.gz +0 -0
  8. databricksedu/_content/nb/auto-loader-copy-into.json.gz +0 -0
  9. databricksedu/_content/nb/cdc-data.json.gz +0 -0
  10. databricksedu/_content/nb/cdc-scd.json.gz +0 -0
  11. databricksedu/_content/nb/change-data-feed.json.gz +0 -0
  12. databricksedu/_content/nb/chunking-parsing.json.gz +0 -0
  13. databricksedu/_content/nb/churn-data.json.gz +0 -0
  14. databricksedu/_content/nb/data-privacy-recap.json.gz +0 -0
  15. databricksedu/_content/nb/data-quality-expectations.json.gz +0 -0
  16. databricksedu/_content/nb/declarative-pipelines-recap.json.gz +0 -0
  17. databricksedu/_content/nb/declarative-pipelines.json.gz +0 -0
  18. databricksedu/_content/nb/deletion-vectors.json.gz +0 -0
  19. databricksedu/_content/nb/delta-acid-concurrency.json.gz +0 -0
  20. databricksedu/_content/nb/delta-dml-merge.json.gz +0 -0
  21. databricksedu/_content/nb/delta-optimization.json.gz +0 -0
  22. databricksedu/_content/nb/delta-sharing.json.gz +0 -0
  23. databricksedu/_content/nb/delta-table-anatomy.json.gz +0 -0
  24. databricksedu/_content/nb/delta-time-travel-vacuum.json.gz +0 -0
  25. databricksedu/_content/nb/delta-transaction-log.json.gz +0 -0
  26. databricksedu/_content/nb/devops-essentials-recap.json.gz +0 -0
  27. databricksedu/_content/nb/embeddings-vector-search.json.gz +0 -0
  28. databricksedu/_content/nb/exam-data-analyst-associate.json.gz +0 -0
  29. databricksedu/_content/nb/exam-data-engineer-associate.json.gz +0 -0
  30. databricksedu/_content/nb/exam-data-engineer-professional.json.gz +0 -0
  31. databricksedu/_content/nb/exam-genai-engineer-associate.json.gz +0 -0
  32. databricksedu/_content/nb/exam-ml-associate.json.gz +0 -0
  33. databricksedu/_content/nb/exam-ml-professional.json.gz +0 -0
  34. databricksedu/_content/nb/exam-spark-developer-associate.json.gz +0 -0
  35. databricksedu/_content/nb/feature-engineering.json.gz +0 -0
  36. databricksedu/_content/nb/genai-evaluation.json.gz +0 -0
  37. databricksedu/_content/nb/genie-spaces.json.gz +0 -0
  38. databricksedu/_content/nb/hr-data.json.gz +0 -0
  39. databricksedu/_content/nb/hyperparameter-tuning.json.gz +0 -0
  40. databricksedu/_content/nb/iot-data.json.gz +0 -0
  41. databricksedu/_content/nb/lakeflow-connect-recap.json.gz +0 -0
  42. databricksedu/_content/nb/lakeflow-jobs-recap.json.gz +0 -0
  43. databricksedu/_content/nb/lakeflow-jobs.json.gz +0 -0
  44. databricksedu/_content/nb/lakehouse-architecture.json.gz +0 -0
  45. databricksedu/_content/nb/lineage-system-tables.json.gz +0 -0
  46. databricksedu/_content/nb/llm-basics.json.gz +0 -0
  47. databricksedu/_content/nb/medallion-architecture.json.gz +0 -0
  48. databricksedu/_content/nb/metric-views.json.gz +0 -0
  49. databricksedu/_content/nb/ml-lifecycle.json.gz +0 -0
  50. databricksedu/_content/nb/mlflow-tracking.json.gz +0 -0
  51. databricksedu/_content/nb/model-monitoring.json.gz +0 -0
  52. databricksedu/_content/nb/model-serving.json.gz +0 -0
  53. databricksedu/_content/nb/models-in-unity-catalog.json.gz +0 -0
  54. databricksedu/_content/nb/parquet-files.json.gz +0 -0
  55. databricksedu/_content/nb/performance-optimization-recap.json.gz +0 -0
  56. databricksedu/_content/nb/prompt-engineering.json.gz +0 -0
  57. databricksedu/_content/nb/rag-architecture.json.gz +0 -0
  58. databricksedu/_content/nb/retail-data.json.gz +0 -0
  59. databricksedu/_content/nb/row-filters-column-masks.json.gz +0 -0
  60. databricksedu/_content/nb/schema-enforcement-evolution.json.gz +0 -0
  61. databricksedu/_content/nb/spark-architecture.json.gz +0 -0
  62. databricksedu/_content/nb/spark-joins-shuffles.json.gz +0 -0
  63. databricksedu/_content/nb/sql-warehouses.json.gz +0 -0
  64. databricksedu/_content/nb/streaming-pipelines-recap.json.gz +0 -0
  65. databricksedu/_content/nb/structured-streaming-basics.json.gz +0 -0
  66. databricksedu/_content/nb/support-data.json.gz +0 -0
  67. databricksedu/_content/nb/uc-privileges.json.gz +0 -0
  68. databricksedu/_content/nb/unity-catalog-basics.json.gz +0 -0
  69. databricksedu/_content/nb/watermarks-stateful-streaming.json.gz +0 -0
  70. databricksedu/_content/web/agents-tools.b64 +1 -0
  71. databricksedu/_content/web/ai-bi-dashboards.b64 +1 -0
  72. databricksedu/_content/web/ai-functions-gateway.b64 +1 -0
  73. databricksedu/_content/web/asset-bundles-cicd.b64 +1 -0
  74. databricksedu/_content/web/asset-bundles-recap.b64 +1 -0
  75. databricksedu/_content/web/auto-loader-copy-into.b64 +1 -0
  76. databricksedu/_content/web/cdc-data.b64 +1 -0
  77. databricksedu/_content/web/cdc-scd.b64 +1 -0
  78. databricksedu/_content/web/change-data-feed.b64 +1 -0
  79. databricksedu/_content/web/chunking-parsing.b64 +1 -0
  80. databricksedu/_content/web/churn-data.b64 +1 -0
  81. databricksedu/_content/web/data-privacy-recap.b64 +1 -0
  82. databricksedu/_content/web/data-quality-expectations.b64 +1 -0
  83. databricksedu/_content/web/declarative-pipelines-recap.b64 +1 -0
  84. databricksedu/_content/web/declarative-pipelines.b64 +1 -0
  85. databricksedu/_content/web/deletion-vectors.b64 +1 -0
  86. databricksedu/_content/web/delta-acid-concurrency.b64 +1 -0
  87. databricksedu/_content/web/delta-dml-merge.b64 +1 -0
  88. databricksedu/_content/web/delta-optimization.b64 +1 -0
  89. databricksedu/_content/web/delta-sharing.b64 +1 -0
  90. databricksedu/_content/web/delta-table-anatomy.b64 +1 -0
  91. databricksedu/_content/web/delta-time-travel-vacuum.b64 +1 -0
  92. databricksedu/_content/web/delta-transaction-log.b64 +1 -0
  93. databricksedu/_content/web/devops-essentials-recap.b64 +1 -0
  94. databricksedu/_content/web/embeddings-vector-search.b64 +1 -0
  95. databricksedu/_content/web/exam-data-analyst-associate.b64 +1 -0
  96. databricksedu/_content/web/exam-data-engineer-associate.b64 +1 -0
  97. databricksedu/_content/web/exam-data-engineer-professional.b64 +1 -0
  98. databricksedu/_content/web/exam-genai-engineer-associate.b64 +1 -0
  99. databricksedu/_content/web/exam-ml-associate.b64 +1 -0
  100. databricksedu/_content/web/exam-ml-professional.b64 +1 -0
  101. databricksedu/_content/web/exam-spark-developer-associate.b64 +1 -0
  102. databricksedu/_content/web/feature-engineering.b64 +1 -0
  103. databricksedu/_content/web/genai-evaluation.b64 +1 -0
  104. databricksedu/_content/web/genie-spaces.b64 +1 -0
  105. databricksedu/_content/web/hr-data.b64 +1 -0
  106. databricksedu/_content/web/hyperparameter-tuning.b64 +1 -0
  107. databricksedu/_content/web/iot-data.b64 +1 -0
  108. databricksedu/_content/web/lakeflow-connect-recap.b64 +1 -0
  109. databricksedu/_content/web/lakeflow-jobs-recap.b64 +1 -0
  110. databricksedu/_content/web/lakeflow-jobs.b64 +1 -0
  111. databricksedu/_content/web/lakehouse-architecture.b64 +1 -0
  112. databricksedu/_content/web/lineage-system-tables.b64 +1 -0
  113. databricksedu/_content/web/llm-basics.b64 +1 -0
  114. databricksedu/_content/web/medallion-architecture.b64 +1 -0
  115. databricksedu/_content/web/metric-views.b64 +1 -0
  116. databricksedu/_content/web/ml-lifecycle.b64 +1 -0
  117. databricksedu/_content/web/mlflow-tracking.b64 +1 -0
  118. databricksedu/_content/web/model-monitoring.b64 +1 -0
  119. databricksedu/_content/web/model-serving.b64 +1 -0
  120. databricksedu/_content/web/models-in-unity-catalog.b64 +1 -0
  121. databricksedu/_content/web/parquet-files.b64 +1 -0
  122. databricksedu/_content/web/performance-optimization-recap.b64 +1 -0
  123. databricksedu/_content/web/prompt-engineering.b64 +1 -0
  124. databricksedu/_content/web/rag-architecture.b64 +1 -0
  125. databricksedu/_content/web/retail-data.b64 +1 -0
  126. databricksedu/_content/web/row-filters-column-masks.b64 +1 -0
  127. databricksedu/_content/web/schema-enforcement-evolution.b64 +1 -0
  128. databricksedu/_content/web/spark-architecture.b64 +1 -0
  129. databricksedu/_content/web/spark-joins-shuffles.b64 +1 -0
  130. databricksedu/_content/web/sql-warehouses.b64 +1 -0
  131. databricksedu/_content/web/streaming-pipelines-recap.b64 +1 -0
  132. databricksedu/_content/web/structured-streaming-basics.b64 +1 -0
  133. databricksedu/_content/web/support-data.b64 +1 -0
  134. databricksedu/_content/web/uc-privileges.b64 +1 -0
  135. databricksedu/_content/web/unity-catalog-basics.b64 +1 -0
  136. databricksedu/_content/web/watermarks-stateful-streaming.b64 +1 -0
  137. databricksedu/_version.py +1 -0
  138. databricksedu/app.py +192 -0
  139. databricksedu/assets/app.css +1 -0
  140. databricksedu/assets/app.js +353 -0
  141. databricksedu/assets/dbx.css +1 -0
  142. databricksedu/assets/quiz.js +47 -0
  143. databricksedu/assets/viz.css +1 -0
  144. databricksedu/assets/viz.js +84 -0
  145. databricksedu/catalog.py +95 -0
  146. databricksedu/data/__init__.py +58 -0
  147. databricksedu/data/_core.py +339 -0
  148. databricksedu/data/cdc.py +75 -0
  149. databricksedu/data/churn.py +74 -0
  150. databricksedu/data/hr.py +58 -0
  151. databricksedu/data/iot.py +86 -0
  152. databricksedu/data/retail.py +77 -0
  153. databricksedu/data/support.py +128 -0
  154. databricksedu/workspace.py +157 -0
  155. databricksedu-0.1.0.dist-info/METADATA +131 -0
  156. databricksedu-0.1.0.dist-info/RECORD +158 -0
  157. databricksedu-0.1.0.dist-info/WHEEL +4 -0
  158. databricksedu-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1 @@
1
+ html,body{margin:0;padding:0;height:auto;background:transparent}#dbe{--navy:#1B3139;--accent:#FF3621;--blue:#2272B4;--purple:#7C4DFF;--teal:#00A3A1;--bg:#F4F2EE;--muted:#6B7280;--line:#E5E7EB;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;color:#1F2937;background:var(--bg);display:flex;flex-direction:column;border-radius:14px;overflow:hidden;position:relative;border:1px solid #D6D3CD;box-sizing:border-box;width:100%;min-width:0}#dbe *{box-sizing:border-box}#dbe.fs{border-radius:0;border:0;height:100vh!important}#dbe button{font-family:inherit}.top{display:flex;align-items:center;gap:10px;padding:9px 16px;background:var(--navy);color:#fff;flex:none;z-index:5}.brand{display:flex;align-items:center;gap:8px;font-weight:800;letter-spacing:.01em;cursor:pointer;border:0;background:transparent;color:#fff;font-size:15px;padding:4px 6px;border-radius:8px}.brand:hover{background:rgba(255,255,255,.1)}.brand .lg{display:inline-flex;width:26px;height:26px;border-radius:8px;background:linear-gradient(135deg,#FF3621,#7C4DFF);align-items:center;justify-content:center;font-size:15px}.brand em{font-style:normal;color:#FF8A7A}.crumb{color:#94A3B8;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0}.crumb b{color:#E2E8F0;font-weight:600}.seg{display:inline-flex;background:rgba(255,255,255,.1);border-radius:999px;padding:3px;flex:none}.seg button{border:0;background:transparent;color:#CBD5E1;padding:6px 14px;border-radius:999px;cursor:pointer;font-size:13px;white-space:nowrap}.seg button.on{background:#fff;color:var(--navy);font-weight:700}.hbtn{border:1px solid rgba(255,255,255,.25);background:transparent;color:#E2E8F0;border-radius:8px;padding:6px 10px;cursor:pointer;font-size:13px;white-space:nowrap;flex:none}.hbtn:hover{background:rgba(255,255,255,.12)}.hbtn.pri{background:linear-gradient(135deg,#FF3621,#c2410c);border-color:transparent;color:#fff;font-weight:700}#bar{height:3px;background:linear-gradient(90deg,var(--accent),var(--purple),var(--teal));width:0;transition:width .35s ease;flex:none}#main{flex:1;min-height:0;position:relative;display:flex;flex-direction:column}#home{flex:1;overflow:auto;padding:18px 22px 26px}.hhero{position:relative;overflow:hidden;border-radius:18px;padding:26px 30px;color:#fff;background:linear-gradient(120deg,#1B3139,#22425a,#2a2f6b,#1B3139);background-size:300% 300%;animation:dbxGrad 14s ease infinite}.hhero .blob{position:absolute;border-radius:50%;filter:blur(34px);opacity:.55;animation:dbxFloat 9s ease-in-out infinite}.hhero .b1{width:260px;height:260px;background:#FF3621;right:-50px;top:-90px}.hhero .b2{width:200px;height:200px;background:#7C4DFF;right:220px;bottom:-120px;animation-delay:-3s}.hhero .b3{width:160px;height:160px;background:#00A3A1;left:-50px;bottom:-70px;animation-delay:-6s}.hhero>div{position:relative}.hhero h1{margin:0 0 6px;font-size:30px;font-weight:800;letter-spacing:-.01em}.hhero h1 em{font-style:normal;color:#FF8A7A}.hhero p{margin:0;color:#E2E8F0;font-size:15px;max-width:760px;line-height:1.5}.hstats{display:flex;gap:10px;flex-wrap:wrap;margin-top:14px}.hstats span{background:rgba(255,255,255,.14);border:1px solid rgba(255,255,255,.25);padding:4px 12px;border-radius:999px;font-size:13px}.hrow{display:flex;gap:10px;align-items:center;margin:16px 0 4px;flex-wrap:wrap}.cats{display:flex;gap:8px;flex-wrap:wrap;flex:1}.cat{border:1px solid var(--line);background:#fff;color:#334155;border-radius:999px;padding:8px 14px;cursor:pointer;font-size:14px;font-weight:600;display:inline-flex;gap:7px;align-items:center;transition:all .2s}.cat:hover{border-color:var(--accent);transform:translateY(-1px)}.cat.on{background:var(--navy);color:#fff;border-color:var(--navy);box-shadow:0 6px 16px rgba(27,49,57,.25)}.cat i{font-style:normal;font-size:12px;background:rgba(100,116,139,.18);border-radius:999px;padding:1px 7px}.cat.on i{background:rgba(255,255,255,.2)}#q{border:1px solid var(--line);border-radius:999px;padding:9px 14px;font-size:14px;min-width:210px;outline:none;font-family:inherit;background:#fff}#q:focus{border-color:var(--purple);box-shadow:0 0 0 3px rgba(124,77,255,.15)}.cdesc{color:var(--muted);font-size:14px;margin:8px 2px 2px;display:flex;gap:10px;align-items:center;flex-wrap:wrap}.cdesc button{margin-left:auto;border:1px solid var(--line);background:#fff;border-radius:999px;padding:6px 14px;cursor:pointer;font-size:13px;font-weight:600;color:var(--navy)}.cdesc button:hover{border-color:var(--accent);color:var(--accent)}.gtitle{font-size:12px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:#94A3B8;margin:18px 2px 8px}.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(270px,1fr));gap:14px}.mcard{background:#fff;border-radius:16px;padding:16px 16px 12px;cursor:pointer;border:2px solid transparent;box-shadow:0 4px 14px rgba(27,49,57,.07);transition:transform .2s,border-color .2s,box-shadow .2s;display:flex;flex-direction:column;animation:dbxRise .45s both;animation-delay:calc(var(--i,0)*35ms)}.mcard:hover{transform:translateY(-3px);border-color:var(--accent);box-shadow:0 12px 28px rgba(27,49,57,.14)}.mcard .mh{display:flex;gap:10px;align-items:flex-start}.mcard .mi{font-size:26px;line-height:1;flex:none;width:44px;height:44px;border-radius:12px;background:linear-gradient(135deg,#FFF4F1,#F5F3FF);display:flex;align-items:center;justify-content:center}.mcard .mt{font-weight:800;color:var(--navy);font-size:15.5px;line-height:1.25}.mcard .ms{color:#475569;font-size:13px;line-height:1.45;margin:8px 0 10px;flex:1}.mchips{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:10px}.mchips span{font-size:11.5px;background:#F1F5F9;color:#475569;border-radius:999px;padding:2px 9px;white-space:nowrap}.mact{display:flex;gap:6px}.mact button{flex:1;border:1px solid var(--line);background:#fff;border-radius:9px;padding:7px 4px;cursor:pointer;font-size:12.5px;font-weight:700;color:var(--navy);white-space:nowrap}.mact button:hover{border-color:var(--accent);color:var(--accent)}.mact button.go{background:linear-gradient(135deg,#FF3621,#7C4DFF);border:0;color:#fff}.empty{color:var(--muted);padding:30px;text-align:center}.hfoot{margin-top:22px;display:flex;gap:14px;flex-wrap:wrap}.hfoot .cta{flex:2 1 380px;margin:0}.hfoot .pip{flex:1 1 260px;background:#fff;border-radius:16px;padding:16px 18px;border:1px solid var(--line);font-size:13px;color:#475569}.hfoot .pip code{display:block;background:#0D1117;color:#E6EDF3;border-radius:8px;padding:8px 10px;margin-top:6px;font-size:12px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;white-space:pre-wrap}#player{flex:1;min-height:0;display:none;flex-direction:column}#slides{flex:1;display:flex;flex-direction:column;min-height:0;padding:14px 18px 8px;position:relative}.stage{flex:1;position:relative;min-height:0;perspective:1400px}.slide{position:absolute;inset:0;background:#fff;border-radius:18px;box-shadow:0 14px 40px rgba(27,49,57,.14);overflow:auto;padding:26px 44px 30px}.slide.enter-r{animation:inR .45s cubic-bezier(.2,.8,.2,1) both}.slide.enter-l{animation:inL .45s cubic-bezier(.2,.8,.2,1) both}@keyframes inR{from{opacity:0;transform:translateX(60px) rotateY(-6deg)}to{opacity:1;transform:none}}@keyframes inL{from{opacity:0;transform:translateX(-60px) rotateY(6deg)}to{opacity:1;transform:none}}.slide .dbx{max-width:none;font-size:17px}.slide .dbx .sec-head h2{font-size:29px}.slide .dbx table{font-size:15px}.slide .dbx .code pre{font-size:13.5px}.slide .dbx>*{animation:dbxRise .55s cubic-bezier(.2,.7,.2,1) both;animation-delay:calc(var(--i,0)*80ms + 100ms)}.slide.title{padding:0;overflow:hidden;background:transparent}.slide.title .dbx{height:100%;display:flex;flex-direction:column;position:relative}.slide.title .hero{flex:1;margin:0;border-radius:18px;display:flex;align-items:center;padding:40px 60px 130px}.slide.title .hero h1{font-size:46px}.slide.title .sub{font-size:19px}.slide.title .b1{width:420px;height:420px}.slide.title .b2{width:340px;height:340px}.slide.title .b3{width:300px;height:300px}.slide.title .idea{position:absolute;left:60px;right:60px;bottom:30px;font-size:17px;background:rgba(255,255,255,.96)}.slide.title .dbx>:not(.hero):not(.idea){display:none}.controls{display:flex;align-items:center;gap:12px;padding-top:10px;flex:none}.controls .nav{border:1px solid var(--line);background:#fff;border-radius:10px;min-width:44px;height:36px;cursor:pointer;font-size:15px;font-weight:700;color:var(--navy);padding:0 12px}.controls .nav:hover{border-color:var(--accent);color:var(--accent)}.controls .nav.next{background:linear-gradient(135deg,#FF3621,#7C4DFF);color:#fff;border:0}.dots{display:flex;gap:6px;flex:1;justify-content:center;flex-wrap:wrap}.dots button{width:10px;height:10px;border-radius:50%;border:0;background:#CBD5E1;cursor:pointer;padding:0;transition:all .25s}.dots button.on{background:var(--accent);width:28px;border-radius:6px}.count{color:var(--muted);font-size:13px;min-width:52px;text-align:right}.hint{color:#94A3B8;font-size:12px;white-space:nowrap}#overview{position:absolute;inset:0;background:rgba(244,242,238,.97);z-index:4;display:none;overflow:auto;padding:22px}#overview.on{display:block;animation:dbxRise .3s both}.ogrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px}.ocard{background:#fff;border-radius:14px;padding:14px;cursor:pointer;border:2px solid transparent;box-shadow:0 4px 14px rgba(0,0,0,.06);transition:all .2s}.ocard:hover{transform:translateY(-3px);border-color:var(--accent)}.ocard .n{font-size:12px;color:var(--muted);font-weight:700}.ocard .i{font-size:26px;margin:4px 0}.ocard .t{font-weight:700;color:var(--navy);font-size:14px}#doc{flex:1;display:none;min-height:0}#player.docmode #slides{display:none}#player.docmode #doc{display:flex}#toc{width:250px;flex:none;overflow:auto;padding:16px 12px;border-right:1px solid var(--line);background:#fff}#toc a{display:flex;gap:8px;align-items:center;padding:7px 10px;border-radius:9px;color:#334155;text-decoration:none;font-size:13px;margin:2px 0;cursor:pointer}#toc a:hover{background:#F1F5F9}#toc a.on{background:#FFF1EE;color:#C62D1A;font-weight:700}#toc .rawbtn{margin-top:12px;width:100%;border:1px dashed #CBD5E1;background:#fff;border-radius:9px;padding:8px;cursor:pointer;font-size:12.5px;color:#475569}#docScroll{flex:1;overflow:auto;padding:20px 28px 60px}.dsec{background:#fff;border-radius:16px;padding:22px 28px;margin:0 auto 16px;max-width:1000px;box-shadow:0 4px 18px rgba(27,49,57,.06)}.dsec.herosec{padding:0;background:transparent;box-shadow:none}.dsec .dbx{max-width:none}.dsec .dbx>*{animation:none}.rawmd{max-width:1000px;margin:0 auto;background:#0D1117;color:#E6EDF3;border-radius:14px;padding:18px 20px;font-size:12.5px;line-height:1.55;white-space:pre-wrap;word-break:break-word;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.quiz{max-width:820px}.dbx .code .copy{display:inline-block;margin-left:auto;border:1px solid #30363D;background:#21262D;color:#C9D1D9;border-radius:6px;font-size:11px;padding:2px 8px;cursor:pointer}.dbx .code .run+.copy{margin-left:10px}.fin{text-align:center;padding:10px 0}.fin .big{font-size:60px;animation:vzPop .6s both}.fin h2{font-size:30px;color:var(--navy);margin:6px 0}.fin p{color:var(--muted);margin:0 0 16px}.fcards{display:flex;gap:12px;flex-wrap:wrap;justify-content:center;text-align:left;margin-bottom:14px}.fcard{flex:1 1 220px;max-width:330px;background:#F8FAFC;border:1px solid var(--line);border-radius:14px;padding:14px 16px;cursor:pointer;transition:all .2s}.fcard:hover{border-color:var(--accent);transform:translateY(-2px)}.fcard b{display:block;color:var(--navy);margin-bottom:2px}.fcard span{font-size:13.5px;color:#475569}#modal{position:absolute;inset:0;background:rgba(15,23,42,.55);z-index:20;display:none;align-items:center;justify-content:center;padding:20px}#modal.on{display:flex;animation:dbxRise .25s both}.mbox{background:#fff;border-radius:18px;max-width:640px;width:100%;max-height:100%;overflow:auto;padding:22px 24px;box-shadow:0 30px 80px rgba(0,0,0,.35)}.mbox h3{margin:0 0 6px;color:var(--navy);font-size:20px}.mbox p{color:#475569;font-size:14px;line-height:1.5;margin:6px 0}.mbox ul{margin:6px 0;padding-left:20px;color:#334155;font-size:14px}.cmd{display:flex;gap:8px;align-items:stretch;margin:8px 0}.cmd code{flex:1;background:#0D1117;color:#E6EDF3;border-radius:10px;padding:10px 12px;font-size:12.5px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;white-space:pre-wrap;word-break:break-all}.cmd button,.mclose{border:0;border-radius:10px;padding:0 14px;cursor:pointer;font-weight:700;background:linear-gradient(135deg,#FF3621,#7C4DFF);color:#fff;font-size:13px}.mclose{padding:9px 18px;margin-top:10px;background:#E5E7EB;color:#374151}.tip{background:#ECFDF3;border:1px solid #A7F3D0;border-radius:10px;padding:9px 12px;font-size:13.5px;color:#065F46;margin:8px 0}#err{position:absolute;left:10px;right:10px;bottom:10px;background:#FEF2F2;border:1px solid #FCA5A5;color:#991B1B;border-radius:10px;padding:8px 12px;font-size:12px;z-index:30;display:none;white-space:pre-wrap}.confetti{position:absolute;top:-20px;font-size:22px;z-index:9;animation:fall 2.6s linear forwards;pointer-events:none}@keyframes fall{to{transform:translateY(900px) rotate(720deg);opacity:.7}}.loading{padding:60px;text-align:center;color:var(--muted)}@media (max-width:820px){.slide{padding:18px}.slide.title .hero{padding:26px 26px 150px}.slide.title .hero h1{font-size:30px}.slide.title .idea{left:16px;right:16px}#toc{display:none}.crumb{display:none}.hint{display:none}.seg button{padding:6px 9px}}@media (prefers-reduced-motion: reduce){*,*::before,*::after{animation:none!important;transition:none!important}}
@@ -0,0 +1,353 @@
1
+ /* databricksedu: the in-notebook app (home, slides, document view). */
2
+ (function () {
3
+ var D = window.DBE, cfg = D.cfg || {}, root = document.getElementById('dbe');
4
+ var CTA_URL = 'https://goldhandacademy.com';
5
+ var mods = {}, cats = {};
6
+ D.categories.forEach(function (c) {
7
+ cats[c.id] = c;
8
+ c.modules.forEach(function (m, n) { m.cat = c; m.pos = n; mods[m.id] = m; });
9
+ });
10
+ var S = { cat: D.categories[0].id, q: '', mod: null, mode: 'slides', idx: 0, slides: [], data: null };
11
+ var cache = {};
12
+ function esc(s) { return String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;'); }
13
+ function $(id) { return document.getElementById(id); }
14
+ function showErr(msg) { var e = $('err'); e.style.display = 'block'; e.textContent = 'databricksedu: ' + msg; }
15
+ window.onerror = function (m, src, line) { showErr(m + ' (line ' + line + ')'); };
16
+ root.innerHTML =
17
+ '<div class="top">' +
18
+ '<button class="brand" id="bHome" title="All modules"><span class="lg">🎓</span><span>databricks<em>edu</em></span></button>' +
19
+ '<div class="crumb" id="crumb"></div>' +
20
+ '<div class="seg" id="seg" style="display:none"><button id="bSlides" class="on">🎞️ Slides</button><button id="bDoc">📄 Document</button></div>' +
21
+ '<button class="hbtn" id="bOver" title="Slide overview (O)" style="display:none">▦</button>' +
22
+ '<button class="hbtn pri" id="bSave" style="display:none">💾 Save to workspace</button>' +
23
+ '<button class="hbtn" id="bSize" title="Window height">↕</button>' +
24
+ '<button class="hbtn" id="bFull" title="Full screen (F)" style="display:none">⛶</button>' +
25
+ '</div><div id="bar"></div>' +
26
+ '<div id="main">' +
27
+ '<div id="home"></div>' +
28
+ '<div id="player">' +
29
+ '<section id="slides"><div class="stage" id="stage"></div>' +
30
+ '<div class="controls"><button class="nav" id="prev" title="Previous (←)">←</button><div class="dots" id="dots"></div>' +
31
+ '<span class="hint">← → to move · O overview · D document</span><span class="count" id="count"></span>' +
32
+ '<button class="nav next" id="next" title="Next (→)">Next →</button></div>' +
33
+ '<div id="overview"><div class="ogrid" id="ogrid"></div></div></section>' +
34
+ '<section id="doc"><nav id="toc"></nav><div id="docScroll"></div></section>' +
35
+ '</div>' +
36
+ '<div id="modal"></div><div id="err"></div>' +
37
+ '</div>';
38
+ // ---------------------------------------------------------------- content loading
39
+ function inflate(b64) {
40
+ var bin = atob(b64), bytes = new Uint8Array(bin.length);
41
+ for (var i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
42
+ if (typeof DecompressionStream === 'undefined') {
43
+ return Promise.reject(new Error('this browser cannot unpack the content. Run databricksedu.start(compress=False) instead.'));
44
+ }
45
+ var stream = new Blob([bytes]).stream().pipeThrough(new DecompressionStream('gzip'));
46
+ return new Response(stream).text().then(JSON.parse);
47
+ }
48
+ function load(id) {
49
+ if (cache[id]) return Promise.resolve(cache[id]);
50
+ var c = D.content[id];
51
+ if (!c) return Promise.reject(new Error('no content for ' + id));
52
+ return (c.j ? Promise.resolve(c.j) : inflate(c.z)).then(function (data) { cache[id] = data; return data; });
53
+ }
54
+ // ---------------------------------------------------------------- helpers
55
+ function copyText(text, btn) {
56
+ function done() { if (btn) { var t = btn.textContent; btn.textContent = 'copied ✓'; setTimeout(function () { btn.textContent = t; }, 1400); } }
57
+ function fallback() {
58
+ var ta = document.createElement('textarea');
59
+ ta.value = text; ta.style.position = 'fixed'; ta.style.opacity = '0';
60
+ document.body.appendChild(ta); ta.select();
61
+ try { document.execCommand('copy'); done(); } catch (e) { }
62
+ ta.remove();
63
+ }
64
+ if (navigator.clipboard && navigator.clipboard.writeText) navigator.clipboard.writeText(text).then(done, fallback);
65
+ else fallback();
66
+ }
67
+ function wire(el) {
68
+ el.querySelectorAll('.code').forEach(function (c) {
69
+ var b = c.querySelector('.copy');
70
+ if (b) b.onclick = function () { copyText(c.querySelector('pre').innerText, b); };
71
+ });
72
+ el.querySelectorAll('.dbx>*').forEach(function (n, i) { n.style.setProperty('--i', i); });
73
+ }
74
+ function confetti() {
75
+ var e = ['🎉', '✨', '🎊', '⭐', '🧡', '💜'];
76
+ for (var i = 0; i < 36; i++) {
77
+ var s = document.createElement('div');
78
+ s.className = 'confetti'; s.textContent = e[i % e.length];
79
+ s.style.left = Math.random() * 100 + '%'; s.style.animationDelay = Math.random() * .8 + 's';
80
+ root.appendChild(s);
81
+ setTimeout(function (n) { return function () { n.remove(); }; }(s), 3600);
82
+ }
83
+ }
84
+ function ctaHtml(strong) {
85
+ return '<div class="cta"><span class="big">🎯</span><div><b>' + (strong ? 'Ready to test yourself?' : 'Preparing for a certification?') +
86
+ '</b><br><span>Practice exams are available at GoldHandAcademy.com</span></div>' +
87
+ '<a href="' + CTA_URL + '" target="_blank" rel="noopener">Practice exams →</a></div>';
88
+ }
89
+ // ---------------------------------------------------------------- home
90
+ function chips(m) {
91
+ var c = [];
92
+ if (m.level) c.push(esc(m.level));
93
+ if (m.minutes) c.push('⏱ ' + m.minutes + ' min');
94
+ c.push('🎞️ ' + m.slides + ' slides');
95
+ if (m.demo) c.push('🧪 demo');
96
+ if (m.exercises) c.push('✍️ ' + m.exercises + ' exercise' + (m.exercises > 1 ? 's' : ''));
97
+ if (m.quiz) c.push('🎯 quiz');
98
+ return c.map(function (x) { return '<span>' + x + '</span>'; }).join('');
99
+ }
100
+ function card(m, i) {
101
+ return '<div class="mcard" data-id="' + m.id + '" style="--i:' + i + '"><div class="mh"><div class="mi">' + m.icon + '</div>' +
102
+ '<div class="mt">' + esc(m.title) + '</div></div><div class="ms">' + esc(m.summary) + '</div>' +
103
+ '<div class="mchips">' + chips(m) + '</div><div class="mact">' +
104
+ '<button class="go" data-a="slides">▶ Start</button><button data-a="doc">📖 Read</button><button data-a="save">💾 Save</button></div></div>';
105
+ }
106
+ function renderHome() {
107
+ var total = Object.keys(mods).length, h = '';
108
+ h += '<div class="dbx" style="max-width:none"><div class="hhero"><div class="blob b1"></div><div class="blob b2"></div><div class="blob b3"></div><div>' +
109
+ '<h1>databricks<em>edu</em></h1><p>Bite-sized Databricks lessons that run inside your notebook: animated slides, readable notes, ' +
110
+ 'hands-on notebooks with exercises, and seeded demo data. Pick a module and press <b>Start</b>.</p>' +
111
+ '<div class="hstats"><span>📚 ' + total + ' modules</span><span>🗂️ ' + D.categories.length + ' tracks</span>' +
112
+ '<span>🧪 seeded demo data</span><span>v' + esc(D.version) + '</span></div></div></div>';
113
+ h += '<div class="hrow"><div class="cats">' + D.categories.map(function (c) {
114
+ return '<button class="cat' + (c.id === S.cat && !S.q ? ' on' : '') + '" data-cat="' + c.id + '">' + c.icon + ' ' + esc(c.title) + ' <i>' + c.modules.length + '</i></button>';
115
+ }).join('') + '</div><input id="q" placeholder="🔎 Search all modules" value="' + esc(S.q) + '"></div>';
116
+ var list, cat = cats[S.cat];
117
+ if (S.q) {
118
+ var needle = S.q.toLowerCase();
119
+ list = Object.keys(mods).map(function (k) { return mods[k]; }).filter(function (m) {
120
+ return (m.title + ' ' + m.summary + ' ' + (m.tags || []).join(' ') + ' ' + m.group).toLowerCase().indexOf(needle) >= 0;
121
+ });
122
+ h += '<div class="cdesc">' + list.length + ' module(s) match “' + esc(S.q) + '”</div>';
123
+ } else {
124
+ list = cat.modules;
125
+ h += '<div class="cdesc"><span>' + esc(cat.desc) + '</span><button data-savecat="' + cat.id + '">💾 Save this whole track</button></div>';
126
+ }
127
+ if (!list.length) h += '<div class="empty">Nothing found. Try another word.</div>';
128
+ var group = null, i = 0;
129
+ list.forEach(function (m) {
130
+ var g = S.q ? m.cat.title : (m.group || '');
131
+ if (g !== group) { if (group !== null) h += '</div>'; group = g; if (g) h += '<div class="gtitle">' + esc(g) + '</div>'; h += '<div class="grid">'; }
132
+ h += card(m, i++);
133
+ });
134
+ if (group !== null) h += '</div>';
135
+ h += '<div class="hfoot">' + ctaHtml(!S.q && cat.cta) + '<div class="pip"><b>Take it with you</b><br>Every module saves to your workspace as notebooks.' +
136
+ '<code>databricksedu.save("all")</code></div></div></div>';
137
+ var home = $('home');
138
+ home.innerHTML = h;
139
+ home.querySelectorAll('.cat').forEach(function (b) { b.onclick = function () { S.cat = b.getAttribute('data-cat'); S.q = ''; renderHome(); }; });
140
+ home.querySelectorAll('.mcard').forEach(function (c) {
141
+ var id = c.getAttribute('data-id');
142
+ c.onclick = function (e) {
143
+ var a = e.target.getAttribute && e.target.getAttribute('data-a');
144
+ if (a === 'save') return saveDialog(id);
145
+ openModule(id, a === 'doc' ? 'doc' : 'slides');
146
+ };
147
+ });
148
+ var sc = home.querySelector('[data-savecat]');
149
+ if (sc) sc.onclick = function () { saveDialog(sc.getAttribute('data-savecat')); };
150
+ var qi = $('q'), t = null;
151
+ qi.oninput = function () {
152
+ clearTimeout(t);
153
+ t = setTimeout(function () { S.q = qi.value.trim(); renderHome(); var n = $('q'); n.focus(); n.setSelectionRange(n.value.length, n.value.length); }, 220);
154
+ };
155
+ }
156
+ function showHome() {
157
+ S.mod = null;
158
+ $('player').style.display = 'none'; $('home').style.display = 'block';
159
+ ['seg', 'bOver', 'bSave'].forEach(function (id) { $(id).style.display = 'none'; });
160
+ $('crumb').innerHTML = ''; $('bar').style.width = '0';
161
+ renderHome();
162
+ }
163
+ // ---------------------------------------------------------------- save dialog
164
+ function saveDialog(id) {
165
+ var m = mods[id], c = cats[id], title, items = '', what;
166
+ if (m) {
167
+ title = m.title; what = 'this module';
168
+ items = '<ul>' + m.notebooks.map(function (n) { return '<li>📓 ' + esc(n) + '</li>'; }).join('') + '<li>📝 notes as Markdown</li></ul>';
169
+ } else if (c) { title = c.title; what = 'all ' + c.modules.length + ' modules of this track'; }
170
+ else { id = 'all'; title = 'everything'; what = 'every module'; }
171
+ var cmd = 'import databricksedu\ndatabricksedu.save("' + id + '")';
172
+ var h = '<div class="mbox"><h3>💾 Save “' + esc(title) + '” to your workspace</h3>' +
173
+ '<p>Copies ' + what + ' into <b>/Workspace/Users/&lt;you&gt;/databricksedu/</b> as notebooks you can run and edit.</p>' + items;
174
+ if (cfg.bar) h += '<div class="tip">👆 Fastest: in the <b>Save to workspace</b> bar above this window choose <b>' + esc(title) + '</b> and press the button.</div>';
175
+ h += '<p>' + (cfg.bar ? 'Or run' : 'Run') + ' this in a notebook cell:</p><div class="cmd"><code>' + esc(cmd) + '</code><button id="mcopy">copy</button></div>' +
176
+ '<button class="mclose" id="mclose">Close</button></div>';
177
+ var modal = $('modal');
178
+ modal.innerHTML = h; modal.classList.add('on');
179
+ $('mcopy').onclick = function () { copyText(cmd, $('mcopy')); };
180
+ $('mclose').onclick = function () { modal.classList.remove('on'); };
181
+ modal.onclick = function (e) { if (e.target === modal) modal.classList.remove('on'); };
182
+ }
183
+ // ---------------------------------------------------------------- player
184
+ function openModule(id, mode, at, vstep) {
185
+ var m = mods[id];
186
+ if (!m) return showErr('unknown module ' + id);
187
+ S.mod = m; S.mode = mode || 'slides'; S.idx = 0;
188
+ $('home').style.display = 'none'; $('player').style.display = 'flex';
189
+ ['seg', 'bSave'].forEach(function (x) { $(x).style.display = ''; });
190
+ $('crumb').innerHTML = esc(m.cat.title) + ' › <b>' + esc(m.title) + '</b>';
191
+ $('stage').innerHTML = '<div class="loading">Loading…</div>';
192
+ load(id).then(function (data) {
193
+ if (S.mod !== m) return;
194
+ S.data = data;
195
+ S.slides = data.slides.map(function (s) { return { t: s.t, i: s.i, h: s.h, title: !!s.hero }; });
196
+ if (data.quiz && data.quiz.length) S.slides.push({ t: 'Check yourself', i: '🎯', quiz: true,
197
+ h: '<div class="sec-head"><span class="sec-num">' + String(S.slides.length).padStart(2, '0') + '</span><span class="sec-icon">🎯</span><h2>Check yourself</h2></div><div class="quiz"></div>' });
198
+ S.slides.push({ t: 'Where next?', i: '🎉', fin: true, h: finHtml(m) });
199
+ buildDots(); buildOverview(); buildDoc();
200
+ S.idx = Math.max(0, Math.min(at || 0, S.slides.length - 1));
201
+ setMode(S.mode);
202
+ for (var k = 0; k < (vstep || 0); k++) { var vz = DBXViz.pending($('stage'), 1); if (vz) DBXViz.step(vz, 1); }
203
+ }, function (e) { showErr(e.message); });
204
+ }
205
+ function nextModule(m) { return m.cat.modules[m.pos + 1] || null; }
206
+ function finHtml(m) {
207
+ var nx = nextModule(m), h = '<div class="fin"><div class="big">🎉</div><h2>You finished “' + esc(m.title) + '”</h2><p>Nice work. Here is what you can do next.</p><div class="fcards">';
208
+ if (nx) h += '<div class="fcard" data-go="' + nx.id + '"><b>▶ Next: ' + nx.icon + ' ' + esc(nx.title) + '</b><span>' + esc(nx.summary) + '</span></div>';
209
+ h += '<div class="fcard" data-save="1"><b>💾 Save the notebooks</b><span>' + m.notebooks.map(esc).join(' · ') + '</span></div>';
210
+ h += '<div class="fcard" data-home="1"><b>🗂️ Back to all modules</b><span>' + esc(m.cat.title) + ' has ' + m.cat.modules.length + ' modules.</span></div></div>';
211
+ return h + ctaHtml(!!m.cat.cta) + '</div>';
212
+ }
213
+ function wireFin(el) {
214
+ el.querySelectorAll('[data-go]').forEach(function (c) { c.onclick = function () { openModule(c.getAttribute('data-go'), 'slides'); }; });
215
+ el.querySelectorAll('[data-save]').forEach(function (c) { c.onclick = function () { saveDialog(S.mod.id); }; });
216
+ el.querySelectorAll('[data-home]').forEach(function (c) { c.onclick = showHome; });
217
+ }
218
+ function mountQuiz(el) { dbxQuiz(el, S.data.quiz, function (score, total) { if (score === total) confetti(); }); }
219
+ function buildDots() {
220
+ var dots = $('dots'); dots.innerHTML = '';
221
+ S.slides.forEach(function (s, i) {
222
+ var b = document.createElement('button'); b.title = s.t;
223
+ b.onclick = function () { go(i); }; dots.appendChild(b);
224
+ });
225
+ }
226
+ function buildOverview() {
227
+ var g = $('ogrid'); g.innerHTML = '';
228
+ S.slides.forEach(function (s, i) {
229
+ var c = document.createElement('div'); c.className = 'ocard';
230
+ c.innerHTML = '<div class="n">' + (i + 1) + '</div><div class="i">' + s.i + '</div><div class="t">' + s.t + '</div>';
231
+ c.onclick = function () { $('overview').classList.remove('on'); go(i); };
232
+ g.appendChild(c);
233
+ });
234
+ }
235
+ function renderSlide(dir) {
236
+ var s = S.slides[S.idx], stage = $('stage');
237
+ var el = document.createElement('div');
238
+ el.className = 'slide ' + (dir < 0 ? 'enter-l' : 'enter-r') + (s.title ? ' title' : '');
239
+ el.innerHTML = '<div class="dbx">' + s.h + '</div>';
240
+ stage.innerHTML = ''; stage.appendChild(el);
241
+ wire(el);
242
+ DBXViz.init(el);
243
+ if (s.quiz) mountQuiz(el.querySelector('.quiz'));
244
+ if (s.fin) wireFin(el);
245
+ $('dots').querySelectorAll('button').forEach(function (b, i) { b.classList.toggle('on', i === S.idx); });
246
+ $('count').textContent = (S.idx + 1) + ' / ' + S.slides.length;
247
+ $('bar').style.width = ((S.idx + 1) / S.slides.length * 100) + '%';
248
+ $('next').textContent = S.idx === S.slides.length - 1 ? '✓ Done' : 'Next →';
249
+ }
250
+ function go(i, dir) {
251
+ if (i < 0 || i >= S.slides.length) return;
252
+ var d = dir || (i < S.idx ? -1 : 1);
253
+ S.idx = i; renderSlide(d);
254
+ }
255
+ function advance(dir) {
256
+ var cur = $('stage').querySelector('.slide');
257
+ var vz = cur && DBXViz.pending(cur, dir);
258
+ if (vz) { DBXViz.step(vz, dir); vz.scrollIntoView({ block: 'nearest', behavior: 'smooth' }); return; }
259
+ if (dir > 0 && S.idx === S.slides.length - 1) return showHome();
260
+ go(S.idx + dir, dir);
261
+ }
262
+ function buildDoc() {
263
+ var toc = $('toc'), sc = $('docScroll'), m = S.mod;
264
+ toc.innerHTML = ''; sc.innerHTML = '';
265
+ S.slides.forEach(function (s, i) {
266
+ if (s.fin) return;
267
+ var sec = document.createElement('div');
268
+ sec.className = 'dsec' + (s.title ? ' herosec' : ''); sec.id = 'dsec' + i;
269
+ sec.innerHTML = '<div class="dbx">' + s.h + '</div>';
270
+ sc.appendChild(sec); wire(sec);
271
+ if (s.quiz) mountQuiz(sec.querySelector('.quiz'));
272
+ var a = document.createElement('a');
273
+ a.innerHTML = '<span>' + s.i + '</span><span>' + s.t + '</span>';
274
+ a.onclick = function () { $('raw') && $('raw').remove(); sc.querySelectorAll('.dsec').forEach(function (d) { d.style.display = ''; }); sec.scrollIntoView({ behavior: 'smooth', block: 'start' }); };
275
+ toc.appendChild(a);
276
+ });
277
+ var end = document.createElement('div');
278
+ end.className = 'dsec'; end.innerHTML = '<div class="dbx">' + ctaHtml(!!m.cat.cta) + '</div>';
279
+ sc.appendChild(end);
280
+ var rb = document.createElement('button');
281
+ rb.className = 'rawbtn'; rb.textContent = '⧉ Raw Markdown';
282
+ rb.onclick = function () {
283
+ if ($('raw')) { $('raw').remove(); sc.querySelectorAll('.dsec').forEach(function (d) { d.style.display = ''; }); return; }
284
+ sc.querySelectorAll('.dsec').forEach(function (d) { d.style.display = 'none'; });
285
+ var w = document.createElement('div'); w.id = 'raw';
286
+ w.innerHTML = '<div style="max-width:1000px;margin:0 auto 10px;text-align:right"><button class="rawbtn" style="width:auto;padding:8px 16px" id="rawcopy">copy Markdown</button></div><pre class="rawmd"></pre>';
287
+ w.querySelector('pre').textContent = S.data.md;
288
+ sc.insertBefore(w, sc.firstChild); sc.scrollTop = 0;
289
+ $('rawcopy').onclick = function () { copyText(S.data.md, $('rawcopy')); };
290
+ };
291
+ toc.appendChild(rb);
292
+ sc.onscroll = function () {
293
+ var best = 0, top = sc.getBoundingClientRect().top;
294
+ sc.querySelectorAll('.dsec').forEach(function (d, i) { if (d.getBoundingClientRect().top - top < 120) best = i; });
295
+ toc.querySelectorAll('a').forEach(function (a, i) { a.classList.toggle('on', i === best); });
296
+ };
297
+ }
298
+ function setMode(mode) {
299
+ S.mode = mode;
300
+ $('player').classList.toggle('docmode', mode === 'doc');
301
+ $('bSlides').classList.toggle('on', mode !== 'doc'); $('bDoc').classList.toggle('on', mode === 'doc');
302
+ $('bOver').style.display = mode === 'doc' ? 'none' : '';
303
+ $('overview').classList.remove('on');
304
+ if (mode === 'doc') { $('bar').style.width = '100%'; DBXViz.init($('docScroll'), { autoplay: true }); $('docScroll').onscroll(); }
305
+ else renderSlide(1);
306
+ }
307
+ // ---------------------------------------------------------------- chrome
308
+ $('bHome').onclick = showHome;
309
+ $('bSlides').onclick = function () { setMode('slides'); };
310
+ $('bDoc').onclick = function () { setMode('doc'); };
311
+ $('bOver').onclick = function () { $('overview').classList.toggle('on'); };
312
+ $('bSave').onclick = function () { saveDialog(S.mod.id); };
313
+ $('prev').onclick = function () { advance(-1); };
314
+ $('next').onclick = function () { advance(1); };
315
+ var sizes = [680, 820, 980], H = cfg.height || 820;
316
+ function setH(h) {
317
+ H = h; root.style.height = h + 'px';
318
+ try { if (window.frameElement && window.frameElement.hasAttribute('data-dbe')) window.frameElement.style.height = (h + 4) + 'px'; } catch (e) { }
319
+ }
320
+ setH(H);
321
+ $('bSize').onclick = function () {
322
+ var next = sizes.filter(function (s) { return s > H; })[0] || sizes[0];
323
+ setH(next);
324
+ };
325
+ var fsOk = document.fullscreenEnabled || document.webkitFullscreenEnabled;
326
+ if (fsOk) {
327
+ $('bFull').style.display = '';
328
+ $('bFull').onclick = toggleFs;
329
+ document.addEventListener('fullscreenchange', function () { root.classList.toggle('fs', !!document.fullscreenElement); });
330
+ }
331
+ function toggleFs() {
332
+ if (!fsOk) return;
333
+ if (document.fullscreenElement) document.exitFullscreen();
334
+ else (root.requestFullscreen || root.webkitRequestFullscreen).call(root);
335
+ }
336
+ document.addEventListener('keydown', function (e) {
337
+ if (/INPUT|TEXTAREA/.test((e.target.tagName || ''))) return;
338
+ if (e.key === 'Escape') { $('modal').classList.remove('on'); $('overview').classList.remove('on'); return; }
339
+ if (!S.mod) return;
340
+ if (e.key === 'd' || e.key === 'D') return setMode(S.mode === 'doc' ? 'slides' : 'doc');
341
+ if (e.key === 'f' || e.key === 'F') return toggleFs();
342
+ if (S.mode === 'doc') return;
343
+ if (e.key === 'ArrowRight' || e.key === 'PageDown' || e.key === ' ') { e.preventDefault(); advance(1); }
344
+ else if (e.key === 'ArrowLeft' || e.key === 'PageUp') { e.preventDefault(); advance(-1); }
345
+ else if (e.key === 'o' || e.key === 'O') $('overview').classList.toggle('on');
346
+ else if (e.key === 'Home') go(0);
347
+ else if (e.key === 'End') go(S.slides.length - 1);
348
+ });
349
+ // ---------------------------------------------------------------- start
350
+ var r = String(cfg.route || 'home').split('/');
351
+ if ((r[0] === 'slides' || r[0] === 'doc') && mods[r[1]]) { S.cat = mods[r[1]].cat.id; openModule(r[1], r[0], +r[2] || 0, +r[3] || 0); }
352
+ else { if (r[0] === 'cat' && cats[r[1]]) S.cat = r[1]; showHome(); }
353
+ })();
@@ -0,0 +1 @@
1
+ .dbx{--navy:#1B3139;--accent:#FF3621;--blue:#2272B4;--teal:#00A3A1;--purple:#7C4DFF;--amber:#FFAB00;--ink:#1F2937;--muted:#6B7280;--line:#E5E7EB;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;color:var(--ink);font-size:15px;line-height:1.6;max-width:1100px}.dbx *{box-sizing:border-box}.dbx>*{animation:dbxRise .55s cubic-bezier(.2,.7,.2,1) both}.dbx>*:nth-child(2){animation-delay:.06s}.dbx>*:nth-child(3){animation-delay:.12s}.dbx>*:nth-child(4){animation-delay:.18s}.dbx>*:nth-child(5){animation-delay:.24s}.dbx>*:nth-child(6){animation-delay:.3s}.dbx>*:nth-child(n+7){animation-delay:.36s}@keyframes dbxRise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}@keyframes dbxGrad{0%{background-position:0% 50%}50%{background-position:100% 50%}100%{background-position:0% 50%}}@keyframes dbxFloat{0%,100%{transform:translate(0,0) scale(1)}50%{transform:translate(18px,-14px) scale(1.08)}}@keyframes dbxLine{from{width:0}to{width:100%}}@keyframes dbxPulse{0%,100%{box-shadow:0 0 0 0 rgba(255,54,33,.25)}50%{box-shadow:0 0 0 8px rgba(255,54,33,0)}}.dbx .hero{position:relative;overflow:hidden;border-radius:18px;padding:38px 40px 34px;margin:4px 0 18px;color:#fff;background:linear-gradient(120deg,#1B3139,#22425a,#2a2f6b,#1B3139);background-size:300% 300%;animation:dbxGrad 14s ease infinite,dbxRise .6s both}.dbx .blob{position:absolute;border-radius:50%;filter:blur(30px);opacity:.55;animation:dbxFloat 9s ease-in-out infinite}.dbx .b1{width:220px;height:220px;background:#FF3621;right:-40px;top:-60px}.dbx .b2{width:180px;height:180px;background:#7C4DFF;right:160px;bottom:-90px;animation-delay:-3s}.dbx .b3{width:140px;height:140px;background:#00A3A1;left:-40px;bottom:-50px;animation-delay:-6s}.dbx .hero-in{position:relative}.dbx .kicker{text-transform:uppercase;letter-spacing:.14em;font-size:12px;color:#FFC4BA;font-weight:700}.dbx .hero h1{font-size:34px;line-height:1.15;margin:8px 0 14px;color:#fff;font-weight:800}.dbx .kicker-inline{display:inline-block;font-size:.5em;vertical-align:middle;background:var(--accent);padding:4px 10px;border-radius:999px;margin-right:10px;letter-spacing:.08em;text-transform:uppercase}.dbx .chips{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:12px}.dbx .chip{background:rgba(255,255,255,.14);border:1px solid rgba(255,255,255,.25);padding:4px 12px;border-radius:999px;font-size:13px;color:#fff}.dbx .chip strong{color:#fff}.dbx .sub{color:#E2E8F0;font-size:16px;margin:0;max-width:820px}.dbx .sub strong,.dbx .sub b{color:#FFD7CF}.dbx .sub code{background:rgba(255,255,255,.16);color:#fff}.dbx .idea{display:flex;gap:14px;align-items:flex-start;background:linear-gradient(135deg,#FFF4F1,#FFF);border:1px solid #FFD0C7;border-left:5px solid var(--accent);border-radius:14px;padding:16px 18px;margin:14px 0;animation:dbxRise .55s both,dbxPulse 3s ease-in-out 1s 2}.dbx .idea-icon{font-size:26px;line-height:1}.dbx .idea b{color:#C62D1A}.dbx .sec-head{display:flex;align-items:center;gap:12px;margin:6px 0 14px;position:relative;padding-bottom:10px}.dbx .sec-head:after{content:"";position:absolute;left:0;bottom:0;height:3px;border-radius:3px;background:linear-gradient(90deg,var(--accent),var(--purple),var(--teal));animation:dbxLine .9s ease-out both}.dbx .sec-num{font-weight:800;font-size:13px;color:#fff;background:linear-gradient(135deg,var(--accent),#ff7a59);padding:5px 10px;border-radius:9px;letter-spacing:.05em}.dbx .sec-icon{font-size:26px;line-height:1}.dbx .sec-head h2{margin:0;font-size:25px;color:var(--navy);font-weight:800;border:0}.dbx h3{color:var(--navy);margin:18px 0 8px}.dbx p{margin:8px 0}.dbx a{color:var(--blue)}.dbx code{background:#EEF2FF;color:#3730A3;padding:1px 6px;border-radius:6px;font-size:.88em;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.dbx .tbl{overflow-x:auto;border-radius:12px;border:1px solid var(--line);box-shadow:0 2px 10px rgba(27,49,57,.06);margin:12px 0;background:#fff}.dbx table{border-collapse:collapse;width:100%;font-size:14px}.dbx th{background:linear-gradient(135deg,#1B3139,#2B4F63);color:#fff;text-align:left;padding:10px 12px;font-weight:600}.dbx td{padding:9px 12px;border-top:1px solid var(--line);vertical-align:top}.dbx tr:nth-child(even) td{background:#F8FAFC}.dbx tr:hover td{background:#FFF4F1}.dbx td:first-child{font-weight:600;color:var(--navy)}.dbx ul,.dbx ol{padding-left:22px;margin:8px 0}.dbx li{margin:5px 0}.dbx li::marker{color:var(--accent)}.dbx li.bad,.dbx li.good{list-style:none;margin:8px 0 8px -22px;padding:10px 14px;border-radius:10px}.dbx li.bad{background:#FFF1F0;border:1px solid #FFCDC7}.dbx li.good{background:#ECFDF3;border:1px solid #B7EBC9}.dbx blockquote.callout{margin:14px 0;padding:12px 16px 12px 46px;border-radius:12px;background:linear-gradient(135deg,#E8F1FF,#F5F9FF);border:1px solid #C7DBFF;position:relative;color:#1E3A5F}.dbx blockquote.callout:before{content:"ℹ️";position:absolute;left:14px;top:11px;font-size:18px}.dbx blockquote.callout p{margin:4px 0}.dbx .code{border-radius:12px;overflow:hidden;margin:12px 0;box-shadow:0 8px 24px rgba(15,23,42,.18);background:#0D1117}.dbx .code-bar{display:flex;align-items:center;gap:6px;padding:8px 12px;background:#161B22;border-bottom:1px solid #30363D}.dbx .code-bar i{width:11px;height:11px;border-radius:50%;background:#FF5F57;display:inline-block}.dbx .code-bar i:nth-child(2){background:#FEBC2E}.dbx .code-bar i:nth-child(3){background:#28C840}.dbx .lang{margin-left:8px;color:#8B949E;font-size:11px;letter-spacing:.1em;font-weight:700}.dbx .run{margin-left:auto;color:#3FB950;font-size:11px;font-weight:700}.dbx .copy{display:none}.dbx .code pre{margin:0;padding:14px 16px;color:#E6EDF3;font-size:13px;line-height:1.55;overflow-x:auto;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;background:transparent}.dbx pre.diagram{background:linear-gradient(135deg,#F8FAFC,#EEF2FF);border:1px dashed #A5B4FC;border-radius:12px;padding:14px 16px;font-size:13px;color:#312E81;overflow-x:auto;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.dbx .tryit{display:flex;gap:12px;align-items:center;background:linear-gradient(135deg,#ECFDF3,#F0FDFA);border:1px solid #A7F3D0;border-radius:12px;padding:12px 16px;margin:12px 0}.dbx .tryit b{color:#047857}.dbx .present{display:flex;gap:16px;align-items:center;border-radius:14px;padding:16px 20px;background:linear-gradient(120deg,#2a2f6b,#7C4DFF);color:#fff;box-shadow:0 10px 30px rgba(124,77,255,.3)}.dbx .present b{font-size:17px}.dbx .present span{color:#E9E5FF}.dbx .present .big{font-size:34px}.dbx .footer{margin-top:10px;padding:14px 18px;border-radius:12px;background:#F8FAFC;border:1px solid var(--line);color:var(--muted);font-size:13px}.dbx .hero-icon{margin-right:12px}.dbx .run.todo{color:#FBBF24}.dbx details.solution{margin:12px 0;border:1px dashed #C4B5FD;border-radius:12px;padding:4px 14px;background:#FAF5FF}.dbx details.solution summary{cursor:pointer;font-weight:700;color:#6D28D9;padding:8px 0}.dbx details.solution[open]{padding-bottom:10px}.dbx .exercise{display:flex;gap:12px;align-items:center;background:linear-gradient(135deg,#FFFBEB,#FFF7ED);border:1px solid #FCD34D;border-radius:12px;padding:12px 16px;margin:12px 0}.dbx .exercise b{color:#B45309}.dbx .cta{display:flex;gap:18px;align-items:center;flex-wrap:wrap;border-radius:16px;padding:20px 24px;margin:14px 0;color:#fff;background:linear-gradient(120deg,#0F172A,#7C2D12,#B45309);background-size:220% 220%;animation:dbxGrad 10s ease infinite;box-shadow:0 12px 34px rgba(180,83,9,.3)}.dbx .cta .big{font-size:40px}.dbx .cta b{font-size:19px;color:#fff}.dbx .cta span{color:#FDE68A}.dbx .cta a{margin-left:auto;background:#FBBF24;color:#1F2937;font-weight:800;padding:10px 20px;border-radius:999px;text-decoration:none;white-space:nowrap}.dbx .dataset{border:1px solid #BFDBFE;border-radius:14px;background:linear-gradient(135deg,#EFF6FF,#fff);padding:14px 16px;margin:12px 0}.dbx .ds-head{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.dbx .ds-head>div{flex:1;min-width:240px}.dbx .ds-head span{color:var(--muted);font-size:.9em}.dbx .ds-icon{font-size:30px;color:inherit}.dbx .ds-call{white-space:nowrap}.dbx .ds-tables{display:flex;gap:12px;flex-wrap:wrap;margin-top:12px}.dbx .ds-table{flex:1;min-width:210px;background:#fff;border:1px solid var(--line);border-radius:12px;overflow:hidden;box-shadow:0 2px 8px rgba(27,49,57,.06)}.dbx .ds-th{background:linear-gradient(135deg,#1B3139,#2B4F63);color:#fff;font-weight:700;padding:7px 12px;font-size:.92em}.dbx .ds-cm{color:var(--muted);font-size:.8em;padding:5px 12px;border-bottom:1px solid var(--line)}.dbx .ds-col{display:flex;gap:8px;align-items:center;padding:3px 12px;font-size:.84em;border-bottom:1px solid #F1F5F9}.dbx .ds-col code{background:transparent;padding:0;color:var(--navy)}.dbx .ds-col .ty{color:#94A3B8;font-size:.86em;margin-left:auto}.dbx .k{font-size:.72em;font-weight:800;padding:1px 6px;border-radius:6px;white-space:nowrap}.dbx .k.pk{background:#FEF3C7;color:#92400E}.dbx .k.fk{background:#DBEAFE;color:#1E40AF}
@@ -0,0 +1,47 @@
1
+ function dbxQuiz(root, questions, onDone) {
2
+ if (typeof root === 'string') root = document.getElementById(root);
3
+ var i = 0, score = 0, picked = null, shown = false, done = false;
4
+ function esc(s) { return String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/`([^`]+)`/g, '<code style="background:#EEF2FF;color:#3730A3;padding:1px 6px;border-radius:6px">$1</code>'); }
5
+ function btn(label, primary) { return '<button style="margin-top:16px;padding:10px 22px;border-radius:10px;border:none;cursor:pointer;font-weight:700;background:' + (primary ? 'linear-gradient(135deg,#FF3621,#7C4DFF)' : '#E5E7EB') + ';color:' + (primary ? '#fff' : '#6B7280') + ';font-size:0.95em;box-shadow:' + (primary ? '0 6px 18px rgba(124,77,255,.3)' : 'none') + '">' + label + '</button>'; }
6
+ var box = 'padding:22px 24px;border-radius:16px;background:#fff;border:1px solid #E5E7EB;box-shadow:0 8px 28px rgba(27,49,57,.08);animation:dbxQ .4s ease both';
7
+ var style = '<style>@keyframes dbxQ{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}</style>';
8
+ function bar() {
9
+ var h = '<div style="display:flex;gap:6px;margin-bottom:14px">';
10
+ for (var k = 0; k < questions.length; k++) h += '<div style="flex:1;height:6px;border-radius:6px;background:' + (k < i ? 'linear-gradient(90deg,#FF3621,#7C4DFF)' : k === i ? '#C4B5FD' : '#E5E7EB') + '"></div>';
11
+ return h + '</div>';
12
+ }
13
+ function render() {
14
+ if (i >= questions.length) {
15
+ var pct = Math.round(score / questions.length * 100), msg = pct === 100 ? 'Perfect! 🎉' : pct >= 60 ? 'Nice work! 💪' : 'Worth another look 📖';
16
+ root.innerHTML = style + '<div style="' + box + ';text-align:center"><div style="font-size:48px">' + (pct === 100 ? '🏆' : pct >= 60 ? '🌟' : '🔁') + '</div><div style="font-size:1.6em;font-weight:800;color:#1B3139">' + score + ' / ' + questions.length + '</div><div style="color:#6B7280;margin-top:4px">' + msg + '</div>' + btn('Retake', true) + '</div>';
17
+ root.querySelector('button').onclick = function () { i = 0; score = 0; picked = null; shown = false; done = false; render(); };
18
+ if (!done && onDone) { done = true; onDone(score, questions.length); }
19
+ return;
20
+ }
21
+ var Q = questions[i], h = style + '<div style="' + box + '">' + bar();
22
+ h += '<div style="color:#7C4DFF;font-size:0.8em;font-weight:800;letter-spacing:.08em;text-transform:uppercase;margin-bottom:6px">Question ' + (i + 1) + ' of ' + questions.length + '</div>';
23
+ h += '<div style="font-weight:700;color:#1B3139;margin-bottom:14px;line-height:1.5;font-size:1.05em">' + esc(Q.q) + '</div>';
24
+ Q.o.forEach(function (t, k) {
25
+ var bg = '#fff', bd = '#E5E7EB', mark = String.fromCharCode(65 + k);
26
+ if (shown && k === Q.c) { bg = '#ECFDF3'; bd = '#22C55E'; mark = '✓'; }
27
+ else if (shown && k === picked) { bg = '#FFF1F0'; bd = '#EF4444'; mark = '✗'; }
28
+ else if (!shown && k === picked) { bg = '#F5F3FF'; bd = '#7C4DFF'; }
29
+ h += '<div data-k="' + k + '" style="display:flex;gap:12px;align-items:center;padding:11px 14px;margin:8px 0;border:2px solid ' + bd + ';background:' + bg + ';border-radius:12px;cursor:' + (shown ? 'default' : 'pointer') + ';color:#1F2937;transition:all .15s">' +
30
+ '<span style="flex:none;width:28px;height:28px;border-radius:8px;display:inline-flex;align-items:center;justify-content:center;font-weight:800;font-size:.85em;background:' + (bd === '#E5E7EB' ? '#F1F5F9' : bd) + ';color:' + (bd === '#E5E7EB' ? '#64748B' : '#fff') + '">' + mark + '</span><span>' + esc(t) + '</span></div>';
31
+ });
32
+ if (shown) {
33
+ var ok = picked === Q.c;
34
+ h += '<div style="margin-top:14px;padding:14px 16px;border-radius:12px;background:' + (ok ? '#ECFDF3' : '#FFF7ED') + ';border:1px solid ' + (ok ? '#A7F3D0' : '#FED7AA') + ';color:#1F2937;animation:dbxQ .3s both"><strong>' + (ok ? '✅ Correct.' : '💡 Not quite.') + '</strong> ' + esc(Q.e) + '</div>' + btn(i + 1 < questions.length ? 'Next →' : 'See score', true);
35
+ } else {
36
+ h += btn('Submit', picked !== null);
37
+ }
38
+ root.innerHTML = h + '</div>';
39
+ if (!shown) root.querySelectorAll('[data-k]').forEach(function (el) { el.onclick = function () { picked = +el.getAttribute('data-k'); render(); }; });
40
+ root.querySelector('button').onclick = function () {
41
+ if (!shown) { if (picked === null) return; if (picked === Q.c) score++; shown = true; }
42
+ else { i++; picked = null; shown = false; }
43
+ render();
44
+ };
45
+ }
46
+ render();
47
+ }
@@ -0,0 +1 @@
1
+ @keyframes vzPop{0%{opacity:0;transform:scale(.92) translateY(8px)}60%{transform:scale(1.03)}100%{opacity:1;transform:none}}@keyframes vzDot{0%{left:-6px;opacity:0}15%{opacity:1}85%{opacity:1}100%{left:100%;opacity:0}}@keyframes vzGlow{0%,100%{box-shadow:0 0 0 0 rgba(34,197,94,.45)}50%{box-shadow:0 0 0 7px rgba(34,197,94,0)}}@keyframes vzFade{to{opacity:.25}}.dbx .vz{border:1px solid var(--line);border-radius:16px;background:linear-gradient(180deg,#fff,#F8FAFC);padding:14px 16px;margin:14px 0;box-shadow:0 6px 22px rgba(27,49,57,.08)}.dbx .vz *{box-sizing:border-box}.dbx .vz [data-state=hide],.dbx .vz [data-state=gone]{display:none!important}.dbx .vz-top{display:flex;align-items:center;gap:10px;margin-bottom:10px;min-height:30px}.dbx .vz-title{font-weight:800;color:var(--navy);font-size:.98em}.dbx .vz-title:empty{display:none}.dbx .vz-ctl{margin-left:auto;display:flex;align-items:center;gap:6px}.dbx .vz-ctl button{border:1px solid var(--line);background:#fff;border-radius:8px;min-width:32px;height:30px;cursor:pointer;font-size:14px;color:var(--navy);font-family:inherit}.dbx .vz-ctl button:hover{border-color:var(--accent);color:var(--accent)}.dbx .vz-ctl button.play{background:linear-gradient(135deg,#FF3621,#7C4DFF);color:#fff;border:0;padding:0 12px;font-weight:700}.dbx .vz-ctl .cnt{font-size:.8em;color:var(--muted);min-width:44px;text-align:center}.dbx .vz-notes{margin-top:10px}.dbx .vz-note{display:flex;gap:10px;align-items:flex-start;padding:9px 12px;border-radius:10px;background:#F1F5F9;margin-top:6px;font-size:.93em}.dbx .vz-note b{color:var(--navy)}.dbx .vz-note b.vz-lb{display:inline-block;background:var(--navy);color:#fff;border-radius:7px;padding:0 9px;margin-right:4px;font-size:.9em}.dbx .vz-n{flex:none;width:24px;height:24px;border-radius:50%;background:linear-gradient(135deg,#FF3621,#7C4DFF);color:#fff;font-weight:800;font-size:.78em;display:inline-flex;align-items:center;justify-content:center}.dbx .vz.js .vz-note{display:none}.dbx .vz.js .vz-note.on{display:flex;animation:dbxRise .35s both;background:linear-gradient(135deg,#FFF4F1,#F5F3FF);border:1px solid #FFD0C7}.dbx .vz-cap{margin-top:8px;color:var(--muted);font-size:.86em;text-align:center}.dbx .c-bronze{--c:#B45309;--cb:#FEF3E2}.dbx .c-silver{--c:#64748B;--cb:#F1F5F9}.dbx .c-gold{--c:#CA8A04;--cb:#FEF9C3}.dbx .c-red{--c:#DC2626;--cb:#FEE2E2}.dbx .c-blue{--c:#2563EB;--cb:#DBEAFE}.dbx .c-teal{--c:#0D9488;--cb:#CCFBF1}.dbx .c-purple{--c:#7C3AED;--cb:#EDE9FE}.dbx .c-amber{--c:#D97706;--cb:#FEF3C7}.dbx .c-green{--c:#16A34A;--cb:#DCFCE7}.dbx .c-navy{--c:#1B3139;--cb:#E2E8F0}.dbx .c-gray{--c:#6B7280;--cb:#F3F4F6}.dbx .c-pink{--c:#DB2777;--cb:#FCE7F3}.dbx .vz-ic{font-size:26px;line-height:1.1}.dbx .vz-flow{display:flex;align-items:stretch;gap:0;flex-wrap:wrap;justify-content:center}.dbx .vz-node{flex:1 1 130px;max-width:260px;background:var(--cb);border:2px solid var(--c);border-radius:14px;padding:12px 12px 10px;text-align:center;animation:vzPop .5s both;animation-delay:calc(var(--i)*.14s);transition:transform .3s,opacity .3s,box-shadow .3s}.dbx .vz-node b{display:block;color:var(--c);font-size:1.02em;margin-top:4px}.dbx .vz-node>span{display:block;color:#475569;font-size:.84em;line-height:1.35}.dbx .vz-node ul{text-align:left;margin:6px 0 0;padding-left:18px;font-size:.82em;color:#334155}.dbx .vz-node li{margin:2px 0}.dbx .vz-node[data-state=dim]{opacity:.38}.dbx .vz-node[data-state=hl]{transform:translateY(-4px) scale(1.04);box-shadow:0 10px 26px rgba(27,49,57,.2)}.dbx .vz-edge{flex:0 0 64px;display:flex;flex-direction:column;justify-content:center;align-items:center;padding:0 4px}.dbx .vz-edge em{font-size:.72em;color:var(--muted);font-style:normal;text-align:center;line-height:1.2;margin-bottom:4px;min-height:1em}.dbx .vz-line{position:relative;width:100%;height:4px;border-radius:4px;background:#CBD5E1;overflow:visible}.dbx .vz-line:after{content:"";position:absolute;right:-2px;top:-5px;border-left:9px solid #94A3B8;border-top:7px solid transparent;border-bottom:7px solid transparent}.dbx .vz-line i{position:absolute;top:-3px;width:10px;height:10px;border-radius:50%;background:var(--accent);animation:vzDot 2.1s linear infinite}.dbx .vz-line i:nth-child(2){animation-delay:.7s;background:var(--purple)}.dbx .vz-line i:nth-child(3){animation-delay:1.4s;background:var(--teal)}.dbx .vz-group{border:1px solid var(--line);border-radius:12px;background:#fff;margin-bottom:8px;overflow:hidden}.dbx .vz-group.log{border-color:#DDD6FE;background:#FAF5FF}.dbx .vz-dir{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.84em;font-weight:700;color:var(--navy);padding:6px 12px;background:rgba(27,49,57,.05)}.dbx .vz-file{display:flex;align-items:center;gap:8px;padding:5px 12px;border-top:1px solid #F1F5F9;font-size:.86em;transition:opacity .3s,background .3s}.dbx .vz-file .fn{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;color:#0F172A;word-break:break-all}.dbx .vz-tag{font-size:.82em;background:#EEF2FF;color:#3730A3;border-radius:999px;padding:1px 9px;white-space:nowrap}.dbx .vz-tag[data-state=new]{animation:vzPop .45s both;background:#FEF3C7;color:#92400E}.dbx .vz-file .fs{margin-left:auto;font-size:.72em;font-weight:800;border-radius:999px;padding:1px 9px;white-space:nowrap}.dbx .vz-group:not(.log) .vz-file .fs:after{content:"active";color:#15803D}.dbx .vz-group:not(.log) .vz-file .fs{background:#DCFCE7}.dbx .vz-file[data-state=new]{animation:vzPop .5s both;background:#F0FDF4}.dbx .vz-file[data-state=new] .fi{animation:vzGlow 1.2s 2;border-radius:50%}.dbx .vz-file[data-state=tomb],.dbx .vz-file[data-state=tombnew]{background:#F8FAFC}.dbx .vz-file[data-state=tomb] .fn,.dbx .vz-file[data-state=tombnew] .fn{text-decoration:line-through;color:#94A3B8}.dbx .vz-group:not(.log) .vz-file[data-state=tomb] .fs,.dbx .vz-group:not(.log) .vz-file[data-state=tombnew] .fs{background:#E2E8F0}.dbx .vz-group:not(.log) .vz-file[data-state=tomb] .fs:after,.dbx .vz-group:not(.log) .vz-file[data-state=tombnew] .fs:after{content:"removed (tombstone)";color:#475569}.dbx .vz-file[data-state=tombnew]{animation:vzPop .45s both;background:#FFF7ED}.dbx .vz-file[data-state=del]{background:#FEF2F2;animation:vzFade 1.2s .3s both}.dbx .vz-file[data-state=del] .fn{text-decoration:line-through;color:#B91C1C}.dbx .vz-group:not(.log) .vz-file[data-state=del] .fs{background:#FEE2E2}.dbx .vz-group .vz-file[data-state=del] .fs:after{content:"deleted from storage";color:#B91C1C}.dbx .vz-legend{display:flex;gap:14px;flex-wrap:wrap;font-size:.76em;color:var(--muted);margin-top:4px}.dbx .lg:before{content:"";display:inline-block;width:10px;height:10px;border-radius:3px;margin-right:5px;vertical-align:-1px}.dbx .lg.on:before{background:#22C55E}.dbx .lg.tomb:before{background:#94A3B8}.dbx .lg.log:before{background:#A78BFA}.dbx .vz-table .tbl{margin:0}.dbx .vz-table td{transition:background .3s}.dbx .vz-table td i{color:#94A3B8}.dbx .vz-table tr[data-state=new] td{background:#DCFCE7!important;animation:vzPop .45s both}.dbx .vz-table tr[data-state=upd] td{background:#FEF9C3!important}.dbx .vz-table tr[data-state=hl] td{background:#DBEAFE!important}.dbx .vz-table tr[data-state=del] td,.dbx .vz-table tr[data-state=delnew] td{background:#FEE2E2!important;text-decoration:line-through;color:#991B1B}.dbx .vz-table tr[data-state=del] td{opacity:.55}.dbx .vz-table td span[data-state=new]{display:inline-block;animation:vzPop .45s both;background:#FDE047;border-radius:5px;padding:0 5px;font-weight:700}.dbx pre.vz-code{margin:0;background:#0D1117;color:#E6EDF3;border-radius:12px;padding:12px 0;font-size:12.5px;line-height:1.6;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;white-space:pre-wrap;word-break:break-all;overflow-x:auto}.dbx .vz-ln{display:block;padding:0 14px 0 46px;position:relative;border-left:3px solid transparent;transition:opacity .3s,background .3s}.dbx .vz-ln>i{position:absolute;left:0;width:34px;text-align:right;color:#6E7681;font-style:normal;user-select:none}.dbx .vz.js .vz-ln[data-state=dim]{opacity:.32}.dbx .vz.js .vz-ln[data-state=hl]{background:rgba(255,214,10,.13);border-left-color:#FBBF24}.dbx .vz-cards{display:flex;gap:12px;flex-wrap:wrap}.dbx .vz-card{flex:1 1 200px;background:#fff;border:1px solid var(--line);border-top:5px solid var(--c);border-radius:14px;padding:14px;animation:vzPop .5s both;animation-delay:calc(var(--i)*.14s)}.dbx .vz-card b{display:block;color:var(--c);font-size:1.05em;margin-top:4px}.dbx .vz-card>span{display:block;color:var(--muted);font-size:.85em;min-height:1.2em}.dbx .vz-card ul{list-style:none;padding:0;margin:8px 0 0;font-size:.88em}.dbx .vz-card li{margin:5px 0;padding:5px 9px;border-radius:8px;background:#F8FAFC;list-style:none}.dbx .vz-card li.good{background:#ECFDF3;border:0;margin:5px 0;padding:5px 9px}.dbx .vz-card li.bad{background:#FFF1F0;border:0;margin:5px 0;padding:5px 9px}.dbx .vz-foot{margin-top:8px;font-size:.82em;color:var(--c);font-weight:700}.dbx .vz-tls{display:flex;gap:0;flex-wrap:wrap;position:relative;padding-top:4px}.dbx .vz-tl{flex:1 1 110px;text-align:center;position:relative;padding:0 6px 4px;animation:vzPop .45s both;animation-delay:calc(var(--i)*.1s)}.dbx .vz-tl:before{content:"";position:absolute;top:17px;left:0;right:0;height:4px;background:#E2E8F0;z-index:0}.dbx .vz-dot{position:relative;z-index:1;display:inline-flex;align-items:center;justify-content:center;min-width:38px;height:38px;padding:0 8px;border-radius:999px;background:var(--c);color:#fff;font-weight:800;font-size:.82em;box-shadow:0 4px 12px rgba(27,49,57,.2)}.dbx .vz-tl b{display:block;color:var(--navy);font-size:.88em;margin-top:6px;line-height:1.25}.dbx .vz-tl>span:last-child{display:block;color:var(--muted);font-size:.78em;line-height:1.3}.dbx .vz .vz-tl[data-state=hide]{display:block!important;visibility:hidden}.dbx .vz-tl[data-state=new] .vz-dot{animation:vzGlow 1.2s 2;transform:scale(1.15)}.dbx .vz-layers{display:flex;flex-direction:column;gap:8px}.dbx .vz-layer{display:flex;align-items:center;gap:12px;background:var(--cb);border-left:6px solid var(--c);border-radius:12px;padding:10px 14px;animation:vzPop .5s both;animation-delay:calc(var(--i)*.14s)}.dbx .vz-lt{flex:0 0 30%;min-width:150px}.dbx .vz-lt b{display:block;color:var(--c)}.dbx .vz-lt em{font-style:normal;color:#475569;font-size:.84em}.dbx .vz-li{display:flex;gap:6px;flex-wrap:wrap;flex:1}.dbx .vz-li span{background:#fff;border:1px solid rgba(0,0,0,.08);border-radius:999px;padding:3px 11px;font-size:.84em;color:#334155}.dbx ul.vz-tree,.dbx ul.vz-tree ul{list-style:none;margin:0;padding-left:26px;position:relative}.dbx ul.vz-tree{padding-left:0}.dbx ul.vz-tree li{margin:6px 0;position:relative;list-style:none}.dbx ul.vz-tree ul li:before{content:"";position:absolute;left:-16px;top:-6px;width:14px;height:24px;border-left:2px solid #CBD5E1;border-bottom:2px solid #CBD5E1;border-bottom-left-radius:8px}.dbx .vz-tn{display:inline-flex;align-items:center;gap:8px;background:var(--cb);border:1.5px solid var(--c);border-radius:10px;padding:5px 12px;animation:vzPop .45s both;animation-delay:calc(var(--i)*.08s)}.dbx .vz-tn .vz-ic{font-size:18px}.dbx .vz-tn b{color:var(--c)}.dbx .vz-tn em{font-style:normal;color:#475569;font-size:.84em}
@@ -0,0 +1,84 @@
1
+ /* Step-through visualizations. Elements carry data-st="0:state,2:state"; a step sets data-state. */
2
+ (function () {
3
+ if (window.DBXViz) return;
4
+ function parse(el) {
5
+ if (!el._st) {
6
+ el._st = el.getAttribute('data-st').split(',').map(function (p) {
7
+ var i = p.indexOf(':');
8
+ return [+p.slice(0, i), p.slice(i + 1)];
9
+ });
10
+ }
11
+ return el._st;
12
+ }
13
+ function apply(vz, k) {
14
+ vz._k = k;
15
+ vz.querySelectorAll('[data-st]').forEach(function (el) {
16
+ var m = parse(el), s = m[0][1];
17
+ for (var i = 0; i < m.length; i++) if (m[i][0] <= k) s = m[i][1];
18
+ if (el.getAttribute('data-state') !== s) el.setAttribute('data-state', s);
19
+ });
20
+ vz.querySelectorAll('.vz-note').forEach(function (n) {
21
+ n.classList.toggle('on', +n.getAttribute('data-step') === k);
22
+ });
23
+ if (vz._cnt) vz._cnt.textContent = (k + 1) + ' / ' + vz._n;
24
+ if (vz._play) vz._play.textContent = k >= vz._n - 1 ? '↻ Replay' : (vz._timer ? '⏸ Pause' : '▶ Play');
25
+ }
26
+ function stop(vz) {
27
+ if (vz._timer) { clearInterval(vz._timer); vz._timer = null; }
28
+ }
29
+ function step(vz, dir) {
30
+ var k = vz._k + dir;
31
+ if (k < 0 || k >= vz._n) return false;
32
+ apply(vz, k);
33
+ return true;
34
+ }
35
+ function play(vz, ms) {
36
+ stop(vz);
37
+ if (vz._k >= vz._n - 1) apply(vz, 0);
38
+ vz._timer = setInterval(function () {
39
+ if (!step(vz, 1) || vz._k >= vz._n - 1) { stop(vz); apply(vz, vz._k); }
40
+ }, ms || 2200);
41
+ apply(vz, vz._k);
42
+ }
43
+ function setup(vz, opts) {
44
+ if (vz._n) return;
45
+ vz._n = +vz.getAttribute('data-steps');
46
+ vz.classList.add('js');
47
+ var ctl = vz.querySelector('.vz-ctl');
48
+ function btn(label, title, cls, fn) {
49
+ var b = document.createElement('button');
50
+ b.type = 'button'; b.textContent = label; b.title = title; if (cls) b.className = cls;
51
+ b.onclick = function (e) { e.stopPropagation(); fn(); };
52
+ ctl.appendChild(b);
53
+ return b;
54
+ }
55
+ btn('◀', 'Previous step', '', function () { stop(vz); step(vz, -1); apply(vz, vz._k); });
56
+ vz._cnt = document.createElement('span'); vz._cnt.className = 'cnt'; ctl.appendChild(vz._cnt);
57
+ btn('▶', 'Next step', '', function () { stop(vz); step(vz, 1); apply(vz, vz._k); });
58
+ vz._play = btn('▶ Play', 'Play all steps', 'play', function () {
59
+ if (vz._timer) { stop(vz); apply(vz, vz._k); } else play(vz);
60
+ });
61
+ apply(vz, 0);
62
+ if (opts && opts.autoplay && 'IntersectionObserver' in window) {
63
+ var io = new IntersectionObserver(function (entries) {
64
+ if (entries[0].isIntersecting) { io.disconnect(); setTimeout(function () { if (vz._k === 0) play(vz); }, 700); }
65
+ }, { threshold: 0.6 });
66
+ io.observe(vz);
67
+ }
68
+ }
69
+ window.DBXViz = {
70
+ init: function (root, opts) {
71
+ (root || document).querySelectorAll('.vz[data-steps]').forEach(function (vz) { setup(vz, opts); });
72
+ },
73
+ step: function (vz, dir) { stop(vz); var ok = step(vz, dir); apply(vz, vz._k); return ok; },
74
+ pending: function (root, dir) {
75
+ var list = Array.prototype.slice.call(root.querySelectorAll('.vz[data-steps]'));
76
+ if (dir < 0) list.reverse();
77
+ for (var i = 0; i < list.length; i++) {
78
+ var vz = list[i];
79
+ if (vz._n && (dir > 0 ? vz._k < vz._n - 1 : vz._k > 0)) return vz;
80
+ }
81
+ return null;
82
+ }
83
+ };
84
+ })();