inkpen 0.7.1

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 (95) hide show
  1. checksums.yaml +7 -0
  2. data/.DS_Store +0 -0
  3. data/.rubocop.yml +8 -0
  4. data/.yardopts +11 -0
  5. data/CLAUDE.md +141 -0
  6. data/README.md +409 -0
  7. data/Rakefile +19 -0
  8. data/app/assets/javascripts/inkpen/controllers/editor_controller.js +2050 -0
  9. data/app/assets/javascripts/inkpen/controllers/sticky_toolbar_controller.js +667 -0
  10. data/app/assets/javascripts/inkpen/controllers/toolbar_controller.js +693 -0
  11. data/app/assets/javascripts/inkpen/export/html.js +637 -0
  12. data/app/assets/javascripts/inkpen/export/index.js +30 -0
  13. data/app/assets/javascripts/inkpen/export/markdown.js +697 -0
  14. data/app/assets/javascripts/inkpen/export/pdf.js +372 -0
  15. data/app/assets/javascripts/inkpen/extensions/advanced_table.js +640 -0
  16. data/app/assets/javascripts/inkpen/extensions/block_commands.js +300 -0
  17. data/app/assets/javascripts/inkpen/extensions/block_gutter.js +338 -0
  18. data/app/assets/javascripts/inkpen/extensions/callout.js +303 -0
  19. data/app/assets/javascripts/inkpen/extensions/columns.js +403 -0
  20. data/app/assets/javascripts/inkpen/extensions/database.js +990 -0
  21. data/app/assets/javascripts/inkpen/extensions/document_section.js +352 -0
  22. data/app/assets/javascripts/inkpen/extensions/drag_handle.js +407 -0
  23. data/app/assets/javascripts/inkpen/extensions/embed.js +629 -0
  24. data/app/assets/javascripts/inkpen/extensions/enhanced_image.js +566 -0
  25. data/app/assets/javascripts/inkpen/extensions/export_commands.js +271 -0
  26. data/app/assets/javascripts/inkpen/extensions/file_attachment.js +593 -0
  27. data/app/assets/javascripts/inkpen/extensions/inkpen_table/index.js +58 -0
  28. data/app/assets/javascripts/inkpen/extensions/inkpen_table/inkpen_table.js +638 -0
  29. data/app/assets/javascripts/inkpen/extensions/inkpen_table/inkpen_table_cell.js +100 -0
  30. data/app/assets/javascripts/inkpen/extensions/inkpen_table/inkpen_table_header.js +100 -0
  31. data/app/assets/javascripts/inkpen/extensions/inkpen_table/table_constants.js +152 -0
  32. data/app/assets/javascripts/inkpen/extensions/inkpen_table/table_helpers.js +254 -0
  33. data/app/assets/javascripts/inkpen/extensions/inkpen_table/table_menu.js +282 -0
  34. data/app/assets/javascripts/inkpen/extensions/preformatted.js +239 -0
  35. data/app/assets/javascripts/inkpen/extensions/section.js +281 -0
  36. data/app/assets/javascripts/inkpen/extensions/section_title.js +126 -0
  37. data/app/assets/javascripts/inkpen/extensions/slash_commands.js +439 -0
  38. data/app/assets/javascripts/inkpen/extensions/table_of_contents.js +474 -0
  39. data/app/assets/javascripts/inkpen/extensions/toggle_block.js +332 -0
  40. data/app/assets/javascripts/inkpen/index.js +87 -0
  41. data/app/assets/stylesheets/inkpen/advanced_table.css +514 -0
  42. data/app/assets/stylesheets/inkpen/animations.css +626 -0
  43. data/app/assets/stylesheets/inkpen/block_gutter.css +265 -0
  44. data/app/assets/stylesheets/inkpen/callout.css +359 -0
  45. data/app/assets/stylesheets/inkpen/columns.css +314 -0
  46. data/app/assets/stylesheets/inkpen/database.css +658 -0
  47. data/app/assets/stylesheets/inkpen/document_section.css +305 -0
  48. data/app/assets/stylesheets/inkpen/drag_drop.css +220 -0
  49. data/app/assets/stylesheets/inkpen/editor.css +652 -0
  50. data/app/assets/stylesheets/inkpen/embed.css +468 -0
  51. data/app/assets/stylesheets/inkpen/enhanced_image.css +453 -0
  52. data/app/assets/stylesheets/inkpen/export.css +499 -0
  53. data/app/assets/stylesheets/inkpen/file_attachment.css +347 -0
  54. data/app/assets/stylesheets/inkpen/footnotes.css +136 -0
  55. data/app/assets/stylesheets/inkpen/inkpen_table.css +608 -0
  56. data/app/assets/stylesheets/inkpen/preformatted.css +215 -0
  57. data/app/assets/stylesheets/inkpen/search_replace.css +58 -0
  58. data/app/assets/stylesheets/inkpen/section.css +236 -0
  59. data/app/assets/stylesheets/inkpen/slash_menu.css +252 -0
  60. data/app/assets/stylesheets/inkpen/sticky_toolbar.css +314 -0
  61. data/app/assets/stylesheets/inkpen/toc.css +386 -0
  62. data/app/assets/stylesheets/inkpen/toggle.css +260 -0
  63. data/app/helpers/inkpen/editor_helper.rb +114 -0
  64. data/app/views/inkpen/_editor.html.erb +139 -0
  65. data/config/importmap.rb +170 -0
  66. data/docs/.DS_Store +0 -0
  67. data/docs/CHANGELOG.md +571 -0
  68. data/docs/FEATURES.md +436 -0
  69. data/docs/ROADMAP.md +3029 -0
  70. data/docs/VISION.md +235 -0
  71. data/docs/extensions/INKPEN_TABLE.md +482 -0
  72. data/docs/thinking/CORRECTED_NO_VUE.md +756 -0
  73. data/docs/thinking/EXECUTIVE_SUMMARY.md +403 -0
  74. data/docs/thinking/INKPEN_CODE_SAMPLES.md +1479 -0
  75. data/docs/thinking/INKPEN_MASTER_GUIDE.md +891 -0
  76. data/docs/thinking/README_START_HERE.md +341 -0
  77. data/lib/inkpen/configuration.rb +175 -0
  78. data/lib/inkpen/editor.rb +204 -0
  79. data/lib/inkpen/engine.rb +32 -0
  80. data/lib/inkpen/extensions/base.rb +109 -0
  81. data/lib/inkpen/extensions/code_block_syntax.rb +177 -0
  82. data/lib/inkpen/extensions/document_section.rb +111 -0
  83. data/lib/inkpen/extensions/forced_document.rb +183 -0
  84. data/lib/inkpen/extensions/mention.rb +155 -0
  85. data/lib/inkpen/extensions/preformatted.rb +111 -0
  86. data/lib/inkpen/extensions/section.rb +139 -0
  87. data/lib/inkpen/extensions/slash_commands.rb +100 -0
  88. data/lib/inkpen/extensions/table.rb +182 -0
  89. data/lib/inkpen/extensions/task_list.rb +145 -0
  90. data/lib/inkpen/sticky_toolbar.rb +157 -0
  91. data/lib/inkpen/toolbar.rb +145 -0
  92. data/lib/inkpen/version.rb +5 -0
  93. data/lib/inkpen.rb +101 -0
  94. data/sig/inkpen.rbs +4 -0
  95. metadata +165 -0
@@ -0,0 +1,652 @@
1
+ /* Inkpen Editor Styles
2
+ * ========================================================================== */
3
+
4
+ /* CSS Custom Properties (override these in your app) */
5
+ :root {
6
+ --inkpen-font-family: inherit;
7
+ --inkpen-font-size: 1rem;
8
+ --inkpen-line-height: 1.6;
9
+ --inkpen-color-text: #1a1a1a;
10
+ --inkpen-color-text-muted: #6b7280;
11
+ --inkpen-color-background: #ffffff;
12
+ --inkpen-color-border: #e5e7eb;
13
+ --inkpen-color-primary: #3b82f6;
14
+ --inkpen-color-selection: rgba(59, 130, 246, 0.2);
15
+ --inkpen-radius: 0.375rem;
16
+ --inkpen-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
17
+ --inkpen-toolbar-bg: #ffffff;
18
+ --inkpen-toolbar-border: #e5e7eb;
19
+ }
20
+
21
+ /* Dark mode support */
22
+ @media (prefers-color-scheme: dark) {
23
+ :root {
24
+ --inkpen-color-text: #f3f4f6;
25
+ --inkpen-color-text-muted: #9ca3af;
26
+ --inkpen-color-background: #1f2937;
27
+ --inkpen-color-border: #374151;
28
+ --inkpen-toolbar-bg: #1f2937;
29
+ --inkpen-toolbar-border: #374151;
30
+ }
31
+ }
32
+
33
+ /* Editor Container */
34
+ .inkpen-editor {
35
+ position: relative;
36
+ font-family: var(--inkpen-font-family);
37
+ font-size: var(--inkpen-font-size);
38
+ line-height: var(--inkpen-line-height);
39
+ color: var(--inkpen-color-text);
40
+ background: var(--inkpen-color-background);
41
+ overflow: hidden;
42
+ display: flex;
43
+ flex-direction: column;
44
+ }
45
+
46
+ /* Content Area */
47
+ .inkpen-editor__content {
48
+ outline: none;
49
+ min-height: 200px;
50
+ padding: 1rem;
51
+ overflow-y: auto;
52
+ overflow-x: hidden;
53
+ flex: 1 1 auto;
54
+ /* Ensure content respects parent max-height */
55
+ max-height: inherit;
56
+ }
57
+
58
+ /* ProseMirror editor element inside content area */
59
+ .inkpen-editor__content .ProseMirror {
60
+ outline: none;
61
+ min-height: 100%;
62
+ }
63
+
64
+ /* Fixed toolbar layout */
65
+ .inkpen-editor--fixed-toolbar {
66
+ border: 1px solid var(--inkpen-toolbar-border);
67
+ border-radius: var(--inkpen-radius);
68
+ }
69
+
70
+ .inkpen-editor--fixed-toolbar .inkpen-toolbar--fixed {
71
+ flex-shrink: 0;
72
+ }
73
+
74
+ .inkpen-editor--fixed-toolbar .inkpen-editor__content {
75
+ flex: 1 1 0;
76
+ min-height: 0; /* Important: allows flex child to shrink below content size */
77
+ overflow-y: auto;
78
+ }
79
+
80
+ /* TipTap Placeholder Extension Styles */
81
+ .inkpen-editor__content .is-empty::before {
82
+ content: attr(data-placeholder);
83
+ color: var(--inkpen-color-text-muted);
84
+ float: left;
85
+ height: 0;
86
+ pointer-events: none;
87
+ }
88
+
89
+ /* Title placeholder - larger, more prominent */
90
+ .inkpen-editor__content h1.is-empty::before {
91
+ font-size: 2rem;
92
+ font-weight: 600;
93
+ }
94
+
95
+ /* Subtitle placeholder - slightly smaller, italic */
96
+ .inkpen-editor__content h2.is-empty::before {
97
+ font-size: 1.5rem;
98
+ font-weight: 400;
99
+ font-style: italic;
100
+ }
101
+
102
+ /* Legacy fallback */
103
+ .inkpen-editor__content:empty::before {
104
+ content: attr(data-placeholder);
105
+ color: var(--inkpen-color-text-muted);
106
+ pointer-events: none;
107
+ }
108
+
109
+ /* Focus state */
110
+ .inkpen-editor__content:focus {
111
+ outline: none;
112
+ }
113
+
114
+ /* Floating Toolbar - uses TipTap's BubbleMenu with Tippy.js */
115
+ .inkpen-toolbar--floating {
116
+ display: flex;
117
+ gap: 0.25rem;
118
+ padding: 0.375rem;
119
+ background: var(--inkpen-toolbar-bg);
120
+ border: 1px solid var(--inkpen-toolbar-border);
121
+ border-radius: var(--inkpen-radius);
122
+ box-shadow: var(--inkpen-shadow);
123
+ }
124
+
125
+ /* Fixed Toolbar - always visible above editor */
126
+ .inkpen-toolbar--fixed {
127
+ display: flex;
128
+ flex-wrap: wrap;
129
+ gap: 0.25rem;
130
+ padding: 0.5rem;
131
+ background: var(--inkpen-toolbar-bg);
132
+ border: 1px solid var(--inkpen-toolbar-border);
133
+ border-bottom: none;
134
+ border-radius: var(--inkpen-radius) var(--inkpen-radius) 0 0;
135
+ }
136
+
137
+ /* Editor container with fixed toolbar */
138
+ .inkpen-editor--fixed-toolbar .inkpen-editor__content {
139
+ border: 1px solid var(--inkpen-toolbar-border);
140
+ border-radius: 0 0 var(--inkpen-radius) var(--inkpen-radius);
141
+ }
142
+
143
+ /* Tippy.js theme for inkpen toolbar */
144
+ .tippy-box[data-theme~='inkpen'] {
145
+ background-color: var(--inkpen-toolbar-bg);
146
+ border: 1px solid var(--inkpen-toolbar-border);
147
+ border-radius: var(--inkpen-radius);
148
+ box-shadow: var(--inkpen-shadow);
149
+ }
150
+
151
+ .tippy-box[data-theme~='inkpen'] > .tippy-arrow::before {
152
+ border-top-color: var(--inkpen-toolbar-bg);
153
+ }
154
+
155
+ .tippy-box[data-theme~='inkpen'] > .tippy-content {
156
+ padding: 0;
157
+ }
158
+
159
+ /* Toolbar Buttons */
160
+ .inkpen-toolbar__button {
161
+ display: flex;
162
+ align-items: center;
163
+ justify-content: center;
164
+ width: 2rem;
165
+ height: 2rem;
166
+ padding: 0;
167
+ background: transparent;
168
+ border: none;
169
+ border-radius: var(--inkpen-radius);
170
+ color: var(--inkpen-color-text);
171
+ cursor: pointer;
172
+ transition: background-color 150ms;
173
+ }
174
+
175
+ .inkpen-toolbar__button:hover {
176
+ background: var(--inkpen-color-selection);
177
+ }
178
+
179
+ .inkpen-toolbar__button.is-active {
180
+ background: var(--inkpen-color-primary);
181
+ color: white;
182
+ }
183
+
184
+ .inkpen-toolbar__button svg {
185
+ width: 1rem;
186
+ height: 1rem;
187
+ }
188
+
189
+ .inkpen-toolbar__divider {
190
+ width: 1px;
191
+ height: 1.5rem;
192
+ background: var(--inkpen-color-border);
193
+ margin: 0 0.25rem;
194
+ }
195
+
196
+ /* ==========================================================================
197
+ Content Styles (inside editor)
198
+ ========================================================================== */
199
+
200
+ .inkpen-editor__content {
201
+ /* Headings */
202
+ h1, h2, h3, h4, h5, h6 {
203
+ font-weight: 600;
204
+ line-height: 1.3;
205
+ margin-top: 1.5rem;
206
+ margin-bottom: 0.5rem;
207
+ }
208
+
209
+ h1 { font-size: 2rem; }
210
+ h2 { font-size: 1.5rem; }
211
+ h3 { font-size: 1.25rem; }
212
+ h4 { font-size: 1rem; }
213
+
214
+ /* Paragraphs */
215
+ p {
216
+ margin-bottom: 1rem;
217
+ }
218
+
219
+ /* Lists */
220
+ ul, ol {
221
+ margin-bottom: 1rem;
222
+ padding-left: 1.5rem;
223
+ }
224
+
225
+ li {
226
+ margin-bottom: 0.25rem;
227
+ }
228
+
229
+ /* Task Lists (TipTap TaskList extension)
230
+ * Uses .inkpen-task-list and .inkpen-task-item classes from TipTap config
231
+ * High specificity via nesting to avoid !important */
232
+ ul.inkpen-task-list,
233
+ ul[data-type="taskList"] {
234
+ list-style-type: none;
235
+ padding-left: 0;
236
+ margin: 0 0 1rem 0;
237
+ }
238
+
239
+ /* Reset any browser default markers */
240
+ ul.inkpen-task-list li,
241
+ ul[data-type="taskList"] li {
242
+ list-style-type: none;
243
+ }
244
+
245
+ li.inkpen-task-item,
246
+ li[data-type="taskItem"] {
247
+ display: flex;
248
+ flex-direction: row;
249
+ align-items: flex-start;
250
+ gap: 0.5rem;
251
+ margin-bottom: 0.5rem;
252
+ }
253
+
254
+ /* Hide any list markers/bullets */
255
+ li.inkpen-task-item::before,
256
+ li[data-type="taskItem"]::before {
257
+ content: none;
258
+ }
259
+
260
+ li.inkpen-task-item::marker,
261
+ li[data-type="taskItem"]::marker {
262
+ content: none;
263
+ }
264
+
265
+ /* Checkbox label container */
266
+ li.inkpen-task-item > label,
267
+ li[data-type="taskItem"] > label {
268
+ flex: 0 0 auto;
269
+ display: inline-flex;
270
+ align-items: center;
271
+ justify-content: center;
272
+ margin-top: 0.125rem;
273
+ user-select: none;
274
+ cursor: pointer;
275
+ }
276
+
277
+ /* Checkbox input */
278
+ li.inkpen-task-item > label input[type="checkbox"],
279
+ li[data-type="taskItem"] > label input[type="checkbox"] {
280
+ width: 1.125rem;
281
+ height: 1.125rem;
282
+ cursor: pointer;
283
+ accent-color: var(--inkpen-color-primary);
284
+ margin: 0;
285
+ padding: 0;
286
+ border-radius: 0.25rem;
287
+ }
288
+
289
+ /* Content area - where user types (contenteditable div) */
290
+ li.inkpen-task-item > div,
291
+ li[data-type="taskItem"] > div {
292
+ flex: 1 1 auto;
293
+ min-width: 0;
294
+ outline: none;
295
+ word-break: break-word;
296
+ }
297
+
298
+ /* Paragraph inside task item - reset margins for inline feel */
299
+ li.inkpen-task-item > div p,
300
+ li[data-type="taskItem"] > div p {
301
+ margin: 0;
302
+ padding: 0;
303
+ }
304
+
305
+ /* Checked state - strikethrough */
306
+ li.inkpen-task-item[data-checked="true"] > div,
307
+ li[data-type="taskItem"][data-checked="true"] > div {
308
+ text-decoration: line-through;
309
+ color: var(--inkpen-color-text-muted);
310
+ }
311
+
312
+ /* Nested task lists */
313
+ ul.inkpen-task-list ul.inkpen-task-list,
314
+ ul[data-type="taskList"] ul[data-type="taskList"] {
315
+ margin-top: 0.5rem;
316
+ margin-bottom: 0;
317
+ padding-left: 1.5rem;
318
+ }
319
+
320
+ /* Blockquote */
321
+ blockquote {
322
+ border-left: 3px solid var(--inkpen-color-border);
323
+ margin: 1rem 0;
324
+ padding: 0.5rem 1rem;
325
+ font-style: italic;
326
+ color: var(--inkpen-color-text-muted);
327
+ }
328
+
329
+ /* Code */
330
+ code {
331
+ background: var(--inkpen-color-selection);
332
+ padding: 0.125rem 0.25rem;
333
+ border-radius: 0.25rem;
334
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
335
+ font-size: 0.875em;
336
+ }
337
+
338
+ pre {
339
+ background: var(--inkpen-color-border);
340
+ padding: 1rem;
341
+ border-radius: var(--inkpen-radius);
342
+ overflow-x: auto;
343
+ margin: 1rem 0;
344
+
345
+ code {
346
+ background: none;
347
+ padding: 0;
348
+ }
349
+ }
350
+
351
+ /* Links */
352
+ a {
353
+ color: var(--inkpen-color-primary);
354
+ text-decoration: underline;
355
+ }
356
+
357
+ /* Highlight mark */
358
+ mark,
359
+ .inkpen-highlight {
360
+ background-color: #fef08a;
361
+ padding: 0.125em 0;
362
+ border-radius: 0.125rem;
363
+ }
364
+
365
+ /* Multicolor highlights */
366
+ mark[data-color="yellow"],
367
+ .inkpen-highlight[data-color="yellow"] {
368
+ background-color: #fef08a;
369
+ }
370
+
371
+ mark[data-color="green"],
372
+ .inkpen-highlight[data-color="green"] {
373
+ background-color: #bbf7d0;
374
+ }
375
+
376
+ mark[data-color="blue"],
377
+ .inkpen-highlight[data-color="blue"] {
378
+ background-color: #bfdbfe;
379
+ }
380
+
381
+ mark[data-color="pink"],
382
+ .inkpen-highlight[data-color="pink"] {
383
+ background-color: #fbcfe8;
384
+ }
385
+
386
+ mark[data-color="purple"],
387
+ .inkpen-highlight[data-color="purple"] {
388
+ background-color: #ddd6fe;
389
+ }
390
+
391
+ mark[data-color="orange"],
392
+ .inkpen-highlight[data-color="orange"] {
393
+ background-color: #fed7aa;
394
+ }
395
+
396
+ /* Horizontal Rule */
397
+ hr {
398
+ border: none;
399
+ border-top: 1px solid var(--inkpen-color-border);
400
+ margin: 2rem 0;
401
+ }
402
+
403
+ /* Tables */
404
+ table {
405
+ width: 100%;
406
+ border-collapse: collapse;
407
+ margin: 1rem 0;
408
+ }
409
+
410
+ th, td {
411
+ border: 1px solid var(--inkpen-color-border);
412
+ padding: 0.5rem 1rem;
413
+ text-align: left;
414
+ }
415
+
416
+ th {
417
+ background: var(--inkpen-color-selection);
418
+ font-weight: 600;
419
+ }
420
+
421
+ /* Images */
422
+ img {
423
+ max-width: 100%;
424
+ height: auto;
425
+ border-radius: var(--inkpen-radius);
426
+ }
427
+
428
+ /* Selection */
429
+ ::selection {
430
+ background: var(--inkpen-color-selection);
431
+ }
432
+
433
+ /* Callout Boxes */
434
+ .inkpen-callout {
435
+ display: flex;
436
+ gap: 0.75rem;
437
+ padding: 1rem;
438
+ border-radius: var(--inkpen-radius);
439
+ margin: 1rem 0;
440
+ background: var(--inkpen-color-border);
441
+ border-left: 4px solid var(--inkpen-color-primary);
442
+ }
443
+
444
+ .inkpen-callout__icon {
445
+ flex-shrink: 0;
446
+ font-size: 1.25rem;
447
+ line-height: 1.5;
448
+ }
449
+
450
+ .inkpen-callout__content {
451
+ flex: 1;
452
+ min-width: 0;
453
+
454
+ p {
455
+ margin: 0;
456
+ }
457
+ }
458
+
459
+ .inkpen-callout--info {
460
+ background: rgba(59, 130, 246, 0.1);
461
+ border-left-color: #3b82f6;
462
+ }
463
+
464
+ .inkpen-callout--warning {
465
+ background: rgba(245, 158, 11, 0.1);
466
+ border-left-color: #f59e0b;
467
+ }
468
+
469
+ .inkpen-callout--tip {
470
+ background: rgba(16, 185, 129, 0.1);
471
+ border-left-color: #10b981;
472
+ }
473
+
474
+ .inkpen-callout--note {
475
+ background: rgba(139, 92, 246, 0.1);
476
+ border-left-color: #8b5cf6;
477
+ }
478
+
479
+ /* HTML Block */
480
+ .inkpen-html-block {
481
+ padding: 1rem;
482
+ margin: 1rem 0;
483
+ border: 1px dashed var(--inkpen-color-border);
484
+ border-radius: var(--inkpen-radius);
485
+ background: var(--inkpen-color-background);
486
+ position: relative;
487
+ }
488
+
489
+ .inkpen-html-block::before {
490
+ content: "HTML";
491
+ position: absolute;
492
+ top: -0.75em;
493
+ left: 0.5rem;
494
+ padding: 0 0.25rem;
495
+ font-size: 0.625rem;
496
+ font-weight: 600;
497
+ text-transform: uppercase;
498
+ letter-spacing: 0.05em;
499
+ color: var(--inkpen-color-text-muted);
500
+ background: var(--inkpen-color-background);
501
+ }
502
+ }
503
+
504
+ /* Context-Aware Toolbar Styles */
505
+ .inkpen-toolbar[data-context="table"] {
506
+ min-width: 400px;
507
+ }
508
+
509
+ .inkpen-toolbar[data-context="code"] {
510
+ min-width: 150px;
511
+ }
512
+
513
+ .inkpen-toolbar[data-context="image"] {
514
+ min-width: 180px;
515
+ }
516
+
517
+ /* Fallback Textarea
518
+ Shown when TipTap fails to initialize (CDN issues, JS errors, etc.)
519
+ ========================================================================== */
520
+ .inkpen-editor__fallback {
521
+ width: 100%;
522
+ min-height: 200px;
523
+ padding: 1rem;
524
+ border: 1px solid var(--inkpen-color-border);
525
+ border-radius: var(--inkpen-radius);
526
+ font-family: var(--inkpen-font-family);
527
+ font-size: var(--inkpen-font-size);
528
+ line-height: var(--inkpen-line-height);
529
+ color: var(--inkpen-color-text);
530
+ background: var(--inkpen-color-background);
531
+ resize: vertical;
532
+ outline: none;
533
+ transition: border-color 150ms ease;
534
+ }
535
+
536
+ .inkpen-editor__fallback:focus {
537
+ border-color: var(--inkpen-color-primary);
538
+ box-shadow: 0 0 0 3px var(--inkpen-color-selection);
539
+ }
540
+
541
+ .inkpen-editor__fallback::placeholder {
542
+ color: var(--inkpen-color-text-muted);
543
+ }
544
+
545
+ /* ============================================
546
+ Markdown Mode Styles
547
+ ============================================ */
548
+
549
+ /* Mode Toggle Button */
550
+ .inkpen-mode-toggle {
551
+ display: flex;
552
+ gap: 2px;
553
+ padding: 4px;
554
+ background: var(--inkpen-toggle-bg, #f5f5f5);
555
+ border-radius: 8px;
556
+ width: fit-content;
557
+ margin-bottom: 12px;
558
+ }
559
+
560
+ .inkpen-mode-toggle button {
561
+ padding: 6px 12px;
562
+ border: none;
563
+ background: transparent;
564
+ font-size: 13px;
565
+ font-weight: 500;
566
+ color: var(--inkpen-color-text-muted);
567
+ border-radius: 6px;
568
+ cursor: pointer;
569
+ transition: all 0.15s ease;
570
+ }
571
+
572
+ .inkpen-mode-toggle button:hover {
573
+ color: var(--inkpen-color-text);
574
+ background: rgba(0, 0, 0, 0.05);
575
+ }
576
+
577
+ .inkpen-mode-toggle button.active {
578
+ background: var(--inkpen-color-background);
579
+ color: var(--inkpen-color-text);
580
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
581
+ }
582
+
583
+ /* Markdown Editor Textarea */
584
+ .inkpen-markdown-editor {
585
+ width: 100%;
586
+ min-height: 300px;
587
+ padding: 16px;
588
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
589
+ font-size: 14px;
590
+ line-height: 1.6;
591
+ color: var(--inkpen-color-text);
592
+ background: var(--inkpen-color-background);
593
+ border: 1px solid var(--inkpen-color-border);
594
+ border-radius: var(--inkpen-radius);
595
+ resize: vertical;
596
+ outline: none;
597
+ transition: border-color 0.15s ease, box-shadow 0.15s ease;
598
+ }
599
+
600
+ .inkpen-markdown-editor:focus {
601
+ border-color: var(--inkpen-color-primary);
602
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
603
+ }
604
+
605
+ .inkpen-markdown-editor::placeholder {
606
+ color: var(--inkpen-color-text-muted);
607
+ }
608
+
609
+ .inkpen-markdown-editor.hidden {
610
+ display: none;
611
+ }
612
+
613
+ /* Split View Layout */
614
+ .inkpen-editor--split {
615
+ display: grid;
616
+ grid-template-columns: 1fr 1fr;
617
+ gap: 16px;
618
+ }
619
+
620
+ .inkpen-editor--split .inkpen-markdown-editor,
621
+ .inkpen-editor--split .inkpen-editor__content {
622
+ min-height: 400px;
623
+ max-height: 600px;
624
+ overflow-y: auto;
625
+ }
626
+
627
+ /* Responsive: Stack on mobile */
628
+ @media (max-width: 768px) {
629
+ .inkpen-editor--split {
630
+ grid-template-columns: 1fr;
631
+ }
632
+
633
+ .inkpen-editor--split .inkpen-markdown-editor,
634
+ .inkpen-editor--split .inkpen-editor__content {
635
+ min-height: 250px;
636
+ max-height: 400px;
637
+ }
638
+ }
639
+
640
+ /* Keyboard Shortcut Hints */
641
+ .inkpen-mode-toggle [data-shortcut]::after {
642
+ content: attr(data-shortcut);
643
+ font-size: 10px;
644
+ color: var(--inkpen-color-text-muted);
645
+ margin-left: 6px;
646
+ opacity: 0;
647
+ transition: opacity 0.15s ease;
648
+ }
649
+
650
+ .inkpen-mode-toggle:hover [data-shortcut]::after {
651
+ opacity: 0.7;
652
+ }