@miliastry/quasar 1.1.0 → 1.2.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.
@@ -31,10 +31,17 @@
31
31
  --color-accent: #2EE6E2;
32
32
  --color-accent-bright: #68FFF8;
33
33
  --color-warning: #FFC34D;
34
+ --color-danger: #FF3B5C;
34
35
  --color-text-primary: #FFFFFF;
35
36
  --color-text-mid: #9EACD4;
36
37
  --color-text-dim: #606C8F;
37
38
  --color-hairline: rgba(255, 255, 255, 0.12);
39
+ --color-hairline-bright: rgba(142, 155, 196, 0.35);
40
+ --color-surface: #0B1024;
41
+ --color-surface-bright: #141C3C;
42
+ --color-inset-well: #080D20;
43
+ --color-on-accent: #05060F;
44
+ --cut-control: 10px;
38
45
  --font-display: var(--font-syne-display, "Saira Condensed"), "Saira Condensed", sans-serif;
39
46
  --font-body: var(--font-syne-body, "Saira"), "Saira", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
40
47
  --font-numeric: var(--font-syne-mono, "IBM Plex Mono"), "IBM Plex Mono", monospace;
@@ -914,9 +921,256 @@
914
921
  margin: 4px 0 !important;
915
922
  }
916
923
 
917
- /* Audio: replica el .bbAudio original de Lyne (bloque centrado, ancho máx). */
918
- .bb-audio {
919
- display: block !important;
924
+ /* ─── Audio: LINE chrome redesign (spec docs/design-spec/bbcode-audio-player) ── */
925
+ .bbcode-preview-lyne .lx-audio,
926
+ .bbcode-preview.theme-lyne .lx-audio,
927
+ [data-theme='syne'] .lx-audio,
928
+ [data-dialect='lyne'] .lx-audio,
929
+ .lx-audio {
930
+ --c: var(--cut-control, 10px);
931
+ display: inline-block !important;
932
+ width: 100% !important;
933
+ max-width: 560px !important;
934
+ margin: 14px 0 !important;
935
+ background:
936
+ linear-gradient(180deg, var(--color-surface-bright, #141C3C) 0%, var(--color-surface, #0B1024) 38%, var(--color-inset-well, #080D20) 100%) !important;
937
+ border: 1px solid var(--color-hairline-bright, rgba(142, 155, 196, 0.35)) !important;
938
+ clip-path: polygon(var(--c) 0, 100% 0, 100% calc(100% - var(--c)), calc(100% - var(--c)) 100%, 0 100%, 0 var(--c)) !important;
939
+ position: relative;
940
+ font-family: var(--font-body, "Saira", sans-serif);
941
+ transition: border-color 120ms cubic-bezier(0.16, 1.0, 0.3, 1.0);
942
+ text-align: left;
943
+ box-sizing: border-box;
944
+ vertical-align: middle;
945
+ }
946
+ .lx-audio audio {
947
+ position: absolute !important;
948
+ width: 1px !important;
949
+ height: 1px !important;
950
+ opacity: 0 !important;
951
+ pointer-events: none !important;
952
+ clip: rect(0, 0, 0, 0) !important;
953
+ }
954
+ .lx-audio:hover {
955
+ border-color: rgba(46, 230, 226, 0.45) !important;
956
+ }
957
+ .lx-audio.is-playing {
958
+ border-color: rgba(46, 230, 226, 0.6) !important;
959
+ }
960
+
961
+ /* thin accent baseline — the "catch line" motif; fills with progress */
962
+ .lx-audio .lx-track {
963
+ position: relative;
964
+ height: 12px;
965
+ cursor: pointer;
966
+ background:
967
+ repeating-linear-gradient(-45deg, rgba(142,155,196,0.10) 0 2px, transparent 2px 9px),
968
+ var(--color-inset-well, #080D20);
969
+ }
970
+ .lx-audio .lx-track .fill {
971
+ position: absolute;
972
+ inset: 0 auto 0 0;
973
+ width: 0%;
974
+ background: linear-gradient(90deg, rgba(46,230,226,0.10), rgba(46,230,226,0.22));
975
+ border-right: 2px solid var(--color-accent, #2EE6E2);
976
+ box-shadow: 0 0 12px rgba(46, 230, 226, 0.55);
977
+ }
978
+ .lx-audio .lx-row {
979
+ display: flex;
980
+ align-items: center;
981
+ gap: 14px;
982
+ padding: 10px 16px 12px;
983
+ }
984
+ .lx-audio .lx-btn {
985
+ flex: none;
986
+ width: 40px;
987
+ height: 40px;
988
+ display: grid;
989
+ place-items: center;
990
+ background: var(--color-accent, #2EE6E2);
991
+ color: var(--color-on-accent, #05060F);
992
+ cursor: pointer;
993
+ border: none;
994
+ clip-path: polygon(var(--c) 0, 100% 0, 100% calc(100% - var(--c)), calc(100% - var(--c)) 100%, 0 100%, 0 var(--c));
995
+ transition: background 120ms cubic-bezier(0.16, 1.0, 0.3, 1.0), transform 120ms cubic-bezier(0.16, 1.0, 0.3, 1.0);
996
+ }
997
+ .lx-audio .lx-btn:hover {
998
+ background: var(--color-accent-bright, #7FF5F0);
999
+ }
1000
+ .lx-audio .lx-btn:active {
1001
+ transform: scale(0.94);
1002
+ }
1003
+ .lx-audio .lx-btn svg {
1004
+ width: 16px;
1005
+ height: 16px;
1006
+ fill: var(--color-on-accent, #05060F);
1007
+ }
1008
+
1009
+ .lx-audio .lx-title {
1010
+ flex: 1;
1011
+ min-width: 0;
1012
+ }
1013
+ .lx-audio .lx-title .name {
1014
+ font-family: var(--font-display, "Saira Condensed", sans-serif);
1015
+ font-weight: 600;
1016
+ font-size: 16px;
1017
+ text-transform: uppercase;
1018
+ letter-spacing: 1px;
1019
+ white-space: nowrap;
1020
+ overflow: hidden;
1021
+ text-overflow: ellipsis;
1022
+ color: var(--color-text-primary, #F2F5FF);
1023
+ }
1024
+ .lx-audio .lx-title .label {
1025
+ font-family: var(--font-numeric, "IBM Plex Mono", monospace);
1026
+ font-size: 10px;
1027
+ font-weight: 500;
1028
+ letter-spacing: 2px;
1029
+ text-transform: uppercase;
1030
+ color: var(--color-text-dim, #8E9BC4);
1031
+ display: flex;
1032
+ align-items: center;
1033
+ gap: 6px;
1034
+ margin-top: 1px;
1035
+ }
1036
+ .lx-audio .lx-title .label .dot {
1037
+ width: 5px;
1038
+ height: 5px;
1039
+ background: var(--color-text-dim, #8E9BC4);
1040
+ flex: none;
1041
+ transition: background 120ms;
1042
+ }
1043
+ .lx-audio.is-playing .lx-title .label .dot {
1044
+ background: var(--color-accent, #2EE6E2);
1045
+ box-shadow: 0 0 6px rgba(46,230,226,0.9);
1046
+ animation: lx-beat 606ms infinite;
1047
+ }
1048
+ @keyframes lx-beat {
1049
+ 0% { transform: scale(1.25); }
1050
+ 100% { transform: scale(1); }
1051
+ }
1052
+
1053
+ .lx-audio .lx-vol {
1054
+ display: flex;
1055
+ align-items: center;
1056
+ gap: 6px;
1057
+ flex: none;
1058
+ }
1059
+ .lx-audio .lx-vol-btn {
1060
+ background: none;
1061
+ border: none;
1062
+ padding: 2px;
1063
+ cursor: pointer;
1064
+ display: grid;
1065
+ place-items: center;
1066
+ color: var(--color-text-dim, #8E9BC4);
1067
+ transition: color 120ms cubic-bezier(0.16, 1.0, 0.3, 1.0);
1068
+ }
1069
+ .lx-audio .lx-vol-btn:hover {
1070
+ color: var(--color-accent, #2EE6E2);
1071
+ }
1072
+ .lx-audio .lx-vol-btn svg {
1073
+ width: 14px;
1074
+ height: 14px;
1075
+ fill: currentColor;
1076
+ }
1077
+ .lx-audio .lx-vol-slider {
1078
+ -webkit-appearance: none;
1079
+ appearance: none;
1080
+ width: 56px;
1081
+ height: 4px;
1082
+ background: var(--color-inset-well, #080D20);
1083
+ border: 1px solid var(--color-hairline, rgba(142, 155, 196, 0.25));
1084
+ outline: none;
1085
+ cursor: pointer;
1086
+ border-radius: 0;
1087
+ vertical-align: middle;
1088
+ }
1089
+ .lx-audio .lx-vol-slider::-webkit-slider-thumb {
1090
+ -webkit-appearance: none;
1091
+ appearance: none;
1092
+ width: 8px;
1093
+ height: 12px;
1094
+ background: var(--color-accent, #2EE6E2);
1095
+ clip-path: polygon(2px 0, 100% 0, 100% calc(100% - 2px), calc(100% - 2px) 100%, 0 100%, 0 2px);
1096
+ cursor: pointer;
1097
+ transition: transform 120ms, background 120ms;
1098
+ }
1099
+ .lx-audio .lx-vol-slider::-moz-range-thumb {
1100
+ width: 8px;
1101
+ height: 12px;
1102
+ border: none;
1103
+ border-radius: 0;
1104
+ background: var(--color-accent, #2EE6E2);
1105
+ clip-path: polygon(2px 0, 100% 0, 100% calc(100% - 2px), calc(100% - 2px) 100%, 0 100%, 0 2px);
1106
+ cursor: pointer;
1107
+ }
1108
+ .lx-audio .lx-vol-slider:hover::-webkit-slider-thumb {
1109
+ background: var(--color-accent-bright, #7FF5F0);
1110
+ transform: scaleY(1.15);
1111
+ }
1112
+ .lx-audio .lx-vol-slider:hover::-moz-range-thumb {
1113
+ background: var(--color-accent-bright, #7FF5F0);
1114
+ }
1115
+
1116
+ .lx-audio .lx-time {
1117
+ flex: none;
1118
+ font-family: var(--font-numeric, "IBM Plex Mono", monospace);
1119
+ font-weight: 500;
1120
+ font-size: 12px;
1121
+ letter-spacing: 0.5px;
1122
+ color: var(--color-text-mid, #AAB6DE);
1123
+ font-variant-numeric: tabular-nums;
1124
+ }
1125
+ .lx-audio .lx-time .cur {
1126
+ color: var(--color-text-primary, #F2F5FF);
1127
+ }
1128
+
1129
+ .lx-audio .lx-speed {
1130
+ flex: none;
1131
+ font-family: var(--font-numeric, "IBM Plex Mono", monospace);
1132
+ font-size: 11px;
1133
+ font-weight: 500;
1134
+ color: var(--color-text-dim, #8E9BC4);
1135
+ background: none;
1136
+ border: 1px solid var(--color-hairline, rgba(142, 155, 196, 0.18));
1137
+ padding: 3px 8px;
1138
+ cursor: pointer;
1139
+ letter-spacing: 1px;
1140
+ clip-path: polygon(5px 0, 100% 0, 100% calc(100% - 5px), calc(100% - 5px) 100%, 0 100%, 0 5px);
1141
+ transition: color 120ms, border-color 120ms;
1142
+ }
1143
+ .lx-audio .lx-speed:hover {
1144
+ color: var(--color-accent, #2EE6E2);
1145
+ border-color: rgba(46,230,226,0.4);
1146
+ }
1147
+ .lx-audio .lx-speed.active {
1148
+ color: var(--color-accent, #2EE6E2);
1149
+ border-color: rgba(46,230,226,0.5);
1150
+ }
1151
+
1152
+ /* states */
1153
+ .lx-audio.is-loading .lx-btn svg {
1154
+ opacity: 0.3;
1155
+ }
1156
+ .lx-audio.is-loading .fill {
1157
+ border-right-color: var(--color-text-dim, #8E9BC4);
1158
+ box-shadow: none;
1159
+ }
1160
+ .lx-audio.is-error {
1161
+ border-color: rgba(255, 59, 92, 0.5) !important;
1162
+ }
1163
+ .lx-audio.is-error .fill {
1164
+ border-right-color: var(--color-danger, #FF3B5C);
1165
+ box-shadow: 0 0 12px rgba(255,59,92,0.5);
1166
+ }
1167
+ .lx-audio.is-error .lx-title .label {
1168
+ color: var(--color-danger, #FF3B5C);
1169
+ }
1170
+
1171
+ /* Fallback si se usa audio nativo directo */
1172
+ audio.bb-audio {
1173
+ display: inline-block !important;
920
1174
  width: 100% !important;
921
1175
  max-width: 420px !important;
922
1176
  margin: 10px 0 !important;
@@ -73,7 +73,7 @@
73
73
  .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) blockquote {
74
74
  padding: 0 0 0 20px;
75
75
  margin: 0 0 20px 0;
76
- border-left: 2px solid #D194B3;
76
+ border-left: 2px solid var(--osu-accent);
77
77
  color: #ffffff;
78
78
  font-style: normal;
79
79
  background: none;
@@ -83,8 +83,8 @@
83
83
  .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) pre {
84
84
  padding: 10px;
85
85
  margin-bottom: 10px;
86
- background: #1C1719;
87
- border: 1px solid #43383A;
86
+ background: var(--osu-code-bg);
87
+ border: 1px solid var(--osu-code-border);
88
88
  border-radius: 8px;
89
89
  overflow-x: auto;
90
90
  }
@@ -150,7 +150,7 @@
150
150
  .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) details summary {
151
151
  cursor: pointer;
152
152
  font-weight: 600;
153
- color: #D194B3;
153
+ color: var(--osu-accent);
154
154
  font-size: 13px;
155
155
  user-select: none;
156
156
  }
@@ -176,7 +176,7 @@
176
176
  display: list-item;
177
177
  }
178
178
  .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) li::marker {
179
- color: #D194B3;
179
+ color: var(--osu-accent);
180
180
  }
181
181
 
182
182
  /* ─── Media ──────────────────────────────────────────── */
@@ -195,7 +195,11 @@
195
195
  border-radius: 8px;
196
196
  }
197
197
  .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) audio {
198
+ /* inline-block: el preflight de Tailwind fuerza `audio{display:block}`
199
+ * y eso rompe el centrado por `text-align:center` de [centre]. */
200
+ display: inline-block;
198
201
  width: 100%;
202
+ max-width: 420px;
199
203
  }
200
204
 
201
205
  /* ─── Image Map ──────────────────────────────────────── */
@@ -268,7 +272,106 @@
268
272
  display: inline-block;
269
273
  transform: rotate(-5deg) scale(0.95);
270
274
  font-style: italic;
271
- color: #F0A0C0;
275
+ color: var(--osu-bloom);
276
+ }
277
+
278
+ /* ─── Semantic Spacing ───────────────────────────────── */
279
+
280
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .bbcode-sp {
281
+ display: block;
282
+ height: 0;
283
+ min-height: 0;
284
+ margin: 0;
285
+ padding: 0;
286
+ }
287
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .bbcode-para {
288
+ display: block;
289
+ height: 1em;
290
+ min-height: 12px;
291
+ padding: 0;
292
+ }
293
+
294
+ /* ─── Vocabulario de clases del dialecto osu ──────────────────────────────
295
+ *
296
+ * Con `dialect: 'osu'` el renderer emite los nombres de clase reales de osu!
297
+ * (`well`, `js-spoilerbox`, `imagemap__link`, …) en vez de los de Miliastry
298
+ * (`notice`, `imagemap-container`, …). Sobre osu.ppy.sh eso basta: su propia
299
+ * hoja los pinta. Fuera de ahí —el preview de la app, el HTML autónomo de
300
+ * `scripts/osu-inject.ts`— no hay nadie, y estas reglas son ese nadie.
301
+ *
302
+ * ── Un solo parámetro, como osu ──────────────────────────────────────
303
+ *
304
+ * osu! no hardcodea sus colores: define `--base-hue` y deriva todo con
305
+ * `hsl()`, porque el usuario elige el tono de su tema. Medirlos y copiar el
306
+ * resultado congelaría UN tema concreto. Así que aquí se reproduce la
307
+ * mecánica, no la foto: los pares saturación/luminosidad son fijos por rol
308
+ * (la familia `b` es fondo al 10%, la `l` enlaces al 40%) y el tono entra por
309
+ * variable.
310
+ *
311
+ * `var(--base-hue, 338)` consume el tono del documento cuando existe —en la
312
+ * página real de osu existe, y ahí gana el del usuario— y si no cae a 338.
313
+ *
314
+ * Ese respaldo NO es el tono de osu (253), y es deliberado: esta hoja se
315
+ * consume sobre todo DENTRO de Miliastry, cuyo modo osu tiene fondo rosado
316
+ * (`#2a1f23`, tono 338) y acento `--accent-pink` (~332). Cayendo al 253 se
317
+ * mezclaban morados de osu sobre un fondo rosa nuestro, que se veía «casi
318
+ * bien» y por eso no saltaba. Un host puede fijar `--base-hue` para forzar
319
+ * otro.
320
+ *
321
+ * Las reglas de arriba (`.notice`, `.imagemap-container`, `.imagemap-area`)
322
+ * siguen vivas: son los nombres que emiten los dialectos miliastry y lyne.
323
+ * Esta sección añade, no reemplaza.
324
+ */
325
+
326
+ /* Qué sigue al tono y qué no: EL CONTENIDO SIGUE, LAS SEÑALES NO.
327
+ *
328
+ * Lo que el BBCode pinta —citas, listas, código, cajas, enlaces— se deriva de
329
+ * `--osu-hue`, porque su color no significa nada por sí mismo: es la piel del
330
+ * documento. Lo que comunica un estado conserva su color fijo, porque ahí el
331
+ * color ES el mensaje: el rojo de `.media-error`, el negro sobre negro de
332
+ * `.spoiler` (que en osu es literalmente eso), el rosa de selección de las
333
+ * áreas de imagemap —una ayuda de edición, no contenido— y el degradado
334
+ * deliberadamente multicolor de `.sparkle`. Los blancos y los `rgba()`
335
+ * neutros tampoco: son veladuras, no color.
336
+ *
337
+ * Si vienes a "terminar el trabajo" convirtiendo los que quedan, esto es el
338
+ * porqué de que sigan ahí.
339
+ */
340
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) {
341
+ --osu-hue: var(--base-hue, 338);
342
+ --osu-bg-deep: hsl(var(--osu-hue), 10%, 15%); /* fondo hundido */
343
+ --osu-border: hsl(var(--osu-hue), 10%, 40%); /* borde sobre ese fondo */
344
+ --osu-link: hsl(var(--osu-hue), 40%, 75%); /* enlaces, perfiles, cajas */
345
+ --osu-link-hi: hsl(var(--osu-hue), 40%, 80%); /* el mismo, al pasar */
346
+ --osu-text: hsl(var(--osu-hue), 40%, 100%); /* texto sobre fondo hundido */
347
+
348
+ /* ── La escalera real de osu ──────────────────────────────────────────
349
+ * Leída de su página en vivo (`--hsl-*` sobre `.bbcode`), no deducida:
350
+ * osu define --base-hue y estos pares de saturación/luminosidad, y su
351
+ * `bbcode.less` asigna un rol a cada elemento. Los cinco alias de arriba
352
+ * son estos mismos: bg-deep = b5, border = b1, link = l2, link-hi = l1,
353
+ * text = c1. Se nombran los roles aparte para poder citar la hoja de osu
354
+ * por su nombre cuando se ajusta un elemento concreto. */
355
+ --osu-b1: hsl(var(--osu-hue), 10%, 40%);
356
+ --osu-b5: hsl(var(--osu-hue), 10%, 15%);
357
+ --osu-b6: hsl(var(--osu-hue), 10%, 10%);
358
+ --osu-c2: hsl(var(--osu-hue), 40%, 90%);
359
+ --osu-l1: hsl(var(--osu-hue), 40%, 80%);
360
+ --osu-l3: hsl(var(--osu-hue), 40%, 70%);
361
+
362
+ /* El acento del cuerpo en el look de MILIASTRY: filo de las citas,
363
+ * marcador de lista, título de `details`. Era el literal `#D194B3`, que es
364
+ * exactamente hsl(330,40%,70%) — o sea `l3`. osu usa otros roles en esos
365
+ * mismos elementos; ver el bloque `[data-dialect="osu"]` más abajo. */
366
+ --osu-accent: var(--osu-l3);
367
+ /* Superficie del bloque de código y su filo, look de Miliastry. Eran
368
+ * `#1C1719` —hsl(336,10%,10%), que es `b6`— y `#43383A`. Este último
369
+ * estaba en el tono 349, fuera de la familia; al derivarlo se corrige. */
370
+ --osu-code-bg: var(--osu-b6);
371
+ --osu-code-border: hsl(var(--osu-hue), 9%, 24%);
372
+ /* Adorno `.flower`: era `#F0A0C0`, hsl(336,73%,78%). Es de Miliastry, osu
373
+ * no tiene nada parecido. */
374
+ --osu-bloom: hsl(var(--osu-hue), 73%, 78%);
272
375
  }
273
376
 
274
377
  /* ─── Semantic Spacing ───────────────────────────────── */
@@ -286,3 +389,251 @@
286
389
  min-height: 12px;
287
390
  padding: 0;
288
391
  }
392
+
393
+ /* ─── Vocabulario de clases del dialecto osu ──────────────────────────────
394
+ *
395
+ * Con `dialect: 'osu'` el renderer emite los nombres de clase reales de osu!
396
+ * (`well`, `js-spoilerbox`, `imagemap__link`, …) en vez de los de Miliastry
397
+ * (`notice`, `imagemap-container`, …). Sobre osu.ppy.sh eso basta: su propia
398
+ * hoja los pinta. Fuera de ahí —el preview de la app, el HTML autónomo de
399
+ * `scripts/osu-inject.ts`— no hay nadie, y estas reglas son ese nadie.
400
+ *
401
+ * ── Un solo parámetro, como osu ──────────────────────────────────────
402
+ *
403
+ * osu! no hardcodea sus colores: define `--base-hue` y deriva todo con
404
+ * `hsl()`, porque el usuario elige el tono de su tema. Medirlos y copiar el
405
+ * resultado congelaría UN tema concreto. Así que aquí se reproduce la
406
+ * mecánica, no la foto: los pares saturación/luminosidad son fijos por rol
407
+ * (la familia `b` es fondo al 10%, la `l` enlaces al 40%) y el tono entra por
408
+ * variable.
409
+ *
410
+ * `var(--base-hue, 338)` consume el tono del documento cuando existe —en la
411
+ * página real de osu existe, y ahí gana el del usuario— y si no cae a 338.
412
+ *
413
+ * Ese respaldo NO es el tono de osu (253), y es deliberado: esta hoja se
414
+ * consume sobre todo DENTRO de Miliastry, cuyo modo osu tiene fondo rosado
415
+ * (`#2a1f23`, tono 338) y acento `--accent-pink` (~332). Cayendo al 253 se
416
+ * mezclaban morados de osu sobre un fondo rosa nuestro, que se veía «casi
417
+ * bien» y por eso no saltaba. Un host puede fijar `--base-hue` para forzar
418
+ * otro.
419
+ *
420
+ * Las reglas de arriba (`.notice`, `.imagemap-container`, `.imagemap-area`)
421
+ * siguen vivas: son los nombres que emiten los dialectos miliastry y lyne.
422
+ * Esta sección añade, no reemplaza.
423
+ */
424
+
425
+ /* Qué sigue al tono y qué no: EL CONTENIDO SIGUE, LAS SEÑALES NO.
426
+ *
427
+ * Lo que el BBCode pinta —citas, listas, código, cajas, enlaces— se deriva de
428
+ * `--osu-hue`, porque su color no significa nada por sí mismo: es la piel del
429
+ * documento. Lo que comunica un estado conserva su color fijo, porque ahí el
430
+ * color ES el mensaje: el rojo de `.media-error`, el negro sobre negro de
431
+ * `.spoiler` (que en osu es literalmente eso), el rosa de selección de las
432
+ * áreas de imagemap —una ayuda de edición, no contenido— y el degradado
433
+ * deliberadamente multicolor de `.sparkle`. Los blancos y los `rgba()`
434
+ * neutros tampoco: son veladuras, no color.
435
+ *
436
+ * Si vienes a "terminar el trabajo" convirtiendo los que quedan, esto es el
437
+ * porqué de que sigan ahí.
438
+ */
439
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) {
440
+ --osu-hue: var(--base-hue, 338);
441
+ --osu-bg-deep: hsl(var(--osu-hue), 10%, 15%); /* fondo hundido */
442
+ --osu-border: hsl(var(--osu-hue), 10%, 40%); /* borde sobre ese fondo */
443
+ --osu-link: hsl(var(--osu-hue), 40%, 75%); /* enlaces, perfiles, cajas */
444
+ --osu-link-hi: hsl(var(--osu-hue), 40%, 80%); /* el mismo, al pasar */
445
+ --osu-text: hsl(var(--osu-hue), 40%, 100%); /* texto sobre fondo hundido */
446
+
447
+ /* El acento del cuerpo: filo de las citas, marcador de lista, título de
448
+ * `details`. Era el literal `#D194B3`, que es exactamente hsl(330,40%,70%). */
449
+ --osu-accent: hsl(var(--osu-hue), 40%, 70%);
450
+ /* Superficie del bloque de código y su filo. Eran `#1C1719` —hsl(336,10%,10%)—
451
+ * y `#43383A`. Este último estaba en el tono 349, fuera de la familia; al
452
+ * derivarlo del tono se corrige de paso. */
453
+ --osu-code-bg: hsl(var(--osu-hue), 10%, 10%);
454
+ --osu-code-border: hsl(var(--osu-hue), 9%, 24%);
455
+ /* Adorno `.flower`: era `#F0A0C0`, hsl(336,73%,78%). */
456
+ --osu-bloom: hsl(var(--osu-hue), 73%, 78%);
457
+ }
458
+
459
+ /* Los enlaces de osu son del mismo morado que los perfiles, no azules. El
460
+ * azul de la sección base es el look de Miliastry, así que sólo se pisa
461
+ * cuando el preview declara el dialecto osu. */
462
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne)[data-dialect="osu"] a { color: var(--osu-link); }
463
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne)[data-dialect="osu"] a:hover { color: var(--osu-link-hi); border-bottom-color: var(--osu-link-hi); }
464
+
465
+ /* ── Roles de osu para el cuerpo del documento ────────────────────────────
466
+ * Fuente: `resources/css/bbcode.less` de osu-web, cruzada con la escalera
467
+ * medida en su página. Estos elementos tienen en Miliastry el acento rosa
468
+ * (`--osu-accent`), que es el look de la casa; bajo el dialecto osu mandan
469
+ * los roles de osu, igual que ya pasa arriba con los enlaces.
470
+ */
471
+
472
+ /* La cita no lleva acento: el texto Y la barra son `c2`, y la barra la pinta
473
+ * osu con un ::before de 2px redondeado. El borde izquierdo da el mismo
474
+ * resultado a esta anchura. */
475
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne)[data-dialect="osu"] blockquote {
476
+ color: var(--osu-c2);
477
+ border-left-color: var(--osu-c2);
478
+ }
479
+
480
+ /* El bloque de código es `b5` y NO lleva borde. El nuestro usaba `b6` con un
481
+ * filo, que es más oscuro y más marcado que el de osu. */
482
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne)[data-dialect="osu"] pre {
483
+ background: var(--osu-b5);
484
+ border: none;
485
+ }
486
+
487
+ /* El código en línea también es `b5`, plano: ni veladura blanca ni filo. */
488
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne)[data-dialect="osu"] code.inline {
489
+ background: var(--osu-b5);
490
+ border: none;
491
+ padding: 1px 4px;
492
+ }
493
+
494
+ /* `[heading]` no es blanco en osu, es `l1`. */
495
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne)[data-dialect="osu"] h2 {
496
+ color: var(--osu-l1);
497
+ }
498
+
499
+ /* osu no le da color al marcador de lista: hereda el del texto. El rosa es
500
+ * cosa nuestra. */
501
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne)[data-dialect="osu"] li::marker {
502
+ color: inherit;
503
+ }
504
+
505
+ /* El spoiler de osu es negro puro sobre negro puro, no un gris. */
506
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne)[data-dialect="osu"] .spoiler {
507
+ background: #000;
508
+ color: #000;
509
+ }
510
+
511
+ /* Notice — osu lo llama `well` */
512
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .well {
513
+ padding: 19px;
514
+ border: 2px solid var(--osu-border);
515
+ border-radius: 4px;
516
+ background: var(--osu-bg-deep);
517
+ color: var(--osu-text);
518
+ text-align: center;
519
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
520
+ }
521
+
522
+ /* Spoilerbox — estructura div > a(icono + texto) + div(cuerpo) */
523
+ /* osu no le pone caja propia al contenedor: el `margin: 8px 0` que trae
524
+ * `features/BBCode/styles.css` para el look de Miliastry sumaba 16px por
525
+ * caja (19 en una userpage real). Se declara a cero en vez de confiar en
526
+ * la especificidad, que aquí sólo ganaba en `display`. */
527
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .bbcode-spoilerbox { display: block; margin: 0; padding: 0; }
528
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .bbcode-spoilerbox__link {
529
+ display: inline-flex;
530
+ align-items: center;
531
+ color: var(--osu-link);
532
+ font-weight: 700;
533
+ text-decoration: none;
534
+ cursor: pointer;
535
+ /* osu lo deja al 100%; `features/BBCode/styles.css` lo baja a 0.85em para el
536
+ * look de Miliastry. Bajo este dialecto manda el de osu. */
537
+ font-size: 1em;
538
+ line-height: inherit;
539
+ /* Un `inline-flex` se alinea sobre la línea base del texto, así que el
540
+ * navegador reserva hueco para los descendentes DEBAJO y la caja crece de
541
+ * 21px a 26px. osu no lo sufre porque su icono es un glifo de fuente, que
542
+ * aporta una línea base real; el nuestro es un triángulo CSS sin texto y la
543
+ * base se sintetiza desde el borde inferior. Alinear arriba elimina el
544
+ * hueco: el enlace es el único contenido de su línea, así que `top` no
545
+ * cambia nada más. Medido: 26px -> 21px, que es lo que mide en osu. */
546
+ vertical-align: top;
547
+ }
548
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .bbcode-spoilerbox__link:hover { color: var(--osu-link-hi); border-bottom: none; }
549
+
550
+ /* El icono de osu es un glifo de Font Awesome 5, que no distribuimos. Este es
551
+ * un triángulo CSS equivalente: apunta a la derecha cerrado y rota al abrir.
552
+ * osu cambia de glifo en vez de rotar; el efecto leído es el mismo. Hereda
553
+ * `currentColor`, así que sigue al tono sin declarar nada. */
554
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .bbcode-spoilerbox__link-icon {
555
+ display: block;
556
+ position: relative;
557
+ flex: none;
558
+ width: 20px;
559
+ height: 21px;
560
+ }
561
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .bbcode-spoilerbox__link-icon::before {
562
+ content: "";
563
+ position: absolute;
564
+ top: 50%;
565
+ left: 5px;
566
+ width: 0;
567
+ height: 0;
568
+ border-left: 5px solid currentColor;
569
+ border-top: 4px solid transparent;
570
+ border-bottom: 4px solid transparent;
571
+ transform: translateY(-50%);
572
+ transform-origin: 2px 50%;
573
+ transition: transform 0.12s ease;
574
+ }
575
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .js-spoilerbox--open .bbcode-spoilerbox__link-icon::before {
576
+ transform: translateY(-50%) rotate(90deg);
577
+ }
578
+
579
+ /* El cuerpo arranca oculto. Lo abre la clase `js-spoilerbox--open` en el
580
+ * CONTENEDOR, que pone `bindBoxDrawer`. */
581
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .bbcode-spoilerbox__body {
582
+ display: none;
583
+ margin: 10px 0 0;
584
+ padding: 0 0 0 20px;
585
+ }
586
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .js-spoilerbox--open > .bbcode-spoilerbox__body { display: block; }
587
+
588
+ /* Imagemap — el contenedor ancla; los enlaces van absolutos con el
589
+ * left/top/width/height en % que el renderer escribe en el style inline.
590
+ * Sin el `position: relative` los enlaces caen al flujo. */
591
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .imagemap {
592
+ display: inline-block;
593
+ position: relative;
594
+ max-width: max-content;
595
+ }
596
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .imagemap__image {
597
+ display: inline;
598
+ max-width: 100%;
599
+ vertical-align: middle;
600
+ }
601
+ /* Transparentes en reposo, como en osu. El realce al pasar por encima es
602
+ * nuestro: en un editor conviene ver dónde están las áreas, y no altera la
603
+ * apariencia estática. */
604
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .imagemap__link {
605
+ display: block;
606
+ position: absolute;
607
+ box-sizing: border-box;
608
+ border-radius: 4px;
609
+ text-decoration: none;
610
+ transition: background-color 0.08s linear, box-shadow 0.08s linear;
611
+ }
612
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .imagemap__link:hover {
613
+ background: hsl(var(--osu-hue), 40%, 75%, 0.22);
614
+ box-shadow: inset 0 0 0 1.5px var(--osu-link);
615
+ border-bottom: none;
616
+ }
617
+
618
+ /* Alineación */
619
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .bbcode__align-centre { display: block; text-align: center; }
620
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .bbcode__align-left { display: block; text-align: left; }
621
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .bbcode__align-right { display: block; text-align: right; }
622
+
623
+ /* Perfil */
624
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .user-name {
625
+ display: inline;
626
+ color: var(--osu-link);
627
+ font-weight: 700;
628
+ text-decoration: none;
629
+ }
630
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .user-name:hover { color: var(--osu-link-hi); border-bottom: none; }
631
+
632
+ /* YouTube */
633
+ .bbcode-preview:not(.bbcode-preview-lyne):not(.theme-lyne) .u-embed-wide--bbcode {
634
+ display: inline-block;
635
+ width: 100%;
636
+ max-width: 425px;
637
+ aspect-ratio: 16 / 9;
638
+ border: 0;
639
+ }