@ermis-network/ermis-chat-react 1.0.1 → 1.0.3

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 (38) hide show
  1. package/dist/index.cjs +2501 -1249
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.css +1231 -134
  4. package/dist/index.css.map +1 -1
  5. package/dist/index.d.mts +306 -2
  6. package/dist/index.d.ts +306 -2
  7. package/dist/index.mjs +2427 -1181
  8. package/dist/index.mjs.map +1 -1
  9. package/package.json +2 -2
  10. package/src/components/ChannelHeader.tsx +50 -9
  11. package/src/components/ChannelInfo/AddMemberModal.tsx +48 -174
  12. package/src/components/ChannelList.tsx +9 -3
  13. package/src/components/CreateChannelModal.tsx +274 -0
  14. package/src/components/ErmisCallProvider.tsx +279 -0
  15. package/src/components/ErmisCallUI.tsx +634 -0
  16. package/src/components/MessageRenderers.tsx +37 -10
  17. package/src/components/Modal.tsx +2 -1
  18. package/src/components/UserPicker.tsx +377 -0
  19. package/src/context/ChatProvider.tsx +49 -1
  20. package/src/context/ErmisCallContext.tsx +37 -0
  21. package/src/hooks/useCallContext.ts +10 -0
  22. package/src/index.ts +27 -0
  23. package/src/styles/_add-member-modal.css +12 -29
  24. package/src/styles/_call-ui.css +743 -0
  25. package/src/styles/_channel-info.css +34 -34
  26. package/src/styles/_channel-list.css +7 -7
  27. package/src/styles/_create-channel-modal.css +183 -0
  28. package/src/styles/_message-bubble.css +108 -16
  29. package/src/styles/_message-input.css +4 -4
  30. package/src/styles/_message-list.css +11 -11
  31. package/src/styles/_modal.css +23 -36
  32. package/src/styles/_panel.css +1 -1
  33. package/src/styles/_search-panel.css +9 -9
  34. package/src/styles/_tokens.css +42 -0
  35. package/src/styles/_typing-indicator.css +15 -2
  36. package/src/styles/_user-picker.css +268 -0
  37. package/src/styles/index.css +3 -0
  38. package/src/types.ts +293 -1
@@ -0,0 +1,743 @@
1
+ /* ============================================================
2
+ Ermis Call UI – Premium Call Experience
3
+ BEM naming: .ermis-call-ui__{element}--{modifier}
4
+ ============================================================ */
5
+
6
+ .ermis-call-ui {
7
+ display: flex;
8
+ flex-direction: column;
9
+ align-items: center;
10
+ width: 100%;
11
+ }
12
+
13
+ /* Fullscreen mode */
14
+ .ermis-call-ui--fullscreen {
15
+ background: #000000;
16
+ justify-content: center;
17
+ height: 100%;
18
+ }
19
+
20
+ .ermis-call-ui--fullscreen .ermis-call-ui__video-container {
21
+ aspect-ratio: auto;
22
+ height: 100%;
23
+ border-radius: 0;
24
+ }
25
+
26
+ .ermis-call-ui--fullscreen .ermis-call-ui__audio-container {
27
+ flex: 1;
28
+ border-radius: 0;
29
+ justify-content: center;
30
+ }
31
+
32
+ /* Hidden audio element (replaces inline style={{ display: 'none' }}) */
33
+ .ermis-call-ui__audio--hidden {
34
+ position: absolute;
35
+ width: 0;
36
+ height: 0;
37
+ overflow: hidden;
38
+ pointer-events: none;
39
+ }
40
+
41
+ /* ============================================================
42
+ RINGING STATE
43
+ ============================================================ */
44
+ .ermis-call-ui__ringing {
45
+ text-align: center;
46
+ padding: 2.5rem var(--ermis-spacing-lg) 2rem;
47
+ display: flex;
48
+ flex-direction: column;
49
+ align-items: center;
50
+ justify-content: center;
51
+ background: var(--ermis-call-bg);
52
+ border-radius: var(--ermis-radius-lg);
53
+ min-height: 340px;
54
+ width: 100%;
55
+ }
56
+
57
+ /* -- Avatar Pulse Container -- */
58
+ .ermis-call-ui__ringing-avatar {
59
+ position: relative;
60
+ display: flex;
61
+ align-items: center;
62
+ justify-content: center;
63
+ margin-bottom: var(--ermis-spacing-lg);
64
+ }
65
+
66
+ /* Pulse rings */
67
+ .ermis-call-ui__ringing-avatar::before,
68
+ .ermis-call-ui__ringing-avatar::after {
69
+ content: '';
70
+ position: absolute;
71
+ border-radius: 50%;
72
+ border: 2px solid var(--ermis-call-pulse);
73
+ animation: ermis-call-pulse 2s ease-out infinite;
74
+ }
75
+
76
+ .ermis-call-ui__ringing-avatar::before {
77
+ width: 110px;
78
+ height: 110px;
79
+ }
80
+
81
+ .ermis-call-ui__ringing-avatar::after {
82
+ width: 130px;
83
+ height: 130px;
84
+ animation-delay: 0.6s;
85
+ }
86
+
87
+ @keyframes ermis-call-pulse {
88
+ 0% {
89
+ transform: scale(0.85);
90
+ opacity: 0.8;
91
+ }
92
+ 100% {
93
+ transform: scale(1.4);
94
+ opacity: 0;
95
+ }
96
+ }
97
+
98
+ /* Floating avatar effect */
99
+ .ermis-call-ui__ringing-avatar-inner {
100
+ position: relative;
101
+ z-index: 2;
102
+ animation: ermis-call-float 3s ease-in-out infinite;
103
+ }
104
+
105
+ @keyframes ermis-call-float {
106
+ 0%,
107
+ 100% {
108
+ transform: translateY(0);
109
+ }
110
+ 50% {
111
+ transform: translateY(-6px);
112
+ }
113
+ }
114
+
115
+ /* -- Name & Status -- */
116
+ .ermis-call-ui__ringing-name {
117
+ margin: 0 0 var(--ermis-spacing-xs);
118
+ font-size: 1.35rem;
119
+ font-weight: 700;
120
+ color: var(--ermis-text-primary);
121
+ letter-spacing: -0.01em;
122
+ }
123
+
124
+ .ermis-call-ui__ringing-status {
125
+ color: var(--ermis-text-secondary);
126
+ margin: 0 0 var(--ermis-spacing-sm);
127
+ font-size: var(--ermis-font-size-sm);
128
+ font-weight: 400;
129
+ }
130
+
131
+ /* -- Call Type Badge -- */
132
+ .ermis-call-ui__type-badge {
133
+ display: inline-flex;
134
+ align-items: center;
135
+ gap: 6px;
136
+ padding: 4px 14px;
137
+ border-radius: var(--ermis-radius-full);
138
+ background: var(--ermis-call-glass);
139
+ border: 1px solid var(--ermis-call-glass-border);
140
+ color: var(--ermis-text-secondary);
141
+ font-size: var(--ermis-font-size-xs);
142
+ font-weight: 500;
143
+ text-transform: capitalize;
144
+ margin-bottom: 1.5rem;
145
+ }
146
+
147
+ .ermis-call-ui__type-badge svg {
148
+ width: 14px;
149
+ height: 14px;
150
+ opacity: 0.8;
151
+ }
152
+
153
+ /* -- Ringing Action Buttons -- */
154
+ .ermis-call-ui__ringing-actions {
155
+ display: flex;
156
+ justify-content: center;
157
+ gap: 2.5rem;
158
+ width: 100%;
159
+ }
160
+
161
+ .ermis-call-ui__ringing-action {
162
+ display: flex;
163
+ flex-direction: column;
164
+ align-items: center;
165
+ gap: var(--ermis-spacing-sm);
166
+ }
167
+
168
+ .ermis-call-ui__action-circle {
169
+ width: 48px;
170
+ height: 48px;
171
+ border-radius: 50%;
172
+ border: none;
173
+ cursor: pointer;
174
+ display: flex;
175
+ align-items: center;
176
+ justify-content: center;
177
+ transition: transform var(--ermis-transition), box-shadow var(--ermis-transition),
178
+ background-color var(--ermis-transition);
179
+ color: #ffffff;
180
+ }
181
+
182
+ .ermis-call-ui__action-circle:hover {
183
+ transform: scale(1.1);
184
+ }
185
+
186
+ .ermis-call-ui__action-circle:active {
187
+ transform: scale(0.95);
188
+ }
189
+
190
+ .ermis-call-ui__action-circle--reject {
191
+ background-color: var(--ermis-color-danger);
192
+ box-shadow: 0 4px 20px rgba(239, 68, 68, 0.35);
193
+ }
194
+
195
+ .ermis-call-ui__action-circle--reject:hover {
196
+ background-color: var(--ermis-color-danger-hover);
197
+ box-shadow: 0 6px 28px rgba(239, 68, 68, 0.45);
198
+ }
199
+
200
+ .ermis-call-ui__action-circle--accept {
201
+ background-color: var(--ermis-color-success);
202
+ box-shadow: 0 4px 20px rgba(34, 197, 94, 0.35);
203
+ }
204
+
205
+ .ermis-call-ui__action-circle--accept:hover {
206
+ background-color: var(--ermis-color-success-hover);
207
+ box-shadow: 0 6px 28px rgba(34, 197, 94, 0.45);
208
+ }
209
+
210
+ .ermis-call-ui__action-circle svg {
211
+ width: 20px;
212
+ height: 20px;
213
+ }
214
+
215
+ .ermis-call-ui__action-label {
216
+ font-size: var(--ermis-font-size-xs);
217
+ color: var(--ermis-text-secondary);
218
+ font-weight: 500;
219
+ }
220
+
221
+ /* ============================================================
222
+ ACTIVE CALL STATE
223
+ ============================================================ */
224
+ .ermis-call-ui__active {
225
+ display: flex;
226
+ flex-direction: column;
227
+ width: 100%;
228
+ gap: 0;
229
+ }
230
+
231
+ /* -- Video Layout -- */
232
+ .ermis-call-ui__video-container {
233
+ position: relative;
234
+ width: 100%;
235
+ aspect-ratio: 16 / 9;
236
+ background-color: #000000;
237
+ border-radius: var(--ermis-radius-lg);
238
+ overflow: hidden;
239
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25);
240
+ }
241
+
242
+ .ermis-call-ui__video-remote {
243
+ width: 100%;
244
+ height: 100%;
245
+ object-fit: cover;
246
+ }
247
+
248
+ .ermis-call-ui__video-local {
249
+ position: absolute;
250
+ bottom: 72px;
251
+ right: 16px;
252
+ width: 140px;
253
+ aspect-ratio: 16 / 9;
254
+ background-color: #1a1a2e;
255
+ border-radius: var(--ermis-radius-md);
256
+ overflow: hidden;
257
+ border: 2px solid rgba(255, 255, 255, 0.25);
258
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
259
+ z-index: 10;
260
+ transition: transform var(--ermis-transition), box-shadow var(--ermis-transition);
261
+ }
262
+
263
+ .ermis-call-ui__video-local:hover {
264
+ border-color: rgba(255, 255, 255, 0.5);
265
+ box-shadow: 0 6px 24px rgba(0, 0, 0, 0.5);
266
+ }
267
+
268
+ .ermis-call-ui__video-local-stream {
269
+ width: 100%;
270
+ height: 100%;
271
+ object-fit: cover;
272
+ transform: scaleX(-1);
273
+ }
274
+
275
+ /* Remote peer muted mic badge */
276
+ .ermis-call-ui__remote-muted-badge {
277
+ position: absolute;
278
+ top: 16px;
279
+ left: 16px;
280
+ z-index: 15;
281
+ display: flex;
282
+ align-items: center;
283
+ justify-content: center;
284
+ width: 32px;
285
+ height: 32px;
286
+ border-radius: 50%;
287
+ background: rgba(239, 68, 68, 0.85);
288
+ color: #ffffff;
289
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
290
+ backdrop-filter: blur(8px);
291
+ -webkit-backdrop-filter: blur(8px);
292
+ }
293
+
294
+ .ermis-call-ui__remote-muted-badge svg {
295
+ width: 16px;
296
+ height: 16px;
297
+ }
298
+
299
+ /* Audio call: badge positioned relative to the avatar wrapper */
300
+ .ermis-call-ui__audio-avatar-wrapper {
301
+ position: relative;
302
+ display: inline-flex;
303
+ }
304
+
305
+ .ermis-call-ui__remote-muted-badge--audio {
306
+ position: absolute;
307
+ top: auto;
308
+ left: auto;
309
+ bottom: 2px;
310
+ right: 2px;
311
+ width: 28px;
312
+ height: 28px;
313
+ border: 2px solid var(--ermis-bg-secondary);
314
+ }
315
+
316
+ /* Glassmorphism controls overlay for video */
317
+ .ermis-call-ui__video-controls-overlay {
318
+ position: absolute;
319
+ bottom: 0;
320
+ left: 0;
321
+ right: 0;
322
+ display: flex;
323
+ justify-content: center;
324
+ padding: var(--ermis-spacing-md) var(--ermis-spacing-lg);
325
+ background: linear-gradient(transparent, rgba(0, 0, 0, 0.6));
326
+ }
327
+
328
+ /* -- Audio Layout -- */
329
+ .ermis-call-ui__audio-container {
330
+ text-align: center;
331
+ padding: 2.5rem var(--ermis-spacing-lg) 2rem;
332
+ display: flex;
333
+ flex-direction: column;
334
+ align-items: center;
335
+ background: var(--ermis-call-bg);
336
+ border-radius: var(--ermis-radius-lg);
337
+ position: relative;
338
+ overflow: hidden;
339
+ }
340
+
341
+ /* Audio wave visualizer */
342
+ .ermis-call-ui__audio-waves {
343
+ display: flex;
344
+ align-items: center;
345
+ justify-content: center;
346
+ gap: 3px;
347
+ height: 40px;
348
+ margin-bottom: var(--ermis-spacing-lg);
349
+ margin-top: var(--ermis-spacing-sm);
350
+ }
351
+
352
+ .ermis-call-ui__audio-wave-bar {
353
+ width: 3px;
354
+ border-radius: var(--ermis-radius-full);
355
+ background-color: var(--ermis-accent);
356
+ opacity: 0.6;
357
+ animation: ermis-call-wave 1.2s ease-in-out infinite;
358
+ }
359
+
360
+ .ermis-call-ui__audio-wave-bar:nth-child(1) {
361
+ height: 12px;
362
+ animation-delay: 0s;
363
+ }
364
+ .ermis-call-ui__audio-wave-bar:nth-child(2) {
365
+ height: 20px;
366
+ animation-delay: 0.1s;
367
+ }
368
+ .ermis-call-ui__audio-wave-bar:nth-child(3) {
369
+ height: 32px;
370
+ animation-delay: 0.2s;
371
+ }
372
+ .ermis-call-ui__audio-wave-bar:nth-child(4) {
373
+ height: 24px;
374
+ animation-delay: 0.3s;
375
+ }
376
+ .ermis-call-ui__audio-wave-bar:nth-child(5) {
377
+ height: 36px;
378
+ animation-delay: 0.15s;
379
+ }
380
+ .ermis-call-ui__audio-wave-bar:nth-child(6) {
381
+ height: 28px;
382
+ animation-delay: 0.25s;
383
+ }
384
+ .ermis-call-ui__audio-wave-bar:nth-child(7) {
385
+ height: 18px;
386
+ animation-delay: 0.35s;
387
+ }
388
+ .ermis-call-ui__audio-wave-bar:nth-child(8) {
389
+ height: 30px;
390
+ animation-delay: 0.05s;
391
+ }
392
+ .ermis-call-ui__audio-wave-bar:nth-child(9) {
393
+ height: 14px;
394
+ animation-delay: 0.4s;
395
+ }
396
+
397
+ @keyframes ermis-call-wave {
398
+ 0%,
399
+ 100% {
400
+ transform: scaleY(0.4);
401
+ }
402
+ 50% {
403
+ transform: scaleY(1);
404
+ }
405
+ }
406
+
407
+ /* Active call info */
408
+ .ermis-call-ui__active-name {
409
+ margin: var(--ermis-spacing-md) 0 var(--ermis-spacing-xs);
410
+ font-size: 1.35rem;
411
+ font-weight: 700;
412
+ color: var(--ermis-text-primary);
413
+ letter-spacing: -0.01em;
414
+ }
415
+
416
+ .ermis-call-ui__active-status {
417
+ display: flex;
418
+ align-items: center;
419
+ gap: var(--ermis-spacing-sm);
420
+ color: var(--ermis-text-secondary);
421
+ font-size: var(--ermis-font-size-sm);
422
+ margin-bottom: var(--ermis-spacing-sm);
423
+ }
424
+
425
+ .ermis-call-ui__active-status-dot {
426
+ width: 8px;
427
+ height: 8px;
428
+ border-radius: 50%;
429
+ background-color: var(--ermis-color-success);
430
+ animation: ermis-call-status-blink 2s ease-in-out infinite;
431
+ }
432
+
433
+ @keyframes ermis-call-status-blink {
434
+ 0%,
435
+ 100% {
436
+ opacity: 1;
437
+ }
438
+ 50% {
439
+ opacity: 0.4;
440
+ }
441
+ }
442
+
443
+ .ermis-call-ui__timer {
444
+ font-variant-numeric: tabular-nums;
445
+ font-weight: 500;
446
+ color: var(--ermis-text-secondary);
447
+ font-size: var(--ermis-font-size-sm);
448
+ }
449
+
450
+ /* ============================================================
451
+ CONTROLS BAR
452
+ ============================================================ */
453
+ .ermis-call-ui__controls {
454
+ display: flex;
455
+ justify-content: center;
456
+ align-items: center;
457
+ gap: var(--ermis-spacing-md);
458
+ padding: var(--ermis-spacing-md) var(--ermis-spacing-lg);
459
+ background: var(--ermis-call-glass);
460
+ backdrop-filter: blur(16px);
461
+ -webkit-backdrop-filter: blur(16px);
462
+ border: 1px solid var(--ermis-call-glass-border);
463
+ border-radius: var(--ermis-radius-full);
464
+ margin-top: var(--ermis-spacing-lg);
465
+ }
466
+
467
+ /* For video mode, controls float inside the video overlay */
468
+ .ermis-call-ui__video-controls-overlay .ermis-call-ui__controls {
469
+ margin-top: 0;
470
+ background: rgba(0, 0, 0, 0.4);
471
+ backdrop-filter: blur(20px);
472
+ -webkit-backdrop-filter: blur(20px);
473
+ border-color: rgba(255, 255, 255, 0.08);
474
+ }
475
+
476
+ .ermis-call-ui__controls-separator {
477
+ width: 1px;
478
+ height: 20px;
479
+ background: var(--ermis-call-glass-border);
480
+ margin: 0 var(--ermis-spacing-xs);
481
+ }
482
+
483
+ /* Control buttons — circular icons */
484
+ .ermis-call-ui__control-btn {
485
+ width: 34px;
486
+ height: 34px;
487
+ border-radius: 50%;
488
+ border: none;
489
+ background-color: var(--ermis-call-glass);
490
+ color: var(--ermis-text-primary);
491
+ cursor: pointer;
492
+ display: flex;
493
+ align-items: center;
494
+ justify-content: center;
495
+ transition: all var(--ermis-transition);
496
+ position: relative;
497
+ }
498
+
499
+ .ermis-call-ui__control-btn svg {
500
+ width: 16px;
501
+ height: 16px;
502
+ }
503
+
504
+ .ermis-call-ui__control-btn:hover {
505
+ background-color: var(--ermis-bg-hover);
506
+ transform: scale(1.08);
507
+ }
508
+
509
+ .ermis-call-ui__control-btn:active {
510
+ transform: scale(0.95);
511
+ }
512
+
513
+ /* Tooltip on hover */
514
+ .ermis-call-ui__control-btn::after {
515
+ content: attr(data-tooltip);
516
+ position: absolute;
517
+ bottom: calc(100% + 8px);
518
+ left: 50%;
519
+ transform: translateX(-50%) translateY(4px);
520
+ padding: 4px 10px;
521
+ background: var(--ermis-bg-primary);
522
+ color: var(--ermis-text-primary);
523
+ font-size: var(--ermis-font-size-xs);
524
+ border-radius: var(--ermis-radius-sm);
525
+ white-space: nowrap;
526
+ opacity: 0;
527
+ visibility: hidden;
528
+ transition: all var(--ermis-transition);
529
+ pointer-events: none;
530
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
531
+ border: 1px solid var(--ermis-call-glass-border);
532
+ }
533
+
534
+ .ermis-call-ui__control-btn:hover::after {
535
+ opacity: 1;
536
+ visibility: visible;
537
+ transform: translateX(-50%) translateY(0);
538
+ }
539
+
540
+ /* Video overlay tooltips need light text */
541
+ .ermis-call-ui__video-controls-overlay .ermis-call-ui__control-btn {
542
+ color: #ffffff;
543
+ }
544
+
545
+ .ermis-call-ui__video-controls-overlay .ermis-call-ui__control-btn::after {
546
+ background: rgba(0, 0, 0, 0.8);
547
+ color: #ffffff;
548
+ border-color: rgba(255, 255, 255, 0.1);
549
+ }
550
+
551
+ /* Muted state */
552
+ .ermis-call-ui__control-btn--muted {
553
+ background-color: rgba(239, 68, 68, 0.15);
554
+ color: var(--ermis-color-danger);
555
+ }
556
+
557
+ .ermis-call-ui__control-btn--muted:hover {
558
+ background-color: rgba(239, 68, 68, 0.25);
559
+ }
560
+
561
+ .ermis-call-ui__video-controls-overlay .ermis-call-ui__control-btn--muted {
562
+ background-color: rgba(239, 68, 68, 0.3);
563
+ color: #ffffff;
564
+ }
565
+
566
+ /* Active state (screen sharing) */
567
+ .ermis-call-ui__control-btn--active {
568
+ background-color: rgba(34, 197, 94, 0.15);
569
+ color: var(--ermis-color-success);
570
+ }
571
+
572
+ .ermis-call-ui__control-btn--active:hover {
573
+ background-color: rgba(34, 197, 94, 0.25);
574
+ }
575
+
576
+ .ermis-call-ui__video-controls-overlay .ermis-call-ui__control-btn--active {
577
+ background-color: rgba(34, 197, 94, 0.3);
578
+ color: #ffffff;
579
+ }
580
+
581
+ /* End call button — always solid danger */
582
+ .ermis-call-ui__control-btn--danger {
583
+ background-color: var(--ermis-color-danger);
584
+ color: #ffffff;
585
+ box-shadow: 0 2px 12px rgba(239, 68, 68, 0.3);
586
+ }
587
+
588
+ .ermis-call-ui__control-btn--danger:hover {
589
+ background-color: var(--ermis-color-danger-hover);
590
+ box-shadow: 0 4px 20px rgba(239, 68, 68, 0.4);
591
+ }
592
+
593
+ /* ============================================================
594
+ ACTION GROUPS & DEVICE SELECTORS
595
+ ============================================================ */
596
+ .ermis-call-ui__action-group {
597
+ display: flex;
598
+ flex-direction: column;
599
+ align-items: center;
600
+ position: relative;
601
+ }
602
+
603
+ .ermis-call-ui__device-select {
604
+ position: absolute;
605
+ bottom: calc(100% + 10px);
606
+ width: 160px;
607
+ left: 50%;
608
+ transform: translateX(-50%);
609
+ background: var(--ermis-bg-primary);
610
+ color: var(--ermis-text-primary);
611
+ border: 1px solid var(--ermis-call-glass-border);
612
+ border-radius: var(--ermis-radius-md);
613
+ padding: 6px 8px;
614
+ font-size: var(--ermis-font-size-xs);
615
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
616
+ outline: none;
617
+ cursor: pointer;
618
+ opacity: 0;
619
+ visibility: hidden;
620
+ transition: all var(--ermis-transition);
621
+ text-overflow: ellipsis;
622
+ overflow: hidden;
623
+ white-space: nowrap;
624
+ }
625
+
626
+ .ermis-call-ui__action-group:hover .ermis-call-ui__device-select {
627
+ opacity: 1;
628
+ visibility: visible;
629
+ }
630
+
631
+ .ermis-call-ui__device-select:focus {
632
+ border-color: var(--ermis-accent);
633
+ opacity: 1;
634
+ visibility: visible;
635
+ }
636
+
637
+ /* Video overlay device selects */
638
+ .ermis-call-ui__video-controls-overlay .ermis-call-ui__device-select {
639
+ background: rgba(0, 0, 0, 0.85);
640
+ border-color: rgba(255, 255, 255, 0.1);
641
+ color: #ffffff;
642
+ }
643
+
644
+ /* ============================================================
645
+ ERROR STATE
646
+ ============================================================ */
647
+ .ermis-call-ui__error {
648
+ display: flex;
649
+ flex-direction: column;
650
+ align-items: center;
651
+ justify-content: center;
652
+ padding: 3rem var(--ermis-spacing-lg);
653
+ text-align: center;
654
+ background: var(--ermis-call-bg);
655
+ border-radius: var(--ermis-radius-lg);
656
+ min-height: 280px;
657
+ width: 100%;
658
+ }
659
+
660
+ .ermis-call-ui__error-icon {
661
+ animation: ermis-call-shake 0.6s ease-in-out;
662
+ margin-bottom: var(--ermis-spacing-md);
663
+ }
664
+
665
+ @keyframes ermis-call-shake {
666
+ 0%,
667
+ 100% {
668
+ transform: translateX(0);
669
+ }
670
+ 15% {
671
+ transform: translateX(-8px);
672
+ }
673
+ 30% {
674
+ transform: translateX(8px);
675
+ }
676
+ 45% {
677
+ transform: translateX(-6px);
678
+ }
679
+ 60% {
680
+ transform: translateX(6px);
681
+ }
682
+ 75% {
683
+ transform: translateX(-3px);
684
+ }
685
+ 90% {
686
+ transform: translateX(3px);
687
+ }
688
+ }
689
+
690
+ .ermis-call-ui__error-text {
691
+ margin: 0 0 var(--ermis-spacing-lg);
692
+ color: var(--ermis-text-primary);
693
+ font-weight: 500;
694
+ font-size: 1.1rem;
695
+ line-height: 1.5;
696
+ max-width: 320px;
697
+ }
698
+
699
+ .ermis-call-ui__error-dismiss {
700
+ display: flex;
701
+ align-items: center;
702
+ gap: var(--ermis-spacing-sm);
703
+ padding: 12px 28px;
704
+ border-radius: var(--ermis-radius-full);
705
+ border: none;
706
+ font-weight: 600;
707
+ font-size: var(--ermis-font-size-base);
708
+ cursor: pointer;
709
+ transition: all var(--ermis-transition);
710
+ background-color: var(--ermis-color-danger);
711
+ color: #ffffff;
712
+ box-shadow: 0 2px 12px rgba(239, 68, 68, 0.3);
713
+ }
714
+
715
+ .ermis-call-ui__error-dismiss:hover {
716
+ background-color: var(--ermis-color-danger-hover);
717
+ box-shadow: 0 4px 20px rgba(239, 68, 68, 0.4);
718
+ transform: scale(1.02);
719
+ }
720
+
721
+ .ermis-call-ui__error-dismiss:active {
722
+ transform: scale(0.98);
723
+ }
724
+
725
+ /* ============================================================
726
+ REDUCED MOTION
727
+ ============================================================ */
728
+ @media (prefers-reduced-motion: reduce) {
729
+ .ermis-call-ui__ringing-avatar::before,
730
+ .ermis-call-ui__ringing-avatar::after,
731
+ .ermis-call-ui__ringing-avatar-inner,
732
+ .ermis-call-ui__audio-wave-bar,
733
+ .ermis-call-ui__active-status-dot,
734
+ .ermis-call-ui__error-icon {
735
+ animation: none;
736
+ }
737
+
738
+ .ermis-call-ui__action-circle:hover,
739
+ .ermis-call-ui__control-btn:hover,
740
+ .ermis-call-ui__error-dismiss:hover {
741
+ transform: none;
742
+ }
743
+ }