@geminixiang/mikan 0.2.0 → 0.2.2

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 (92) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +54 -181
  3. package/dist/adapters/discord/bot.d.ts.map +1 -1
  4. package/dist/adapters/discord/bot.js +5 -4
  5. package/dist/adapters/discord/bot.js.map +1 -1
  6. package/dist/adapters/shared.d.ts +3 -2
  7. package/dist/adapters/shared.d.ts.map +1 -1
  8. package/dist/adapters/shared.js +11 -11
  9. package/dist/adapters/shared.js.map +1 -1
  10. package/dist/adapters/slack/bot.d.ts +1 -0
  11. package/dist/adapters/slack/bot.d.ts.map +1 -1
  12. package/dist/adapters/slack/bot.js +43 -1
  13. package/dist/adapters/slack/bot.js.map +1 -1
  14. package/dist/adapters/telegram/bot.d.ts.map +1 -1
  15. package/dist/adapters/telegram/bot.js +2 -3
  16. package/dist/adapters/telegram/bot.js.map +1 -1
  17. package/dist/admin/portal.d.ts +27 -0
  18. package/dist/admin/portal.d.ts.map +1 -0
  19. package/dist/admin/portal.js +2029 -0
  20. package/dist/admin/portal.js.map +1 -0
  21. package/dist/admin/store.d.ts +22 -0
  22. package/dist/admin/store.d.ts.map +1 -0
  23. package/dist/admin/store.js +39 -0
  24. package/dist/admin/store.js.map +1 -0
  25. package/dist/agent.d.ts +5 -0
  26. package/dist/agent.d.ts.map +1 -1
  27. package/dist/agent.js +10 -9
  28. package/dist/agent.js.map +1 -1
  29. package/dist/commands/admin.d.ts +8 -0
  30. package/dist/commands/admin.d.ts.map +1 -0
  31. package/dist/commands/admin.js +59 -0
  32. package/dist/commands/admin.js.map +1 -0
  33. package/dist/commands/auto-reply.d.ts.map +1 -1
  34. package/dist/commands/auto-reply.js +8 -7
  35. package/dist/commands/auto-reply.js.map +1 -1
  36. package/dist/commands/index.d.ts.map +1 -1
  37. package/dist/commands/index.js +2 -0
  38. package/dist/commands/index.js.map +1 -1
  39. package/dist/commands/login.d.ts.map +1 -1
  40. package/dist/commands/login.js +38 -14
  41. package/dist/commands/login.js.map +1 -1
  42. package/dist/commands/model.d.ts.map +1 -1
  43. package/dist/commands/model.js +2 -2
  44. package/dist/commands/model.js.map +1 -1
  45. package/dist/commands/new.d.ts.map +1 -1
  46. package/dist/commands/new.js +13 -3
  47. package/dist/commands/new.js.map +1 -1
  48. package/dist/commands/sandbox.d.ts.map +1 -1
  49. package/dist/commands/sandbox.js +2 -2
  50. package/dist/commands/sandbox.js.map +1 -1
  51. package/dist/commands/session-view.d.ts.map +1 -1
  52. package/dist/commands/session-view.js +3 -6
  53. package/dist/commands/session-view.js.map +1 -1
  54. package/dist/commands/types.d.ts +11 -0
  55. package/dist/commands/types.d.ts.map +1 -1
  56. package/dist/commands/types.js.map +1 -1
  57. package/dist/commands/utils.d.ts +1 -0
  58. package/dist/commands/utils.d.ts.map +1 -1
  59. package/dist/commands/utils.js +5 -0
  60. package/dist/commands/utils.js.map +1 -1
  61. package/dist/config.d.ts.map +1 -1
  62. package/dist/config.js +5 -13
  63. package/dist/config.js.map +1 -1
  64. package/dist/events.d.ts +0 -1
  65. package/dist/events.d.ts.map +1 -1
  66. package/dist/events.js +2 -5
  67. package/dist/events.js.map +1 -1
  68. package/dist/file-guards.d.ts.map +1 -1
  69. package/dist/file-guards.js +10 -7
  70. package/dist/file-guards.js.map +1 -1
  71. package/dist/login/portal.d.ts +11 -1
  72. package/dist/login/portal.d.ts.map +1 -1
  73. package/dist/login/portal.js +57 -175
  74. package/dist/login/portal.js.map +1 -1
  75. package/dist/main.d.ts.map +1 -1
  76. package/dist/main.js +5 -1
  77. package/dist/main.js.map +1 -1
  78. package/dist/portal-shell.d.ts +30 -0
  79. package/dist/portal-shell.d.ts.map +1 -0
  80. package/dist/portal-shell.js +371 -0
  81. package/dist/portal-shell.js.map +1 -0
  82. package/dist/session-view/portal.d.ts.map +1 -1
  83. package/dist/session-view/portal.js +88 -242
  84. package/dist/session-view/portal.js.map +1 -1
  85. package/dist/store.d.ts +1 -0
  86. package/dist/store.d.ts.map +1 -1
  87. package/dist/store.js +30 -12
  88. package/dist/store.js.map +1 -1
  89. package/dist/vault.d.ts.map +1 -1
  90. package/dist/vault.js +2 -8
  91. package/dist/vault.js.map +1 -1
  92. package/package.json +1 -1
@@ -1,6 +1,7 @@
1
1
  import { basename } from "path";
2
2
  import MarkdownIt from "markdown-it";
3
3
  import * as log from "../log.js";
4
+ import { renderPortalShell } from "../portal-shell.js";
4
5
  import { reportUserFacingError } from "../sentry.js";
5
6
  import { inferConversationKind } from "../sessions/policy.js";
6
7
  import { loadSessionViewModel, resolveRequestedSessionFile, } from "./service.js";
@@ -153,55 +154,51 @@ function renderSessionPage(model, token, expiresAt, isRunning, displayedSessionK
153
154
  ${renderRelationCard(model.parent, token)}
154
155
  </section>`
155
156
  : "";
156
- return renderHtmlDocument(`${model.title} · Session Viewer`, `<header class="hero-card">
157
- <div class="hero-top">
158
- <div class="hero-title-group">
159
- <span class="hero-wordmark">mikan</span>
160
- <h1 class="hero-title">${esc(model.title)}</h1>
161
- <div class="hero-meta-line">
162
- <span>Created ${esc(formatDate(model.createdAt))}</span>
163
- <span>Updated <strong data-session-updated>${esc(formatDate(model.updatedAt))}</strong></span>
164
- <span><strong data-session-entries>${esc(String(model.entryCount))}</strong> entries</span>
165
- </div>
166
- </div>
167
- <div class="hero-side">
168
- <span class="hero-badge hero-badge-status${isRunning ? " is-running" : ""}"><span class="hero-badge-dot"></span><strong data-session-status>${esc(isRunning ? "Running" : "Idle")}</strong></span>
169
- <span class="hero-badge">${esc(displayedSessionKey === conversationId ? "Channel" : "Thread")}</span>
170
- </div>
157
+ const body = `<header class="page-head">
158
+ <div>
159
+ <p class="eyebrow">Session</p>
160
+ <h2 class="page-title">${esc(model.title)}</h2>
161
+ <p class="page-desc">
162
+ <span>Created ${esc(formatDate(model.createdAt))}</span> ·
163
+ <span>Updated <strong data-session-updated>${esc(formatDate(model.updatedAt))}</strong></span> ·
164
+ <span><strong data-session-entries>${esc(String(model.entryCount))}</strong> entries</span>
165
+ </p>
171
166
  </div>
172
- <div class="hero-detail-row">
173
- <span class="hero-detail"><span class="hero-detail-label">Session</span><code>${esc(model.sessionId.slice(0, 8))}</code></span>
174
- <span class="hero-detail"><span class="hero-detail-label">File</span><code>${esc(model.fileName)}</code></span>
175
- <span class="hero-detail"><span class="hero-detail-label">Expires</span><span>${esc(formatDate(new Date(expiresAt).toISOString()))}</span></span>
167
+ <div class="session-side">
168
+ <span class="session-badge session-badge-status${isRunning ? " is-running" : ""}"><span class="session-badge-dot"></span><strong data-session-status>${esc(isRunning ? "Running" : "Idle")}</strong></span>
169
+ <span class="session-badge">${esc(displayedSessionKey === conversationId ? "Channel" : "Thread")}</span>
176
170
  </div>
177
171
  </header>
178
172
 
173
+ <div class="session-detail-row">
174
+ <span class="session-detail"><span class="session-detail-label">Session</span><code>${esc(model.sessionId.slice(0, 8))}</code></span>
175
+ <span class="session-detail"><span class="session-detail-label">File</span><code>${esc(model.fileName)}</code></span>
176
+ <span class="session-detail"><span class="session-detail-label">Expires</span><span>${esc(formatDate(new Date(expiresAt).toISOString()))}</span></span>
177
+ </div>
178
+
179
179
  ${relatedSections}
180
180
 
181
- <main class="timeline-shell">
181
+ <div class="timeline-shell">
182
182
  <div class="timeline-list" data-timeline-list>
183
183
  ${items}
184
184
  </div>
185
- </main>
185
+ </div>
186
186
 
187
187
  <button class="jump-latest-btn" type="button" hidden data-jump-latest aria-label="Jump to latest" title="Jump to latest">↓</button>
188
188
 
189
189
  <section class="composer-card">
190
- <div class="composer-copy">
191
- <p class="eyebrow">Interactive preview</p>
192
- <p>Ask mikan in this same session. Replies stay in Session View and do not post back to Slack.</p>
193
- </div>
194
190
  <form class="composer-form" data-session-composer>
195
191
  <input type="hidden" name="token" value="${esc(token)}">
196
192
  <input type="hidden" name="session" value="${esc(model.fileName)}">
197
193
  <input type="hidden" name="sessionKey" value="${esc(displayedSessionKey)}">
198
- <textarea name="text" rows="1" placeholder="Write a message…" required></textarea>
194
+ <textarea name="text" rows="1" placeholder="Ask mikan in this session (replies stay in Session View)" required></textarea>
199
195
  <div class="composer-actions">
200
196
  <span class="composer-status" data-composer-status></span>
201
197
  <button class="composer-send-btn" type="submit" aria-label="Send" title="Send">↑</button>
202
198
  </div>
203
199
  </form>
204
- </section>`, isRunning);
200
+ </section>`;
201
+ return renderHtmlDocument(`${model.title} · Session Viewer`, body, isRunning);
205
202
  }
206
203
  function renderRelationCard(relation, token) {
207
204
  const href = `/session?token=${encodeURIComponent(token)}&session=${encodeURIComponent(relation.fileName)}`;
@@ -623,24 +620,21 @@ function json(res, status, body) {
623
620
  function renderStatusPage(title, message) {
624
621
  return renderHtmlDocument(title, `<section class="card stack">
625
622
  <p class="eyebrow">mikan</p>
626
- <h1>${esc(title)}</h1>
623
+ <h1 class="page-title">${esc(title)}</h1>
627
624
  <div class="status err">${esc(message)}</div>
628
625
  </section>`, false);
629
626
  }
630
627
  function renderHtmlDocument(title, shellContent, isRunning) {
631
- return `<!DOCTYPE html>
632
- <html lang="en">
633
- <head>
634
- <meta charset="utf-8">
635
- <meta name="viewport" content="width=device-width, initial-scale=1">
636
- <title>${esc(title)}</title>
637
- <style>${styles}</style>
638
- </head>
639
- <body data-session-running="${isRunning ? "true" : "false"}">
640
- <main class="shell">
641
- ${shellContent}
642
- </main>
643
- <script>
628
+ return renderPortalShell({
629
+ activeView: "session",
630
+ pageTitle: "Session",
631
+ body: shellContent,
632
+ extraStyles: sessionViewStyles,
633
+ bodyAttributes: { "data-session-running": isRunning ? "true" : "false" },
634
+ inlineScript: sessionViewScript,
635
+ });
636
+ }
637
+ const sessionViewScript = `
644
638
  const form = document.querySelector('[data-session-composer]');
645
639
  const timelineList = document.querySelector('[data-timeline-list]');
646
640
  const jumpLatestBtn = document.querySelector('[data-jump-latest]');
@@ -808,10 +802,7 @@ function renderHtmlDocument(title, shellContent, isRunning) {
808
802
  });
809
803
 
810
804
  toggleJumpButton();
811
- </script>
812
- </body>
813
- </html>`;
814
- }
805
+ `;
815
806
  function formatDate(value) {
816
807
  const date = new Date(value);
817
808
  if (Number.isNaN(date.getTime()))
@@ -826,17 +817,8 @@ function esc(value) {
826
817
  .replaceAll('"', "&quot;")
827
818
  .replaceAll("'", "&#39;");
828
819
  }
829
- const styles = `
830
- @import url('https://fonts.googleapis.com/css2?family=Lora:wght@400;600&family=DM+Sans:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap');
831
-
820
+ const sessionViewStyles = `
832
821
  :root {
833
- --bg: #f0ece3;
834
- --surface: #ffffff;
835
- --border: rgba(0, 0, 0, 0.08);
836
- --text: #18181b;
837
- --muted: #71717a;
838
- --subtle: #a1a1aa;
839
-
840
822
  --user-bg: #18181b;
841
823
  --user-text: #fafafa;
842
824
  --user-time: rgba(250, 250, 250, 0.5);
@@ -852,174 +834,56 @@ const styles = `
852
834
  --tool-ok: #3fb950;
853
835
  --tool-err: #f85149;
854
836
  --tool-time: #484f58;
855
-
856
- --ok-bg: #f0fdf4;
857
- --ok-text: #15803d;
858
- --err-bg: #fef2f2;
859
- --err-text: #b91c1c;
860
837
  }
861
838
 
862
- *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
863
-
864
839
  body {
865
- min-height: 100vh;
866
- padding: 40px 20px calc(140px + env(safe-area-inset-bottom, 0px));
867
- display: flex;
868
- flex-direction: column;
869
- align-items: center;
840
+ /* Extra bottom padding for the fixed composer */
841
+ padding-bottom: calc(140px + env(safe-area-inset-bottom, 0px));
870
842
  overflow-x: hidden;
871
- background-color: var(--bg);
872
- background-image:
873
- radial-gradient(ellipse 80% 40% at 50% -10%, rgba(255,255,255,0.6) 0%, transparent 70%);
874
- color: var(--text);
875
- font-family: 'DM Sans', 'Segoe UI', system-ui, sans-serif;
876
- font-size: 15px;
877
- line-height: 1.5;
878
- -webkit-font-smoothing: antialiased;
879
- }
880
-
881
- .shell {
882
- width: 100%;
883
- max-width: 780px;
884
- min-width: 0;
885
- display: flex;
886
- flex-direction: column;
887
- gap: 12px;
888
- }
889
-
890
- /* ── Hero ─────────────────────────────────────────────────────────────── */
891
-
892
- .hero-card {
893
- padding: 28px 32px 24px;
894
- border: 1px solid var(--border);
895
- border-radius: 20px;
896
- background: var(--surface);
897
- box-shadow: 0 1px 2px rgba(0,0,0,0.04), 0 4px 16px rgba(0,0,0,0.06);
898
843
  }
899
844
 
900
- .hero-top {
901
- display: flex;
902
- align-items: flex-start;
903
- justify-content: space-between;
904
- gap: 20px;
905
- margin-bottom: 18px;
906
- }
907
-
908
- .hero-wordmark {
909
- display: block;
910
- margin-bottom: 6px;
911
- color: var(--subtle);
912
- font-size: 0.72rem;
913
- font-weight: 600;
914
- letter-spacing: 0.12em;
915
- text-transform: uppercase;
916
- }
917
-
918
- .hero-title {
919
- font-family: 'Lora', Georgia, serif;
920
- font-size: clamp(1.4rem, 2.5vw, 1.75rem);
921
- font-weight: 600;
922
- line-height: 1.2;
923
- letter-spacing: -0.01em;
924
- color: var(--text);
925
- text-wrap: balance;
926
- margin-bottom: 8px;
927
- }
845
+ /* ── Session-specific page-head extras ─────────────────────────────── */
928
846
 
929
- .hero-meta-line {
930
- display: flex;
931
- flex-wrap: wrap;
932
- gap: 8px 14px;
933
- color: var(--muted);
934
- font-size: 0.82rem;
935
- line-height: 1.4;
936
- }
937
-
938
- .hero-meta-line strong {
939
- color: var(--text);
940
- font-weight: 600;
941
- }
942
-
943
- .hero-side {
944
- display: flex;
945
- flex-direction: column;
946
- align-items: flex-end;
947
- gap: 8px;
847
+ .session-side {
848
+ display: flex; flex-direction: column; align-items: flex-end; gap: 8px;
948
849
  flex-shrink: 0;
949
850
  }
950
-
951
- .hero-badge {
952
- display: inline-flex;
953
- align-items: center;
954
- gap: 8px;
955
- padding: 6px 11px;
956
- border: 1px solid var(--border);
957
- border-radius: 999px;
958
- background: rgba(255,255,255,0.7);
959
- font-size: 0.78rem;
960
- color: var(--muted);
851
+ .session-badge {
852
+ display: inline-flex; align-items: center; gap: 8px;
853
+ padding: 6px 11px; border: 1px solid var(--border); border-radius: 999px;
854
+ background: rgba(255,255,255,0.7); font-size: 0.78rem; color: var(--muted);
961
855
  line-height: 1;
962
856
  }
963
-
964
- .hero-badge strong {
965
- color: var(--text);
966
- font-weight: 600;
857
+ .session-badge strong { color: var(--text); font-weight: 600; }
858
+ .session-badge-status.is-running {
859
+ background: #fff7ed; border-color: rgba(217, 119, 6, 0.18); color: #9a3412;
967
860
  }
968
-
969
- .hero-badge-status.is-running {
970
- background: #fff7ed;
971
- border-color: rgba(217, 119, 6, 0.18);
972
- color: #9a3412;
861
+ .session-badge-dot {
862
+ width: 7px; height: 7px; border-radius: 50%;
863
+ background: #a1a1aa; flex-shrink: 0;
973
864
  }
974
-
975
- .hero-badge-dot {
976
- width: 7px;
977
- height: 7px;
978
- border-radius: 50%;
979
- background: #a1a1aa;
980
- flex-shrink: 0;
865
+ .session-badge-status.is-running .session-badge-dot {
866
+ background: #d97706; box-shadow: 0 0 0 4px rgba(217, 119, 6, 0.14);
981
867
  }
982
868
 
983
- .hero-badge-status.is-running .hero-badge-dot {
984
- background: #d97706;
985
- box-shadow: 0 0 0 4px rgba(217, 119, 6, 0.14);
869
+ .session-detail-row {
870
+ display: flex; flex-wrap: wrap; gap: 8px;
871
+ padding: 12px 14px; border: 1px solid var(--border); border-radius: 14px;
872
+ background: rgba(255,255,255,0.6);
986
873
  }
987
-
988
- .hero-detail-row {
989
- display: flex;
990
- flex-wrap: wrap;
991
- gap: 10px;
992
- padding-top: 14px;
993
- border-top: 1px solid rgba(0, 0, 0, 0.06);
874
+ .session-detail {
875
+ display: inline-flex; align-items: center; gap: 8px; min-width: 0;
876
+ padding: 4px 10px; border-radius: 10px; background: rgba(0, 0, 0, 0.025);
877
+ color: var(--muted); font-size: 0.78rem;
994
878
  }
995
-
996
- .hero-detail {
997
- display: inline-flex;
998
- align-items: center;
999
- gap: 8px;
1000
- min-width: 0;
1001
- padding: 6px 10px;
1002
- border-radius: 12px;
1003
- background: rgba(0, 0, 0, 0.025);
1004
- color: var(--muted);
1005
- font-size: 0.78rem;
879
+ .session-detail-label {
880
+ text-transform: uppercase; letter-spacing: 0.08em;
881
+ font-size: 0.68rem; color: var(--subtle);
1006
882
  }
1007
-
1008
- .hero-detail-label {
1009
- text-transform: uppercase;
1010
- letter-spacing: 0.08em;
1011
- font-size: 0.68rem;
1012
- color: var(--subtle);
1013
- }
1014
-
1015
- .hero-detail code {
1016
- min-width: 0;
1017
- overflow: hidden;
1018
- text-overflow: ellipsis;
1019
- white-space: nowrap;
1020
- font-family: 'JetBrains Mono', ui-monospace, monospace;
1021
- font-size: 0.74rem;
1022
- color: var(--text);
883
+ .session-detail code {
884
+ min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
885
+ font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 0.74rem;
886
+ color: var(--text); padding: 0;
1023
887
  }
1024
888
 
1025
889
  /* ── Timeline shell ───────────────────────────────────────────────────── */
@@ -1622,32 +1486,8 @@ const styles = `
1622
1486
 
1623
1487
  /* ── Status page ──────────────────────────────────────────────────────── */
1624
1488
 
1625
- .card {
1626
- padding: 28px 32px;
1627
- border: 1px solid var(--border);
1628
- border-radius: 20px;
1629
- background: var(--surface);
1630
- box-shadow: 0 1px 2px rgba(0,0,0,0.04), 0 4px 16px rgba(0,0,0,0.06);
1631
- }
1632
-
1633
1489
  .stack > * + * { margin-top: 14px; }
1634
1490
 
1635
- .eyebrow {
1636
- color: var(--subtle);
1637
- font-size: 0.72rem;
1638
- font-weight: 600;
1639
- letter-spacing: 0.12em;
1640
- text-transform: uppercase;
1641
- }
1642
-
1643
- h1 {
1644
- font-family: 'Lora', Georgia, serif;
1645
- font-size: clamp(1.4rem, 2.5vw, 1.75rem);
1646
- font-weight: 600;
1647
- letter-spacing: -0.01em;
1648
- line-height: 1.2;
1649
- }
1650
-
1651
1491
  p { color: var(--muted); font-size: 0.9rem; line-height: 1.5; }
1652
1492
 
1653
1493
  .status {
@@ -1666,11 +1506,10 @@ const styles = `
1666
1506
 
1667
1507
  .composer-card {
1668
1508
  position: fixed;
1669
- left: 50%;
1509
+ left: calc(72px + (100vw - 72px) / 2);
1670
1510
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
1671
1511
  transform: translateX(-50%);
1672
- width: calc(100% - 32px);
1673
- max-width: 780px;
1512
+ width: min(960px, calc(100vw - 96px));
1674
1513
  padding: 10px 12px 10px 14px;
1675
1514
  border: 1px solid var(--border);
1676
1515
  border-radius: 22px;
@@ -1681,8 +1520,6 @@ const styles = `
1681
1520
  z-index: 20;
1682
1521
  }
1683
1522
 
1684
- .composer-card .composer-copy { display: none; }
1685
-
1686
1523
  .composer-form {
1687
1524
  display: flex;
1688
1525
  flex-direction: column;
@@ -1691,7 +1528,7 @@ const styles = `
1691
1528
 
1692
1529
  .jump-latest-btn {
1693
1530
  position: fixed;
1694
- left: 50%;
1531
+ left: calc(72px + (100vw - 72px) / 2);
1695
1532
  bottom: calc(env(safe-area-inset-bottom, 0px) + 120px);
1696
1533
  z-index: 25;
1697
1534
  width: 42px;
@@ -1799,16 +1636,25 @@ const styles = `
1799
1636
 
1800
1637
  /* ── Responsive ───────────────────────────────────────────────────────── */
1801
1638
 
1802
- @media (max-width: 600px) {
1803
- body { padding: 20px 12px calc(130px + env(safe-area-inset-bottom, 0px)); }
1639
+ @media (max-width: 900px) {
1640
+ .composer-card {
1641
+ left: 50%;
1642
+ width: min(960px, calc(100vw - 24px));
1643
+ }
1644
+ .jump-latest-btn { left: 50%; }
1645
+ }
1804
1646
 
1805
- .composer-card { width: calc(100% - 16px); bottom: calc(8px + env(safe-area-inset-bottom, 0px)); padding: 8px 10px; border-radius: 18px; }
1647
+ @media (max-width: 600px) {
1648
+ body { padding-bottom: calc(130px + env(safe-area-inset-bottom, 0px)); }
1806
1649
 
1807
- .hero-card, .card { padding: 20px; border-radius: 16px; }
1650
+ .composer-card {
1651
+ width: calc(100vw - 16px);
1652
+ bottom: calc(8px + env(safe-area-inset-bottom, 0px));
1653
+ padding: 8px 10px;
1654
+ border-radius: 18px;
1655
+ }
1808
1656
 
1809
- .hero-top { flex-direction: column; gap: 12px; }
1810
- .hero-side { align-items: flex-start; }
1811
- .hero-detail-row { gap: 8px; }
1657
+ .session-side { align-items: flex-start; flex-direction: row; }
1812
1658
 
1813
1659
  .user-bubble,
1814
1660
  .msg-assistant,