@jjlmoya/utils-audiovisual 1.16.0 → 1.18.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 (234) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +2 -0
  3. package/src/entries.ts +4 -1
  4. package/src/index.ts +1 -0
  5. package/src/pages/[locale]/[slug].astro +28 -12
  6. package/src/tests/locale_completeness.test.ts +2 -36
  7. package/src/tests/shared-test-helpers.ts +56 -0
  8. package/src/tests/tool_exports.test.ts +34 -0
  9. package/src/tests/tool_validation.test.ts +2 -2
  10. package/src/tool/chromaticLens/bibliography.ts +12 -0
  11. package/src/tool/chromaticLens/chromatic-lens-color-palette-extraction-online.css +39 -39
  12. package/src/tool/chromaticLens/entry.ts +2 -0
  13. package/src/tool/chromaticLens/i18n/de.ts +1 -15
  14. package/src/tool/chromaticLens/i18n/en.ts +1 -15
  15. package/src/tool/chromaticLens/i18n/es.ts +1 -13
  16. package/src/tool/chromaticLens/i18n/fr.ts +1 -13
  17. package/src/tool/chromaticLens/i18n/id.ts +1 -15
  18. package/src/tool/chromaticLens/i18n/it.ts +1 -15
  19. package/src/tool/chromaticLens/i18n/ja.ts +1 -15
  20. package/src/tool/chromaticLens/i18n/ko.ts +1 -15
  21. package/src/tool/chromaticLens/i18n/nl.ts +1 -15
  22. package/src/tool/chromaticLens/i18n/pl.ts +1 -15
  23. package/src/tool/chromaticLens/i18n/pt.ts +1 -15
  24. package/src/tool/chromaticLens/i18n/ru.ts +1 -15
  25. package/src/tool/chromaticLens/i18n/sv.ts +1 -15
  26. package/src/tool/chromaticLens/i18n/tr.ts +1 -15
  27. package/src/tool/chromaticLens/i18n/zh.ts +1 -15
  28. package/src/tool/chromaticLens/seo.astro +1 -1
  29. package/src/tool/collageMaker/bibliography.ts +8 -0
  30. package/src/tool/collageMaker/entry.ts +2 -0
  31. package/src/tool/collageMaker/free-online-photo-collage-maker-professional-compositions.css +47 -47
  32. package/src/tool/collageMaker/i18n/de.ts +1 -11
  33. package/src/tool/collageMaker/i18n/en.ts +1 -11
  34. package/src/tool/collageMaker/i18n/es.ts +1 -9
  35. package/src/tool/collageMaker/i18n/fr.ts +1 -9
  36. package/src/tool/collageMaker/i18n/id.ts +1 -11
  37. package/src/tool/collageMaker/i18n/it.ts +1 -11
  38. package/src/tool/collageMaker/i18n/ja.ts +1 -11
  39. package/src/tool/collageMaker/i18n/ko.ts +1 -11
  40. package/src/tool/collageMaker/i18n/nl.ts +1 -11
  41. package/src/tool/collageMaker/i18n/pl.ts +1 -11
  42. package/src/tool/collageMaker/i18n/pt.ts +1 -11
  43. package/src/tool/collageMaker/i18n/ru.ts +1 -11
  44. package/src/tool/collageMaker/i18n/sv.ts +1 -11
  45. package/src/tool/collageMaker/i18n/tr.ts +1 -11
  46. package/src/tool/collageMaker/i18n/zh.ts +1 -11
  47. package/src/tool/collageMaker/seo.astro +1 -1
  48. package/src/tool/depthOfFieldCalculator/bibliography.astro +15 -0
  49. package/src/tool/depthOfFieldCalculator/bibliography.ts +20 -0
  50. package/src/tool/depthOfFieldCalculator/component.astro +341 -0
  51. package/src/tool/depthOfFieldCalculator/depth-of-field-calculator.css +417 -0
  52. package/src/tool/depthOfFieldCalculator/entry.ts +52 -0
  53. package/src/tool/depthOfFieldCalculator/i18n/de.ts +141 -0
  54. package/src/tool/depthOfFieldCalculator/i18n/en.ts +141 -0
  55. package/src/tool/depthOfFieldCalculator/i18n/es.ts +141 -0
  56. package/src/tool/depthOfFieldCalculator/i18n/fr.ts +141 -0
  57. package/src/tool/depthOfFieldCalculator/i18n/id.ts +141 -0
  58. package/src/tool/depthOfFieldCalculator/i18n/it.ts +141 -0
  59. package/src/tool/depthOfFieldCalculator/i18n/ja.ts +141 -0
  60. package/src/tool/depthOfFieldCalculator/i18n/ko.ts +141 -0
  61. package/src/tool/depthOfFieldCalculator/i18n/nl.ts +141 -0
  62. package/src/tool/depthOfFieldCalculator/i18n/pl.ts +141 -0
  63. package/src/tool/depthOfFieldCalculator/i18n/pt.ts +141 -0
  64. package/src/tool/depthOfFieldCalculator/i18n/ru.ts +141 -0
  65. package/src/tool/depthOfFieldCalculator/i18n/sv.ts +141 -0
  66. package/src/tool/depthOfFieldCalculator/i18n/tr.ts +141 -0
  67. package/src/tool/depthOfFieldCalculator/i18n/zh.ts +141 -0
  68. package/src/tool/depthOfFieldCalculator/index.ts +10 -0
  69. package/src/tool/depthOfFieldCalculator/logic.ts +91 -0
  70. package/src/tool/depthOfFieldCalculator/seo.astro +15 -0
  71. package/src/tool/exifCleaner/bibliography.ts +12 -0
  72. package/src/tool/exifCleaner/entry.ts +2 -0
  73. package/src/tool/exifCleaner/exif-metadata-cleaner-remove-gps-photo-privacy.css +36 -36
  74. package/src/tool/exifCleaner/i18n/de.ts +1 -15
  75. package/src/tool/exifCleaner/i18n/en.ts +1 -15
  76. package/src/tool/exifCleaner/i18n/es.ts +1 -15
  77. package/src/tool/exifCleaner/i18n/fr.ts +1 -15
  78. package/src/tool/exifCleaner/i18n/id.ts +1 -15
  79. package/src/tool/exifCleaner/i18n/it.ts +1 -15
  80. package/src/tool/exifCleaner/i18n/ja.ts +1 -15
  81. package/src/tool/exifCleaner/i18n/ko.ts +1 -15
  82. package/src/tool/exifCleaner/i18n/nl.ts +1 -15
  83. package/src/tool/exifCleaner/i18n/pl.ts +1 -15
  84. package/src/tool/exifCleaner/i18n/pt.ts +1 -15
  85. package/src/tool/exifCleaner/i18n/ru.ts +1 -15
  86. package/src/tool/exifCleaner/i18n/sv.ts +1 -15
  87. package/src/tool/exifCleaner/i18n/tr.ts +1 -15
  88. package/src/tool/exifCleaner/i18n/zh.ts +1 -15
  89. package/src/tool/exifCleaner/seo.astro +2 -5
  90. package/src/tool/imageCompressor/bibliography.ts +12 -0
  91. package/src/tool/imageCompressor/entry.ts +2 -0
  92. package/src/tool/imageCompressor/i18n/de.ts +1 -15
  93. package/src/tool/imageCompressor/i18n/en.ts +1 -15
  94. package/src/tool/imageCompressor/i18n/es.ts +1 -13
  95. package/src/tool/imageCompressor/i18n/fr.ts +1 -13
  96. package/src/tool/imageCompressor/i18n/id.ts +1 -15
  97. package/src/tool/imageCompressor/i18n/it.ts +1 -15
  98. package/src/tool/imageCompressor/i18n/ja.ts +1 -15
  99. package/src/tool/imageCompressor/i18n/ko.ts +1 -15
  100. package/src/tool/imageCompressor/i18n/nl.ts +1 -15
  101. package/src/tool/imageCompressor/i18n/pl.ts +1 -15
  102. package/src/tool/imageCompressor/i18n/pt.ts +1 -15
  103. package/src/tool/imageCompressor/i18n/ru.ts +1 -15
  104. package/src/tool/imageCompressor/i18n/sv.ts +1 -15
  105. package/src/tool/imageCompressor/i18n/tr.ts +1 -15
  106. package/src/tool/imageCompressor/i18n/zh.ts +1 -15
  107. package/src/tool/imageCompressor/online-image-compressor-reduce-file-size-no-quality-loss.css +71 -64
  108. package/src/tool/imageCompressor/seo.astro +1 -1
  109. package/src/tool/printQualityCalculator/bibliography.ts +12 -0
  110. package/src/tool/printQualityCalculator/entry.ts +2 -0
  111. package/src/tool/printQualityCalculator/i18n/de.ts +1 -15
  112. package/src/tool/printQualityCalculator/i18n/en.ts +1 -15
  113. package/src/tool/printQualityCalculator/i18n/es.ts +1 -13
  114. package/src/tool/printQualityCalculator/i18n/fr.ts +1 -13
  115. package/src/tool/printQualityCalculator/i18n/id.ts +1 -15
  116. package/src/tool/printQualityCalculator/i18n/it.ts +1 -15
  117. package/src/tool/printQualityCalculator/i18n/ja.ts +1 -15
  118. package/src/tool/printQualityCalculator/i18n/ko.ts +1 -15
  119. package/src/tool/printQualityCalculator/i18n/nl.ts +1 -15
  120. package/src/tool/printQualityCalculator/i18n/pl.ts +1 -15
  121. package/src/tool/printQualityCalculator/i18n/pt.ts +1 -15
  122. package/src/tool/printQualityCalculator/i18n/ru.ts +1 -15
  123. package/src/tool/printQualityCalculator/i18n/sv.ts +1 -15
  124. package/src/tool/printQualityCalculator/i18n/tr.ts +1 -15
  125. package/src/tool/printQualityCalculator/i18n/zh.ts +1 -15
  126. package/src/tool/printQualityCalculator/print-quality-calculator-pixels-to-cm-dpi.css +89 -81
  127. package/src/tool/printQualityCalculator/seo.astro +2 -5
  128. package/src/tool/privacyBlur/bibliography.ts +8 -0
  129. package/src/tool/privacyBlur/entry.ts +2 -0
  130. package/src/tool/privacyBlur/i18n/de.ts +1 -11
  131. package/src/tool/privacyBlur/i18n/en.ts +1 -11
  132. package/src/tool/privacyBlur/i18n/es.ts +1 -9
  133. package/src/tool/privacyBlur/i18n/fr.ts +1 -9
  134. package/src/tool/privacyBlur/i18n/id.ts +1 -11
  135. package/src/tool/privacyBlur/i18n/it.ts +1 -11
  136. package/src/tool/privacyBlur/i18n/ja.ts +1 -11
  137. package/src/tool/privacyBlur/i18n/ko.ts +1 -11
  138. package/src/tool/privacyBlur/i18n/nl.ts +1 -11
  139. package/src/tool/privacyBlur/i18n/pl.ts +1 -11
  140. package/src/tool/privacyBlur/i18n/pt.ts +1 -11
  141. package/src/tool/privacyBlur/i18n/ru.ts +1 -11
  142. package/src/tool/privacyBlur/i18n/sv.ts +1 -11
  143. package/src/tool/privacyBlur/i18n/tr.ts +1 -11
  144. package/src/tool/privacyBlur/i18n/zh.ts +1 -11
  145. package/src/tool/privacyBlur/online-privacy-editor-pixelate-blur-faces-photos.css +36 -36
  146. package/src/tool/privacyBlur/seo.astro +1 -1
  147. package/src/tool/subtitleSync/bibliography.ts +12 -0
  148. package/src/tool/subtitleSync/entry.ts +2 -0
  149. package/src/tool/subtitleSync/i18n/de.ts +1 -13
  150. package/src/tool/subtitleSync/i18n/en.ts +1 -13
  151. package/src/tool/subtitleSync/i18n/es.ts +1 -13
  152. package/src/tool/subtitleSync/i18n/fr.ts +1 -13
  153. package/src/tool/subtitleSync/i18n/id.ts +1 -13
  154. package/src/tool/subtitleSync/i18n/it.ts +1 -13
  155. package/src/tool/subtitleSync/i18n/ja.ts +1 -13
  156. package/src/tool/subtitleSync/i18n/ko.ts +1 -13
  157. package/src/tool/subtitleSync/i18n/nl.ts +1 -13
  158. package/src/tool/subtitleSync/i18n/pl.ts +1 -13
  159. package/src/tool/subtitleSync/i18n/pt.ts +1 -13
  160. package/src/tool/subtitleSync/i18n/ru.ts +1 -13
  161. package/src/tool/subtitleSync/i18n/sv.ts +1 -13
  162. package/src/tool/subtitleSync/i18n/tr.ts +1 -13
  163. package/src/tool/subtitleSync/i18n/zh.ts +1 -13
  164. package/src/tool/subtitleSync/seo.astro +1 -1
  165. package/src/tool/subtitleSync/synchronize-srt-subtitles-online-adjust-timing-free.css +43 -43
  166. package/src/tool/timelapseCalculator/bibliography.ts +20 -0
  167. package/src/tool/timelapseCalculator/entry.ts +2 -0
  168. package/src/tool/timelapseCalculator/i18n/de.ts +1 -21
  169. package/src/tool/timelapseCalculator/i18n/en.ts +1 -21
  170. package/src/tool/timelapseCalculator/i18n/es.ts +1 -21
  171. package/src/tool/timelapseCalculator/i18n/fr.ts +1 -21
  172. package/src/tool/timelapseCalculator/i18n/id.ts +1 -21
  173. package/src/tool/timelapseCalculator/i18n/it.ts +1 -21
  174. package/src/tool/timelapseCalculator/i18n/ja.ts +1 -21
  175. package/src/tool/timelapseCalculator/i18n/ko.ts +1 -21
  176. package/src/tool/timelapseCalculator/i18n/nl.ts +1 -21
  177. package/src/tool/timelapseCalculator/i18n/pl.ts +1 -21
  178. package/src/tool/timelapseCalculator/i18n/pt.ts +1 -21
  179. package/src/tool/timelapseCalculator/i18n/ru.ts +1 -21
  180. package/src/tool/timelapseCalculator/i18n/sv.ts +1 -21
  181. package/src/tool/timelapseCalculator/i18n/tr.ts +1 -21
  182. package/src/tool/timelapseCalculator/i18n/zh.ts +1 -21
  183. package/src/tool/timelapseCalculator/seo.astro +2 -5
  184. package/src/tool/timelapseCalculator/timelapse-hyperlapse-calculator-perfect-intervals.css +44 -42
  185. package/src/tool/tvDistance/bibliography.ts +12 -0
  186. package/src/tool/tvDistance/entry.ts +2 -0
  187. package/src/tool/tvDistance/i18n/de.ts +1 -13
  188. package/src/tool/tvDistance/i18n/en.ts +1 -13
  189. package/src/tool/tvDistance/i18n/es.ts +1 -13
  190. package/src/tool/tvDistance/i18n/fr.ts +1 -13
  191. package/src/tool/tvDistance/i18n/id.ts +1 -13
  192. package/src/tool/tvDistance/i18n/it.ts +1 -13
  193. package/src/tool/tvDistance/i18n/ja.ts +1 -13
  194. package/src/tool/tvDistance/i18n/ko.ts +1 -13
  195. package/src/tool/tvDistance/i18n/nl.ts +1 -13
  196. package/src/tool/tvDistance/i18n/pl.ts +1 -13
  197. package/src/tool/tvDistance/i18n/pt.ts +1 -13
  198. package/src/tool/tvDistance/i18n/ru.ts +1 -13
  199. package/src/tool/tvDistance/i18n/sv.ts +1 -13
  200. package/src/tool/tvDistance/i18n/tr.ts +1 -13
  201. package/src/tool/tvDistance/i18n/zh.ts +1 -13
  202. package/src/tool/tvDistance/seo.astro +1 -1
  203. package/src/tool/tvDistance/tv-viewing-distance-calculator-thx-4k-optimal-screen.css +56 -56
  204. package/src/tool/videoFrameExtractor/bibliography.ts +8 -0
  205. package/src/tool/videoFrameExtractor/entry.ts +2 -0
  206. package/src/tool/videoFrameExtractor/i18n/de.ts +1 -9
  207. package/src/tool/videoFrameExtractor/i18n/en.ts +1 -9
  208. package/src/tool/videoFrameExtractor/i18n/es.ts +1 -9
  209. package/src/tool/videoFrameExtractor/i18n/fr.ts +1 -8
  210. package/src/tool/videoFrameExtractor/i18n/id.ts +1 -9
  211. package/src/tool/videoFrameExtractor/i18n/it.ts +1 -8
  212. package/src/tool/videoFrameExtractor/i18n/ja.ts +1 -9
  213. package/src/tool/videoFrameExtractor/i18n/ko.ts +1 -9
  214. package/src/tool/videoFrameExtractor/i18n/nl.ts +1 -9
  215. package/src/tool/videoFrameExtractor/i18n/pl.ts +1 -9
  216. package/src/tool/videoFrameExtractor/i18n/pt.ts +1 -9
  217. package/src/tool/videoFrameExtractor/i18n/ru.ts +1 -9
  218. package/src/tool/videoFrameExtractor/i18n/sv.ts +1 -9
  219. package/src/tool/videoFrameExtractor/i18n/tr.ts +1 -9
  220. package/src/tool/videoFrameExtractor/i18n/zh.ts +1 -9
  221. package/src/tool/videoFrameExtractor/online-video-frame-extractor-capture-hd-stills.css +55 -55
  222. package/src/tool/videoFrameExtractor/seo.astro +1 -1
  223. package/src/tools.ts +2 -0
  224. package/src/types.ts +0 -2
  225. package/src/tool/chromaticLens/style.css +0 -308
  226. package/src/tool/collageMaker/style.css +0 -386
  227. package/src/tool/exifCleaner/style.css +0 -289
  228. package/src/tool/imageCompressor/style.css +0 -503
  229. package/src/tool/printQualityCalculator/style.css +0 -491
  230. package/src/tool/privacyBlur/style.css +0 -332
  231. package/src/tool/subtitleSync/style.css +0 -325
  232. package/src/tool/timelapseCalculator/style.css +0 -285
  233. package/src/tool/tvDistance/style.css +0 -435
  234. package/src/tool/videoFrameExtractor/style.css +0 -426
@@ -0,0 +1,141 @@
1
+ import { bibliography } from '../bibliography';
2
+ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
3
+ import type { DepthOfFieldUI, DepthOfFieldLocaleContent } from '../index';
4
+
5
+ const slug = 'alan-derinligi-hesaplama';
6
+ const title = 'Alan Derinliği Hesaplama: Tüm Kameralar İçin Gerçek Zamanlı DoF';
7
+ const description = 'Alan derinliğini, hiperfokal mesafeyi ve odak sınırlarını gerçek zamanlı hesaplayın. 1/3 durak diyafram hassasiyetiyle tüm sensörleri destekler.';
8
+
9
+ const ui: DepthOfFieldUI = {
10
+ title: 'Alan Derinliği Hesaplama',
11
+ paramsTitle: 'Parametreler',
12
+ sensorLabel: 'Kamera Sensörü',
13
+ moreLabel: 'Daha fazla sensör…',
14
+ apertureLabel: 'Diyafram',
15
+ focalLabel: 'Odak Uzaklığı',
16
+ distanceLabel: 'Obje Mesafesi',
17
+ metersLabel: 'm',
18
+ feetLabel: 'ft',
19
+ resultsTitle: 'Sonuçlar',
20
+ totalDofLabel: 'Toplam Alan Derinliği',
21
+ infiniteLabel: 'Sonsuz',
22
+ nearLimitLabel: 'Yakın Sınır',
23
+ farLimitLabel: 'Uzak Sınır',
24
+ hyperfocalLabel: 'Hiperfokal',
25
+ cocLabel: 'Bulanıklık Halkası',
26
+ cocUnit: 'mm',
27
+ showDetailsLabel: 'Teknik detayları göster',
28
+ hideDetailsLabel: 'Teknik detayları gizle',
29
+ errorBelowFocal: 'Obje mesafesi odak uzaklığından büyük olmalıdır.',
30
+ };
31
+
32
+ const faq: DepthOfFieldLocaleContent['faq'] = [
33
+ {
34
+ question: 'Alan derinliği nedir?',
35
+ answer: 'Alan derinliği (DoF), bir sahnedeki kabul edilebilir düzeyde net görünen mesafe aralığıdır. Diyafram, odak uzaklığı, obje mesafesi ve sensör boyutu tarafından belirlenir.',
36
+ },
37
+ {
38
+ question: 'Hiperfokal mesafe nedir?',
39
+ answer: 'Hiperfokal mesafe, sonsuzdaki nesnelerin hala kabul edilebilir düzeyde net olduğu en yakın odaklama mesafesidir. Bu mesafeye odaklanmak alan derinliğini maksimize eder.',
40
+ },
41
+ {
42
+ question: 'Daha geniş diyafram (küçük f-değeri) neden alan derinliğini azaltır?',
43
+ answer: 'Geniş diyafram, lensin daha büyük bir alanından ışık toplar, bu da odak dışı noktalar için bulanıklık halkasını büyüterek net alan derinliğini daraltır.',
44
+ },
45
+ {
46
+ question: 'Sensör boyutu alan derinliğini nasıl etkiler?',
47
+ answer: 'Büyük sensörler daha yüksek bulanıklık halkası eşiği kullanır. Ancak eşdeğer bakış açılarında, büyük sensörler daha uzun odak uzaklığı gerektirdiği için genellikle daha sığ alan derinliği üretir.',
48
+ },
49
+ ];
50
+
51
+ const howTo: DepthOfFieldLocaleContent['howTo'] = [
52
+ {
53
+ name: 'Kamera sensörünüzü seçin',
54
+ text: 'Kamera gövdenize uygun olan sensör formatını seçin. Bu, hesaplamalarda kullanılacak bulanıklık halkası (CoC) değerini belirler.',
55
+ },
56
+ {
57
+ name: 'Diyafram ve odak uzaklığını ayarlayın',
58
+ text: 'Diyaframı 1/3 durak adımlarla seçin. Odak uzaklığı sürgüsü, geniş açıda daha hassas ayar yapabilmeniz için logaritmik ölçek kullanır.',
59
+ },
60
+ {
61
+ name: 'Obje mesafesini belirleyin',
62
+ text: 'Kamera ile ana objeniz arasındaki mesafeyi ayarlayın. İhtiyacınıza göre metre ve fit birimleri arasında geçiş yapın.',
63
+ },
64
+ {
65
+ name: 'Sonuçları okuyun',
66
+ text: 'Odak Çubuğu, objenizin etrafındaki net bölgeyi görselleştirir. Yakın ve uzak sınırlar kabul edilebilir odak sınırlarını gösterir.',
67
+ },
68
+ ];
69
+
70
+ const seo: DepthOfFieldLocaleContent['seo'] = [
71
+ { type: 'title', text: 'Fotoğraf ve Sinemada Alan Derinliğini Anlamak', level: 2 },
72
+ { type: 'paragraph', html: 'Alan derinliği, fotoğrafçılar ve sinemacılar için en güçlü yaratıcı araçlardan biridir. <strong>Sığ alan derinliği</strong> konuyu arka plandan ayırırken, <strong>geniş alan derinliği</strong> manzarayı net tutar.' },
73
+
74
+ { type: 'title', text: 'Alan Derinliğini Kontrol Eden Üç Değişken', level: 3 },
75
+ { type: 'table', headers: ['Değişken', 'Artış →', 'DoF Üzerindeki Etkisi'], rows: [
76
+ ['Diyafram', 'f/1.4 → f/16', 'Daha geniş diyafram = daha sığ DoF'],
77
+ ['Odak Uzaklığı', '24mm → 200mm', 'Daha uzun odak = aynı mesafede daha sığ DoF'],
78
+ ['Obje Mesafesi', '1m → 10m', 'Daha uzak obje = daha geniş DoF'],
79
+ ]},
80
+
81
+ { type: 'title', text: 'Hiperfokal Mesafe: Maksimum Netlik', level: 3 },
82
+ { type: 'paragraph', html: '<strong>Hiperfokal mesafeye</strong> odaklandığınızda, bu mesafenin yarısından sonsuza kadar her şey net görünür. Manzara fotoğrafçıları bu tekniği sıkça kullanır.' },
83
+ { type: 'tip', title: 'Pratik ipucu', html: 'Sokak fotoğrafçılığı için odağınızı hiperfokal mesafeye ayarlayın. APS-C sensörde 35mm lens ve f/8 ile hiperfokal yaklaşık <strong>4 metredir</strong>: 2 metreden sonsuza her şey net olacaktır.' },
84
+
85
+ { type: 'title', text: 'Sensör Boyutu ve Bulanıklık Halkası', level: 3 },
86
+ { type: 'paragraph', html: '<strong>Bulanıklık halkası (CoC)</strong>, kabul edilebilir netliğin sınırıdır. Full Frame sensörde CoC 0.030mm iken akıllı telefonda ~0.006mm\'dir. Daha küçük CoC, daha katı netlik kriteri demektir.' },
87
+ { type: 'stats', columns: 3, items: [
88
+ { label: 'Full Frame', value: '0.030 mm', icon: 'mdi:camera' },
89
+ { label: 'APS-C', value: '0.019 mm', icon: 'mdi:camera-outline' },
90
+ { label: 'Akıllı Telefon', value: '0.006 mm', icon: 'mdi:cellphone' },
91
+ ]},
92
+
93
+ { type: 'title', text: 'Sinemada DoF: Odak Uzaklığı vs Sensör', level: 3 },
94
+ { type: 'paragraph', html: 'Super 35 formatında çekim yapan sinemacılar, "sinematik görünüm" oluşturmak için genellikle perspektifi sıkıştıran uzun odak uzaklıklarını tercih ederler.' },
95
+ { type: 'diagnostic', variant: 'success', title: 'Odak Dağılım Kuralı', icon: 'mdi:lightbulb-outline', badge: 'Profil Teknik', html: '3 metredeki bir obje için 50mm ve f/2.8 ile: Net alan objenin arkasında, önüne göre her zaman daha fazladır; oran yaklaşık <strong>2:1</strong>\'dir.' },
96
+ ];
97
+
98
+ const faqSchema: WithContext<FAQPage> = {
99
+ '@context': 'https://schema.org',
100
+ '@type': 'FAQPage',
101
+ mainEntity: faq.map((item) => ({
102
+ '@type': 'Question',
103
+ name: item.question,
104
+ acceptedAnswer: { '@type': 'Answer', text: item.answer },
105
+ })),
106
+ };
107
+
108
+ const howToSchema: WithContext<HowTo> = {
109
+ '@context': 'https://schema.org',
110
+ '@type': 'HowTo',
111
+ name: title,
112
+ description,
113
+ step: howTo.map((step) => ({
114
+ '@type': 'HowToStep',
115
+ name: step.name,
116
+ text: step.text,
117
+ })),
118
+ };
119
+
120
+ const appSchema: WithContext<SoftwareApplication> = {
121
+ '@context': 'https://schema.org',
122
+ '@type': 'SoftwareApplication',
123
+ name: title,
124
+ description,
125
+ applicationCategory: 'UtilitiesApplication',
126
+ operatingSystem: 'Web',
127
+ offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
128
+ inLanguage: 'tr',
129
+ };
130
+
131
+ export const content: DepthOfFieldLocaleContent = {
132
+ slug,
133
+ title,
134
+ description,
135
+ ui,
136
+ seo,
137
+ faq,
138
+ bibliography,
139
+ howTo,
140
+ schemas: [faqSchema as any, howToSchema as any, appSchema],
141
+ };
@@ -0,0 +1,141 @@
1
+ import { bibliography } from '../bibliography';
2
+ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
3
+ import type { DepthOfFieldUI, DepthOfFieldLocaleContent } from '../index';
4
+
5
+ const slug = 'depth-of-field-calculator';
6
+ const title = '景深计算器:全相机实时景深计算';
7
+ const description = '实时计算景深、超焦距和焦点限制。支持所有传感器尺寸,具备 1/3 档光圈精度。';
8
+
9
+ const ui: DepthOfFieldUI = {
10
+ title: '景深计算器',
11
+ paramsTitle: '设定参数',
12
+ sensorLabel: '相机传感器',
13
+ moreLabel: '更多传感器…',
14
+ apertureLabel: '光圈值',
15
+ focalLabel: '焦距',
16
+ distanceLabel: '拍摄距离',
17
+ metersLabel: 'm',
18
+ feetLabel: 'ft',
19
+ resultsTitle: '计算结果',
20
+ totalDofLabel: '总景深',
21
+ infiniteLabel: '无穷远',
22
+ nearLimitLabel: '近景界限',
23
+ farLimitLabel: '远景界限',
24
+ hyperfocalLabel: '超焦距',
25
+ cocLabel: '弥散圆 (CoC)',
26
+ cocUnit: 'mm',
27
+ showDetailsLabel: '显示技术细节',
28
+ hideDetailsLabel: '隐藏技术细节',
29
+ errorBelowFocal: '拍摄距离必须大于焦距。',
30
+ };
31
+
32
+ const faq: DepthOfFieldLocaleContent['faq'] = [
33
+ {
34
+ question: '什么是景深?',
35
+ answer: '景深 (DoF) 是指场景中在最终图像里显得清晰的范围。它由光圈、焦距、拍摄距离和传感器尺寸决定。',
36
+ },
37
+ {
38
+ question: '什么是超焦距?',
39
+ answer: '超焦距是指在对无穷远处的物体依然能保持清晰的情况下,最近的对焦距离。对焦在此距离可以最大化景深。',
40
+ },
41
+ {
42
+ question: '为什么较大的光圈(较小的 f 值)会减小景深?',
43
+ answer: '较大的光圈通过镜头的更大区域收集光线,这增加了焦点外点的弥散圆大小,从而收窄了清晰范围。',
44
+ },
45
+ {
46
+ question: '传感器尺寸如何影响景深?',
47
+ answer: '较大的传感器使用更大的弥散圆阈值。但在相同视角下,大传感器通常产生更浅的景深,因为它们需要更长的焦距。',
48
+ },
49
+ ];
50
+
51
+ const howTo: DepthOfFieldLocaleContent['howTo'] = [
52
+ {
53
+ name: '选择相机传感器',
54
+ text: '选择与您的相机机身匹配的传感器格式。这将设定计算中使用的弥散圆 (CoC) 值。',
55
+ },
56
+ {
57
+ name: '设定光圈和焦距',
58
+ text: '以 1/3 档为增量选择光圈。焦距滑块采用对数刻度,便于在广角端进行精细调整。',
59
+ },
60
+ {
61
+ name: '设定拍摄距离',
62
+ text: '设置相机与主主体之间的距离。根据需要切换米和英尺单位。',
63
+ },
64
+ {
65
+ name: '查看结果',
66
+ text: '对焦条可视化主体周围的清晰区域。近景和远景界限显示了精确的焦点边界。',
67
+ },
68
+ ];
69
+
70
+ const seo: DepthOfFieldLocaleContent['seo'] = [
71
+ { type: 'title', text: '深入理解摄影与电影中的景深', level: 2 },
72
+ { type: 'paragraph', html: '景深是摄影师和摄像师最强大的创意工具之一。<strong>浅景深</strong>可以将主体从干扰背景中分离,而<strong>深景深</strong>则能让整个风景从前景到地平线保持清晰。' },
73
+
74
+ { type: 'title', text: '控制景深的三大变量', level: 3 },
75
+ { type: 'table', headers: ['变量', '变化趋势 →', '对景深的影响'], rows: [
76
+ ['光圈', 'f/1.4 → f/16', '光圈越大 = 景深越浅'],
77
+ ['焦距', '24mm → 200mm', '焦距越长 = 景深越浅(同一距离下)'],
78
+ ['拍摄距离', '1m → 10m', '主体越远 = 景深越深'],
79
+ ]},
80
+
81
+ { type: 'title', text: '超焦距:实现最大清晰度', level: 3 },
82
+ { type: 'paragraph', html: '当您对焦在<strong>超焦距</strong>时,从该距离的一半到无穷远的一切都会显得清晰。风景摄影师常用此技术确保前景和远山同时清晰。' },
83
+ { type: 'tip', title: '实践建议', html: '对于街头摄影,将焦点设为超焦距。在 APS-C 上使用 35mm 镜头并设置 f/8 时,超焦距约为 <strong>4 米</strong>:从 2 米到无穷远的一切都将保持清晰。' },
84
+
85
+ { type: 'title', text: '传感器尺寸与弥散圆', level: 3 },
86
+ { type: 'paragraph', html: '<strong>弥散圆 (CoC)</strong> 是定义“清晰度”的阈值。全画幅传感器的 CoC 为 0.030mm,而智能手机约为 0.006mm。CoC 值越小意味着清晰度要求越严格。' },
87
+ { type: 'stats', columns: 3, items: [
88
+ { label: '全画幅', value: '0.030 mm', icon: 'mdi:camera' },
89
+ { label: 'APS-C', value: '0.019 mm', icon: 'mdi:camera-outline' },
90
+ { label: '智能手机', value: '0.006 mm', icon: 'mdi:cellphone' },
91
+ ]},
92
+
93
+ { type: 'title', text: '电影中的景深:焦距 vs. 传感器', level: 3 },
94
+ { type: 'paragraph', html: '在 Super 35(接近 APS-C)上拍摄的电影人经常使用较长焦距来压缩透视,这也会收窄景深,营造出“电影感”。大光圈 85mm 是经典人像选择。' },
95
+ { type: 'diagnostic', variant: 'success', title: '焦点分布规律', icon: 'mdi:lightbulb-outline', badge: '专家技法', html: '对于 3 米处的主体,使用 50mm f/2.8 全画幅拍摄:主体后的清晰区域总是比主体前大,比例约为 <strong>2:1</strong>。' },
96
+ ];
97
+
98
+ const faqSchema: WithContext<FAQPage> = {
99
+ '@context': 'https://schema.org',
100
+ '@type': 'FAQPage',
101
+ mainEntity: faq.map((item) => ({
102
+ '@type': 'Question',
103
+ name: item.question,
104
+ acceptedAnswer: { '@type': 'Answer', text: item.answer },
105
+ })),
106
+ };
107
+
108
+ const howToSchema: WithContext<HowTo> = {
109
+ '@context': 'https://schema.org',
110
+ '@type': 'HowTo',
111
+ name: title,
112
+ description,
113
+ step: howTo.map((step) => ({
114
+ '@type': 'HowToStep',
115
+ name: step.name,
116
+ text: step.text,
117
+ })),
118
+ };
119
+
120
+ const appSchema: WithContext<SoftwareApplication> = {
121
+ '@context': 'https://schema.org',
122
+ '@type': 'SoftwareApplication',
123
+ name: title,
124
+ description,
125
+ applicationCategory: 'UtilitiesApplication',
126
+ operatingSystem: 'Web',
127
+ offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
128
+ inLanguage: 'zh',
129
+ };
130
+
131
+ export const content: DepthOfFieldLocaleContent = {
132
+ slug,
133
+ title,
134
+ description,
135
+ ui,
136
+ seo,
137
+ faq,
138
+ bibliography,
139
+ howTo,
140
+ schemas: [faqSchema as any, howToSchema as any, appSchema],
141
+ };
@@ -0,0 +1,10 @@
1
+ import type { ToolDefinition, AudiovisualToolEntry } from '../../types';
2
+ import { depthOfFieldCalculator } from './entry';
3
+ export * from './entry';
4
+
5
+ export const DEPTH_OF_FIELD_CALCULATOR_TOOL: ToolDefinition = {
6
+ entry: depthOfFieldCalculator as unknown as AudiovisualToolEntry,
7
+ Component: () => import('./component.astro'),
8
+ SEOComponent: () => import('./seo.astro'),
9
+ BibliographyComponent: () => import('./bibliography.astro'),
10
+ };
@@ -0,0 +1,91 @@
1
+
2
+ export interface SensorPreset {
3
+ key: string;
4
+ label: string;
5
+ shortLabel: string;
6
+ coc: number;
7
+ }
8
+
9
+ export const SENSOR_PRESETS: SensorPreset[] = [
10
+ { key: 'ff', label: 'Full Frame (35mm)', shortLabel: 'FF', coc: 0.030 },
11
+ { key: 'apsc-canon', label: 'APS-C Canon', shortLabel: 'APS-C', coc: 0.019 },
12
+ { key: 'apsc', label: 'APS-C Nikon / Sony', shortLabel: 'APS-N', coc: 0.020 },
13
+ { key: 'mft', label: 'Micro Four Thirds', shortLabel: 'MFT', coc: 0.015 },
14
+ { key: '1inch', label: '1" Sensor', shortLabel: '1"', coc: 0.011 },
15
+ { key: 'phone', label: 'Smartphone', shortLabel: 'Phone', coc: 0.006 },
16
+ ];
17
+
18
+ export const QUICK_SENSOR_KEYS = ['ff', 'apsc-canon', 'mft', 'phone'];
19
+
20
+ export const F_STOPS: number[] = [
21
+ 1.0, 1.1, 1.2, 1.4, 1.6, 1.8,
22
+ 2.0, 2.2, 2.5, 2.8, 3.2, 3.5,
23
+ 4.0, 4.5, 5.0, 5.6, 6.3, 7.1,
24
+ 8.0, 9.0, 10, 11, 13, 14, 16, 18, 20, 22,
25
+ ];
26
+
27
+ export interface DoFResult {
28
+ hyperfocal: number;
29
+ nearLimit: number;
30
+ farLimit: number;
31
+ totalDoF: number;
32
+ isInfinite: boolean;
33
+ hasError: boolean;
34
+ errorCode: 'BELOW_FOCAL' | null;
35
+ }
36
+
37
+ export function calculateDoF(
38
+ subjectMetres: number,
39
+ focalMm: number,
40
+ aperture: number,
41
+ cocMm: number,
42
+ ): DoFResult {
43
+ const fM = focalMm / 1000;
44
+ const cM = cocMm / 1000;
45
+
46
+ if (subjectMetres <= fM) {
47
+ return { hyperfocal: 0, nearLimit: 0, farLimit: 0, totalDoF: 0, isInfinite: false, hasError: true, errorCode: 'BELOW_FOCAL' };
48
+ }
49
+
50
+ const H = (fM * fM) / (aperture * cM) + fM;
51
+ const nearLimit = (subjectMetres * (H - fM)) / (H + subjectMetres - 2 * fM);
52
+ const isInfinite = subjectMetres >= H;
53
+ const farLimit = isInfinite ? Infinity : (subjectMetres * (H - fM)) / (H - subjectMetres);
54
+ const totalDoF = isInfinite ? Infinity : farLimit - nearLimit;
55
+
56
+ return { hyperfocal: H, nearLimit, farLimit, totalDoF, isInfinite, hasError: false, errorCode: null };
57
+ }
58
+
59
+ const LOG_FOCAL_MIN = Math.log(8);
60
+ const LOG_FOCAL_MAX = Math.log(800);
61
+ const LOG_SUBJECT_MIN = Math.log(0.5);
62
+ const LOG_SUBJECT_MAX = Math.log(200);
63
+
64
+ export function sliderToFocal(index: number, steps: number): number {
65
+ const t = index / (steps - 1);
66
+ return Math.round(Math.exp(LOG_FOCAL_MIN + t * (LOG_FOCAL_MAX - LOG_FOCAL_MIN)));
67
+ }
68
+
69
+ export function focalToSlider(focal: number, steps: number): number {
70
+ const t = (Math.log(focal) - LOG_FOCAL_MIN) / (LOG_FOCAL_MAX - LOG_FOCAL_MIN);
71
+ return Math.round(t * (steps - 1));
72
+ }
73
+
74
+ export function sliderToSubject(index: number, steps: number): number {
75
+ const t = index / (steps - 1);
76
+ return Math.exp(LOG_SUBJECT_MIN + t * (LOG_SUBJECT_MAX - LOG_SUBJECT_MIN));
77
+ }
78
+
79
+ export function subjectToSlider(subject: number, steps: number): number {
80
+ const t = (Math.log(subject) - LOG_SUBJECT_MIN) / (LOG_SUBJECT_MAX - LOG_SUBJECT_MIN);
81
+ return Math.round(t * (steps - 1));
82
+ }
83
+
84
+ export function formatDistance(metres: number, useFeet: boolean): string {
85
+ if (!isFinite(metres)) return '∞';
86
+ const value = useFeet ? metres * 3.28084 : metres;
87
+ const unit = useFeet ? 'ft' : 'm';
88
+ if (value >= 1000) return `${(value / 1000).toFixed(1)} km`;
89
+ if (value < 1) return `${(value * 100).toFixed(0)} cm`;
90
+ return value >= 10 ? `${value.toFixed(1)} ${unit}` : `${value.toFixed(2)} ${unit}`;
91
+ }
@@ -0,0 +1,15 @@
1
+ ---
2
+ import { SEORenderer } from '@jjlmoya/utils-shared';
3
+ import { depthOfFieldCalculator } from './index';
4
+ import type { KnownLocale } from '../../types';
5
+
6
+ interface Props {
7
+ locale?: KnownLocale;
8
+ }
9
+
10
+ const { locale = 'en' } = Astro.props;
11
+ const content = await depthOfFieldCalculator.i18n[locale]?.();
12
+ if (!content) return null;
13
+ ---
14
+
15
+ {content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
@@ -0,0 +1,12 @@
1
+ import type { BibliographyEntry } from '../../types';
2
+
3
+ export const bibliography: BibliographyEntry[] = [
4
+ {
5
+ name: "Exchangeable Image File Format (EXIF) - Wikipedia",
6
+ url: "https://de.wikipedia.org/wiki/Exchangeable_Image_File_Format",
7
+ },
8
+ {
9
+ name: "W3C - Metadaten in Bildern",
10
+ url: "https://www.w3.org/community/image-metadata/",
11
+ },
12
+ ];
@@ -51,3 +51,5 @@ export const exifCleaner: AudiovisualToolEntry<ExifCleanerUI> = {
51
51
  zh: async () => (await import('./i18n/zh')).content as unknown as ExifCleanerLocaleContent,
52
52
  },
53
53
  };
54
+
55
+ export { bibliography } from './bibliography';
@@ -1,4 +1,4 @@
1
- :global(.ec-root) {
1
+ .ec-root {
2
2
  --ec-bg: #fff;
3
3
  --ec-bg-elevated: #f8fafc;
4
4
  --ec-border: #e2e8f0;
@@ -14,7 +14,7 @@
14
14
  margin: 0 auto;
15
15
  }
16
16
 
17
- :global(.theme-dark .ec-root) {
17
+ .theme-dark .ec-root {
18
18
  --ec-bg: #18181b;
19
19
  --ec-bg-elevated: #27272a;
20
20
  --ec-border: #3f3f46;
@@ -26,7 +26,7 @@
26
26
  --ec-shadow: rgba(0, 0, 0, 0.3);
27
27
  }
28
28
 
29
- :global(.ec-card) {
29
+ .ec-card {
30
30
  background: var(--ec-bg);
31
31
  border: 1px solid var(--ec-border);
32
32
  border-radius: 3rem;
@@ -36,7 +36,7 @@
36
36
  overflow: hidden;
37
37
  }
38
38
 
39
- :global(.ec-drop) {
39
+ .ec-drop {
40
40
  padding: 4rem 2rem;
41
41
  border: 3px dashed var(--ec-border);
42
42
  border-radius: 2.5rem;
@@ -49,13 +49,13 @@
49
49
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
50
50
  }
51
51
 
52
- :global(.ec-drop:hover),
53
- :global(.ec-drop-active) {
52
+ .ec-drop:hover,
53
+ .ec-drop-active {
54
54
  border-color: var(--ec-accent);
55
55
  background: var(--ec-accent-alpha-hover);
56
56
  }
57
57
 
58
- :global(.ec-drop-icon) {
58
+ .ec-drop-icon {
59
59
  width: 6rem;
60
60
  height: 6rem;
61
61
  background: var(--ec-accent-alpha);
@@ -66,19 +66,19 @@
66
66
  color: var(--ec-accent);
67
67
  }
68
68
 
69
- :global(.ec-drop-icon svg) {
69
+ .ec-drop-icon svg {
70
70
  width: 3rem;
71
71
  height: 3rem;
72
72
  }
73
73
 
74
- :global(.ec-title) {
74
+ .ec-title {
75
75
  font-size: 2.5rem;
76
76
  font-weight: 950;
77
77
  color: var(--ec-text);
78
78
  margin: 0;
79
79
  }
80
80
 
81
- :global(.ec-subtitle) {
81
+ .ec-subtitle {
82
82
  font-size: 1.15rem;
83
83
  color: var(--ec-text-muted);
84
84
  max-width: 500px;
@@ -86,14 +86,14 @@
86
86
  font-weight: 700;
87
87
  }
88
88
 
89
- :global(.ec-badges) {
89
+ .ec-badges {
90
90
  display: flex;
91
91
  gap: 1rem;
92
92
  flex-wrap: wrap;
93
93
  justify-content: center;
94
94
  }
95
95
 
96
- :global(.ec-badge) {
96
+ .ec-badge {
97
97
  padding: 0.6rem 1.25rem;
98
98
  background: var(--ec-bg-elevated);
99
99
  border-radius: 2rem;
@@ -105,13 +105,13 @@
105
105
  gap: 0.5rem;
106
106
  }
107
107
 
108
- :global(.ec-badge svg) {
108
+ .ec-badge svg {
109
109
  width: 1rem;
110
110
  height: 1rem;
111
111
  flex-shrink: 0;
112
112
  }
113
113
 
114
- :global(.ec-processing) {
114
+ .ec-processing {
115
115
  padding: 5rem;
116
116
  display: flex;
117
117
  flex-direction: column;
@@ -120,7 +120,7 @@
120
120
  gap: 1.5rem;
121
121
  }
122
122
 
123
- :global(.ec-spinner) {
123
+ .ec-spinner {
124
124
  width: 4rem;
125
125
  height: 4rem;
126
126
  border: 4px solid var(--ec-accent-alpha);
@@ -129,45 +129,45 @@
129
129
  animation: ec-spin 0.8s linear infinite;
130
130
  }
131
131
 
132
- :global(.ec-processing-text) {
132
+ .ec-processing-text {
133
133
  font-weight: 800;
134
134
  color: var(--ec-text);
135
135
  margin: 0;
136
136
  }
137
137
 
138
- :global(.ec-result) {
138
+ .ec-result {
139
139
  padding: 2.5rem;
140
140
  display: flex;
141
141
  flex-direction: column;
142
142
  animation: ec-slide-up 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
143
143
  }
144
144
 
145
- :global(.ec-result-layout) {
145
+ .ec-result-layout {
146
146
  display: grid;
147
147
  grid-template-columns: 1fr 1fr;
148
148
  gap: 3rem;
149
149
  }
150
150
 
151
151
  @media (max-width: 800px) {
152
- :global(.ec-result-layout) {
152
+ .ec-result-layout {
153
153
  grid-template-columns: 1fr;
154
154
  }
155
155
  }
156
156
 
157
- :global(.ec-preview-col) {
157
+ .ec-preview-col {
158
158
  display: flex;
159
159
  flex-direction: column;
160
160
  gap: 1.5rem;
161
161
  }
162
162
 
163
- :global(.ec-preview-img) {
163
+ .ec-preview-img {
164
164
  width: 100%;
165
165
  border-radius: 1.5rem;
166
166
  box-shadow: 0 20px 50px var(--ec-shadow);
167
167
  display: block;
168
168
  }
169
169
 
170
- :global(.ec-metadata) {
170
+ .ec-metadata {
171
171
  background: var(--ec-bg-elevated);
172
172
  border: 1px solid var(--ec-border);
173
173
  border-radius: 1.25rem;
@@ -178,7 +178,7 @@
178
178
  justify-content: center;
179
179
  }
180
180
 
181
- :global(.ec-no-metadata) {
181
+ .ec-no-metadata {
182
182
  display: flex;
183
183
  align-items: center;
184
184
  justify-content: center;
@@ -187,14 +187,14 @@
187
187
  text-align: center;
188
188
  }
189
189
 
190
- :global(.ec-metadata-title) {
190
+ .ec-metadata-title {
191
191
  color: var(--ec-accent);
192
192
  font-weight: 700;
193
193
  margin-bottom: 1rem;
194
194
  font-size: 0.9rem;
195
195
  }
196
196
 
197
- :global(.ec-metadata-list) {
197
+ .ec-metadata-list {
198
198
  list-style: none;
199
199
  padding: 0;
200
200
  margin: 0;
@@ -203,7 +203,7 @@
203
203
  gap: 0.75rem;
204
204
  }
205
205
 
206
- :global(.ec-metadata-list li) {
206
+ .ec-metadata-list li {
207
207
  display: flex;
208
208
  justify-content: space-between;
209
209
  gap: 1rem;
@@ -212,21 +212,21 @@
212
212
  color: var(--ec-text);
213
213
  }
214
214
 
215
- :global(.ec-metadata-list li span:first-child) {
215
+ .ec-metadata-list li span:first-child {
216
216
  font-weight: 700;
217
217
  }
218
218
 
219
- :global(.ec-metadata-list li span:last-child) {
219
+ .ec-metadata-list li span:last-child {
220
220
  color: var(--ec-text-muted);
221
221
  }
222
222
 
223
- :global(.ec-actions-col) {
223
+ .ec-actions-col {
224
224
  display: flex;
225
225
  flex-direction: column;
226
226
  gap: 1.5rem;
227
227
  }
228
228
 
229
- :global(.ec-btn) {
229
+ .ec-btn {
230
230
  padding: 1.25rem;
231
231
  border-radius: 1.5rem;
232
232
  font-weight: 950;
@@ -240,29 +240,29 @@
240
240
  transition: all 0.2s;
241
241
  }
242
242
 
243
- :global(.ec-btn svg) {
243
+ .ec-btn svg {
244
244
  width: 1.25rem;
245
245
  height: 1.25rem;
246
246
  }
247
247
 
248
- :global(.ec-btn-primary) {
248
+ .ec-btn-primary {
249
249
  background: var(--ec-accent);
250
250
  color: #fff;
251
251
  box-shadow: 0 15px 35px -10px var(--ec-accent);
252
252
  }
253
253
 
254
- :global(.ec-btn-primary:hover) {
254
+ .ec-btn-primary:hover {
255
255
  transform: translateY(-2px);
256
256
  box-shadow: 0 20px 45px -10px var(--ec-accent);
257
257
  }
258
258
 
259
- :global(.ec-btn-secondary) {
259
+ .ec-btn-secondary {
260
260
  background: var(--ec-bg-elevated);
261
261
  border: 1px solid var(--ec-border);
262
262
  color: var(--ec-text);
263
263
  }
264
264
 
265
- :global(.ec-btn-secondary:hover) {
265
+ .ec-btn-secondary:hover {
266
266
  border-color: var(--ec-accent);
267
267
  color: var(--ec-accent);
268
268
  }
@@ -286,4 +286,4 @@
286
286
  opacity: 1;
287
287
  transform: translateY(0);
288
288
  }
289
- }
289
+ }