enya-agent 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (389) hide show
  1. package/.env.example +20 -0
  2. package/.github/workflows/ci.yml +70 -0
  3. package/.github/workflows/publish.yml +250 -0
  4. package/.gitmodules +3 -0
  5. package/Cargo.lock +3584 -0
  6. package/Cargo.toml +97 -0
  7. package/crates/enact/Cargo.toml +27 -0
  8. package/crates/enact/src/lib.rs +60 -0
  9. package/crates/enact-a2a/Cargo.toml +25 -0
  10. package/crates/enact-a2a/src/lib.rs +411 -0
  11. package/crates/enact-channels/Cargo.toml +64 -0
  12. package/crates/enact-channels/examples/README.md +80 -0
  13. package/crates/enact-channels/examples/channel_bot.rs +169 -0
  14. package/crates/enact-channels/examples/telegram-echo.rs +34 -0
  15. package/crates/enact-channels/examples/whatsapp-echo.rs +142 -0
  16. package/crates/enact-channels/src/config.rs +213 -0
  17. package/crates/enact-channels/src/lib.rs +25 -0
  18. package/crates/enact-channels/src/runtime.rs +237 -0
  19. package/crates/enact-channels/src/security/mod.rs +5 -0
  20. package/crates/enact-channels/src/security/pairing.rs +205 -0
  21. package/crates/enact-channels/src/teams.rs +601 -0
  22. package/crates/enact-channels/src/telegram.rs +2833 -0
  23. package/crates/enact-channels/src/traits.rs +200 -0
  24. package/crates/enact-channels/src/webhook.rs +262 -0
  25. package/crates/enact-channels/src/whatsapp.rs +310 -0
  26. package/crates/enact-cli/Cargo.toml +40 -0
  27. package/crates/enact-cli/src/commands/doctor.rs +62 -0
  28. package/crates/enact-cli/src/commands/mod.rs +3 -0
  29. package/crates/enact-cli/src/commands/run.rs +69 -0
  30. package/crates/enact-cli/src/commands/serve.rs +81 -0
  31. package/crates/enact-cli/src/config.rs +2 -0
  32. package/crates/enact-cli/src/main.rs +79 -0
  33. package/crates/enact-config/Cargo.toml +36 -0
  34. package/crates/enact-config/ENV_VAR_MAPPING.md +135 -0
  35. package/crates/enact-config/QUICK_REFERENCE.md +92 -0
  36. package/crates/enact-config/README.md +107 -0
  37. package/crates/enact-config/TESTING.md +161 -0
  38. package/crates/enact-config/examples/test-env-vars.rs +100 -0
  39. package/crates/enact-config/src/config.rs +399 -0
  40. package/crates/enact-config/src/encrypted_store.rs +211 -0
  41. package/crates/enact-config/src/lib.rs +298 -0
  42. package/crates/enact-config/src/secrets.rs +149 -0
  43. package/crates/enact-config/src/sync.rs +260 -0
  44. package/crates/enact-config/test-env-vars.sh +34 -0
  45. package/crates/enact-config/tests/README.md +99 -0
  46. package/crates/enact-config/tests/config_integration_test.rs +202 -0
  47. package/crates/enact-config/tests/security_test.rs +140 -0
  48. package/crates/enact-context/Cargo.toml +41 -0
  49. package/crates/enact-context/src/budget.rs +314 -0
  50. package/crates/enact-context/src/calibrator.rs +535 -0
  51. package/crates/enact-context/src/compactor.rs +392 -0
  52. package/crates/enact-context/src/condenser.rs +826 -0
  53. package/crates/enact-context/src/lib.rs +94 -0
  54. package/crates/enact-context/src/segment.rs +238 -0
  55. package/crates/enact-context/src/step_context.rs +645 -0
  56. package/crates/enact-context/src/token_counter.rs +148 -0
  57. package/crates/enact-context/src/window.rs +372 -0
  58. package/crates/enact-core/Cargo.toml +42 -0
  59. package/crates/enact-core/README.md +98 -0
  60. package/crates/enact-core/src/background/executor.rs +524 -0
  61. package/crates/enact-core/src/background/mod.rs +48 -0
  62. package/crates/enact-core/src/background/target_binding.rs +390 -0
  63. package/crates/enact-core/src/background/trigger.rs +511 -0
  64. package/crates/enact-core/src/callable/callable.rs +152 -0
  65. package/crates/enact-core/src/callable/composite.rs +817 -0
  66. package/crates/enact-core/src/callable/graph.rs +104 -0
  67. package/crates/enact-core/src/callable/llm.rs +211 -0
  68. package/crates/enact-core/src/callable/mod.rs +64 -0
  69. package/crates/enact-core/src/callable/registry.rs +206 -0
  70. package/crates/enact-core/src/context/execution_context.rs +757 -0
  71. package/crates/enact-core/src/context/invocation.rs +99 -0
  72. package/crates/enact-core/src/context/mod.rs +50 -0
  73. package/crates/enact-core/src/context/tenant.rs +175 -0
  74. package/crates/enact-core/src/context/trace.rs +127 -0
  75. package/crates/enact-core/src/flow/conditional.rs +293 -0
  76. package/crates/enact-core/src/flow/mod.rs +43 -0
  77. package/crates/enact-core/src/flow/parallel.rs +437 -0
  78. package/crates/enact-core/src/flow/repeat.rs +534 -0
  79. package/crates/enact-core/src/flow/sequential.rs +248 -0
  80. package/crates/enact-core/src/graph/checkpoint.rs +79 -0
  81. package/crates/enact-core/src/graph/checkpoint_store.rs +76 -0
  82. package/crates/enact-core/src/graph/compiled.rs +189 -0
  83. package/crates/enact-core/src/graph/edge.rs +59 -0
  84. package/crates/enact-core/src/graph/graph_schema.rs +218 -0
  85. package/crates/enact-core/src/graph/loader.rs +155 -0
  86. package/crates/enact-core/src/graph/mod.rs +18 -0
  87. package/crates/enact-core/src/graph/node/function.rs +49 -0
  88. package/crates/enact-core/src/graph/node/mod.rs +48 -0
  89. package/crates/enact-core/src/graph/schema.rs +62 -0
  90. package/crates/enact-core/src/inbox/message.rs +405 -0
  91. package/crates/enact-core/src/inbox/mod.rs +31 -0
  92. package/crates/enact-core/src/inbox/store.rs +355 -0
  93. package/crates/enact-core/src/kernel/artifact/filesystem.rs +546 -0
  94. package/crates/enact-core/src/kernel/artifact/metadata.rs +283 -0
  95. package/crates/enact-core/src/kernel/artifact/mod.rs +27 -0
  96. package/crates/enact-core/src/kernel/artifact/store.rs +427 -0
  97. package/crates/enact-core/src/kernel/enforcement.rs +1315 -0
  98. package/crates/enact-core/src/kernel/error.rs +1200 -0
  99. package/crates/enact-core/src/kernel/event.rs +1394 -0
  100. package/crates/enact-core/src/kernel/execution_model.rs +831 -0
  101. package/crates/enact-core/src/kernel/execution_state.rs +189 -0
  102. package/crates/enact-core/src/kernel/execution_strategy.rs +117 -0
  103. package/crates/enact-core/src/kernel/ids.rs +2086 -0
  104. package/crates/enact-core/src/kernel/interrupt.rs +125 -0
  105. package/crates/enact-core/src/kernel/kernel.rs +1283 -0
  106. package/crates/enact-core/src/kernel/mod.rs +205 -0
  107. package/crates/enact-core/src/kernel/persistence/event_store.rs +270 -0
  108. package/crates/enact-core/src/kernel/persistence/message_store.rs +908 -0
  109. package/crates/enact-core/src/kernel/persistence/mod.rs +102 -0
  110. package/crates/enact-core/src/kernel/persistence/state_store.rs +228 -0
  111. package/crates/enact-core/src/kernel/persistence/vector_store.rs +299 -0
  112. package/crates/enact-core/src/kernel/reducer.rs +808 -0
  113. package/crates/enact-core/src/kernel/replay.rs +153 -0
  114. package/crates/enact-core/src/lib.rs +413 -0
  115. package/crates/enact-core/src/memory/episodic.rs +0 -0
  116. package/crates/enact-core/src/memory/mod.rs +6 -0
  117. package/crates/enact-core/src/memory/semantic.rs +0 -0
  118. package/crates/enact-core/src/memory/trait.rs +0 -0
  119. package/crates/enact-core/src/memory/vector_db.rs +0 -0
  120. package/crates/enact-core/src/memory/working.rs +0 -0
  121. package/crates/enact-core/src/policy/execution_policy.rs +292 -0
  122. package/crates/enact-core/src/policy/filters.rs +458 -0
  123. package/crates/enact-core/src/policy/input_processor.rs +407 -0
  124. package/crates/enact-core/src/policy/long_running.rs +134 -0
  125. package/crates/enact-core/src/policy/mod.rs +193 -0
  126. package/crates/enact-core/src/policy/pii_input.rs +274 -0
  127. package/crates/enact-core/src/policy/tenant_policy.rs +453 -0
  128. package/crates/enact-core/src/policy/tool_policy.rs +407 -0
  129. package/crates/enact-core/src/providers/mod.rs +63 -0
  130. package/crates/enact-core/src/providers/trait.rs +292 -0
  131. package/crates/enact-core/src/runner/callbacks.rs +6 -0
  132. package/crates/enact-core/src/runner/execution_runner.rs +476 -0
  133. package/crates/enact-core/src/runner/loop.rs +117 -0
  134. package/crates/enact-core/src/runner/mod.rs +58 -0
  135. package/crates/enact-core/src/runner/protected_runner.rs +280 -0
  136. package/crates/enact-core/src/signal/inmemory.rs +231 -0
  137. package/crates/enact-core/src/signal/mod.rs +108 -0
  138. package/crates/enact-core/src/streaming/event_logger.rs +195 -0
  139. package/crates/enact-core/src/streaming/event_stream.rs +1423 -0
  140. package/crates/enact-core/src/streaming/mod.rs +108 -0
  141. package/crates/enact-core/src/streaming/pause_cancel.rs +0 -0
  142. package/crates/enact-core/src/streaming/protected_emitter.rs +173 -0
  143. package/crates/enact-core/src/streaming/protection/context.rs +136 -0
  144. package/crates/enact-core/src/streaming/protection/encryption.rs +289 -0
  145. package/crates/enact-core/src/streaming/protection/mod.rs +43 -0
  146. package/crates/enact-core/src/streaming/protection/pii_protection.rs +243 -0
  147. package/crates/enact-core/src/streaming/protection/processor.rs +166 -0
  148. package/crates/enact-core/src/streaming/sse.rs +0 -0
  149. package/crates/enact-core/src/telemetry/exporter.rs +0 -0
  150. package/crates/enact-core/src/telemetry/init.rs +0 -0
  151. package/crates/enact-core/src/telemetry/mod.rs +49 -0
  152. package/crates/enact-core/src/telemetry/spans.rs +245 -0
  153. package/crates/enact-core/src/tool/agent_tool.rs +177 -0
  154. package/crates/enact-core/src/tool/browser/mod.rs +0 -0
  155. package/crates/enact-core/src/tool/browser/webdriver.rs +0 -0
  156. package/crates/enact-core/src/tool/cost.rs +247 -0
  157. package/crates/enact-core/src/tool/discovery.rs +0 -0
  158. package/crates/enact-core/src/tool/dispatcher.rs +347 -0
  159. package/crates/enact-core/src/tool/filesystem.rs +231 -0
  160. package/crates/enact-core/src/tool/function.rs +99 -0
  161. package/crates/enact-core/src/tool/git.rs +162 -0
  162. package/crates/enact-core/src/tool/http.rs +214 -0
  163. package/crates/enact-core/src/tool/mcp/client.rs +0 -0
  164. package/crates/enact-core/src/tool/mcp/mod.rs +0 -0
  165. package/crates/enact-core/src/tool/mod.rs +51 -0
  166. package/crates/enact-core/src/tool/reasoning/debugging.rs +0 -0
  167. package/crates/enact-core/src/tool/reasoning/mcts.rs +0 -0
  168. package/crates/enact-core/src/tool/reasoning/mod.rs +0 -0
  169. package/crates/enact-core/src/tool/reasoning/sequential.rs +0 -0
  170. package/crates/enact-core/src/tool/sandbox/dagger.rs +0 -0
  171. package/crates/enact-core/src/tool/sandbox/mod.rs +0 -0
  172. package/crates/enact-core/src/tool/shell.rs +147 -0
  173. package/crates/enact-core/src/tool/trait.rs +33 -0
  174. package/crates/enact-core/src/tool/web_search.rs +277 -0
  175. package/crates/enact-core/src/util/config.rs +0 -0
  176. package/crates/enact-core/src/util/errors.rs +0 -0
  177. package/crates/enact-core/src/util/mod.rs +6 -0
  178. package/crates/enact-core/tests/airgapped_e2e_test.rs +291 -0
  179. package/crates/enact-core/tests/e2e_agentic_loop.rs +119 -0
  180. package/crates/enact-core/tests/e2e_test.rs +259 -0
  181. package/crates/enact-core/tests/graph_test.rs +130 -0
  182. package/crates/enact-core/tests/stream_event_id_validation.rs +435 -0
  183. package/crates/enact-cron/Cargo.toml +28 -0
  184. package/crates/enact-cron/src/lib.rs +44 -0
  185. package/crates/enact-cron/src/schedule.rs +156 -0
  186. package/crates/enact-cron/src/store.rs +589 -0
  187. package/crates/enact-cron/src/types.rs +148 -0
  188. package/crates/enact-gateway/Cargo.toml +31 -0
  189. package/crates/enact-gateway/README.md +30 -0
  190. package/crates/enact-gateway/examples/whatsapp-gateway-runner-mock.rs +59 -0
  191. package/crates/enact-gateway/examples/whatsapp-gateway.rs +42 -0
  192. package/crates/enact-gateway/src/lib.rs +582 -0
  193. package/crates/enact-mcp/Cargo.toml +24 -0
  194. package/crates/enact-mcp/src/lib.rs +178 -0
  195. package/crates/enact-memory/Cargo.toml +25 -0
  196. package/crates/enact-memory/src/backend.rs +20 -0
  197. package/crates/enact-memory/src/chunker.rs +230 -0
  198. package/crates/enact-memory/src/embeddings.rs +221 -0
  199. package/crates/enact-memory/src/lib.rs +67 -0
  200. package/crates/enact-memory/src/markdown.rs +127 -0
  201. package/crates/enact-memory/src/none.rs +61 -0
  202. package/crates/enact-memory/src/sqlite.rs +276 -0
  203. package/crates/enact-memory/src/traits.rs +65 -0
  204. package/crates/enact-memory/src/vector.rs +198 -0
  205. package/crates/enact-oauth/Cargo.toml +27 -0
  206. package/crates/enact-oauth/src/lib.rs +584 -0
  207. package/crates/enact-observability/Cargo.toml +22 -0
  208. package/crates/enact-observability/src/lib.rs +197 -0
  209. package/crates/enact-providers/Cargo.toml +33 -0
  210. package/crates/enact-providers/examples/hello-agent.rs +33 -0
  211. package/crates/enact-providers/src/anthropic.rs +182 -0
  212. package/crates/enact-providers/src/azure.rs +96 -0
  213. package/crates/enact-providers/src/bridge.rs +221 -0
  214. package/crates/enact-providers/src/gemini.rs +227 -0
  215. package/crates/enact-providers/src/http.rs +78 -0
  216. package/crates/enact-providers/src/lib.rs +53 -0
  217. package/crates/enact-providers/src/openai_compatible.rs +167 -0
  218. package/crates/enact-providers/src/openrouter.rs +33 -0
  219. package/crates/enact-runner/Cargo.toml +24 -0
  220. package/crates/enact-runner/README.md +76 -0
  221. package/crates/enact-runner/src/compaction.rs +225 -0
  222. package/crates/enact-runner/src/config.rs +118 -0
  223. package/crates/enact-runner/src/lib.rs +63 -0
  224. package/crates/enact-runner/src/loop_driver.rs +414 -0
  225. package/crates/enact-runner/src/parser.rs +421 -0
  226. package/crates/enact-runner/src/retry.rs +262 -0
  227. package/crates/enact-runner/tests/integration.rs +278 -0
  228. package/crates/enact-security/Cargo.toml +22 -0
  229. package/crates/enact-security/src/audit.rs +375 -0
  230. package/crates/enact-security/src/lib.rs +37 -0
  231. package/crates/enact-security/src/policy.rs +406 -0
  232. package/crates/enact-skills/Cargo.toml +25 -0
  233. package/crates/enact-skills/src/lib.rs +506 -0
  234. package/crates/enact-tools/Cargo.toml +22 -0
  235. package/crates/enact-tools/src/file_read.rs +166 -0
  236. package/crates/enact-tools/src/file_write.rs +216 -0
  237. package/crates/enact-tools/src/git_operations.rs +513 -0
  238. package/crates/enact-tools/src/http_request.rs +417 -0
  239. package/crates/enact-tools/src/lib.rs +104 -0
  240. package/crates/enact-tools/src/security.rs +227 -0
  241. package/crates/enact-tools/src/shell.rs +191 -0
  242. package/crates/enact-tools/src/traits.rs +159 -0
  243. package/docs/Makefile +74 -0
  244. package/docs/config.toml +62 -0
  245. package/docs/content/_index.md +174 -0
  246. package/docs/content/a2a/_index.md +431 -0
  247. package/docs/content/api/_index.md +323 -0
  248. package/docs/content/channels/_index.md +160 -0
  249. package/docs/content/channels/teams.md +205 -0
  250. package/docs/content/channels/telegram.md +182 -0
  251. package/docs/content/channels/webhook.md +423 -0
  252. package/docs/content/channels/whatsapp.md +240 -0
  253. package/docs/content/cli/_index.md +261 -0
  254. package/docs/content/concepts/_index.md +273 -0
  255. package/docs/content/configuration/_index.md +241 -0
  256. package/docs/content/cron/_index.md +248 -0
  257. package/docs/content/developers/_index.md +278 -0
  258. package/docs/content/getting-started/_index.md +180 -0
  259. package/docs/content/installation/_index.md +186 -0
  260. package/docs/content/installation/uninstall.md +101 -0
  261. package/docs/content/installation/updating.md +120 -0
  262. package/docs/content/mcp/_index.md +215 -0
  263. package/docs/content/memory/_index.md +163 -0
  264. package/docs/content/oauth/_index.md +515 -0
  265. package/docs/content/providers/_index.md +206 -0
  266. package/docs/content/roadmap/_index.md +199 -0
  267. package/docs/content/security/_index.md +219 -0
  268. package/docs/content/skills/_index.md +228 -0
  269. package/docs/content/tools/_index.md +485 -0
  270. package/docs/content/troubleshooting/_index.md +259 -0
  271. package/docs/content/yaml-schema/_index.md +294 -0
  272. package/docs/static/giallo-dark.css +91 -0
  273. package/docs/static/giallo-light.css +91 -0
  274. package/docs/themes/tanuki/.github/workflows/deploy.yml +44 -0
  275. package/docs/themes/tanuki/LICENSE +21 -0
  276. package/docs/themes/tanuki/README.md +166 -0
  277. package/docs/themes/tanuki/examples/blog/config.toml +58 -0
  278. package/docs/themes/tanuki/examples/blog/content/_index.md +4 -0
  279. package/docs/themes/tanuki/examples/blog/content/about.md +33 -0
  280. package/docs/themes/tanuki/examples/blog/content/blog/_index.md +7 -0
  281. package/docs/themes/tanuki/examples/blog/content/blog/api-design-best-practices.md +245 -0
  282. package/docs/themes/tanuki/examples/blog/content/blog/building-accessible-websites.md +147 -0
  283. package/docs/themes/tanuki/examples/blog/content/blog/css-grid-vs-flexbox.md +165 -0
  284. package/docs/themes/tanuki/examples/blog/content/blog/customizing-catppuccin-colors.md +137 -0
  285. package/docs/themes/tanuki/examples/blog/content/blog/dark-mode-best-practices.md +82 -0
  286. package/docs/themes/tanuki/examples/blog/content/blog/docker-essentials.md +301 -0
  287. package/docs/themes/tanuki/examples/blog/content/blog/getting-started-with-zola.md +129 -0
  288. package/docs/themes/tanuki/examples/blog/content/blog/git-workflow-for-content.md +112 -0
  289. package/docs/themes/tanuki/examples/blog/content/blog/introduction-to-webassembly.md +183 -0
  290. package/docs/themes/tanuki/examples/blog/content/blog/modern-javascript-features.md +234 -0
  291. package/docs/themes/tanuki/examples/blog/content/blog/testing-strategies.md +311 -0
  292. package/docs/themes/tanuki/examples/blog/content/blog/typography-for-developers.md +104 -0
  293. package/docs/themes/tanuki/examples/blog/content/blog/welcome-to-tanuki.md +67 -0
  294. package/docs/themes/tanuki/examples/blog/content/blog/why-static-sites.md +85 -0
  295. package/docs/themes/tanuki/examples/blog/content/projects.md +64 -0
  296. package/docs/themes/tanuki/examples/book/config.toml +17 -0
  297. package/docs/themes/tanuki/examples/book/content/_index.md +12 -0
  298. package/docs/themes/tanuki/examples/book/content/chapter-1.md +90 -0
  299. package/docs/themes/tanuki/examples/book/content/chapter-2.md +143 -0
  300. package/docs/themes/tanuki/examples/book/content/chapter-3.md +217 -0
  301. package/docs/themes/tanuki/examples/book/content/chapter-4.md +224 -0
  302. package/docs/themes/tanuki/examples/book/content/chapter-5.md +297 -0
  303. package/docs/themes/tanuki/examples/book/content/print.md +6 -0
  304. package/docs/themes/tanuki/examples/docs/config.toml +28 -0
  305. package/docs/themes/tanuki/examples/docs/content/_index.md +20 -0
  306. package/docs/themes/tanuki/examples/docs/content/components.md +156 -0
  307. package/docs/themes/tanuki/examples/docs/content/configuration.md +94 -0
  308. package/docs/themes/tanuki/examples/docs/content/customization.md +202 -0
  309. package/docs/themes/tanuki/examples/docs/content/deployment.md +204 -0
  310. package/docs/themes/tanuki/examples/docs/content/installation.md +59 -0
  311. package/docs/themes/tanuki/examples/docs/content/print.md +6 -0
  312. package/docs/themes/tanuki/examples/docs/static/img/tanuki-icon.avif +0 -0
  313. package/docs/themes/tanuki/examples/index.html +2104 -0
  314. package/docs/themes/tanuki/mise.toml +108 -0
  315. package/docs/themes/tanuki/sass/base/_catppuccin.scss +164 -0
  316. package/docs/themes/tanuki/sass/base/_fonts.scss +64 -0
  317. package/docs/themes/tanuki/sass/base/_reset.scss +152 -0
  318. package/docs/themes/tanuki/sass/base/_typography.scss +523 -0
  319. package/docs/themes/tanuki/sass/components/_buttons.scss +209 -0
  320. package/docs/themes/tanuki/sass/components/_code.scss +457 -0
  321. package/docs/themes/tanuki/sass/components/_landing.scss +633 -0
  322. package/docs/themes/tanuki/sass/components/_layout.scss +294 -0
  323. package/docs/themes/tanuki/sass/components/_navigation.scss +1200 -0
  324. package/docs/themes/tanuki/sass/components/_print.scss +237 -0
  325. package/docs/themes/tanuki/sass/components/_search.scss +224 -0
  326. package/docs/themes/tanuki/sass/components/_sidebar.scss +473 -0
  327. package/docs/themes/tanuki/sass/components/_theme-toggle.scss +186 -0
  328. package/docs/themes/tanuki/sass/modes/_blog.scss +366 -0
  329. package/docs/themes/tanuki/sass/modes/_product.scss +875 -0
  330. package/docs/themes/tanuki/sass/modes/_raskell.scss +1696 -0
  331. package/docs/themes/tanuki/sass/patterns/_buttons.scss +183 -0
  332. package/docs/themes/tanuki/sass/patterns/_cards.scss +144 -0
  333. package/docs/themes/tanuki/sass/patterns/_index.scss +9 -0
  334. package/docs/themes/tanuki/sass/patterns/_lists.scss +259 -0
  335. package/docs/themes/tanuki/sass/patterns/_sections.scss +243 -0
  336. package/docs/themes/tanuki/sass/style.scss +47 -0
  337. package/docs/themes/tanuki/sass/tokens/_colors.scss +139 -0
  338. package/docs/themes/tanuki/sass/tokens/_spacing.scss +100 -0
  339. package/docs/themes/tanuki/sass/tokens/_typography.scss +186 -0
  340. package/docs/themes/tanuki/screenshot.png +0 -0
  341. package/docs/themes/tanuki/sentinel.kdl +59 -0
  342. package/docs/themes/tanuki/static/elasticlunr.min.js +10 -0
  343. package/docs/themes/tanuki/static/fonts/GEIST-LICENSE.txt +92 -0
  344. package/docs/themes/tanuki/static/fonts/Geist-Variable.woff2 +0 -0
  345. package/docs/themes/tanuki/static/fonts/GeistMono-Variable.woff2 +0 -0
  346. package/docs/themes/tanuki/static/img/tanuki-icon.avif +0 -0
  347. package/docs/themes/tanuki/static/img/tanuki-icon.png +0 -0
  348. package/docs/themes/tanuki/static/js/anchors.js +18 -0
  349. package/docs/themes/tanuki/static/js/app.js +274 -0
  350. package/docs/themes/tanuki/static/js/code.js +394 -0
  351. package/docs/themes/tanuki/static/js/navigation.js +778 -0
  352. package/docs/themes/tanuki/static/js/scroll-to-top.js +33 -0
  353. package/docs/themes/tanuki/static/js/search-raskell.js +240 -0
  354. package/docs/themes/tanuki/static/js/search.js +215 -0
  355. package/docs/themes/tanuki/static/js/theme.js +169 -0
  356. package/docs/themes/tanuki/static/syntax-dark.css +151 -0
  357. package/docs/themes/tanuki/static/syntax-light.css +151 -0
  358. package/docs/themes/tanuki/static/wasm/sentinel_playground_wasm.js +486 -0
  359. package/docs/themes/tanuki/static/wasm/sentinel_playground_wasm_bg.wasm +0 -0
  360. package/docs/themes/tanuki/templates/404.html +52 -0
  361. package/docs/themes/tanuki/templates/base.html +428 -0
  362. package/docs/themes/tanuki/templates/blog.html +66 -0
  363. package/docs/themes/tanuki/templates/home.html +108 -0
  364. package/docs/themes/tanuki/templates/index.html +178 -0
  365. package/docs/themes/tanuki/templates/landing.html +168 -0
  366. package/docs/themes/tanuki/templates/macros/nav.html +128 -0
  367. package/docs/themes/tanuki/templates/macros/posts.html +101 -0
  368. package/docs/themes/tanuki/templates/macros/ui.html +159 -0
  369. package/docs/themes/tanuki/templates/page.html +135 -0
  370. package/docs/themes/tanuki/templates/partials/footer.html +38 -0
  371. package/docs/themes/tanuki/templates/partials/header.html +366 -0
  372. package/docs/themes/tanuki/templates/partials/nav-buttons.html +55 -0
  373. package/docs/themes/tanuki/templates/partials/nav-overlay.html +81 -0
  374. package/docs/themes/tanuki/templates/partials/page-toc-panel.html +43 -0
  375. package/docs/themes/tanuki/templates/partials/search.html +52 -0
  376. package/docs/themes/tanuki/templates/partials/sidebar.html +107 -0
  377. package/docs/themes/tanuki/templates/partials/theme-toggle.html +35 -0
  378. package/docs/themes/tanuki/templates/partials/toc-overlay.html +146 -0
  379. package/docs/themes/tanuki/templates/partials/version-picker.html +38 -0
  380. package/docs/themes/tanuki/templates/print.html +244 -0
  381. package/docs/themes/tanuki/templates/section.html +186 -0
  382. package/docs/themes/tanuki/templates/taxonomy_list.html +18 -0
  383. package/docs/themes/tanuki/templates/taxonomy_single.html +31 -0
  384. package/docs/themes/tanuki/theme.toml +58 -0
  385. package/examples/hello-agent.rs +55 -0
  386. package/package.json +36 -0
  387. package/proto/config.proto +60 -0
  388. package/proto/events.proto +0 -0
  389. package/proto/runtime.proto +215 -0
@@ -0,0 +1,1696 @@
1
+ // =============================================================================
2
+ // Mode: Raskell.io Blog
3
+ // Complete styling for www.raskell.io blog/site mode
4
+ // =============================================================================
5
+
6
+ // =============================================================================
7
+ // Variable Mappings (Catppuccin to www.raskell.io semantics)
8
+ // =============================================================================
9
+
10
+ :root {
11
+ // Font families
12
+ --sys-font-family:
13
+ -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
14
+ Arial, sans-serif;
15
+ --base-font-family: "Geist", var(--sys-font-family);
16
+ --code-font-family:
17
+ "Geist Mono", "SFMono-Regular", Consolas, "Liberation Mono", Menlo,
18
+ monospace;
19
+ --article-font-family: var(--base-font-family);
20
+
21
+ // Theme mappings (light mode - Catppuccin Latte)
22
+ --h1-color: var(--ctp-text);
23
+ --font-color: var(--ctp-text);
24
+ --heading-color: var(--ctp-text);
25
+ --background: var(--ctp-base);
26
+ --dark-font-color: var(--ctp-text);
27
+ --medium-font-color: var(--ctp-subtext1);
28
+ --light-font-color: var(--ctp-subtext0);
29
+ --light-background: var(--ctp-mantle);
30
+ --light-background-hover: var(--ctp-surface0);
31
+ --border: var(--ctp-surface0);
32
+ --link-color: var(--ctp-blue);
33
+ --link-color-darker: var(--ctp-sapphire);
34
+ --link-hover-color: var(--ctp-sapphire);
35
+ --navbar-color: var(--ctp-base);
36
+ --blockquote: var(--ctp-mantle);
37
+ --blockquote-left: var(--ctp-surface0);
38
+ --transparent-text: var(--ctp-overlay2);
39
+ --transparent-bg: var(--ctp-surface1);
40
+ --light-transparent-bg: var(--ctp-surface0);
41
+ --input-color: var(--ctp-text);
42
+
43
+ // Accent colors
44
+ --accent-primary: var(--ctp-mauve);
45
+ --accent-secondary: var(--ctp-teal);
46
+ --accent-tertiary: var(--ctp-peach);
47
+ --accent-success: var(--ctp-green);
48
+ }
49
+
50
+ // Dark mode overrides
51
+ [data-user-color-scheme="dark"],
52
+ [data-theme="dark"] {
53
+ --h1-color: var(--ctp-text);
54
+ --font-color: var(--ctp-text);
55
+ --heading-color: var(--ctp-lavender);
56
+ --dark-font-color: var(--ctp-text);
57
+ --background: var(--ctp-base);
58
+ --medium-font-color: var(--ctp-subtext1);
59
+ --light-font-color: var(--ctp-subtext0);
60
+ --light-background: var(--ctp-mantle);
61
+ --light-background-hover: var(--ctp-surface0);
62
+ --code-background-color: var(--ctp-mantle);
63
+ --border: var(--ctp-surface0);
64
+ --link-color: var(--ctp-sapphire);
65
+ --link-color-darker: var(--ctp-blue);
66
+ --link-hover-color: var(--ctp-mauve);
67
+ --navbar-color: var(--ctp-base);
68
+ --blockquote: var(--ctp-mantle);
69
+ --blockquote-left: var(--ctp-mauve);
70
+ --transparent-text: var(--ctp-overlay1);
71
+ --transparent-bg: var(--ctp-surface0);
72
+ --light-transparent-bg: var(--ctp-surface1);
73
+ --input-color: var(--ctp-text);
74
+
75
+ // Accent colors
76
+ --accent-primary: var(--ctp-mauve);
77
+ --accent-secondary: var(--ctp-teal);
78
+ --accent-tertiary: var(--ctp-peach);
79
+ --accent-success: var(--ctp-green);
80
+ }
81
+
82
+ // =============================================================================
83
+ // Base Styles (for site/blog mode only)
84
+ // =============================================================================
85
+
86
+ [data-mode="site"],
87
+ [data-mode="blog"] {
88
+ // Scaffolding
89
+ html {
90
+ font-family: var(--base-font-family);
91
+ color: var(--font-color);
92
+ font-weight: 400;
93
+ font-size: 1rem;
94
+ line-height: 1.75;
95
+ }
96
+
97
+ body {
98
+ background: var(--background);
99
+ margin: 0;
100
+ padding: 0;
101
+ }
102
+
103
+ main {
104
+ margin-top: 60px;
105
+ }
106
+
107
+ @media screen and (min-width: 800px) {
108
+ main {
109
+ margin-top: 0;
110
+ }
111
+ }
112
+
113
+ section {
114
+ margin: 2rem 0;
115
+
116
+ &:first-of-type {
117
+ margin-top: 0;
118
+ }
119
+
120
+ > h2 {
121
+ display: flex;
122
+ align-items: center;
123
+ font-size: 1.6rem;
124
+ margin-top: 0;
125
+ margin-bottom: 0.5rem;
126
+ border-bottom-width: 0;
127
+ }
128
+ }
129
+
130
+ @media screen and (min-width: 800px) {
131
+ section {
132
+ margin: 3.5rem 0;
133
+
134
+ > h2 {
135
+ font-size: 2rem;
136
+ margin: 0 0 1rem;
137
+ border-bottom-width: 4px;
138
+ }
139
+ }
140
+ }
141
+
142
+ .container {
143
+ max-width: 830px;
144
+ padding: 0 1.5rem;
145
+ margin-left: auto;
146
+ margin-right: auto;
147
+
148
+ &.page p {
149
+ max-width: 600px;
150
+ }
151
+ }
152
+
153
+ @media screen and (min-width: 800px) {
154
+ .container {
155
+ padding: 0 2rem;
156
+ }
157
+ }
158
+
159
+ img {
160
+ display: inline-block;
161
+ max-width: 100%;
162
+ height: auto;
163
+ }
164
+
165
+ p,
166
+ ol,
167
+ ul,
168
+ dl,
169
+ table,
170
+ blockquote {
171
+ font-size: 1.05rem;
172
+ margin: 0 0 1.5rem 0;
173
+ }
174
+
175
+ blockquote p {
176
+ margin: 0;
177
+ }
178
+
179
+ ul {
180
+ padding: 0 1rem;
181
+ }
182
+
183
+ @media screen and (min-width: 800px) {
184
+ p,
185
+ ol,
186
+ ul,
187
+ dl,
188
+ table,
189
+ blockquote {
190
+ font-size: 1.125rem;
191
+ }
192
+
193
+ ul {
194
+ padding: 0 2rem;
195
+ }
196
+ }
197
+
198
+ ul li p {
199
+ margin: 0;
200
+ }
201
+
202
+ ul li ul {
203
+ padding-left: 1rem;
204
+ margin: 0;
205
+ }
206
+
207
+ blockquote {
208
+ margin: 2rem 0;
209
+ padding: 1rem;
210
+ background: var(--blockquote);
211
+ font-weight: 400;
212
+ border-left: 5px solid var(--blockquote-left);
213
+ }
214
+
215
+ @media screen and (min-width: 800px) {
216
+ blockquote {
217
+ padding: 2rem 0 2rem 2rem;
218
+ }
219
+ }
220
+
221
+ ::selection {
222
+ background: #3b5bdb;
223
+ color: white;
224
+ }
225
+
226
+ // Links
227
+ a {
228
+ color: var(--link-color);
229
+ text-decoration: none;
230
+ font-weight: 600;
231
+ border-bottom: 2px solid transparent;
232
+
233
+ &:hover {
234
+ border-bottom-color: currentColor;
235
+ color: var(--link-hover-color);
236
+ }
237
+ }
238
+
239
+ // =============================================================================
240
+ // Navbar
241
+ // =============================================================================
242
+
243
+ .emoji {
244
+ margin: 0 0.4rem 0 0.1rem;
245
+ }
246
+
247
+ .navbar {
248
+ width: 100%;
249
+ position: fixed;
250
+ top: 0;
251
+ left: 0;
252
+ background: var(--navbar-color);
253
+ z-index: 10;
254
+ padding: 0.75rem 0.5rem;
255
+
256
+ .flex {
257
+ display: flex;
258
+ justify-content: space-between;
259
+ align-items: center;
260
+ }
261
+
262
+ .nav-links {
263
+ display: none;
264
+ }
265
+
266
+ a {
267
+ border-radius: 0.35rem;
268
+ margin: 0;
269
+ color: var(--font-color);
270
+ font-weight: 500;
271
+ font-size: 0.9rem;
272
+ border: 1px solid transparent;
273
+ padding: 0.5rem 0.65rem;
274
+ background: transparent;
275
+
276
+ &:first-of-type {
277
+ margin-left: -0.5rem;
278
+ }
279
+
280
+ .emoji {
281
+ display: none;
282
+ }
283
+
284
+ &.brand {
285
+ font-weight: 500;
286
+ color: var(--font-color);
287
+ white-space: nowrap;
288
+ border: none;
289
+ display: flex;
290
+ align-items: center;
291
+ gap: 0.5rem;
292
+ line-height: 1;
293
+ background: transparent;
294
+ padding: 0.25rem;
295
+
296
+ .emoji {
297
+ display: inline-block !important;
298
+ }
299
+
300
+ .brand-logo {
301
+ height: 28px;
302
+ width: 28px;
303
+ border-radius: 6px;
304
+ object-fit: contain;
305
+ }
306
+
307
+ .brand-text {
308
+ font-weight: 600;
309
+ letter-spacing: -0.01em;
310
+ }
311
+ }
312
+ }
313
+ }
314
+
315
+ @media screen and (min-width: 800px) {
316
+ .emoji {
317
+ margin: 0 0.5rem 0 0.1rem;
318
+ }
319
+
320
+ .navbar {
321
+ position: static;
322
+ padding: 1.5rem 0;
323
+ background: transparent;
324
+ box-shadow: none;
325
+
326
+ .flex {
327
+ justify-content: space-between;
328
+ }
329
+
330
+ .nav-links {
331
+ display: flex;
332
+ align-items: center;
333
+ }
334
+
335
+ a {
336
+ padding: 0.75rem 1.25rem;
337
+ margin: 0 0.25rem;
338
+ font-size: 1.2rem;
339
+ font-weight: 400;
340
+ color: var(--font-color);
341
+
342
+ &:first-of-type {
343
+ margin-left: -1.5rem;
344
+ }
345
+
346
+ &:hover {
347
+ background: var(--light-background);
348
+ color: var(--dark-font-color);
349
+ }
350
+
351
+ &[aria-current="page"] {
352
+ background: var(--light-background);
353
+ border-bottom: 2px solid var(--accent-primary);
354
+ color: var(--dark-font-color);
355
+ }
356
+
357
+ &.brand {
358
+ font-size: 1.3rem;
359
+ margin-right: 3rem;
360
+ border: none;
361
+ background: transparent !important;
362
+ color: var(--dark-font-color);
363
+
364
+ &:hover {
365
+ background: var(--light-background) !important;
366
+ }
367
+
368
+ .brand-logo {
369
+ height: 32px;
370
+ width: 32px;
371
+ }
372
+
373
+ .brand-text {
374
+ font-weight: 700;
375
+ }
376
+ }
377
+ }
378
+
379
+ // Navigation Dropdowns
380
+ .nav-dropdown {
381
+ position: relative;
382
+ }
383
+
384
+ .nav-dropdown__trigger {
385
+ display: inline-flex;
386
+ align-items: center;
387
+ gap: 0.4rem;
388
+ padding: 0.75rem 1.25rem;
389
+ margin: 0 0.25rem;
390
+ font-size: 1.2rem;
391
+ font-weight: 400;
392
+ font-family: inherit;
393
+ color: var(--font-color);
394
+ background: transparent;
395
+ border: 1px solid transparent;
396
+ border-radius: 0.35rem;
397
+ cursor: pointer;
398
+ transition: all 0.15s ease;
399
+
400
+ &:hover {
401
+ background: var(--light-background);
402
+ color: var(--dark-font-color);
403
+ }
404
+ }
405
+
406
+ .nav-dropdown__chevron {
407
+ transition: transform 0.2s ease;
408
+ opacity: 0.5;
409
+ }
410
+
411
+ .nav-dropdown.open .nav-dropdown__trigger {
412
+ background: var(--light-background);
413
+ color: var(--dark-font-color);
414
+ }
415
+
416
+ .nav-dropdown.open .nav-dropdown__chevron {
417
+ transform: rotate(180deg);
418
+ }
419
+
420
+ .nav-dropdown__menu {
421
+ position: absolute;
422
+ top: calc(100% + 4px);
423
+ left: 50%;
424
+ transform: translateX(-50%) translateY(4px);
425
+ min-width: 200px;
426
+ padding: 8px;
427
+ background: color-mix(in srgb, var(--background) 70%, transparent);
428
+ backdrop-filter: blur(12px);
429
+ -webkit-backdrop-filter: blur(12px);
430
+ border: 1px solid var(--light-background);
431
+ border-radius: 12px;
432
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
433
+ opacity: 0;
434
+ visibility: hidden;
435
+ transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s;
436
+ z-index: 100;
437
+
438
+ &::before {
439
+ content: "";
440
+ position: absolute;
441
+ top: -12px;
442
+ left: 0;
443
+ right: 0;
444
+ height: 12px;
445
+ }
446
+
447
+ a {
448
+ display: flex;
449
+ align-items: center;
450
+ gap: 0.5rem;
451
+ padding: 0.625rem 0.875rem;
452
+ margin: 0;
453
+ font-size: 0.95rem;
454
+ font-weight: 500;
455
+ color: var(--font-color);
456
+ border-radius: 8px;
457
+ text-decoration: none;
458
+ transition: all 0.15s ease;
459
+
460
+ &:first-of-type {
461
+ margin-left: 0;
462
+ }
463
+
464
+ &:hover {
465
+ background: var(--light-background);
466
+ color: var(--accent-primary);
467
+ }
468
+
469
+ svg {
470
+ opacity: 0.5;
471
+ flex-shrink: 0;
472
+ }
473
+ }
474
+ }
475
+
476
+ .nav-dropdown.open .nav-dropdown__menu {
477
+ opacity: 1;
478
+ visibility: visible;
479
+ transform: translateX(-50%) translateY(0);
480
+ }
481
+ }
482
+ }
483
+
484
+ @media print {
485
+ .navbar {
486
+ display: none;
487
+ }
488
+ }
489
+
490
+ // Mobile Menu Button
491
+ .mobile-menu-button {
492
+ display: flex;
493
+ align-items: center;
494
+ justify-content: center;
495
+ width: 44px;
496
+ height: 44px;
497
+ border: none;
498
+ border-radius: 12px;
499
+ background: var(--light-background);
500
+ cursor: pointer;
501
+ transition: all 0.2s ease;
502
+ color: var(--font-color);
503
+
504
+ &:hover {
505
+ background: var(--light-background-hover);
506
+ }
507
+
508
+ &:active {
509
+ transform: scale(0.95);
510
+ }
511
+
512
+ .menu-icon {
513
+ display: block;
514
+ }
515
+
516
+ .close-icon {
517
+ display: none;
518
+ }
519
+
520
+ &[aria-expanded="true"] {
521
+ .menu-icon {
522
+ display: none;
523
+ }
524
+
525
+ .close-icon {
526
+ display: block;
527
+ }
528
+ }
529
+ }
530
+
531
+ @media screen and (min-width: 800px) {
532
+ .mobile-menu-button {
533
+ display: none;
534
+ }
535
+ }
536
+
537
+ // Mobile Menu Overlay
538
+ .mobile-menu-overlay {
539
+ position: fixed;
540
+ top: 0;
541
+ left: 0;
542
+ right: 0;
543
+ bottom: 0;
544
+ background: var(--background);
545
+ z-index: 9;
546
+ display: flex;
547
+ align-items: center;
548
+ justify-content: center;
549
+ opacity: 0;
550
+ visibility: hidden;
551
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
552
+
553
+ &.active {
554
+ opacity: 1;
555
+ visibility: visible;
556
+ }
557
+ }
558
+
559
+ .mobile-menu-content {
560
+ display: flex;
561
+ flex-direction: column;
562
+ align-items: center;
563
+ gap: 0.5rem;
564
+ transform: translateY(20px);
565
+ opacity: 0;
566
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
567
+ transition-delay: 0.1s;
568
+
569
+ .mobile-menu-overlay.active & {
570
+ transform: translateY(0);
571
+ opacity: 1;
572
+ }
573
+
574
+ a {
575
+ font-size: 1.5rem;
576
+ font-weight: 500;
577
+ color: var(--font-color);
578
+ padding: 1rem 2rem;
579
+ border-radius: 12px;
580
+ text-decoration: none;
581
+ transition: all 0.2s ease;
582
+ display: inline-flex;
583
+ align-items: center;
584
+ gap: 0.5rem;
585
+
586
+ &:hover {
587
+ background: var(--light-background);
588
+ color: var(--accent-primary);
589
+ }
590
+
591
+ svg {
592
+ opacity: 0.5;
593
+ flex-shrink: 0;
594
+ }
595
+ }
596
+
597
+ // Mobile navigation groups
598
+ .mobile-nav-group {
599
+ display: flex;
600
+ flex-direction: column;
601
+ align-items: center;
602
+ gap: 0.25rem;
603
+ margin: 0.75rem 0;
604
+ }
605
+
606
+ .mobile-nav-group__label {
607
+ font-size: 0.8rem;
608
+ font-weight: 600;
609
+ text-transform: uppercase;
610
+ letter-spacing: 0.1em;
611
+ color: var(--font-color);
612
+ opacity: 0.5;
613
+ margin-bottom: 0.25rem;
614
+ }
615
+
616
+ .mobile-nav-group a {
617
+ font-size: 1.25rem;
618
+ padding: 0.75rem 1.5rem;
619
+ }
620
+ }
621
+
622
+ @media screen and (min-width: 800px) {
623
+ .mobile-menu-overlay {
624
+ display: none;
625
+ }
626
+ }
627
+
628
+ // =============================================================================
629
+ // Theme Toggle (3-way: light/dark/auto)
630
+ // =============================================================================
631
+
632
+ .theme-toggle {
633
+ position: relative;
634
+ display: flex;
635
+ align-items: center;
636
+ justify-content: center;
637
+ width: 44px;
638
+ height: 44px;
639
+ border: none;
640
+ border-radius: 10px;
641
+ background: transparent;
642
+ cursor: pointer;
643
+ overflow: hidden;
644
+ transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
645
+
646
+ &:hover {
647
+ background: var(--light-background);
648
+ transform: scale(1.05);
649
+ }
650
+
651
+ &:active {
652
+ transform: scale(0.95);
653
+ }
654
+
655
+ &:focus-visible {
656
+ outline: none;
657
+ box-shadow: 0 0 0 3px rgba(136, 57, 239, 0.3);
658
+ }
659
+ }
660
+
661
+ .theme-toggle__icons {
662
+ position: relative;
663
+ width: 20px;
664
+ height: 20px;
665
+ }
666
+
667
+ .theme-toggle__sun,
668
+ .theme-toggle__moon,
669
+ .theme-toggle__auto {
670
+ position: absolute;
671
+ inset: 0;
672
+ display: flex;
673
+ align-items: center;
674
+ justify-content: center;
675
+ transition: all 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
676
+ opacity: 0;
677
+ transform: rotate(-90deg) scale(0.5);
678
+
679
+ svg {
680
+ width: 20px;
681
+ height: 20px;
682
+ stroke: currentColor;
683
+ stroke-width: 2;
684
+ stroke-linecap: round;
685
+ stroke-linejoin: round;
686
+ fill: none;
687
+ }
688
+ }
689
+
690
+ .theme-toggle__sun {
691
+ color: #fbbf24;
692
+ }
693
+
694
+ .theme-toggle__moon {
695
+ color: #818cf8;
696
+ }
697
+
698
+ .theme-toggle__auto {
699
+ color: var(--accent-primary);
700
+ opacity: 1;
701
+ transform: rotate(0deg) scale(1);
702
+ }
703
+
704
+ @keyframes bounce {
705
+ 0%, 100% { transform: scale(1); }
706
+ 25% { transform: scale(1.15); }
707
+ 50% { transform: scale(0.9); }
708
+ 75% { transform: scale(1.05); }
709
+ }
710
+
711
+ .theme-toggle.animating {
712
+ animation: bounce 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
713
+ }
714
+
715
+ @media screen and (min-width: 800px) {
716
+ .theme-toggle:not(.mobile-theme-toggle) {
717
+ width: 48px;
718
+ height: 48px;
719
+ border: 2px solid var(--border);
720
+ border-radius: 50%;
721
+ background: var(--light-background);
722
+
723
+ &:hover {
724
+ border-color: var(--accent-primary);
725
+ box-shadow: 0 0 0 4px rgba(136, 57, 239, 0.1);
726
+ }
727
+ }
728
+ }
729
+
730
+ // Mobile Theme Toggle
731
+ .mobile-theme-toggle {
732
+ display: flex;
733
+ align-items: center;
734
+ gap: 1rem;
735
+ margin-top: 0.5rem;
736
+ padding: 1rem 1.5rem;
737
+ width: auto;
738
+ height: auto;
739
+ border: 2px solid var(--border);
740
+ border-radius: 16px;
741
+ background: var(--light-background);
742
+
743
+ &:hover {
744
+ border-color: var(--accent-primary);
745
+ background: var(--light-background-hover);
746
+ transform: none;
747
+ }
748
+
749
+ .theme-toggle__icons {
750
+ width: 24px;
751
+ height: 24px;
752
+ }
753
+
754
+ .theme-toggle__sun svg,
755
+ .theme-toggle__moon svg,
756
+ .theme-toggle__auto svg {
757
+ width: 24px;
758
+ height: 24px;
759
+ }
760
+
761
+ .theme-label {
762
+ font-size: 1rem;
763
+ font-weight: 500;
764
+ color: var(--font-color);
765
+ }
766
+ }
767
+
768
+ // =============================================================================
769
+ // Search
770
+ // =============================================================================
771
+
772
+ .search-container {
773
+ position: relative;
774
+ margin-bottom: 3rem;
775
+ }
776
+
777
+ #search-query {
778
+ padding: 1rem 1.25rem;
779
+ padding-right: 140px;
780
+ background: var(--light-background);
781
+ color: var(--input-color);
782
+ border: 2px solid rgba(0, 0, 0, 0.08);
783
+ outline: none;
784
+ width: 100%;
785
+ border-radius: 12px;
786
+ font-size: 1rem;
787
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
788
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.02);
789
+
790
+ &:focus {
791
+ border-color: var(--accent-primary);
792
+ box-shadow: 0 4px 12px rgba(136, 57, 239, 0.08);
793
+ }
794
+
795
+ &::placeholder {
796
+ color: var(--font-color);
797
+ opacity: 0.5;
798
+ }
799
+ }
800
+
801
+ .search-shortcuts {
802
+ position: absolute;
803
+ right: 1rem;
804
+ top: 50%;
805
+ transform: translateY(-50%);
806
+ display: flex;
807
+ gap: 0.5rem;
808
+ pointer-events: none;
809
+
810
+ kbd {
811
+ padding: 0.35rem 0.6rem;
812
+ background: var(--background);
813
+ border: 1px solid rgba(0, 0, 0, 0.12);
814
+ border-radius: 6px;
815
+ font-family: var(--code-font-family);
816
+ font-size: 0.75rem;
817
+ font-weight: 500;
818
+ color: var(--font-color);
819
+ opacity: 0.6;
820
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
821
+ }
822
+ }
823
+
824
+ // Search Toggle Button
825
+ .search-toggle {
826
+ display: flex;
827
+ align-items: center;
828
+ justify-content: center;
829
+ width: 44px;
830
+ height: 44px;
831
+ padding: 0;
832
+ background: transparent;
833
+ border: none;
834
+ color: var(--font-color);
835
+ border-radius: 10px;
836
+ cursor: pointer;
837
+ transition: all 0.2s ease;
838
+
839
+ svg {
840
+ width: 20px;
841
+ height: 20px;
842
+ }
843
+
844
+ &:hover {
845
+ background: var(--light-background);
846
+ color: var(--dark-font-color);
847
+ }
848
+ }
849
+
850
+ @media screen and (min-width: 800px) {
851
+ .search-toggle:not(.mobile-search-toggle) {
852
+ width: 48px;
853
+ height: 48px;
854
+ border: 2px solid var(--border);
855
+ border-radius: 50%;
856
+ background: var(--light-background);
857
+
858
+ &:hover {
859
+ border-color: var(--accent-primary);
860
+ transform: scale(1.05);
861
+ }
862
+ }
863
+ }
864
+
865
+ // Mobile Search Toggle
866
+ .mobile-search-toggle {
867
+ display: flex;
868
+ align-items: center;
869
+ gap: 1rem;
870
+ margin-top: 2rem;
871
+ padding: 1rem 1.5rem;
872
+ width: auto;
873
+ height: auto;
874
+ border: 2px solid var(--border);
875
+ border-radius: 16px;
876
+ background: var(--light-background);
877
+
878
+ &:hover {
879
+ border-color: var(--accent-primary);
880
+ background: var(--light-background-hover);
881
+ transform: none;
882
+ }
883
+
884
+ svg {
885
+ width: 24px;
886
+ height: 24px;
887
+ }
888
+
889
+ .search-label {
890
+ font-size: 1rem;
891
+ font-weight: 500;
892
+ color: var(--font-color);
893
+ }
894
+ }
895
+
896
+ // Search Overlay Modal
897
+ .search-overlay {
898
+ position: fixed;
899
+ inset: 0;
900
+ background: rgba(0, 0, 0, 0.7);
901
+ backdrop-filter: blur(8px);
902
+ display: flex;
903
+ align-items: flex-start;
904
+ justify-content: center;
905
+ padding: 10vh 1rem 1rem;
906
+ opacity: 0;
907
+ visibility: hidden;
908
+ transition: all 0.3s ease;
909
+ z-index: 1000;
910
+
911
+ &.open {
912
+ opacity: 1;
913
+ visibility: visible;
914
+ }
915
+ }
916
+
917
+ .search {
918
+ width: 100%;
919
+ max-width: 600px;
920
+ background: var(--background);
921
+ border: 1px solid var(--border);
922
+ border-radius: 16px;
923
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
924
+ overflow: hidden;
925
+ transform: translateY(-20px) scale(0.95);
926
+ transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
927
+
928
+ .search-overlay.open & {
929
+ transform: translateY(0) scale(1);
930
+ }
931
+ }
932
+
933
+ .search__input-wrapper {
934
+ display: flex;
935
+ align-items: center;
936
+ padding: 1rem 1.25rem;
937
+ border-bottom: 1px solid var(--border);
938
+ }
939
+
940
+ .search__icon {
941
+ flex-shrink: 0;
942
+ margin-right: 0.75rem;
943
+ color: var(--font-color);
944
+ opacity: 0.5;
945
+
946
+ svg {
947
+ width: 20px;
948
+ height: 20px;
949
+ }
950
+ }
951
+
952
+ .search__input {
953
+ flex: 1;
954
+ font-size: 1rem;
955
+ background: none;
956
+ border: none;
957
+ color: var(--font-color);
958
+ outline: none;
959
+
960
+ &::placeholder {
961
+ color: var(--font-color);
962
+ opacity: 0.5;
963
+ }
964
+ }
965
+
966
+ .search__shortcut {
967
+ display: none;
968
+ padding: 0.25rem 0.5rem;
969
+ font-family: var(--code-font-family);
970
+ font-size: 0.75rem;
971
+ color: var(--font-color);
972
+ opacity: 0.5;
973
+ background: var(--light-background);
974
+ border: 1px solid var(--border);
975
+ border-radius: 4px;
976
+
977
+ @media (min-width: 768px) {
978
+ display: block;
979
+ }
980
+ }
981
+
982
+ .search__close {
983
+ display: flex;
984
+ align-items: center;
985
+ justify-content: center;
986
+ width: 32px;
987
+ height: 32px;
988
+ margin-left: 0.5rem;
989
+ color: var(--font-color);
990
+ opacity: 0.5;
991
+ background: transparent;
992
+ border: none;
993
+ border-radius: 6px;
994
+ cursor: pointer;
995
+ transition: all 0.2s ease;
996
+
997
+ svg {
998
+ width: 18px;
999
+ height: 18px;
1000
+ }
1001
+
1002
+ &:hover {
1003
+ background: var(--light-background);
1004
+ opacity: 1;
1005
+ }
1006
+ }
1007
+
1008
+ .search__results {
1009
+ max-height: 60vh;
1010
+ overflow-y: auto;
1011
+ }
1012
+
1013
+ .search__result {
1014
+ display: block;
1015
+ padding: 1rem 1.25rem;
1016
+ color: var(--font-color);
1017
+ text-decoration: none;
1018
+ transition: background 0.15s ease;
1019
+
1020
+ &:hover {
1021
+ background: var(--light-background);
1022
+ }
1023
+
1024
+ &.selected {
1025
+ background: rgba(136, 57, 239, 0.1);
1026
+ }
1027
+ }
1028
+
1029
+ .search__result-title {
1030
+ font-weight: 600;
1031
+ margin-bottom: 0.25rem;
1032
+
1033
+ mark {
1034
+ background: rgba(249, 226, 175, 0.4);
1035
+ color: inherit;
1036
+ padding: 0 0.15em;
1037
+ border-radius: 2px;
1038
+ }
1039
+ }
1040
+
1041
+ .search__result-path {
1042
+ font-size: 0.875rem;
1043
+ color: var(--font-color);
1044
+ opacity: 0.6;
1045
+ }
1046
+
1047
+ .search__result-preview {
1048
+ font-size: 0.875rem;
1049
+ color: var(--font-color);
1050
+ opacity: 0.8;
1051
+ margin-top: 0.5rem;
1052
+ line-height: 1.5;
1053
+
1054
+ mark {
1055
+ background: rgba(249, 226, 175, 0.3);
1056
+ color: inherit;
1057
+ padding: 0 0.1em;
1058
+ border-radius: 2px;
1059
+ }
1060
+ }
1061
+
1062
+ .search__no-results {
1063
+ padding: 2rem 1.25rem;
1064
+ text-align: center;
1065
+ color: var(--font-color);
1066
+ opacity: 0.6;
1067
+ }
1068
+
1069
+ .search__footer {
1070
+ display: flex;
1071
+ align-items: center;
1072
+ justify-content: space-between;
1073
+ padding: 0.75rem 1.25rem;
1074
+ border-top: 1px solid var(--border);
1075
+ font-size: 0.75rem;
1076
+ color: var(--font-color);
1077
+ opacity: 0.5;
1078
+ }
1079
+
1080
+ .search__hints {
1081
+ display: flex;
1082
+ gap: 1rem;
1083
+ }
1084
+
1085
+ .search__hint {
1086
+ display: flex;
1087
+ align-items: center;
1088
+ gap: 0.4rem;
1089
+
1090
+ kbd {
1091
+ padding: 0.15rem 0.4rem;
1092
+ font-size: 0.65rem;
1093
+ background: var(--light-background);
1094
+ border: 1px solid var(--border);
1095
+ border-radius: 3px;
1096
+ }
1097
+ }
1098
+
1099
+ // =============================================================================
1100
+ // Homepage
1101
+ // =============================================================================
1102
+
1103
+ .hero {
1104
+ margin: 3rem 0;
1105
+ padding-bottom: 2.5rem;
1106
+ border-bottom: none;
1107
+
1108
+ p {
1109
+ font-size: 1.25rem;
1110
+ line-height: 1.6;
1111
+ margin-bottom: 0.75rem;
1112
+ color: var(--font-color);
1113
+ max-width: 800px;
1114
+ font-weight: 400;
1115
+
1116
+ &:first-of-type {
1117
+ font-weight: 600;
1118
+ color: var(--heading-color);
1119
+ }
1120
+ }
1121
+
1122
+ .hero-meta {
1123
+ margin-top: 2rem;
1124
+ display: flex;
1125
+ flex-direction: column;
1126
+ gap: 1.25rem;
1127
+ align-items: flex-start;
1128
+
1129
+ .speaking-badge {
1130
+ font-size: 0.95rem;
1131
+ color: var(--font-color);
1132
+ margin: 0;
1133
+
1134
+ strong {
1135
+ color: var(--accent-primary);
1136
+ font-weight: 600;
1137
+ }
1138
+ }
1139
+
1140
+ .bio-social {
1141
+ display: flex;
1142
+ gap: 1rem;
1143
+
1144
+ a {
1145
+ color: var(--font-color);
1146
+ transition: all 0.2s ease;
1147
+ opacity: 0.8;
1148
+ border: none;
1149
+
1150
+ &:hover {
1151
+ color: var(--accent-primary);
1152
+ opacity: 1;
1153
+ transform: translateY(-2px);
1154
+ }
1155
+ }
1156
+ }
1157
+ }
1158
+ }
1159
+
1160
+ @media screen and (min-width: 800px) {
1161
+ .hero {
1162
+ margin: 4rem 0 3rem;
1163
+
1164
+ p {
1165
+ font-size: 1.4rem;
1166
+ }
1167
+
1168
+ .hero-meta {
1169
+ flex-direction: column;
1170
+ align-items: flex-start;
1171
+ gap: 1.5rem;
1172
+ margin-top: 2.5rem;
1173
+
1174
+ .speaking-badge {
1175
+ font-size: 1rem;
1176
+ }
1177
+
1178
+ .bio-social {
1179
+ gap: 1.5rem;
1180
+ }
1181
+ }
1182
+ }
1183
+ }
1184
+
1185
+ .view-all-link {
1186
+ display: inline-block;
1187
+ margin-top: 2rem;
1188
+ padding: 0.75rem 1.5rem;
1189
+ font-weight: 500;
1190
+ text-decoration: none;
1191
+ color: var(--accent-primary);
1192
+ background: var(--light-background);
1193
+ border-radius: 999px;
1194
+ border: none;
1195
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
1196
+
1197
+ &:hover {
1198
+ background: var(--accent-primary);
1199
+ color: var(--background);
1200
+ transform: translateY(-2px);
1201
+ box-shadow: 0 4px 12px rgba(136, 57, 239, 0.15);
1202
+ }
1203
+ }
1204
+
1205
+ // =============================================================================
1206
+ // Posts List
1207
+ // =============================================================================
1208
+
1209
+ .post-row {
1210
+ display: flex;
1211
+ align-items: center;
1212
+ width: 100%;
1213
+
1214
+ time {
1215
+ display: block;
1216
+ flex: 0 0 100px;
1217
+ font-size: 0.85rem;
1218
+ color: var(--font-color);
1219
+ opacity: 0.7;
1220
+ font-variant-numeric: tabular-nums;
1221
+ }
1222
+
1223
+ h3 {
1224
+ flex: 1;
1225
+ }
1226
+ }
1227
+
1228
+ .posts .post:last-of-type a {
1229
+ border-bottom-width: 0;
1230
+ }
1231
+
1232
+ .post {
1233
+ a {
1234
+ display: flex;
1235
+ flex-direction: column;
1236
+ padding: 1rem 0;
1237
+ border-bottom: 1px solid rgba(0, 0, 0, 0.04);
1238
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
1239
+ border: none;
1240
+
1241
+ &:hover {
1242
+ transform: translateX(4px);
1243
+ }
1244
+ }
1245
+
1246
+ h3 {
1247
+ margin-top: 0;
1248
+ margin-bottom: 0;
1249
+ font-size: 1.05rem;
1250
+ font-weight: 500;
1251
+ color: var(--heading-color);
1252
+ }
1253
+ }
1254
+
1255
+ @media screen and (min-width: 800px) {
1256
+ .posts {
1257
+ margin-left: -1rem;
1258
+ margin-right: -1rem;
1259
+ }
1260
+
1261
+ .post {
1262
+ a {
1263
+ padding: 1.25rem 1rem;
1264
+ border-bottom-color: rgba(0, 0, 0, 0.04);
1265
+ border-radius: 12px;
1266
+
1267
+ &:hover {
1268
+ background: var(--light-background);
1269
+ border-bottom-color: transparent;
1270
+ }
1271
+ }
1272
+
1273
+ h3 {
1274
+ font-size: 1.2rem;
1275
+ }
1276
+ }
1277
+
1278
+ .post-row time {
1279
+ flex: 0 0 110px;
1280
+ font-size: 0.9rem;
1281
+ }
1282
+ }
1283
+
1284
+ // Tags
1285
+ .post-tags {
1286
+ display: flex;
1287
+ gap: 0.5rem;
1288
+ margin-top: 0.5rem;
1289
+ flex-wrap: wrap;
1290
+ }
1291
+
1292
+ .tag {
1293
+ display: inline-block;
1294
+ padding: 0.35rem 0.85rem;
1295
+ font-size: 0.75rem;
1296
+ font-weight: 500;
1297
+ background: var(--light-background);
1298
+ border: none;
1299
+ border-radius: 999px;
1300
+ color: var(--font-color);
1301
+ text-decoration: none;
1302
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
1303
+ opacity: 0.85;
1304
+
1305
+ &:hover {
1306
+ background: var(--accent-primary);
1307
+ color: var(--background);
1308
+ opacity: 1;
1309
+ transform: translateY(-1px);
1310
+ }
1311
+ }
1312
+
1313
+ // =============================================================================
1314
+ // Article/Page Styles
1315
+ // =============================================================================
1316
+
1317
+ header {
1318
+ padding: 1.5rem 0;
1319
+
1320
+ h1 {
1321
+ font-size: 2rem;
1322
+ display: inline-block;
1323
+ font-weight: 600;
1324
+ margin-top: 1rem;
1325
+ }
1326
+
1327
+ u {
1328
+ display: inline-block;
1329
+ text-decoration: none;
1330
+ padding: 0.4rem 0;
1331
+ }
1332
+ }
1333
+
1334
+ .article-header {
1335
+ padding-top: 2rem;
1336
+ margin-bottom: 0.5rem;
1337
+
1338
+ .container {
1339
+ padding-left: 0;
1340
+ padding-right: 0;
1341
+ }
1342
+
1343
+ .thumb {
1344
+ display: flex;
1345
+ flex-direction: column;
1346
+ }
1347
+
1348
+ h1 {
1349
+ font-weight: 700;
1350
+ font-size: 1.8rem;
1351
+ margin: 0;
1352
+ }
1353
+
1354
+ .description {
1355
+ font-size: 1.2rem;
1356
+ color: var(--light-font-color);
1357
+ font-weight: 300;
1358
+ margin-top: 2rem;
1359
+ margin-bottom: 0;
1360
+ }
1361
+ }
1362
+
1363
+ .post-meta {
1364
+ margin-top: 1rem;
1365
+ padding: 0;
1366
+ color: var(--light-font-color);
1367
+ font-size: 0.9rem;
1368
+
1369
+ a {
1370
+ color: var(--font-color);
1371
+ border-width: 0;
1372
+ }
1373
+
1374
+ time {
1375
+ margin-top: 0.2rem;
1376
+ font-size: 0.9rem;
1377
+ }
1378
+
1379
+ .meta-line {
1380
+ display: flex;
1381
+ align-items: center;
1382
+ gap: 0.5rem;
1383
+ font-size: 0.9rem;
1384
+
1385
+ .author {
1386
+ font-weight: 600;
1387
+ }
1388
+
1389
+ .separator {
1390
+ opacity: 0.5;
1391
+ }
1392
+
1393
+ .reading-time {
1394
+ font-family: var(--code-font-family);
1395
+ font-size: 0.85rem;
1396
+ }
1397
+ }
1398
+
1399
+ .article-taxonomies {
1400
+ margin-top: 1rem;
1401
+ display: flex;
1402
+ gap: 1rem;
1403
+ flex-wrap: wrap;
1404
+ align-items: center;
1405
+ }
1406
+
1407
+ .tags {
1408
+ display: flex;
1409
+ gap: 0.5rem;
1410
+ flex-wrap: wrap;
1411
+
1412
+ a {
1413
+ text-decoration: none;
1414
+ }
1415
+ }
1416
+
1417
+ .series-badge {
1418
+ font-size: 0.85rem;
1419
+ font-weight: 600;
1420
+
1421
+ a {
1422
+ text-decoration: none;
1423
+ color: var(--link-color);
1424
+
1425
+ &:hover {
1426
+ text-decoration: underline;
1427
+ }
1428
+ }
1429
+ }
1430
+ }
1431
+
1432
+ .article-post {
1433
+ margin-bottom: 2rem;
1434
+ font-family: var(--article-font-family);
1435
+
1436
+ img {
1437
+ border-radius: 5px;
1438
+ display: block;
1439
+ margin-left: auto;
1440
+ margin-right: auto;
1441
+ }
1442
+
1443
+ a {
1444
+ box-shadow: 0px -2px 0px var(--accent-secondary) inset;
1445
+ transition: all 0.3s ease;
1446
+ border: none;
1447
+
1448
+ &:hover {
1449
+ box-shadow: 0px -10px 0px var(--accent-secondary) inset;
1450
+ }
1451
+ }
1452
+
1453
+ code {
1454
+ overflow-x: auto;
1455
+ }
1456
+
1457
+ h1, h2, h3, h4, h5, h6 {
1458
+ position: relative;
1459
+
1460
+ .anchor {
1461
+ position: absolute;
1462
+ left: -2.5rem;
1463
+ top: 50%;
1464
+ transform: translateY(-50%);
1465
+ color: var(--accent-primary);
1466
+ font-weight: 600;
1467
+ text-decoration: none;
1468
+ opacity: 0;
1469
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
1470
+ padding: 0.25rem 0.5rem;
1471
+ border-radius: 6px;
1472
+ font-size: 0.9em;
1473
+ border: none;
1474
+
1475
+ &::before {
1476
+ content: "#";
1477
+ }
1478
+
1479
+ &:hover {
1480
+ background: var(--light-background);
1481
+ opacity: 1 !important;
1482
+ }
1483
+ }
1484
+
1485
+ &:hover {
1486
+ .anchor {
1487
+ opacity: 0.6;
1488
+ }
1489
+ }
1490
+ }
1491
+
1492
+ .highlight {
1493
+ position: relative;
1494
+ }
1495
+ }
1496
+
1497
+ @media screen and (min-width: 800px) {
1498
+ .article-post {
1499
+ margin-bottom: 3rem;
1500
+ }
1501
+
1502
+ .article-post h1,
1503
+ .article-post h2,
1504
+ .article-post h3,
1505
+ .article-post h4,
1506
+ .article-post h5 {
1507
+ padding-top: 1rem;
1508
+ }
1509
+
1510
+ .post-meta {
1511
+ margin-top: 0.5rem;
1512
+ padding: 0.5rem 0;
1513
+ }
1514
+
1515
+ header h1 {
1516
+ font-size: 3rem;
1517
+ margin-top: 2rem;
1518
+ }
1519
+
1520
+ header u {
1521
+ background: linear-gradient(transparent 85%, #bac8ff 0);
1522
+ }
1523
+
1524
+ .article-header {
1525
+ padding-top: 3rem;
1526
+
1527
+ h1 {
1528
+ padding-top: 0;
1529
+ font-size: 2.5rem;
1530
+ }
1531
+
1532
+ .thumb {
1533
+ flex-direction: row;
1534
+ }
1535
+
1536
+ .description {
1537
+ font-size: 1.8rem;
1538
+ line-height: 1.5;
1539
+ }
1540
+ }
1541
+ }
1542
+
1543
+ .post-thumbnail {
1544
+ display: block !important;
1545
+ width: 100%;
1546
+ height: auto;
1547
+ margin: 1.5rem 0;
1548
+ border-radius: 8px;
1549
+ }
1550
+
1551
+ // =============================================================================
1552
+ // Suggested/Navigation
1553
+ // =============================================================================
1554
+
1555
+ .suggested {
1556
+ display: flex;
1557
+ flex-direction: column;
1558
+ gap: 1rem;
1559
+ margin: 3rem 0;
1560
+ padding: 0;
1561
+
1562
+ a {
1563
+ display: block;
1564
+ padding: 1rem;
1565
+ background: var(--light-background);
1566
+ border-radius: 8px;
1567
+ text-decoration: none;
1568
+ transition: all 0.2s ease;
1569
+ border: none;
1570
+
1571
+ span {
1572
+ font-size: 0.85rem;
1573
+ color: var(--light-font-color);
1574
+ }
1575
+
1576
+ strong {
1577
+ display: block;
1578
+ margin-top: 0.25rem;
1579
+ color: var(--heading-color);
1580
+ font-weight: 600;
1581
+ }
1582
+
1583
+ &:hover {
1584
+ background: var(--light-background-hover);
1585
+ transform: translateY(-2px);
1586
+ }
1587
+ }
1588
+
1589
+ @media screen and (min-width: 600px) {
1590
+ flex-direction: row;
1591
+ justify-content: space-between;
1592
+
1593
+ a {
1594
+ flex: 1;
1595
+ max-width: 48%;
1596
+ }
1597
+ }
1598
+ }
1599
+
1600
+ // =============================================================================
1601
+ // Footer
1602
+ // =============================================================================
1603
+
1604
+ .footer {
1605
+ margin-top: 4rem;
1606
+ padding: 2rem 0;
1607
+ border-top: none;
1608
+ background: transparent;
1609
+
1610
+ .container {
1611
+ display: flex;
1612
+ justify-content: center;
1613
+ }
1614
+
1615
+ .footer-links {
1616
+ display: flex;
1617
+ gap: 1.5rem;
1618
+
1619
+ a {
1620
+ color: var(--light-font-color);
1621
+ font-size: 0.9rem;
1622
+ font-weight: 500;
1623
+ text-decoration: none;
1624
+ border: none;
1625
+
1626
+ &:hover {
1627
+ color: var(--accent-primary);
1628
+ }
1629
+ }
1630
+ }
1631
+ }
1632
+
1633
+ // =============================================================================
1634
+ // Helpers
1635
+ // =============================================================================
1636
+
1637
+ .sr-only {
1638
+ position: absolute;
1639
+ width: 1px;
1640
+ height: 1px;
1641
+ padding: 0;
1642
+ margin: -1px;
1643
+ overflow: hidden;
1644
+ clip: rect(0, 0, 0, 0);
1645
+ white-space: nowrap;
1646
+ border-width: 0;
1647
+ }
1648
+
1649
+ .skip-link {
1650
+ position: absolute;
1651
+ top: -40px;
1652
+ left: 0;
1653
+ background: var(--accent-primary);
1654
+ color: white;
1655
+ padding: 8px;
1656
+ z-index: 100;
1657
+ transition: top 0.3s;
1658
+
1659
+ &:focus {
1660
+ top: 0;
1661
+ }
1662
+ }
1663
+ }
1664
+
1665
+ // =============================================================================
1666
+ // Theme Toggle States (must be at root level, not inside mode selector)
1667
+ // =============================================================================
1668
+
1669
+ [data-theme-setting="light"] .theme-toggle {
1670
+ .theme-toggle__auto {
1671
+ opacity: 0;
1672
+ transform: rotate(-90deg) scale(0.5);
1673
+ }
1674
+ .theme-toggle__sun {
1675
+ opacity: 1;
1676
+ transform: rotate(0deg) scale(1);
1677
+ }
1678
+ }
1679
+
1680
+ [data-theme-setting="dark"] .theme-toggle {
1681
+ .theme-toggle__auto {
1682
+ opacity: 0;
1683
+ transform: rotate(-90deg) scale(0.5);
1684
+ }
1685
+ .theme-toggle__moon {
1686
+ opacity: 1;
1687
+ transform: rotate(0deg) scale(1);
1688
+ }
1689
+ }
1690
+
1691
+ [data-theme-setting="auto"] .theme-toggle {
1692
+ .theme-toggle__auto {
1693
+ opacity: 1;
1694
+ transform: rotate(0deg) scale(1);
1695
+ }
1696
+ }