code-node-graph 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 (178) hide show
  1. code_node/__init__.py +40 -0
  2. code_node/__main__.py +7 -0
  3. code_node/analysis/__init__.py +3 -0
  4. code_node/analysis/aws_model.py +197 -0
  5. code_node/analysis/findings.py +462 -0
  6. code_node/analysis/graph.py +780 -0
  7. code_node/analysis/mapping.py +114 -0
  8. code_node/analysis/model.py +289 -0
  9. code_node/analysis/reader.py +1926 -0
  10. code_node/analysis/syntax.py +220 -0
  11. code_node/analysis/terms.py +505 -0
  12. code_node/cli.py +316 -0
  13. code_node/deploys/__init__.py +321 -0
  14. code_node/deploys/sam.py +371 -0
  15. code_node/deploys/serverless.py +117 -0
  16. code_node/kit/__init__.py +4 -0
  17. code_node/kit/blocks.py +184 -0
  18. code_node/kit/fmt.py +389 -0
  19. code_node/kit/highlight.py +131 -0
  20. code_node/kit/render.py +1066 -0
  21. code_node/kit/text.py +81 -0
  22. code_node/libraries/__init__.py +333 -0
  23. code_node/libraries/llm.py +124 -0
  24. code_node/libraries/mongo.py +169 -0
  25. code_node/libraries/redis.py +253 -0
  26. code_node/libraries/sql.py +232 -0
  27. code_node/pages.py +92 -0
  28. code_node/platforms/__init__.py +203 -0
  29. code_node/platforms/aws_lambda.py +290 -0
  30. code_node/platforms/web.py +301 -0
  31. code_node/project.py +402 -0
  32. code_node/report/__init__.py +3 -0
  33. code_node/report/brands.py +244 -0
  34. code_node/report/build.py +119 -0
  35. code_node/report/editor.py +40 -0
  36. code_node/report/graph.py +1411 -0
  37. code_node/report/logos/README.md +8 -0
  38. code_node/report/logos/anthropic-icon.svg +1 -0
  39. code_node/report/logos/aws-amplify.svg +1 -0
  40. code_node/report/logos/aws-api-gateway.svg +1 -0
  41. code_node/report/logos/aws-appflow.svg +1 -0
  42. code_node/report/logos/aws-appsync.svg +1 -0
  43. code_node/report/logos/aws-athena.svg +1 -0
  44. code_node/report/logos/aws-backup.svg +1 -0
  45. code_node/report/logos/aws-batch.svg +1 -0
  46. code_node/report/logos/aws-certificate-manager.svg +1 -0
  47. code_node/report/logos/aws-cloudformation.svg +1 -0
  48. code_node/report/logos/aws-cloudfront.svg +1 -0
  49. code_node/report/logos/aws-cloudtrail.svg +1 -0
  50. code_node/report/logos/aws-cloudwatch.svg +1 -0
  51. code_node/report/logos/aws-codebuild.svg +1 -0
  52. code_node/report/logos/aws-codecommit.svg +1 -0
  53. code_node/report/logos/aws-codedeploy.svg +1 -0
  54. code_node/report/logos/aws-codepipeline.svg +1 -0
  55. code_node/report/logos/aws-cognito.svg +1 -0
  56. code_node/report/logos/aws-config.svg +1 -0
  57. code_node/report/logos/aws-documentdb.svg +1 -0
  58. code_node/report/logos/aws-dynamodb.svg +1 -0
  59. code_node/report/logos/aws-ec2.svg +1 -0
  60. code_node/report/logos/aws-ecs.svg +1 -0
  61. code_node/report/logos/aws-eks.svg +1 -0
  62. code_node/report/logos/aws-elasticache.svg +1 -0
  63. code_node/report/logos/aws-elb.svg +1 -0
  64. code_node/report/logos/aws-eventbridge.svg +1 -0
  65. code_node/report/logos/aws-glacier.svg +1 -0
  66. code_node/report/logos/aws-glue.svg +1 -0
  67. code_node/report/logos/aws-iam.svg +1 -0
  68. code_node/report/logos/aws-keyspaces.svg +1 -0
  69. code_node/report/logos/aws-kinesis.svg +1 -0
  70. code_node/report/logos/aws-kms.svg +1 -0
  71. code_node/report/logos/aws-lake-formation.svg +1 -0
  72. code_node/report/logos/aws-lambda.svg +1 -0
  73. code_node/report/logos/aws-lightsail.svg +1 -0
  74. code_node/report/logos/aws-mq.svg +1 -0
  75. code_node/report/logos/aws-msk.svg +1 -0
  76. code_node/report/logos/aws-neptune.svg +1 -0
  77. code_node/report/logos/aws-open-search.svg +1 -0
  78. code_node/report/logos/aws-quicksight.svg +1 -0
  79. code_node/report/logos/aws-rds.svg +1 -0
  80. code_node/report/logos/aws-redshift.svg +1 -0
  81. code_node/report/logos/aws-route53.svg +1 -0
  82. code_node/report/logos/aws-s3.svg +1 -0
  83. code_node/report/logos/aws-secrets-manager.svg +1 -0
  84. code_node/report/logos/aws-ses.svg +1 -0
  85. code_node/report/logos/aws-shield.svg +1 -0
  86. code_node/report/logos/aws-sns.svg +1 -0
  87. code_node/report/logos/aws-sqs.svg +1 -0
  88. code_node/report/logos/aws-step-functions.svg +1 -0
  89. code_node/report/logos/aws-systems-manager.svg +1 -0
  90. code_node/report/logos/aws-timestream.svg +1 -0
  91. code_node/report/logos/aws-waf.svg +1 -0
  92. code_node/report/logos/aws-xray.svg +1 -0
  93. code_node/report/logos/aws.svg +1 -0
  94. code_node/report/logos/azure-icon.svg +1 -0
  95. code_node/report/logos/django-icon.svg +1 -0
  96. code_node/report/logos/elasticsearch.svg +1 -0
  97. code_node/report/logos/fastapi-icon.svg +1 -0
  98. code_node/report/logos/firebase-icon.svg +1 -0
  99. code_node/report/logos/flask.svg +1 -0
  100. code_node/report/logos/google-cloud.svg +1 -0
  101. code_node/report/logos/kafka-icon.svg +1 -0
  102. code_node/report/logos/mariadb-icon.svg +1 -0
  103. code_node/report/logos/mongodb-icon.svg +1 -0
  104. code_node/report/logos/mysql-icon.svg +1 -0
  105. code_node/report/logos/openai-icon.svg +1 -0
  106. code_node/report/logos/postgresql.svg +1 -0
  107. code_node/report/logos/python.svg +1 -0
  108. code_node/report/logos/rabbitmq-icon.svg +1 -0
  109. code_node/report/logos/redis.svg +1 -0
  110. code_node/report/logos/serverless.svg +1 -0
  111. code_node/report/logos/slack-icon.svg +1 -0
  112. code_node/report/logos/small/aws-api-gateway.svg +1 -0
  113. code_node/report/logos/small/aws-appflow.svg +1 -0
  114. code_node/report/logos/small/aws-appsync.svg +1 -0
  115. code_node/report/logos/small/aws-athena.svg +1 -0
  116. code_node/report/logos/small/aws-backup.svg +1 -0
  117. code_node/report/logos/small/aws-batch.svg +1 -0
  118. code_node/report/logos/small/aws-certificate-manager.svg +1 -0
  119. code_node/report/logos/small/aws-cloudformation.svg +1 -0
  120. code_node/report/logos/small/aws-cloudfront.svg +1 -0
  121. code_node/report/logos/small/aws-cloudtrail.svg +1 -0
  122. code_node/report/logos/small/aws-cloudwatch.svg +1 -0
  123. code_node/report/logos/small/aws-codebuild.svg +1 -0
  124. code_node/report/logos/small/aws-codecommit.svg +1 -0
  125. code_node/report/logos/small/aws-codedeploy.svg +1 -0
  126. code_node/report/logos/small/aws-codepipeline.svg +1 -0
  127. code_node/report/logos/small/aws-cognito.svg +1 -0
  128. code_node/report/logos/small/aws-config.svg +1 -0
  129. code_node/report/logos/small/aws-documentdb.svg +1 -0
  130. code_node/report/logos/small/aws-dynamodb.svg +1 -0
  131. code_node/report/logos/small/aws-ec2.svg +1 -0
  132. code_node/report/logos/small/aws-ecs.svg +1 -0
  133. code_node/report/logos/small/aws-eks.svg +1 -0
  134. code_node/report/logos/small/aws-elasticache.svg +1 -0
  135. code_node/report/logos/small/aws-elb.svg +1 -0
  136. code_node/report/logos/small/aws-eventbridge.svg +1 -0
  137. code_node/report/logos/small/aws-glacier.svg +1 -0
  138. code_node/report/logos/small/aws-glue.svg +1 -0
  139. code_node/report/logos/small/aws-iam.svg +1 -0
  140. code_node/report/logos/small/aws-keyspaces.svg +1 -0
  141. code_node/report/logos/small/aws-kinesis.svg +1 -0
  142. code_node/report/logos/small/aws-kms.svg +1 -0
  143. code_node/report/logos/small/aws-lake-formation.svg +1 -0
  144. code_node/report/logos/small/aws-lambda.svg +1 -0
  145. code_node/report/logos/small/aws-mq.svg +1 -0
  146. code_node/report/logos/small/aws-msk.svg +1 -0
  147. code_node/report/logos/small/aws-neptune.svg +1 -0
  148. code_node/report/logos/small/aws-open-search.svg +1 -0
  149. code_node/report/logos/small/aws-quicksight.svg +1 -0
  150. code_node/report/logos/small/aws-rds.svg +1 -0
  151. code_node/report/logos/small/aws-redshift.svg +1 -0
  152. code_node/report/logos/small/aws-route53.svg +1 -0
  153. code_node/report/logos/small/aws-s3.svg +1 -0
  154. code_node/report/logos/small/aws-secrets-manager.svg +1 -0
  155. code_node/report/logos/small/aws-ses.svg +1 -0
  156. code_node/report/logos/small/aws-shield.svg +1 -0
  157. code_node/report/logos/small/aws-sns.svg +1 -0
  158. code_node/report/logos/small/aws-sqs.svg +1 -0
  159. code_node/report/logos/small/aws-step-functions.svg +1 -0
  160. code_node/report/logos/small/aws-systems-manager.svg +1 -0
  161. code_node/report/logos/small/aws-timestream.svg +1 -0
  162. code_node/report/logos/small/aws-waf.svg +1 -0
  163. code_node/report/logos/small/aws-xray.svg +1 -0
  164. code_node/report/logos/snowflake-icon.svg +1 -0
  165. code_node/report/logos/sqlite.svg +1 -0
  166. code_node/report/logos/stripe.svg +1 -0
  167. code_node/report/logos/supabase-icon.svg +1 -0
  168. code_node/report/logos/twilio-icon.svg +1 -0
  169. code_node/report/outline.py +219 -0
  170. code_node/report/style.py +358 -0
  171. code_node/report/tabs.py +73 -0
  172. code_node/report/walk.py +624 -0
  173. code_node/serve.py +277 -0
  174. code_node_graph-0.1.0.dist-info/METADATA +165 -0
  175. code_node_graph-0.1.0.dist-info/RECORD +178 -0
  176. code_node_graph-0.1.0.dist-info/WHEEL +4 -0
  177. code_node_graph-0.1.0.dist-info/entry_points.txt +2 -0
  178. code_node_graph-0.1.0.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,358 @@
1
+ """
2
+ The look of code-node's pages: their CSS root class, stylesheet and badge.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import Any
8
+ from urllib.parse import quote
9
+
10
+ from ..kit.render import _base_css, _page_document, _report_html
11
+
12
+
13
+ # code-node's logo (docs/images/logo.svg): the tab icon of every page, and the served page's /favicon.ico
14
+ FAVICON_SVG = """\
15
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none">
16
+ <path d="M8 16C12 16 12 8 16.5 8" stroke="#60a5fa" stroke-width="2.2" stroke-linecap="round"/>
17
+ <path d="M8 16C12 16 12 24 16.5 24" stroke="#f472b6" stroke-width="2.2" stroke-linecap="round"/>
18
+ <path d="M19.5 8H24" stroke="#60a5fa" stroke-width="2.2" stroke-linecap="round" stroke-dasharray="0.1 3.2"/>
19
+ <path d="M19.5 24H24" stroke="#f472b6" stroke-width="2.2" stroke-linecap="round" stroke-dasharray="0.1 3.2"/>
20
+ <rect x="2.5" y="11.5" width="9" height="9" rx="2.6" fill="#9097a3"/>
21
+ <circle cx="18" cy="8" r="3.4" fill="#60a5fa"/>
22
+ <circle cx="18" cy="24" r="3.4" fill="#f472b6"/>
23
+ <circle cx="27" cy="16" r="2.6" fill="#fbbf24"/>
24
+ <path d="M21 9.5C24 11 25 13 25.5 14" stroke="#fbbf24" stroke-width="1.6" stroke-linecap="round"/>
25
+ </svg>
26
+ """
27
+
28
+ # inline, so a saved page has its icon too, with nothing beside it
29
+ FAVICON_LINK = f'<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,{quote(FAVICON_SVG)}">\n'
30
+
31
+ _ROOT = "cnd" # the class around each page's HTML: its stylesheet's rules are scoped to it
32
+
33
+ _EXTRA_CSS = """\
34
+ .cnd{--mono:"Cascadia Mono","Cascadia Code",ui-monospace,SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace}
35
+ .cnd code,.cnd table.t td.tree{font-family:var(--mono)}
36
+ .cnd .wire{display:grid;grid-template-columns:minmax(0,1fr) 26px minmax(0,.9fr) 26px minmax(0,1fr);align-items:center;margin:6px 0 10px;max-width:980px}
37
+ .cnd .wire .wc{display:flex;flex-direction:column;gap:6px;min-width:0}
38
+ .cnd .wire .wa{text-align:center;font-size:18px;opacity:.45}
39
+ .cnd .wire .wn{border:1px solid rgba(127,127,127,.3);border-radius:8px;padding:5px 10px;line-height:1.35;min-width:0}
40
+ .cnd .wire .wn.warn{border-color:rgba(245,158,11,.8);background:rgba(245,158,11,.08)}
41
+ .cnd .wire .wn.bad{border-color:rgba(239,68,68,.8);background:rgba(239,68,68,.08)}
42
+ .cnd .wire .wn.none{border-style:dashed;opacity:.7}
43
+ .cnd .wire .wk{display:block;font-size:10px;font-weight:650;letter-spacing:.05em;text-transform:uppercase;opacity:.6}
44
+ .cnd .wire .wn b{display:block;font-weight:600;overflow-wrap:anywhere}
45
+ .cnd .wire .wd{display:block;font-size:11.5px;opacity:.7;overflow-wrap:anywhere}
46
+ .cnd .wire .wf{border:1px solid rgba(234,88,12,.55);border-radius:10px;padding:10px 12px;background:rgba(234,88,12,.06);text-align:center}
47
+ .cnd .wire .wf .wl{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;border-radius:8px;margin-bottom:4px;color:#fff;font-weight:700;background:linear-gradient(135deg,#f97316,#ea580c)}
48
+ .cnd .wire .wf b{display:block;font-size:14px;overflow-wrap:anywhere}
49
+ .cnd .colbars{display:flex;align-items:flex-end;gap:2px;height:120px;padding:0 0 0 2px;position:relative;border-bottom:1px solid rgba(127,127,127,.35);max-width:980px}
50
+ .cnd .colbars i{flex:1 1 0;min-width:2px;max-width:34px;border-radius:2px 2px 0 0;background:rgba(59,130,246,.55);position:relative;display:flex;flex-direction:column;justify-content:flex-start}
51
+ .cnd .colbars i:hover{background:rgba(59,130,246,.8)}
52
+ .cnd .colbars i b{display:block;width:100%;border-radius:2px 2px 0 0;background:#ef4444}
53
+ .cnd .colbars.dim i{background:rgba(59,130,246,.22);justify-content:flex-end}
54
+ .cnd .colbars.dim i b{background:rgba(59,130,246,.75);border-radius:0}
55
+ .cnd .colbars .lim{position:absolute;left:0;right:0;border-top:1.5px dashed rgba(239,68,68,.7);pointer-events:none}
56
+ .cnd .colbars .lim span{position:absolute;right:0;top:-16px;font-size:10.5px;color:#ef4444;opacity:.85}
57
+ .cnd .colbars .top{position:absolute;left:4px;top:-2px;font-size:10.5px;opacity:.55;pointer-events:none}
58
+ .cnd .colx{display:flex;justify-content:space-between;font-size:10.5px;opacity:.55;margin:3px 0 10px;max-width:980px}
59
+ .cnd .pgw{display:flex;align-items:center;flex-wrap:wrap;gap:4px 12px;margin:8px 0 10px}
60
+ .cnd a.pgo{display:inline-block;padding:5px 16px;border:1px solid rgba(59,130,246,.5);border-radius:999px;color:#3b82f6;font-weight:600;font-size:13.5px;text-decoration:none}
61
+ .cnd a.pgo:hover{background:rgba(59,130,246,.1)}
62
+ .cnd .pgp{font-size:12px;opacity:.65;overflow-wrap:anywhere}
63
+ .cnd .flow{border:1px solid rgba(127,127,127,.25);border-radius:8px;padding:6px 10px 6px 4px;margin:4px 0 10px;max-width:1180px;max-height:760px;overflow:auto;font-size:12px}
64
+ .cnd .flow .ol{display:flex;align-items:baseline;flex-wrap:wrap;column-gap:8px;row-gap:2px;padding:1px 4px;border-radius:5px;line-height:1.55;min-width:0}
65
+ .cnd .flow .ol:hover{background:rgba(127,127,127,.08)}
66
+ .cnd .flow .ln{flex:0 0 30px;text-align:right;font:11px var(--mono);opacity:.45;user-select:none;-webkit-user-select:none}
67
+ .cnd .flow code.ocd{font:12px var(--mono);white-space:pre-wrap;overflow-wrap:anywhere;background:none;padding:0;min-width:0}
68
+ .cnd .flow .k-def>code.ocd{font-weight:600}
69
+ .cnd .flow .k-return>code.ocd,.cnd .flow .k-raise>code.ocd{font-weight:600}
70
+ .cnd .flow .ox{margin-left:38px;padding-left:10px;border-left:1px solid rgba(127,127,127,.28)}
71
+ .cnd :is(.flow,.walk) .nt{display:inline-block;font-size:10.5px;font-weight:600;line-height:1.6;padding:0 7px;border-radius:9px;white-space:nowrap;background:rgba(127,127,127,.14)}
72
+ .cnd :is(.flow,.walk) .nt i{font-style:normal;font-weight:500;opacity:.7;margin-left:4px}
73
+ .cnd :is(.flow,.walk) :is(.n-aws-reads,.n-lib-reads){background:rgba(59,130,246,.16);color:#2f6fdb}
74
+ .cnd :is(.flow,.walk) :is(.n-aws-writes,.n-lib-writes){background:rgba(234,88,12,.16);color:#d0570c}
75
+ .cnd :is(.flow,.walk) :is(.n-aws-sends,.n-lib-sends){background:rgba(219,39,119,.14);color:#c42a73}
76
+ .cnd :is(.flow,.walk) :is(.n-aws-runs,.n-lib-runs){background:rgba(147,51,234,.15);color:#8b3fd9}
77
+ .cnd :is(.flow,.walk) .n-aws-signs{background:rgba(100,116,139,.18)}
78
+ .cnd :is(.flow,.walk) .n-env{background:rgba(13,148,136,.16);color:#0f8a7e}
79
+ .cnd :is(.flow,.walk) .n-event{background:rgba(22,163,74,.15);color:#178a45}
80
+ .cnd :is(.flow,.walk) .n-http{background:rgba(219,39,119,.14);color:#c42a73}
81
+ .cnd :is(.flow,.walk) .n-client{background:rgba(59,130,246,.08);color:#2f6fdb}
82
+ .cnd :is(.flow,.walk) .n-warn,.cnd :is(.flow,.walk) .n-sleep{background:rgba(245,158,11,.2);color:#b86e04}
83
+ .cnd :is(.flow,.walk) .n-route{background:rgba(147,51,234,.15);color:#8b3fd9}
84
+ .cnd :is(.flow,.walk) .n-log,.cnd :is(.flow,.walk) .n-file,.cnd :is(.flow,.walk) .n-command,.cnd :is(.flow,.walk) .n-more{font-weight:500;opacity:.85}
85
+ .cnd .flow details.od{margin:0}
86
+ .cnd .flow details.od>summary{list-style:none;cursor:pointer}
87
+ .cnd .flow details.od>summary::-webkit-details-marker{display:none}
88
+ .cnd .flow .on{white-space:nowrap}
89
+ .cnd .flow .on b{font:600 12px var(--mono)}
90
+ .cnd .flow .och{display:inline-block;width:6px;height:6px;margin:0 7px 2px 1px;border-right:1.6px solid currentColor;border-bottom:1.6px solid currentColor;transform:rotate(-45deg);opacity:.6;transition:transform .15s}
91
+ .cnd .flow details.od[open]>summary .och{transform:rotate(45deg);margin-bottom:4px}
92
+ .cnd .flow details.od[open]>summary .os{display:none}
93
+ .cnd .flow .oseen .on{padding-left:15px}
94
+ .cnd .flow .of,.cnd .flow .oq{font-size:11px;opacity:.6}
95
+ .cnd .flow .oq{font-style:italic}
96
+ .cnd .flow .os{display:inline-flex;flex-wrap:wrap;gap:3px 5px}
97
+ .cnd .flow .ob{margin-left:22px}
98
+ .cnd :is(.flow,.cside,.walk) .pk{color:var(--jp-mirror-editor-keyword-color,light-dark(#7c3aed,#c792ea))}
99
+ .cnd :is(.flow,.cside,.walk) .pf{color:var(--jp-mirror-editor-def-color,light-dark(#2563eb,#82aaff))}
100
+ .cnd :is(.flow,.cside,.walk) :is(.js,.jk){color:var(--jp-mirror-editor-string-color,light-dark(#047857,#a5d6a7))}
101
+ .cnd :is(.flow,.cside,.walk) :is(.jn,.jl){color:var(--jp-mirror-editor-number-color,light-dark(#c2410c,#f78c6c))}
102
+ .cnd :is(.flow,.cside,.walk) .pa{font-style:italic}
103
+ .cnd :is(.flow,.cside,.walk) .pc{opacity:.6;font-style:italic}
104
+ .cnd .cgb{width:fit-content;max-width:min(100%,1180px)}
105
+ .cnd .cg{border:1px solid rgba(127,127,127,.2);border-radius:14px;margin:6px 0 8px;overflow:auto;background-color:rgba(127,127,127,.035);background-attachment:local;background-size:18px 18px;
106
+ background-image:radial-gradient(circle at 1px 1px,rgba(127,127,127,.3) 1px,transparent 0);background-position:9px 9px}
107
+ .cnd .cg svg{display:block;width:calc(var(--w)*var(--z,1));max-width:none;height:auto;overflow:visible;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif}
108
+ .cnd .cgw{position:relative}
109
+ .cnd .cgw>.cgs{position:absolute;left:0;top:0;width:1px;height:1px;margin:0;opacity:0;pointer-events:none}
110
+ .cnd .cgt{display:flex;align-items:center;justify-content:flex-end;flex-wrap:wrap;gap:8px;margin:0 0 6px;font-size:12px;user-select:none;-webkit-user-select:none}
111
+ .cnd .cgtz{display:inline-flex;border:1px solid rgba(127,127,127,.28);border-radius:8px;overflow:hidden}
112
+ .cnd .cgtz label{padding:3px 10px;cursor:pointer;opacity:.6;font-variant-numeric:tabular-nums}
113
+ .cnd .cgtz label+label{border-left:1px solid rgba(127,127,127,.2)}
114
+ .cnd .cgt label:hover{opacity:.95;background:rgba(127,127,127,.08)}
115
+ .cnd .cgtf{padding:3px 10px;border:1px solid rgba(127,127,127,.28);border-radius:8px;cursor:pointer;opacity:.7}
116
+ .cnd .cgtf .off,.cnd .cgfs:checked~.cgb .cgtf .on{display:none}
117
+ .cnd .cgfs:checked~.cgb .cgtf .off{display:inline}
118
+ .cnd .cgz-auto:checked~.cgb .zl-auto,.cnd .cgz-fit:checked~.cgb .zl-fit,.cnd .cgz-100:checked~.cgb .zl-100,.cnd .cgz-150:checked~.cgb .zl-150{opacity:1;font-weight:650;background:rgba(127,127,127,.14)}
119
+ .cnd .cgz-auto:focus-visible~.cgb .zl-auto,.cnd .cgz-fit:focus-visible~.cgb .zl-fit,.cnd .cgz-100:focus-visible~.cgb .zl-100,.cnd .cgz-150:focus-visible~.cgb .zl-150,.cnd .cgfs:focus-visible~.cgb .cgtf{outline:2px solid light-dark(#2563eb,#60a5fa);outline-offset:-2px}
120
+ .cnd .cgz-150:checked~.cgb{--z:1.5}
121
+ .cnd .cgz-auto:checked~.cgb .cg svg{width:var(--w);max-width:100%;min-width:calc(var(--w)*.8)}
122
+ .cnd .cgz-fit:checked~.cgb .cg svg{width:var(--w);max-width:100%}
123
+ .cnd .cgfs:checked~.cgb{position:fixed;inset:0;z-index:25;width:auto;max-width:none;display:flex;flex-direction:column;box-sizing:border-box;padding:12px clamp(12px,2vw,28px) 4px;background:var(--jp-layout-color0,var(--vscode-editor-background,Canvas))}
124
+ .cnd .cgfs:checked~.cgb .cg{flex:1;min-height:0;margin:0 0 8px}
125
+ .cnd .cgfs:checked~.cgz-fit:checked~.cgb .cg svg{width:100%;height:100%;max-width:none}
126
+ .cnd .cgfs:checked~.cgz-auto:checked~.cgb .cg svg{min-width:0}
127
+ @media (min-width:1100px){.cnd .cgw:has(.cside:target) .cgfs:checked~.cgb{right:min(660px,94vw)}}
128
+ .cnd .cg .cap{font-size:12px;font-weight:650;letter-spacing:1.2px;fill:currentColor;fill-opacity:.6}
129
+ .cnd .cg .capl{stroke:currentColor;stroke-opacity:.14;stroke-width:1;fill:none}
130
+ .cnd .cg .cn,.cnd .cg .ce{transition:opacity .15s}
131
+ .cnd .cg .cn .bg{fill:var(--jp-layout-color0,var(--vscode-editor-background,Canvas));stroke:none;filter:drop-shadow(0 1px 1.5px rgba(0,0,0,.07)) drop-shadow(0 6px 16px rgba(15,23,42,.07))}
132
+ .cnd .cg .cn .fg{fill:rgba(255,255,255,.05);stroke:rgba(127,127,127,.32);stroke-width:1}
133
+ .cnd .cg .cn:hover .fg{stroke:rgba(127,127,127,.6)}
134
+ .cnd .cg .cn text{fill:currentColor}
135
+ .cnd .cg .cn .lb{font-size:14px;font-weight:650;letter-spacing:-.1px}
136
+ .cnd .cg .k-handler .lb,.cnd .cg .k-function .lb{font-family:var(--mono);font-size:13.5px;font-weight:650;letter-spacing:0}
137
+ .cnd .cg .k-handler .lb{font-size:14px;font-weight:700}
138
+ .cnd .cg .cn .sb{font-size:12.5px;fill-opacity:.62}
139
+ .cnd .cg .cn .sb .dir{fill-opacity:.4}
140
+ .cnd .cg .cn .sb .ac{font-weight:600;fill-opacity:.95}
141
+ .cnd .cg .cn .sb .sep{fill-opacity:.4}
142
+ .cnd .cg .cn .dv{stroke:rgba(127,127,127,.2);stroke-width:1;fill:none}
143
+ .cnd .cg .cn .rw{font:12.5px var(--mono);fill-opacity:.88}
144
+ .cnd .cg .cn .rw.mo{font-family:inherit;font-style:italic;fill-opacity:.55}
145
+ .cnd .cg .cn .pr{font-size:12.5px;fill-opacity:.7}
146
+ .cnd .cg .cn .pr.mo{font-style:italic;fill-opacity:.5}
147
+ .cnd .cg .cn .ns{font-size:12px;font-weight:650;fill:light-dark(#b45309,#fbbf24);letter-spacing:.2px}
148
+ .cnd .cg .cn .bu{fill:var(--c,rgba(127,127,127,.6))}
149
+ .cnd .cg .cn .bdg{fill:var(--t,rgba(127,127,127,.12));stroke:var(--c,rgba(127,127,127,.5));stroke-opacity:.22;stroke-width:1}
150
+ .cnd .cg .cn .ico{fill:none;stroke:var(--c,currentColor);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
151
+ .cnd .cg .k-event{--c:#16a34a;--t:rgba(22,163,74,.12)}
152
+ .cnd .cg .k-env{--c:#0d9488;--t:rgba(13,148,136,.13)}
153
+ .cnd .cg .k-aws{--c:#3b82f6;--t:rgba(59,130,246,.12)}
154
+ .cnd .cg .k-http{--c:#db2777;--t:rgba(219,39,119,.11)}
155
+ .cnd .cg .k-service{--c:#0891b2;--t:rgba(8,145,178,.12)}
156
+ .cnd .cg .cn .bdg.lg{fill:#fff;stroke:rgba(127,127,127,.35);stroke-opacity:1}
157
+ .cnd .cg .logo{color:#1b1d22}
158
+ .cnd .cg .logo.lgf{display:none}
159
+ @media (min-resolution:2dppx){.cnd .cg .logo.lgs{display:none}.cnd .cg .logo.lgf{display:inline}}
160
+ .cnd .cg .k-start{--c:#64748b;--t:rgba(100,116,139,.13)}
161
+ .cnd .cg .k-function{--c:currentColor;--t:rgba(127,127,127,.12)}
162
+ .cnd .cg .k-function .ico{stroke-opacity:.72}
163
+ .cnd .cg :is(.k-aws,.k-service,.k-http) .bu{fill:rgba(127,127,127,.55)}
164
+ .cnd .cg .k-start .fg{stroke-dasharray:5 4;stroke:rgba(127,127,127,.55);fill:rgba(127,127,127,.04)}
165
+ .cnd .cg .k-start .bg{filter:none}
166
+ .cnd .cg .k-handler .bg{filter:drop-shadow(0 1px 2px rgba(0,0,0,.1)) drop-shadow(0 10px 24px rgba(15,23,42,.12))}
167
+ .cnd .cg .k-handler .fg{stroke:currentColor;stroke-opacity:.6;stroke-width:1.5}
168
+ .cnd .cg .k-handler .bdg{fill:currentColor;stroke:none}
169
+ .cnd .cg .k-handler .ico{stroke:var(--jp-layout-color0,var(--vscode-editor-background,Canvas));stroke-width:1.7}
170
+ .cnd .cg .cn.warn .fg{stroke:#f59e0b;stroke-opacity:1;stroke-width:1.5;fill:rgba(245,158,11,.06)}
171
+ .cnd .cg .wb circle,.cnd .cg .wm circle{fill:#f59e0b;stroke:var(--jp-layout-color0,var(--vscode-editor-background,Canvas));stroke-width:1.5}
172
+ .cnd .cg .wb path,.cnd .cg .wm path{stroke:var(--jp-layout-color0,var(--vscode-editor-background,Canvas));stroke-width:2;stroke-linecap:round;fill:none}
173
+ .cnd .cg .rt rect{fill:rgba(127,127,127,.1);stroke:rgba(127,127,127,.22)}
174
+ .cnd .cg .rt text{font:12.5px var(--mono);fill-opacity:.85}
175
+ .cnd .cg .rt .mt{font-weight:700;fill-opacity:1}
176
+ .cnd .cg .wh rect{fill:none;stroke-dasharray:3 3}
177
+ .cnd .cg .wh .ww{font-weight:600;fill-opacity:.55}
178
+ .cnd .cg .ce path{fill:none}
179
+ .cnd .cg .ce .ln{stroke:var(--c);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
180
+ .cnd .cg .ce .ah{fill:var(--c);stroke:var(--c);stroke-width:.6;stroke-linejoin:round}
181
+ .cnd .cg .ce .hit{stroke:transparent;stroke-width:12}
182
+ .cnd .cg .ce .halo{stroke:#f59e0b;stroke-opacity:.75;stroke-width:7;stroke-linecap:round;stroke-linejoin:round}
183
+ .cnd .cg .ce .cs{stroke:var(--jp-layout-color0,var(--vscode-editor-background,Canvas));stroke-width:3.4;stroke-linecap:round;stroke-linejoin:round}
184
+ .cnd .cg .ce:hover .ln{stroke-width:2.6}
185
+ .cnd .cg .ce.pt circle{fill:var(--jp-layout-color0,var(--vscode-editor-background,Canvas));stroke:var(--c);stroke-width:1.6}
186
+ .cnd .cg .ce .lpb circle{fill:var(--jp-layout-color0,var(--vscode-editor-background,Canvas));stroke:var(--c);stroke-width:1.3}
187
+ .cnd .cg .ce .lpb path{fill:none;stroke:var(--c);stroke-width:2.1;stroke-linecap:round;stroke-linejoin:round}
188
+ .cnd .cg .ek-call,.cnd .cgk .ek-call,.cnd .cgk .ek-guess,.cnd .cgk .ek-via{--c:rgba(127,127,127,.95)}
189
+ .cnd .cg .ek-event{--c:#16a34a}
190
+ .cnd .cg .ek-event .ln{stroke-width:2.2}
191
+ .cnd .cg .ek-env,.cnd .cgk .ek-env{--c:#0d9488}
192
+ .cnd .cg :is(.ek-env,.ek-client) .ln{stroke-opacity:.6}
193
+ .cnd .cg .ek-env .ln,.cnd .cgk .ek-env .ln{stroke-dasharray:5 4}
194
+ .cnd .cg .ek-client,.cnd .cgk .ek-client{--c:rgba(100,116,139,.85)}
195
+ .cnd .cg .ek-client .ln,.cnd .cgk .ek-client .ln{stroke-dasharray:.5 4.5;stroke-width:2}
196
+ .cnd .cg .ek-reads,.cnd .cgk .ek-reads{--c:#3b82f6}
197
+ .cnd .cg .ek-writes,.cnd .cgk .ek-writes{--c:#ea580c}
198
+ .cnd .cg .ek-sends,.cnd .cg .ek-http,.cnd .cgk .ek-sends,.cnd .cgk .ek-http{--c:#db2777}
199
+ .cnd .cg .ek-runs,.cnd .cgk .ek-runs{--c:#9333ea}
200
+ .cnd .cg .ek-signs,.cnd .cgk .ek-signs{--c:rgba(100,116,139,.9)}
201
+ .cnd .cg .ek-signs .ln,.cnd .cgk .ek-signs .ln{stroke-dasharray:6 3}
202
+ .cnd .cg .ek-http .ln,.cnd .cgk .ek-http .ln{stroke-dasharray:8 3}
203
+ .cnd .cg .ce.guess .ln,.cnd .cgk .ek-guess .ln{stroke-dasharray:3 2.5;stroke-linecap:butt}
204
+ .cnd .cg .ce.via .ln,.cnd .cgk .ek-via .ln{stroke-dasharray:9 3 2 3}
205
+ .cnd .cg .cn .ac{fill:var(--c)}
206
+ .cnd .cg .cn .sb .ek-reads{fill:light-dark(#2563eb,#60a5fa)}.cnd .cg .cn .sb .ek-writes{fill:light-dark(#c2410c,#fb923c)}
207
+ .cnd .cg .cn .sb .ek-sends{fill:light-dark(#be185d,#f472b6)}.cnd .cg .cn .sb .ek-runs{fill:light-dark(#7e22ce,#c084fc)}
208
+ .cnd .cg .cn .sb .ek-signs{fill:light-dark(#475569,#94a3b8)}
209
+ .cnd .cg .cn .bu.flagged{fill:#f59e0b}
210
+ .cnd .cgk{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:0 0 12px;width:0;min-width:100%;font-size:12px}
211
+ .cnd .cgk .kp{display:inline-flex;align-items:center;gap:6px;padding:3px 10px 3px 8px;border:1px solid rgba(127,127,127,.25);border-radius:999px;background:rgba(127,127,127,.05);line-height:16px;white-space:nowrap}
212
+ .cnd .cgk .kp b{font-weight:650;margin-right:3px}
213
+ .cnd .cgk .kh{border-style:dashed;white-space:normal}
214
+ .cnd .cgk .kt{opacity:.55;margin-left:auto;padding:3px 2px}
215
+ .cnd .cgk .sw{display:block;overflow:visible;flex:none}
216
+ .cnd .cgk .sw .ln{fill:none;stroke:var(--c);stroke-width:1.8;stroke-linecap:round}
217
+ .cnd .cgk .sw .ah{fill:var(--c);stroke:var(--c);stroke-width:.6;stroke-linejoin:round}
218
+ .cnd .cgk .kw circle{fill:#f59e0b}
219
+ .cnd .cgk .kw path{stroke:var(--jp-layout-color0,var(--vscode-editor-background,Canvas));stroke-width:1.8;stroke-linecap:round;fill:none}
220
+ .cnd .cgk .kl circle{fill:none;stroke:currentColor;stroke-opacity:.55;stroke-width:1.2}
221
+ .cnd .cgk .kl path{fill:none;stroke:currentColor;stroke-opacity:.8;stroke-width:2.1;stroke-linecap:round;stroke-linejoin:round}
222
+ .cnd .cg a.cl{cursor:pointer;outline:none}
223
+ .cnd .cg a.cl:focus-visible .fg{stroke:light-dark(#2563eb,#60a5fa);stroke-opacity:1;stroke-width:2}
224
+ .cnd .cside{position:fixed;top:0;right:0;bottom:0;z-index:30;box-sizing:border-box;width:min(660px,94vw);overflow:auto;padding:0 20px 28px;background:var(--jp-layout-color0,var(--vscode-editor-background,Canvas));color:CanvasText;border-left:1px solid rgba(127,127,127,.3);box-shadow:-14px 0 36px rgba(15,23,42,.14);transform:translateX(104%);visibility:hidden;transition:transform .22s ease,visibility 0s linear .22s}
225
+ .cnd .cside:target{transform:none;visibility:visible;transition:transform .22s ease}
226
+ .cnd .cside .csh{display:flex;align-items:flex-start;gap:12px;position:sticky;top:0;z-index:1;margin:0 -20px 12px;padding:16px 20px 12px;background:var(--jp-layout-color0,var(--vscode-editor-background,Canvas));border-bottom:1px solid rgba(127,127,127,.2)}
227
+ .cnd .cside .cst{flex:1;min-width:0}
228
+ .cnd .cside .csk{display:block;font-size:11px;font-weight:650;letter-spacing:.08em;text-transform:uppercase;opacity:.55}
229
+ .cnd .cside .csn{display:block;font-size:17px;font-weight:650;overflow-wrap:anywhere;margin:2px 0 1px}
230
+ .cnd .cside .csn.mono{font:650 16px var(--mono)}
231
+ .cnd .cside .css{font-size:12.5px;opacity:.65;overflow-wrap:anywhere}
232
+ .cnd .cside a.csx{flex:none;display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:8px;font-size:22px;line-height:1;color:inherit;text-decoration:none;opacity:.6}
233
+ .cnd .cside a.csx:hover,.cnd .cside a.csx:focus-visible{opacity:1;background:rgba(127,127,127,.14)}
234
+ .cnd .cside .csd{font-size:13px;line-height:1.5;margin:0 0 6px;opacity:.82;overflow-wrap:anywhere}
235
+ .cnd .cside .csl{font-size:12px;opacity:.6}
236
+ .cnd .cside .csw{font:12px var(--mono);margin:16px 0 5px;overflow-wrap:anywhere}
237
+ .cnd .cside .csw span{opacity:.55}
238
+ .cnd .cside .ced{margin-left:6px;font-family:inherit;color:light-dark(#2563eb,#60a5fa);text-decoration:none}
239
+ .cnd .cside .ced:hover{text-decoration:underline}
240
+ .cnd .cside pre.csc{margin:0;padding:8px 0;border:1px solid rgba(127,127,127,.22);border-radius:8px;overflow:auto;background:rgba(127,127,127,.04);font:12.5px/1.6 var(--mono)}
241
+ .cnd .cside .sl{display:block;width:max-content;min-width:100%;box-sizing:border-box;padding-right:14px;white-space:pre}
242
+ .cnd .cside .sl.lit{background:rgba(245,158,11,.16);box-shadow:inset 3px 0 #f59e0b}
243
+ .cnd .cside .sn{display:inline-block;width:3.2em;padding-right:14px;text-align:right;opacity:.42;user-select:none;-webkit-user-select:none}
244
+ .cnd .cside .csm{font-size:12px;font-style:italic;opacity:.6;margin:6px 2px 0}
245
+ @media (min-width:1100px){.cnd .cgw:has(.cside:target){margin-right:min(660px,94vw)}}
246
+ @media (prefers-reduced-motion:reduce){.cnd .cside,.cnd .cside:target{transition:none}}
247
+ .cnd .tabs{position:relative;margin:0 0 8px}
248
+ .cnd .tbar{position:sticky;top:0;z-index:20;display:flex;flex-wrap:wrap;align-items:flex-end;gap:2px;padding-top:6px;margin:0 0 18px;border-bottom:1px solid rgba(127,127,127,.22);background:var(--jp-layout-color0,var(--vscode-editor-background,Canvas))}
249
+ .cnd .tabs>.tr{position:absolute;left:0;top:0;width:1px;height:1px;margin:0;opacity:0;pointer-events:none}
250
+ .cnd .tbar .tl{padding:9px 14px 10px;margin-bottom:-1px;border-bottom:2px solid transparent;font-size:14px;font-weight:600;cursor:pointer;opacity:.55;user-select:none;-webkit-user-select:none;transition:opacity .15s,border-color .15s}
251
+ .cnd .tbar .tl:first-of-type{padding-left:2px}
252
+ .cnd .tbar .tl small{margin-left:7px;font-size:12px;font-weight:450;opacity:.7;font-variant-numeric:tabular-nums}
253
+ .cnd .tbar .tl:hover{opacity:.85}
254
+ .cnd .tbar .tcap{display:flex;align-items:baseline;flex-wrap:wrap;justify-content:flex-end;gap:2px 10px;margin-left:auto;padding:0 2px 11px;min-width:0}
255
+ .cnd .tbar .tcap code{font:600 12.5px var(--mono);background:none;padding:0;overflow-wrap:anywhere}
256
+ .cnd .tbar .tcap small{font-size:12px;opacity:.55}
257
+ .cnd .tabs>.tp{display:none;animation:cnd-in .2s ease}
258
+ .cnd .tabs>.tp>h4{margin:30px 0 8px;font-size:14px;font-weight:600}
259
+ .cnd .tabs>.tp>h4:first-child{margin-top:2px}
260
+ .cnd .tabs>.tp details.sec{margin:14px 0 4px}
261
+ .cnd .tabs>.tp details.sec>summary{font-size:13px;font-weight:550;opacity:.7}
262
+ .cnd .tabs>.tp details.sec>summary:hover,.cnd .tabs>.tp details.sec[open]>summary{opacity:1}
263
+ .cnd .tabs>.tp .note{border-radius:0 8px 8px 0;padding:10px 14px;max-width:1000px}
264
+ .cnd .tfoot{max-width:900px;margin:36px 0 0;padding-top:14px;border-top:1px solid rgba(127,127,127,.15);font-size:12px;line-height:1.55;opacity:.55}
265
+ @keyframes cnd-in{from{opacity:0;transform:translateY(4px)}}
266
+ .cnd .wsub{font-size:13px;line-height:1.5;opacity:.7;margin:-2px 0 10px;max-width:900px}
267
+ .cnd .wsub kbd{display:inline-block;min-width:14px;padding:0 3px;border:1px solid rgba(127,127,127,.4);border-bottom-width:2px;border-radius:4px;font:10.5px/14px var(--mono);text-align:center}
268
+ .cnd .walk{--lw:38%;--ch:240px;--lh:21px;--pad:12px;--bg:var(--jp-layout-color0,var(--vscode-editor-background,Canvas));--blue:light-dark(#2563eb,#60a5fa);position:relative;display:grid;grid-template-columns:var(--lw) minmax(0,1fr);min-height:580px;margin:4px 0 10px;border:1px solid rgba(127,127,127,.25);border-radius:12px;overflow:hidden;font-size:13px}
269
+ .cnd .walk .wl{min-height:0;max-height:clamp(580px,calc(100vh - 110px),1000px);box-sizing:border-box;overflow:auto;padding:0 0 48px;overscroll-behavior:contain;scroll-padding:48px 0 72px}
270
+ .cnd .walk .ws{border-left:1px solid rgba(127,127,127,.2)}
271
+ .cnd .walk .wch{position:sticky;top:0;z-index:2;padding:12px 16px 9px;font-size:12.5px;font-weight:650;background:var(--bg);border-bottom:1px solid rgba(127,127,127,.14)}
272
+ .cnd .walk .wr{display:block;width:0;height:0;margin:0;border:0;padding:0;opacity:0;appearance:none;-webkit-appearance:none;pointer-events:none}
273
+ .cnd .walk .wil{display:flex;align-items:center;gap:10px;min-height:30px;padding:0 14px 0 4px;cursor:pointer;white-space:nowrap;user-select:none;-webkit-user-select:none;transition:background-color .15s}
274
+ .cnd .walk .wil:hover{background-color:rgba(127,127,127,.08)}
275
+ .cnd .walk .wr:checked+.wil{background-color:rgba(245,158,11,.16);box-shadow:inset 3px 0 #f59e0b}
276
+ .cnd .walk .wr:focus-visible+.wil{outline:2px solid var(--blue);outline-offset:-2px}
277
+ .cnd .walk .wno{flex:0 0 26px;text-align:right;font:11px var(--mono);opacity:.4;font-variant-numeric:tabular-nums}
278
+ .cnd .walk .wr:checked+.wil .wno{opacity:.8}
279
+ .cnd .walk .wx{display:flex;align-items:center;align-self:stretch;gap:8px;min-width:0;flex:1;padding-left:calc(var(--d)*16px);background:repeating-linear-gradient(90deg,rgba(127,127,127,.18) 0 1px,transparent 1px 16px) 5px 0/calc(var(--d)*16px) 100% no-repeat}
280
+ .cnd .walk .wtx{min-width:0;overflow:hidden;text-overflow:ellipsis}
281
+ .cnd .walk .wtx code{font:12px var(--mono);background:none;padding:0}
282
+ .cnd .walk :is(.k-def,.k-module) .wtx b{font:650 12.5px var(--mono)}
283
+ .cnd .walk :is(.k-def,.k-module) .wof{margin-left:8px;font-size:11.5px;opacity:.55}
284
+ .cnd .walk .wdot{flex:none;width:8px;height:8px;border-radius:50%;background:var(--c,rgba(127,127,127,.6))}
285
+ .cnd .walk :is(.d-aws-reads,.d-lib-reads){--c:#3b82f6}.cnd .walk :is(.d-aws-writes,.d-lib-writes){--c:#ea580c}
286
+ .cnd .walk :is(.d-aws-sends,.d-lib-sends,.d-http){--c:#db2777}.cnd .walk :is(.d-aws-runs,.d-lib-runs){--c:#9333ea}.cnd .walk .d-aws-signs{--c:#64748b}
287
+ .cnd .walk .wc{display:none;position:absolute;left:var(--lw);right:0;top:0;height:var(--ch);box-sizing:border-box;overflow:auto;padding:14px 22px 12px;white-space:normal;cursor:auto;border-left:1px solid rgba(127,127,127,.2);border-bottom:1px solid rgba(127,127,127,.18);background:var(--bg);animation:cnd-in .18s ease}
288
+ .cnd .walk .wr:checked+.wil+.wc{display:block}
289
+ .cnd .walk .wnav{display:flex;flex-wrap:wrap;align-items:center;gap:8px}
290
+ .cnd .walk .wbt{display:inline-flex;align-items:center;gap:5px;padding:4px 14px;border:1px solid rgba(127,127,127,.32);border-radius:8px;font-size:13px;font-weight:600;line-height:20px;cursor:pointer;user-select:none;-webkit-user-select:none;transition:background-color .12s,transform .06s}
291
+ .cnd .walk .wbt code{font:600 12px var(--mono);background:none;padding:0;max-width:16em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
292
+ .cnd .walk label.wbt:hover{background:rgba(127,127,127,.12)}
293
+ .cnd .walk label.wbt:active{transform:translateY(1px)}
294
+ .cnd .walk .wbt.go{color:var(--bg);background:var(--blue);border-color:var(--blue)}
295
+ .cnd .walk label.wbt.go:hover{background:var(--blue);filter:brightness(1.1)}
296
+ .cnd .walk .wbt.off{opacity:.35;cursor:default}
297
+ .cnd .walk .wbt.go.off{color:inherit;background:none;border-color:rgba(127,127,127,.32)}
298
+ .cnd .walk .wpos{font-size:12.5px;opacity:.65;padding:0 4px;font-variant-numeric:tabular-nums}
299
+ .cnd .walk .wgap{flex:1}
300
+ .cnd .walk .whead{margin:16px 0 4px;font-size:17px;font-weight:650;line-height:1.35;overflow-wrap:anywhere}
301
+ .cnd .walk .whead code{font:600 15px var(--mono);background:rgba(127,127,127,.12);padding:1px 5px;border-radius:5px}
302
+ .cnd .walk .wstk{display:flex;flex-wrap:wrap;align-items:center;gap:2px 4px;font-size:12.5px}
303
+ .cnd .walk .wstk .win{opacity:.55;margin-right:2px}
304
+ .cnd .walk .wstk label{font-family:var(--mono);font-size:12px;cursor:pointer;user-select:none;-webkit-user-select:none;opacity:.7;border-radius:4px;padding:0 3px}
305
+ .cnd .walk .wstk label:hover{opacity:1;background:rgba(127,127,127,.12)}
306
+ .cnd .walk .wstk label.here{opacity:1;font-weight:650}
307
+ .cnd .walk .wsep{opacity:.35}
308
+ .cnd .walk :is(.wed,.wln){margin-left:auto;padding-left:12px;font-size:12px;font-variant-numeric:tabular-nums}
309
+ .cnd .walk .wln{opacity:.55}
310
+ .cnd .walk .wed{color:var(--blue);text-decoration:none}
311
+ .cnd .walk .wed:hover{text-decoration:underline}
312
+ .cnd .walk .wsay{margin-top:10px;font-size:13.5px;line-height:1.55}
313
+ .cnd .walk .wsay p{margin:4px 0 0;opacity:.85}
314
+ .cnd .walk .wsay code{font-size:12.5px}
315
+ .cnd .walk .wdoc{font-style:italic;opacity:.7}
316
+ .cnd .walk .wjump{user-select:none;-webkit-user-select:none;color:var(--blue);cursor:pointer;text-decoration:underline;text-underline-offset:2px}
317
+ .cnd .walk .wfacts{list-style:none;margin:10px 0 0;padding:10px 0 0;border-top:1px solid rgba(127,127,127,.14);display:flex;flex-direction:column;gap:5px}
318
+ .cnd .walk .wfacts li{display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 8px;font-size:12.5px;overflow-wrap:anywhere}
319
+ .cnd .walk .wfacts code{font:12.5px var(--mono)}
320
+ .cnd .walk :is(.wfm,.wfv){opacity:.6}
321
+ .cnd .walk .wthen{margin-top:10px;font-size:12px;opacity:.6}
322
+ .cnd .walk .wf{display:none;position:absolute;left:var(--lw);right:0;top:var(--ch);bottom:0;flex-direction:column;border-left:1px solid rgba(127,127,127,.2);background:var(--bg)}
323
+ .cnd .walk .wfn>.wr:checked~.wf{display:flex}
324
+ .cnd .walk .wfh{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 10px;padding:8px 22px;font-size:12px;border-bottom:1px solid rgba(127,127,127,.12)}
325
+ .cnd .walk .wfh b{font:650 12.5px var(--mono)}
326
+ .cnd .walk .wfh span{opacity:.62}
327
+ .cnd .walk .wfh .wfl{margin-left:auto;opacity:.5}
328
+ .cnd .walk .wfw{position:relative;flex:1;min-height:0;overflow-x:auto;overflow-y:hidden;container-type:size;background:rgba(127,127,127,.03)}
329
+ .cnd .walk .wfp{position:relative;box-sizing:border-box;width:max-content;min-width:100%;padding:var(--pad) 0;font:12.5px/var(--lh) var(--mono);
330
+ translate:0 min(0px,max(calc(100cqh - var(--n)*var(--lh) - 2*var(--pad)),calc(36cqh - var(--k,0)*var(--lh))));transition:translate .32s cubic-bezier(.25,.8,.25,1)}
331
+ .cnd .walk .wbar{position:absolute;left:0;right:0;top:calc(var(--pad) + var(--k,-9)*var(--lh));height:var(--lh);background:rgba(245,158,11,.2);box-shadow:inset 3px 0 #f59e0b;transition:top .32s cubic-bezier(.25,.8,.25,1)}
332
+ .cnd .walk .sl{position:relative;display:block;padding-right:16px;white-space:pre}
333
+ .cnd .walk span.sl{opacity:.6}
334
+ .cnd .walk label.sl{cursor:pointer}
335
+ .cnd .walk label.sl:hover{background:rgba(127,127,127,.1)}
336
+ .cnd .walk .sn{display:inline-block;width:3.2em;padding-right:14px;text-align:right;opacity:.42;user-select:none;-webkit-user-select:none}
337
+ .cnd .walk label.sl .sn{opacity:.8}
338
+ @media (max-width:860px){.cnd .walk{--lt:40vh;grid-template-columns:minmax(0,1fr);grid-template-rows:var(--lt) 1fr;height:calc(var(--lt) + var(--ch) + 380px)}.cnd .walk .wl{max-height:none}.cnd .walk :is(.wc,.wf){left:0;border-left:0}.cnd .walk .wc{top:var(--lt);border-top:1px solid rgba(127,127,127,.2);padding:12px 16px}.cnd .walk .wf{top:calc(var(--lt) + var(--ch))}.cnd .walk .ws{border-left:0}}
339
+ @media (prefers-reduced-motion:reduce){.cnd .walk .wfp,.cnd .walk .wbar,.cnd .walk .wc,.cnd .tabs>.tp{transition:none;animation:none}}"""
340
+
341
+ _CSS = _base_css(_ROOT, _EXTRA_CSS)
342
+
343
+ _BADGE = "◆ code-node" # the chip before each page's title
344
+
345
+ _WIDE_CSS = """\
346
+ <style>
347
+ .cnd .flow{max-width:none;max-height:none}
348
+ .cnd .cgb{max-width:100%}
349
+ </style>
350
+ """
351
+
352
+
353
+ def render_page(blocks: list[Any], title: str) -> str:
354
+ """
355
+ A report as a whole HTML document to open in a browser tab, with no row cap: the outline and the graph are as
356
+ wide and tall as they are instead of scrolling in a box.
357
+ """
358
+ return _page_document(_report_html(blocks, 0, _CSS + _WIDE_CSS, _ROOT, _BADGE), title, FAVICON_LINK)
@@ -0,0 +1,73 @@
1
+ """
2
+ _Tabs: blocks in tabs, one shown at a time (the graph, and the walk through its steps).
3
+
4
+ No JavaScript: each tab is a radio button with its label as the tab, and the page's CSS shows the panel after the
5
+ checked one (`#tab:checked ~ .tp`, not :has(), which would look through the whole page each time a step changes).
6
+ In text every tab's blocks are shown one after the other.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from dataclasses import dataclass
12
+ from typing import Any
13
+
14
+ from ..kit.blocks import _Report, _draws
15
+ from ..kit.render import _block_html, _block_lines
16
+ from ..kit.text import _esc
17
+ from .style import _ROOT
18
+
19
+
20
+ @dataclass
21
+ class _Tabs:
22
+ """
23
+ Tabs, each (its name, a few words beside it, its blocks). The first is open. caption (code) and about (words) sit
24
+ at the right of the tab bar, and foot is a quiet line under every tab.
25
+ """
26
+
27
+ tabs: list[tuple[str, str, list[Any]]]
28
+ caption: str = ""
29
+ about: str = ""
30
+ foot: str = ""
31
+
32
+
33
+ @_draws(_Tabs, "html")
34
+ def _tabs_html(block: _Tabs, report: _Report) -> str:
35
+ root = report.root or _ROOT
36
+ made = report.shared("tabs", lambda: [0]) # tab groups drawn so far, so each has ids of its own
37
+ group = f"cnd-tab{made[0]}"
38
+ made[0] += 1
39
+ radios, heads, panels = [], [], []
40
+ for i, (name, sub, blocks) in enumerate(block.tabs):
41
+ tab = f"{group}-{i}"
42
+ checked = " checked" if i == 0 else ""
43
+ radios.append(f'<input type="radio" class="tr" name="{group}" id="{tab}"{checked}>')
44
+ heads.append(
45
+ f'<label class="tl" for="{tab}">{_esc(name)}{f"<small>{_esc(sub)}</small>" if sub else ""}</label>'
46
+ )
47
+ panels.append(f'<div class="tp tp{i}" role="tabpanel">{"".join(_block_html(b, report) for b in blocks)}</div>')
48
+ report.rules.add(f".{root} #{tab}:checked~.tp{i}{{display:block}}")
49
+ report.rules.add(f".{root} #{tab}:checked~.tbar [for={tab}]{{opacity:1;border-bottom-color:currentColor}}")
50
+ report.rules.add(
51
+ f".{root} #{tab}:focus-visible~.tbar [for={tab}]"
52
+ "{outline:2px solid light-dark(#2563eb,#60a5fa);outline-offset:-2px;border-radius:6px 6px 0 0}"
53
+ )
54
+ if block.caption or block.about:
55
+ heads.append(
56
+ f'<span class="tcap">{f"<code>{_esc(block.caption)}</code>" if block.caption else ""}'
57
+ f"{f'<small>{_esc(block.about)}</small>' if block.about else ''}</span>"
58
+ )
59
+ foot = f'<p class="tfoot">{_esc(block.foot)}</p>' if block.foot else ""
60
+ return (
61
+ f'<div class="tabs">{"".join(radios)}<div class="tbar" role="tablist">{"".join(heads)}</div>'
62
+ f"{''.join(panels)}{foot}</div>"
63
+ )
64
+
65
+
66
+ @_draws(_Tabs, "text")
67
+ def _tabs_lines(block: _Tabs, report: _Report) -> list[str]:
68
+ head = [" · ".join(filter(None, [block.caption, block.about]))] if block.caption or block.about else []
69
+ return (
70
+ head
71
+ + [line for _, _, blocks in block.tabs for b in blocks for line in _block_lines(b, report)]
72
+ + ([block.foot] if block.foot else [])
73
+ )