@jjlmoya/utils-nautical 1.5.0 → 1.7.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 (99) hide show
  1. package/package.json +72 -71
  2. package/src/tests/i18n_coverage.test.ts +36 -0
  3. package/src/tests/locale_completeness.test.ts +42 -0
  4. package/src/tests/no_h1_in_components.test.ts +48 -0
  5. package/src/tests/schemas_fulfillment.test.ts +23 -0
  6. package/src/tests/slug_uniqueness.test.ts +81 -0
  7. package/src/tests/title_quality.test.ts +55 -0
  8. package/src/tool/endurance/component.astro +340 -1
  9. package/src/tool/endurance/i18n/de.ts +249 -0
  10. package/src/tool/endurance/i18n/id.ts +249 -0
  11. package/src/tool/endurance/i18n/it.ts +249 -0
  12. package/src/tool/endurance/i18n/ja.ts +249 -0
  13. package/src/tool/endurance/i18n/ko.ts +249 -0
  14. package/src/tool/endurance/i18n/nl.ts +249 -0
  15. package/src/tool/endurance/i18n/pl.ts +249 -0
  16. package/src/tool/endurance/i18n/pt.ts +249 -0
  17. package/src/tool/endurance/i18n/ru.ts +249 -0
  18. package/src/tool/endurance/i18n/sv.ts +249 -0
  19. package/src/tool/endurance/i18n/tr.ts +249 -0
  20. package/src/tool/endurance/i18n/zh.ts +249 -0
  21. package/src/tool/endurance/index.ts +12 -0
  22. package/src/tool/nauticalConverter/component.astro +208 -1
  23. package/src/tool/nauticalConverter/i18n/de.ts +239 -0
  24. package/src/tool/nauticalConverter/i18n/id.ts +239 -0
  25. package/src/tool/nauticalConverter/i18n/it.ts +239 -0
  26. package/src/tool/nauticalConverter/i18n/ja.ts +239 -0
  27. package/src/tool/nauticalConverter/i18n/ko.ts +239 -0
  28. package/src/tool/nauticalConverter/i18n/nl.ts +239 -0
  29. package/src/tool/nauticalConverter/i18n/pl.ts +239 -0
  30. package/src/tool/nauticalConverter/i18n/pt.ts +239 -0
  31. package/src/tool/nauticalConverter/i18n/ru.ts +239 -0
  32. package/src/tool/nauticalConverter/i18n/sv.ts +239 -0
  33. package/src/tool/nauticalConverter/i18n/tr.ts +239 -0
  34. package/src/tool/nauticalConverter/i18n/zh.ts +239 -0
  35. package/src/tool/nauticalConverter/index.ts +12 -0
  36. package/src/tool/sailArea/component.astro +355 -2
  37. package/src/tool/sailArea/i18n/de.ts +275 -0
  38. package/src/tool/sailArea/i18n/id.ts +275 -0
  39. package/src/tool/sailArea/i18n/it.ts +275 -0
  40. package/src/tool/sailArea/i18n/ja.ts +275 -0
  41. package/src/tool/sailArea/i18n/ko.ts +275 -0
  42. package/src/tool/sailArea/i18n/nl.ts +275 -0
  43. package/src/tool/sailArea/i18n/pl.ts +275 -0
  44. package/src/tool/sailArea/i18n/pt.ts +275 -0
  45. package/src/tool/sailArea/i18n/ru.ts +275 -0
  46. package/src/tool/sailArea/i18n/sv.ts +275 -0
  47. package/src/tool/sailArea/i18n/tr.ts +275 -0
  48. package/src/tool/sailArea/i18n/zh.ts +275 -0
  49. package/src/tool/sailArea/index.ts +12 -0
  50. package/src/tool/speedConverter/component.astro +242 -1
  51. package/src/tool/speedConverter/i18n/de.ts +271 -0
  52. package/src/tool/speedConverter/i18n/id.ts +271 -0
  53. package/src/tool/speedConverter/i18n/it.ts +271 -0
  54. package/src/tool/speedConverter/i18n/ja.ts +271 -0
  55. package/src/tool/speedConverter/i18n/ko.ts +271 -0
  56. package/src/tool/speedConverter/i18n/nl.ts +271 -0
  57. package/src/tool/speedConverter/i18n/pl.ts +271 -0
  58. package/src/tool/speedConverter/i18n/pt.ts +271 -0
  59. package/src/tool/speedConverter/i18n/ru.ts +194 -0
  60. package/src/tool/speedConverter/i18n/sv.ts +271 -0
  61. package/src/tool/speedConverter/i18n/tr.ts +225 -0
  62. package/src/tool/speedConverter/i18n/zh.ts +271 -0
  63. package/src/tool/speedConverter/index.ts +12 -0
  64. package/src/tool/tideCalculator/component.astro +313 -1
  65. package/src/tool/tideCalculator/i18n/de.ts +203 -0
  66. package/src/tool/tideCalculator/i18n/id.ts +203 -0
  67. package/src/tool/tideCalculator/i18n/it.ts +203 -0
  68. package/src/tool/tideCalculator/i18n/ja.ts +203 -0
  69. package/src/tool/tideCalculator/i18n/ko.ts +203 -0
  70. package/src/tool/tideCalculator/i18n/nl.ts +203 -0
  71. package/src/tool/tideCalculator/i18n/pl.ts +203 -0
  72. package/src/tool/tideCalculator/i18n/pt.ts +203 -0
  73. package/src/tool/tideCalculator/i18n/ru.ts +203 -0
  74. package/src/tool/tideCalculator/i18n/sv.ts +203 -0
  75. package/src/tool/tideCalculator/i18n/tr.ts +203 -0
  76. package/src/tool/tideCalculator/i18n/zh.ts +203 -0
  77. package/src/tool/tideCalculator/index.ts +12 -0
  78. package/src/tool/underKeel/component.astro +321 -1
  79. package/src/tool/underKeel/i18n/de.ts +189 -0
  80. package/src/tool/underKeel/i18n/en.ts +2 -2
  81. package/src/tool/underKeel/i18n/fr.ts +2 -2
  82. package/src/tool/underKeel/i18n/id.ts +189 -0
  83. package/src/tool/underKeel/i18n/it.ts +176 -0
  84. package/src/tool/underKeel/i18n/ja.ts +185 -0
  85. package/src/tool/underKeel/i18n/ko.ts +185 -0
  86. package/src/tool/underKeel/i18n/nl.ts +176 -0
  87. package/src/tool/underKeel/i18n/pl.ts +176 -0
  88. package/src/tool/underKeel/i18n/pt.ts +176 -0
  89. package/src/tool/underKeel/i18n/ru.ts +176 -0
  90. package/src/tool/underKeel/i18n/sv.ts +176 -0
  91. package/src/tool/underKeel/i18n/tr.ts +185 -0
  92. package/src/tool/underKeel/i18n/zh.ts +185 -0
  93. package/src/tool/underKeel/index.ts +12 -0
  94. package/src/tool/endurance/style.css +0 -337
  95. package/src/tool/nauticalConverter/style.css +0 -205
  96. package/src/tool/sailArea/style.css +0 -351
  97. package/src/tool/speedConverter/style.css +0 -239
  98. package/src/tool/tideCalculator/style.css +0 -310
  99. package/src/tool/underKeel/style.css +0 -318
@@ -0,0 +1,275 @@
1
+ import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
2
+ import type { SailAreaUI, SailAreaLocaleContent } from '../index';
3
+
4
+ const slug = 'sail-area-calculator';
5
+ const title = '帆面积及 SA/D 比例计算器';
6
+ const description =
7
+ '计算您船只的总帆面积以及帆面积与排水量的比例(SA/D 比)。基于 I、J、P 和 E 测量值的航海性能分析。';
8
+
9
+ const ui: SailAreaUI = {
10
+ hullSectionLabel: '船体数据',
11
+ totalMassLabel: '排水量',
12
+ rigSystemLabel: '索具',
13
+ intendedUseLabel: '预期用途',
14
+ rigGeometryLabel: '索具几何尺寸',
15
+ sailConfigLabel: '索具类型',
16
+ genoaOverlapLabel: '热那亚帆重叠度',
17
+ foqueLabel: '大前帆',
18
+ genovaLabel: '热那亚帆',
19
+ sadRatioLabel: 'SA/D 比例',
20
+ totalAreaLabel: '总面积',
21
+ performanceLabel: '性能',
22
+ sloopLabel: '单桅船 (Sloop)',
23
+ cutterLabel: '双前帆船 (Cutter)',
24
+ ketchLabel: '双桅船 (Ketch)',
25
+ cruiserLabel: '巡航型',
26
+ performanceTypeLabel: '性能类型',
27
+ racerLabel: '竞赛型',
28
+ exportPdfLabel: '生成技术报告',
29
+ faqTitle: '常见问题',
30
+ bibliographyTitle: '参考文献统计',
31
+ };
32
+
33
+ const faq: SailAreaLocaleContent['faq'] = [
34
+ {
35
+ question: '为什么我的船在微风下行驶缓慢?',
36
+ answer: '您的 SA/D 比例可能低于 15,这表明该船属于重排水量船只,相对于其重量而言帆面积较小。这类船只通常需要 12 节以上的风速才能轻快航行。',
37
+ },
38
+ {
39
+ question: '我应该排空水箱以提高性能吗?',
40
+ answer: '是的,减轻船只重量会直接提高 SA/D 比例,因为实际排水量减少了。排空淡水和燃油箱可以减少数百公斤的排水量,并显著提升该比例。',
41
+ },
42
+ {
43
+ question: '帆上的“Roach”(帆边外扩)是什么?',
44
+ answer: 'Roach 是主帆后缘(曳尾缘)的凸起曲线。它提供了超出由 P 和 E 定义的基础几何三角形之外的额外帆面积。竞赛类船只通常具有 aggressive Roach,并配合硬帆骨。',
45
+ },
46
+ {
47
+ question: '如何测量我船只的真实排水量?',
48
+ answer: '最可靠的方法是使用满载排水量(包括所有备品、水、燃油和在船人员)。建造商手册中的轻载排水量通常过于乐观。请使用您正常航行条件下的实际排水量。',
49
+ },
50
+ {
51
+ question: '在哪里可以找到我船只的 I, J, P 和 E 测量值?',
52
+ answer: '您可以在船主手册、ORC 或 IRC 等级证书,或者船级证书文档中找到它们。您也可以在船上用卷尺直接测量,或联系造船厂确认。',
53
+ },
54
+ ];
55
+
56
+ const howTo: SailAreaLocaleContent['howTo'] = [
57
+ {
58
+ name: '选择索具类型',
59
+ text: '在单桅 (Sloop)、双前帆 (Cutter) 或双桅 (Ketch) 索具之间选择。这决定了总帆面积的计算方式。',
60
+ },
61
+ {
62
+ name: '输入排水量',
63
+ text: '使用您船只的实际满载排水量(单位为公斤或磅)。该数值是计算 SA/D 比例的关键。',
64
+ },
65
+ {
66
+ name: '测量索具几何尺寸',
67
+ text: '输入 P(桅杆高度)、E(帆杆长度)、I(前三角高度)和 J(前三角底边长度)的测量值,单位为米或英尺。',
68
+ },
69
+ {
70
+ name: '调整热那亚帆重叠度',
71
+ text: '移动滑块以指示您的帆重叠比例:100% 为不重叠的三角帆,130% 为标准热那亚帆,155% 为大重叠热那亚帆。',
72
+ },
73
+ {
74
+ name: '解读 SA/D 比例',
75
+ text: '比例在 16 到 20 之间属于平衡的巡航船。超过 20 时,船只在微风下非常活跃,但在劲风条件下对操控要求更高。',
76
+ },
77
+ ];
78
+
79
+ const bibliography: SailAreaLocaleContent['bibliography'] = [
80
+ {
81
+ name: 'Society of Naval Architects and Marine Engineers - SNAME',
82
+ url: 'https://www.sname.org/',
83
+ },
84
+ {
85
+ name: 'ORC - Offshore Racing Congress',
86
+ url: 'https://orc.org/',
87
+ },
88
+ {
89
+ name: 'Elvstrom Sailmakers - Sail Manual',
90
+ url: 'https://www.elvstromsails.com/',
91
+ },
92
+ ];
93
+
94
+ const seo: SailAreaLocaleContent['seo'] = [
95
+ {
96
+ type: 'title',
97
+ text: '帆面积计算器:性能与比例完整指南',
98
+ level: 2,
99
+ },
100
+ {
101
+ type: 'paragraph',
102
+ html: '帆面积是任何帆船的“气动引擎”。它决定了船只能捕获多少风能,并结合其排水量,定义了其航海特性:是慢速巡航船还是灵敏的竞赛机器。正确计算此值是理解任何帆船行为的第一步。',
103
+ },
104
+ {
105
+ type: 'paragraph',
106
+ html: '航行涉及帆上的风力指向与船体上的水阻力之间的持续平衡。<strong>帆面积 / 排水量比例 (SA/D)</strong> 通过一个数值捕捉这种关系,使不同长度和排水量的船只能够在平等的基础上进行比较。',
107
+ },
108
+ {
109
+ type: 'stats',
110
+ items: [
111
+ { label: '理想巡航比例', value: '15-18', icon: 'mdi:anchor' },
112
+ { label: '竞赛型船只', value: '+24', icon: 'mdi:sailing' },
113
+ { label: '误差范围', value: '5-10%', icon: 'mdi:alert-circle-outline' },
114
+ ],
115
+ columns: 3,
116
+ },
117
+ {
118
+ type: 'title',
119
+ text: 'SA/D 比例有什么用途?',
120
+ level: 3,
121
+ },
122
+ {
123
+ type: 'paragraph',
124
+ html: '<strong>SA/D 比例</strong>是一种诊断工具,可让您在起航前预测船只行为。低比例表示船只坚固安全,但在轻风中较慢;高比例提供速度和“飞翔”感,但在风力增大时对组员技能要求更高。两者并无优劣之分:完全取决于预期的航行类型。',
125
+ },
126
+ {
127
+ type: 'title',
128
+ text: 'SA/D 比例参考表',
129
+ level: 4,
130
+ },
131
+ {
132
+ type: 'table',
133
+ headers: ['比例', '船只类型', '海上表现'],
134
+ rows: [
135
+ ['< 14', '重排水量 / 货运船只', '稳定但缓慢,需要持续的风力'],
136
+ ['14 - 16.5', '远洋远航巡航船', '平衡、舒适、上风性能好'],
137
+ ['16.5 - 20', '标准港池巡航船', '在微风中活跃,易于操控,多功能'],
138
+ ['20 - 25', '高性能巡航 / 运动型', '快速、要求高、在轻风中令人兴奋'],
139
+ ['> 25', '竞赛 / 极限运动型', '非常快且灵敏,需要专家级组员'],
140
+ ],
141
+ },
142
+ {
143
+ type: 'title',
144
+ text: '测量技术术语表 (I, J, P, E)',
145
+ level: 3,
146
+ },
147
+ {
148
+ type: 'glossary',
149
+ items: [
150
+ {
151
+ term: 'I (前三角高度)',
152
+ definition: '从甲板到前帆升降索在桅杆上连接点的垂直距离。定义了前三角的高度。',
153
+ },
154
+ {
155
+ term: 'J (前三角底边长度)',
156
+ definition: '从桅杆到船首(森林座)的水平距离。定义了前帆安装的前三角基准底边长度。',
157
+ },
158
+ {
159
+ term: 'P (桅杆高度)',
160
+ definition: '从主帆帆杆到桅杆顶部主帆升降索滑轮的距离。定义了主帆的高度。',
161
+ },
162
+ {
163
+ term: 'E (帆杆长度)',
164
+ definition: '从桅杆到帆杆末端主帆后角 (Clew) 的距离。定义了主帆的底边长度。',
165
+ },
166
+ ],
167
+ },
168
+ {
169
+ type: 'title',
170
+ text: '航海执照计算 (Yachtmaster)',
171
+ level: 3,
172
+ },
173
+ {
174
+ type: 'paragraph',
175
+ html: '帆面积计算和 SA/D 比例是 <strong>Yachtmaster</strong> 和近岸船长考试大纲的一部分。理解索具几何形状及其与排水量的关系对于做出海上安全决策至关重要:及时缩帆、选择正确的热那亚帆或在狂风来临前预估船只行为。',
176
+ },
177
+ {
178
+ type: 'tip',
179
+ title: '顺风帆与安全',
180
+ html: '对于远洋或远距离航行,SA/D 比例在 16 到 18 之间提供了速度与安全性之间的最佳平衡。比例超过 22 的船只可能在仅有 4-5 级蒲福风级时就需要缩帆。',
181
+ },
182
+ {
183
+ type: 'title',
184
+ text: '热那亚帆重叠度如何影响性能?',
185
+ level: 4,
186
+ },
187
+ {
188
+ type: 'paragraph',
189
+ html: '<strong>热那亚帆 (Genoa)</strong> 是最大的头帆,其后角位于桅杆后方,与主帆“重叠”。重叠百分比表示帆宽垂直线 (LP) 与 J 距离相比长出多少。150% 的热那亚帆具有相当于 J 长度 150% 的 LP,提供比简单的前三角帆大得多的面积。',
190
+ },
191
+ {
192
+ type: 'comparative',
193
+ items: [
194
+ {
195
+ title: 'Dacron (巡航级)',
196
+ description: '巡航帆的经典材料。坚固且易于维护。',
197
+ points: [
198
+ '高耐用性和耐紫外线性能',
199
+ '维护成本低',
200
+ '重量较重且在载荷下易拉伸',
201
+ '近岸和远航巡航的理想选择',
202
+ ],
203
+ },
204
+ {
205
+ title: '层压材料 (竞赛级)',
206
+ description: '高科技材料,如凯夫拉 (Kevlar)、Spectra 或迪尼玛 (Dyneema)。',
207
+ highlight: true,
208
+ points: [
209
+ '极低拉伸:最大化气动效率',
210
+ '比 Dacron 轻得多',
211
+ '成本较高且使用寿命较短',
212
+ '对于 SA/D 比例 > 22 的船只是必不可少的',
213
+ ],
214
+ },
215
+ ],
216
+ columns: 2,
217
+ },
218
+ {
219
+ type: 'title',
220
+ text: '航行物理学与稳定性',
221
+ level: 3,
222
+ },
223
+ {
224
+ type: 'paragraph',
225
+ html: '帆面积产生驱动力,但也会产生 <strong>倾侧力矩 (Heeling moment)</strong>,倾向于使船只倾覆。稳定性通过船只抵抗这种倾侧力的复原力矩来衡量。压载较少的船只具有高 SA/D 比例可能很危险,而同样的比例在具有深重龙骨的船上则是完全可以掌控的。',
226
+ },
227
+ {
228
+ type: 'paragraph',
229
+ html: '为了计算实际可用功率,造船工程师通常将 <strong>排水量-长度比 (DLR)</strong> 与 SA/D 结合使用。这两个比例共同精准描述了一艘船是海上的“拖船”还是“竞速滑行艇”。',
230
+ },
231
+ {
232
+ type: 'tip',
233
+ title: '稳定性与安全',
234
+ html: '切勿孤立地评估 SA/D。一艘比例为 22 且复原角为 90 度的帆船远比比例为 18 且复原角为 60 度的帆船安全。请务必参考您船只的稳定性曲线。',
235
+ },
236
+ ];
237
+
238
+ const schemas: SailAreaLocaleContent['schemas'] = [
239
+ {
240
+ '@context': 'https://schema.org',
241
+ '@type': 'SoftwareApplication',
242
+ name: title,
243
+ description,
244
+ applicationCategory: 'UtilityApplication',
245
+ operatingSystem: 'Web',
246
+ offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR' },
247
+ } as WithContext<SoftwareApplication>,
248
+ {
249
+ '@context': 'https://schema.org',
250
+ '@type': 'FAQPage',
251
+ mainEntity: faq.map((item) => ({
252
+ '@type': 'Question',
253
+ name: item.question,
254
+ acceptedAnswer: { '@type': 'Answer', text: item.answer },
255
+ })),
256
+ } as WithContext<FAQPage>,
257
+ {
258
+ '@context': 'https://schema.org',
259
+ '@type': 'HowTo',
260
+ name: `如何使用: ${title}`,
261
+ step: howTo.map((s) => ({ '@type': 'HowToStep', name: s.name, text: s.text })),
262
+ } as WithContext<HowTo>,
263
+ ];
264
+
265
+ export const content: SailAreaLocaleContent = {
266
+ slug,
267
+ title,
268
+ description,
269
+ ui,
270
+ seo,
271
+ faq,
272
+ bibliography,
273
+ howTo,
274
+ schemas,
275
+ };
@@ -40,6 +40,18 @@ export const sailArea: NauticalToolEntry<SailAreaUI> = {
40
40
  es: () => import('./i18n/es').then((m) => m.content),
41
41
  en: () => import('./i18n/en').then((m) => m.content),
42
42
  fr: () => import('./i18n/fr').then((m) => m.content),
43
+ de: () => import('./i18n/de').then((m) => m.content),
44
+ id: () => import('./i18n/id').then((m) => m.content),
45
+ it: () => import('./i18n/it').then((m) => m.content),
46
+ ja: () => import('./i18n/ja').then((m) => m.content),
47
+ ko: () => import('./i18n/ko').then((m) => m.content),
48
+ nl: () => import('./i18n/nl').then((m) => m.content),
49
+ pl: () => import('./i18n/pl').then((m) => m.content),
50
+ pt: () => import('./i18n/pt').then((m) => m.content),
51
+ ru: () => import('./i18n/ru').then((m) => m.content),
52
+ sv: () => import('./i18n/sv').then((m) => m.content),
53
+ tr: () => import('./i18n/tr').then((m) => m.content),
54
+ zh: () => import('./i18n/zh').then((m) => m.content),
43
55
  },
44
56
  };
45
57
 
@@ -1,5 +1,4 @@
1
1
  ---
2
- import './style.css';
3
2
  import type { SpeedConverterUI } from './index';
4
3
  interface Props { ui: SpeedConverterUI; }
5
4
  const { ui } = Astro.props;
@@ -123,3 +122,245 @@ const bd = JSON.parse(ui.beaufortDataJson) as { force: number; name: string; sea
123
122
  iKn.value = savedKn > 0 ? String(savedKn) : '';
124
123
  sync('val-kn', savedKn);
125
124
  </script>
125
+
126
+ <style>
127
+ .speed-converter {
128
+ --n-bg: #fff;
129
+ --n-bg-muted: #f1f5f9;
130
+ --n-text: #0f172a;
131
+ --n-text-muted: #475569;
132
+ --n-text-dim: #64748b;
133
+ --n-border: #e2e8f0;
134
+ --n-shadow: rgba(0, 0, 0, 0.05);
135
+ --n-primary: #3b82f6;
136
+ --n-primary-on: #fff;
137
+ --n-accent: #6366f1;
138
+ --n-cyan: #0891b2;
139
+ --n-success: #10b981;
140
+ --n-warning: #f59e0b;
141
+ --n-error: #f43f5e;
142
+
143
+ max-width: 900px;
144
+ margin: 0 auto;
145
+ display: flex;
146
+ flex-direction: column;
147
+ gap: 2rem;
148
+ }
149
+
150
+ :global(.theme-dark) .speed-converter {
151
+ --n-bg: #0f172a;
152
+ --n-bg-muted: #1e293b;
153
+ --n-text: #f8fafc;
154
+ --n-text-muted: #94a3b8;
155
+ --n-text-dim: #64748b;
156
+ --n-border: #334155;
157
+ --n-shadow: rgba(0, 0, 0, 0.3);
158
+ --n-primary: #60a5fa;
159
+ --n-primary-on: #fff;
160
+ --n-accent: #818cf8;
161
+ --n-cyan: #22d3ee;
162
+ --n-success: #34d399;
163
+ --n-warning: #fbbf24;
164
+ --n-error: #fb7185;
165
+ }
166
+
167
+ .sc-input-grid {
168
+ display: grid;
169
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
170
+ gap: 1rem;
171
+ background: var(--n-bg);
172
+ border: 1px solid var(--n-border);
173
+ border-radius: 1.5rem;
174
+ padding: 2rem;
175
+ }
176
+
177
+ .sc-input-group {
178
+ display: flex;
179
+ flex-direction: column;
180
+ gap: 0.5rem;
181
+ }
182
+
183
+ .sc-input-group label {
184
+ font-size: 0.8rem;
185
+ font-weight: 600;
186
+ color: var(--n-text-muted);
187
+ text-transform: uppercase;
188
+ }
189
+
190
+ .sc-input-wrapper {
191
+ background: var(--n-bg-muted);
192
+ border: 2px solid var(--n-border);
193
+ border-radius: 0.8rem;
194
+ padding: 0.8rem 1rem;
195
+ transition: border-color 0.2s;
196
+ }
197
+
198
+ .sc-input-wrapper:focus-within {
199
+ border-color: var(--n-cyan);
200
+ }
201
+
202
+ .sc-input-wrapper input {
203
+ background: transparent;
204
+ border: none;
205
+ outline: none;
206
+ color: var(--n-text);
207
+ font-size: 1.5rem;
208
+ font-weight: 800;
209
+ width: 100%;
210
+ }
211
+
212
+ .sc-input-wrapper input::-webkit-outer-spin-button,
213
+ .sc-input-wrapper input::-webkit-inner-spin-button {
214
+ appearance: none;
215
+ }
216
+
217
+ .sc-beaufort-summary {
218
+ background: var(--n-primary);
219
+ color: var(--n-primary-on);
220
+ border-radius: 1.5rem;
221
+ padding: 2rem;
222
+ display: grid;
223
+ grid-template-columns: auto 1fr;
224
+ gap: 1rem 2rem;
225
+ align-items: center;
226
+ }
227
+
228
+ .sc-force-circle {
229
+ width: 80px;
230
+ height: 80px;
231
+ border-radius: 50%;
232
+ background: rgba(255, 255, 255, 0.15);
233
+ display: flex;
234
+ align-items: center;
235
+ justify-content: center;
236
+ font-size: 2.5rem;
237
+ font-weight: 800;
238
+ color: var(--n-primary-on);
239
+ flex-shrink: 0;
240
+ }
241
+
242
+ .sc-force-text-box {
243
+ display: flex;
244
+ flex-direction: column;
245
+ gap: 0.3rem;
246
+ }
247
+
248
+ .sc-force-name {
249
+ margin: 0;
250
+ font-size: 1.4rem;
251
+ font-weight: 800;
252
+ color: var(--n-primary-on);
253
+ }
254
+
255
+ .sc-force-detail {
256
+ margin: 0;
257
+ opacity: 0.8;
258
+ font-size: 0.9rem;
259
+ color: var(--n-primary-on);
260
+ }
261
+
262
+ .sc-sea-state-box {
263
+ grid-column: 1 / -1;
264
+ background: rgba(255, 255, 255, 0.1);
265
+ border-radius: 1rem;
266
+ padding: 1rem 1.5rem;
267
+ }
268
+
269
+ .sc-sea-text .label {
270
+ font-size: 0.7rem;
271
+ text-transform: uppercase;
272
+ opacity: 0.7;
273
+ color: var(--n-primary-on);
274
+ font-weight: 700;
275
+ }
276
+
277
+ .sc-sea-text p {
278
+ margin: 0.2rem 0 0;
279
+ font-weight: 600;
280
+ color: var(--n-primary-on);
281
+ }
282
+
283
+ .sc-table-container {
284
+ background: var(--n-bg);
285
+ border: 1px solid var(--n-border);
286
+ border-radius: 1.5rem;
287
+ overflow: hidden;
288
+ }
289
+
290
+ .sc-table-container h3 {
291
+ padding: 1.5rem;
292
+ margin: 0;
293
+ font-size: 1rem;
294
+ color: var(--n-text-muted);
295
+ border-bottom: 1px solid var(--n-border);
296
+ font-weight: 700;
297
+ }
298
+
299
+ .sc-scroll-area {
300
+ overflow-x: auto;
301
+ }
302
+
303
+ .sc-beaufort-table {
304
+ width: 100%;
305
+ border-collapse: collapse;
306
+ }
307
+
308
+ .sc-beaufort-table th {
309
+ text-align: left;
310
+ padding: 0.8rem 1rem;
311
+ font-size: 0.75rem;
312
+ color: var(--n-text-muted);
313
+ text-transform: uppercase;
314
+ border-bottom: 2px solid var(--n-border);
315
+ }
316
+
317
+ .sc-beaufort-table td {
318
+ padding: 0.8rem 1rem;
319
+ font-size: 0.9rem;
320
+ color: var(--n-text-muted);
321
+ border-bottom: 1px solid var(--n-border);
322
+ }
323
+
324
+ .sc-clickable-row {
325
+ cursor: pointer;
326
+ transition: background 0.15s;
327
+ }
328
+
329
+ .sc-clickable-row:hover {
330
+ background: var(--n-bg-muted);
331
+ }
332
+
333
+ .sc-clickable-row.active {
334
+ background: var(--n-primary);
335
+ }
336
+
337
+ .sc-clickable-row.active td {
338
+ color: var(--n-primary-on);
339
+ }
340
+
341
+ .sc-force-tag {
342
+ background: var(--n-bg-muted);
343
+ padding: 0.2rem 0.5rem;
344
+ border-radius: 0.4rem;
345
+ font-weight: 700;
346
+ font-size: 0.85rem;
347
+ color: var(--n-text);
348
+ }
349
+
350
+ .sc-clickable-row.active .sc-force-tag {
351
+ background: rgba(255, 255, 255, 0.2);
352
+ color: var(--n-primary-on);
353
+ }
354
+
355
+ @media (max-width: 640px) {
356
+ .sc-beaufort-summary {
357
+ grid-template-columns: 1fr;
358
+ }
359
+
360
+ .sc-force-circle {
361
+ width: 60px;
362
+ height: 60px;
363
+ font-size: 2rem;
364
+ }
365
+ }
366
+ </style>