@jjlmoya/utils-developer 1.13.0 → 1.15.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 (184) hide show
  1. package/package.json +1 -1
  2. package/src/category/i18n/fr.ts +1 -1
  3. package/src/category/i18n/ru.ts +1 -1
  4. package/src/layouts/PreviewLayout.astro +1 -0
  5. package/src/pages/[locale]/[slug].astro +29 -12
  6. package/src/tests/diacritics_density.test.ts +118 -0
  7. package/src/tests/inverted_punctuation.test.ts +113 -0
  8. package/src/tests/no_en_dash.test.ts +73 -0
  9. package/src/tests/script_density.test.ts +94 -0
  10. package/src/tests/shared-test-helpers.ts +56 -0
  11. package/src/tests/tool_exports.test.ts +34 -0
  12. package/src/tool/aspectRatio/aspect-ratio-calculator.css +1 -1
  13. package/src/tool/aspectRatio/i18n/de.ts +1 -1
  14. package/src/tool/aspectRatio/i18n/fr.ts +1 -1
  15. package/src/tool/aspectRatio/i18n/pl.ts +2 -2
  16. package/src/tool/aspectRatio/i18n/ru.ts +4 -4
  17. package/src/tool/aspectRatio/i18n/zh.ts +1 -1
  18. package/src/tool/aspectRatio/seo.astro +2 -1
  19. package/src/tool/calculadoraTiempoDatos/data-time-calculator-web-speed-impact.css +26 -26
  20. package/src/tool/calculadoraTiempoDatos/i18n/de.ts +1 -1
  21. package/src/tool/calculadoraTiempoDatos/i18n/pl.ts +1 -1
  22. package/src/tool/calculadoraTiempoDatos/i18n/ru.ts +5 -5
  23. package/src/tool/calculadoraTiempoDatos/i18n/sv.ts +5 -5
  24. package/src/tool/calculadoraTiempoDatos/i18n/zh.ts +1 -1
  25. package/src/tool/calculadoraTiempoDatos/seo.astro +2 -1
  26. package/src/tool/colorConverter/color-converter-rgb-hex-hsl.css +9 -9
  27. package/src/tool/colorConverter/i18n/de.ts +1 -1
  28. package/src/tool/colorConverter/i18n/ru.ts +2 -2
  29. package/src/tool/colorConverter/seo.astro +2 -1
  30. package/src/tool/conversorExcelCsvHtml/excel-csv-html-table-converter.css +24 -24
  31. package/src/tool/conversorExcelCsvHtml/i18n/es.ts +1 -1
  32. package/src/tool/conversorExcelCsvHtml/i18n/pl.ts +1 -1
  33. package/src/tool/conversorExcelCsvHtml/i18n/ru.ts +2 -2
  34. package/src/tool/conversorExcelCsvHtml/i18n/zh.ts +2 -2
  35. package/src/tool/conversorExcelCsvHtml/seo.astro +2 -1
  36. package/src/tool/cronGenerator/cron.css +5 -5
  37. package/src/tool/cronGenerator/i18n/de.ts +4 -4
  38. package/src/tool/cronGenerator/i18n/en.ts +1 -1
  39. package/src/tool/cronGenerator/i18n/es.ts +2 -2
  40. package/src/tool/cronGenerator/i18n/fr.ts +5 -5
  41. package/src/tool/cronGenerator/i18n/id.ts +1 -1
  42. package/src/tool/cronGenerator/i18n/nl.ts +1 -1
  43. package/src/tool/cronGenerator/i18n/pl.ts +8 -8
  44. package/src/tool/cronGenerator/i18n/pt.ts +1 -1
  45. package/src/tool/cronGenerator/i18n/ru.ts +9 -9
  46. package/src/tool/cronGenerator/i18n/sv.ts +1 -1
  47. package/src/tool/cronGenerator/i18n/zh.ts +3 -3
  48. package/src/tool/cronGenerator/seo.astro +2 -1
  49. package/src/tool/cssSpecificityCalculator/css-specificity-calculator.css +1 -1
  50. package/src/tool/cssSpecificityCalculator/i18n/de.ts +1 -1
  51. package/src/tool/cssSpecificityCalculator/i18n/fr.ts +3 -3
  52. package/src/tool/cssSpecificityCalculator/i18n/pl.ts +2 -2
  53. package/src/tool/cssSpecificityCalculator/i18n/ru.ts +2 -2
  54. package/src/tool/cssSpecificityCalculator/seo.astro +2 -1
  55. package/src/tool/cssToInlineConverter/css-to-inline-converter.css +1 -1
  56. package/src/tool/cssToInlineConverter/i18n/de.ts +6 -6
  57. package/src/tool/cssToInlineConverter/i18n/es.ts +1 -1
  58. package/src/tool/cssToInlineConverter/i18n/fr.ts +3 -3
  59. package/src/tool/cssToInlineConverter/seo.astro +2 -1
  60. package/src/tool/duplicateCssRemover/duplicate-css-remover.css +2 -2
  61. package/src/tool/duplicateCssRemover/i18n/de.ts +7 -7
  62. package/src/tool/duplicateCssRemover/i18n/fr.ts +1 -1
  63. package/src/tool/duplicateCssRemover/i18n/id.ts +1 -1
  64. package/src/tool/duplicateCssRemover/i18n/nl.ts +1 -1
  65. package/src/tool/duplicateCssRemover/i18n/pl.ts +1 -1
  66. package/src/tool/duplicateCssRemover/i18n/pt.ts +1 -1
  67. package/src/tool/duplicateCssRemover/i18n/ru.ts +3 -3
  68. package/src/tool/duplicateCssRemover/i18n/sv.ts +1 -1
  69. package/src/tool/duplicateCssRemover/seo.astro +2 -1
  70. package/src/tool/generadorSecurityTxt/i18n/de.ts +5 -5
  71. package/src/tool/generadorSecurityTxt/i18n/ru.ts +2 -2
  72. package/src/tool/generadorSecurityTxt/security-txt-generator-rfc-9116.css +9 -9
  73. package/src/tool/generadorSecurityTxt/seo.astro +2 -1
  74. package/src/tool/hashGenerator/hash-generator.css +10 -10
  75. package/src/tool/hashGenerator/i18n/ru.ts +5 -5
  76. package/src/tool/hashGenerator/i18n/zh.ts +2 -2
  77. package/src/tool/hashGenerator/seo.astro +2 -1
  78. package/src/tool/inspectorCertificadosSsl/i18n/de.ts +6 -6
  79. package/src/tool/inspectorCertificadosSsl/i18n/ru.ts +5 -5
  80. package/src/tool/inspectorCertificadosSsl/seo.astro +2 -1
  81. package/src/tool/inspectorCertificadosSsl/ssl-tls-certificate-inspector.css +9 -9
  82. package/src/tool/jsonFormatter/i18n/de.ts +4 -4
  83. package/src/tool/jsonFormatter/i18n/en.ts +4 -4
  84. package/src/tool/jsonFormatter/i18n/es.ts +4 -4
  85. package/src/tool/jsonFormatter/i18n/fr.ts +4 -4
  86. package/src/tool/jsonFormatter/i18n/id.ts +4 -4
  87. package/src/tool/jsonFormatter/i18n/it.ts +4 -4
  88. package/src/tool/jsonFormatter/i18n/ja.ts +4 -4
  89. package/src/tool/jsonFormatter/i18n/ko.ts +4 -4
  90. package/src/tool/jsonFormatter/i18n/nl.ts +4 -4
  91. package/src/tool/jsonFormatter/i18n/pl.ts +4 -4
  92. package/src/tool/jsonFormatter/i18n/pt.ts +4 -4
  93. package/src/tool/jsonFormatter/i18n/ru.ts +5 -5
  94. package/src/tool/jsonFormatter/i18n/sv.ts +4 -4
  95. package/src/tool/jsonFormatter/i18n/tr.ts +4 -4
  96. package/src/tool/jsonFormatter/i18n/zh.ts +5 -5
  97. package/src/tool/jsonFormatter/json-formatter.css +33 -33
  98. package/src/tool/jsonFormatter/seo.astro +2 -1
  99. package/src/tool/keycode/i18n/de.ts +7 -7
  100. package/src/tool/keycode/i18n/en.ts +5 -5
  101. package/src/tool/keycode/i18n/es.ts +5 -5
  102. package/src/tool/keycode/i18n/fr.ts +7 -7
  103. package/src/tool/keycode/i18n/id.ts +5 -5
  104. package/src/tool/keycode/i18n/it.ts +5 -5
  105. package/src/tool/keycode/i18n/ja.ts +5 -5
  106. package/src/tool/keycode/i18n/ko.ts +5 -5
  107. package/src/tool/keycode/i18n/nl.ts +5 -5
  108. package/src/tool/keycode/i18n/pl.ts +7 -7
  109. package/src/tool/keycode/i18n/pt.ts +5 -5
  110. package/src/tool/keycode/i18n/ru.ts +6 -6
  111. package/src/tool/keycode/i18n/sv.ts +5 -5
  112. package/src/tool/keycode/i18n/tr.ts +5 -5
  113. package/src/tool/keycode/i18n/zh.ts +5 -5
  114. package/src/tool/keycode/keycode.css +1 -1
  115. package/src/tool/keycode/seo.astro +2 -1
  116. package/src/tool/llmCostCalculator/i18n/de.ts +4 -4
  117. package/src/tool/llmCostCalculator/i18n/en.ts +3 -3
  118. package/src/tool/llmCostCalculator/i18n/fr.ts +3 -3
  119. package/src/tool/llmCostCalculator/i18n/id.ts +3 -3
  120. package/src/tool/llmCostCalculator/i18n/pt.ts +3 -3
  121. package/src/tool/llmCostCalculator/i18n/ru.ts +3 -3
  122. package/src/tool/llmCostCalculator/i18n/sv.ts +3 -3
  123. package/src/tool/llmCostCalculator/i18n/tr.ts +3 -3
  124. package/src/tool/llmCostCalculator/i18n/zh.ts +3 -3
  125. package/src/tool/llmCostCalculator/llm-cost-calculator.css +1 -1
  126. package/src/tool/llmCostCalculator/seo.astro +2 -1
  127. package/src/tool/mobileMockupGenerator/i18n/es.ts +1 -1
  128. package/src/tool/mobileMockupGenerator/mobile-mockup-generator.css +68 -68
  129. package/src/tool/mobileMockupGenerator/seo.astro +2 -1
  130. package/src/tool/musicalTypography/i18n/de.ts +1 -1
  131. package/src/tool/musicalTypography/i18n/fr.ts +1 -1
  132. package/src/tool/musicalTypography/i18n/id.ts +1 -1
  133. package/src/tool/musicalTypography/i18n/it.ts +1 -1
  134. package/src/tool/musicalTypography/i18n/ko.ts +1 -1
  135. package/src/tool/musicalTypography/i18n/ru.ts +3 -3
  136. package/src/tool/musicalTypography/musical-typography.css +8 -8
  137. package/src/tool/musicalTypography/seo.astro +2 -1
  138. package/src/tool/placeholderGenerator/i18n/de.ts +4 -4
  139. package/src/tool/placeholderGenerator/i18n/ru.ts +1 -1
  140. package/src/tool/placeholderGenerator/placeholder-image-generator.css +2 -2
  141. package/src/tool/placeholderGenerator/seo.astro +2 -1
  142. package/src/tool/promptLibrary/i18n/de.ts +1 -1
  143. package/src/tool/promptLibrary/prompt-library.css +30 -30
  144. package/src/tool/promptLibrary/seo.astro +2 -1
  145. package/src/tool/readabilityCalculator/i18n/de.ts +2 -2
  146. package/src/tool/readabilityCalculator/seo.astro +2 -1
  147. package/src/tool/readabilityCalculator/visual-readability-calculator-wcag-apca.css +98 -14
  148. package/src/tool/svgSanitizer/i18n/de.ts +2 -2
  149. package/src/tool/svgSanitizer/i18n/id.ts +1 -1
  150. package/src/tool/svgSanitizer/i18n/pl.ts +1 -1
  151. package/src/tool/svgSanitizer/i18n/ru.ts +7 -7
  152. package/src/tool/svgSanitizer/i18n/sv.ts +3 -3
  153. package/src/tool/svgSanitizer/i18n/tr.ts +3 -3
  154. package/src/tool/svgSanitizer/i18n/zh.ts +3 -3
  155. package/src/tool/svgSanitizer/seo.astro +2 -1
  156. package/src/tool/svgSanitizer/svg-sanitizer.css +7 -7
  157. package/src/tool/svgToCss/i18n/de.ts +2 -2
  158. package/src/tool/svgToCss/i18n/es.ts +1 -1
  159. package/src/tool/svgToCss/i18n/fr.ts +1 -1
  160. package/src/tool/svgToCss/i18n/pl.ts +1 -1
  161. package/src/tool/svgToCss/i18n/ru.ts +2 -2
  162. package/src/tool/svgToCss/i18n/zh.ts +2 -2
  163. package/src/tool/svgToCss/seo.astro +2 -1
  164. package/src/tool/svgToCss/svg-to-css-converter.css +2 -2
  165. package/src/tool/urlCleaner/component.astro +23 -5
  166. package/src/tool/urlCleaner/i18n/de.ts +3 -3
  167. package/src/tool/urlCleaner/i18n/es.ts +1 -1
  168. package/src/tool/urlCleaner/i18n/id.ts +1 -1
  169. package/src/tool/urlCleaner/i18n/nl.ts +1 -1
  170. package/src/tool/urlCleaner/seo.astro +2 -1
  171. package/src/tool/urlCleaner/url-tracking-cleaner.css +104 -14
  172. package/src/tool/urlEncoderDecoder/i18n/de.ts +5 -5
  173. package/src/tool/urlEncoderDecoder/i18n/fr.ts +2 -2
  174. package/src/tool/urlEncoderDecoder/i18n/pl.ts +5 -5
  175. package/src/tool/urlEncoderDecoder/i18n/ru.ts +8 -8
  176. package/src/tool/urlEncoderDecoder/i18n/sv.ts +5 -5
  177. package/src/tool/urlEncoderDecoder/i18n/zh.ts +5 -5
  178. package/src/tool/urlEncoderDecoder/seo.astro +2 -1
  179. package/src/tool/urlEncoderDecoder/url-encoder-decoder.css +1 -1
  180. package/src/tool/utmGenerator/i18n/de.ts +2 -2
  181. package/src/tool/utmGenerator/i18n/pl.ts +5 -5
  182. package/src/tool/utmGenerator/i18n/ru.ts +6 -6
  183. package/src/tool/utmGenerator/seo.astro +2 -1
  184. package/src/tool/utmGenerator/utm-generator.css +6 -6
@@ -41,7 +41,7 @@
41
41
  border-color: rgb(254, 202, 202);
42
42
  }
43
43
 
44
- :global(.theme-dark) .mmg-btn-clear {
44
+ .theme-dark .mmg-btn-clear {
45
45
  background: rgb(15, 23, 42);
46
46
  border-color: rgb(30, 41, 59);
47
47
  color: rgb(148, 163, 184);
@@ -68,7 +68,7 @@
68
68
  transform: translateY(-1px);
69
69
  }
70
70
 
71
- :global(.theme-dark) .mmg-btn-download {
71
+ .theme-dark .mmg-btn-download {
72
72
  background: #fff;
73
73
  color: rgb(15, 23, 42);
74
74
  }
@@ -100,7 +100,7 @@
100
100
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
101
101
  }
102
102
 
103
- :global(.theme-dark) .mmg-card {
103
+ .theme-dark .mmg-card {
104
104
  background: rgba(15, 23, 42, 0.7);
105
105
  border-color: rgb(30, 41, 59);
106
106
  }
@@ -123,7 +123,7 @@
123
123
  margin-bottom: 1rem;
124
124
  }
125
125
 
126
- :global(.theme-dark) .mmg-card-title {
126
+ .theme-dark .mmg-card-title {
127
127
  color: #fff;
128
128
  }
129
129
 
@@ -148,7 +148,7 @@
148
148
  background: rgba(99, 102, 241, 0.05);
149
149
  }
150
150
 
151
- :global(.theme-dark) .mmg-drop-zone {
151
+ .theme-dark .mmg-drop-zone {
152
152
  border-color: rgb(51, 65, 85);
153
153
  }
154
154
 
@@ -186,7 +186,7 @@
186
186
  margin-top: 0.25rem;
187
187
  }
188
188
 
189
- :global(.theme-dark) .mmg-drop-hint {
189
+ .theme-dark .mmg-drop-hint {
190
190
  color: rgb(203, 213, 225);
191
191
  }
192
192
 
@@ -217,7 +217,7 @@
217
217
  background: rgb(254, 243, 199);
218
218
  }
219
219
 
220
- :global(.theme-dark) .mmg-btn-mass {
220
+ .theme-dark .mmg-btn-mass {
221
221
  background: rgba(180, 83, 9, 0.1);
222
222
  border-color: rgba(180, 83, 9, 0.5);
223
223
  color: rgb(252, 211, 77);
@@ -283,12 +283,12 @@
283
283
  transform: translateY(-1px);
284
284
  }
285
285
 
286
- :global(.theme-dark) .mmg-device-btn {
286
+ .theme-dark .mmg-device-btn {
287
287
  background: rgb(15, 23, 42);
288
288
  color: rgb(203, 213, 225);
289
289
  }
290
290
 
291
- :global(.theme-dark) .mmg-device-active {
291
+ .theme-dark .mmg-device-active {
292
292
  background: rgba(79, 70, 229, 0.2);
293
293
  border-color: rgb(129, 140, 248);
294
294
  }
@@ -314,7 +314,7 @@
314
314
  border-color: rgb(99, 102, 241);
315
315
  }
316
316
 
317
- :global(.theme-dark) .mmg-select {
317
+ .theme-dark .mmg-select {
318
318
  background: rgb(2, 6, 23);
319
319
  border-color: rgb(30, 41, 59);
320
320
  color: #fff;
@@ -363,7 +363,7 @@
363
363
  background: rgb(241, 245, 249);
364
364
  }
365
365
 
366
- :global(.theme-dark) .mmg-swap-btn:hover {
366
+ .theme-dark .mmg-swap-btn:hover {
367
367
  background: rgb(30, 41, 59);
368
368
  }
369
369
 
@@ -397,7 +397,7 @@
397
397
  accent-color: rgb(99, 102, 241);
398
398
  }
399
399
 
400
- :global(.theme-dark) .mmg-range {
400
+ .theme-dark .mmg-range {
401
401
  background: rgb(30, 41, 59);
402
402
  }
403
403
 
@@ -415,7 +415,7 @@
415
415
  border-top: 1px solid rgb(241, 245, 249);
416
416
  }
417
417
 
418
- :global(.theme-dark) .mmg-safe-section {
418
+ .theme-dark .mmg-safe-section {
419
419
  border-color: rgba(30, 41, 59, 0.5);
420
420
  }
421
421
 
@@ -483,7 +483,7 @@
483
483
  border: 2px dashed rgb(226, 232, 240);
484
484
  }
485
485
 
486
- :global(.theme-dark) .mmg-empty {
486
+ .theme-dark .mmg-empty {
487
487
  background: rgba(15, 23, 42, 0.5);
488
488
  border-color: rgb(30, 41, 59);
489
489
  }
@@ -499,7 +499,7 @@
499
499
  margin-bottom: 1.5rem;
500
500
  }
501
501
 
502
- :global(.theme-dark) .mmg-empty-icon-wrap {
502
+ .theme-dark .mmg-empty-icon-wrap {
503
503
  background: rgba(79, 70, 229, 0.3);
504
504
  }
505
505
 
@@ -509,7 +509,7 @@
509
509
  color: rgb(99, 102, 241);
510
510
  }
511
511
 
512
- :global(.theme-dark) .mmg-empty-icon-svg {
512
+ .theme-dark .mmg-empty-icon-svg {
513
513
  color: rgb(129, 140, 248);
514
514
  }
515
515
 
@@ -524,7 +524,7 @@
524
524
  margin-top: 0.5rem;
525
525
  }
526
526
 
527
- :global(.theme-dark) .mmg-empty-title {
527
+ .theme-dark .mmg-empty-title {
528
528
  color: #fff;
529
529
  }
530
530
 
@@ -540,7 +540,7 @@
540
540
  }
541
541
  }
542
542
 
543
- :global(.mmg-preview-card) {
543
+ .mmg-preview-card {
544
544
  background: rgba(255, 255, 255, 0.7);
545
545
  backdrop-filter: blur(10px);
546
546
  border-radius: 2.5rem;
@@ -550,12 +550,12 @@
550
550
  position: relative;
551
551
  }
552
552
 
553
- :global(.theme-dark) :global(.mmg-preview-card) {
553
+ .theme-dark .mmg-preview-card {
554
554
  background: rgba(15, 23, 42, 0.7);
555
555
  border-color: rgb(30, 41, 59);
556
556
  }
557
557
 
558
- :global(.mmg-card-actions) {
558
+ .mmg-card-actions {
559
559
  position: absolute;
560
560
  top: 1rem;
561
561
  right: 1rem;
@@ -566,11 +566,11 @@
566
566
  z-index: 10;
567
567
  }
568
568
 
569
- :global(.mmg-preview-card:hover) :global(.mmg-card-actions) {
569
+ .mmg-preview-card:hover .mmg-card-actions {
570
570
  opacity: 1;
571
571
  }
572
572
 
573
- :global(.mmg-card-action-btn) {
573
+ .mmg-card-action-btn {
574
574
  padding: 0.5rem;
575
575
  background: #fff;
576
576
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
@@ -581,23 +581,23 @@
581
581
  display: flex;
582
582
  }
583
583
 
584
- :global(.mmg-card-action-btn:hover) {
584
+ .mmg-card-action-btn:hover {
585
585
  transform: scale(1.1);
586
586
  }
587
587
 
588
- :global(.theme-dark) :global(.mmg-card-action-btn) {
588
+ .theme-dark .mmg-card-action-btn {
589
589
  background: rgb(15, 23, 42);
590
590
  }
591
591
 
592
- :global(.mmg-duplicate-img) {
592
+ .mmg-duplicate-img {
593
593
  color: rgb(99, 102, 241);
594
594
  }
595
595
 
596
- :global(.mmg-replace-img) {
596
+ .mmg-replace-img {
597
597
  color: rgb(217, 119, 6);
598
598
  }
599
599
 
600
- :global(.mmg-canvas-wrap) {
600
+ .mmg-canvas-wrap {
601
601
  aspect-ratio: 9/16;
602
602
  background: rgb(241, 245, 249);
603
603
  border-radius: 1.5rem;
@@ -606,42 +606,42 @@
606
606
  outline: 1px solid rgb(226, 232, 240);
607
607
  }
608
608
 
609
- :global(.theme-dark) :global(.mmg-canvas-wrap) {
609
+ .theme-dark .mmg-canvas-wrap {
610
610
  background: rgba(15, 23, 42, 0.5);
611
611
  outline-color: rgb(30, 41, 59);
612
612
  }
613
613
 
614
- :global(.mmg-canvas) {
614
+ .mmg-canvas {
615
615
  width: 100%;
616
616
  height: 100%;
617
617
  object-fit: contain;
618
618
  display: block;
619
619
  }
620
620
 
621
- :global(.mmg-card-body) {
621
+ .mmg-card-body {
622
622
  margin-top: 1.5rem;
623
623
  display: flex;
624
624
  flex-direction: column;
625
625
  gap: 1.5rem;
626
626
  }
627
627
 
628
- :global(.mmg-section) {
628
+ .mmg-section {
629
629
  padding-top: 1rem;
630
630
  border-top: 1px solid rgb(241, 245, 249);
631
631
  }
632
632
 
633
- :global(.theme-dark) :global(.mmg-section) {
633
+ .theme-dark .mmg-section {
634
634
  border-color: rgba(30, 41, 59, 0.5);
635
635
  }
636
636
 
637
- :global(.mmg-section-head) {
637
+ .mmg-section-head {
638
638
  display: flex;
639
639
  align-items: center;
640
640
  justify-content: space-between;
641
641
  margin-bottom: 0.75rem;
642
642
  }
643
643
 
644
- :global(.mmg-section-label) {
644
+ .mmg-section-label {
645
645
  font-size: 0.625rem;
646
646
  font-weight: 900;
647
647
  text-transform: uppercase;
@@ -649,7 +649,7 @@
649
649
  color: rgb(148, 163, 184);
650
650
  }
651
651
 
652
- :global(.mmg-reset-btn) {
652
+ .mmg-reset-btn {
653
653
  padding: 0.375rem;
654
654
  color: rgb(148, 163, 184);
655
655
  border: none;
@@ -660,22 +660,22 @@
660
660
  display: flex;
661
661
  }
662
662
 
663
- :global(.mmg-reset-btn:hover) {
663
+ .mmg-reset-btn:hover {
664
664
  color: rgb(99, 102, 241);
665
665
  background: rgb(238, 242, 255);
666
666
  }
667
667
 
668
- :global(.theme-dark) :global(.mmg-reset-btn:hover) {
668
+ .theme-dark .mmg-reset-btn:hover {
669
669
  background: rgba(99, 102, 241, 0.3);
670
670
  }
671
671
 
672
- :global(.mmg-presets-grid) {
672
+ .mmg-presets-grid {
673
673
  display: grid;
674
674
  grid-template-columns: repeat(3, 1fr);
675
675
  gap: 0.5rem;
676
676
  }
677
677
 
678
- :global(.mmg-preset-btn) {
678
+ .mmg-preset-btn {
679
679
  padding: 0.625rem 0.5rem;
680
680
  font-size: 0.5625rem;
681
681
  font-weight: 900;
@@ -690,33 +690,33 @@
690
690
  line-height: 1.2;
691
691
  }
692
692
 
693
- :global(.mmg-preset-btn:hover) {
693
+ .mmg-preset-btn:hover {
694
694
  background: rgb(241, 245, 249);
695
695
  border-color: rgb(199, 210, 254);
696
696
  color: rgb(79, 70, 229);
697
697
  }
698
698
 
699
- :global(.mmg-preset-btn:active) {
699
+ .mmg-preset-btn:active {
700
700
  transform: scale(0.95);
701
701
  }
702
702
 
703
- :global(.theme-dark) :global(.mmg-preset-btn) {
703
+ .theme-dark .mmg-preset-btn {
704
704
  background: rgb(15, 23, 42);
705
705
  border-color: rgb(30, 41, 59);
706
706
  color: rgb(148, 163, 184);
707
707
  }
708
708
 
709
- :global(.theme-dark) :global(.mmg-preset-btn:hover) {
709
+ .theme-dark .mmg-preset-btn:hover {
710
710
  background: rgba(79, 70, 229, 0.2);
711
711
  border-color: rgba(99, 102, 241, 0.5);
712
712
  color: rgb(129, 140, 248);
713
713
  }
714
714
 
715
- :global(.mmg-color-row) {
715
+ .mmg-color-row {
716
716
  margin-bottom: 0.75rem;
717
717
  }
718
718
 
719
- :global(.mmg-color-sublabel) {
719
+ .mmg-color-sublabel {
720
720
  display: block;
721
721
  font-size: 0.625rem;
722
722
  font-weight: 700;
@@ -727,7 +727,7 @@
727
727
  margin-left: 0.25rem;
728
728
  }
729
729
 
730
- :global(.mmg-color-field) {
730
+ .mmg-color-field {
731
731
  display: flex;
732
732
  align-items: center;
733
733
  gap: 0.75rem;
@@ -737,12 +737,12 @@
737
737
  border-radius: 1rem;
738
738
  }
739
739
 
740
- :global(.theme-dark) :global(.mmg-color-field) {
740
+ .theme-dark .mmg-color-field {
741
741
  background: rgb(2, 6, 23);
742
742
  border-color: rgb(30, 41, 59);
743
743
  }
744
744
 
745
- :global(.mmg-color-input) {
745
+ .mmg-color-input {
746
746
  width: 1.5rem;
747
747
  height: 1.5rem;
748
748
  border-radius: 0.5rem;
@@ -751,17 +751,17 @@
751
751
  cursor: pointer;
752
752
  }
753
753
 
754
- :global(.mmg-color-hex) {
754
+ .mmg-color-hex {
755
755
  font-size: 0.75rem;
756
756
  font-weight: 700;
757
757
  color: rgb(71, 85, 105);
758
758
  }
759
759
 
760
- :global(.theme-dark) :global(.mmg-color-hex) {
760
+ .theme-dark .mmg-color-hex {
761
761
  color: rgb(148, 163, 184);
762
762
  }
763
763
 
764
- :global(.mmg-textarea) {
764
+ .mmg-textarea {
765
765
  width: 100%;
766
766
  padding: 0.75rem 1rem;
767
767
  background: rgb(248, 250, 252);
@@ -777,29 +777,29 @@
777
777
  color: rgb(15, 23, 42);
778
778
  }
779
779
 
780
- :global(.mmg-textarea:focus) {
780
+ .mmg-textarea:focus {
781
781
  border-color: rgb(99, 102, 241);
782
782
  }
783
783
 
784
- :global(.theme-dark) :global(.mmg-textarea) {
784
+ .theme-dark .mmg-textarea {
785
785
  background: rgb(2, 6, 23);
786
786
  border-color: rgb(30, 41, 59);
787
787
  color: #fff;
788
788
  }
789
789
 
790
- :global(.mmg-range-grid) {
790
+ .mmg-range-grid {
791
791
  display: grid;
792
792
  grid-template-columns: 1fr 1fr;
793
793
  gap: 1rem 1.5rem;
794
794
  }
795
795
 
796
- :global(.mmg-range-item) {
796
+ .mmg-range-item {
797
797
  display: flex;
798
798
  flex-direction: column;
799
799
  gap: 0.25rem;
800
800
  }
801
801
 
802
- :global(.mmg-range-row) {
802
+ .mmg-range-row {
803
803
  display: flex;
804
804
  justify-content: space-between;
805
805
  font-size: 0.5625rem;
@@ -809,12 +809,12 @@
809
809
  color: rgb(148, 163, 184);
810
810
  }
811
811
 
812
- :global(.mmg-scene-row) {
812
+ .mmg-scene-row {
813
813
  display: flex;
814
814
  gap: 0.5rem;
815
815
  }
816
816
 
817
- :global(.mmg-scene-btn) {
817
+ .mmg-scene-btn {
818
818
  flex: 1;
819
819
  display: flex;
820
820
  align-items: center;
@@ -833,17 +833,17 @@
833
833
  transition: all 0.2s;
834
834
  }
835
835
 
836
- :global(.mmg-scene-btn:hover) {
836
+ .mmg-scene-btn:hover {
837
837
  background: rgb(224, 231, 255);
838
838
  }
839
839
 
840
- :global(.theme-dark) :global(.mmg-scene-btn) {
840
+ .theme-dark .mmg-scene-btn {
841
841
  background: rgba(79, 70, 229, 0.2);
842
842
  border-color: rgba(99, 102, 241, 0.5);
843
843
  color: rgb(129, 140, 248);
844
844
  }
845
845
 
846
- :global(.mmg-clear-bg-btn) {
846
+ .mmg-clear-bg-btn {
847
847
  display: flex;
848
848
  align-items: center;
849
849
  justify-content: center;
@@ -856,16 +856,16 @@
856
856
  transition: all 0.2s;
857
857
  }
858
858
 
859
- :global(.mmg-clear-bg-btn:hover) {
859
+ .mmg-clear-bg-btn:hover {
860
860
  background: rgb(254, 226, 226);
861
861
  }
862
862
 
863
- :global(.theme-dark) :global(.mmg-clear-bg-btn) {
863
+ .theme-dark .mmg-clear-bg-btn {
864
864
  background: rgba(239, 68, 68, 0.2);
865
865
  border-color: rgba(239, 68, 68, 0.5);
866
866
  }
867
867
 
868
- :global(.mmg-delete-btn) {
868
+ .mmg-delete-btn {
869
869
  width: 100%;
870
870
  padding: 0.75rem;
871
871
  font-size: 0.625rem;
@@ -880,16 +880,16 @@
880
880
  transition: all 0.2s;
881
881
  }
882
882
 
883
- :global(.mmg-delete-btn:hover) {
883
+ .mmg-delete-btn:hover {
884
884
  color: rgb(239, 68, 68);
885
885
  background: rgb(254, 242, 242);
886
886
  }
887
887
 
888
- :global(.theme-dark) :global(.mmg-delete-btn:hover) {
888
+ .theme-dark .mmg-delete-btn:hover {
889
889
  background: rgba(239, 68, 68, 0.2);
890
890
  }
891
891
 
892
- :global(.mmg-preset-swatch) {
892
+ .mmg-preset-swatch {
893
893
  width: 100%;
894
894
  aspect-ratio: 1;
895
895
  border-radius: 0.5rem;
@@ -899,6 +899,6 @@
899
899
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
900
900
  }
901
901
 
902
- :global(.mmg-preset-swatch:hover) {
902
+ .mmg-preset-swatch:hover {
903
903
  transform: scale(1.1);
904
904
  }
@@ -9,6 +9,7 @@ interface Props {
9
9
 
10
10
  const { locale = 'es' } = Astro.props;
11
11
  const content = await mobileMockupGenerator.i18n[locale]?.();
12
+ if (!content) return null;
12
13
  ---
13
14
 
14
- {content && <SEORenderer content={{ locale, sections: content.seo }} />}
15
+ {content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
@@ -160,7 +160,7 @@ export const content: ToolLocaleContent<MusicalTypographyUI> = {
160
160
  {
161
161
  type: 'card',
162
162
  title: 'Warum "Musikalisch"',
163
- html: '<p>Die Pythagoreer entdeckten, dass das Teilen einer Saite in einfache Proportionen (1:2, 2:3, 3:4) Konsonanz erzeugt. Diese Intervalle Oktave, reine Quinte und reine Quarte sind genau die typografischen Ratios. Du komponierst visuelle Musik.</p>',
163
+ html: '<p>Die Pythagoreer entdeckten, dass das Teilen einer Saite in einfache Proportionen (1:2, 2:3, 3:4) Konsonanz erzeugt. Diese Intervalle - Oktave, reine Quinte und reine Quarte - sind genau die typografischen Ratios. Du komponierst visuelle Musik.</p>',
164
164
  },
165
165
  {
166
166
  type: 'title',
@@ -155,7 +155,7 @@ export const content: ToolLocaleContent<MusicalTypographyUI> = {
155
155
  {
156
156
  type: 'card',
157
157
  title: 'La formule',
158
- html: '<p>La progression est simple : <code>Taille = Base × Ratio<sup>n</sup></code>. L\'étape 0 est votre texte de base. L\'étape 1 est un petit sous-titre. L\'étape 4 ou 5 pourrait être votre H1 principal. La même constante multiplicative garantit que toutes les relations sont cohérentes.</p>',
158
+ html: '<p>La progression est simple: <code>Taille = Base × Ratio<sup>n</sup></code>. L\'étape 0 est votre texte de base. L\'étape 1 est un petit sous-titre. L\'étape 4 ou 5 pourrait être votre H1 principal. La même constante multiplicative garantit que toutes les relations sont cohérentes.</p>',
159
159
  },
160
160
  {
161
161
  type: 'card',
@@ -160,7 +160,7 @@ export const content: ToolLocaleContent<MusicalTypographyUI> = {
160
160
  {
161
161
  type: 'card',
162
162
  title: 'Mengapa "Musikal"',
163
- html: '<p>Kaum Pythagoras menemukan bahwa membagi senar dalam proporsi sederhana (1:2, 2:3, 3:4) menghasilkan bunyi yang konsonan. Interval-interval ini oktaf, kuint sempurna, dan kuart sempurna adalah persis rasio tipografi yang digunakan. Anda sedang menggubah musik visual.</p>',
163
+ html: '<p>Kaum Pythagoras menemukan bahwa membagi senar dalam proporsi sederhana (1:2, 2:3, 3:4) menghasilkan bunyi yang konsonan. Interval-interval ini - oktaf, kuint sempurna, dan kuart sempurna - adalah persis rasio tipografi yang digunakan. Anda sedang menggubah musik visual.</p>',
164
164
  },
165
165
  {
166
166
  type: 'title',
@@ -160,7 +160,7 @@ export const content: ToolLocaleContent<MusicalTypographyUI> = {
160
160
  {
161
161
  type: 'card',
162
162
  title: 'Perché "Musicale"',
163
- html: "<p>I pitagorici scoprirono che dividere una corda in proporzioni semplici (1:2, 2:3, 3:4) produceva suoni consonanti. Questi intervalli ottava, quinta giusta e quarta giusta sono esattamente i rapporti tipografici. Stai componendo musica visiva.</p>",
163
+ html: "<p>I pitagorici scoprirono che dividere una corda in proporzioni semplici (1:2, 2:3, 3:4) produceva suoni consonanti. Questi intervalli - ottava, quinta giusta e quarta giusta - sono esattamente i rapporti tipografici. Stai componendo musica visiva.</p>",
164
164
  },
165
165
  {
166
166
  type: 'title',
@@ -160,7 +160,7 @@ export const content: ToolLocaleContent<MusicalTypographyUI> = {
160
160
  {
161
161
  type: 'card',
162
162
  title: '왜 "음악적"인가',
163
- html: '<p>피타고라스학파는 현을 단순한 비율(1:2, 2:3, 3:4)로 나누면 협화음이 생긴다는 것을 발견했습니다. 옥타브, 완전5도, 완전4도 이 음정들이 바로 타이포그래피 비율과 정확히 일치합니다. 당신은 시각적 음악을 작곡하고 있는 것입니다.</p>',
163
+ html: '<p>피타고라스학파는 현을 단순한 비율(1:2, 2:3, 3:4)로 나누면 협화음이 생긴다는 것을 발견했습니다. 옥타브, 완전5도, 완전4도 - 이 음정들이 바로 타이포그래피 비율과 정확히 일치합니다. 당신은 시각적 음악을 작곡하고 있는 것입니다.</p>',
164
164
  },
165
165
  {
166
166
  type: 'title',
@@ -8,7 +8,7 @@ const description = 'Бесплатный онлайн-инструмент дл
8
8
 
9
9
  const faqData = [
10
10
  { question: 'Что такое типографическая модульная шкала?', answer: 'Это метод определения размеров шрифтов на основе постоянного математического соотношения. Подобно музыке, где ноты имеют гармонические отношения, модульная шкала создаёт сбалансированную и предсказуемую визуальную иерархию.' },
11
- { question: 'Почему использовать музыкальные интервалы для дизайна?', answer: 'Музыкальные интервалы это пропорции, которые человеческий мозг воспринимает как гармоничные. Применение их к размерам текста создаёт визуальную структуру, которая ощущается правильной и профессиональной, а не случайно выбранной.' },
11
+ { question: 'Почему использовать музыкальные интервалы для дизайна?', answer: 'Музыкальные интервалы - это пропорции, которые человеческий мозг воспринимает как гармоничные. Применение их к размерам текста создаёт визуальную структуру, которая ощущается правильной и профессиональной, а не случайно выбранной.' },
12
12
  { question: 'Что такое Золотое Сечение в типографии?', answer: 'Это пропорция 1.618, известная как Золотое Сечение. Она создаёт очень драматичные и элегантные шкалы, где каждый шаг иерархии растёт экспоненциально. Идеально для портфолио или сайтов, ориентированных на искусство.' },
13
13
  { question: 'Как я могу применить шкалу в своём файле CSS?', answer: 'Инструмент генерирует CSS-переменные (токены) в формате :root { --step-N: Xrem; }. Скопируйте их в свой основной CSS-файл и используйте с var(--step-N), чтобы сохранить типографическую согласованность на всём сайте.' },
14
14
  ];
@@ -38,8 +38,8 @@ export const content: ToolLocaleContent<MusicalTypographyUI> = {
38
38
  { type: 'paragraph', html: '<strong>Музыкальная Типографическая Шкала</strong> применяет математику музыкальных интервалов к типографическому дизайну. Подобно тому, как музыкальная композиция управляется точными пропорциями, хороший дизайн выигрывает от математической структуры, которая связывает все размеры вместе.' },
39
39
  { type: 'title', text: 'Как работает модульная шкала', level: 3 },
40
40
  { type: 'grid', columns: 2 },
41
- { type: 'card', title: 'Формула', html: '<p>Прогрессия простая: <code>Size = Base × Ratio<sup>n</sup></code>. Шаг 0 это ваш базовый текст. Шаг 1 маленький подзаголовок. Шаг 4 или 5 может быть вашим главным H1. Одна и та же постоянная умножения (соотношение) гарантирует, что все отношения согласованы.</p>' },
42
- { type: 'card', title: 'Почему "Музыкальная"', html: '<p>Пифагорейцы открыли, что деление струны на простые пропорции (1:2, 2:3, 3:4) производит созвучные звуки. Эти интервалы, октава, чистая квинта и чистая кварта, это ровно типографические соотношения. Вы сочиняете визуальную музыку.</p>' },
41
+ { type: 'card', title: 'Формула', html: '<p>Прогрессия простая: <code>Size = Base × Ratio<sup>n</sup></code>. Шаг 0 - это ваш базовый текст. Шаг 1 - маленький подзаголовок. Шаг 4 или 5 может быть вашим главным H1. Одна и та же постоянная умножения (соотношение) гарантирует, что все отношения согласованы.</p>' },
42
+ { type: 'card', title: 'Почему "Музыкальная"', html: '<p>Пифагорейцы открыли, что деление струны на простые пропорции (1:2, 2:3, 3:4) производит созвучные звуки. Эти интервалы, октава, чистая квинта и чистая кварта, - это ровно типографические соотношения. Вы сочиняете визуальную музыку.</p>' },
43
43
  { type: 'title', text: 'Выбор правильного соотношения', level: 3 },
44
44
  { type: 'tip', html: 'Для плотных интерфейсов (приборные панели, таблицы) используйте малые соотношения, такие как <code>1.125</code> или <code>1.2</code>. Для редакционных или портфельных сайтов используйте более выразительные соотношения, такие как <code>1.5</code> или <code>1.618</code>.' },
45
45
  { type: 'paragraph', html: 'Не ограничивайте шкалу только <code>font-size</code>. Те же CSS-переменные работают для <code>margin</code>, <code>padding</code> и <code>gap</code>. Когда белое пространство следует той же математической прогрессии, что и текст, дизайн достигает уровня связности, который все ощущают, но мало кто может объяснить.' },
@@ -16,7 +16,7 @@
16
16
  --mt-feedback-color: #059669;
17
17
  }
18
18
 
19
- :global(.theme-dark) .mt-root {
19
+ .theme-dark .mt-root {
20
20
  --mt-card-bg: #1e293b;
21
21
  --mt-border: #334155;
22
22
  --mt-text: #f1f5f9;
@@ -65,7 +65,7 @@
65
65
  background: rgba(236, 72, 153, 0.04);
66
66
  }
67
67
 
68
- :global(.theme-dark) .mt-card-header-preview {
68
+ .theme-dark .mt-card-header-preview {
69
69
  background: rgba(236, 72, 153, 0.08);
70
70
  }
71
71
 
@@ -168,7 +168,7 @@
168
168
  gap: 0.25rem;
169
169
  }
170
170
 
171
- :global(.mt-scale-row) {
171
+ .mt-scale-row {
172
172
  display: flex;
173
173
  justify-content: space-between;
174
174
  font-size: 0.8125rem;
@@ -176,7 +176,7 @@
176
176
  padding: 0.125rem 0;
177
177
  }
178
178
 
179
- :global(.mt-scale-base) {
179
+ .mt-scale-base {
180
180
  color: var(--mt-base-color);
181
181
  font-weight: 700;
182
182
  background: var(--mt-accent-bg);
@@ -217,12 +217,12 @@
217
217
  border-radius: 9999px;
218
218
  }
219
219
 
220
- :global(.mt-prev-item) {
220
+ .mt-prev-item {
221
221
  border-bottom: 1px solid var(--mt-border);
222
222
  padding-bottom: 1rem;
223
223
  }
224
224
 
225
- :global(.mt-prev-meta) {
225
+ .mt-prev-meta {
226
226
  display: flex;
227
227
  align-items: baseline;
228
228
  gap: 0.5rem;
@@ -231,7 +231,7 @@
231
231
  color: var(--mt-muted);
232
232
  }
233
233
 
234
- :global(.mt-prev-text) {
234
+ .mt-prev-text {
235
235
  font-weight: 700;
236
236
  color: var(--mt-text);
237
237
  white-space: nowrap;
@@ -240,7 +240,7 @@
240
240
  margin: 0;
241
241
  }
242
242
 
243
- :global(.mt-sub) {
243
+ .mt-sub {
244
244
  color: var(--mt-muted);
245
245
  margin: 0.25rem 0 0;
246
246
  white-space: nowrap;
@@ -9,6 +9,7 @@ interface Props {
9
9
 
10
10
  const { locale = 'es' } = Astro.props;
11
11
  const content = await musicalTypography.i18n[locale]?.();
12
+ if (!content) return null;
12
13
  ---
13
14
 
14
- {content && <SEORenderer content={{ locale, sections: content.seo }} />}
15
+ {content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}