/ easyshell-web / src / index.css
index.css
  1  :root,
  2  [data-theme='dark'] {
  3    /* ─── Layout Dimensions ─── */
  4    --sidebar-width: 240px;
  5    --sidebar-collapsed-width: 80px;
  6    --header-height: 64px;
  7    --content-padding: 24px;
  8    --chat-sidebar-width: 280px;
  9    
 10    /* ─── Responsive Breakpoints (for JS reference) ─── */
 11    --breakpoint-xs: 480px;
 12    --breakpoint-sm: 576px;
 13    --breakpoint-md: 768px;
 14    --breakpoint-lg: 992px;
 15    --breakpoint-xl: 1200px;
 16    --breakpoint-xxl: 1600px;
 17    
 18    /* ─── Calculated Heights ─── */
 19    --content-height: calc(100vh - var(--header-height));
 20    --content-inner-height: calc(100vh - var(--header-height) - var(--content-padding) * 2);
 21    
 22    /* ─── Colors ─── */
 23    --bg-primary: #09090b;
 24    --bg-secondary: #18181b;
 25    --bg-card: #1c1c1f;
 26    --bg-card-hover: #27272a;
 27    --bg-header: #09090b;
 28    --border-color: #27272a;
 29    --border-color-light: #1f1f23;
 30    --text-primary: #fafafa;
 31    --text-secondary: #a1a1aa;
 32    --text-tertiary: #71717a;
 33    --accent-color: #2563eb;
 34    --scrollbar-thumb: #3f3f46;
 35    --scrollbar-thumb-hover: #52525b;
 36    color-scheme: dark;
 37  }
 38  
 39  [data-theme='light'] {
 40    --sidebar-width: 240px;
 41    --sidebar-collapsed-width: 80px;
 42    --header-height: 64px;
 43    --content-padding: 24px;
 44    --chat-sidebar-width: 280px;
 45    --breakpoint-xs: 480px;
 46    --breakpoint-sm: 576px;
 47    --breakpoint-md: 768px;
 48    --breakpoint-lg: 992px;
 49    --breakpoint-xl: 1200px;
 50    --breakpoint-xxl: 1600px;
 51    --content-height: calc(100vh - var(--header-height));
 52    --content-inner-height: calc(100vh - var(--header-height) - var(--content-padding) * 2);
 53    --bg-primary: #fafafa;
 54    --bg-secondary: #ffffff;
 55    --bg-card: #ffffff;
 56    --bg-card-hover: #f4f4f5;
 57    --bg-header: #ffffff;
 58    --border-color: #e4e4e7;
 59    --border-color-light: #f4f4f5;
 60    --text-primary: #09090b;
 61    --text-secondary: #71717a;
 62    --text-tertiary: #a1a1aa;
 63    --accent-color: #2563eb;
 64    --scrollbar-thumb: rgba(0, 0, 0, 0.12);
 65    --scrollbar-thumb-hover: rgba(0, 0, 0, 0.2);
 66    color-scheme: light;
 67  }
 68  
 69  * {
 70    margin: 0;
 71    padding: 0;
 72    box-sizing: border-box;
 73  }
 74  
 75  html,
 76  body,
 77  #root {
 78    height: 100%;
 79    width: 100%;
 80  }
 81  
 82  body {
 83    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
 84      'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji',
 85      'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
 86    -webkit-font-smoothing: antialiased;
 87    -moz-osx-font-smoothing: grayscale;
 88    background: var(--bg-primary);
 89    color: var(--text-primary);
 90  }
 91  
 92  /* Custom Scrollbar */
 93  ::-webkit-scrollbar {
 94    width: 6px;
 95    height: 6px;
 96  }
 97  ::-webkit-scrollbar-track {
 98    background: transparent;
 99  }
100  ::-webkit-scrollbar-thumb {
101    background: var(--scrollbar-thumb);
102    border-radius: 3px;
103  }
104  ::-webkit-scrollbar-thumb:hover {
105    background: var(--scrollbar-thumb-hover);
106  }
107  
108  :focus-visible {
109    outline: 2px solid var(--accent-color);
110    outline-offset: 2px;
111  }
112  
113  @media (prefers-reduced-motion: reduce) {
114    *,
115    *::before,
116    *::after {
117      animation-duration: 0.01ms !important;
118      animation-iteration-count: 1 !important;
119      transition-duration: 0.01ms !important;
120      scroll-behavior: auto !important;
121    }
122  }
123  
124  /* ─── Smooth page transitions ─── */
125  .ant-layout-content {
126    animation: fadeIn 0.2s ease-out;
127  }
128  @keyframes fadeIn {
129    from { opacity: 0; transform: translateY(4px); }
130    to { opacity: 1; transform: translateY(0); }
131  }
132  
133  /* ─── Card hover effect ─── */
134  .ant-card {
135    transition: box-shadow 0.2s ease, border-color 0.2s ease;
136  }
137  .ant-card:hover {
138    box-shadow: 0 1px 6px rgba(0, 0, 0, 0.06);
139  }
140  [data-theme='dark'] .ant-card:hover {
141    box-shadow: 0 1px 6px rgba(0, 0, 0, 0.3);
142  }
143  
144  /* ─── Table refinement ─── */
145  .ant-table-wrapper .ant-table {
146    border-radius: 12px !important;
147  }
148  .ant-table-thead > tr > th,
149  .ant-table-thead > tr > td {
150    font-weight: 600 !important;
151    font-size: 12px !important;
152    text-transform: uppercase;
153    letter-spacing: 0.4px;
154  }
155  
156  /* ─── Better tag styling ─── */
157  .ant-tag {
158    border-radius: 6px;
159    font-size: 12px;
160    line-height: 20px;
161    padding: 0 8px;
162  }
163  
164  /* ─── Pro Table toolbar refinement ─── */
165  .ant-pro-table-list-toolbar {
166    padding: 16px 0 !important;
167  }
168  
169  /* ─── Sidebar menu font weights ─── */
170  .ant-menu-item,
171  .ant-menu-submenu-title {
172    font-weight: 500;
173  }
174  .ant-menu-item-selected {
175    font-weight: 600;
176  }
177  
178  /* ─── Selection highlight ─── */
179  ::selection {
180    background: rgba(37, 99, 235, 0.2);
181    color: inherit;
182  }
183  
184  /* ─── MainLayout Sidebar Fix ─── */
185  .main-layout-sider {
186    position: sticky !important;
187    top: 0;
188    height: 100vh;
189    display: flex;
190    flex-direction: column;
191    z-index: 11;
192  }
193  
194  .main-layout-sider .ant-layout-sider-children {
195    display: flex;
196    flex-direction: column;
197    height: 100%;
198    overflow: hidden;
199  }
200  
201  .sidebar-header {
202    height: var(--header-height);
203    flex-shrink: 0;
204    display: flex;
205    align-items: center;
206  }
207  
208  .sidebar-menu-wrapper {
209    flex: 1;
210    overflow-y: auto;
211    overflow-x: hidden;
212    min-height: 0;
213  }
214  
215  .sidebar-footer {
216    flex-shrink: 0;
217    padding: 12px 16px;
218  }
219  
220  /* ─── MainLayout Content Fix ─── */
221  .main-layout-content {
222    margin: var(--content-padding);
223    padding: 0;
224    min-height: 280px;
225    height: var(--content-inner-height);
226    overflow: auto;
227  }
228  
229  /* ─── AI Chat Layout Fix ─── */
230  .ai-chat-container {
231    display: flex;
232    height: var(--content-inner-height);
233    width: 100%;
234    overflow: hidden;
235  }
236  
237  .ai-chat-sidebar {
238    width: var(--chat-sidebar-width);
239    min-width: var(--chat-sidebar-width);
240    flex-shrink: 0;
241    display: flex;
242    flex-direction: column;
243    height: 100%;
244    overflow: hidden;
245  }
246  
247  .ai-chat-sidebar-list {
248    flex: 1;
249    overflow-y: auto;
250    overflow-x: hidden;
251    min-height: 0;
252    padding: 0 8px 8px;
253  }
254  
255  .ai-chat-main {
256    flex: 1;
257    display: flex;
258    flex-direction: column;
259    height: 100%;
260    min-width: 0;
261    overflow: hidden;
262  }
263  
264  .ai-chat-messages {
265    flex: 1 1 0;
266    overflow-y: auto;
267    overflow-x: hidden;
268    min-height: 0;
269    max-height: 100%;
270    padding: 16px 24px;
271    -webkit-user-select: text !important;
272    -moz-user-select: text !important;
273    -ms-user-select: text !important;
274    user-select: text !important;
275    cursor: text;
276  }
277  
278  .ai-chat-messages * {
279    -webkit-user-select: text !important;
280    -moz-user-select: text !important;
281    -ms-user-select: text !important;
282    user-select: text !important;
283  }
284  
285  .ai-chat-messages button,
286  .ai-chat-messages .ant-btn {
287    -webkit-user-select: none !important;
288    -moz-user-select: none !important;
289    -ms-user-select: none !important;
290    user-select: none !important;
291    cursor: pointer !important;
292  }
293  
294  /* Message row hover: show action buttons via CSS instead of React state */
295  .msg-row .msg-actions {
296    opacity: 0;
297    visibility: hidden;
298    transition: opacity 0.2s;
299  }
300  .msg-row .msg-actions.has-process {
301    opacity: 0.6;
302    visibility: visible;
303  }
304  .msg-row:hover .msg-actions {
305    opacity: 1;
306    visibility: visible;
307  }
308  .msg-row .msg-actions .msg-hover-btns {
309    display: none;
310  }
311  .msg-row:hover .msg-actions .msg-hover-btns {
312    display: contents;
313  }
314  
315  /* Make text selection visible on both white assistant and colored user message bubbles */
316  .ai-chat-messages ::selection {
317    background: rgba(37, 99, 235, 0.3);
318    color: inherit;
319  }
320  
321  .ai-chat-input-wrapper {
322    flex-shrink: 0;
323    position: relative;
324    transition: all 0.3s ease;
325  }
326  
327  .ai-chat-input-wrapper::before {
328    content: '';
329    position: absolute;
330    top: 0;
331    left: 0;
332    right: 0;
333    height: 1px;
334    background: linear-gradient(90deg, transparent, var(--accent-color), transparent);
335    opacity: 0.3;
336    z-index: 1;
337  }
338  
339  /* ─── AI Chat Polish ─── */
340  .ai-chat-empty-state {
341    animation: fadeInUp 0.5s ease-out forwards;
342  }
343  
344  .ai-chat-empty-icon {
345    animation: breathe 3s ease-in-out infinite;
346    display: inline-block;
347    color: var(--accent-color);
348  }
349  
350  @keyframes breathe {
351    0% { transform: scale(1); opacity: 0.8; }
352    50% { transform: scale(1.05); opacity: 1; filter: drop-shadow(0 0 12px rgba(37, 99, 235, 0.4)); }
353    100% { transform: scale(1); opacity: 0.8; }
354  }
355  
356  @keyframes fadeInUp {
357    from { opacity: 0; transform: translateY(10px); }
358    to { opacity: 1; transform: translateY(0); }
359  }
360  
361  .ai-chat-messages .msg-row {
362    animation: fadeInUp 0.3s ease-out forwards;
363  }
364  
365  .suggested-prompt-card {
366    transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
367  }
368  .suggested-prompt-card:hover {
369    transform: scale(1.02);
370    border-left-width: 4px !important;
371  }
372  
373  .typing-dots {
374    display: inline-flex;
375    align-items: center;
376    gap: 4px;
377    height: 24px;
378    padding: 0 4px;
379  }
380  .typing-dots span {
381    width: 6px;
382    height: 6px;
383    background-color: var(--text-secondary);
384    border-radius: 50%;
385    animation: typingBounce 1.4s infinite ease-in-out both;
386  }
387  .typing-dots span:nth-child(1) { animation-delay: -0.32s; }
388  .typing-dots span:nth-child(2) { animation-delay: -0.16s; }
389  .typing-dots span:nth-child(3) { animation-delay: 0s; }
390  
391  @keyframes typingBounce {
392    0%, 80%, 100% { transform: scale(0); opacity: 0.4; }
393    40% { transform: scale(1); opacity: 1; }
394  }
395  
396  /* ─── Responsive: Mobile Sidebar ─── */
397  @media (max-width: 768px) {
398    :root {
399      --content-padding: 12px;
400      --chat-sidebar-width: 100%;
401    }
402    
403    .main-layout-content {
404      margin: var(--content-padding);
405      height: calc(100vh - var(--header-height) - var(--content-padding) * 2);
406    }
407    
408    .ai-chat-container {
409      flex-direction: column;
410    }
411    
412    .ai-chat-sidebar {
413      width: 100%;
414      min-width: 100%;
415      height: 100%;
416      border-right: none;
417    }
418    
419    .ai-chat-main {
420      flex: 1;
421      min-height: 0;
422    }
423    
424    .ai-chat-messages {
425      padding: 12px 16px;
426    }
427  }
428  
429  /* ─── Mobile Drawer Styles ─── */
430  .mobile-nav-drawer .ant-drawer-body {
431    padding: 0 !important;
432  }
433  
434  .mobile-nav-drawer .sidebar-header {
435    height: var(--header-height);
436    flex-shrink: 0;
437    display: flex;
438    align-items: center;
439  }
440  
441  .mobile-nav-drawer .sidebar-menu-wrapper {
442    flex: 1;
443    overflow-y: auto;
444    overflow-x: hidden;
445    min-height: 0;
446  }
447  
448  .mobile-nav-drawer .sidebar-footer {
449    flex-shrink: 0;
450    padding: 12px 16px;
451  }
452  
453  /* ─── Responsive Table Styles ─── */
454  @media (max-width: 768px) {
455    .ant-pro-table-list-toolbar {
456      flex-wrap: wrap;
457      gap: 8px;
458      padding: 12px 0 !important;
459    }
460    
461    .ant-pro-table-list-toolbar-container {
462      flex-wrap: wrap;
463      gap: 8px;
464    }
465    
466    .ant-pro-table-list-toolbar-left {
467      flex: 1 1 100%;
468      margin-bottom: 8px;
469    }
470    
471    .ant-pro-table-list-toolbar-right {
472      flex: 1 1 100%;
473      justify-content: flex-start !important;
474      flex-wrap: wrap;
475      gap: 8px;
476    }
477    
478    .ant-table-wrapper {
479      overflow-x: auto;
480    }
481    
482    .ant-table {
483      min-width: 600px;
484    }
485    
486    .ant-pagination {
487      flex-wrap: wrap;
488      justify-content: center;
489      gap: 8px;
490    }
491    
492    .ant-pagination-options {
493      display: none;
494    }
495  }
496  
497  /* ─── Responsive Card Styles ─── */
498  @media (max-width: 768px) {
499    .ant-card {
500      border-radius: 8px !important;
501    }
502    
503    .ant-card-body {
504      padding: 12px !important;
505    }
506  }
507  
508  /* ─── Responsive Modal Styles ─── */
509  @media (max-width: 768px) {
510    .ant-modal {
511      max-width: calc(100vw - 32px) !important;
512      margin: 16px auto !important;
513    }
514    
515    .ant-modal-content {
516      padding: 16px !important;
517    }
518    
519    .ant-drawer-content-wrapper {
520      max-width: 100vw !important;
521    }
522  }
523  
524  /* ─── Responsive: Tablet ─── */
525  @media (min-width: 769px) and (max-width: 992px) {
526    :root {
527      --sidebar-width: 200px;
528      --chat-sidebar-width: 240px;
529    }
530  }
531  
532  /* ─── Responsive: Desktop ─── */
533  @media (min-width: 1600px) {
534    :root {
535      --chat-sidebar-width: 320px;
536    }
537  }