kiku-agent 1.0.11 → 1.2.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 (221) hide show
  1. package/README.md +300 -495
  2. package/package.json +12 -11
  3. package/public/fonts/GoogleSans-Bold.ttf +0 -0
  4. package/public/fonts/GoogleSans-Bold.woff2 +0 -0
  5. package/public/fonts/GoogleSans-BoldItalic.ttf +0 -0
  6. package/public/fonts/GoogleSans-Italic.ttf +0 -0
  7. package/public/fonts/GoogleSans-Latin-400.woff2 +0 -0
  8. package/public/fonts/GoogleSans-Latin-500.woff2 +0 -0
  9. package/public/fonts/GoogleSans-Latin-600.woff2 +0 -0
  10. package/public/fonts/GoogleSans-Latin-700.woff2 +0 -0
  11. package/public/fonts/GoogleSans-Medium.ttf +0 -0
  12. package/public/fonts/GoogleSans-Medium.woff2 +0 -0
  13. package/public/fonts/GoogleSans-Regular.ttf +0 -0
  14. package/public/fonts/GoogleSans-Regular.woff2 +0 -0
  15. package/public/fonts/GoogleSans-Thai-400.woff2 +0 -0
  16. package/public/fonts/GoogleSans-Thai-500.woff2 +0 -0
  17. package/public/fonts/GoogleSans-Thai-600.woff2 +0 -0
  18. package/public/fonts/GoogleSans-Thai-700.woff2 +0 -0
  19. package/public/fonts/NotoSansThai-Bold.woff2 +0 -0
  20. package/public/fonts/NotoSansThai-Regular.woff2 +0 -0
  21. package/public/fonts/google-sans-official.css +900 -0
  22. package/public/images/0040jbadgy1id6am4yxqfj61s82dn1kx02.jpg +0 -0
  23. package/public/images/0040jbadgy1id6am708pbj62c0340qv602.jpg +0 -0
  24. package/public/images/0040jbadgy1id6amb81uqj62c0340x6q02.jpg +0 -0
  25. package/public/images/0040jbadgy1id6amcqte3j62c0340qv602.jpg +0 -0
  26. package/public/images/0040jbadgy1id6amdg3xcj62b232wqv502.jpg +0 -0
  27. package/public/images/0040jbadgy1id6amexv23j620v2pau0x02.jpg +0 -0
  28. package/public/images/0040jbadly8icq3if7twwj60qy0qy0uc02.jpg +0 -0
  29. package/public/images/008ET7Legy1ig9s89nri5j30i20n1gn4.jpg +0 -0
  30. package/public/images/008ET7Legy1ig9s8a2lmlj30i20ny409.jpg +0 -0
  31. package/public/images/008ET7Legy1ig9s8ay1hsj30i20nk3zv.jpg +0 -0
  32. package/public/images/008ET7Legy1ig9s8bab6sj30i20o7go1.jpg +0 -0
  33. package/public/images/008ET7Legy1ig9s8blqsxj30i20oiq4r.jpg +0 -0
  34. package/public/images/008ET7Legy1ig9s8cbxkzj30i20mxmzh.jpg +0 -0
  35. package/public/images/douyin-update/thumbs//346/212/226/351/237/2632026820-399915.jpg +0 -0
  36. package/public/images/douyin-update/thumbs//346/212/226/351/237/2632026820-424041.jpg +0 -0
  37. package/public/images/douyin-update/thumbs//346/212/226/351/237/2632026820-588166.jpg +0 -0
  38. package/public/images/douyin-update/thumbs//346/212/226/351/237/2632026820-672198.jpg +0 -0
  39. package/public/images/douyin-update/thumbs//346/212/226/351/237/2632026820-700522.jpg +0 -0
  40. package/public/images/douyin-update/thumbs//346/212/226/351/237/2632026820-839722.jpg +0 -0
  41. package/public/images/douyin-update/thumbs//346/212/226/351/237/2632026825-460586.jpg +0 -0
  42. package/public/images/douyin-update/thumbs//346/212/226/351/237/263202694-689407.jpg +0 -0
  43. package/public/images/douyin-update//346/212/226/351/237/2632026820-399915.mp4 +0 -0
  44. package/public/images/douyin-update//346/212/226/351/237/2632026820-424041.mp4 +0 -0
  45. package/public/images/douyin-update//346/212/226/351/237/2632026820-588166.mp4 +0 -0
  46. package/public/images/douyin-update//346/212/226/351/237/2632026820-672198.mp4 +0 -0
  47. package/public/images/douyin-update//346/212/226/351/237/2632026820-700522.mp4 +0 -0
  48. package/public/images/douyin-update//346/212/226/351/237/2632026820-839722.mp4 +0 -0
  49. package/public/images/douyin-update//346/212/226/351/237/2632026825-460586.mp4 +0 -0
  50. package/public/images/douyin-update//346/212/226/351/237/263202694-689407.mp4 +0 -0
  51. package/public/images/general/0040jbadgy1id6am4yxqfj61s82dn1kx02.jpg +0 -0
  52. package/public/images/general/0040jbadgy1id6am708pbj62c0340qv602.jpg +0 -0
  53. package/public/images/general/0040jbadgy1id6amb81uqj62c0340x6q02.jpg +0 -0
  54. package/public/images/general/0040jbadgy1id6amcqte3j62c0340qv602.jpg +0 -0
  55. package/public/images/general/0040jbadgy1id6amdg3xcj62b232wqv502.jpg +0 -0
  56. package/public/images/general/0040jbadgy1id6amexv23j620v2pau0x02.jpg +0 -0
  57. package/public/images/general/0040jbadly8icq3if7twwj60qy0qy0uc02.jpg +0 -0
  58. package/public/images/general/008ET7Legy1ig9s89nri5j30i20n1gn4.jpg +0 -0
  59. package/public/images/general/008ET7Legy1ig9s8a2lmlj30i20ny409.jpg +0 -0
  60. package/public/images/general/008ET7Legy1ig9s8ay1hsj30i20nk3zv.jpg +0 -0
  61. package/public/images/general/008ET7Legy1ig9s8bab6sj30i20o7go1.jpg +0 -0
  62. package/public/images/general/008ET7Legy1ig9s8blqsxj30i20oiq4r.jpg +0 -0
  63. package/public/images/general/008ET7Legy1ig9s8cbxkzj30i20mxmzh.jpg +0 -0
  64. package/public/images/general/jujingyi_portrait.jpg +0 -0
  65. package/public/images/jujingyi_portrait.jpg +0 -0
  66. package/public/images/series/a-millenniums-wait/poster.jpg +0 -0
  67. package/public/images/series/beauty-of-resilience/poster.jpg +0 -0
  68. package/public/images/series/detective-samoyeds/poster.jpg +0 -0
  69. package/public/images/series/everyday/poster.jpg +0 -0
  70. package/public/images/series/fu-rong-ancient-painting/poster.jpg +0 -0
  71. package/public/images/series/in-a-class-of-her-own/poster.jpg +0 -0
  72. package/public/images/series/in-blossom/poster.jpg +0 -0
  73. package/public/images/series/legend-of-yunxi/poster.jpg +0 -0
  74. package/public/images/series/lets-fight/poster-2.jpg +0 -0
  75. package/public/images/series/lets-fight/poster.jpg +0 -0
  76. package/public/images/series/love-emergency/poster.jpg +0 -0
  77. package/public/images/series/love-under-the-full-moon/poster.jpg +0 -0
  78. package/public/images/series/money-bastion/poster.jpg +0 -0
  79. package/public/images/series/mr-swimmer/poster.jpg +0 -0
  80. package/public/images/series/novoland-castle-in-the-sky/poster.jpg +0 -0
  81. package/public/images/series/please-give-me-a-pair-of-wings/poster.jpg +0 -0
  82. package/public/images/series/rebirth-for-you/poster.jpg +0 -0
  83. package/public/images/series/sword-and-fairy-4/poster.jpg +0 -0
  84. package/public/images/series/the-blooms-at-ruyi-pavilion/poster.jpg +0 -0
  85. package/public/images/series/the-eternal-fragrance/poster-2.jpg +0 -0
  86. package/public/images/series/the-eternal-fragrance/poster.jpg +0 -0
  87. package/public/images/series/the-fallen-flowers/poster.jpg +0 -0
  88. package/public/images/series/the-legend-of-white-snake/poster.jpg +0 -0
  89. package/public/images/series/veil-of-shadows/poster.jpg +0 -0
  90. package/public/images/series/wanhua-sin/poster-2.jpg +0 -0
  91. package/public/images/series/wanhua-sin/poster.jpg +0 -0
  92. package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkj10yogj62u03s0npe02.jpg +0 -0
  93. package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkj2pdvyj61li25jkjl02.jpg +0 -0
  94. package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkj71177j62672w9e8302.jpg +0 -0
  95. package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkj7twpfj62192197rw02.jpg +0 -0
  96. package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkj8jfu8j62c03401kx02.jpg +0 -0
  97. package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkj9dhdsj622k2l77wh02.jpg +0 -0
  98. package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkja31s4j62bw3407r802.jpg +0 -0
  99. package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkjcf331j61402ey1kx02.jpg +0 -0
  100. package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkjdx8gqj62602pihdt02.jpg +0 -0
  101. package/public/images/weibo-update/41/345/210/206/351/222/237/345/211/215/0040jbadgy1igrkjfvxnzj62432n57wh02.jpg +0 -0
  102. package/public/images/weibo-update/8-14-17-16/0040jbadgy1ig3ixniv2yj627y4fxb2b02.jpg +0 -0
  103. package/public/images/weibo-update/8-14-17-16/0040jbadgy1ig3ixsvbdaj625k2vfu1102.jpg +0 -0
  104. package/public/images/weibo-update/8-14-17-16/0040jbadgy1ig3ixxxdaoj62c03501l202.jpg +0 -0
  105. package/public/images/weibo-update/8-14-17-16/0040jbadgy1ig3ixzeef9j62c0340npd02.jpg +0 -0
  106. package/public/images/weibo-update/8-14-17-16/0040jbadgy1ig3iy0vs6tj626t4rbhdu02.jpg +0 -0
  107. package/public/images/weibo-update/8-14-17-16/0040jbadgy1ig3iy21wwuj62bt34hx6q02.jpg +0 -0
  108. package/public/images/weibo-update/8-8-17-39/0040jbadgy1ifwly4wr85j62z629y7wh02.jpg +0 -0
  109. package/public/images/weibo-update/8-8-17-39/0040jbadgy1ifwly67oilj623u2t5npd02.jpg +0 -0
  110. package/public/images/weibo-update/8-8-17-39/0040jbadgy1ifwly9qtw8j62c0340u0x02.jpg +0 -0
  111. package/public/images/weibo-update/8-8-17-39/0040jbadgy1ifwlyem4m4j63402c01kz02.jpg +0 -0
  112. package/public/images/weibo-update/8-8-17-39/0040jbadgy1ifwlygkoq4j627s2yeavd02.jpg +0 -0
  113. package/public/images/weibo-update/8-8-17-39/0040jbadgy1ifwlyjh0daj62bw340nm102.jpg +0 -0
  114. package/public/images/weibo-update/8-8-17-39/0040jbadgy1ifwlylejlhj62bw3401kx02.jpg +0 -0
  115. package/public/images/weibo-update/today/0040jbadgy1igaiaa8b7fj627j2y67wh02.jpg +0 -0
  116. package/public/images/weibo-update/today/0040jbadgy1igaiagw3ezj61s02ebu0x02.jpg +0 -0
  117. package/public/images/weibo-update/today/0040jbadgy1igaiaivng3j61rv2ebx6p02.jpg +0 -0
  118. package/public/images/weibo-update/today/0040jbadgy1igaiajuixvj62bw340qv502.jpg +0 -0
  119. package/public/images/weibo-update/today/0040jbadgy1igaiapyartj62bw340hdt02.jpg +0 -0
  120. package/public/images/weibo-update/today/0040jbadgy1igaibkwu4ij61vy2iq1kx02.jpg +0 -0
  121. package/public/images/weibo-update/today/0040jbadgy1igaic1fvkpj61u92eo1ky02.jpg +0 -0
  122. package/public/images/weibo-update/today/0040jbadgy1igaic3cruhj62822ywb2902.jpg +0 -0
  123. package/public/manifest.json +25 -0
  124. package/public/mcp-logo-128.png +0 -0
  125. package/public/mcp-logo-64.png +0 -0
  126. package/public/mcp-logo.svg +16 -0
  127. package/server/agent/agentCore.js +542 -74
  128. package/server/agent/appPaths.js +1 -0
  129. package/server/agent/audioPlayer.js +4 -2
  130. package/server/agent/citations.js +294 -0
  131. package/server/agent/clarificationAnalytics.js +477 -0
  132. package/server/agent/clarifyingQuestions.js +1089 -0
  133. package/server/agent/cli.js +549 -125
  134. package/server/agent/commandFeatures.js +1 -0
  135. package/server/agent/commandRegistry.js +946 -879
  136. package/server/agent/commands.js +546 -272
  137. package/server/agent/config.js +581 -412
  138. package/server/agent/contextCompactor.js +2 -2
  139. package/server/agent/debate.js +235 -0
  140. package/server/agent/eventBus.js +3 -0
  141. package/server/agent/feedbackLearning.js +217 -0
  142. package/server/agent/llmClient.js +512 -394
  143. package/server/agent/mcpClient.js +182 -32
  144. package/server/agent/memory.js +283 -224
  145. package/server/agent/modelManager.js +79 -39
  146. package/server/agent/profiles.js +178 -0
  147. package/server/agent/publicTools.js +22 -0
  148. package/server/agent/queryDetails.js +68 -8
  149. package/server/agent/quizData.js +398 -384
  150. package/server/agent/research.js +121 -79
  151. package/server/agent/sanitizer.js +104 -13
  152. package/server/agent/session.js +319 -11
  153. package/server/agent/subagent.js +8 -3
  154. package/server/agent/suggestionTui.js +294 -0
  155. package/server/agent/suggestions.js +69 -3
  156. package/server/agent/telemetry.js +119 -0
  157. package/server/agent/terminalImage.js +146 -27
  158. package/server/agent/theme.js +17 -0
  159. package/server/agent/toolRouter.js +16 -1
  160. package/server/agent/tools.js +424 -225
  161. package/server/agent/ui.js +486 -64
  162. package/server/agent/version.js +2 -4
  163. package/server/agent/webSearch.js +111 -11
  164. package/server/agent/youtubeAuth.js +24 -6
  165. package/server/apiRouter.js +4222 -0
  166. package/server/mcp/data/discography.js +25 -16
  167. package/server/mcp/data/gallery.js +308 -20
  168. package/server/mcp/data/profile.js +74 -44
  169. package/server/mcp/data/timeline.js +1 -1
  170. package/server/mcp/data/works.js +51 -17
  171. package/server/mcp/dataAdapter.js +5 -3
  172. package/server/mcp/handler.js +5 -11
  173. package/server/mcp/prompts.js +86 -0
  174. package/server/mcp/security.js +18 -15
  175. package/server/mcp/server.js +7 -2
  176. package/server/mcp/tools.js +66 -2
  177. package/server/web-chat/core/browserLauncher.js +18 -0
  178. package/server/web-chat/core/connection.js +194 -0
  179. package/server/web-chat/core/conversationContext.js +82 -0
  180. package/server/web-chat/core/directCatalogEngine.js +196 -0
  181. package/server/web-chat/core/dramaKnowledge.js +142 -0
  182. package/server/web-chat/core/errorHandler.js +51 -0
  183. package/server/web-chat/core/followUpEngine.js +182 -0
  184. package/server/web-chat/core/futureEventGuard.js +80 -0
  185. package/server/web-chat/core/memorySnapshot.js +12 -0
  186. package/server/web-chat/core/security.js +146 -0
  187. package/server/web-chat/core/toolInspector.js +52 -0
  188. package/server/web-chat/router.js +120 -0
  189. package/server/web-chat/routes/chatRoute.js +397 -0
  190. package/server/web-chat/routes/clarifyConfigRoute.js +98 -0
  191. package/server/web-chat/routes/clarifyRoute.js +83 -0
  192. package/server/web-chat/routes/compareRoute.js +79 -0
  193. package/server/web-chat/routes/exportRoute.js +59 -0
  194. package/server/web-chat/routes/feedbackRoute.js +57 -0
  195. package/server/web-chat/routes/newsRoute.js +33 -0
  196. package/server/web-chat/routes/quizRoute.js +11 -0
  197. package/server/web-chat/routes/staticRoute.js +103 -0
  198. package/server/web-chat/routes/statusRoute.js +52 -0
  199. package/server/web-chat/routes/suggestRoute.js +77 -0
  200. package/server/web-chat/routes/timelineRoute.js +34 -0
  201. package/server/web-chat/routes/verifyRoute.js +57 -0
  202. package/server/web-chat/server.js +116 -0
  203. package/server/web-chat/ui/htmlBuilder.js +91 -0
  204. package/server/web-chat/ui/previews/agentBubble.preview.html +134 -0
  205. package/server/web-chat/ui/scripts/agentBubbleSystem.js +320 -0
  206. package/server/web-chat/ui/scripts/client.js +8397 -0
  207. package/server/web-chat/ui/scripts/kikuDb.js +177 -0
  208. package/server/web-chat/ui/scripts/suggestionsData.js +118 -0
  209. package/server/web-chat/ui/scripts/webchatI18n.js +291 -0
  210. package/server/web-chat/ui/styles/main.css +8568 -0
  211. package/server/web-chat/ui/templates/body.html +796 -0
  212. package/server/webChatHtml.js +1 -0
  213. package/server/webChatServer.js +6 -0
  214. package/src/data/discographyData.js +892 -866
  215. package/src/data/galleryData.js +1805 -561
  216. package/src/data/profileData.js +79 -2
  217. package/src/data/socialUpdatesData.js +106 -47
  218. package/src/data/timelineData.js +1 -1
  219. package/src/data/worksData.js +25 -4
  220. package/tokens.css +97 -0
  221. package/server/agent/updateManager.js +0 -456
@@ -0,0 +1,796 @@
1
+ <div class="ambient-glow aura-1"></div>
2
+ <div class="ambient-glow aura-2"></div>
3
+ <canvas id="petal-canvas" aria-hidden="true"></canvas>
4
+ <button type="button" class="sidebar-backdrop" id="sidebar-backdrop" onclick="toggleAppSidebar(false)" aria-label="ปิดแถบเมนู"></button>
5
+
6
+ <aside class="app-sidebar" id="app-sidebar" aria-label="KIKU AGENT navigation">
7
+ <div class="sidebar-brand-row">
8
+ <button type="button" class="sidebar-brand" onclick="createNewChatSession()" aria-label="KIKU AGENT — เริ่มแชทใหม่">
9
+ <span class="brand-spark"><svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="m12 3 2.8 5.7 6.2.9-4.5 4.4 1.1 6.2L12 17.3 6.4 20.2l1.1-6.2-4.5-4.4 6.2-.9z"/></svg></span>
10
+ <span class="brand-text">
11
+ <strong class="brand-name-wrap">KIKU AGENT</strong>
12
+ </span>
13
+ </button>
14
+ <button type="button" class="sidebar-icon-button sidebar-collapse-button" id="btn-sidebar-collapse" onclick="toggleAppSidebar()" title="ย่อ/ขยายแถบเมนู" aria-label="ย่อ/ขยายแถบเมนู" aria-expanded="true">
15
+ <svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="4" y1="6" x2="20" y2="6"/><line x1="4" y1="12" x2="20" y2="12"/><line x1="4" y1="18" x2="20" y2="18"/></svg>
16
+ </button>
17
+ </div>
18
+
19
+ <div class="sidebar-scroll-region">
20
+ <nav class="sidebar-nav" aria-label="เครื่องมือหลักและการสำรวจ">
21
+ <div class="sidebar-section-heading static">
22
+ <span data-sidebar-i18n="exploreHeading">Explore &amp; Features</span>
23
+ </div>
24
+ <button type="button" class="sidebar-nav-item" onclick="openSessionsModal()" title="ค้นหาประวัติการสนทนา">
25
+ <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.4-3.4"/></svg>
26
+ <span data-sidebar-i18n="search">Search Chat</span>
27
+ </button>
28
+ <button type="button" class="sidebar-nav-item" id="sidebar-music-button" onclick="openMusicModal()" title="คลังเพลงและ Jukebox">
29
+ <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18V5l12-2v13"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="16" r="3"/></svg>
30
+ <span data-sidebar-i18n="music">Music Jukebox</span>
31
+ </button>
32
+ <button type="button" class="sidebar-nav-item" onclick="openQuizModal()" title="เกมทายปัญหาแฟนคลับ">
33
+ <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 9H4.5a2.5 2.5 0 0 1 0-5H6"/><path d="M18 9h1.5a2.5 2.5 0 0 0 0-5H18"/><path d="M4 22h16"/><path d="M10 14.66V17c0 .55-.45 1-1 1H7.5a1.5 1.5 0 0 0 0 3h9a1.5 1.5 0 0 0 0-3H15c-.55 0-1-.45-1-1v-2.34"/><path d="M18 4H6v7a6 6 0 0 0 12 0V4Z"/></svg>
34
+ <span data-sidebar-i18n="quiz">Fan Quiz Challenge</span>
35
+ </button>
36
+ <button type="button" class="sidebar-nav-item" onclick="renderTimelineModal()" title="ไทม์ไลน์เส้นทางอาชีพ">
37
+ <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="20" x2="12" y2="4"/><polyline points="6 10 12 4 18 10"/><line x1="4" y1="20" x2="20" y2="20"/></svg>
38
+ <span data-sidebar-i18n="timeline">Career Timeline</span>
39
+ </button>
40
+ <button type="button" class="sidebar-nav-item" onclick="toggleSuggestionsDrawer()" title="หัวข้อคำถามแนะนำ">
41
+ <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z"/></svg>
42
+ <span data-sidebar-i18n="prompts">Suggested Prompts</span>
43
+ </button>
44
+ <button type="button" class="sidebar-nav-item" onclick="toggleSavedPrompts()" title="พรอมต์ที่บันทึกไว้">
45
+ <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"/></svg>
46
+ <span data-sidebar-i18n="saved">Saved Prompts</span>
47
+ </button>
48
+ <button type="button" class="sidebar-nav-item" onclick="openSponsorsModal()" title="ผู้สนับสนุนโครงการ (Sponsors & Ads)">
49
+ <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="8" r="7"/><polyline points="8.21 13.89 7 23 12 20 17 23 15.79 13.88"/></svg>
50
+ <span data-sidebar-i18n="sponsors">Sponsors &amp; Ads</span>
51
+ </button>
52
+ </nav>
53
+
54
+ <section class="sidebar-section sidebar-history" aria-labelledby="history-section-title">
55
+ <div class="sidebar-section-heading static">
56
+ <span id="history-section-title" data-sidebar-i18n="history">Chats</span>
57
+ <button type="button" onclick="openSessionsModal()" title="ดูประวัติทั้งหมด" aria-label="ดูประวัติทั้งหมด">
58
+ <svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 8v4l3 2"/><circle cx="12" cy="12" r="9"/></svg>
59
+ </button>
60
+ </div>
61
+ <div class="sidebar-session-list" id="sidebar-session-list" aria-live="polite"></div>
62
+ <div class="sidebar-empty-chat-state" id="sidebar-empty-chat-state">
63
+ <div class="empty-state-circle"></div>
64
+ <div class="empty-state-title" data-sidebar-i18n="emptyTitle">No chat history</div>
65
+ <div class="empty-state-sub" data-sidebar-i18n="emptySub">Type a message to start a new chat...</div>
66
+ </div>
67
+ </section>
68
+
69
+ <!-- Sponsor Spotlight Section (Matching Kiku CLI Ads) -->
70
+ <section class="sidebar-section sidebar-sponsors" aria-label="ผู้สนับสนุนโครงการ">
71
+ <div class="sidebar-section-heading static" style="display:flex; justify-content:space-between; align-items:center;">
72
+ <span style="display:flex; align-items:center; gap:6px; font-weight:700; font-size:11px; letter-spacing:0.04em;">
73
+ <span style="color:#f472b6;">📢</span>
74
+ <span data-sidebar-i18n="sponsorsHeading">Sponsor Spotlight</span>
75
+ </span>
76
+ <div style="display:flex; gap:4px; align-items:center;">
77
+ <button type="button" class="btn-sidebar-heading-action" onclick="cycleSidebarAd(event)" title="หมุนเวียนโฆษณา (Next Sponsor)" aria-label="หมุนเวียนโฆษณา">
78
+ <svg aria-hidden="true" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21.5 2v6h-6M21.34 15.57a10 10 0 1 1-.57-8.38l5.67-5.67"/></svg>
79
+ </button>
80
+ <button type="button" class="btn-sidebar-heading-action" onclick="openSponsorsModal(event)" title="ดูผู้สนับสนุนทั้งหมด" aria-label="ดูผู้สนับสนุนทั้งหมด">
81
+ <svg aria-hidden="true" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>
82
+ </button>
83
+ </div>
84
+ </div>
85
+ <div class="sidebar-ad-card" id="sidebar-ad-card" onclick="openSponsorsModal(event)" onkeydown="if(event.key==='Enter'||event.key===' '){openSponsorsModal(event);}" role="button" tabindex="0" title="คลิกเพื่อดูรายละเอียดผู้สนับสนุนทั้งหมด">
86
+ <!-- Dynamically populated by renderSidebarAd() -->
87
+ </div>
88
+ </section>
89
+
90
+ <section class="sidebar-section sidebar-controls" aria-label="การตั้งค่าและระบบ">
91
+ <div class="sidebar-section-heading static">
92
+ <span data-sidebar-i18n="controlsHeading">System Controls</span>
93
+ </div>
94
+ <button type="button" class="sidebar-nav-item" onclick="exportChat()" title="ส่งออกบทสนทนาเป็นไฟล์ Markdown">
95
+ <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
96
+ <span data-sidebar-i18n="export">Export Chat</span>
97
+ </button>
98
+ <button type="button" class="sidebar-nav-item" onclick="togglePetals()" title="เปิด/ปิด กลีบดอกซากุระ">
99
+ <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M12 2a4 4 0 0 0-4 4c0 3 4 5 4 5s4-2 4-5a4 4 0 0 0-4-4Z"/><path d="M12 22a4 4 0 0 0 4-4c0-3-4-5-4-5s-4 2-4 5a4 4 0 0 0 4 4Z"/><path d="M2 12a4 4 0 0 0 4 4c3 0 5-4 5-4s-2-4-5-4a4 4 0 0 0-4 4Z"/><path d="M22 12a4 4 0 0 0-4-4c-3 0-5 4-5 4s2 4 5 4a4 4 0 0 0 4-4Z"/></svg>
100
+ <span id="sidebar-petals-label" data-sidebar-i18n="petals">Sakura Petals</span>
101
+ </button>
102
+ <button type="button" class="sidebar-nav-item" onclick="toggleTheme()" title="สลับโหมด กลางวัน / กลางคืน">
103
+ <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/></svg>
104
+ <span id="sidebar-theme-label" data-sidebar-i18n="theme">Theme Mode</span>
105
+ </button>
106
+ <button type="button" class="sidebar-nav-item" onclick="toggleSound()" title="เปิด/ปิด เสียงเอฟเฟกต์">
107
+ <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M15.54 8.46a5 5 0 0 1 0 7.07"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/></svg>
108
+ <span id="sidebar-sound-label" data-sidebar-i18n="sound">Sound FX</span>
109
+ </button>
110
+ <button type="button" class="sidebar-nav-item" onclick="cycleLanguage()" title="เปลี่ยนภาษา (TH / 中文 / EN)">
111
+ <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
112
+ <span id="sidebar-lang-label" data-sidebar-i18n="lang">Language (TH)</span>
113
+ </button>
114
+ </section>
115
+ </div>
116
+ </aside>
117
+
118
+ <header class="workspace-toolbar">
119
+ <div class="toolbar-leading">
120
+ <button type="button" class="toolbar-sidebar-button" id="toolbar-sidebar-button" onclick="toggleAppSidebar()" title="เปิด/ปิดแถบเมนู (Sidebar)" aria-label="เปิดแถบเมนู" aria-expanded="false">
121
+ <svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="4" y1="6" x2="20" y2="6"/><line x1="4" y1="12" x2="20" y2="12"/><line x1="4" y1="18" x2="20" y2="18"/></svg>
122
+ </button>
123
+ </div>
124
+ </header>
125
+
126
+ <div class="settings-drawer" id="settings-drawer">
127
+ <div class="settings-container">
128
+ <div class="settings-header-row">
129
+ <div class="settings-title-group">
130
+ <span class="settings-title-icon">⚙️</span>
131
+ <div>
132
+ <h4 class="settings-title">AI Engine &amp; Model Configuration</h4>
133
+ <p class="settings-subtitle">กำหนดค่า AI Provider, Model ID, และพารามิเตอร์การประมวลผล</p>
134
+ </div>
135
+ </div>
136
+ <div class="settings-status-pill" id="settings-status-pill">
137
+ <span class="status-dot-pulse"></span>
138
+ <span id="settings-provider-badge">LM Studio (Local)</span>
139
+ </div>
140
+ </div>
141
+
142
+ <div class="settings-grid-cards">
143
+
144
+ <div class="settings-card">
145
+ <div class="settings-card-label">
146
+ <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>
147
+ <span>โมเดลและผู้ให้บริการ (AI Provider &amp; Model)</span>
148
+ </div>
149
+ <div class="settings-card-body">
150
+ <div class="form-group">
151
+ <label for="cfg-provider" id="lbl-cfg-provider">AI Provider</label>
152
+ <div class="form-control-wrap">
153
+ <select id="cfg-provider" class="form-control" onchange="onProviderChange()">
154
+ <option value="lmstudio">LM Studio (Local gemma-4-e4b / Qwen)</option>
155
+ <option value="gemini">Google Gemini (Gemini 3.7 Flash / Pro)</option>
156
+ <option value="openai">OpenAI (GPT-4o / o1 / o3)</option>
157
+ <option value="groq">Groq (Llama 3.3 70B Fast)</option>
158
+ <option value="deepseek">DeepSeek AI (V3 / R1)</option>
159
+ <option value="openrouter">OpenRouter (Unified Gateway)</option>
160
+ </select>
161
+ </div>
162
+ </div>
163
+ <div class="form-group">
164
+ <label for="cfg-model" id="lbl-cfg-model">Model Name / ID</label>
165
+ <div class="form-control-wrap">
166
+ <input type="text" id="cfg-model" class="form-control" placeholder="google/gemma-4-e4b" value="google/gemma-4-e4b" onchange="autoSaveSettings()">
167
+ </div>
168
+ </div>
169
+ </div>
170
+ </div>
171
+
172
+ <div class="settings-card">
173
+ <div class="settings-card-label">
174
+ <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
175
+ <span>คีย์และการประมวลผล (Security &amp; Inference)</span>
176
+ </div>
177
+ <div class="settings-card-body">
178
+ <div class="form-group" id="group-cfg-apikey">
179
+ <label for="cfg-apikey" id="lbl-cfg-apikey">Cloud API Key</label>
180
+ <div class="form-control-wrap with-toggle">
181
+ <input type="password" id="cfg-apikey" class="form-control" placeholder="sk-... / AIza... (เว้นว่างหากใช้ LM Studio)" onchange="autoSaveSettings()">
182
+ <button type="button" id="btn-toggle-apikey-vis" class="btn-input-icon" onclick="toggleApiKeyVisibility()" title="แสดง/ซ่อน API Key">
183
+ <svg aria-hidden="true" id="eye-icon" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
184
+ </button>
185
+ </div>
186
+ <div id="cfg-apikey-help" class="form-help-text">🔒 ไม่จำเป็นต้องใส่หากใช้ Local LM Studio</div>
187
+ </div>
188
+
189
+ <div class="form-row-dual">
190
+ <div class="form-group" style="flex: 1;">
191
+ <label for="cfg-thinking" id="lbl-cfg-thinking">Thinking Mode</label>
192
+ <div class="form-control-wrap">
193
+ <select id="cfg-thinking" class="form-control" onchange="autoSaveSettings()">
194
+ <option value="show">แสดงทั้งหมด (Deep Thinking)</option>
195
+ <option value="collapse">ย่อเริ่มต้น (Auto Collapse)</option>
196
+ <option value="hide">ซ่อนทั้งหมด (Direct Answer)</option>
197
+ </select>
198
+ </div>
199
+ </div>
200
+ <div class="form-group" style="flex: 1;">
201
+ <div class="label-with-badge">
202
+ <label for="cfg-temperature" id="lbl-cfg-temp">Creativity</label>
203
+ <span class="temp-badge" id="temp-val">0.7</span>
204
+ </div>
205
+ <div class="form-control-wrap slider-wrap">
206
+ <input type="range" id="cfg-temperature" min="0" max="1" step="0.05" value="0.7" class="form-slider" oninput="document.getElementById('temp-val').textContent = this.value; autoSaveSettings();">
207
+ </div>
208
+ </div>
209
+ </div>
210
+ </div>
211
+ </div>
212
+ </div>
213
+ </div>
214
+ </div>
215
+
216
+ <main class="main-chat-workspace" id="main-chat-workspace">
217
+ <div class="main-inner">
218
+ <div id="chat-container">
219
+ <div class="welcome-hero" id="welcome-hero">
220
+ <section class="hero-media" aria-label="แกลเลอรีภาพจวีจิ้งอี">
221
+ <figure class="hero-media-frame hero-media-primary">
222
+ <img src="/images/0040jbadgy1id6am4yxqfj61s82dn1kx02.jpg" alt="จวีจิ้งอีในลุคชุดสีครีม" width="690" height="903" fetchpriority="high" decoding="async">
223
+ </figure>
224
+ <figure class="hero-media-frame hero-media-secondary">
225
+ <img src="/images/008ET7Legy1ig9s8bab6sj30i20o7go1.jpg" alt="ภาพพอร์ตเทรตจวีจิ้งอีกลางแสงธรรมชาติ" width="650" height="871" decoding="async">
226
+ </figure>
227
+ <figure class="hero-media-frame hero-media-poster">
228
+ <img src="/images/008ET7Legy1ig9s8cbxkzj30i20mxmzh.jpg" alt="โปสเตอร์ซีรีส์ In Blossom" width="1000" height="1778" decoding="async">
229
+ </figure>
230
+ <div class="hero-media-mark" aria-hidden="true">
231
+ <strong>JU JINGYI</strong>
232
+ <span>VISUAL ARCHIVE</span>
233
+ </div>
234
+ </section>
235
+
236
+ <div class="hero-copy">
237
+ <div class="hero-kicker"><span></span>KIKU AGENT</div>
238
+ <div class="hero-title-area">
239
+ <h2 class="hero-main-title">สวัสดีชาวมี่จวี (Miju)</h2>
240
+ <p id="hero-subtitle">วันนี้อยากร่วมเดินทางและค้นหาเรื่องราวของเสี่ยวจวีเรื่องไหนดี?</p>
241
+ </div>
242
+ <p class="hero-body" id="hero-body-text">ถามเรื่องผลงานซีรีส์ เพลงเพราะๆ สเตจในความทรงจำ หรือสวมบทบาทพูดคุยกับตัวละครโปรดได้เลย</p>
243
+ </div>
244
+ </div>
245
+ </div>
246
+
247
+ <button type="button" id="btn-scroll-bottom" class="btn-scroll-bottom" onclick="scrollToBottomSmooth(true)" title="เลื่อนลงล่างสุด">
248
+ <svg aria-hidden="true" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M19 12l-7 7-7-7"/></svg>
249
+ <span>เลื่อนลงล่างสุด</span>
250
+ </button>
251
+
252
+ <div class="suggestions-drawer" id="suggestions-drawer">
253
+ <div class="suggestions-header-bar">
254
+ <span class="suggestions-title">
255
+ <svg aria-hidden="true" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>
256
+ <span id="suggestions-title-text">หัวข้อคำถามแนะนำ</span>
257
+ </span>
258
+ <span class="suggestions-header-actions">
259
+ <button type="button" class="btn-ai-suggest" id="btn-ai-suggest" onclick="requestAiSuggestions()" title="ให้ KIKU AI สร้างคำถาม">
260
+ <span id="btn-ai-suggest-label">✨ AI สร้างคำถาม</span>
261
+ </button>
262
+ <button type="button" class="btn-toggle-drawer" onclick="toggleSuggestionsDrawer()">
263
+ <svg aria-hidden="true" width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
264
+ <span id="suggestions-close-label">ย่อเก็บ</span>
265
+ </button>
266
+ </span>
267
+ </div>
268
+ <div class="category-tabs" id="category-tabs"></div>
269
+ <div class="chips-container" id="chips-container"></div>
270
+ </div>
271
+
272
+ <div id="attachment-tray" class="attachment-tray" style="display: none;"></div>
273
+
274
+ <!-- Futuristic Glassmorphic Voice HUD (การรับฟังเสียง AI โฉมใหม่) -->
275
+ <div id="voice-hud" class="voice-hud luxury-voice-hud" style="display: none;" role="region" aria-label="อินเทอร์เฟซการรับฟังเสียง">
276
+ <div class="voice-hud-inner">
277
+ <!-- Top Row: Status, Dynamic Orb, Language Controls -->
278
+ <div class="voice-hud-header">
279
+ <div class="voice-hud-identity">
280
+ <div class="voice-live-orb" title="ไมโครโฟนทำงานอยู่">
281
+ <span class="voice-orb-ring ring-1"></span>
282
+ <span class="voice-orb-ring ring-2"></span>
283
+ <span class="voice-orb-core">
284
+ <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="23"/><line x1="8" y1="23" x2="16" y2="23"/></svg>
285
+ </span>
286
+ </div>
287
+ <div class="voice-identity-meta">
288
+ <div class="voice-identity-title-row">
289
+ <span class="voice-live-title">กำลังรับฟังเสียงสด...</span>
290
+ <span id="voice-lang-badge" class="voice-lang-badge" title="ภาษาที่ตรวจพบขณะนี้">🇹🇭 ภาษาไทย</span>
291
+ </div>
292
+ <span class="voice-live-sub">พูดคำถามหรือเรื่องที่ต้องการค้นหาเกี่ยวกับจวีจิ้งอี</span>
293
+ </div>
294
+ </div>
295
+
296
+ <!-- Language Pills Bar -->
297
+ <div class="voice-lang-pills">
298
+ <button type="button" class="voice-pill active" id="vpill-th" onclick="setVoiceRecognitionLang('th-TH')" title="ภาษาไทย">🇹🇭 ไทย</button>
299
+ <button type="button" class="voice-pill" id="vpill-zh" onclick="setVoiceRecognitionLang('zh-CN')" title="ภาษาจีน (中文)">🇨🇳 中文</button>
300
+ <button type="button" class="voice-pill" id="vpill-en" onclick="setVoiceRecognitionLang('en-US')" title="English">🇺🇸 EN</button>
301
+ </div>
302
+ </div>
303
+
304
+ <!-- Middle Row: Interactive Waveform Canvas + Live Transcript Bubble -->
305
+ <div class="voice-hud-body">
306
+ <div class="voice-visualizer-wrap">
307
+ <canvas id="voice-canvas" class="voice-canvas" width="540" height="42" aria-hidden="true"></canvas>
308
+ </div>
309
+
310
+ <div class="voice-transcript-card" id="voice-transcript-card">
311
+ <div class="voice-transcript-content">
312
+ <span id="voice-hud-text" class="voice-transcript-text">“กำลังรับฟังเสียงสด... กรุณาพูดคำถามของคุณ”</span>
313
+ <span class="voice-streaming-cursor" aria-hidden="true"></span>
314
+ </div>
315
+ </div>
316
+ </div>
317
+
318
+ <!-- Bottom Row: Quick Actions -->
319
+ <div class="voice-hud-footer">
320
+ <div class="voice-hud-hint">
321
+ <span class="voice-hint-bullet">●</span>
322
+ <span>พูดเสร็จแล้วคลิกนำไปใช้ หรือส่งคำถามทันที</span>
323
+ </div>
324
+
325
+ <div class="voice-hud-actions">
326
+ <button type="button" class="btn-voice-action btn-voice-discard" onclick="cancelSpeechRecognition()" title="ยกเลิกการบันทึกเสียง">
327
+ <svg aria-hidden="true" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
328
+ <span>ยกเลิก</span>
329
+ </button>
330
+
331
+ <button type="button" class="btn-voice-action btn-voice-finish" onclick="toggleSpeechRecognition()" title="เสร็จสิ้น นำข้อความลงในช่องพิมพ์">
332
+ <svg aria-hidden="true" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><polyline points="20 6 9 17 4 12"/></svg>
333
+ <span>นำไปใช้</span>
334
+ </button>
335
+
336
+ <button type="button" class="btn-voice-action btn-voice-send" id="btn-voice-send" onclick="sendVoiceQueryDirectly()" title="ส่งคำถามนี้ไปยัง AI ทันที">
337
+ <svg aria-hidden="true" width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><polygon points="6 3 20 12 6 21 6 3"/></svg>
338
+ <span>ส่งคำถามทันที</span>
339
+ </button>
340
+ </div>
341
+ </div>
342
+ </div>
343
+ </div>
344
+
345
+ <!-- Chat-Integrated Mini Player Dock (ผนวกเข้ากับ UX/UI ช่องแชท) -->
346
+ <aside id="mini-player-dock" class="mini-player-draggable-dock chat-integrated-dock" aria-label="Ju Jingyi Mini Player">
347
+ <div class="mini-player-card" id="mini-player-card">
348
+ <div class="mini-card-drag-bar" id="mini-player-drag-handle" title="แถบสถานะเครื่องเล่นเพลง" aria-label="สถานะเครื่องเล่นเพลง">
349
+ <div class="drag-bar-pill"></div>
350
+ </div>
351
+
352
+ <div class="mini-card-video-wrap" id="mini-card-video-wrap">
353
+ <div id="mini-player-video-frame-container"></div>
354
+ </div>
355
+
356
+ <div class="mini-card-horizontal-main">
357
+ <div class="mini-vinyl-art-wrap">
358
+ <div class="mini-vinyl-art-disc" id="mini-vinyl-art-disc">
359
+ <img id="mini-player-poster" class="mini-card-poster" src="https://img.youtube.com/vi/9AeErG03SZw/hqdefault.jpg" alt="Poster" onerror="this.onerror=null;this.src='https://img.youtube.com/vi/9AeErG03SZw/hqdefault.jpg';" />
360
+ <div class="mini-vinyl-center-pin"></div>
361
+ </div>
362
+ <div class="poster-glow-aura" id="mini-poster-glow"></div>
363
+ </div>
364
+
365
+ <div class="mini-card-details">
366
+ <div class="mini-card-top-meta">
367
+ <span class="mini-card-title-cn font-calligraphy" id="mini-player-title-cn">月鳞绮纪 · 不苦</span>
368
+ <span class="mini-card-badge">
369
+ <span class="sound-wave-equalizer" id="mini-player-equalizer" aria-hidden="true">
370
+ <span class="eq-bar eq-1"></span>
371
+ <span class="eq-bar eq-2"></span>
372
+ <span class="eq-bar eq-3"></span>
373
+ <span class="eq-bar eq-4"></span>
374
+ </span>
375
+ <span class="badge-text" id="mini-player-track-tag">Now Playing</span>
376
+ </span>
377
+ </div>
378
+ <div class="mini-card-title" id="mini-player-track-title">FIND THE WAY (2026)</div>
379
+ <div class="mini-card-artist" id="mini-player-track-artist">鞠婧祎 (Ju Jingyi)</div>
380
+ </div>
381
+
382
+ <div class="mini-card-actions">
383
+ <div class="mini-volume-control-wrap" id="mini-volume-wrap">
384
+ <button type="button" class="mini-card-btn-icon" id="btn-mini-vol" onclick="toggleMiniPlayerMute()" title="ปรับระดับเสียง" aria-label="ปรับระดับเสียง">
385
+ <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M15.54 8.46a5 5 0 0 1 0 7.07"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14"/></svg>
386
+ </button>
387
+ <div class="mini-volume-slider-popup" id="mini-volume-popup">
388
+ <input type="range" id="mini-player-volume-slider" min="0" max="100" value="100" oninput="setMiniPlayerVolume(this.value)" aria-label="Volume">
389
+ </div>
390
+ </div>
391
+ <button type="button" class="mini-card-btn-icon" id="btn-mini-video-toggle" onclick="toggleMiniPlayerVideo()" title="สลับดูวิดีโอ MV">
392
+ <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect width="20" height="15" x="2" y="5" rx="2"/><polygon points="10 9 15 12.5 10 16 10 9"/></svg>
393
+ </button>
394
+ <button type="button" class="mini-card-btn-icon" onclick="openMusicModal()" title="เปิดคลังเพลงทั้งหมด (46 บทเพลง)">
395
+ <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18V5l12-2v13"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="16" r="3"/></svg>
396
+ </button>
397
+ <button type="button" class="mini-card-btn-icon" onclick="setMiniPlayerExpanded(false)" title="ย่อขนาด">
398
+ <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="5" y1="12" x2="19" y2="12"/></svg>
399
+ </button>
400
+ <button type="button" class="mini-card-btn-icon" onclick="closeMiniPlayer()" title="ปิดเครื่องเล่น">
401
+ <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
402
+ </button>
403
+ </div>
404
+ </div>
405
+
406
+ <div class="mini-card-progress-section">
407
+ <span class="mini-time-text" id="mini-player-cur-time">0:00</span>
408
+ <div class="mini-progress-bar-bg" id="mini-player-progressbar" role="slider" aria-label="Playback progress" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" tabindex="0" onclick="seekMiniPlayerProgress(event)" onkeydown="seekMiniPlayer(event)">
409
+ <div class="mini-progress-bar-val" id="mini-player-progressbar-fill"></div>
410
+ <div class="mini-progress-thumb" id="mini-player-progressbar-thumb"></div>
411
+ </div>
412
+ <span class="mini-time-text" id="mini-player-dur-time">3:30</span>
413
+ </div>
414
+
415
+ <div class="mini-card-controls-row">
416
+ <button type="button" class="btn-mini-ctl" id="btn-mini-shuffle" onclick="toggleMiniPlayerShuffle()" title="สลับโหมดสุ่มเพลง">
417
+ <svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 3 21 3 21 8"/><line x1="4" y1="20" x2="21" y2="3"/><polyline points="21 16 21 21 16 21"/><line x1="15" y1="15" x2="21" y2="21"/><line x1="4" y1="4" x2="9" y2="9"/></svg>
418
+ </button>
419
+ <button type="button" class="btn-mini-ctl" onclick="prevMiniPlayerTrack()" title="เพลงก่อนหน้า">
420
+ <svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><polygon points="19 20 9 12 19 4 19 20"/><line x1="5" y1="19" x2="5" y2="5" stroke="currentColor" stroke-width="2"/></svg>
421
+ </button>
422
+ <button type="button" class="btn-mini-main-play" id="btn-mini-main-play" onclick="toggleMiniPlayerPlay()" title="เล่น/หยุด">
423
+ <span id="icon-mini-play"><svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><polygon points="6 3 20 12 6 21 6 3"/></svg></span>
424
+ <span id="icon-mini-pause" style="display:none;"><svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></svg></span>
425
+ </button>
426
+ <button type="button" class="btn-mini-ctl" onclick="nextMiniPlayerTrack()" title="เพลงถัดไป">
427
+ <svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 4 15 12 5 20 5 4"/><line x1="19" y1="5" x2="19" y2="19" stroke="currentColor" stroke-width="2"/></svg>
428
+ </button>
429
+ <button type="button" class="btn-mini-ctl" id="btn-mini-repeat" onclick="toggleMiniPlayerRepeat()" title="โหมดวนซ้ำ">
430
+ <svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg>
431
+ </button>
432
+ </div>
433
+ </div>
434
+
435
+ <button type="button" class="mini-player-disc-badge" id="btn-mini-disc" onclick="handleMiniDiscClick()" title="คลิกเพื่อขยายเครื่องเล่นเพลง">
436
+ <div class="mini-disc-graphic-wrap">
437
+ <span class="disc-radar-pulse" id="mini-disc-radar-pulse"></span>
438
+ <svg aria-hidden="true" class="mini-disc-progress-ring" viewBox="0 0 72 72">
439
+ <circle class="mini-disc-progress-bg" cx="36" cy="36" r="34"></circle>
440
+ <circle class="mini-disc-progress-val" id="mini-disc-progress-circle" cx="36" cy="36" r="34"></circle>
441
+ </svg>
442
+ <img id="mini-disc-thumb" class="mini-disc-thumb" src="https://img.youtube.com/vi/9AeErG03SZw/hqdefault.jpg" alt="Disc" onerror="this.onerror=null;this.src='https://img.youtube.com/vi/9AeErG03SZw/hqdefault.jpg';" />
443
+ <div class="mini-disc-overlay">
444
+ <span id="mini-disc-icon"><svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><polygon points="6 3 20 12 6 21 6 3"/></svg></span>
445
+ </div>
446
+ </div>
447
+ <div class="mini-disc-label-pill">
448
+ <span class="mini-disc-pill-title" id="mini-disc-pill-title">FIND THE WAY (2026)</span>
449
+ <span class="mini-disc-pill-hint">กำลังเล่นเพลง • คลิกเพื่อขยาย</span>
450
+ </div>
451
+ <div class="mini-disc-expand-icon">
452
+ <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>
453
+ </div>
454
+ </button>
455
+ </aside>
456
+
457
+ <div class="input-box" id="input-box-container">
458
+ <div class="input-box-top">
459
+ <textarea id="prompt-input" rows="1" placeholder="ถามอะไรเกี่ยวกับจวีจิ้งอีก็ได้... (กด Enter เพื่อส่ง, Shift + Enter เพื่อขึ้นบรรทัดใหม่)" onkeydown="handleInputKeyDown(event)" oninput="autoGrowTextarea(this)" aria-label="พิมพ์ข้อความถาม AI"></textarea>
460
+ </div>
461
+
462
+ <div class="input-box-bottom">
463
+ <div class="input-actions-left quick-actions-anchor">
464
+ <button type="button" id="btn-quick-actions" class="btn-quick-actions" title="เปิดเมนูเครื่องมือด่วน" onclick="toggleQuickActions()" aria-label="เปิดเมนูเครื่องมือด่วน" aria-expanded="false">
465
+ <span class="btn-quick-icon">
466
+ <svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
467
+ </span>
468
+ </button>
469
+ <div class="quick-action-menu" id="quick-action-menu" role="menu" aria-label="เครื่องมือด่วน">
470
+ <button type="button" role="menuitem" onclick="handleImageUpload(); closeQuickActions()"><span class="quick-item-icon"></span><span>แนบรูปภาพ / ไฟล์</span></button>
471
+ <button type="button" role="menuitem" onclick="toggleSpeechRecognition(); closeQuickActions()"><span class="quick-item-icon"></span><span>สั่งงานด้วยเสียง</span></button>
472
+ <button type="button" role="menuitem" onclick="openQuizModal(); closeQuickActions()"><span class="quick-item-icon"></span><span>Fan Quiz Challenge</span></button>
473
+ <button type="button" role="menuitem" onclick="openMusicModal(); closeQuickActions()"><span class="quick-item-icon"></span><span>คลังเพลง Jukebox</span></button>
474
+ </div>
475
+
476
+ <button type="button" id="btn-attach" class="btn-input-tool" title="แนบรูปภาพ" onclick="handleImageUpload()">
477
+ <svg aria-hidden="true" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg>
478
+ </button>
479
+ <button type="button" id="btn-mic" class="btn-input-tool btn-mic" title="สั่งงานด้วยเสียง" onclick="toggleSpeechRecognition()">
480
+ <svg aria-hidden="true" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="22"/></svg>
481
+ </button>
482
+ </div>
483
+
484
+ <div class="input-actions-right">
485
+ <button type="button" id="btn-stop" class="btn-stop" title="หยุดสร้างคำตอบ" onclick="stopGeneration()" aria-label="หยุดการสร้างคำตอบ">
486
+ <span class="btn-stop-icon">
487
+ <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><rect x="4" y="4" width="16" height="16" rx="3"/></svg>
488
+ </span>
489
+ </button>
490
+ <button type="button" id="btn-send" class="btn-send" title="ส่งข้อความ (Enter)" onclick="submitQuery()" aria-label="ส่งข้อความ">
491
+ <span class="btn-send-icon">
492
+ <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.3" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
493
+ </span>
494
+ </button>
495
+ </div>
496
+ </div>
497
+ </div>
498
+
499
+ <p class="input-disclaimer" id="input-disclaimer">🌸 Kiku Official Fan AI Assistant • ข้อมูลอาจมีความคลาดเคลื่อน โปรดอ้างอิงจากข้อมูลอย่างเป็นทางการ</p>
500
+ </div>
501
+ </main>
502
+
503
+ <div class="modal-backdrop" id="music-modal" role="dialog" aria-modal="true" tabindex="-1" onclick="if(event.target===this) closeMusicModal()" onkeydown="if(event.key==='Escape') closeMusicModal()">
504
+ <div class="modal-dialog jukebox-modal-dialog">
505
+ <div class="jukebox-header">
506
+ <h3>
507
+ <span class="svg-icon"></span>
508
+ <span>คลังเพลงจวีจิ้งอี (Ju Jingyi Jukebox)</span>
509
+ <span id="jukebox-song-count" style="font-size: 12px; font-weight: normal; color: var(--text-muted); margin-left: 8px;">44 บทเพลง</span>
510
+ </h3>
511
+ <div class="jukebox-header-actions">
512
+ <button type="button" class="btn-random-song" onclick="playRandomSongFromJukebox()" title="สุ่มเลือกบทเพลงมาฟัง">
513
+ <span></span>
514
+ <span>สุ่มเพลง</span>
515
+ </button>
516
+ <button type="button" class="btn-close-drawer" onclick="closeMusicModal()" title="ปิดหน้าต่าง">
517
+ <span style="font-size: 16px; font-weight: 700; line-height: 1;">✕</span>
518
+ </button>
519
+ </div>
520
+ </div>
521
+
522
+ <div class="jukebox-toolbar">
523
+ <div class="jukebox-search-box">
524
+ <span class="search-icon">
525
+ <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.4-3.4"/></svg>
526
+ </span>
527
+ <input type="text" id="music-search-input" placeholder="ค้นหาชื่อเพลง, ซีรีส์, หรือปีที่ปล่อย (เช่น In Blossom, 2026, 叹云兮, Everyday)..." oninput="filterJukeboxList(); if(typeof toggleMusicSearchClear==='function') toggleMusicSearchClear(this);" />
528
+ <button type="button" class="jukebox-search-clear" id="music-search-clear" onclick="clearMusicSearch()" title="ล้างการค้นหา">✕</button>
529
+ </div>
530
+ <div class="music-tabs">
531
+ <button type="button" class="music-tab-pill active" id="pill-music-all" onclick="setJukeboxCategory('all')">ทั้งหมด</button>
532
+ <button type="button" class="music-tab-pill" id="pill-music-new" onclick="setJukeboxCategory('new')"> New 2026-2024</button>
533
+ <button type="button" class="music-tab-pill" id="pill-music-ost" onclick="setJukeboxCategory('ost')"> เพลงซีรีส์ (OST)</button>
534
+ <button type="button" class="music-tab-pill" id="pill-music-single" onclick="setJukeboxCategory('single')"> ซิงเกิลเดี่ยว</button>
535
+ <button type="button" class="music-tab-pill" id="pill-music-stage" onclick="setJukeboxCategory('stage')"> สเตจพิเศษ</button>
536
+ </div>
537
+ </div>
538
+
539
+ <div class="jukebox-list-body" id="music-playlist-container">
540
+
541
+ </div>
542
+ </div>
543
+ </div>
544
+
545
+ <div class="modal-backdrop" id="quiz-modal" role="dialog" aria-modal="true" tabindex="-1" onclick="if(event.target===this) closeQuizModal()" onkeydown="if(event.key==='Escape') closeQuizModal()">
546
+ <div class="modal-dialog" style="max-width: 580px;">
547
+ <div class="modal-header">
548
+ <h3>
549
+ <span class="svg-icon"></span>
550
+ Ju Jingyi Trivia Quiz Challenge
551
+ </h3>
552
+ <button type="button" class="btn-close-drawer" onclick="closeQuizModal()">
553
+ <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
554
+ </button>
555
+ </div>
556
+ <div class="modal-body" id="quiz-modal-body">
557
+
558
+ </div>
559
+ </div>
560
+ </div>
561
+
562
+ <div class="modal-backdrop" id="sessions-modal" role="dialog" aria-modal="true" tabindex="-1" onclick="if(event.target===this) closeSessionsModal()" onkeydown="if(event.key==='Escape') closeSessionsModal()">
563
+ <div class="modal-dialog" style="max-width: 660px;">
564
+ <div class="modal-header">
565
+ <h3>
566
+ <svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.4-3.4"/></svg>
567
+ <span>ค้นหาประวัติการสนทนา (Search Chat History)</span>
568
+ </h3>
569
+ <button type="button" class="btn-close-drawer" onclick="closeSessionsModal()">
570
+ <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
571
+ </button>
572
+ </div>
573
+ <div class="modal-body" style="padding: 18px 22px;">
574
+ <div class="search-modal-box" style="margin-bottom: 14px; position: relative;">
575
+ <input type="text" id="sessions-search-input" class="form-control" style="width: 100%; padding-left: 38px; padding-right: 14px; border-radius: 12px; height: 42px; font-size: 13.5px;" placeholder="ค้นหาตามชื่อแชท หรือข้อความในบทสนทนา (เช่น In Blossom, Versace, 2026)..." oninput="filterSessions(this.value)">
576
+ <svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="position: absolute; left: 12px; top: 13px; color: var(--text-dim); pointer-events: none;"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.4-3.4"/></svg>
577
+ </div>
578
+
579
+ <div class="sessions-toolbar" style="display: flex; gap: 8px; margin-bottom: 14px; flex-wrap: wrap;">
580
+ <button type="button" class="btn-action" style="flex:1; justify-content:center;" onclick="createNewChatSession(); closeSessionsModal();">
581
+ <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
582
+ <span>สร้างแชทใหม่</span>
583
+ </button>
584
+ <button type="button" class="btn-action" style="justify-content:center;" onclick="exportChat()">
585
+ <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
586
+ <span>ส่งออกประวัติ</span>
587
+ </button>
588
+ <button type="button" class="btn-action" style="justify-content:center; color: #ef4444;" onclick="clearAllChatSessions()">
589
+ <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/></svg>
590
+ <span>ล้างทั้งหมด</span>
591
+ </button>
592
+ </div>
593
+
594
+ <div id="sessions-list-container" class="sessions-list" style="display: flex; flex-direction: column; gap: 10px; max-height: 48vh; overflow-y: auto;">
595
+ </div>
596
+ </div>
597
+ </div>
598
+ </div>
599
+
600
+ <div class="modal-backdrop" id="saved-prompts-modal" role="dialog" aria-modal="true" tabindex="-1" onclick="if(event.target===this) closeSavedPromptsModal()" onkeydown="if(event.key==='Escape') closeSavedPromptsModal()">
601
+ <div class="modal-dialog" style="max-width: 720px;">
602
+ <div class="modal-header">
603
+ <h3>
604
+ <svg aria-hidden="true" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"/></svg>
605
+ <span>คลังพรอมต์ &amp; บุ๊กมาร์ก (Saved Prompts &amp; Bookmarks)</span>
606
+ </h3>
607
+ <button type="button" class="btn-close-drawer" onclick="closeSavedPromptsModal()">
608
+ <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
609
+ </button>
610
+ </div>
611
+ <div class="modal-body" style="padding: 18px 22px;">
612
+ <div class="modal-tabs">
613
+ <button type="button" id="tab-btn-prompts" class="modal-tab-btn active" onclick="switchSavedPromptsTab('prompts')">
614
+ <svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"/></svg>
615
+ <span>คลังพรอมต์แม่แบบ (Prompt Library)</span>
616
+ </button>
617
+ <button type="button" id="tab-btn-bookmarks" class="modal-tab-btn" onclick="switchSavedPromptsTab('bookmarks')">
618
+ <svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="currentColor"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>
619
+ <span>คำตอบที่ปักหมุดไว้ (Bookmarked Answers)</span>
620
+ </button>
621
+ </div>
622
+
623
+ <div id="tab-content-prompts">
624
+ <div style="display: flex; gap: 8px; margin-bottom: 12px;">
625
+ <div style="flex: 1; position: relative;">
626
+ <input type="text" id="prompts-search-input" class="form-control" style="width: 100%; padding-left: 36px; border-radius: 10px; height: 38px; font-size: 13px;" placeholder="ค้นหาตามชื่อพรอมต์ หรือคีย์เวิร์ด..." oninput="filterSavedPrompts(this.value)">
627
+ <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="position: absolute; left: 11px; top: 12px; color: var(--text-dim); pointer-events: none;"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.4-3.4"/></svg>
628
+ </div>
629
+ <button type="button" class="btn-action" onclick="openCreatePromptModal()" style="background: rgba(255,117,140,0.18); border-color: var(--primary); color: var(--primary);">
630
+ <span>สร้างพรอมต์</span>
631
+ </button>
632
+ </div>
633
+ <div id="saved-prompts-list" style="display: flex; flex-direction: column; gap: 10px; max-height: 46vh; overflow-y: auto;">
634
+ </div>
635
+ </div>
636
+
637
+ <div id="tab-content-bookmarks" style="display: none;">
638
+ <div style="margin-bottom: 12px; position: relative;">
639
+ <input type="text" id="bookmarks-search-input" class="form-control" style="width: 100%; padding-left: 36px; border-radius: 10px; height: 38px; font-size: 13px;" placeholder="ค้นหาข้อความที่ปักหมุดไว้..." oninput="filterBookmarks(this.value)">
640
+ <svg aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="position: absolute; left: 11px; top: 12px; color: var(--text-dim); pointer-events: none;"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.4-3.4"/></svg>
641
+ </div>
642
+ <div id="bookmarks-list" style="display: flex; flex-direction: column; gap: 10px; max-height: 46vh; overflow-y: auto;">
643
+ </div>
644
+ </div>
645
+ </div>
646
+ </div>
647
+ </div>
648
+
649
+ <div class="modal-backdrop" id="create-prompt-modal" role="dialog" aria-modal="true" tabindex="-1" onclick="if(event.target===this) closeCreatePromptModal()" onkeydown="if(event.key==='Escape') closeCreatePromptModal()">
650
+ <div class="modal-dialog" style="max-width: 520px;">
651
+ <div class="modal-header">
652
+ <h3>
653
+ <span>➕ บันทึกพรอมต์ใหม่ (Create Saved Prompt)</span>
654
+ </h3>
655
+ <button type="button" class="btn-close-drawer" onclick="closeCreatePromptModal()">
656
+ <svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
657
+ </button>
658
+ </div>
659
+ <div class="modal-body" style="padding: 18px 20px;">
660
+ <div style="display: flex; flex-direction: column; gap: 12px;">
661
+ <div>
662
+ <label for="new-prompt-title" style="font-size: 12px; font-weight: 700; color: var(--text); margin-bottom: 4px; display: block;">ชื่อพรอมต์ (Prompt Title)</label>
663
+ <input type="text" id="new-prompt-title" class="form-control" style="width: 100%;" placeholder="เช่น วิเคราะห์บทบาทใน In Blossom...">
664
+ </div>
665
+ <div>
666
+ <label for="new-prompt-cat" style="font-size: 12px; font-weight: 700; color: var(--text); margin-bottom: 4px; display: block;">หมวดหมู่ (Category)</label>
667
+ <select id="new-prompt-cat" class="form-control" style="width: 100%;">
668
+ <option value="ซีรีส์ &amp; การแสดง"> ซีรีส์ &amp; การแสดง</option>
669
+ <option value="เพลง &amp; เวที"> เพลง &amp; เวที</option>
670
+ <option value="แฟชั่น &amp; แบรนด์"> แฟชั่น &amp; แบรนด์</option>
671
+ <option value="ประวัติ &amp; เกร็ดความรู้"> ประวัติ &amp; เกร็ดความรู้</option>
672
+ <option value="ทั่วไป"> ทั่วไป</option>
673
+ </select>
674
+ </div>
675
+ <div>
676
+ <label for="new-prompt-text" style="font-size: 12px; font-weight: 700; color: var(--text); margin-bottom: 4px; display: block;">ข้อความคำสั่ง (Prompt Text)</label>
677
+ <textarea id="new-prompt-text" class="form-control" rows="4" style="width: 100%; resize: vertical;" placeholder="พิมพ์ข้อความคำสั่งที่ต้องการให้ AI ตอบ..."></textarea>
678
+ </div>
679
+ <button type="button" class="btn-action" style="margin-top: 8px; justify-content: center; background: var(--primary); color: #fff; border: none; padding: 10px;" onclick="saveNewCustomPrompt()">
680
+ <span>💾 บันทึกพรอมต์</span>
681
+ </button>
682
+ </div>
683
+ </div>
684
+ </div>
685
+ </div>
686
+
687
+ <!-- Spotlight Command Palette (Ctrl+K / Cmd+K) -->
688
+ <div class="command-palette-backdrop" id="command-palette-modal" onclick="handleCommandPaletteBackdrop(event)" onkeydown="if(event.key==='Escape') closeCommandPalette()" style="display:none;" role="dialog" aria-modal="true" aria-label="Command Palette" tabindex="-1">
689
+ <div class="command-palette-box">
690
+ <div class="command-palette-header">
691
+ <svg aria-hidden="true" class="command-palette-search-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.4-3.4"/></svg>
692
+ <input type="text" id="command-palette-input" placeholder="ค้นหาฟีเจอร์, คำสั่งลัด, เพลง, หรือเครื่องมือ AI... (ESC เพื่อปิด)" oninput="filterCommandPalette(this.value)" onkeydown="handleCommandPaletteKeyDown(event)" autocomplete="off" />
693
+ <kbd class="palette-kbd">ESC</kbd>
694
+ </div>
695
+ <div class="command-palette-results" id="command-palette-results" role="listbox"></div>
696
+ <div class="command-palette-footer">
697
+ <span><kbd>↑</kbd> <kbd>↓</kbd> นำทาง</span>
698
+ <span><kbd>Enter</kbd> เลือก</span>
699
+ <span><kbd>Ctrl+K</kbd> เปิด/ปิด</span>
700
+ </div>
701
+ </div>
702
+ </div>
703
+
704
+ <!-- Social Share Card Modal -->
705
+ <div class="modal-backdrop" id="share-card-modal" onclick="handleShareCardBackdrop(event)" onkeydown="if(event.key==='Escape') closeShareCardModal()" style="display:none;" role="dialog" aria-modal="true" aria-label="Social Share Card" tabindex="-1">
706
+ <div class="share-card-dialog">
707
+ <div class="modal-header">
708
+ <div class="modal-title-wrap">
709
+ <span class="modal-spark">🌸</span>
710
+ <h3>สร้างการ์ดแชร์บทสนทนา (Share Card)</h3>
711
+ </div>
712
+ <button type="button" class="btn-close-drawer" onclick="closeShareCardModal()" aria-label="ปิด"><svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>
713
+ </div>
714
+ <div class="share-card-preview-area" id="share-card-canvas-container"></div>
715
+ <div class="share-card-actions">
716
+ <button type="button" class="btn-share-download" onclick="downloadShareCardImage(this)">
717
+ <svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
718
+ <span>ดาวน์โหลดรูปภาพ (PNG)</span>
719
+ </button>
720
+ <button type="button" class="btn-share-copy" onclick="copyShareCardToClipboard(this)">
721
+ <svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>
722
+ <span>คัดลอกข้อความ</span>
723
+ </button>
724
+ </div>
725
+ </div>
726
+ </div>
727
+
728
+ <!-- Quote Card Modal -->
729
+ <div class="modal-backdrop" id="quote-card-modal" onclick="if(event.target===this)closeQuoteCardModal()" onkeydown="if(event.key==='Escape') closeQuoteCardModal()" style="display:none;" role="dialog" aria-modal="true" aria-label="Quote Card" tabindex="-1">
730
+ <div class="share-card-dialog" style="max-width:640px;">
731
+ <div class="modal-header">
732
+ <div class="modal-title-wrap">
733
+ <span class="modal-spark">🌸</span>
734
+ <h3>สร้างการ์ดคำคม (Quote Card)</h3>
735
+ </div>
736
+ <button type="button" class="btn-close-drawer" onclick="closeQuoteCardModal()" aria-label="ปิด"><svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>
737
+ </div>
738
+ <div class="modal-body" style="padding:16px 20px; display:flex; flex-direction:column; align-items:center; gap:14px;">
739
+ <canvas id="quote-canvas" width="600" height="340" style="max-width:100%; height:auto; border-radius:18px; box-shadow:0 12px 32px rgba(0,0,0,0.4); border:1px solid rgba(255,117,140,0.3);"></canvas>
740
+ <div style="width:100%; max-width:600px; display:flex; flex-direction:column; gap:6px;">
741
+ <textarea id="quote-text-editor" class="quote-text-editor" maxlength="220" rows="3" oninput="updateQuoteText(this.value)" placeholder="แก้ไขข้อความคำคม..." style="width:100%; border-radius:12px; padding:10px 14px; font-size:13.5px; background:rgba(255,255,255,0.06); border:1px solid rgba(255,117,140,0.25); color:var(--text); resize:vertical; outline:none;"></textarea>
742
+ <div style="display:flex; justify-content:space-between; align-items:center; font-size:11.5px; color:var(--text-muted);">
743
+ <span>ปรับแต่งข้อความคำคมของจวีจิ้งอีได้ตามต้องการ</span>
744
+ <span id="quote-char-count">0 / 220</span>
745
+ </div>
746
+ </div>
747
+ </div>
748
+ <div class="share-card-actions">
749
+ <button type="button" class="btn-share-download" id="btn-quote-download" onclick="downloadQuoteCard(this)">
750
+ <svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
751
+ <span>ดาวน์โหลดรูปภาพ (PNG)</span>
752
+ </button>
753
+ <button type="button" class="btn-share-copy" id="btn-quote-copy" onclick="copyQuoteCardImage(this)">
754
+ <svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>
755
+ <span>คัดลอกรูปภาพ</span>
756
+ </button>
757
+ </div>
758
+ </div>
759
+ </div>
760
+
761
+ <!-- Drama & Song Comparison Modal -->
762
+ <div class="modal-backdrop" id="compare-modal" onclick="handleCompareBackdrop(event)" onkeydown="if(event.key==='Escape') closeCompareModal()" style="display:none;" role="dialog" aria-modal="true" aria-label="Compare Works" tabindex="-1">
763
+ <div class="modal-dialog" style="max-width:760px; max-height:85vh; overflow-y:auto;">
764
+ <div class="modal-header">
765
+ <div class="modal-title-wrap">
766
+ <span class="modal-spark">⚔️</span>
767
+ <h3>เปรียบเทียบผลงานซีรีส์ &amp; เพลง (Comparison Matrix)</h3>
768
+ </div>
769
+ <button type="button" class="btn-close-drawer" onclick="closeCompareModal()" aria-label="ปิด"><svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>
770
+ </div>
771
+ <div class="modal-body" id="compare-modal-body"></div>
772
+ </div>
773
+ </div>
774
+
775
+ <!-- Sponsors & Ads Modal -->
776
+ <div class="modal-backdrop" id="sponsors-modal" onclick="if(event.target===this)closeSponsorsModal()" onkeydown="if(event.key==='Escape') closeSponsorsModal()" style="display:none;" role="dialog" aria-modal="true" aria-label="Sponsors and Partners" tabindex="-1">
777
+ <div class="modal-dialog sponsors-modal-dialog">
778
+ <div class="modal-header">
779
+ <div class="modal-title-wrap">
780
+ <span class="modal-spark">📢</span>
781
+ <div>
782
+ <h3 style="margin:0; font-size:16px; font-weight:700;">SPONSOR SPOTLIGHT</h3>
783
+ <p style="margin:2px 0 0; font-size:12px; color:var(--text-muted);">ผู้สนับสนุนโครงการและระบบนิเวศ Kiku Agent (Matching CLI /ads)</p>
784
+ </div>
785
+ </div>
786
+ <button type="button" class="btn-close-drawer" onclick="closeSponsorsModal()" aria-label="ปิด"><svg aria-hidden="true" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button>
787
+ </div>
788
+ <div class="modal-body sponsors-modal-body" id="sponsors-modal-body">
789
+ <!-- Dynamically rendered by renderSponsorsModal() -->
790
+ </div>
791
+ <div class="modal-footer sponsors-modal-footer">
792
+ <span>🌸 สนับสนุนการพัฒนา Open-Source AI Agent Ecosystem</span>
793
+ <button type="button" class="btn-msg-action" onclick="closeSponsorsModal()" style="padding:6px 14px; border-radius:8px;">ปิด</button>
794
+ </div>
795
+ </div>
796
+ </div>