@lumir-company/editor 0.4.22 → 0.4.25

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.
package/dist/style.css CHANGED
@@ -1,1457 +1,1463 @@
1
- @import '@blocknote/core/fonts/inter.css';
2
- @import '@blocknote/mantine/style.css';
3
- @import '@blocknote/react/style.css';
4
-
5
- /* Pretendard 한글 글꼴 (가변 폰트, swap).
6
- @import url()은 번들 시 @import 순서 규칙을 위반해 사용 불가 → @font-face로 로드.
7
- 호스트 앱이 Pretendard를 자체 로드한다면 이 블록은 제거해도 된다. */
8
- @font-face {
9
- font-family: 'Pretendard';
10
- font-weight: 100 900;
11
- font-style: normal;
12
- font-display: swap;
13
- src: url('https://cdn.jsdelivr.net/npm/pretendard@1.3.9/dist/web/variable/woff2/PretendardVariable.woff2')
14
- format('woff2-variations');
15
- }
16
-
17
- .lumirEditor {
18
- width: 100%;
19
- height: 100%;
20
- min-width: 200px;
21
- overflow: visible; /* 슬래시 메뉴가 컨테이너를 넘어서 표시되도록 변경 */
22
- background-color: #ffffff;
23
- /* 에디터 전체(본문·툴바·인-DOM 드롭다운) 한글 글꼴 Pretendard */
24
- font-family:
25
- 'Pretendard',
26
- 'Noto Sans KR',
27
- -apple-system,
28
- BlinkMacSystemFont,
29
- 'Segoe UI',
30
- 'Roboto',
31
- sans-serif;
32
- }
33
-
34
- /* 에디터 내부 콘텐츠 영역만 스크롤 가능하게 설정 */
35
- .lumirEditor .bn-container {
36
- overflow: auto;
37
- max-height: 100%;
38
- }
39
-
40
- /* 슬래시 메뉴(SuggestionMenu)가 컨테이너를 넘어서 표시되도록 */
41
- .bn-suggestion-menu,
42
- .bn-slash-menu,
43
- .mantine-Menu-dropdown,
44
- .mantine-Popover-dropdown {
45
- z-index: 9999 !important;
46
- }
47
-
48
- /* 포털(body)로 빠지는 메뉴/드롭다운에도 Pretendard 적용 */
49
- .bn-suggestion-menu,
50
- .bn-slash-menu,
51
- .mantine-Menu-dropdown,
52
- .mantine-Popover-dropdown,
53
- .bn-table-handle-menu,
54
- .bn-menu-dropdown {
55
- font-family:
56
- 'Pretendard',
57
- 'Noto Sans KR',
58
- -apple-system,
59
- BlinkMacSystemFont,
60
- 'Segoe UI',
61
- 'Roboto',
62
- sans-serif;
63
- }
64
- /* 포커스 상태 스타일 - 테두리 없음 */
65
- .lumirEditor:focus-within {
66
- outline: none;
67
- box-shadow: none;
68
- }
69
- .lumirEditor {
70
- border: none;
71
- }
72
-
73
- /* BlockNote 에디터 내부 폰트 설정 */
74
- .lumirEditor .bn-editor,
75
- .lumirEditor .bn-inline-content {
76
- font-family:
77
- 'Pretendard',
78
- 'Noto Sans KR',
79
- -apple-system,
80
- BlinkMacSystemFont,
81
- 'Segoe UI',
82
- 'Roboto',
83
- 'Oxygen',
84
- 'Ubuntu',
85
- 'Cantarell',
86
- sans-serif;
87
- }
88
-
89
- /* 링크 스타일 - Tailwind Preflight 리셋 복원 */
90
- .lumirEditor .bn-editor a,
91
- .lumirEditor .bn-inline-content a {
92
- color: #0b6e99;
93
- text-decoration: underline;
94
- text-underline-offset: 2px;
95
- cursor: pointer;
96
- }
97
-
98
- .lumirEditor .bn-editor a:hover,
99
- .lumirEditor .bn-inline-content a:hover {
100
- color: #0b6e99;
101
- }
102
-
103
- /* CSS 변수를 사용한 패딩 설정 */
104
- .lumirEditor .bn-editor {
105
- padding-left: 25px;
106
- padding-right: 10px;
107
- padding-top: 5px;
108
- padding-bottom: 0;
109
- }
110
-
111
- /*
112
- * 본문·번호·글머리·체크 목록 인라인 텍스트 14px 통일
113
- * BlockNote `.bn-default-styles { font-size: 16px }` + `p { font-size: inherit }` 때문에
114
- * `p.bn-inline-content`에 명시적으로 14px (`.bn-block-content`에 data-type이 붙음)
115
- */
116
- .lumirEditor
117
- .bn-block-content[data-content-type='paragraph']
118
- p.bn-inline-content,
119
- .lumirEditor
120
- .bn-block-content[data-content-type='numberedListItem']
121
- p.bn-inline-content,
122
- .lumirEditor
123
- .bn-block-content[data-content-type='bulletListItem']
124
- p.bn-inline-content,
125
- .lumirEditor
126
- .bn-block-content[data-content-type='checkListItem']
127
- p.bn-inline-content {
128
- font-size: 14px;
129
- }
130
-
131
- /* 마커(번호·불릿)·체크 행 */
132
- .lumirEditor .bn-block-content[data-content-type='numberedListItem'],
133
- .lumirEditor .bn-block-content[data-content-type='bulletListItem'],
134
- .lumirEditor .bn-block-content[data-content-type='checkListItem'] {
135
- font-size: 14px;
136
- }
137
-
138
- .lumirEditor .bn-block-content {
139
- max-width: 100%;
140
- }
141
-
142
- /* File Panel: Embed 탭 미노출 (URL 입력 방식 비활성화) */
143
- .lumirEditor [data-test='embed-tab'] {
144
- display: none !important;
145
- }
146
-
147
- /* 정렬된 블록의 인라인 콘텐츠 - 빈 블록에서 스크롤 방지 */
148
- .lumirEditor .bn-inline-content {
149
- overflow: hidden;
150
- max-width: 100%;
151
- min-width: 0;
152
- }
153
-
154
- /* 우측 정렬 시 빈 블록 placeholder 위치 수정 */
155
- .lumirEditor [data-text-alignment='right'] .bn-inline-content::before {
156
- position: relative;
157
- max-width: 100%;
158
- }
159
-
160
- /* 이미지 업로드 로딩 스피너 */
161
- .lumirEditor-upload-overlay {
162
- position: absolute;
163
- top: 0;
164
- left: 0;
165
- right: 0;
166
- bottom: 0;
167
- display: flex;
168
- flex-direction: column;
169
- align-items: center;
170
- justify-content: center;
171
- gap: 8px;
172
- background-color: rgba(255, 255, 255, 0.8);
173
- backdrop-filter: blur(2px);
174
- z-index: 1000;
175
- }
176
-
177
- .lumirEditor-spinner {
178
- width: 30px;
179
- height: 30px;
180
- border: 3px solid #f3f3f3;
181
- border-top: 3px solid #3b82f6;
182
- border-radius: 50%;
183
- animation: lumir-spin 1s linear infinite;
184
- }
185
-
186
- .lumirEditor-upload-progress {
187
- font-size: 14px;
188
- font-weight: 500;
189
- color: #374151;
190
- }
191
-
192
- @keyframes lumir-spin {
193
- 0% {
194
- transform: rotate(0deg);
195
- }
196
- 100% {
197
- transform: rotate(360deg);
198
- }
199
- }
200
-
201
- /* ========================================
202
- Floating Toolbar 스타일 (컴팩트 + 반응형)
203
- ======================================== */
204
-
205
- /* CSS 변수 정의 */
206
- .lumir-floating-toolbar-wrapper {
207
- --lumir-bg-light: #fafaf9;
208
- --lumir-bg-dark: #1c1917;
209
- --lumir-paper-light: #ffffff;
210
- --lumir-paper-dark: #292524;
211
- --lumir-border-light: #e7e5e4;
212
- --lumir-border-dark: #44403c;
213
- --lumir-text-light: #1c1917;
214
- --lumir-text-dark: #fafaf9;
215
- --lumir-text-muted-light: #78716c;
216
- --lumir-text-muted-dark: #a8a29e;
217
- --lumir-hover-light: #f5f5f4;
218
- --lumir-hover-dark: #44403c;
219
- --lumir-active-bg: rgba(59, 130, 246, 0.1);
220
- --lumir-active-color: #3b82f6;
221
- --lumir-radius-lg: 0.5rem;
222
- --lumir-radius-md: 0.25rem;
223
- --lumir-transition: 0.15s cubic-bezier(0.4, 0, 0.2, 1);
224
- --lumir-btn-size: 28px;
225
- --lumir-btn-padding: 6px;
226
- --lumir-icon-size: 16px;
227
- }
228
-
229
- /* Toolbar Wrapper */
230
- .lumir-floating-toolbar-wrapper {
231
- width: 100%;
232
- display: flex;
233
- justify-content: center;
234
- padding: 8px 12px;
235
- z-index: 40;
236
- }
237
-
238
- /* 최소화 모드일 때는 좌측 상단 배치 */
239
- .lumir-floating-toolbar-wrapper.is-minimizable {
240
- justify-content: flex-start;
241
- padding: 0;
242
- }
243
-
244
- .lumir-floating-toolbar-wrapper[data-position='sticky'] {
245
- position: sticky;
246
- top: 0;
247
- }
248
-
249
- .lumir-floating-toolbar-wrapper[data-position='fixed'] {
250
- position: fixed;
251
- top: 64px;
252
- left: 0;
253
- right: 0;
254
- }
255
-
256
- /* Toolbar Container - 항상 밝은 배경 유지 */
257
- .lumir-floating-toolbar {
258
- display: flex;
259
- flex-wrap: wrap;
260
- align-items: center;
261
- gap: 2px;
262
- padding: 4px;
263
- background-color: #ffffff !important;
264
- border: 1px solid #e5e7eb !important;
265
- border-radius: var(--lumir-radius-lg);
266
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
267
- max-width: 100%;
268
- font-family: ui-sans-serif, system-ui, sans-serif;
269
- font-size: 13px;
270
- }
271
-
272
- /* 1단 레이아웃 (넓은 화면) */
273
- .lumir-floating-toolbar {
274
- flex-wrap: nowrap;
275
- }
276
-
277
- /* 2단 레이아웃 (좁은 화면) */
278
- .lumir-floating-toolbar.is-compact {
279
- flex-wrap: wrap;
280
- justify-content: center;
281
- }
282
-
283
- .lumir-floating-toolbar.is-compact .lumir-toolbar-row {
284
- display: flex;
285
- align-items: center;
286
- width: 100%;
287
- justify-content: center;
288
- gap: 2px;
289
- }
290
-
291
- .lumir-floating-toolbar.is-compact .lumir-toolbar-row:not(:last-child) {
292
- padding-bottom: 4px;
293
- border-bottom: 1px solid var(--lumir-border-light);
294
- margin-bottom: 4px;
295
- }
296
-
297
- /* 최소화 가능 레이아웃 (400px 이하) */
298
- .lumir-floating-toolbar.is-minimizable {
299
- flex-wrap: wrap; /* 여러 줄로 확장 가능 */
300
- justify-content: flex-start; /* 좌측 정렬 */
301
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
302
- padding: 0; /* 내부 공백 제거 */
303
- }
304
-
305
- /* 토글 버튼 스타일 */
306
- .lumir-floating-toolbar.is-minimizable .lumir-toggle-button {
307
- order: -1; /* 항상 맨 앞에 배치 */
308
- flex-shrink: 0;
309
- width: 24px; /* 컴팩트한 크기 */
310
- height: 24px;
311
- padding: 0; /* 패딩 제거하여 정확한 정렬 */
312
- margin: 0;
313
- border-radius: 4px;
314
- display: flex;
315
- align-items: center;
316
- justify-content: center;
317
- cursor: pointer;
318
- transition: transform 0.2s ease;
319
- }
320
-
321
- .lumir-floating-toolbar.is-minimizable .lumir-toggle-button:hover {
322
- transform: scale(1.1);
323
- }
324
-
325
- .lumir-floating-toolbar.is-minimizable .lumir-toggle-button svg {
326
- width: 16px;
327
- height: 16px;
328
- display: block; /* inline 여백 제거 */
329
- transition: transform 0.3s ease;
330
- }
331
-
332
- /* 메뉴 항목 애니메이션 */
333
- .lumir-floating-toolbar.is-minimizable > *:not(.lumir-toggle-button) {
334
- opacity: 1;
335
- transform: translateX(0);
336
- transition:
337
- opacity 0.3s ease,
338
- transform 0.3s ease;
339
- }
340
-
341
- /* 최소화 상태 - 토글 버튼만 표시 */
342
- .lumir-floating-toolbar.is-minimizable.is-minimized {
343
- width: auto;
344
- min-width: 24px;
345
- padding: 0;
346
- border: none;
347
- background: transparent !important;
348
- box-shadow: none;
349
- }
350
-
351
- .lumir-floating-toolbar.is-minimizable.is-minimized
352
- > *:not(.lumir-toggle-button) {
353
- opacity: 0;
354
- transform: translateX(-10px);
355
- pointer-events: none;
356
- max-width: 0;
357
- overflow: hidden;
358
- margin: 0;
359
- padding: 0;
360
- }
361
-
362
- /* Toolbar Group */
363
- .lumir-toolbar-group {
364
- display: flex;
365
- align-items: center;
366
- gap: 1px;
367
- padding: 0 2px;
368
- }
369
-
370
- /* Divider */
371
- .lumir-toolbar-divider {
372
- width: 1px;
373
- height: 18px;
374
- background-color: var(--lumir-border-light);
375
- margin: 0 2px;
376
- flex-shrink: 0;
377
- }
378
-
379
- /* 2단에서 divider 숨기기 */
380
- .lumir-floating-toolbar.is-compact .lumir-toolbar-divider.row-break {
381
- display: none;
382
- }
383
-
384
- /* Toolbar Button (컴팩트) */
385
- .lumir-toolbar-btn {
386
- display: flex;
387
- align-items: center;
388
- justify-content: center;
389
- width: var(--lumir-btn-size);
390
- height: var(--lumir-btn-size);
391
- padding: var(--lumir-btn-padding);
392
- border: none;
393
- background: transparent;
394
- color: var(--lumir-text-muted-light);
395
- cursor: pointer;
396
- border-radius: var(--lumir-radius-md);
397
- transition: all var(--lumir-transition);
398
- position: relative;
399
- flex-shrink: 0;
400
- }
401
-
402
- .lumir-toolbar-btn svg {
403
- width: var(--lumir-icon-size);
404
- height: var(--lumir-icon-size);
405
- }
406
-
407
- .lumir-toolbar-btn:hover {
408
- background-color: var(--lumir-hover-light);
409
- color: var(--lumir-text-light);
410
- }
411
-
412
- .lumir-toolbar-btn.is-active {
413
- background-color: var(--lumir-active-bg);
414
- color: var(--lumir-active-color);
415
- }
416
-
417
- .lumir-toolbar-btn:disabled {
418
- opacity: 0.4;
419
- cursor: not-allowed;
420
- }
421
-
422
- /* 색상 버튼 인디케이터 */
423
- .lumir-color-btn {
424
- flex-direction: column;
425
- gap: 1px;
426
- width: var(--lumir-btn-size);
427
- height: var(--lumir-btn-size);
428
- padding: 4px;
429
- }
430
-
431
- .lumir-color-btn svg {
432
- width: 14px;
433
- height: 14px;
434
- }
435
-
436
- .lumir-color-indicator {
437
- width: 12px;
438
- height: 2px;
439
- border-radius: 1px;
440
- border: 1px solid rgba(0, 0, 0, 0.1);
441
- }
442
-
443
- /* SVG 아이콘 스타일 */
444
- .lumir-toolbar-btn svg,
445
- .lumir-dropdown-btn svg {
446
- flex-shrink: 0;
447
- }
448
-
449
- /* Dropdown Wrapper */
450
- .lumir-dropdown-wrapper {
451
- position: relative;
452
- }
453
-
454
- /* Dropdown Button (컴팩트) */
455
- .lumir-dropdown-btn {
456
- display: flex;
457
- align-items: center;
458
- justify-content: space-between;
459
- min-width: 90px;
460
- max-width: 110px;
461
- height: var(--lumir-btn-size);
462
- padding: 4px 8px;
463
- border: none;
464
- background: transparent;
465
- color: inherit;
466
- cursor: pointer;
467
- border-radius: var(--lumir-radius-md);
468
- font-size: 12px;
469
- font-weight: 500;
470
- transition: all var(--lumir-transition);
471
- gap: 2px;
472
- white-space: nowrap;
473
- overflow: hidden;
474
- }
475
-
476
- .lumir-dropdown-btn span {
477
- overflow: hidden;
478
- text-overflow: ellipsis;
479
- }
480
-
481
- .lumir-dropdown-btn:hover {
482
- background-color: var(--lumir-hover-light);
483
- }
484
-
485
- .lumir-dropdown-btn svg {
486
- width: 14px;
487
- height: 14px;
488
- flex-shrink: 0;
489
- color: var(--lumir-text-muted-light);
490
- }
491
-
492
- /* Dropdown Menu - 항상 밝은 배경 유지 */
493
- .lumir-dropdown-menu {
494
- position: absolute;
495
- top: calc(100% + 4px);
496
- left: 0;
497
- min-width: 160px;
498
- background-color: #ffffff !important;
499
- border: 1px solid #e5e7eb !important;
500
- border-radius: 10px;
501
- box-shadow:
502
- 0 4px 16px rgba(0, 0, 0, 0.12),
503
- 0 0 0 1px rgba(0, 0, 0, 0.04);
504
- z-index: 9999;
505
- padding: 6px;
506
- animation: lumir-dropdown-appear 0.15s ease;
507
- }
508
-
509
- @keyframes lumir-dropdown-appear {
510
- from {
511
- opacity: 0;
512
- transform: translateY(-4px);
513
- }
514
- to {
515
- opacity: 1;
516
- transform: translateY(0);
517
- }
518
- }
519
-
520
- /* Dropdown Item - 항상 밝은 스타일 */
521
- .lumir-dropdown-item {
522
- display: flex;
523
- align-items: center;
524
- width: 100%;
525
- padding: 8px 12px;
526
- text-align: left;
527
- border: none;
528
- background: transparent;
529
- color: #374151 !important;
530
- cursor: pointer;
531
- border-radius: 6px;
532
- font-size: 14px;
533
- transition: background-color 0.1s ease;
534
- }
535
-
536
- .lumir-dropdown-item:hover {
537
- background-color: #f3f4f6 !important;
538
- }
539
-
540
- .lumir-dropdown-item.is-active {
541
- background-color: rgba(59, 130, 246, 0.1) !important;
542
- color: #3b82f6 !important;
543
- }
544
-
545
- /* Font Size Dropdown Button (글자 크기) */
546
- .lumir-font-size-btn {
547
- min-width: 52px;
548
- max-width: 72px;
549
- }
550
-
551
- .lumir-font-size-label {
552
- flex: 1;
553
- text-align: center;
554
- }
555
-
556
- .lumir-font-size-menu {
557
- min-width: 96px;
558
- max-height: 280px;
559
- overflow-y: auto;
560
- }
561
-
562
- /* Font Size 1px Stepper (글자 크기 −/+ + 직접 입력) — 두 드롭다운(FormattingToolbar/FloatingMenu) 공용 */
563
- .lumir-fs-stepper {
564
- display: flex;
565
- align-items: center;
566
- justify-content: center;
567
- gap: 4px;
568
- padding: 6px 8px;
569
- border-bottom: 1px solid #e5e7eb;
570
- }
571
-
572
- .lumir-fs-stepper-btn {
573
- width: 24px;
574
- height: 24px;
575
- display: flex;
576
- align-items: center;
577
- justify-content: center;
578
- border: 1px solid #d1d5db;
579
- border-radius: 4px;
580
- background: #fff;
581
- color: #374151;
582
- cursor: pointer;
583
- font-size: 14px;
584
- line-height: 1;
585
- flex-shrink: 0;
586
- }
587
-
588
- .lumir-fs-stepper-btn:hover:not(:disabled) {
589
- background: #f3f4f6;
590
- }
591
-
592
- .lumir-fs-stepper-btn:disabled {
593
- opacity: 0.4;
594
- cursor: default;
595
- }
596
-
597
- .lumir-fs-stepper-input {
598
- width: 40px;
599
- text-align: center;
600
- border: 1px solid #d1d5db;
601
- border-radius: 4px;
602
- padding: 3px 2px;
603
- font-size: 13px;
604
- color: #111827;
605
- background: #fff;
606
- -moz-appearance: textfield;
607
- appearance: textfield;
608
- }
609
-
610
- .lumir-fs-stepper-input:focus {
611
- outline: none;
612
- border-color: #3b82f6;
613
- }
614
-
615
- .lumir-fs-stepper-input::-webkit-outer-spin-button,
616
- .lumir-fs-stepper-input::-webkit-inner-spin-button {
617
- -webkit-appearance: none;
618
- margin: 0;
619
- }
620
-
621
- /* Block Type Dropdown Button */
622
- .lumir-block-type-btn {
623
- min-width: 110px;
624
- max-width: 130px;
625
- gap: 4px;
626
- padding: 4px 8px;
627
- }
628
-
629
- .lumir-block-icon {
630
- display: flex;
631
- align-items: center;
632
- justify-content: center;
633
- width: 22px;
634
- height: 22px;
635
- flex-shrink: 0;
636
- color: #6b7280;
637
- }
638
-
639
- .lumir-block-icon svg {
640
- width: 18px;
641
- height: 18px;
642
- }
643
-
644
- .lumir-block-icon-text {
645
- font-size: 13px;
646
- font-weight: 700;
647
- color: #6b7280;
648
- line-height: 1;
649
- }
650
-
651
- .lumir-block-label {
652
- flex: 1;
653
- text-align: left;
654
- overflow: hidden;
655
- text-overflow: ellipsis;
656
- white-space: nowrap;
657
- font-size: 13px;
658
- }
659
-
660
- /* Block Type Dropdown Menu - 최대 컴팩트 */
661
- .lumir-block-menu {
662
- min-width: 160px;
663
- max-height: 320px;
664
- overflow-y: auto;
665
- padding: 3px;
666
- }
667
-
668
- /* 커스텀 스크롤바 - 더 얇게 */
669
- .lumir-block-menu::-webkit-scrollbar {
670
- width: 4px;
671
- }
672
-
673
- .lumir-block-menu::-webkit-scrollbar-track {
674
- background: transparent;
675
- }
676
-
677
- .lumir-block-menu::-webkit-scrollbar-thumb {
678
- background-color: #d1d5db;
679
- border-radius: 2px;
680
- }
681
-
682
- .lumir-block-menu::-webkit-scrollbar-thumb:hover {
683
- background-color: #9ca3af;
684
- }
685
-
686
- /* Block Type Menu Item - 최대 컴팩트 */
687
- .lumir-block-item {
688
- display: flex;
689
- align-items: center;
690
- gap: 6px;
691
- padding: 4px 8px;
692
- border-radius: 4px;
693
- margin-bottom: 0;
694
- transition: all 0.1s ease;
695
- }
696
-
697
- .lumir-block-item:last-child {
698
- margin-bottom: 0;
699
- }
700
-
701
- .lumir-block-item .lumir-block-icon {
702
- width: 20px;
703
- height: 20px;
704
- background-color: #f3f4f6;
705
- border-radius: 3px;
706
- display: flex;
707
- align-items: center;
708
- justify-content: center;
709
- flex-shrink: 0;
710
- }
711
-
712
- .lumir-block-item .lumir-block-icon svg {
713
- width: 14px;
714
- height: 14px;
715
- }
716
-
717
- .lumir-block-item .lumir-block-icon-text {
718
- font-size: 10px;
719
- font-weight: 700;
720
- }
721
-
722
- .lumir-block-item-title {
723
- font-size: 12px;
724
- font-weight: 500;
725
- color: #374151;
726
- }
727
-
728
- .lumir-block-item:hover {
729
- background-color: #f3f4f6 !important;
730
- }
731
-
732
- .lumir-block-item:hover .lumir-block-icon {
733
- background-color: #e5e7eb;
734
- color: #374151;
735
- }
736
-
737
- .lumir-block-item:hover .lumir-block-icon-text {
738
- color: #374151;
739
- }
740
-
741
- .lumir-block-item.is-active {
742
- background-color: rgba(59, 130, 246, 0.08) !important;
743
- }
744
-
745
- .lumir-block-item.is-active .lumir-block-icon {
746
- background-color: rgba(59, 130, 246, 0.15);
747
- color: #3b82f6;
748
- }
749
-
750
- .lumir-block-item.is-active .lumir-block-icon-text {
751
- color: #3b82f6;
752
- }
753
-
754
- /* Block Type Category - 최대 컴팩트 */
755
- .lumir-block-category {
756
- margin-bottom: 2px;
757
- }
758
-
759
- .lumir-block-category:last-child {
760
- margin-bottom: 0;
761
- }
762
-
763
- .lumir-block-category-title {
764
- font-size: 9px;
765
- font-weight: 600;
766
- color: #9ca3af;
767
- text-transform: uppercase;
768
- letter-spacing: 0.05em;
769
- padding: 4px 8px 2px;
770
- margin-bottom: 0;
771
- }
772
-
773
- /* Block Item Title */
774
- .lumir-block-item:hover .lumir-block-item-title {
775
- color: #1f2937;
776
- }
777
-
778
- .lumir-block-item.is-active .lumir-block-item-title {
779
- color: #3b82f6;
780
- font-weight: 600;
781
- }
782
-
783
- /* Toggle Heading 아이콘 - 컴팩트 */
784
- .lumir-block-icon-toggle {
785
- display: flex;
786
- align-items: center;
787
- gap: 2px;
788
- font-size: 9px;
789
- font-weight: 700;
790
- color: #6b7280;
791
- line-height: 1;
792
- }
793
-
794
- .lumir-block-icon-toggle svg {
795
- width: 6px;
796
- height: 6px;
797
- flex-shrink: 0;
798
- }
799
-
800
- .lumir-block-icon-toggle span {
801
- font-size: 9px;
802
- font-weight: 700;
803
- }
804
-
805
- .lumir-block-item .lumir-block-icon-toggle {
806
- font-size: 10px;
807
- }
808
-
809
- .lumir-block-item .lumir-block-icon-toggle svg {
810
- width: 7px;
811
- height: 7px;
812
- }
813
-
814
- .lumir-block-item .lumir-block-icon-toggle span {
815
- font-size: 10px;
816
- }
817
-
818
- .lumir-block-item:hover .lumir-block-icon-toggle,
819
- .lumir-block-item.is-active .lumir-block-icon-toggle {
820
- color: inherit;
821
- }
822
-
823
- /* Color Picker Menu */
824
- .lumir-color-menu {
825
- min-width: 180px;
826
- padding: 8px;
827
- }
828
-
829
- .lumir-color-grid {
830
- display: grid;
831
- grid-template-columns: repeat(5, 1fr);
832
- gap: 6px;
833
- }
834
-
835
- .lumir-color-swatch {
836
- width: 28px;
837
- height: 28px;
838
- border: 1px solid rgba(0, 0, 0, 0.15);
839
- border-radius: 4px;
840
- cursor: pointer;
841
- transition: all 0.15s ease;
842
- position: relative;
843
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
844
- }
845
-
846
- .lumir-color-swatch:hover {
847
- transform: scale(1.15);
848
- border-color: #3b82f6;
849
- box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
850
- z-index: 1;
851
- }
852
-
853
- .lumir-color-swatch.is-active {
854
- border-color: #3b82f6;
855
- border-width: 2px;
856
- box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3);
857
- }
858
-
859
- .lumir-color-swatch.is-active::after {
860
- content: '✓';
861
- position: absolute;
862
- top: 50%;
863
- left: 50%;
864
- transform: translate(-50%, -50%);
865
- color: #ffffff;
866
- font-size: 12px;
867
- font-weight: bold;
868
- text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
869
- }
870
-
871
- .lumir-color-remove {
872
- width: 100%;
873
- padding: 6px 8px;
874
- border: none;
875
- background-color: #f3f4f6;
876
- color: #6b7280;
877
- font-size: 11px;
878
- font-weight: 500;
879
- border-radius: 4px;
880
- cursor: pointer;
881
- transition: all 0.15s ease;
882
- }
883
-
884
- .lumir-color-remove:hover {
885
- background-color: #e5e7eb;
886
- color: #374151;
887
- }
888
-
889
- /* Text Controls Group */
890
- .lumir-text-controls {
891
- gap: 8px;
892
- }
893
-
894
- /* Link Input Menu - Compact */
895
- .lumir-link-menu {
896
- min-width: 240px;
897
- padding: 8px;
898
- left: auto;
899
- right: 0;
900
- }
901
-
902
- .lumir-link-form {
903
- display: flex;
904
- flex-direction: column;
905
- gap: 6px;
906
- }
907
-
908
- .lumir-link-input {
909
- width: 100%;
910
- padding: 6px 8px;
911
- border: 1px solid #d1d5db;
912
- border-radius: 4px;
913
- font-size: 12px;
914
- font-family: inherit;
915
- outline: none;
916
- transition: all 0.15s ease;
917
- }
918
-
919
- .lumir-link-input:focus {
920
- border-color: #3b82f6;
921
- box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
922
- }
923
-
924
- .lumir-link-input::placeholder {
925
- color: #9ca3af;
926
- font-size: 11px;
927
- }
928
-
929
- .lumir-link-actions {
930
- display: flex;
931
- gap: 4px;
932
- justify-content: flex-end;
933
- }
934
-
935
- .lumir-link-btn {
936
- padding: 4px 10px;
937
- border: none;
938
- border-radius: 4px;
939
- font-size: 11px;
940
- font-weight: 500;
941
- cursor: pointer;
942
- transition: all 0.15s ease;
943
- }
944
-
945
- .lumir-link-cancel {
946
- background-color: #f3f4f6;
947
- color: #6b7280;
948
- }
949
-
950
- .lumir-link-cancel:hover {
951
- background-color: #e5e7eb;
952
- color: #374151;
953
- }
954
-
955
- .lumir-link-submit {
956
- background-color: #3b82f6;
957
- color: #ffffff;
958
- }
959
-
960
- .lumir-link-submit:hover:not(:disabled) {
961
- background-color: #2563eb;
962
- }
963
-
964
- .lumir-link-submit:disabled {
965
- opacity: 0.5;
966
- cursor: not-allowed;
967
- }
968
-
969
- /*
970
- * 플로팅 툴바는 다크모드와 관계없이 항상 밝은 스타일 유지
971
- * 다크모드 오버라이드를 적용하지 않음
972
- */
973
-
974
- /* ========================================
975
- 에러 토스트 스타일
976
- ======================================== */
977
-
978
- .lumirEditor-error-toast {
979
- position: absolute;
980
- bottom: 16px;
981
- left: 50%;
982
- transform: translateX(-50%);
983
- display: flex;
984
- align-items: center;
985
- gap: 8px;
986
- padding: 12px 16px;
987
- background-color: #fef2f2;
988
- border: 1px solid #fecaca;
989
- border-radius: 8px;
990
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
991
- z-index: 1001;
992
- animation: lumirEditor-toast-appear 0.3s ease;
993
- max-width: 90%;
994
- }
995
-
996
- @keyframes lumirEditor-toast-appear {
997
- from {
998
- opacity: 0;
999
- transform: translateX(-50%) translateY(10px);
1000
- }
1001
- to {
1002
- opacity: 1;
1003
- transform: translateX(-50%) translateY(0);
1004
- }
1005
- }
1006
-
1007
- .lumirEditor-error-icon {
1008
- flex-shrink: 0;
1009
- font-size: 16px;
1010
- }
1011
-
1012
- .lumirEditor-error-message {
1013
- font-size: 13px;
1014
- font-weight: 500;
1015
- color: #991b1b;
1016
- line-height: 1.4;
1017
- }
1018
-
1019
- .lumirEditor-error-close {
1020
- flex-shrink: 0;
1021
- display: flex;
1022
- align-items: center;
1023
- justify-content: center;
1024
- width: 20px;
1025
- height: 20px;
1026
- padding: 0;
1027
- border: none;
1028
- background: transparent;
1029
- color: #991b1b;
1030
- font-size: 14px;
1031
- cursor: pointer;
1032
- border-radius: 4px;
1033
- transition: background-color 0.15s ease;
1034
- }
1035
-
1036
- .lumirEditor-error-close:hover {
1037
- background-color: #fee2e2;
1038
- }
1039
-
1040
- /* ========================================
1041
- Link Preview 카드 스타일
1042
- ======================================== */
1043
-
1044
- @keyframes lumir-skeleton-pulse {
1045
- 0% {
1046
- opacity: 1;
1047
- }
1048
- 50% {
1049
- opacity: 0.4;
1050
- }
1051
- 100% {
1052
- opacity: 1;
1053
- }
1054
- }
1055
-
1056
- .lumir-link-preview-card:hover .lumir-link-preview-delete {
1057
- opacity: 1 !important;
1058
- }
1059
-
1060
- .lumir-link-preview-delete:hover {
1061
- background-color: rgba(0, 0, 0, 0.7) !important;
1062
- }
1063
-
1064
- .lumir-resize-handle {
1065
- position: absolute;
1066
- width: 8px;
1067
- height: 30px;
1068
- background-color: black;
1069
- border: 1px solid white;
1070
- border-radius: 4px;
1071
- cursor: ew-resize;
1072
- top: 50%;
1073
- transform: translateY(-50%);
1074
- z-index: 3;
1075
- }
1076
-
1077
- .lumir-resize-handle-bottom {
1078
- position: absolute;
1079
- bottom: 4px;
1080
- left: 50%;
1081
- transform: translateX(-50%);
1082
- width: 30px;
1083
- height: 8px;
1084
- background-color: black;
1085
- border: 1px solid white;
1086
- border-radius: 4px;
1087
- cursor: ns-resize;
1088
- z-index: 3;
1089
- }
1090
-
1091
- .lumir-link-preview-card:hover {
1092
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
1093
- }
1094
-
1095
- .node-linkPreview.ProseMirror-selectednode .bn-block-content {
1096
- outline: 2px solid #3b82f6;
1097
- outline-offset: 2px;
1098
- border-radius: 8px;
1099
- }
1100
-
1101
- .node-linkPreview .bn-block-content {
1102
- outline: none !important;
1103
- }
1104
-
1105
- /* 다크 테마 대응 */
1106
- [data-color-scheme='dark'] .lumir-link-preview-card,
1107
- .bn-container[data-color-scheme='dark'] .lumir-link-preview-card {
1108
- background-color: #292524 !important;
1109
- border-color: #44403c !important;
1110
- }
1111
-
1112
- [data-color-scheme='dark'] .lumir-link-preview-card:hover,
1113
- .bn-container[data-color-scheme='dark'] .lumir-link-preview-card:hover {
1114
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3) !important;
1115
- }
1116
-
1117
- [data-color-scheme='dark'] .lumir-link-preview-skeleton,
1118
- .bn-container[data-color-scheme='dark'] .lumir-link-preview-skeleton {
1119
- background-color: #292524 !important;
1120
- border-color: #44403c !important;
1121
- }
1122
-
1123
- [data-color-scheme='dark'] .lumir-link-preview-error,
1124
- .bn-container[data-color-scheme='dark'] .lumir-link-preview-error {
1125
- background-color: #292524 !important;
1126
- border-color: #44403c !important;
1127
- }
1128
-
1129
- /* 인용·코드·테이블 본문 14px */
1130
- .lumirEditor .bn-block-content[data-content-type='quote'] p.bn-inline-content,
1131
- .lumirEditor [data-content-type='quote'] blockquote {
1132
- font-size: 14px;
1133
- }
1134
-
1135
- .lumirEditor .bn-block-content[data-content-type='codeBlock'] pre,
1136
- .lumirEditor .bn-block-content[data-content-type='codeBlock'] pre code {
1137
- font-size: 14px;
1138
- }
1139
-
1140
- .lumirEditor .bn-editor [data-content-type='table'] th,
1141
- .lumirEditor .bn-editor [data-content-type='table'] td,
1142
- .lumirEditor .bn-editor [data-content-type='table'] p.bn-inline-content {
1143
- font-size: 14px;
1144
- }
1145
-
1146
- /* 테이블 세로 정렬 (VerticalAlignmentExtension) */
1147
- .lumirEditor
1148
- .bn-editor
1149
- [data-content-type='table']
1150
- td[data-vertical-alignment='middle'],
1151
- .lumirEditor
1152
- .bn-editor
1153
- [data-content-type='table']
1154
- th[data-vertical-alignment='middle'] {
1155
- vertical-align: middle;
1156
- }
1157
-
1158
- .lumirEditor
1159
- .bn-editor
1160
- [data-content-type='table']
1161
- td[data-vertical-alignment='bottom'],
1162
- .lumirEditor
1163
- .bn-editor
1164
- [data-content-type='table']
1165
- th[data-vertical-alignment='bottom'] {
1166
- vertical-align: bottom;
1167
- }
1168
-
1169
- /* ==========================================================================
1170
- Notion 스타일 FOCUS 기반 테이블 gutter/grip (LumirTableHandlesController)
1171
- - 셀 focus 시: 셀 테두리 하이라이트(파란 보더, 셀을 살짝 감쌈)
1172
- - 상단(열)·좌측(행): 짧고 두꺼운 회색 gutter 바 / 우측(셀): 작은 파란 앵커
1173
- - gutter hover 시: 발판 grip 노출 → 클릭 시 드롭다운
1174
- - active(메뉴 열림/드래그): 발판이 파란 배경 + 흰 점
1175
- 기본 BlockNote hover 핸들은 tableHandles={false}로 비활성.
1176
- ========================================================================== */
1177
-
1178
- /* focus된 테두리 하이라이트 (셀을 ~2px 바깥에서 감싸는 비클릭 오버레이) */
1179
- .lumirEditor .lumir-tbl-cell-focus {
1180
- position: absolute;
1181
- top: 0;
1182
- left: 0;
1183
- box-sizing: border-box;
1184
- border: 2px solid #2383e2;
1185
- border-radius: 2px;
1186
- pointer-events: none;
1187
- z-index: 1;
1188
- }
1189
-
1190
- /* gutter wrapper = hover 히트 영역. 보더에 걸쳐 중앙 배치(positioner offset -7). */
1191
- .lumirEditor .lumir-tbl-gutter-wrap {
1192
- position: absolute;
1193
- z-index: 2;
1194
- cursor: pointer;
1195
- }
1196
-
1197
- .lumirEditor .lumir-tbl-gutter-wrap--col {
1198
- width: 34px;
1199
- height: 14px;
1200
- }
1201
-
1202
- .lumirEditor .lumir-tbl-gutter-wrap--row,
1203
- .lumirEditor .lumir-tbl-gutter-wrap--cell {
1204
- width: 14px;
1205
- height: 34px;
1206
- }
1207
-
1208
- /* 기본 노출: 짧고 두꺼운 gutter 바. wrapper가 셀 보더에 중앙 정렬되어 있으므로,
1209
- gutter wrapper 중앙에 두면 "거터 중앙이 셀 보더선 위"에 오도록 걸쳐진다
1210
- (절반은 셀 안쪽, 절반은 바깥쪽). */
1211
- .lumirEditor .lumir-tbl-gutter {
1212
- position: absolute;
1213
- inset: 0;
1214
- margin: auto;
1215
- box-sizing: border-box;
1216
- background-color: #c0c0c2;
1217
- transition: opacity 0.1s ease;
1218
- }
1219
-
1220
- /* 상(top): 가로 pill — 상단 보더 중앙 */
1221
- .lumirEditor .lumir-tbl-gutter-wrap--col .lumir-tbl-gutter {
1222
- width: 14px;
1223
- height: 4px;
1224
- border-left: 1px solid #fff;
1225
- border-right: 1px solid #fff;
1226
- }
1227
-
1228
- /* 좌(left): 세로 pill — 좌측 보더 중앙 (Notion도 좌측에 표시) */
1229
- .lumirEditor .lumir-tbl-gutter-wrap--row .lumir-tbl-gutter {
1230
- width: 4px;
1231
- height: 14px;
1232
- border-top: 1px solid #fff;
1233
- border-bottom: 1px solid #fff;
1234
- }
1235
-
1236
- /* 우(right): Notion의 파란 선택 앵커 — 우측 보더 중앙 */
1237
- /* 우(right): 셀 우측 보더의 파란 세로 앵커 */
1238
- .lumirEditor .lumir-tbl-gutter-wrap--cell .lumir-tbl-gutter {
1239
- width: 4px;
1240
- height: 14px;
1241
- background-color: #2383e2;
1242
- border-top: 1px solid #fff;
1243
- border-bottom: 1px solid #fff;
1244
- }
1245
-
1246
- .lumirEditor .lumir-tbl-gutter-wrap:hover .lumir-tbl-gutter {
1247
- opacity: 0;
1248
- }
1249
-
1250
- /* 발판 grip: 기본 숨김, gutter hover 시 노출 */
1251
- .lumirEditor .lumir-tbl-grip {
1252
- position: absolute;
1253
- inset: 0;
1254
- display: flex;
1255
- align-items: center;
1256
- justify-content: center;
1257
- opacity: 0;
1258
- pointer-events: none;
1259
- cursor: pointer;
1260
- transition: opacity 0.1s ease;
1261
- }
1262
-
1263
- .lumirEditor .lumir-tbl-gutter-wrap:hover .lumir-tbl-grip {
1264
- opacity: 1;
1265
- pointer-events: auto;
1266
- }
1267
-
1268
- /* 메뉴 열림(active) 동안 발판 유지(마우스가 떠나도) + rest 바 숨김 */
1269
- .lumirEditor .lumir-tbl-gutter-wrap--active .lumir-tbl-grip {
1270
- opacity: 1;
1271
- pointer-events: auto;
1272
- }
1273
-
1274
- .lumirEditor .lumir-tbl-gutter-wrap--active .lumir-tbl-gutter {
1275
- opacity: 0;
1276
- }
1277
-
1278
- /* 드롭다운 오픈(active)·드래그 시 발판: 배경·보더 파랑(#2383e2) + 흰 아이콘 */
1279
- .lumirEditor .lumir-tbl-gutter-wrap--active .bn-table-handle,
1280
- .lumirEditor .lumir-tbl-gutter-wrap--active .bn-table-cell-handle,
1281
- .lumirEditor .lumir-tbl-grip .bn-table-handle-dragging {
1282
- background-color: #2383e2 !important;
1283
- border-color: #2383e2 !important;
1284
- color: #fff !important;
1285
- }
1286
-
1287
- /* 발판 크기: 너비(11)↓·높이(14) 유지. 상단 발판은 90° 회전이라 너비↓ = 시각적 높이↓.
1288
- 배경 흰색 + 보더 진하게(#999). */
1289
- .lumirEditor .lumir-tbl-grip .bn-table-handle,
1290
- .lumirEditor .lumir-tbl-grip .bn-table-cell-handle {
1291
- width: 12px;
1292
- min-width: 12px;
1293
- height: 16px;
1294
- padding: 0;
1295
- border-radius: 3px;
1296
- cursor: pointer; /* mantine 기본 grab → pointer */
1297
- background-color: #fff;
1298
- border: 1px solid #cfcfcf;
1299
- box-shadow: none; /* mantine 기본 그림자(--bn-shadow-light, 블러처럼 보임) 제거 */
1300
- }
1301
-
1302
- /* hover 시에도 배경 유지 (mantine hover 회색 오버라이드) */
1303
- .lumirEditor .lumir-tbl-grip .bn-table-handle:hover,
1304
- .lumirEditor .lumir-tbl-grip .bn-table-cell-handle:hover {
1305
- background-color: #fff;
1306
- }
1307
-
1308
- .lumirEditor .lumir-tbl-grip .bn-table-handle svg {
1309
- width: 12px;
1310
- height: 12px;
1311
- margin-inline: 0;
1312
- }
1313
-
1314
- .lumirEditor .lumir-tbl-grip .bn-table-cell-handle svg {
1315
- width: 12px;
1316
- height: 12px;
1317
- }
1318
-
1319
- /* =========================================================
1320
- 높이(row height) 드래그 리사이즈 — rowResizing 플러그인
1321
- prosemirror-tables의 column-resize 스타일을 수직축으로 미러링.
1322
- ========================================================= */
1323
-
1324
- /* activeHandle 동안 에디터 전체 커서를 행 리사이즈로 */
1325
- .lumirEditor .ProseMirror.row-resize-cursor {
1326
- cursor: ns-resize;
1327
- cursor: row-resize;
1328
- }
1329
-
1330
- /* 핸들 위젯의 절대배치 기준(셀). prosemirror-tables 기본값 보강. */
1331
- .lumirEditor .ProseMirror td,
1332
- .lumirEditor .ProseMirror th {
1333
- position: relative;
1334
- }
1335
-
1336
- /* 하단 경계 핸들(셀별 1개가 모여 폭 전체를 덮음). */
1337
- .lumirEditor .ProseMirror .row-resize-handle {
1338
- position: absolute;
1339
- left: 0;
1340
- right: 0;
1341
- bottom: -2px;
1342
- height: 4px;
1343
- z-index: 20;
1344
- background-color: #adf;
1345
- pointer-events: none;
1346
- }
1347
-
1348
- /* 드래그 중 셀: 레이아웃 트랜지션 제거로 프리뷰 떨림 방지. */
1349
- .lumirEditor .ProseMirror .row-resize-dragging {
1350
- transition: none;
1351
- }
1352
-
1353
- /* 표 전체 스케일: 우하단 모서리 hit-zone(투명). 오버레이라 에디터 위에 떠서 코너의
1354
- hover/클릭을 가로채므로 행/열 리사이즈(하단·우측 경계)와 충돌하지 않는다.
1355
- 보이는 핸들 없이 hover 시 대각 리사이즈 커서만 노출 + 드래그로 크기 조절. */
1356
- .lumirEditor .lumir-tbl-scale-handle {
1357
- width: 18px;
1358
- height: 18px;
1359
- background: transparent;
1360
- cursor: nwse-resize;
1361
- z-index: 30;
1362
- pointer-events: auto;
1363
- touch-action: none;
1364
- }
1365
- /* 드래그 중 셀: 트랜지션 제거로 프리뷰 떨림 방지. */
1366
- .lumirEditor .ProseMirror .lumir-table-scale-dragging {
1367
- transition: none;
1368
- }
1369
-
1370
- /* =========================================================
1371
- 블록 정렬(좌/가운데/우) TableAlignmentExtension
1372
- <table>이 width:auto(content 폭)이므로 margin으로 수평 정렬.
1373
- 좌측(기본)은 별도 규칙 불필요.
1374
- ========================================================= */
1375
- .lumirEditor
1376
- .bn-editor
1377
- [data-content-type='table'][data-table-alignment='center']
1378
- table {
1379
- margin-left: auto;
1380
- margin-right: auto;
1381
- }
1382
-
1383
- .lumirEditor
1384
- .bn-editor
1385
- [data-content-type='table'][data-table-alignment='right']
1386
- table {
1387
- margin-left: auto;
1388
- margin-right: 0;
1389
- }
1390
-
1391
- /* =========================================================
1392
- 하단 여백 축소
1393
- @blocknote 기본 .tableWrapper는 `position:relative; top:-16px`라서, 화면상 16px
1394
- 위로 그리되 레이아웃 공간은 원위치에 예약 → 래퍼 박스 아래에 사용되지 않는 16px가
1395
- 남는다(순수 artifact). 음수 margin-bottom으로 이 예약 공백만 정확히 상쇄한다.
1396
- 래퍼의 padding/overflow는 건드리지 않으므로 행/열 추가 버튼·리사이즈 핸들·거터의
1397
- 클리어런스(클립 경계)는 그대로 유지된다 → 사이드이펙트 없음.
1398
- ========================================================= */
1399
- .lumirEditor .bn-editor [data-content-type='table'] .tableWrapper {
1400
- margin-bottom: -16px;
1401
- }
1402
-
1403
- /* =========================================================
1404
- 다단(컬럼) 레이아웃 — columnList / column 노드
1405
- columnList: 가로 flex 컨테이너, column: 균등 폭 flex 아이템.
1406
- ========================================================= */
1407
- .lumirEditor .bn-column-list {
1408
- display: flex;
1409
- gap: 16px;
1410
- width: 100%;
1411
- }
1412
-
1413
- .lumirEditor .bn-column {
1414
- flex: 1 1 0;
1415
- min-width: 0; /* 컬럼 내 넓은 콘텐츠(표 등) 오버플로 방지 */
1416
- }
1417
-
1418
- /* 컬럼 중앙 세로 구분선. 두 가지 방식으로 켜진다(둘 중 하나라도 켜지면 표시):
1419
- 1) 전역: columnDivider prop → 루트 `.lumir-column-divider` (모든 컬럼).
1420
- 2) 블록별: columnList의 `showDivider` attr → `data-divider="true"` (드래그핸들 메뉴 토글).
1421
- divider가 드래그 핸들(grip)에 가려지지 않도록 gap을 넓혀(기본 16px grip-space×2)
1422
- divider를 정중앙에 두고 양쪽에 grip 너비만큼 여백을 둔다. 마지막 컬럼 제외 → N컬럼이면
1423
- N-1개. flex 기본 align-items:stretch로 컬럼 높이가 같아 구분선이 전체 높이를 채운다.
1424
- grip-space/색은 CSS 변수로 조정 가능. */
1425
- .lumirEditor.lumir-column-divider .bn-column-list,
1426
- .lumirEditor .bn-column-list[data-divider="true"] {
1427
- --lumir-column-grip-space: 28px; /* divider ~ 콘텐츠 여백(≈grip 너비 + 여유) */
1428
- gap: calc(var(--lumir-column-grip-space) * 2);
1429
- }
1430
- .lumirEditor.lumir-column-divider .bn-column,
1431
- .lumirEditor .bn-column-list[data-divider="true"] .bn-column {
1432
- position: relative;
1433
- }
1434
- .lumirEditor.lumir-column-divider .bn-column:not(:last-child)::after,
1435
- .lumirEditor .bn-column-list[data-divider="true"] .bn-column:not(:last-child)::after {
1436
- content: "";
1437
- position: absolute;
1438
- top: 0;
1439
- bottom: 0;
1440
- right: calc(var(--lumir-column-grip-space) * -1); /* gap 정중앙 */
1441
- width: 1px;
1442
- background: var(--lumir-column-divider-color, #e5e7eb);
1443
- pointer-events: none;
1444
- }
1445
-
1446
- /* DnD 컬럼 생성: 드롭 대상 블록의 좌/우 가장자리 세로 인디케이터(레이아웃 비이동 box-shadow) */
1447
- .lumirEditor .lumir-col-drop-left {
1448
- box-shadow: -3px 0 0 0 #3b82f6;
1449
- }
1450
- .lumirEditor .lumir-col-drop-right {
1451
- box-shadow: 3px 0 0 0 #3b82f6;
1452
- }
1453
- /* 가장자리 드롭 중에는 기본(가로) 드롭커서를 숨겨 인디케이터 중복 방지 */
1454
- .lumirEditor .lumir-col-dnd-active .prosemirror-dropcursor,
1455
- .lumirEditor .lumir-col-dnd-active .ProseMirror-dropcursor {
1456
- display: none !important;
1457
- }
1
+ @import '@blocknote/core/fonts/inter.css';
2
+ @import '@blocknote/mantine/style.css';
3
+ @import '@blocknote/react/style.css';
4
+
5
+ /* Pretendard 한글 글꼴 (가변 폰트, swap).
6
+ @import url()은 번들 시 @import 순서 규칙을 위반해 사용 불가 → @font-face로 로드.
7
+ 호스트 앱이 Pretendard를 자체 로드한다면 이 블록은 제거해도 된다. */
8
+ @font-face {
9
+ font-family: 'Pretendard';
10
+ font-weight: 100 900;
11
+ font-style: normal;
12
+ font-display: swap;
13
+ src: url('https://cdn.jsdelivr.net/npm/pretendard@1.3.9/dist/web/variable/woff2/PretendardVariable.woff2')
14
+ format('woff2-variations');
15
+ }
16
+
17
+ .lumirEditor {
18
+ width: 100%;
19
+ height: 100%;
20
+ min-width: 200px;
21
+ overflow: visible; /* 슬래시 메뉴가 컨테이너를 넘어서 표시되도록 변경 */
22
+ background-color: #ffffff;
23
+ /* 에디터 전체(본문·툴바·인-DOM 드롭다운) 한글 글꼴 Pretendard */
24
+ font-family:
25
+ 'Pretendard',
26
+ 'Noto Sans KR',
27
+ -apple-system,
28
+ BlinkMacSystemFont,
29
+ 'Segoe UI',
30
+ 'Roboto',
31
+ sans-serif;
32
+ }
33
+
34
+ /* 에디터 내부 콘텐츠 영역만 스크롤 가능하게 설정 */
35
+ .lumirEditor .bn-container {
36
+ overflow: auto;
37
+ max-height: 100%;
38
+ }
39
+
40
+ /* 슬래시 메뉴(SuggestionMenu)가 컨테이너를 넘어서 표시되도록 */
41
+ .bn-suggestion-menu,
42
+ .bn-slash-menu,
43
+ .mantine-Menu-dropdown,
44
+ .mantine-Popover-dropdown {
45
+ z-index: 9999 !important;
46
+ }
47
+
48
+ /* 포털(body)로 빠지는 메뉴/드롭다운에도 Pretendard 적용 */
49
+ .bn-suggestion-menu,
50
+ .bn-slash-menu,
51
+ .mantine-Menu-dropdown,
52
+ .mantine-Popover-dropdown,
53
+ .bn-table-handle-menu,
54
+ .bn-menu-dropdown {
55
+ font-family:
56
+ 'Pretendard',
57
+ 'Noto Sans KR',
58
+ -apple-system,
59
+ BlinkMacSystemFont,
60
+ 'Segoe UI',
61
+ 'Roboto',
62
+ sans-serif;
63
+ }
64
+ /* 포커스 상태 스타일 - 테두리 없음 */
65
+ .lumirEditor:focus-within {
66
+ outline: none;
67
+ box-shadow: none;
68
+ }
69
+ .lumirEditor {
70
+ border: none;
71
+ }
72
+
73
+ /* BlockNote 에디터 내부 폰트 설정 */
74
+ .lumirEditor .bn-editor,
75
+ .lumirEditor .bn-inline-content {
76
+ font-family:
77
+ 'Pretendard',
78
+ 'Noto Sans KR',
79
+ -apple-system,
80
+ BlinkMacSystemFont,
81
+ 'Segoe UI',
82
+ 'Roboto',
83
+ 'Oxygen',
84
+ 'Ubuntu',
85
+ 'Cantarell',
86
+ sans-serif;
87
+ }
88
+
89
+ /* 링크 스타일 - Tailwind Preflight 리셋 복원 */
90
+ .lumirEditor .bn-editor a,
91
+ .lumirEditor .bn-inline-content a {
92
+ color: #0b6e99;
93
+ text-decoration: underline;
94
+ text-underline-offset: 2px;
95
+ cursor: pointer;
96
+ }
97
+
98
+ .lumirEditor .bn-editor a:hover,
99
+ .lumirEditor .bn-inline-content a:hover {
100
+ color: #0b6e99;
101
+ }
102
+
103
+ /* CSS 변수를 사용한 패딩 설정 */
104
+ .lumirEditor .bn-editor {
105
+ padding-left: 25px;
106
+ padding-right: 10px;
107
+ padding-top: 5px;
108
+ padding-bottom: 0;
109
+ }
110
+
111
+ /*
112
+ * 본문·번호·글머리·체크 목록 인라인 텍스트 14px 통일
113
+ * BlockNote `.bn-default-styles { font-size: 16px }` + `p { font-size: inherit }` 때문에
114
+ * `p.bn-inline-content`에 명시적으로 14px (`.bn-block-content`에 data-type이 붙음)
115
+ */
116
+ .lumirEditor
117
+ .bn-block-content[data-content-type='paragraph']
118
+ p.bn-inline-content,
119
+ .lumirEditor
120
+ .bn-block-content[data-content-type='numberedListItem']
121
+ p.bn-inline-content,
122
+ .lumirEditor
123
+ .bn-block-content[data-content-type='bulletListItem']
124
+ p.bn-inline-content,
125
+ .lumirEditor
126
+ .bn-block-content[data-content-type='checkListItem']
127
+ p.bn-inline-content {
128
+ font-size: 14px;
129
+ }
130
+
131
+ /* 마커(번호·불릿)·체크 행 */
132
+ .lumirEditor .bn-block-content[data-content-type='numberedListItem'],
133
+ .lumirEditor .bn-block-content[data-content-type='bulletListItem'],
134
+ .lumirEditor .bn-block-content[data-content-type='checkListItem'] {
135
+ font-size: 14px;
136
+ }
137
+
138
+ .lumirEditor .bn-block-content {
139
+ max-width: 100%;
140
+ }
141
+
142
+ /* File Panel: Embed 탭 미노출 (URL 입력 방식 비활성화) */
143
+ .lumirEditor [data-test='embed-tab'] {
144
+ display: none !important;
145
+ }
146
+
147
+ /* 정렬된 블록의 인라인 콘텐츠 - 빈 블록에서 스크롤 방지 */
148
+ .lumirEditor .bn-inline-content {
149
+ overflow: hidden;
150
+ max-width: 100%;
151
+ min-width: 0;
152
+ }
153
+
154
+ /* 우측 정렬 시 빈 블록 placeholder 위치 수정 */
155
+ .lumirEditor [data-text-alignment='right'] .bn-inline-content::before {
156
+ position: relative;
157
+ max-width: 100%;
158
+ }
159
+
160
+ /* 이미지 업로드 로딩 스피너 */
161
+ .lumirEditor-upload-overlay {
162
+ position: absolute;
163
+ top: 0;
164
+ left: 0;
165
+ right: 0;
166
+ bottom: 0;
167
+ display: flex;
168
+ flex-direction: column;
169
+ align-items: center;
170
+ justify-content: center;
171
+ gap: 8px;
172
+ background-color: rgba(255, 255, 255, 0.8);
173
+ backdrop-filter: blur(2px);
174
+ z-index: 1000;
175
+ }
176
+
177
+ .lumirEditor-spinner {
178
+ width: 30px;
179
+ height: 30px;
180
+ border: 3px solid #f3f3f3;
181
+ border-top: 3px solid #3b82f6;
182
+ border-radius: 50%;
183
+ animation: lumir-spin 1s linear infinite;
184
+ }
185
+
186
+ .lumirEditor-upload-progress {
187
+ font-size: 14px;
188
+ font-weight: 500;
189
+ color: #374151;
190
+ }
191
+
192
+ @keyframes lumir-spin {
193
+ 0% {
194
+ transform: rotate(0deg);
195
+ }
196
+ 100% {
197
+ transform: rotate(360deg);
198
+ }
199
+ }
200
+
201
+ /* ========================================
202
+ Floating Toolbar 스타일 (컴팩트 + 반응형)
203
+ ======================================== */
204
+
205
+ /* CSS 변수 정의 */
206
+ .lumir-floating-toolbar-wrapper {
207
+ --lumir-bg-light: #fafaf9;
208
+ --lumir-bg-dark: #1c1917;
209
+ --lumir-paper-light: #ffffff;
210
+ --lumir-paper-dark: #292524;
211
+ --lumir-border-light: #e7e5e4;
212
+ --lumir-border-dark: #44403c;
213
+ --lumir-text-light: #1c1917;
214
+ --lumir-text-dark: #fafaf9;
215
+ --lumir-text-muted-light: #78716c;
216
+ --lumir-text-muted-dark: #a8a29e;
217
+ --lumir-hover-light: #f5f5f4;
218
+ --lumir-hover-dark: #44403c;
219
+ --lumir-active-bg: rgba(59, 130, 246, 0.1);
220
+ --lumir-active-color: #3b82f6;
221
+ --lumir-radius-lg: 0.5rem;
222
+ --lumir-radius-md: 0.25rem;
223
+ --lumir-transition: 0.15s cubic-bezier(0.4, 0, 0.2, 1);
224
+ --lumir-btn-size: 28px;
225
+ --lumir-btn-padding: 6px;
226
+ --lumir-icon-size: 16px;
227
+ }
228
+
229
+ /* Toolbar Wrapper */
230
+ .lumir-floating-toolbar-wrapper {
231
+ width: 100%;
232
+ display: flex;
233
+ justify-content: center;
234
+ padding: 8px 12px;
235
+ z-index: 40;
236
+ }
237
+
238
+ /* 최소화 모드일 때는 좌측 상단 배치 */
239
+ .lumir-floating-toolbar-wrapper.is-minimizable {
240
+ justify-content: flex-start;
241
+ padding: 0;
242
+ }
243
+
244
+ .lumir-floating-toolbar-wrapper[data-position='sticky'] {
245
+ position: sticky;
246
+ top: 0;
247
+ }
248
+
249
+ .lumir-floating-toolbar-wrapper[data-position='fixed'] {
250
+ position: fixed;
251
+ top: 64px;
252
+ left: 0;
253
+ right: 0;
254
+ }
255
+
256
+ /* Toolbar Container - 항상 밝은 배경 유지 */
257
+ .lumir-floating-toolbar {
258
+ display: flex;
259
+ flex-wrap: wrap;
260
+ align-items: center;
261
+ gap: 2px;
262
+ padding: 4px;
263
+ background-color: #ffffff !important;
264
+ border: 1px solid #e5e7eb !important;
265
+ border-radius: var(--lumir-radius-lg);
266
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
267
+ max-width: 100%;
268
+ font-family: ui-sans-serif, system-ui, sans-serif;
269
+ font-size: 13px;
270
+ }
271
+
272
+ /* 1단 레이아웃 (넓은 화면) */
273
+ .lumir-floating-toolbar {
274
+ flex-wrap: nowrap;
275
+ }
276
+
277
+ /* 2단 레이아웃 (좁은 화면) */
278
+ .lumir-floating-toolbar.is-compact {
279
+ flex-wrap: wrap;
280
+ justify-content: center;
281
+ }
282
+
283
+ .lumir-floating-toolbar.is-compact .lumir-toolbar-row {
284
+ display: flex;
285
+ align-items: center;
286
+ width: 100%;
287
+ justify-content: center;
288
+ gap: 2px;
289
+ }
290
+
291
+ .lumir-floating-toolbar.is-compact .lumir-toolbar-row:not(:last-child) {
292
+ padding-bottom: 4px;
293
+ border-bottom: 1px solid var(--lumir-border-light);
294
+ margin-bottom: 4px;
295
+ }
296
+
297
+ /* 최소화 가능 레이아웃 (400px 이하) */
298
+ .lumir-floating-toolbar.is-minimizable {
299
+ flex-wrap: wrap; /* 여러 줄로 확장 가능 */
300
+ justify-content: flex-start; /* 좌측 정렬 */
301
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
302
+ padding: 0; /* 내부 공백 제거 */
303
+ }
304
+
305
+ /* 토글 버튼 스타일 */
306
+ .lumir-floating-toolbar.is-minimizable .lumir-toggle-button {
307
+ order: -1; /* 항상 맨 앞에 배치 */
308
+ flex-shrink: 0;
309
+ width: 24px; /* 컴팩트한 크기 */
310
+ height: 24px;
311
+ padding: 0; /* 패딩 제거하여 정확한 정렬 */
312
+ margin: 0;
313
+ border-radius: 4px;
314
+ display: flex;
315
+ align-items: center;
316
+ justify-content: center;
317
+ cursor: pointer;
318
+ transition: transform 0.2s ease;
319
+ }
320
+
321
+ .lumir-floating-toolbar.is-minimizable .lumir-toggle-button:hover {
322
+ transform: scale(1.1);
323
+ }
324
+
325
+ .lumir-floating-toolbar.is-minimizable .lumir-toggle-button svg {
326
+ width: 16px;
327
+ height: 16px;
328
+ display: block; /* inline 여백 제거 */
329
+ transition: transform 0.3s ease;
330
+ }
331
+
332
+ /* 메뉴 항목 애니메이션 */
333
+ .lumir-floating-toolbar.is-minimizable > *:not(.lumir-toggle-button) {
334
+ opacity: 1;
335
+ transform: translateX(0);
336
+ transition:
337
+ opacity 0.3s ease,
338
+ transform 0.3s ease;
339
+ }
340
+
341
+ /* 최소화 상태 - 토글 버튼만 표시 */
342
+ .lumir-floating-toolbar.is-minimizable.is-minimized {
343
+ width: auto;
344
+ min-width: 24px;
345
+ padding: 0;
346
+ border: none;
347
+ background: transparent !important;
348
+ box-shadow: none;
349
+ }
350
+
351
+ .lumir-floating-toolbar.is-minimizable.is-minimized
352
+ > *:not(.lumir-toggle-button) {
353
+ opacity: 0;
354
+ transform: translateX(-10px);
355
+ pointer-events: none;
356
+ max-width: 0;
357
+ overflow: hidden;
358
+ margin: 0;
359
+ padding: 0;
360
+ }
361
+
362
+ /* Toolbar Group */
363
+ .lumir-toolbar-group {
364
+ display: flex;
365
+ align-items: center;
366
+ gap: 1px;
367
+ padding: 0 2px;
368
+ }
369
+
370
+ /* Divider */
371
+ .lumir-toolbar-divider {
372
+ width: 1px;
373
+ height: 18px;
374
+ background-color: var(--lumir-border-light);
375
+ margin: 0 2px;
376
+ flex-shrink: 0;
377
+ }
378
+
379
+ /* 2단에서 divider 숨기기 */
380
+ .lumir-floating-toolbar.is-compact .lumir-toolbar-divider.row-break {
381
+ display: none;
382
+ }
383
+
384
+ /* Toolbar Button (컴팩트) */
385
+ .lumir-toolbar-btn {
386
+ display: flex;
387
+ align-items: center;
388
+ justify-content: center;
389
+ width: var(--lumir-btn-size);
390
+ height: var(--lumir-btn-size);
391
+ padding: var(--lumir-btn-padding);
392
+ border: none;
393
+ background: transparent;
394
+ color: var(--lumir-text-muted-light);
395
+ cursor: pointer;
396
+ border-radius: var(--lumir-radius-md);
397
+ transition: all var(--lumir-transition);
398
+ position: relative;
399
+ flex-shrink: 0;
400
+ }
401
+
402
+ .lumir-toolbar-btn svg {
403
+ width: var(--lumir-icon-size);
404
+ height: var(--lumir-icon-size);
405
+ }
406
+
407
+ .lumir-toolbar-btn:hover {
408
+ background-color: var(--lumir-hover-light);
409
+ color: var(--lumir-text-light);
410
+ }
411
+
412
+ .lumir-toolbar-btn.is-active {
413
+ background-color: var(--lumir-active-bg);
414
+ color: var(--lumir-active-color);
415
+ }
416
+
417
+ .lumir-toolbar-btn:disabled {
418
+ opacity: 0.4;
419
+ cursor: not-allowed;
420
+ }
421
+
422
+ /* 색상 버튼 인디케이터 */
423
+ .lumir-color-btn {
424
+ flex-direction: column;
425
+ gap: 1px;
426
+ width: var(--lumir-btn-size);
427
+ height: var(--lumir-btn-size);
428
+ padding: 4px;
429
+ }
430
+
431
+ .lumir-color-btn svg {
432
+ width: 14px;
433
+ height: 14px;
434
+ }
435
+
436
+ .lumir-color-indicator {
437
+ width: 12px;
438
+ height: 2px;
439
+ border-radius: 1px;
440
+ border: 1px solid rgba(0, 0, 0, 0.1);
441
+ }
442
+
443
+ /* SVG 아이콘 스타일 */
444
+ .lumir-toolbar-btn svg,
445
+ .lumir-dropdown-btn svg {
446
+ flex-shrink: 0;
447
+ }
448
+
449
+ /* Dropdown Wrapper */
450
+ .lumir-dropdown-wrapper {
451
+ position: relative;
452
+ }
453
+
454
+ /* Dropdown Button (컴팩트) */
455
+ .lumir-dropdown-btn {
456
+ display: flex;
457
+ align-items: center;
458
+ justify-content: space-between;
459
+ min-width: 90px;
460
+ max-width: 110px;
461
+ height: var(--lumir-btn-size);
462
+ padding: 4px 8px;
463
+ border: none;
464
+ background: transparent;
465
+ color: inherit;
466
+ cursor: pointer;
467
+ border-radius: var(--lumir-radius-md);
468
+ font-size: 12px;
469
+ font-weight: 500;
470
+ transition: all var(--lumir-transition);
471
+ gap: 2px;
472
+ white-space: nowrap;
473
+ overflow: hidden;
474
+ }
475
+
476
+ .lumir-dropdown-btn span {
477
+ overflow: hidden;
478
+ text-overflow: ellipsis;
479
+ }
480
+
481
+ .lumir-dropdown-btn:hover {
482
+ background-color: var(--lumir-hover-light);
483
+ }
484
+
485
+ .lumir-dropdown-btn svg {
486
+ width: 14px;
487
+ height: 14px;
488
+ flex-shrink: 0;
489
+ color: var(--lumir-text-muted-light);
490
+ }
491
+
492
+ /* Dropdown Menu - 항상 밝은 배경 유지 */
493
+ .lumir-dropdown-menu {
494
+ position: absolute;
495
+ top: calc(100% + 4px);
496
+ left: 0;
497
+ min-width: 160px;
498
+ background-color: #ffffff !important;
499
+ border: 1px solid #e5e7eb !important;
500
+ border-radius: 10px;
501
+ box-shadow:
502
+ 0 4px 16px rgba(0, 0, 0, 0.12),
503
+ 0 0 0 1px rgba(0, 0, 0, 0.04);
504
+ z-index: 9999;
505
+ padding: 6px;
506
+ animation: lumir-dropdown-appear 0.15s ease;
507
+ }
508
+
509
+ @keyframes lumir-dropdown-appear {
510
+ from {
511
+ opacity: 0;
512
+ transform: translateY(-4px);
513
+ }
514
+ to {
515
+ opacity: 1;
516
+ transform: translateY(0);
517
+ }
518
+ }
519
+
520
+ /* Dropdown Item - 항상 밝은 스타일 */
521
+ .lumir-dropdown-item {
522
+ display: flex;
523
+ align-items: center;
524
+ width: 100%;
525
+ padding: 8px 12px;
526
+ text-align: left;
527
+ border: none;
528
+ background: transparent;
529
+ color: #374151 !important;
530
+ cursor: pointer;
531
+ border-radius: 6px;
532
+ font-size: 14px;
533
+ transition: background-color 0.1s ease;
534
+ }
535
+
536
+ .lumir-dropdown-item:hover {
537
+ background-color: #f3f4f6 !important;
538
+ }
539
+
540
+ .lumir-dropdown-item.is-active {
541
+ background-color: rgba(59, 130, 246, 0.1) !important;
542
+ color: #3b82f6 !important;
543
+ }
544
+
545
+ /* Font Size Dropdown Button (글자 크기) */
546
+ .lumir-font-size-btn {
547
+ min-width: 52px;
548
+ max-width: 72px;
549
+ }
550
+
551
+ .lumir-font-size-label {
552
+ flex: 1;
553
+ text-align: center;
554
+ }
555
+
556
+ .lumir-font-size-menu {
557
+ min-width: 96px;
558
+ max-height: 280px;
559
+ overflow-y: auto;
560
+ }
561
+
562
+ /* blur 상태에서도 텍스트 선택 하이라이트 유지 (InactiveSelectionExtension).
563
+ 툴바 드롭다운(글자 크기 등) 조작 시 에디터가 blur돼 네이티브 선택이 사라지는 문제 보완. */
564
+ .bn-inactive-selection {
565
+ background-color: var(--lumir-inactive-selection, rgba(35, 131, 226, 0.28));
566
+ }
567
+
568
+ /* Font Size 1px Stepper (글자 크기 −/+ + 직접 입력) — 두 드롭다운(FormattingToolbar/FloatingMenu) 공용 */
569
+ .lumir-fs-stepper {
570
+ display: flex;
571
+ align-items: center;
572
+ justify-content: center;
573
+ gap: 4px;
574
+ padding: 6px 8px;
575
+ border-bottom: 1px solid #e5e7eb;
576
+ }
577
+
578
+ .lumir-fs-stepper-btn {
579
+ width: 24px;
580
+ height: 24px;
581
+ display: flex;
582
+ align-items: center;
583
+ justify-content: center;
584
+ border: 1px solid #d1d5db;
585
+ border-radius: 4px;
586
+ background: #fff;
587
+ color: #374151;
588
+ cursor: pointer;
589
+ font-size: 14px;
590
+ line-height: 1;
591
+ flex-shrink: 0;
592
+ }
593
+
594
+ .lumir-fs-stepper-btn:hover:not(:disabled) {
595
+ background: #f3f4f6;
596
+ }
597
+
598
+ .lumir-fs-stepper-btn:disabled {
599
+ opacity: 0.4;
600
+ cursor: default;
601
+ }
602
+
603
+ .lumir-fs-stepper-input {
604
+ width: 40px;
605
+ text-align: center;
606
+ border: 1px solid #d1d5db;
607
+ border-radius: 4px;
608
+ padding: 3px 2px;
609
+ font-size: 13px;
610
+ color: #111827;
611
+ background: #fff;
612
+ -moz-appearance: textfield;
613
+ appearance: textfield;
614
+ }
615
+
616
+ .lumir-fs-stepper-input:focus {
617
+ outline: none;
618
+ border-color: #3b82f6;
619
+ }
620
+
621
+ .lumir-fs-stepper-input::-webkit-outer-spin-button,
622
+ .lumir-fs-stepper-input::-webkit-inner-spin-button {
623
+ -webkit-appearance: none;
624
+ margin: 0;
625
+ }
626
+
627
+ /* Block Type Dropdown Button */
628
+ .lumir-block-type-btn {
629
+ min-width: 110px;
630
+ max-width: 130px;
631
+ gap: 4px;
632
+ padding: 4px 8px;
633
+ }
634
+
635
+ .lumir-block-icon {
636
+ display: flex;
637
+ align-items: center;
638
+ justify-content: center;
639
+ width: 22px;
640
+ height: 22px;
641
+ flex-shrink: 0;
642
+ color: #6b7280;
643
+ }
644
+
645
+ .lumir-block-icon svg {
646
+ width: 18px;
647
+ height: 18px;
648
+ }
649
+
650
+ .lumir-block-icon-text {
651
+ font-size: 13px;
652
+ font-weight: 700;
653
+ color: #6b7280;
654
+ line-height: 1;
655
+ }
656
+
657
+ .lumir-block-label {
658
+ flex: 1;
659
+ text-align: left;
660
+ overflow: hidden;
661
+ text-overflow: ellipsis;
662
+ white-space: nowrap;
663
+ font-size: 13px;
664
+ }
665
+
666
+ /* Block Type Dropdown Menu - 최대 컴팩트 */
667
+ .lumir-block-menu {
668
+ min-width: 160px;
669
+ max-height: 320px;
670
+ overflow-y: auto;
671
+ padding: 3px;
672
+ }
673
+
674
+ /* 커스텀 스크롤바 - 더 얇게 */
675
+ .lumir-block-menu::-webkit-scrollbar {
676
+ width: 4px;
677
+ }
678
+
679
+ .lumir-block-menu::-webkit-scrollbar-track {
680
+ background: transparent;
681
+ }
682
+
683
+ .lumir-block-menu::-webkit-scrollbar-thumb {
684
+ background-color: #d1d5db;
685
+ border-radius: 2px;
686
+ }
687
+
688
+ .lumir-block-menu::-webkit-scrollbar-thumb:hover {
689
+ background-color: #9ca3af;
690
+ }
691
+
692
+ /* Block Type Menu Item - 최대 컴팩트 */
693
+ .lumir-block-item {
694
+ display: flex;
695
+ align-items: center;
696
+ gap: 6px;
697
+ padding: 4px 8px;
698
+ border-radius: 4px;
699
+ margin-bottom: 0;
700
+ transition: all 0.1s ease;
701
+ }
702
+
703
+ .lumir-block-item:last-child {
704
+ margin-bottom: 0;
705
+ }
706
+
707
+ .lumir-block-item .lumir-block-icon {
708
+ width: 20px;
709
+ height: 20px;
710
+ background-color: #f3f4f6;
711
+ border-radius: 3px;
712
+ display: flex;
713
+ align-items: center;
714
+ justify-content: center;
715
+ flex-shrink: 0;
716
+ }
717
+
718
+ .lumir-block-item .lumir-block-icon svg {
719
+ width: 14px;
720
+ height: 14px;
721
+ }
722
+
723
+ .lumir-block-item .lumir-block-icon-text {
724
+ font-size: 10px;
725
+ font-weight: 700;
726
+ }
727
+
728
+ .lumir-block-item-title {
729
+ font-size: 12px;
730
+ font-weight: 500;
731
+ color: #374151;
732
+ }
733
+
734
+ .lumir-block-item:hover {
735
+ background-color: #f3f4f6 !important;
736
+ }
737
+
738
+ .lumir-block-item:hover .lumir-block-icon {
739
+ background-color: #e5e7eb;
740
+ color: #374151;
741
+ }
742
+
743
+ .lumir-block-item:hover .lumir-block-icon-text {
744
+ color: #374151;
745
+ }
746
+
747
+ .lumir-block-item.is-active {
748
+ background-color: rgba(59, 130, 246, 0.08) !important;
749
+ }
750
+
751
+ .lumir-block-item.is-active .lumir-block-icon {
752
+ background-color: rgba(59, 130, 246, 0.15);
753
+ color: #3b82f6;
754
+ }
755
+
756
+ .lumir-block-item.is-active .lumir-block-icon-text {
757
+ color: #3b82f6;
758
+ }
759
+
760
+ /* Block Type Category - 최대 컴팩트 */
761
+ .lumir-block-category {
762
+ margin-bottom: 2px;
763
+ }
764
+
765
+ .lumir-block-category:last-child {
766
+ margin-bottom: 0;
767
+ }
768
+
769
+ .lumir-block-category-title {
770
+ font-size: 9px;
771
+ font-weight: 600;
772
+ color: #9ca3af;
773
+ text-transform: uppercase;
774
+ letter-spacing: 0.05em;
775
+ padding: 4px 8px 2px;
776
+ margin-bottom: 0;
777
+ }
778
+
779
+ /* Block Item Title */
780
+ .lumir-block-item:hover .lumir-block-item-title {
781
+ color: #1f2937;
782
+ }
783
+
784
+ .lumir-block-item.is-active .lumir-block-item-title {
785
+ color: #3b82f6;
786
+ font-weight: 600;
787
+ }
788
+
789
+ /* Toggle Heading 아이콘 - 컴팩트 */
790
+ .lumir-block-icon-toggle {
791
+ display: flex;
792
+ align-items: center;
793
+ gap: 2px;
794
+ font-size: 9px;
795
+ font-weight: 700;
796
+ color: #6b7280;
797
+ line-height: 1;
798
+ }
799
+
800
+ .lumir-block-icon-toggle svg {
801
+ width: 6px;
802
+ height: 6px;
803
+ flex-shrink: 0;
804
+ }
805
+
806
+ .lumir-block-icon-toggle span {
807
+ font-size: 9px;
808
+ font-weight: 700;
809
+ }
810
+
811
+ .lumir-block-item .lumir-block-icon-toggle {
812
+ font-size: 10px;
813
+ }
814
+
815
+ .lumir-block-item .lumir-block-icon-toggle svg {
816
+ width: 7px;
817
+ height: 7px;
818
+ }
819
+
820
+ .lumir-block-item .lumir-block-icon-toggle span {
821
+ font-size: 10px;
822
+ }
823
+
824
+ .lumir-block-item:hover .lumir-block-icon-toggle,
825
+ .lumir-block-item.is-active .lumir-block-icon-toggle {
826
+ color: inherit;
827
+ }
828
+
829
+ /* Color Picker Menu */
830
+ .lumir-color-menu {
831
+ min-width: 180px;
832
+ padding: 8px;
833
+ }
834
+
835
+ .lumir-color-grid {
836
+ display: grid;
837
+ grid-template-columns: repeat(5, 1fr);
838
+ gap: 6px;
839
+ }
840
+
841
+ .lumir-color-swatch {
842
+ width: 28px;
843
+ height: 28px;
844
+ border: 1px solid rgba(0, 0, 0, 0.15);
845
+ border-radius: 4px;
846
+ cursor: pointer;
847
+ transition: all 0.15s ease;
848
+ position: relative;
849
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
850
+ }
851
+
852
+ .lumir-color-swatch:hover {
853
+ transform: scale(1.15);
854
+ border-color: #3b82f6;
855
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
856
+ z-index: 1;
857
+ }
858
+
859
+ .lumir-color-swatch.is-active {
860
+ border-color: #3b82f6;
861
+ border-width: 2px;
862
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3);
863
+ }
864
+
865
+ .lumir-color-swatch.is-active::after {
866
+ content: '✓';
867
+ position: absolute;
868
+ top: 50%;
869
+ left: 50%;
870
+ transform: translate(-50%, -50%);
871
+ color: #ffffff;
872
+ font-size: 12px;
873
+ font-weight: bold;
874
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
875
+ }
876
+
877
+ .lumir-color-remove {
878
+ width: 100%;
879
+ padding: 6px 8px;
880
+ border: none;
881
+ background-color: #f3f4f6;
882
+ color: #6b7280;
883
+ font-size: 11px;
884
+ font-weight: 500;
885
+ border-radius: 4px;
886
+ cursor: pointer;
887
+ transition: all 0.15s ease;
888
+ }
889
+
890
+ .lumir-color-remove:hover {
891
+ background-color: #e5e7eb;
892
+ color: #374151;
893
+ }
894
+
895
+ /* Text Controls Group */
896
+ .lumir-text-controls {
897
+ gap: 8px;
898
+ }
899
+
900
+ /* Link Input Menu - Compact */
901
+ .lumir-link-menu {
902
+ min-width: 240px;
903
+ padding: 8px;
904
+ left: auto;
905
+ right: 0;
906
+ }
907
+
908
+ .lumir-link-form {
909
+ display: flex;
910
+ flex-direction: column;
911
+ gap: 6px;
912
+ }
913
+
914
+ .lumir-link-input {
915
+ width: 100%;
916
+ padding: 6px 8px;
917
+ border: 1px solid #d1d5db;
918
+ border-radius: 4px;
919
+ font-size: 12px;
920
+ font-family: inherit;
921
+ outline: none;
922
+ transition: all 0.15s ease;
923
+ }
924
+
925
+ .lumir-link-input:focus {
926
+ border-color: #3b82f6;
927
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
928
+ }
929
+
930
+ .lumir-link-input::placeholder {
931
+ color: #9ca3af;
932
+ font-size: 11px;
933
+ }
934
+
935
+ .lumir-link-actions {
936
+ display: flex;
937
+ gap: 4px;
938
+ justify-content: flex-end;
939
+ }
940
+
941
+ .lumir-link-btn {
942
+ padding: 4px 10px;
943
+ border: none;
944
+ border-radius: 4px;
945
+ font-size: 11px;
946
+ font-weight: 500;
947
+ cursor: pointer;
948
+ transition: all 0.15s ease;
949
+ }
950
+
951
+ .lumir-link-cancel {
952
+ background-color: #f3f4f6;
953
+ color: #6b7280;
954
+ }
955
+
956
+ .lumir-link-cancel:hover {
957
+ background-color: #e5e7eb;
958
+ color: #374151;
959
+ }
960
+
961
+ .lumir-link-submit {
962
+ background-color: #3b82f6;
963
+ color: #ffffff;
964
+ }
965
+
966
+ .lumir-link-submit:hover:not(:disabled) {
967
+ background-color: #2563eb;
968
+ }
969
+
970
+ .lumir-link-submit:disabled {
971
+ opacity: 0.5;
972
+ cursor: not-allowed;
973
+ }
974
+
975
+ /*
976
+ * 플로팅 툴바는 다크모드와 관계없이 항상 밝은 스타일 유지
977
+ * 다크모드 오버라이드를 적용하지 않음
978
+ */
979
+
980
+ /* ========================================
981
+ 에러 토스트 스타일
982
+ ======================================== */
983
+
984
+ .lumirEditor-error-toast {
985
+ position: absolute;
986
+ bottom: 16px;
987
+ left: 50%;
988
+ transform: translateX(-50%);
989
+ display: flex;
990
+ align-items: center;
991
+ gap: 8px;
992
+ padding: 12px 16px;
993
+ background-color: #fef2f2;
994
+ border: 1px solid #fecaca;
995
+ border-radius: 8px;
996
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
997
+ z-index: 1001;
998
+ animation: lumirEditor-toast-appear 0.3s ease;
999
+ max-width: 90%;
1000
+ }
1001
+
1002
+ @keyframes lumirEditor-toast-appear {
1003
+ from {
1004
+ opacity: 0;
1005
+ transform: translateX(-50%) translateY(10px);
1006
+ }
1007
+ to {
1008
+ opacity: 1;
1009
+ transform: translateX(-50%) translateY(0);
1010
+ }
1011
+ }
1012
+
1013
+ .lumirEditor-error-icon {
1014
+ flex-shrink: 0;
1015
+ font-size: 16px;
1016
+ }
1017
+
1018
+ .lumirEditor-error-message {
1019
+ font-size: 13px;
1020
+ font-weight: 500;
1021
+ color: #991b1b;
1022
+ line-height: 1.4;
1023
+ }
1024
+
1025
+ .lumirEditor-error-close {
1026
+ flex-shrink: 0;
1027
+ display: flex;
1028
+ align-items: center;
1029
+ justify-content: center;
1030
+ width: 20px;
1031
+ height: 20px;
1032
+ padding: 0;
1033
+ border: none;
1034
+ background: transparent;
1035
+ color: #991b1b;
1036
+ font-size: 14px;
1037
+ cursor: pointer;
1038
+ border-radius: 4px;
1039
+ transition: background-color 0.15s ease;
1040
+ }
1041
+
1042
+ .lumirEditor-error-close:hover {
1043
+ background-color: #fee2e2;
1044
+ }
1045
+
1046
+ /* ========================================
1047
+ Link Preview 카드 스타일
1048
+ ======================================== */
1049
+
1050
+ @keyframes lumir-skeleton-pulse {
1051
+ 0% {
1052
+ opacity: 1;
1053
+ }
1054
+ 50% {
1055
+ opacity: 0.4;
1056
+ }
1057
+ 100% {
1058
+ opacity: 1;
1059
+ }
1060
+ }
1061
+
1062
+ .lumir-link-preview-card:hover .lumir-link-preview-delete {
1063
+ opacity: 1 !important;
1064
+ }
1065
+
1066
+ .lumir-link-preview-delete:hover {
1067
+ background-color: rgba(0, 0, 0, 0.7) !important;
1068
+ }
1069
+
1070
+ .lumir-resize-handle {
1071
+ position: absolute;
1072
+ width: 8px;
1073
+ height: 30px;
1074
+ background-color: black;
1075
+ border: 1px solid white;
1076
+ border-radius: 4px;
1077
+ cursor: ew-resize;
1078
+ top: 50%;
1079
+ transform: translateY(-50%);
1080
+ z-index: 3;
1081
+ }
1082
+
1083
+ .lumir-resize-handle-bottom {
1084
+ position: absolute;
1085
+ bottom: 4px;
1086
+ left: 50%;
1087
+ transform: translateX(-50%);
1088
+ width: 30px;
1089
+ height: 8px;
1090
+ background-color: black;
1091
+ border: 1px solid white;
1092
+ border-radius: 4px;
1093
+ cursor: ns-resize;
1094
+ z-index: 3;
1095
+ }
1096
+
1097
+ .lumir-link-preview-card:hover {
1098
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
1099
+ }
1100
+
1101
+ .node-linkPreview.ProseMirror-selectednode .bn-block-content {
1102
+ outline: 2px solid #3b82f6;
1103
+ outline-offset: 2px;
1104
+ border-radius: 8px;
1105
+ }
1106
+
1107
+ .node-linkPreview .bn-block-content {
1108
+ outline: none !important;
1109
+ }
1110
+
1111
+ /* 다크 테마 대응 */
1112
+ [data-color-scheme='dark'] .lumir-link-preview-card,
1113
+ .bn-container[data-color-scheme='dark'] .lumir-link-preview-card {
1114
+ background-color: #292524 !important;
1115
+ border-color: #44403c !important;
1116
+ }
1117
+
1118
+ [data-color-scheme='dark'] .lumir-link-preview-card:hover,
1119
+ .bn-container[data-color-scheme='dark'] .lumir-link-preview-card:hover {
1120
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3) !important;
1121
+ }
1122
+
1123
+ [data-color-scheme='dark'] .lumir-link-preview-skeleton,
1124
+ .bn-container[data-color-scheme='dark'] .lumir-link-preview-skeleton {
1125
+ background-color: #292524 !important;
1126
+ border-color: #44403c !important;
1127
+ }
1128
+
1129
+ [data-color-scheme='dark'] .lumir-link-preview-error,
1130
+ .bn-container[data-color-scheme='dark'] .lumir-link-preview-error {
1131
+ background-color: #292524 !important;
1132
+ border-color: #44403c !important;
1133
+ }
1134
+
1135
+ /* 인용·코드·테이블 본문 14px */
1136
+ .lumirEditor .bn-block-content[data-content-type='quote'] p.bn-inline-content,
1137
+ .lumirEditor [data-content-type='quote'] blockquote {
1138
+ font-size: 14px;
1139
+ }
1140
+
1141
+ .lumirEditor .bn-block-content[data-content-type='codeBlock'] pre,
1142
+ .lumirEditor .bn-block-content[data-content-type='codeBlock'] pre code {
1143
+ font-size: 14px;
1144
+ }
1145
+
1146
+ .lumirEditor .bn-editor [data-content-type='table'] th,
1147
+ .lumirEditor .bn-editor [data-content-type='table'] td,
1148
+ .lumirEditor .bn-editor [data-content-type='table'] p.bn-inline-content {
1149
+ font-size: 14px;
1150
+ }
1151
+
1152
+ /* 테이블 셀 세로 정렬 (VerticalAlignmentExtension) */
1153
+ .lumirEditor
1154
+ .bn-editor
1155
+ [data-content-type='table']
1156
+ td[data-vertical-alignment='middle'],
1157
+ .lumirEditor
1158
+ .bn-editor
1159
+ [data-content-type='table']
1160
+ th[data-vertical-alignment='middle'] {
1161
+ vertical-align: middle;
1162
+ }
1163
+
1164
+ .lumirEditor
1165
+ .bn-editor
1166
+ [data-content-type='table']
1167
+ td[data-vertical-alignment='bottom'],
1168
+ .lumirEditor
1169
+ .bn-editor
1170
+ [data-content-type='table']
1171
+ th[data-vertical-alignment='bottom'] {
1172
+ vertical-align: bottom;
1173
+ }
1174
+
1175
+ /* ==========================================================================
1176
+ Notion 스타일 FOCUS 기반 테이블 gutter/grip (LumirTableHandlesController)
1177
+ - 셀 focus 시: 셀 테두리 하이라이트(파란 보더, 셀을 살짝 감쌈)
1178
+ - 상단(열)·좌측(행): 짧고 두꺼운 회색 gutter / 우측(셀): 작은 파란 앵커
1179
+ - gutter hover 시: 발판 grip 노출 → 클릭 시 드롭다운
1180
+ - active(메뉴 열림/드래그): 발판이 파란 배경 + 흰 점
1181
+ 기본 BlockNote hover 핸들은 tableHandles={false}로 비활성.
1182
+ ========================================================================== */
1183
+
1184
+ /* focus된 셀 테두리 하이라이트 (셀을 ~2px 바깥에서 감싸는 비클릭 오버레이) */
1185
+ .lumirEditor .lumir-tbl-cell-focus {
1186
+ position: absolute;
1187
+ top: 0;
1188
+ left: 0;
1189
+ box-sizing: border-box;
1190
+ border: 2px solid #2383e2;
1191
+ border-radius: 2px;
1192
+ pointer-events: none;
1193
+ z-index: 1;
1194
+ }
1195
+
1196
+ /* gutter wrapper = hover 히트 영역. 보더에 걸쳐 중앙 배치(positioner offset -7). */
1197
+ .lumirEditor .lumir-tbl-gutter-wrap {
1198
+ position: absolute;
1199
+ z-index: 2;
1200
+ cursor: pointer;
1201
+ }
1202
+
1203
+ .lumirEditor .lumir-tbl-gutter-wrap--col {
1204
+ width: 34px;
1205
+ height: 14px;
1206
+ }
1207
+
1208
+ .lumirEditor .lumir-tbl-gutter-wrap--row,
1209
+ .lumirEditor .lumir-tbl-gutter-wrap--cell {
1210
+ width: 14px;
1211
+ height: 34px;
1212
+ }
1213
+
1214
+ /* 기본 노출: 짧고 두꺼운 gutter 바. wrapper가 셀 보더에 중앙 정렬되어 있으므로,
1215
+ gutter를 wrapper 중앙에 두면 "거터 중앙이 셀 보더선 위"에 오도록 걸쳐진다
1216
+ (절반은 셀 안쪽, 절반은 바깥쪽). */
1217
+ .lumirEditor .lumir-tbl-gutter {
1218
+ position: absolute;
1219
+ inset: 0;
1220
+ margin: auto;
1221
+ box-sizing: border-box;
1222
+ background-color: #c0c0c2;
1223
+ transition: opacity 0.1s ease;
1224
+ }
1225
+
1226
+ /* 상(top): 가로 pill — 상단 보더 중앙 */
1227
+ .lumirEditor .lumir-tbl-gutter-wrap--col .lumir-tbl-gutter {
1228
+ width: 14px;
1229
+ height: 4px;
1230
+ border-left: 1px solid #fff;
1231
+ border-right: 1px solid #fff;
1232
+ }
1233
+
1234
+ /* 좌(left): 세로 pill — 좌측 보더 중앙 (Notion도 좌측에 표시) */
1235
+ .lumirEditor .lumir-tbl-gutter-wrap--row .lumir-tbl-gutter {
1236
+ width: 4px;
1237
+ height: 14px;
1238
+ border-top: 1px solid #fff;
1239
+ border-bottom: 1px solid #fff;
1240
+ }
1241
+
1242
+ /* 우(right): Notion의 파란 선택 앵커 — 우측 보더 중앙 */
1243
+ /* 우(right): 우측 보더의 파란 세로 앵커 */
1244
+ .lumirEditor .lumir-tbl-gutter-wrap--cell .lumir-tbl-gutter {
1245
+ width: 4px;
1246
+ height: 14px;
1247
+ background-color: #2383e2;
1248
+ border-top: 1px solid #fff;
1249
+ border-bottom: 1px solid #fff;
1250
+ }
1251
+
1252
+ .lumirEditor .lumir-tbl-gutter-wrap:hover .lumir-tbl-gutter {
1253
+ opacity: 0;
1254
+ }
1255
+
1256
+ /* 발판 grip: 기본 숨김, gutter hover 시 노출 */
1257
+ .lumirEditor .lumir-tbl-grip {
1258
+ position: absolute;
1259
+ inset: 0;
1260
+ display: flex;
1261
+ align-items: center;
1262
+ justify-content: center;
1263
+ opacity: 0;
1264
+ pointer-events: none;
1265
+ cursor: pointer;
1266
+ transition: opacity 0.1s ease;
1267
+ }
1268
+
1269
+ .lumirEditor .lumir-tbl-gutter-wrap:hover .lumir-tbl-grip {
1270
+ opacity: 1;
1271
+ pointer-events: auto;
1272
+ }
1273
+
1274
+ /* 메뉴 열림(active) 동안 발판 유지(마우스가 떠나도) + rest 바 숨김 */
1275
+ .lumirEditor .lumir-tbl-gutter-wrap--active .lumir-tbl-grip {
1276
+ opacity: 1;
1277
+ pointer-events: auto;
1278
+ }
1279
+
1280
+ .lumirEditor .lumir-tbl-gutter-wrap--active .lumir-tbl-gutter {
1281
+ opacity: 0;
1282
+ }
1283
+
1284
+ /* 드롭다운 오픈(active)·드래그 시 발판: 배경·보더 파랑(#2383e2) + 흰 아이콘 */
1285
+ .lumirEditor .lumir-tbl-gutter-wrap--active .bn-table-handle,
1286
+ .lumirEditor .lumir-tbl-gutter-wrap--active .bn-table-cell-handle,
1287
+ .lumirEditor .lumir-tbl-grip .bn-table-handle-dragging {
1288
+ background-color: #2383e2 !important;
1289
+ border-color: #2383e2 !important;
1290
+ color: #fff !important;
1291
+ }
1292
+
1293
+ /* 발판 크기: 너비(11)↓·높이(14) 유지. 상단 발판은 90° 회전이라 너비↓ = 시각적 높이↓.
1294
+ 배경 흰색 + 보더 진하게(#999). */
1295
+ .lumirEditor .lumir-tbl-grip .bn-table-handle,
1296
+ .lumirEditor .lumir-tbl-grip .bn-table-cell-handle {
1297
+ width: 12px;
1298
+ min-width: 12px;
1299
+ height: 16px;
1300
+ padding: 0;
1301
+ border-radius: 3px;
1302
+ cursor: pointer; /* mantine 기본 grab pointer */
1303
+ background-color: #fff;
1304
+ border: 1px solid #cfcfcf;
1305
+ box-shadow: none; /* mantine 기본 그림자(--bn-shadow-light, 블러처럼 보임) 제거 */
1306
+ }
1307
+
1308
+ /* hover 시에도 배경 유지 (mantine hover 회색 오버라이드) */
1309
+ .lumirEditor .lumir-tbl-grip .bn-table-handle:hover,
1310
+ .lumirEditor .lumir-tbl-grip .bn-table-cell-handle:hover {
1311
+ background-color: #fff;
1312
+ }
1313
+
1314
+ .lumirEditor .lumir-tbl-grip .bn-table-handle svg {
1315
+ width: 12px;
1316
+ height: 12px;
1317
+ margin-inline: 0;
1318
+ }
1319
+
1320
+ .lumirEditor .lumir-tbl-grip .bn-table-cell-handle svg {
1321
+ width: 12px;
1322
+ height: 12px;
1323
+ }
1324
+
1325
+ /* =========================================================
1326
+ 행 높이(row height) 드래그 리사이즈 — rowResizing 플러그인
1327
+ prosemirror-tables의 column-resize 스타일을 수직축으로 미러링.
1328
+ ========================================================= */
1329
+
1330
+ /* activeHandle 동안 에디터 전체 커서를 리사이즈로 */
1331
+ .lumirEditor .ProseMirror.row-resize-cursor {
1332
+ cursor: ns-resize;
1333
+ cursor: row-resize;
1334
+ }
1335
+
1336
+ /* 핸들 위젯의 절대배치 기준(셀). prosemirror-tables 기본값 보강. */
1337
+ .lumirEditor .ProseMirror td,
1338
+ .lumirEditor .ProseMirror th {
1339
+ position: relative;
1340
+ }
1341
+
1342
+ /* 셀 하단 경계 핸들(셀별 1개가 모여 행 폭 전체를 덮음). */
1343
+ .lumirEditor .ProseMirror .row-resize-handle {
1344
+ position: absolute;
1345
+ left: 0;
1346
+ right: 0;
1347
+ bottom: -2px;
1348
+ height: 4px;
1349
+ z-index: 20;
1350
+ background-color: #adf;
1351
+ pointer-events: none;
1352
+ }
1353
+
1354
+ /* 드래그 셀: 레이아웃 트랜지션 제거로 프리뷰 떨림 방지. */
1355
+ .lumirEditor .ProseMirror .row-resize-dragging {
1356
+ transition: none;
1357
+ }
1358
+
1359
+ /* 표 전체 스케일: 우하단 모서리 hit-zone(투명). 오버레이라 에디터 위에 떠서 코너의
1360
+ hover/클릭을 가로채므로 행/열 리사이즈(하단·우측 경계)와 충돌하지 않는다.
1361
+ 보이는 핸들 없이 hover 시 대각 리사이즈 커서만 노출 + 드래그로 크기 조절. */
1362
+ .lumirEditor .lumir-tbl-scale-handle {
1363
+ width: 18px;
1364
+ height: 18px;
1365
+ background: transparent;
1366
+ cursor: nwse-resize;
1367
+ z-index: 30;
1368
+ pointer-events: auto;
1369
+ touch-action: none;
1370
+ }
1371
+ /* 드래그 셀: 트랜지션 제거로 프리뷰 떨림 방지. */
1372
+ .lumirEditor .ProseMirror .lumir-table-scale-dragging {
1373
+ transition: none;
1374
+ }
1375
+
1376
+ /* =========================================================
1377
+ 표 블록 정렬(좌/가운데/우) — TableAlignmentExtension
1378
+ <table>이 width:auto(content 폭)이므로 margin으로 수평 정렬.
1379
+ 좌측(기본)은 별도 규칙 불필요.
1380
+ ========================================================= */
1381
+ .lumirEditor
1382
+ .bn-editor
1383
+ [data-content-type='table'][data-table-alignment='center']
1384
+ table {
1385
+ margin-left: auto;
1386
+ margin-right: auto;
1387
+ }
1388
+
1389
+ .lumirEditor
1390
+ .bn-editor
1391
+ [data-content-type='table'][data-table-alignment='right']
1392
+ table {
1393
+ margin-left: auto;
1394
+ margin-right: 0;
1395
+ }
1396
+
1397
+ /* =========================================================
1398
+ 하단 여백 축소
1399
+ @blocknote 기본 .tableWrapper `position:relative; top:-16px`라서, 화면상 16px
1400
+ 위로 그리되 레이아웃 공간은 원위치에 예약 → 래퍼 박스 아래에 사용되지 않는 16px
1401
+ 남는다(순수 artifact). 음수 margin-bottom으로 이 예약 공백만 정확히 상쇄한다.
1402
+ 래퍼의 padding/overflow는 건드리지 않으므로 행/열 추가 버튼·리사이즈 핸들·거터의
1403
+ 클리어런스(클립 경계)는 그대로 유지된다 → 사이드이펙트 없음.
1404
+ ========================================================= */
1405
+ .lumirEditor .bn-editor [data-content-type='table'] .tableWrapper {
1406
+ margin-bottom: -16px;
1407
+ }
1408
+
1409
+ /* =========================================================
1410
+ 다단(컬럼) 레이아웃 — columnList / column 노드
1411
+ columnList: 가로 flex 컨테이너, column: 균등 폭 flex 아이템.
1412
+ ========================================================= */
1413
+ .lumirEditor .bn-column-list {
1414
+ display: flex;
1415
+ gap: 16px;
1416
+ width: 100%;
1417
+ }
1418
+
1419
+ .lumirEditor .bn-column {
1420
+ flex: 1 1 0;
1421
+ min-width: 0; /* 컬럼 넓은 콘텐츠( 등) 오버플로 방지 */
1422
+ }
1423
+
1424
+ /* 컬럼 중앙 세로 구분선. 두 가지 방식으로 켜진다(둘 중 하나라도 켜지면 표시):
1425
+ 1) 전역: columnDivider prop → 루트 `.lumir-column-divider` (모든 컬럼).
1426
+ 2) 블록별: columnList의 `showDivider` attr → `data-divider="true"` (드래그핸들 메뉴 토글).
1427
+ divider가 드래그 핸들(grip)에 가려지지 않도록 gap을 넓혀(기본 16px grip-space×2)
1428
+ divider를 정중앙에 두고 양쪽에 grip 너비만큼 여백을 둔다. 마지막 컬럼 제외 → N컬럼이면
1429
+ N-1개. flex 기본 align-items:stretch로 컬럼 높이가 같아 구분선이 전체 높이를 채운다.
1430
+ grip-space/색은 CSS 변수로 조정 가능. */
1431
+ .lumirEditor.lumir-column-divider .bn-column-list,
1432
+ .lumirEditor .bn-column-list[data-divider="true"] {
1433
+ --lumir-column-grip-space: 28px; /* divider ~ 콘텐츠 여백(≈grip 너비 + 여유) */
1434
+ gap: calc(var(--lumir-column-grip-space) * 2);
1435
+ }
1436
+ .lumirEditor.lumir-column-divider .bn-column,
1437
+ .lumirEditor .bn-column-list[data-divider="true"] .bn-column {
1438
+ position: relative;
1439
+ }
1440
+ .lumirEditor.lumir-column-divider .bn-column:not(:last-child)::after,
1441
+ .lumirEditor .bn-column-list[data-divider="true"] .bn-column:not(:last-child)::after {
1442
+ content: "";
1443
+ position: absolute;
1444
+ top: 0;
1445
+ bottom: 0;
1446
+ right: calc(var(--lumir-column-grip-space) * -1); /* gap 정중앙 */
1447
+ width: 1px;
1448
+ background: var(--lumir-column-divider-color, #e5e7eb);
1449
+ pointer-events: none;
1450
+ }
1451
+
1452
+ /* DnD 컬럼 생성: 드롭 대상 블록의 좌/우 가장자리 세로 인디케이터(레이아웃 비이동 box-shadow) */
1453
+ .lumirEditor .lumir-col-drop-left {
1454
+ box-shadow: -3px 0 0 0 #3b82f6;
1455
+ }
1456
+ .lumirEditor .lumir-col-drop-right {
1457
+ box-shadow: 3px 0 0 0 #3b82f6;
1458
+ }
1459
+ /* 가장자리 드롭 중에는 기본(가로) 드롭커서를 숨겨 인디케이터 중복 방지 */
1460
+ .lumirEditor .lumir-col-dnd-active .prosemirror-dropcursor,
1461
+ .lumirEditor .lumir-col-dnd-active .ProseMirror-dropcursor {
1462
+ display: none !important;
1463
+ }