@miliastry/quasar 1.0.0

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 (172) hide show
  1. package/LICENSE +119 -0
  2. package/README.md +45 -0
  3. package/dist/Visuals/lyne.css +1027 -0
  4. package/dist/Visuals/osu.css +257 -0
  5. package/dist/index.d.mts +4563 -0
  6. package/dist/index.d.ts +4563 -0
  7. package/dist/index.js +11291 -0
  8. package/dist/index.mjs +11197 -0
  9. package/package.json +51 -0
  10. package/src/Analysis/Contracts/AnalysisReport.ts +26 -0
  11. package/src/Analysis/Contracts/Contribution.ts +76 -0
  12. package/src/Analysis/Contracts/Pass.ts +76 -0
  13. package/src/Analysis/Contracts/PipelineContext.ts +48 -0
  14. package/src/Analysis/Passes/Analysis/GradientAnalyzer.ts +292 -0
  15. package/src/Analysis/Passes/Analysis/MergeableColorAnalyzer.ts +112 -0
  16. package/src/Analysis/Passes/Analysis/RainbowAnalyzer.ts +233 -0
  17. package/src/Analysis/Passes/Analysis/WaveAnalyzer.ts +211 -0
  18. package/src/Analysis/Passes/Analysis/__tests__/GradientAnalyzer.test.ts +135 -0
  19. package/src/Analysis/Passes/Analysis/__tests__/MergeableColorAnalyzer.test.ts +84 -0
  20. package/src/Analysis/Passes/Analysis/__tests__/RainbowAnalyzer.test.ts +99 -0
  21. package/src/Analysis/Passes/Analysis/__tests__/WaveAnalyzer.test.ts +119 -0
  22. package/src/Analysis/Passes/Decision/DefaultDecision.ts +139 -0
  23. package/src/Analysis/Passes/Decision/__tests__/DefaultDecision.test.ts +179 -0
  24. package/src/Analysis/Passes/Transform/CollapseGradientTransform.ts +176 -0
  25. package/src/Analysis/Passes/Transform/MergeColorsTransform.ts +126 -0
  26. package/src/Analysis/Passes/Transform/RainbowCollapseTransform.ts +83 -0
  27. package/src/Analysis/Passes/Transform/WaveCollapseTransform.ts +88 -0
  28. package/src/Analysis/Passes/Utility/CharacterCountAnalyzer.ts +45 -0
  29. package/src/Analysis/Pipeline/Pipeline.ts +133 -0
  30. package/src/Analysis/Pipeline/PipelineBuilder.ts +55 -0
  31. package/src/Analysis/Pipeline/PipelineStage.ts +19 -0
  32. package/src/Analysis/Utils/color-utils.ts +132 -0
  33. package/src/Analysis/__tests__/Integration.test.ts +162 -0
  34. package/src/Analysis/__tests__/Pipeline.test.ts +133 -0
  35. package/src/Analysis/index.ts +52 -0
  36. package/src/BBCode/BBCodeDocumentModel.ts +175 -0
  37. package/src/BBCode/BBCodeToGreenNode.ts +755 -0
  38. package/src/BBCode/Parser.ts +384 -0
  39. package/src/BBCode/index.ts +12 -0
  40. package/src/Collab/positions.ts +91 -0
  41. package/src/Commands/Command.ts +44 -0
  42. package/src/Commands/CommandRegistry.ts +78 -0
  43. package/src/Commands/DeleteNode.ts +20 -0
  44. package/src/Commands/InsertText.ts +21 -0
  45. package/src/Commands/SplitMerge.ts +28 -0
  46. package/src/Commands/WrapInTag.ts +21 -0
  47. package/src/Commands/index.ts +6 -0
  48. package/src/Diff/TreeDiffer.ts +264 -0
  49. package/src/Diff/__tests__/TreeDiffer.test.ts +65 -0
  50. package/src/Diff/index.ts +2 -0
  51. package/src/Events/EventBus.ts +160 -0
  52. package/src/Events/index.ts +2 -0
  53. package/src/Formatter/Formatter.ts +54 -0
  54. package/src/Formatter/index.ts +2 -0
  55. package/src/HTML/HTMLDocumentModel.ts +35 -0
  56. package/src/HTML/HTMLToGreenNode.ts +290 -0
  57. package/src/Incremental/ChangeTracker.ts +105 -0
  58. package/src/Incremental/IncrementalParser.ts +591 -0
  59. package/src/Incremental/__tests__/IncrementalParser.test.ts +164 -0
  60. package/src/Incremental/index.ts +4 -0
  61. package/src/Lexer/BBCodeLexer.ts +382 -0
  62. package/src/Lexer/Lexer.ts +181 -0
  63. package/src/Lexer/index.ts +10 -0
  64. package/src/Linter/Linter.ts +193 -0
  65. package/src/Linter/index.ts +2 -0
  66. package/src/Markdown/MarkdownAST.ts +112 -0
  67. package/src/Markdown/MarkdownDocumentModel.ts +55 -0
  68. package/src/Markdown/MarkdownLexer.ts +203 -0
  69. package/src/Markdown/MarkdownParser.ts +455 -0
  70. package/src/Markdown/MarkdownToGreenNode.ts +153 -0
  71. package/src/Model/DocumentModel.ts +694 -0
  72. package/src/Model/NodeFactory.ts +117 -0
  73. package/src/Model/TagRegistry.ts +495 -0
  74. package/src/Model/index.ts +5 -0
  75. package/src/Plugins/PluginAPI.ts +119 -0
  76. package/src/Plugins/PluginRegistry.ts +132 -0
  77. package/src/Plugins/index.ts +3 -0
  78. package/src/Queries/QueryEngine.ts +152 -0
  79. package/src/Queries/index.ts +1 -0
  80. package/src/RenderPipeline/RenderPipeline.ts +125 -0
  81. package/src/RenderPipeline/RenderTree.ts +134 -0
  82. package/src/RenderPipeline/index.ts +4 -0
  83. package/src/Semantic/SemanticAnalyzer.ts +506 -0
  84. package/src/Semantic/index.ts +2 -0
  85. package/src/Symbols/SymbolTable.ts +124 -0
  86. package/src/Symbols/index.ts +1 -0
  87. package/src/Syntax/GreenNode.ts +324 -0
  88. package/src/Syntax/GreenNodePool.ts +269 -0
  89. package/src/Syntax/NodeMatcher.ts +370 -0
  90. package/src/Syntax/RedNode.ts +569 -0
  91. package/src/Syntax/RedNodeStore.ts +184 -0
  92. package/src/Syntax/TreeBuilder.ts +214 -0
  93. package/src/Syntax/__tests__/GreenNode.test.ts +33 -0
  94. package/src/Syntax/__tests__/RedNode.test.ts +81 -0
  95. package/src/Syntax/__tests__/RedNodeStore.test.ts +104 -0
  96. package/src/Syntax/greenEdit.ts +110 -0
  97. package/src/Syntax/hash.ts +30 -0
  98. package/src/Syntax/index.ts +12 -0
  99. package/src/Syntax/partition.ts +161 -0
  100. package/src/Syntax/preserveNodeIds.ts +201 -0
  101. package/src/Tests/ASTOptimizerIdempotence.test.ts +77 -0
  102. package/src/Tests/BlockPatcher.test.ts +437 -0
  103. package/src/Tests/BlockPatcherWindowed.test.ts +364 -0
  104. package/src/Tests/BoxDrawer.test.ts +217 -0
  105. package/src/Tests/BoxRichTitle.test.ts +105 -0
  106. package/src/Tests/Chars500kBenchmark.test.ts +151 -0
  107. package/src/Tests/Chars500kEdits.test.ts +321 -0
  108. package/src/Tests/CollabPositions.test.ts +146 -0
  109. package/src/Tests/CompilerPathProfiling.test.ts +186 -0
  110. package/src/Tests/DOMMorpher.test.ts +142 -0
  111. package/src/Tests/DomPatchPerf.test.ts +60 -0
  112. package/src/Tests/EffectSegments.snapshot.json +616 -0
  113. package/src/Tests/EffectSegments.test.ts +68 -0
  114. package/src/Tests/FindNodeAtOffset.test.ts +65 -0
  115. package/src/Tests/Fuzzer.test.ts +166 -0
  116. package/src/Tests/GreenNodePool.test.ts +153 -0
  117. package/src/Tests/Lexer.test.ts +238 -0
  118. package/src/Tests/LyneMode.test.ts +187 -0
  119. package/src/Tests/ModelCoherence.test.ts +180 -0
  120. package/src/Tests/Partition.test.ts +238 -0
  121. package/src/Tests/PluginTags.test.ts +150 -0
  122. package/src/Tests/ProblematicSection.test.ts +46 -0
  123. package/src/Tests/ProblematicSectionHTML.test.ts +58 -0
  124. package/src/Tests/RedReuse.test.ts +134 -0
  125. package/src/Tests/ReproDelete20k.test.ts +62 -0
  126. package/src/Tests/SemanticValidators.test.ts +136 -0
  127. package/src/Tests/StableNodeIds.test.ts +210 -0
  128. package/src/Tests/StudioColorBloat.test.ts +25 -0
  129. package/src/Tests/StudioDebugText.test.ts +27 -0
  130. package/src/Tests/StudioTrailingChar.test.ts +25 -0
  131. package/src/Tests/StudioValidText.test.ts +25 -0
  132. package/src/Tests/UrlImgBug.test.ts +23 -0
  133. package/src/Tests/VisualBuilderFidelity.test.ts +105 -0
  134. package/src/Tests/referenceDocument.ts +119 -0
  135. package/src/Transactions/Transaction.ts +176 -0
  136. package/src/Transactions/UndoManager.ts +111 -0
  137. package/src/Transactions/index.ts +3 -0
  138. package/src/Transformers/ASTOptimizer.ts +315 -0
  139. package/src/Transformers/GradientTransformer.ts +143 -0
  140. package/src/Transformers/GrowTransformer.ts +115 -0
  141. package/src/Transformers/RainbowTransformer.ts +121 -0
  142. package/src/Transformers/SineWaveTransformer.ts +130 -0
  143. package/src/Transformers/Transformer.ts +22 -0
  144. package/src/Types/core.ts +270 -0
  145. package/src/Types/diagnostics.ts +156 -0
  146. package/src/Types/index.ts +23 -0
  147. package/src/Types/operations.ts +180 -0
  148. package/src/Types/queries.ts +121 -0
  149. package/src/Types/symbols.ts +69 -0
  150. package/src/Types/tokens.ts +186 -0
  151. package/src/Utils/BBCodeGenerator.ts +126 -0
  152. package/src/Utils/ColorMath.ts +276 -0
  153. package/src/Utils/color.ts +112 -0
  154. package/src/Utils/dom-to-svg.test.ts +86 -0
  155. package/src/Utils/dom-to-svg.ts +615 -0
  156. package/src/Utils/treeTransformers.ts +717 -0
  157. package/src/Visitors/BBBlocksExporter.ts +69 -0
  158. package/src/Visitors/BBCodeExporter.ts +318 -0
  159. package/src/Visitors/BlockPatcher.ts +963 -0
  160. package/src/Visitors/DOMMorpher.ts +134 -0
  161. package/src/Visitors/HTMLRenderer.ts +1077 -0
  162. package/src/Visitors/JSONExporter.ts +66 -0
  163. package/src/Visitors/MarkdownExporter.ts +99 -0
  164. package/src/Visitors/SVGRenderer.ts +35 -0
  165. package/src/Visitors/TiptapExporter.ts +145 -0
  166. package/src/Visitors/Visitor.ts +48 -0
  167. package/src/Visitors/index.ts +9 -0
  168. package/src/Visuals/BoxDrawer.ts +175 -0
  169. package/src/Visuals/index.ts +42 -0
  170. package/src/Visuals/lyne.css +1027 -0
  171. package/src/Visuals/osu.css +257 -0
  172. package/src/index.ts +197 -0
@@ -0,0 +1,1027 @@
1
+ /**
2
+ * DocumentEngine — Visuals / lyne.css
3
+ *
4
+ * Lyne-inspired BBCode preview theme.
5
+ * Reusable visual platform style for the Lyne cyberpunk rhythm game aesthetic.
6
+ *
7
+ * Scoped under `.bbcode-preview-lyne` and `.theme-lyne`.
8
+ * All rules strictly override default/osu.css styles to ensure 0% pink bleed.
9
+ */
10
+
11
+ @import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=Saira+Condensed:wght@600;700&family=Saira:wght@400;600&display=swap');
12
+
13
+ :root {
14
+ --color-accent: #2EE6E2;
15
+ --color-accent-bright: #68FFF8;
16
+ --color-warning: #FFC34D;
17
+ --color-text-primary: #FFFFFF;
18
+ --color-text-mid: #9EACD4;
19
+ --color-text-dim: #606C8F;
20
+ --color-hairline: rgba(255, 255, 255, 0.12);
21
+ --font-display: "Saira Condensed", sans-serif;
22
+ --font-body: "Saira", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
23
+ --font-numeric: "IBM Plex Mono", monospace;
24
+ --lyne-cut: 8px;
25
+ }
26
+
27
+ .bbcode-preview-lyne,
28
+ .bbcode-preview.theme-lyne {
29
+ font-family: var(--font-body) !important;
30
+ font-size: 0.875rem !important;
31
+ /* 1.5 igual que osu.css: 1.6 estiraba las líneas y exageraba los huecos
32
+ * verticales (los <br> del renderer miden un line-height cada uno). */
33
+ line-height: 1.5 !important;
34
+ color: var(--color-text-mid, #9EACD4) !important;
35
+ word-break: break-word;
36
+ overflow-wrap: anywhere;
37
+ }
38
+
39
+ /* ─── Links ─────────────────────────────────────────────────────────────── */
40
+
41
+ .bbcode-preview-lyne a,
42
+ .bbcode-preview.theme-lyne a {
43
+ color: var(--color-accent, #2EE6E2) !important;
44
+ text-decoration: none !important;
45
+ border-bottom: 1px dashed rgba(46, 230, 226, 0.35) !important;
46
+ transition: color 0.15s ease, border-color 0.15s ease;
47
+ }
48
+
49
+ .bbcode-preview-lyne a:hover,
50
+ .bbcode-preview.theme-lyne a:hover {
51
+ color: var(--color-accent-bright, #68FFF8) !important;
52
+ border-bottom-color: var(--color-accent, #2EE6E2) !important;
53
+ }
54
+
55
+ /* ─── 45° Cut Panels ────────────────────────────────────────────────────── */
56
+
57
+ .bb-cut-panel {
58
+ border-radius: 0 !important;
59
+ outline: none !important;
60
+ clip-path: polygon(
61
+ var(--lyne-cut, 8px) 0,
62
+ 100% 0,
63
+ 100% calc(100% - var(--lyne-cut, 8px)),
64
+ calc(100% - var(--lyne-cut, 8px)) 100%,
65
+ 0 100%,
66
+ 0 var(--lyne-cut, 8px)
67
+ ) !important;
68
+ }
69
+
70
+ .bb-cut-panel:focus-visible {
71
+ outline: none !important;
72
+ filter: drop-shadow(0 0 3px var(--color-accent, #2EE6E2)) !important;
73
+ }
74
+
75
+ /* ─── Headings ──────────────────────────────────────────────────────────── */
76
+
77
+ .bbcode-preview-lyne h2,
78
+ .bbcode-preview.theme-lyne h2 {
79
+ font-family: var(--font-display, "Saira Condensed", sans-serif) !important;
80
+ font-weight: 700 !important;
81
+ font-size: 1.35rem !important;
82
+ letter-spacing: 1px !important;
83
+ color: var(--color-text-primary, #FFFFFF) !important;
84
+ margin: 0 !important;
85
+ padding: 0 !important;
86
+ text-transform: uppercase !important;
87
+ line-height: 1.1 !important;
88
+ }
89
+
90
+ /* ─── Notice & Warning Notice ───────────────────────────────────────────── */
91
+
92
+ .bbcode-preview-lyne .notice,
93
+ .bbcode-preview.theme-lyne .notice,
94
+ .bb-notice {
95
+ display: block !important;
96
+ background: rgba(255, 195, 77, 0.08) !important;
97
+ border: 1px solid rgba(255, 195, 77, 0.4) !important;
98
+ border-radius: 0 !important;
99
+ padding: 13px 16px !important;
100
+ margin: 0 !important;
101
+ font-size: 0.8125rem !important;
102
+ line-height: 1.55 !important;
103
+ color: rgb(255, 224, 163) !important;
104
+ white-space: normal !important;
105
+ clip-path: polygon(8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%, 0 8px) !important;
106
+ width: 100% !important;
107
+ box-sizing: border-box !important;
108
+ }
109
+
110
+ /* Especificidad 0,2,0 (igual a `.bbcode-preview-lyne .notice`) para que el
111
+ `display:flex` gane sobre el `display:block` de la regla base del notice;
112
+ con un selector de clase simple (0,1,0) el símbolo quedaba ARRIBA del texto. */
113
+ .bbcode-preview-lyne .bb-wnotice,
114
+ .bbcode-preview.theme-lyne .bb-wnotice,
115
+ .bb-notice.bb-wnotice {
116
+ display: flex !important;
117
+ gap: 12px !important;
118
+ align-items: flex-start !important;
119
+ border-color: rgba(255, 195, 77, 0.6) !important;
120
+ background: rgba(255, 195, 77, 0.12) !important;
121
+ }
122
+
123
+ .bb-notice-mark {
124
+ color: var(--color-warning, #FFC34D) !important;
125
+ font-size: 0.9375rem !important;
126
+ flex: 0 0 auto !important;
127
+ margin-top: 1px !important;
128
+ }
129
+
130
+ .bb-notice-body {
131
+ min-width: 0 !important;
132
+ flex: 1 1 100% !important;
133
+ width: 100% !important;
134
+ display: block !important;
135
+ }
136
+
137
+ /* ─── Quotes ────────────────────────────────────────────────────────────── */
138
+
139
+ .bbcode-preview-lyne blockquote,
140
+ .bbcode-preview.theme-lyne blockquote {
141
+ margin: 0 !important;
142
+ padding: 10px 16px !important;
143
+ border: 1px solid rgba(46, 230, 226, 0.3) !important;
144
+ border-left: 1px solid rgba(46, 230, 226, 0.3) !important;
145
+ background: rgba(46, 230, 226, 0.06) !important;
146
+ color: var(--color-text-mid, #9EACD4) !important;
147
+ white-space: normal !important;
148
+ border-radius: 0 !important;
149
+ clip-path: polygon(8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%, 0 8px) !important;
150
+ }
151
+
152
+ .bbcode-preview-lyne blockquote div strong,
153
+ .bbcode-preview.theme-lyne blockquote div strong {
154
+ display: block;
155
+ font-family: var(--font-numeric, "IBM Plex Mono", monospace) !important;
156
+ font-size: 0.6875rem !important;
157
+ letter-spacing: 1px !important;
158
+ text-transform: uppercase !important;
159
+ color: var(--color-accent, #2EE6E2) !important;
160
+ margin-bottom: 6px !important;
161
+ font-style: normal !important;
162
+ }
163
+
164
+ /* ─── Code ──────────────────────────────────────────────────────────────── */
165
+
166
+ .bbcode-preview-lyne pre,
167
+ .bbcode-preview.theme-lyne pre {
168
+ margin: 0 !important;
169
+ padding: 12px 14px !important;
170
+ background: rgba(5, 6, 15, 0.85) !important;
171
+ border: 1px solid var(--color-hairline, rgba(255, 255, 255, 0.12)) !important;
172
+ font-family: var(--font-numeric, "IBM Plex Mono", monospace) !important;
173
+ font-size: 0.8125rem !important;
174
+ color: var(--color-text-primary, #FFFFFF) !important;
175
+ white-space: pre-wrap !important;
176
+ overflow-wrap: anywhere !important;
177
+ border-radius: 0 !important;
178
+ clip-path: polygon(8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%, 0 8px) !important;
179
+ }
180
+
181
+ .bbcode-preview-lyne pre code,
182
+ .bbcode-preview.theme-lyne pre code {
183
+ color: var(--color-text-primary, #FFFFFF) !important;
184
+ font-family: inherit !important;
185
+ background: transparent !important;
186
+ padding: 0 !important;
187
+ }
188
+
189
+ .bbcode-preview-lyne code.inline,
190
+ .bbcode-preview.theme-lyne code.inline {
191
+ font-family: var(--font-numeric, "IBM Plex Mono", monospace) !important;
192
+ font-size: 0.8125em !important;
193
+ padding: 1px 5px !important;
194
+ background: rgba(5, 6, 15, 0.85) !important;
195
+ border: 1px solid var(--color-hairline, rgba(255, 255, 255, 0.12)) !important;
196
+ border-radius: 0 !important;
197
+ clip-path: polygon(3px 0, 100% 0, 100% calc(100% - 3px), calc(100% - 3px) 100%, 0 100%, 0 3px) !important;
198
+ color: var(--color-text-primary, #FFFFFF) !important;
199
+ }
200
+
201
+ /* ─── Boxes & Disclosures (with rotating chevron) ─────────────────────────── */
202
+
203
+ /* [box]/[spoilerbox] normales: limpios por defecto — sin fondo, sin líneas,
204
+ * sin recorte de esquinas. El look de caja (fondo + líneas + cut-corner)
205
+ * solo lo lleva [boxw] (ver `details.boxw` abajo). */
206
+ .bbcode-preview-lyne details,
207
+ .bbcode-preview.theme-lyne details {
208
+ margin: 0 !important;
209
+ background: none !important;
210
+ border: none !important;
211
+ border-radius: 0 !important;
212
+ padding: 0 !important;
213
+ display: block !important;
214
+ width: 100% !important;
215
+ box-sizing: border-box !important;
216
+ }
217
+
218
+ /* [boxw]: el box con líneas y fondo (estilo Lyne). El borde sigue el acento
219
+ * del autor ([boxw=Title:#hex]) si lo hay; si no, el hairline del tema. */
220
+ .bbcode-preview-lyne details.boxw,
221
+ .bbcode-preview.theme-lyne details.boxw {
222
+ background: rgba(11, 16, 36, 0.5) !important;
223
+ border: 1px solid var(--box-accent, var(--card-accent, var(--glass-accent, var(--color-hairline, rgba(255, 255, 255, 0.12))))) !important;
224
+ border-radius: 0 !important;
225
+ clip-path: polygon(8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%, 0 8px) !important;
226
+ padding: 0 !important;
227
+ display: block !important;
228
+ width: 100% !important;
229
+ box-sizing: border-box !important;
230
+ }
231
+
232
+ .bbcode-preview-lyne details > summary::-webkit-details-marker,
233
+ .bbcode-preview.theme-lyne details > summary::-webkit-details-marker {
234
+ display: none !important;
235
+ }
236
+
237
+ .bbcode-preview-lyne details summary,
238
+ .bbcode-preview.theme-lyne details summary,
239
+ .bbcode-preview-lyne details > summary,
240
+ .bbcode-preview.theme-lyne details > summary {
241
+ cursor: pointer !important;
242
+ padding: 9px 14px !important;
243
+ display: flex !important;
244
+ align-items: center !important;
245
+ gap: 9px !important;
246
+ list-style: none !important;
247
+ font-family: var(--font-numeric, "IBM Plex Mono", monospace) !important;
248
+ font-size: 0.6875rem !important;
249
+ letter-spacing: 1px !important;
250
+ /* --box-accent: color del autor via [box=Title:#hex]; si no, el acento de
251
+ * la card/glass que lo contiene (--card-accent/--glass-accent se heredan);
252
+ * si no, el acento del tema */
253
+ color: var(--box-accent, var(--card-accent, var(--glass-accent, var(--color-accent, #2EE6E2)))) !important;
254
+ user-select: none !important;
255
+ transition: color 0.15s ease !important;
256
+ text-align: inherit;
257
+ width: 100% !important;
258
+ box-sizing: border-box !important;
259
+ }
260
+
261
+ .bbcode-preview-lyne details > summary > div,
262
+ .bbcode-preview.theme-lyne details > summary > div {
263
+ flex: 1;
264
+ }
265
+
266
+ /* Centered box titles (direct or nested inside any [centre] or centered ancestor) */
267
+ .bbcode-preview-lyne [style*="text-align:center"] details summary,
268
+ .bbcode-preview.theme-lyne [style*="text-align:center"] details summary,
269
+ .bbcode-preview-lyne [style*="text-align: center"] details summary,
270
+ .bbcode-preview.theme-lyne [style*="text-align: center"] details summary,
271
+ .bbcode-preview-lyne [align="center"] details summary,
272
+ .bbcode-preview.theme-lyne [align="center"] details summary,
273
+ .bbcode-preview-lyne .center details summary,
274
+ .bbcode-preview.theme-lyne .center details summary,
275
+ .bbcode-preview-lyne details[style*="text-align:center"] summary,
276
+ .bbcode-preview.theme-lyne details[style*="text-align:center"] summary,
277
+ .bbcode-preview-lyne details[style*="text-align: center"] summary,
278
+ .bbcode-preview.theme-lyne details[style*="text-align: center"] summary,
279
+ .bbcode-preview-lyne details > summary:has([style*="text-align:center"]),
280
+ .bbcode-preview-lyne details > summary:has([style*="text-align: center"]),
281
+ .bbcode-preview-lyne details > summary:has(.center) {
282
+ justify-content: center !important;
283
+ text-align: center !important;
284
+ }
285
+
286
+ /* Right-aligned box titles */
287
+ .bbcode-preview-lyne [style*="text-align:right"] details summary,
288
+ .bbcode-preview.theme-lyne [style*="text-align:right"] details summary,
289
+ .bbcode-preview-lyne [style*="text-align: right"] details summary,
290
+ .bbcode-preview.theme-lyne [style*="text-align: right"] details summary,
291
+ .bbcode-preview-lyne details[style*="text-align:right"] summary,
292
+ .bbcode-preview.theme-lyne details[style*="text-align:right"] summary,
293
+ .bbcode-preview-lyne details > summary:has([style*="text-align:right"]) {
294
+ justify-content: flex-end !important;
295
+ text-align: right !important;
296
+ }
297
+
298
+ .bbcode-preview-lyne details > summary::before,
299
+ .bbcode-preview.theme-lyne details > summary::before {
300
+ content: "" !important;
301
+ width: 7px !important;
302
+ height: 7px !important;
303
+ flex: 0 0 7px !important;
304
+ border-right: 1.5px solid currentColor !important;
305
+ border-bottom: 1.5px solid currentColor !important;
306
+ transform: rotate(-45deg) !important;
307
+ transition: transform 0.15s ease !important;
308
+ }
309
+
310
+ .bbcode-preview-lyne details:not([open]),
311
+ .bbcode-preview.theme-lyne details:not([open]) {
312
+ font-size: 0 !important;
313
+ line-height: 0 !important;
314
+ padding: 0 !important;
315
+ }
316
+
317
+ .bbcode-preview-lyne details:not([open]) > summary,
318
+ .bbcode-preview.theme-lyne details:not([open]) > summary {
319
+ font-size: 0.6875rem !important;
320
+ line-height: 1.5 !important;
321
+ }
322
+
323
+ .bbcode-preview-lyne .bb-box-body,
324
+ .bbcode-preview.theme-lyne .bb-box-body {
325
+ padding: 4px 14px 12px !important;
326
+ font-size: 0.875rem !important;
327
+ line-height: 1.5 !important;
328
+ white-space: normal !important;
329
+ }
330
+
331
+ .bbcode-preview-lyne details.boxw[open] > summary,
332
+ .bbcode-preview.theme-lyne details.boxw[open] > summary {
333
+ border-bottom: 1px solid var(--box-accent, var(--card-accent, var(--glass-accent, var(--color-hairline, rgba(255, 255, 255, 0.12))))) !important;
334
+ }
335
+
336
+ .bbcode-preview-lyne details[open] > summary::before,
337
+ .bbcode-preview.theme-lyne details[open] > summary::before {
338
+ transform: rotate(45deg) !important;
339
+ }
340
+
341
+ .bbcode-preview-lyne details > summary:hover,
342
+ .bbcode-preview.theme-lyne details > summary:hover {
343
+ color: var(--color-accent-bright, #68FFF8) !important;
344
+ }
345
+
346
+ /* ─── Lists & Markers ───────────────────────────────────────────────────── */
347
+
348
+ .bbcode-preview-lyne ul,
349
+ .bbcode-preview.theme-lyne ul {
350
+ margin: 0 !important;
351
+ padding-left: 20px !important;
352
+ list-style: disc outside !important;
353
+ }
354
+
355
+ .bbcode-preview-lyne ol,
356
+ .bbcode-preview.theme-lyne ol {
357
+ margin: 0 !important;
358
+ padding-left: 20px !important;
359
+ list-style: decimal outside !important;
360
+ }
361
+
362
+ .bbcode-preview-lyne li,
363
+ .bbcode-preview.theme-lyne li {
364
+ margin: 0 !important;
365
+ line-height: 1.5 !important;
366
+ display: list-item !important;
367
+ }
368
+
369
+ .bbcode-preview-lyne li::marker,
370
+ .bbcode-preview.theme-lyne li::marker {
371
+ color: var(--color-accent, #2EE6E2) !important;
372
+ }
373
+
374
+ /* ─── Spoilers ──────────────────────────────────────────────────────────── */
375
+
376
+ .bbcode-preview-lyne .spoiler,
377
+ .bbcode-preview.theme-lyne .spoiler {
378
+ background: rgba(142, 155, 196, 0.3) !important;
379
+ color: transparent !important;
380
+ cursor: pointer !important;
381
+ padding: 1px 4px !important;
382
+ border-radius: 0 !important;
383
+ clip-path: polygon(3px 0, 100% 0, 100% calc(100% - 3px), calc(100% - 3px) 100%, 0 100%, 0 3px) !important;
384
+ user-select: none !important;
385
+ transition: all 0.2s ease !important;
386
+ }
387
+
388
+ .bbcode-preview-lyne .spoiler:hover,
389
+ .bbcode-preview.theme-lyne .spoiler:hover {
390
+ color: #FFFFFF !important;
391
+ background: rgba(142, 155, 196, 0.15) !important;
392
+ }
393
+
394
+ /* ─── Media ─────────────────────────────────────────────────────────────── */
395
+
396
+ .bbcode-preview-lyne img,
397
+ .bbcode-preview.theme-lyne img {
398
+ /* Igual que osu.css: NO se declara display. El renderer ya emite
399
+ * `display:inline-block` inline para [img] sin modificadores, y eso es lo
400
+ * que centra la imagen bajo [center]/[centre] (text-align:center). Si el
401
+ * CSS forzara display (p. ej. block por el preflight de Tailwind) rompería
402
+ * ese centrado — por eso aquí no se toca, como en osu.css. */
403
+ border-radius: 0 !important;
404
+ max-width: 100% !important;
405
+ height: auto !important;
406
+ }
407
+
408
+ .bbcode-preview-lyne iframe,
409
+ .bbcode-preview.theme-lyne iframe {
410
+ /* inline-block (no block): el preflight de Tailwind fuerza `iframe{display:block}`
411
+ * y eso rompe el centrado por `text-align:center` de [centre]. Igual que las
412
+ * imágenes: inline-level para que text-align lo centre. */
413
+ display: inline-block !important;
414
+ border-radius: 0 !important;
415
+ border: 1px solid var(--color-hairline, rgba(255, 255, 255, 0.12)) !important;
416
+ clip-path: polygon(8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%, 0 8px) !important;
417
+ }
418
+
419
+ /* ─── Tables ────────────────────────────────────────────────────────────── */
420
+
421
+ .bb-table-frame {
422
+ position: relative !important;
423
+ width: 100% !important;
424
+ max-width: 100% !important;
425
+ margin: 0 !important;
426
+ overflow-x: auto !important;
427
+ border: 1px solid var(--color-hairline, rgba(255, 255, 255, 0.12)) !important;
428
+ background:
429
+ linear-gradient(125deg, color-mix(in srgb, var(--table-accent, var(--color-accent, #2EE6E2)) 7%, transparent), transparent 34%),
430
+ repeating-linear-gradient(-45deg, transparent 0 10px, rgba(142, 155, 196, 0.018) 10px 12px),
431
+ rgba(7, 10, 23, 0.82) !important;
432
+ box-shadow:
433
+ inset 0 1px rgba(127, 245, 240, 0.08),
434
+ inset 0 -1px rgba(142, 155, 196, 0.08) !important;
435
+ clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 12px 100%, 0 calc(100% - 12px)) !important;
436
+ scrollbar-width: thin;
437
+ }
438
+
439
+ .bb-table {
440
+ width: 100% !important;
441
+ min-width: 380px !important;
442
+ border-collapse: separate !important;
443
+ border-spacing: 0 !important;
444
+ margin: 0 !important;
445
+ font-size: 0.8125rem !important;
446
+ white-space: normal !important;
447
+ }
448
+
449
+ .bb-table td,
450
+ .bb-table .bb-th {
451
+ min-width: 0 !important;
452
+ padding: 11px 14px !important;
453
+ border-bottom: 1px solid var(--color-hairline, rgba(255, 255, 255, 0.12)) !important;
454
+ border-right: 1px solid rgba(142, 155, 196, 0.08) !important;
455
+ color: var(--color-text-mid, #9EACD4) !important;
456
+ text-align: left !important;
457
+ vertical-align: middle !important;
458
+ overflow-wrap: anywhere !important;
459
+ transition: background 0.15s ease, color 0.15s ease !important;
460
+ }
461
+
462
+ .bb-table tr > :last-child {
463
+ border-right: 0 !important;
464
+ }
465
+
466
+ .bb-table tr:last-child > * {
467
+ border-bottom: 0 !important;
468
+ }
469
+
470
+ .bb-table tr:hover td {
471
+ color: var(--color-text-primary, #FFFFFF) !important;
472
+ background: color-mix(in srgb, var(--table-accent, var(--color-accent, #2EE6E2)) 4.5%, transparent) !important;
473
+ }
474
+
475
+ .bb-table tr:hover td:first-child {
476
+ box-shadow: inset 2px 0 var(--table-accent, var(--color-accent, #2EE6E2)) !important;
477
+ }
478
+
479
+ .bb-table .bb-th {
480
+ position: relative !important;
481
+ background: linear-gradient(90deg, color-mix(in srgb, var(--table-accent, var(--color-accent, #2EE6E2)) 10%, transparent), rgba(142, 155, 196, 0.035)) !important;
482
+ border-bottom: 1px solid color-mix(in srgb, var(--table-accent, var(--color-accent, #2EE6E2)) 28%, transparent) !important;
483
+ color: var(--color-text-primary, #FFFFFF) !important;
484
+ font-family: var(--font-numeric, "IBM Plex Mono", monospace) !important;
485
+ font-size: 0.625rem !important;
486
+ font-weight: 600 !important;
487
+ letter-spacing: 1.8px !important;
488
+ line-height: 1.3 !important;
489
+ text-transform: uppercase !important;
490
+ padding: 8px 10px !important;
491
+ }
492
+
493
+ .bb-table-badge {
494
+ display: inline-flex !important;
495
+ align-items: center !important;
496
+ max-width: 100% !important;
497
+ min-height: 22px !important;
498
+ padding: 4px 13px 4px 10px !important;
499
+ overflow: hidden !important;
500
+ /* Los títulos ([th]) siguen el acento de la tabla ([tables=:#hex]) */
501
+ color: var(--table-accent, var(--color-accent-bright, #68FFF8)) !important;
502
+ background: color-mix(in srgb, var(--table-accent, var(--color-accent, #2EE6E2)) 9%, transparent) !important;
503
+ border-left: 2px solid var(--table-accent, var(--color-accent, #2EE6E2)) !important;
504
+ clip-path: polygon(0 0, 100% 0, calc(100% - 7px) 100%, 0 100%) !important;
505
+ text-overflow: ellipsis !important;
506
+ white-space: nowrap !important;
507
+ }
508
+
509
+ .bb-table-striped tr:nth-child(even) td {
510
+ background: rgba(142, 155, 196, 0.04) !important;
511
+ }
512
+
513
+ .bb-table-borders td,
514
+ .bb-table-borders .bb-th {
515
+ border-right: 1px solid var(--color-hairline, rgba(255, 255, 255, 0.12)) !important;
516
+ border-bottom: 1px solid rgba(255, 255, 255, 0.18) !important;
517
+ }
518
+
519
+ /* ─── Gallery & Columns ─────────────────────────────────────────────────── */
520
+
521
+ .bb-gallery {
522
+ display: flex !important;
523
+ flex-wrap: wrap !important;
524
+ gap: 8px !important;
525
+ margin: 0 !important;
526
+ }
527
+
528
+ .bb-gallery img {
529
+ max-height: 180px !important;
530
+ object-fit: cover !important;
531
+ border: 1px solid var(--color-hairline, rgba(255, 255, 255, 0.12)) !important;
532
+ clip-path: polygon(4px 0, 100% 0, 100% calc(100% - 4px), calc(100% - 4px) 100%, 0 100%, 0 4px) !important;
533
+ }
534
+
535
+ .bb-columns {
536
+ display: grid !important;
537
+ grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
538
+ gap: 16px !important;
539
+ margin: 0 !important;
540
+ white-space: normal !important;
541
+ align-items: start !important;
542
+ }
543
+
544
+ .bb-columns[style*="column-count: 2"],
545
+ .bb-columns[style*="column-count:2"] {
546
+ grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
547
+ }
548
+
549
+ .bb-columns[style*="column-count: 3"],
550
+ .bb-columns[style*="column-count:3"] {
551
+ grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
552
+ }
553
+
554
+ .bb-columns[style*="column-count: 4"],
555
+ .bb-columns[style*="column-count:4"] {
556
+ grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
557
+ }
558
+
559
+ .bb-columns > * {
560
+ min-width: 0 !important;
561
+ width: 100% !important;
562
+ margin-top: 0 !important;
563
+ box-sizing: border-box !important;
564
+ }
565
+
566
+ /* [columns=2:#hex]: superficie opcional derivada del acento — solo aparece
567
+ * cuando el autor puso color; sin color, .bb-columns queda grid limpio. */
568
+ .bb-columns-surface {
569
+ border: 1px solid color-mix(in srgb, var(--columns-accent, var(--color-accent, #2EE6E2)) 45%, transparent) !important;
570
+ background:
571
+ linear-gradient(125deg, color-mix(in srgb, var(--columns-accent, var(--color-accent, #2EE6E2)) 6%, transparent), transparent 45%) !important;
572
+ border-radius: 0 !important;
573
+ clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 10px 100%, 0 calc(100% - 10px)) !important;
574
+ padding: 12px !important;
575
+ }
576
+
577
+ /* ─── Separators ────────────────────────────────────────────────────────── */
578
+
579
+ .bb-separator {
580
+ border: 0 !important;
581
+ height: 1px !important;
582
+ background: linear-gradient(90deg, transparent, var(--color-accent, #2EE6E2), transparent) !important;
583
+ margin: 0 !important;
584
+ text-align: center !important;
585
+ color: var(--color-accent, #2EE6E2) !important;
586
+ font-family: var(--font-numeric, monospace) !important;
587
+ letter-spacing: 2px !important;
588
+ }
589
+
590
+ /* ─── Scroll Container ──────────────────────────────────────────────────── */
591
+
592
+ .bb-scroll {
593
+ overflow-y: auto !important;
594
+ overscroll-behavior: auto !important;
595
+ margin: 0 !important;
596
+ padding: 8px 12px !important;
597
+ background: rgba(5, 6, 15, 0.5) !important;
598
+ border: 1px solid var(--color-hairline, rgba(255, 255, 255, 0.12)) !important;
599
+ border-radius: 0 !important;
600
+ clip-path: polygon(8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%, 0 8px) !important;
601
+ scrollbar-width: thin;
602
+ }
603
+
604
+ /* ─── Inline Typography & Badges ────────────────────────────────────────── */
605
+
606
+ .bb-mark {
607
+ background: rgba(255, 220, 77, 0.3) !important;
608
+ color: inherit !important;
609
+ padding: 1px 4px !important;
610
+ border-radius: 0 !important;
611
+ clip-path: polygon(3px 0, 100% 0, 100% calc(100% - 3px), calc(100% - 3px) 100%, 0 100%, 0 3px) !important;
612
+ }
613
+
614
+ .bb-kbd {
615
+ font-family: var(--font-numeric, "IBM Plex Mono", monospace) !important;
616
+ font-size: 0.85em !important;
617
+ padding: 2px 6px !important;
618
+ background: rgba(255, 255, 255, 0.08) !important;
619
+ border: 1px solid var(--color-hairline, rgba(255, 255, 255, 0.12)) !important;
620
+ border-bottom-width: 2px !important;
621
+ border-radius: 0 !important;
622
+ clip-path: polygon(3px 0, 100% 0, 100% calc(100% - 3px), calc(100% - 3px) 100%, 0 100%, 0 3px) !important;
623
+ color: var(--color-text-primary, #FFFFFF) !important;
624
+ }
625
+
626
+ .bb-tooltip {
627
+ border-bottom: 1px dotted var(--color-text-dim, #606C8F) !important;
628
+ cursor: help !important;
629
+ }
630
+
631
+ .bb-raw {
632
+ font-family: var(--font-numeric, "IBM Plex Mono", monospace) !important;
633
+ font-size: 0.85em !important;
634
+ color: var(--color-text-mid, #9EACD4) !important;
635
+ }
636
+
637
+ /* ─── Containers (card, glass, neon-box, flex, grid, middle, circle) ────── */
638
+
639
+ /* card/glass aceptan color `[card=#hex]` / `[container=glass:#hex]`: el borde
640
+ * y el tinte de fondo derivan de `--card-accent` / `--glass-accent`. Sin
641
+ * color, los fallbacks reproducen exactamente los valores por defecto. */
642
+ .bb-card {
643
+ padding: 14px 18px !important;
644
+ background: color-mix(in srgb, var(--card-accent, rgb(14 16 28 / 0.85)) 6%, rgb(14 16 28 / 0.85)) !important;
645
+ border: 1px solid var(--card-accent, var(--color-hairline, rgba(255, 255, 255, 0.12))) !important;
646
+ margin: 0 !important;
647
+ contain: layout style;
648
+ }
649
+
650
+ .bb-glass {
651
+ padding: 14px 18px !important;
652
+ /* Glass sin backdrop-filter: el blur re-rasteriza todo lo que hay detrás en
653
+ cada scroll (costo dominante con varios glass en el documento) y sabotea
654
+ el `contain` de abajo. Sobre fondos oscuros el blur era casi invisible
655
+ (el tint ya es 4% blanco), así que se sustituye por un fondo ligeramente
656
+ más opaco que conserva el look de vidrio. */
657
+ background: color-mix(in srgb, var(--glass-accent, #ffffff) 7%, transparent) !important;
658
+ border: 1px solid color-mix(in srgb, var(--glass-accent, #ffffff) 10%, transparent) !important;
659
+ margin: 0 !important;
660
+ contain: layout style;
661
+ }
662
+
663
+ /* ─── Propagación del acento al contenido sin color propio ────────────────
664
+ * Cuando la card/glass recibió color (clase `bb-accented`, emitida por el
665
+ * renderer), el contenido que NO tiene [color=...] hereda una paleta derivada
666
+ * del acento: texto en un tint claro (legible sobre el fondo oscuro), negritas
667
+ * más brillantes, links en el acento puro, y quotes/separadores en el mismo
668
+ * tono. Todo se resuelve por luminancia con `color-mix`, así que un acento
669
+ * oscuro produce tints claros y uno claro, pasteles. Los [color=...] inline
670
+ * ganan por especificidad (style > clase). La cadena `var(--card-accent,
671
+ * var(--glass-accent, …))` permite que una regla sirva para ambas clases. */
672
+ .bb-card.bb-accented,
673
+ .bb-glass.bb-accented {
674
+ color: color-mix(in srgb, var(--card-accent, var(--glass-accent, #ffffff)) 62%, #ffffff) !important;
675
+ }
676
+
677
+ .bb-card.bb-accented strong,
678
+ .bb-card.bb-accented b,
679
+ .bb-glass.bb-accented strong,
680
+ .bb-glass.bb-accented b {
681
+ color: color-mix(in srgb, var(--card-accent, var(--glass-accent, #ffffff)) 82%, #ffffff) !important;
682
+ }
683
+
684
+ .bb-card.bb-accented a,
685
+ .bb-glass.bb-accented a {
686
+ color: var(--card-accent, var(--glass-accent, #2EE6E2)) !important;
687
+ text-decoration-color: color-mix(in srgb, var(--card-accent, var(--glass-accent, #2EE6E2)) 45%, transparent) !important;
688
+ }
689
+
690
+ .bb-card.bb-accented blockquote,
691
+ .bb-glass.bb-accented blockquote {
692
+ border-color: color-mix(in srgb, var(--card-accent, var(--glass-accent, #2EE6E2)) 30%, transparent) !important;
693
+ background: color-mix(in srgb, var(--card-accent, var(--glass-accent, #2EE6E2)) 6%, transparent) !important;
694
+ color: color-mix(in srgb, var(--card-accent, var(--glass-accent, #2EE6E2)) 55%, #9EACD4) !important;
695
+ }
696
+
697
+ .bb-card.bb-accented .bb-separator,
698
+ .bb-glass.bb-accented .bb-separator {
699
+ background: linear-gradient(90deg, transparent, var(--card-accent, var(--glass-accent, #2EE6E2)), transparent) !important;
700
+ color: var(--card-accent, var(--glass-accent, #2EE6E2)) !important;
701
+ }
702
+
703
+ .bb-neon-box {
704
+ padding: 16px !important;
705
+ margin: 0 !important;
706
+ border: 2px solid var(--neon-color, var(--color-accent, #2EE6E2)) !important;
707
+ background: color-mix(in srgb, var(--neon-color, var(--color-accent, #2EE6E2)) 4%, rgba(7, 10, 23, 0.55)) !important;
708
+ border-radius: 0 !important;
709
+ box-shadow: none !important;
710
+ contain: layout style;
711
+ }
712
+
713
+ .bb-flex {
714
+ display: flex !important;
715
+ flex-wrap: wrap !important;
716
+ align-items: center !important;
717
+ }
718
+
719
+ .bb-grid {
720
+ display: grid !important;
721
+ gap: 8px !important;
722
+ margin: 0 !important;
723
+ }
724
+
725
+ .bb-middle {
726
+ display: flex !important;
727
+ justify-content: center !important;
728
+ align-items: center !important;
729
+ }
730
+
731
+ /* Circle: replica el .bbCircle original de Lyne (Main Bridge/line/web/
732
+ * components/bbcode.module.css). aspect-ratio:1 + centrado convierten el div
733
+ * en un círculo real con el contenido al centro; fondo y borde lo pintan como
734
+ * badge. clip-path:none evita que herede los cortes de esquina de los paneles. */
735
+ .bb-circle {
736
+ display: inline-flex !important;
737
+ align-items: center !important;
738
+ justify-content: center !important;
739
+ aspect-ratio: 1 !important;
740
+ border-radius: 50% !important;
741
+ overflow: hidden !important;
742
+ background: rgb(11 16 36 / 0.5) !important;
743
+ border: 1px solid var(--color-hairline, rgba(255, 255, 255, 0.12)) !important;
744
+ clip-path: none !important;
745
+ }
746
+
747
+ /* Stack: replica el .bbStack original de Lyne (columna flex con gap).
748
+ * El container por defecto ([stack] / [container=stack] / default) emite
749
+ * `<div class="bb-stack">` y sin estas reglas se veía como un div vacío. */
750
+ .bb-stack {
751
+ display: flex !important;
752
+ flex-direction: column !important;
753
+ gap: 8px !important;
754
+ margin: 8px 0 !important;
755
+ }
756
+
757
+ /* Imagen inline: conserva las dimensiones máx y el margen, pero SIN borde,
758
+ * sombra ni redondeo — la imagen queda limpia por defecto. Los modificadores
759
+ * explícitos ([img round], [img shadow], [img float], [img=WxH]) siguen
760
+ * emitiendo su estilo inline desde el renderer. */
761
+ .bb-img {
762
+ max-width: 100% !important;
763
+ max-height: 420px !important;
764
+ height: auto !important;
765
+ vertical-align: middle !important;
766
+ margin: 4px 0 !important;
767
+ }
768
+
769
+ /* Audio: replica el .bbAudio original de Lyne (bloque centrado, ancho máx). */
770
+ .bb-audio {
771
+ display: block !important;
772
+ width: 100% !important;
773
+ max-width: 420px !important;
774
+ margin: 10px 0 !important;
775
+ }
776
+
777
+ /* ─── Imagemap (replica .bbImageMap de Lyne) ──────────────────────────── */
778
+
779
+ .bbcode-preview-lyne .imagemap-container,
780
+ .bbcode-preview.theme-lyne .imagemap-container,
781
+ .bbcode-preview-lyne .bbcode-imagemap,
782
+ .bbcode-preview.theme-lyne .bbcode-imagemap {
783
+ /* inline-block igual que osu.css: el renderer emite `display:inline-block`
784
+ * en el contenedor y eso es lo que hace que [centre] (text-align:center) lo
785
+ * centre. Forzarlo a block rompe el centrado. max-width:100% igual que
786
+ * osu.css: el mapa se escala al ancho disponible del preview en vez de
787
+ * quedarse clavado en 640px (el tope que ponía el .bbImageMap de Lyne). */
788
+ display: inline-block !important;
789
+ position: relative !important;
790
+ max-width: 100% !important;
791
+ margin: 10px 0 !important;
792
+ line-height: 0 !important;
793
+ }
794
+
795
+ .bbcode-preview-lyne .imagemap-container > img,
796
+ .bbcode-preview.theme-lyne .imagemap-container > img,
797
+ .bbcode-preview-lyne .bbcode-imagemap > img,
798
+ .bbcode-preview.theme-lyne .bbcode-imagemap > img {
799
+ /* Sin borde: la imagen del mapa queda limpia, igual que osu.css. Solo las
800
+ * regiones (imagemap-area) llevan borde para ser interactivas. */
801
+ width: 100% !important;
802
+ height: auto !important;
803
+ }
804
+
805
+ .bbcode-preview-lyne .imagemap-container > a,
806
+ .bbcode-preview.theme-lyne .imagemap-container > a,
807
+ .bbcode-preview-lyne .bbcode-imagemap > a,
808
+ .bbcode-preview.theme-lyne .bbcode-imagemap > a {
809
+ position: absolute;
810
+ border: 1px solid transparent;
811
+ transition: border-color 0.12s ease, background 0.12s ease;
812
+ }
813
+
814
+ .bbcode-preview-lyne .imagemap-container > a:hover,
815
+ .bbcode-preview.theme-lyne .imagemap-container > a:hover,
816
+ .bbcode-preview-lyne .bbcode-imagemap > a:hover,
817
+ .bbcode-preview.theme-lyne .bbcode-imagemap > a:hover {
818
+ border-color: var(--color-accent, #2EE6E2) !important;
819
+ background: rgba(46, 230, 226, 0.14) !important;
820
+ }
821
+
822
+ /* ─── Visual Effects & Animations ───────────────────────────────────────── */
823
+
824
+ /* Neon: basado en el CSS original de Lyne (Main Bridge/line/web/
825
+ * components/bbcode.module.css), con el parpadeo real de neón (neon-flicker)
826
+ * intacto. El glow se reduce de 5 a 2 capas (7px + 10px, sin halos externos):
827
+ * en el preview el contenido vive en un scroll container, y según
828
+ * css-overflow-3 §2.2/§2.3 la spec obliga a recortar todo lo que sobresale por
829
+ * encima del scroll origin (la "unreachable scrollable overflow region"), así
830
+ * que un halo amplio se cortaba en la primera línea. 7/10px caben holgados
831
+ * dentro del padding del preview y conservan el brillo de neón. */
832
+ .bb-neon {
833
+ color: var(--neon-color, #fff);
834
+ text-shadow:
835
+ 0 0 7px var(--neon-color, #fff),
836
+ 0 0 10px var(--neon-color, #fff);
837
+ animation: bb-neon-flicker 1.5s ease-in-out infinite alternate;
838
+ }
839
+ @keyframes bb-neon-flicker {
840
+ 0%, 19%, 21%, 23%, 25%, 54%, 56%, 100% {
841
+ text-shadow:
842
+ 0 0 7px var(--neon-color, #fff),
843
+ 0 0 10px var(--neon-color, #fff);
844
+ }
845
+ 20%, 24%, 55% {
846
+ text-shadow: none;
847
+ }
848
+ }
849
+
850
+ .bb-glow {
851
+ display: inline-block !important;
852
+ padding: 0 2px !important;
853
+ text-shadow:
854
+ 0 0 4px var(--glow-color, var(--color-accent, #2EE6E2)),
855
+ 0 0 8px var(--glow-color, var(--color-accent, #2EE6E2)) !important;
856
+ }
857
+
858
+ .bb-emboss {
859
+ text-shadow: 1px 1px 1px rgba(255,255,255,0.3), -1px -1px 1px rgba(0,0,0,0.7) !important;
860
+ }
861
+
862
+ .bb-engrave {
863
+ text-shadow: -1px -1px 1px rgba(255,255,255,0.3), 1px 1px 1px rgba(0,0,0,0.7) !important;
864
+ }
865
+
866
+ /* Shimmer: replica exacta del CSS original de Lyne (Main Bridge/line/web/
867
+ * components/bbcode.module.css). Sin `!important`, sin `inline-block` y sin
868
+ * picos de color fijos: el destello sigue los tokens del tema (text-mid →
869
+ * text-primary → text-mid) y anima con ease-in-out. */
870
+ .bb-shimmer,
871
+ .bbShimmer {
872
+ background: linear-gradient(
873
+ 90deg,
874
+ var(--color-text-mid) 0%,
875
+ var(--color-text-primary) 50%,
876
+ var(--color-text-mid) 100%
877
+ );
878
+ background-size: 200% 100%;
879
+ -webkit-background-clip: text;
880
+ background-clip: text;
881
+ color: transparent;
882
+ animation: bb-shimmer-anim 2s ease-in-out infinite;
883
+ }
884
+ @keyframes bb-shimmer-anim {
885
+ 0% {
886
+ background-position: 200% center;
887
+ }
888
+ 100% {
889
+ background-position: -200% center;
890
+ }
891
+ }
892
+
893
+ .bb-pulse {
894
+ display: inline-block !important;
895
+ transform: translateZ(0);
896
+ animation: bb-pulse-anim 2s ease-in-out infinite !important;
897
+ }
898
+ @keyframes bb-pulse-anim {
899
+ 0%, 100% { transform: translateZ(0) scale(1); }
900
+ 50% { transform: translateZ(0) scale(1.08); }
901
+ }
902
+
903
+ .bb-bounce {
904
+ display: inline-block !important;
905
+ transform: translateZ(0);
906
+ animation: bb-bounce-anim 2.4s ease-in-out infinite alternate !important;
907
+ }
908
+ @keyframes bb-bounce-anim {
909
+ from { transform: translate3d(0, 0, 0); }
910
+ to { transform: translate3d(0, -4px, 0); }
911
+ }
912
+
913
+ .bb-shake {
914
+ display: inline-block !important;
915
+ animation: bb-shake-anim 0.5s ease-in-out infinite !important;
916
+ }
917
+ @keyframes bb-shake-anim {
918
+ 0%, 100% { transform: translateX(0); }
919
+ 25% { transform: translateX(-3px); }
920
+ 75% { transform: translateX(3px); }
921
+ }
922
+
923
+ .bb-fade-in {
924
+ display: inline-block !important;
925
+ animation: bb-fade-in-anim 2s ease-in !important;
926
+ }
927
+ @keyframes bb-fade-in-anim {
928
+ from { opacity: 0; }
929
+ to { opacity: 1; }
930
+ }
931
+
932
+ .bb-fade-out {
933
+ display: inline-block !important;
934
+ animation: bb-fade-out-anim 2s ease-out forwards !important;
935
+ }
936
+ @keyframes bb-fade-out-anim {
937
+ from { opacity: 1; }
938
+ to { opacity: 0.3; }
939
+ }
940
+
941
+ .bb-typewriter-wrap {
942
+ display: inline-block !important;
943
+ vertical-align: text-bottom !important;
944
+ width: max-content !important;
945
+ max-width: 100% !important;
946
+ }
947
+
948
+ .bb-typewriter {
949
+ display: block !important;
950
+ overflow: hidden !important;
951
+ white-space: nowrap !important;
952
+ border-right: 2px solid var(--color-text-primary, #fff);
953
+ box-sizing: border-box !important;
954
+ animation:
955
+ bb-typewriter-anim calc(var(--bb-ch, 20) * 0.07s) steps(var(--bb-ch, 20), end) 0.3s 1 normal both,
956
+ bb-blink-anim 0.75s step-end infinite;
957
+ }
958
+ @keyframes bb-typewriter-anim {
959
+ from { width: 0; }
960
+ to { width: 100%; }
961
+ }
962
+ @keyframes bb-blink-anim {
963
+ 0%, 100% { border-color: var(--color-text-primary, #fff); }
964
+ 50% { border-color: transparent; }
965
+ }
966
+
967
+ .bb-wave {
968
+ display: inline-block !important;
969
+ animation: bb-wave-anim 1.5s ease-in-out infinite !important;
970
+ }
971
+ @keyframes bb-wave-anim {
972
+ 0%, 100% { transform: translateY(0); }
973
+ 25% { transform: translateY(-3px); }
974
+ 75% { transform: translateY(3px); }
975
+ }
976
+
977
+ .bb-sparkle {
978
+ display: inline-block !important;
979
+ animation: bb-sparkle-anim 1.5s ease-in-out infinite !important;
980
+ }
981
+ /* Sparkle sin `filter: brightness()`: filter no es compositable (repinta por
982
+ frame). opacity + transform corren en el compositor (GPU, gratis). */
983
+ @keyframes bb-sparkle-anim {
984
+ 0%, 100% { opacity: 1; transform: scale(1); }
985
+ 50% { opacity: 0.8; transform: scale(1.05); }
986
+ }
987
+
988
+ .bb-glitch {
989
+ position: relative !important;
990
+ display: inline-block !important;
991
+ }
992
+
993
+ .bb-levitate {
994
+ display: inline-block !important;
995
+ animation: bb-levitate-anim 3s ease-in-out infinite alternate !important;
996
+ }
997
+ @keyframes bb-levitate-anim {
998
+ from { transform: translateY(0); }
999
+ to { transform: translateY(-6px); }
1000
+ }
1001
+
1002
+ /* Ghost sin `filter: blur(0.5px)`: medio píxel de blur era casi invisible pero
1003
+ creaba una capa de composición propia + repintado. Solo opacity basta. */
1004
+ .bb-ghost {
1005
+ opacity: 0.6 !important;
1006
+ }
1007
+
1008
+ .bb-rainbow {
1009
+ background: linear-gradient(90deg, #ff0000, #ff7f00, #ffff00, #00ff00, #0000ff, #4b0082, #8f00ff) !important;
1010
+ -webkit-background-clip: text !important;
1011
+ background-clip: text !important;
1012
+ color: transparent !important;
1013
+ }
1014
+
1015
+ .bb-fire {
1016
+ background: linear-gradient(180deg, #ffe600 0%, #ff5e00 60%, #ff0000 100%) !important;
1017
+ -webkit-background-clip: text !important;
1018
+ background-clip: text !important;
1019
+ color: transparent !important;
1020
+ }
1021
+
1022
+ .bb-ice {
1023
+ background: linear-gradient(180deg, #ffffff 0%, #a0e6ff 50%, #00aaff 100%) !important;
1024
+ -webkit-background-clip: text !important;
1025
+ background-clip: text !important;
1026
+ color: transparent !important;
1027
+ }