globals.css 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. :root {
  2. color-scheme: light;
  3. --surface: #ffffff;
  4. --surface-raised: #ffffff;
  5. --surface-muted: #f4f4f5;
  6. --border: #e4e4e7;
  7. --text: #0a0a0a;
  8. --text-muted: #71717a;
  9. --accent: #6366f1;
  10. --accent-fg: #ffffff;
  11. --success: #16a34a;
  12. --warn: #d97706;
  13. --user-bubble-bg: #0a0a0a;
  14. --user-bubble-fg: #ffffff;
  15. font-family:
  16. ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
  17. "Helvetica Neue", sans-serif;
  18. font-size: 14px;
  19. line-height: 1.5;
  20. -webkit-font-smoothing: antialiased;
  21. color: var(--text);
  22. background: var(--surface-muted);
  23. }
  24. * {
  25. box-sizing: border-box;
  26. }
  27. html,
  28. body {
  29. margin: 0;
  30. padding: 0;
  31. height: 100%;
  32. }
  33. button,
  34. input,
  35. textarea {
  36. font: inherit;
  37. color: inherit;
  38. }
  39. a {
  40. color: var(--accent);
  41. }
  42. code {
  43. font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  44. font-size: 0.9em;
  45. background: var(--surface-muted);
  46. padding: 0.1em 0.35em;
  47. border-radius: 4px;
  48. }
  49. /* Dividers between repeated list items — top border on all but the first
  50. so there's no dangling line at either end. */
  51. .jr-list-item + .jr-list-item {
  52. border-top: 1px solid var(--border);
  53. }
  54. @keyframes jr-shimmer {
  55. 0%,
  56. 100% {
  57. opacity: 0.55;
  58. }
  59. 50% {
  60. opacity: 1;
  61. }
  62. }
  63. .jr-shimmer {
  64. animation: jr-shimmer 1.4s ease-in-out infinite;
  65. }
  66. kbd {
  67. display: inline-block;
  68. padding: 1px 5px;
  69. border: 1px solid var(--border);
  70. border-radius: 4px;
  71. background: var(--surface);
  72. font-family:
  73. ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  74. font-size: 11px;
  75. line-height: 1.3;
  76. }
  77. /* ==========================================================================
  78. App shell
  79. ========================================================================== */
  80. .app {
  81. height: 100%;
  82. display: grid;
  83. grid-template-rows: auto 1fr auto;
  84. background: var(--surface-muted);
  85. }
  86. .topbar {
  87. display: flex;
  88. align-items: center;
  89. justify-content: space-between;
  90. padding: 10px 20px;
  91. background: var(--surface);
  92. border-bottom: 1px solid var(--border);
  93. }
  94. .topbar-brand {
  95. display: flex;
  96. align-items: center;
  97. gap: 10px;
  98. }
  99. .logo-dot {
  100. width: 22px;
  101. height: 22px;
  102. border-radius: 6px;
  103. background: linear-gradient(135deg, var(--accent), color-mix(in oklab, var(--accent) 60%, #000));
  104. box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 20%, transparent);
  105. }
  106. .topbar-text {
  107. display: flex;
  108. flex-direction: column;
  109. line-height: 1.2;
  110. }
  111. .topbar-title {
  112. font-weight: 600;
  113. font-size: 14px;
  114. }
  115. .topbar-sub {
  116. font-size: 12px;
  117. color: var(--text-muted);
  118. }
  119. .topbar-actions {
  120. display: flex;
  121. gap: 8px;
  122. align-items: center;
  123. }
  124. .btn-ghost {
  125. background: transparent;
  126. border: 1px solid transparent;
  127. padding: 6px 10px;
  128. border-radius: 8px;
  129. font-size: 13px;
  130. color: var(--text-muted);
  131. cursor: pointer;
  132. }
  133. .btn-ghost:hover {
  134. background: var(--surface-muted);
  135. color: var(--text);
  136. }
  137. .btn-link {
  138. text-decoration: none;
  139. font-size: 13px;
  140. color: var(--text-muted);
  141. padding: 6px 10px;
  142. border-radius: 8px;
  143. }
  144. .btn-link:hover {
  145. background: var(--surface-muted);
  146. color: var(--text);
  147. }
  148. .btn-primary {
  149. background: var(--accent);
  150. color: var(--accent-fg);
  151. border: none;
  152. border-radius: 8px;
  153. padding: 8px 16px;
  154. font-size: 13px;
  155. font-weight: 500;
  156. cursor: pointer;
  157. transition: opacity 0.15s;
  158. }
  159. .btn-primary:disabled {
  160. opacity: 0.5;
  161. cursor: not-allowed;
  162. }
  163. /* ==========================================================================
  164. Scrollable chat area
  165. ========================================================================== */
  166. .scroll {
  167. overflow-y: auto;
  168. padding: 24px 20px 40px;
  169. }
  170. .thread {
  171. max-width: 760px;
  172. margin: 0 auto;
  173. display: flex;
  174. flex-direction: column;
  175. gap: 20px;
  176. }
  177. .row {
  178. display: flex;
  179. width: 100%;
  180. }
  181. .row.user {
  182. justify-content: flex-end;
  183. }
  184. .row.assistant {
  185. justify-content: flex-start;
  186. }
  187. .bubble.user {
  188. max-width: 85%;
  189. padding: 10px 14px;
  190. border-radius: 16px 16px 4px 16px;
  191. background: var(--user-bubble-bg);
  192. color: var(--user-bubble-fg);
  193. font-size: 13px;
  194. line-height: 1.5;
  195. white-space: pre-wrap;
  196. }
  197. .assistant-inner {
  198. width: 100%;
  199. display: flex;
  200. flex-direction: column;
  201. gap: 12px;
  202. }
  203. .assistant-text {
  204. font-size: 13px;
  205. line-height: 1.55;
  206. white-space: pre-wrap;
  207. color: var(--text);
  208. }
  209. .thinking {
  210. font-size: 13px;
  211. color: var(--text-muted);
  212. }
  213. /* Each rendered spec is wrapped in a structural container without any
  214. visual chrome of its own — the AI-generated Card (or whatever the
  215. root element is) carries the framing. `.thread` already provides the
  216. gap between messages, so no outer border is needed here. */
  217. .spec-wrap {
  218. width: 100%;
  219. }
  220. .error {
  221. padding: 12px 14px;
  222. border-radius: 10px;
  223. border: 1px solid color-mix(in oklab, var(--warn) 40%, var(--border));
  224. background: color-mix(in oklab, var(--warn) 10%, transparent);
  225. color: var(--warn);
  226. font-size: 13px;
  227. }
  228. /* ==========================================================================
  229. Empty state
  230. ========================================================================== */
  231. .empty {
  232. min-height: 100%;
  233. display: flex;
  234. align-items: center;
  235. justify-content: center;
  236. padding: 40px 0;
  237. }
  238. .empty-inner {
  239. max-width: 720px;
  240. width: 100%;
  241. display: flex;
  242. flex-direction: column;
  243. gap: 20px;
  244. }
  245. .eyebrow {
  246. font-size: 12px;
  247. font-weight: 500;
  248. letter-spacing: 0.06em;
  249. text-transform: uppercase;
  250. color: var(--accent);
  251. }
  252. .empty h1 {
  253. margin: 0;
  254. font-size: 28px;
  255. font-weight: 600;
  256. letter-spacing: -0.01em;
  257. line-height: 1.2;
  258. }
  259. .lead {
  260. margin: 0;
  261. font-size: 15px;
  262. color: var(--text-muted);
  263. line-height: 1.55;
  264. }
  265. .callout-row {
  266. display: grid;
  267. grid-template-columns: 1fr 1fr;
  268. gap: 12px;
  269. }
  270. @media (max-width: 620px) {
  271. .callout-row {
  272. grid-template-columns: 1fr;
  273. }
  274. }
  275. .callout {
  276. padding: 12px 14px;
  277. border-radius: 10px;
  278. border: 1px solid var(--border);
  279. background: var(--surface);
  280. font-size: 13px;
  281. line-height: 1.5;
  282. }
  283. .callout .cap {
  284. font-size: 11px;
  285. font-weight: 500;
  286. letter-spacing: 0.04em;
  287. text-transform: uppercase;
  288. color: var(--text-muted);
  289. margin-bottom: 4px;
  290. }
  291. .sugg-grid {
  292. display: grid;
  293. grid-template-columns: 1fr 1fr;
  294. gap: 12px;
  295. margin-top: 8px;
  296. }
  297. @media (max-width: 620px) {
  298. .sugg-grid {
  299. grid-template-columns: 1fr;
  300. }
  301. }
  302. .sugg {
  303. text-align: left;
  304. background: var(--surface);
  305. border: 1px solid var(--border);
  306. border-radius: 12px;
  307. padding: 14px;
  308. cursor: pointer;
  309. transition:
  310. border-color 0.15s,
  311. transform 0.05s;
  312. display: flex;
  313. flex-direction: column;
  314. gap: 4px;
  315. }
  316. .sugg:hover {
  317. border-color: color-mix(in oklab, var(--accent) 40%, var(--border));
  318. }
  319. .sugg:active {
  320. transform: translateY(1px);
  321. }
  322. .sugg-label {
  323. font-size: 13px;
  324. font-weight: 600;
  325. }
  326. .sugg-prompt {
  327. font-size: 13px;
  328. color: var(--text-muted);
  329. line-height: 1.45;
  330. }
  331. .sugg-blurb {
  332. font-size: 11px;
  333. color: var(--accent);
  334. margin-top: 4px;
  335. }
  336. /* ==========================================================================
  337. Composer
  338. ========================================================================== */
  339. .composer {
  340. background: var(--surface);
  341. border-top: 1px solid var(--border);
  342. padding: 12px 20px 14px;
  343. }
  344. .composer-inner {
  345. max-width: 760px;
  346. margin: 0 auto;
  347. display: flex;
  348. gap: 8px;
  349. align-items: flex-end;
  350. }
  351. .composer textarea {
  352. flex: 1;
  353. resize: none;
  354. padding: 10px 12px;
  355. border-radius: 10px;
  356. border: 1px solid var(--border);
  357. background: var(--surface);
  358. color: var(--text);
  359. font-size: 13px;
  360. line-height: 1.5;
  361. outline: none;
  362. min-height: 58px;
  363. }
  364. .composer textarea:focus {
  365. border-color: color-mix(in oklab, var(--accent) 50%, var(--border));
  366. }
  367. .composer .btn-primary {
  368. padding: 10px 18px;
  369. align-self: stretch;
  370. }
  371. .composer-hint {
  372. max-width: 760px;
  373. margin: 6px auto 0;
  374. font-size: 11px;
  375. color: var(--text-muted);
  376. }