@jjlmoya/utils-diy 1.1.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 (135) hide show
  1. package/package.json +60 -0
  2. package/src/category/i18n/en.ts +110 -0
  3. package/src/category/i18n/es.ts +110 -0
  4. package/src/category/i18n/fr.ts +101 -0
  5. package/src/category/index.ts +25 -0
  6. package/src/category/seo.astro +15 -0
  7. package/src/components/PreviewNavSidebar.astro +116 -0
  8. package/src/components/PreviewToolbar.astro +143 -0
  9. package/src/data.ts +11 -0
  10. package/src/env.d.ts +5 -0
  11. package/src/index.ts +57 -0
  12. package/src/layouts/PreviewLayout.astro +117 -0
  13. package/src/pages/[locale]/[slug].astro +146 -0
  14. package/src/pages/[locale].astro +251 -0
  15. package/src/pages/index.astro +4 -0
  16. package/src/tests/faq_count.test.ts +19 -0
  17. package/src/tests/locale_completeness.test.ts +42 -0
  18. package/src/tests/mocks/astro_mock.js +2 -0
  19. package/src/tests/no_h1_in_components.test.ts +48 -0
  20. package/src/tests/schemas_fulfillment.test.ts +23 -0
  21. package/src/tests/seo_length.test.ts +22 -0
  22. package/src/tests/title_quality.test.ts +55 -0
  23. package/src/tests/tool_validation.test.ts +17 -0
  24. package/src/tool/balusterCalculator/bibliography.astro +14 -0
  25. package/src/tool/balusterCalculator/component.astro +605 -0
  26. package/src/tool/balusterCalculator/i18n/en.ts +264 -0
  27. package/src/tool/balusterCalculator/i18n/es.ts +264 -0
  28. package/src/tool/balusterCalculator/i18n/fr.ts +264 -0
  29. package/src/tool/balusterCalculator/index.ts +33 -0
  30. package/src/tool/balusterCalculator/seo.astro +15 -0
  31. package/src/tool/balusterCalculator/ui.ts +15 -0
  32. package/src/tool/clayCalculator/bibliography.astro +14 -0
  33. package/src/tool/clayCalculator/component.astro +731 -0
  34. package/src/tool/clayCalculator/i18n/en.ts +183 -0
  35. package/src/tool/clayCalculator/i18n/es.ts +183 -0
  36. package/src/tool/clayCalculator/i18n/fr.ts +183 -0
  37. package/src/tool/clayCalculator/index.ts +33 -0
  38. package/src/tool/clayCalculator/seo.astro +15 -0
  39. package/src/tool/clayCalculator/ui.ts +19 -0
  40. package/src/tool/concreteCalculator/bibliography.astro +13 -0
  41. package/src/tool/concreteCalculator/component.astro +1089 -0
  42. package/src/tool/concreteCalculator/i18n/en.ts +201 -0
  43. package/src/tool/concreteCalculator/i18n/es.ts +201 -0
  44. package/src/tool/concreteCalculator/i18n/fr.ts +201 -0
  45. package/src/tool/concreteCalculator/index.ts +28 -0
  46. package/src/tool/concreteCalculator/seo.astro +14 -0
  47. package/src/tool/concreteCalculator/ui.ts +35 -0
  48. package/src/tool/cutOptimizer/bibliography.astro +13 -0
  49. package/src/tool/cutOptimizer/component.astro +825 -0
  50. package/src/tool/cutOptimizer/i18n/en.ts +178 -0
  51. package/src/tool/cutOptimizer/i18n/es.ts +178 -0
  52. package/src/tool/cutOptimizer/i18n/fr.ts +178 -0
  53. package/src/tool/cutOptimizer/index.ts +28 -0
  54. package/src/tool/cutOptimizer/optimizer.ts +199 -0
  55. package/src/tool/cutOptimizer/seo.astro +14 -0
  56. package/src/tool/cutOptimizer/ui.ts +25 -0
  57. package/src/tool/drillCalculator/bibliography.astro +13 -0
  58. package/src/tool/drillCalculator/component.astro +1210 -0
  59. package/src/tool/drillCalculator/engine.ts +63 -0
  60. package/src/tool/drillCalculator/i18n/en.ts +137 -0
  61. package/src/tool/drillCalculator/i18n/es.ts +137 -0
  62. package/src/tool/drillCalculator/i18n/fr.ts +137 -0
  63. package/src/tool/drillCalculator/index.ts +28 -0
  64. package/src/tool/drillCalculator/seo.astro +14 -0
  65. package/src/tool/drillCalculator/ui.ts +41 -0
  66. package/src/tool/drillSharpener/bibliography.astro +13 -0
  67. package/src/tool/drillSharpener/component.astro +712 -0
  68. package/src/tool/drillSharpener/engine.ts +42 -0
  69. package/src/tool/drillSharpener/i18n/en.ts +121 -0
  70. package/src/tool/drillSharpener/i18n/es.ts +121 -0
  71. package/src/tool/drillSharpener/i18n/fr.ts +121 -0
  72. package/src/tool/drillSharpener/index.ts +31 -0
  73. package/src/tool/drillSharpener/seo.astro +14 -0
  74. package/src/tool/drillSharpener/ui.ts +53 -0
  75. package/src/tool/epoxyCalculator/bibliography.astro +14 -0
  76. package/src/tool/epoxyCalculator/component.astro +888 -0
  77. package/src/tool/epoxyCalculator/i18n/en.ts +195 -0
  78. package/src/tool/epoxyCalculator/i18n/es.ts +195 -0
  79. package/src/tool/epoxyCalculator/i18n/fr.ts +195 -0
  80. package/src/tool/epoxyCalculator/index.ts +33 -0
  81. package/src/tool/epoxyCalculator/seo.astro +15 -0
  82. package/src/tool/epoxyCalculator/ui.ts +22 -0
  83. package/src/tool/furnitureFit/bibliography.astro +13 -0
  84. package/src/tool/furnitureFit/component.astro +552 -0
  85. package/src/tool/furnitureFit/engine.ts +51 -0
  86. package/src/tool/furnitureFit/i18n/en.ts +152 -0
  87. package/src/tool/furnitureFit/i18n/es.ts +152 -0
  88. package/src/tool/furnitureFit/i18n/fr.ts +152 -0
  89. package/src/tool/furnitureFit/index.ts +28 -0
  90. package/src/tool/furnitureFit/seo.astro +14 -0
  91. package/src/tool/furnitureFit/ui.ts +21 -0
  92. package/src/tool/mortarCalculator/bibliography.astro +13 -0
  93. package/src/tool/mortarCalculator/component.astro +1139 -0
  94. package/src/tool/mortarCalculator/i18n/en.ts +219 -0
  95. package/src/tool/mortarCalculator/i18n/es.ts +205 -0
  96. package/src/tool/mortarCalculator/i18n/fr.ts +220 -0
  97. package/src/tool/mortarCalculator/index.ts +24 -0
  98. package/src/tool/mortarCalculator/seo.astro +14 -0
  99. package/src/tool/mortarCalculator/ui.ts +37 -0
  100. package/src/tool/passepartoutCalculator/bibliography.astro +13 -0
  101. package/src/tool/passepartoutCalculator/component.astro +741 -0
  102. package/src/tool/passepartoutCalculator/i18n/en.ts +178 -0
  103. package/src/tool/passepartoutCalculator/i18n/es.ts +178 -0
  104. package/src/tool/passepartoutCalculator/i18n/fr.ts +178 -0
  105. package/src/tool/passepartoutCalculator/index.ts +28 -0
  106. package/src/tool/passepartoutCalculator/seo.astro +14 -0
  107. package/src/tool/passepartoutCalculator/ui.ts +17 -0
  108. package/src/tool/stairCalculator/bibliography.astro +52 -0
  109. package/src/tool/stairCalculator/component.astro +766 -0
  110. package/src/tool/stairCalculator/engine.ts +128 -0
  111. package/src/tool/stairCalculator/i18n/en.ts +149 -0
  112. package/src/tool/stairCalculator/i18n/es.ts +149 -0
  113. package/src/tool/stairCalculator/i18n/fr.ts +149 -0
  114. package/src/tool/stairCalculator/index.ts +31 -0
  115. package/src/tool/stairCalculator/seo.astro +211 -0
  116. package/src/tool/stairCalculator/ui.ts +109 -0
  117. package/src/tool/thermalExpansionCalculator/bibliography.astro +13 -0
  118. package/src/tool/thermalExpansionCalculator/component.astro +771 -0
  119. package/src/tool/thermalExpansionCalculator/engine.ts +23 -0
  120. package/src/tool/thermalExpansionCalculator/i18n/en.ts +174 -0
  121. package/src/tool/thermalExpansionCalculator/i18n/es.ts +174 -0
  122. package/src/tool/thermalExpansionCalculator/i18n/fr.ts +174 -0
  123. package/src/tool/thermalExpansionCalculator/index.ts +28 -0
  124. package/src/tool/thermalExpansionCalculator/seo.astro +14 -0
  125. package/src/tool/thermalExpansionCalculator/ui.ts +41 -0
  126. package/src/tool/voltageDropCalculator/bibliography.astro +13 -0
  127. package/src/tool/voltageDropCalculator/component.astro +1022 -0
  128. package/src/tool/voltageDropCalculator/i18n/en.ts +155 -0
  129. package/src/tool/voltageDropCalculator/i18n/es.ts +155 -0
  130. package/src/tool/voltageDropCalculator/i18n/fr.ts +148 -0
  131. package/src/tool/voltageDropCalculator/index.ts +28 -0
  132. package/src/tool/voltageDropCalculator/seo.astro +14 -0
  133. package/src/tool/voltageDropCalculator/ui.ts +22 -0
  134. package/src/tools.ts +16 -0
  135. package/src/types.ts +72 -0
@@ -0,0 +1,712 @@
1
+ ---
2
+ import type { DrillSharpenerUI } from "./ui";
3
+ interface Props {
4
+ ui?: DrillSharpenerUI;
5
+ }
6
+ const { ui } = Astro.props;
7
+ const t = (ui ?? {}) as DrillSharpenerUI;
8
+ ---
9
+
10
+ <div class="drillsharp-root" id="drill-app">
11
+ <div class="drillsharp-layout">
12
+ <section class="drillsharp-gauge">
13
+ <svg class="drillsharp-svg" viewBox="0 0 500 500" id="gauge-svg">
14
+ <line
15
+ x1="250"
16
+ y1="20"
17
+ x2="250"
18
+ y2="480"
19
+ stroke="currentColor"
20
+ stroke-width="2"
21
+ stroke-dasharray="10,10"></line>
22
+ <line
23
+ x1="20"
24
+ y1="250"
25
+ x2="480"
26
+ y2="250"
27
+ stroke="currentColor"
28
+ stroke-width="1"
29
+ stroke-dasharray="10,10"></line>
30
+ <rect x="249" y="250" width="2" height="230" fill="currentColor" rx="1"
31
+ ></rect>
32
+ <g
33
+ class="drillsharp-guide-circles"
34
+ fill="none"
35
+ stroke="currentColor"
36
+ stroke-width="1"
37
+ >
38
+ <circle cx="250" cy="250" r="30" data-val="3"></circle>
39
+ <circle cx="250" cy="250" r="60" data-val="6"></circle>
40
+ <circle cx="250" cy="250" r="100" data-val="10"></circle>
41
+ <circle cx="250" cy="250" r="130" data-val="13"></circle>
42
+ <circle cx="250" cy="250" r="200" data-val="20"></circle>
43
+ </g>
44
+ <g id="drillsharp-gauge-lines" class="drillsharp-gauge-lines">
45
+ <line
46
+ id="gl"
47
+ x1="250"
48
+ y1="250"
49
+ x2="50"
50
+ y2="100"
51
+ stroke="var(--drillsharp-accent)"
52
+ stroke-width="3"
53
+ stroke-linecap="round"></line>
54
+ <line
55
+ id="gr"
56
+ x1="250"
57
+ y1="250"
58
+ x2="450"
59
+ y2="100"
60
+ stroke="var(--drillsharp-accent)"
61
+ stroke-width="3"
62
+ stroke-linecap="round"></line>
63
+ <circle cx="250" cy="250" r="6" fill="var(--drillsharp-accent)"></circle>
64
+ </g>
65
+ <text
66
+ id="drillsharp-angle-text"
67
+ x="250"
68
+ y="235"
69
+ text-anchor="middle"
70
+ fill="var(--drillsharp-accent)"
71
+ font-size="28"
72
+ font-weight="900">118°</text
73
+ >
74
+ </svg>
75
+ <div class="drillsharp-instruction">
76
+ <span>{t.gaugeInstruction}</span>
77
+ </div>
78
+ </section>
79
+
80
+ <aside class="drillsharp-controls">
81
+ <div class="drillsharp-group">
82
+ <h4>{t.labelMaterial}</h4>
83
+ <div class="drillsharp-material-grid">
84
+ <button
85
+ class="drillsharp-mat-btn active"
86
+ data-angle="118"
87
+ data-vc="25"
88
+ data-label="Acero / Hierro"
89
+ data-id="steel">{t.matSteel}</button
90
+ >
91
+ <button
92
+ class="drillsharp-mat-btn"
93
+ data-angle="135"
94
+ data-vc="12"
95
+ data-label="Inoxidable"
96
+ data-id="inox">{t.matInox}</button
97
+ >
98
+ <button
99
+ class="drillsharp-mat-btn"
100
+ data-angle="140"
101
+ data-vc="8"
102
+ data-label="Aceros Duros"
103
+ data-id="hard">{t.matHard}</button
104
+ >
105
+ <button
106
+ class="drillsharp-mat-btn"
107
+ data-angle="90"
108
+ data-vc="40"
109
+ data-label="Latón / Cobre"
110
+ data-id="brass">{t.matBrass}</button
111
+ >
112
+ <button
113
+ class="drillsharp-mat-btn"
114
+ data-angle="60"
115
+ data-vc="60"
116
+ data-label="Plásticos"
117
+ data-id="plastic">{t.matPlastic}</button
118
+ >
119
+ <button
120
+ class="drillsharp-mat-btn"
121
+ data-angle="80"
122
+ data-vc="35"
123
+ data-label="Madera"
124
+ data-id="wood">{t.matWood}</button
125
+ >
126
+ </div>
127
+ </div>
128
+
129
+ <div class="drillsharp-group">
130
+ <h4>{t.labelDiameter}</h4>
131
+ <div class="drillsharp-stepper">
132
+ <button type="button" class="drillsharp-step-btn" id="btn-minus">−</button>
133
+ <input
134
+ type="number"
135
+ id="diam-input"
136
+ value="10"
137
+ step="0.5"
138
+ min="1"
139
+ max="50"
140
+ />
141
+ <button type="button" class="drillsharp-step-btn" id="btn-plus">+</button>
142
+ </div>
143
+
144
+ <div class="drillsharp-results">
145
+ <div class="drillsharp-res-item">
146
+ <span class="drillsharp-res-label">{t.labelVelocity}</span>
147
+ <div class="drillsharp-res-value-box">
148
+ <span class="drillsharp-res-value" id="rpm-display">796</span>
149
+ <span class="drillsharp-res-unit">{t.unitRpm}</span>
150
+ </div>
151
+ </div>
152
+ <div class="drillsharp-res-item">
153
+ <span class="drillsharp-res-label">{t.labelCooling}</span>
154
+ <div class="drillsharp-res-value-box">
155
+ <span
156
+ class="drillsharp-res-value"
157
+ id="cooling-display"
158
+ style="font-size: 0.8rem; color: var(--drillsharp-accent);"
159
+ >TALADRINA</span
160
+ >
161
+ </div>
162
+ </div>
163
+ </div>
164
+ </div>
165
+
166
+ <button
167
+ class="drillsharp-diag-btn"
168
+ id="trigger-diag"
169
+ title="Si la broca no corta, pulsa aquí"
170
+ >
171
+ {t.btnDiagnosis}
172
+ </button>
173
+ </aside>
174
+ </div>
175
+
176
+ <div class="drillsharp-modal" id="diag-modal">
177
+ <div class="drillsharp-modal-header">
178
+ <h3>{t.diagTitle}</h3>
179
+ <button type="button" class="drillsharp-modal-close" id="close-modal">×</button>
180
+ </div>
181
+
182
+ <div class="drillsharp-diag-item">
183
+ <strong>{t.diagIssue1}</strong>
184
+ <p>{t.diagIssue1Desc}</p>
185
+ <div class="drillsharp-diag-img">
186
+ <svg viewBox="0 0 160 60" width="100%">
187
+ <path
188
+ d="M10,45 L40,15 L70,45 Z"
189
+ fill="none"
190
+ stroke="#ef4444"
191
+ stroke-width="2"></path>
192
+ <line
193
+ x1="40"
194
+ y1="15"
195
+ x2="70"
196
+ y2="15"
197
+ stroke="#ef444430"
198
+ stroke-width="1"
199
+ stroke-dasharray="3,3"></line>
200
+ <path
201
+ d="M90,45 L120,15 L150,25 L150,45 Z"
202
+ fill="none"
203
+ stroke="#22c55e"
204
+ stroke-width="2"></path>
205
+ <line
206
+ x1="120"
207
+ y1="15"
208
+ x2="150"
209
+ y2="15"
210
+ stroke="#22c55e30"
211
+ stroke-width="1"
212
+ stroke-dasharray="3,3"></line>
213
+ <text x="10" y="58" fill="#ef4444" font-size="7">MAL: Plano</text>
214
+ <text x="90" y="58" fill="#22c55e" font-size="7">OK: Destalonado</text
215
+ >
216
+ </svg>
217
+ </div>
218
+ </div>
219
+
220
+ <div class="drillsharp-diag-item">
221
+ <strong>{t.diagIssue2}</strong>
222
+ <p>{t.diagIssue2Desc}</p>
223
+ </div>
224
+
225
+ <div class="drillsharp-diag-item">
226
+ <strong>{t.diagIssue3}</strong>
227
+ <p>{t.diagIssue3Desc}</p>
228
+ </div>
229
+ </div>
230
+ </div>
231
+
232
+ <script>
233
+ import { calculateSharpener } from "./engine";
234
+
235
+ const state = { angle: 118, vc: 25, diameter: 10, materialId: "steel" };
236
+
237
+ const ui = {
238
+ gaugeL: document.getElementById("gl") as SVGLineElement,
239
+ gaugeR: document.getElementById("gr") as SVGLineElement,
240
+ angleText: document.getElementById("drillsharp-angle-text") as SVGTextElement,
241
+ rpmDisplay: document.getElementById("rpm-display") as HTMLElement,
242
+ coolingDisplay: document.getElementById("cooling-display") as HTMLElement,
243
+ diamInput: document.getElementById("diam-input") as HTMLInputElement,
244
+ btnMinus: document.getElementById("btn-minus") as HTMLElement,
245
+ btnPlus: document.getElementById("btn-plus") as HTMLElement,
246
+ diagTrigger: document.getElementById("trigger-diag") as HTMLElement,
247
+ modal: document.getElementById("diag-modal") as HTMLElement,
248
+ modalClose: document.getElementById("close-modal") as HTMLElement,
249
+ };
250
+
251
+ function updateGauge() {
252
+ if (!ui.gaugeL || !ui.gaugeR) return;
253
+ const halfRad = (state.angle / 2) * (Math.PI / 180);
254
+ const len = 250;
255
+ const lx2 = 250 - Math.sin(halfRad) * len;
256
+ const ly2 = 250 + Math.cos(halfRad) * len;
257
+ const rx2 = 250 + Math.sin(halfRad) * len;
258
+ const ry2 = 250 + Math.cos(halfRad) * len;
259
+
260
+ ui.gaugeL.setAttribute("x2", lx2.toString());
261
+ ui.gaugeL.setAttribute("y2", ly2.toString());
262
+ ui.gaugeR.setAttribute("x2", rx2.toString());
263
+ ui.gaugeR.setAttribute("y2", ry2.toString());
264
+ if (ui.angleText) ui.angleText.textContent = `${state.angle}°`;
265
+ }
266
+
267
+ function updateResults() {
268
+ const result = calculateSharpener(state.materialId, state.diameter);
269
+ if (ui.rpmDisplay) ui.rpmDisplay.textContent = result.rpm.toLocaleString();
270
+ if (ui.coolingDisplay) ui.coolingDisplay.textContent = result.cooling;
271
+ }
272
+
273
+ function refresh() {
274
+ updateGauge();
275
+ updateResults();
276
+ }
277
+
278
+ document.querySelectorAll(".drillsharp-mat-btn").forEach((btn) => {
279
+ btn.addEventListener("click", () => {
280
+ document
281
+ .querySelectorAll(".drillsharp-mat-btn")
282
+ .forEach((b) => b.classList.remove("active"));
283
+ btn.classList.add("active");
284
+ state.angle = parseInt(btn.getAttribute("data-angle") || "118");
285
+ state.vc = parseInt(btn.getAttribute("data-vc") || "25");
286
+ state.materialId = btn.getAttribute("data-id") || "steel";
287
+ refresh();
288
+ });
289
+ });
290
+
291
+ ui.diamInput?.addEventListener("input", () => {
292
+ state.diameter = parseFloat(ui.diamInput.value) || 1;
293
+ refresh();
294
+ });
295
+
296
+ ui.btnMinus?.addEventListener("click", () => {
297
+ const v = Math.max(1, parseFloat(ui.diamInput.value) - 0.5);
298
+ ui.diamInput.value = v.toString();
299
+ state.diameter = v;
300
+ refresh();
301
+ });
302
+
303
+ ui.btnPlus?.addEventListener("click", () => {
304
+ const v = Math.min(50, parseFloat(ui.diamInput.value) + 0.5);
305
+ ui.diamInput.value = v.toString();
306
+ state.diameter = v;
307
+ refresh();
308
+ });
309
+
310
+ ui.diagTrigger?.addEventListener("click", () =>
311
+ ui.modal?.classList.add("active"),
312
+ );
313
+ ui.modalClose?.addEventListener("click", () =>
314
+ ui.modal?.classList.remove("active"),
315
+ );
316
+
317
+ refresh();
318
+ </script>
319
+
320
+ <style>
321
+ :root {
322
+ --drillsharp-primary: #0284c7;
323
+ --drillsharp-accent: #0284c7;
324
+ --drillsharp-text: #0f172a;
325
+ --drillsharp-text-muted: #475569;
326
+ --drillsharp-bg-dark: #f1f5f9;
327
+ --drillsharp-bg-panel: #fff;
328
+ --drillsharp-border: #cbd5e1;
329
+ --drillsharp-button-bg: #e2e8f0;
330
+ --drillsharp-button-hover: #cbd5e1;
331
+ }
332
+
333
+ :global(.theme-dark) {
334
+ --drillsharp-primary: #38bdf8;
335
+ --drillsharp-accent: #38bdf8;
336
+ --drillsharp-text: #f8fafc;
337
+ --drillsharp-text-muted: #94a3b8;
338
+ --drillsharp-bg-dark: #000;
339
+ --drillsharp-bg-panel: #0a0f1d;
340
+ --drillsharp-border: #1e293b;
341
+ --drillsharp-button-bg: #1e293b;
342
+ --drillsharp-button-hover: #334155;
343
+ }
344
+
345
+ .drillsharp-root {
346
+ max-width: 1200px;
347
+ margin: 1rem auto;
348
+ padding: 0 1rem;
349
+ color: var(--drillsharp-text);
350
+ }
351
+
352
+ .drillsharp-layout {
353
+ display: grid;
354
+ grid-template-columns: minmax(0, 1fr) 340px;
355
+ gap: 1.5rem;
356
+ background: var(--drillsharp-bg-dark);
357
+ border-radius: 2.5rem;
358
+ padding: 2rem;
359
+ border: 1px solid var(--drillsharp-border);
360
+ box-shadow: 0 30px 60px -12px rgba(0, 0, 0, 0.1);
361
+ overflow: hidden;
362
+ }
363
+
364
+ .drillsharp-gauge {
365
+ position: relative;
366
+ display: flex;
367
+ flex-direction: column;
368
+ align-items: center;
369
+ justify-content: center;
370
+ background: radial-gradient(
371
+ circle at center,
372
+ var(--drillsharp-bg-panel) 0%,
373
+ var(--drillsharp-bg-dark) 100%
374
+ );
375
+ border-radius: 2rem;
376
+ min-height: 550px;
377
+ border: 1px solid var(--drillsharp-border);
378
+ transition: background 0.3s ease;
379
+ }
380
+
381
+ .drillsharp-svg {
382
+ width: 95%;
383
+ height: 95%;
384
+ max-height: 600px;
385
+ color: var(--drillsharp-text);
386
+ }
387
+
388
+ .drillsharp-gauge-lines {
389
+ filter: drop-shadow(0 0 2px var(--drillsharp-accent));
390
+ transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
391
+ }
392
+
393
+ .drillsharp-instruction {
394
+ position: absolute;
395
+ bottom: 2rem;
396
+ text-align: center;
397
+ width: 100%;
398
+ pointer-events: none;
399
+ padding: 0 1rem;
400
+ }
401
+
402
+ .drillsharp-instruction span {
403
+ background: var(--drillsharp-bg-panel);
404
+ color: var(--drillsharp-accent);
405
+ padding: 0.6rem 2rem;
406
+ border-radius: 2rem;
407
+ font-size: 0.7rem;
408
+ font-weight: 800;
409
+ text-transform: uppercase;
410
+ letter-spacing: 0.15em;
411
+ border: 1px solid var(--drillsharp-border);
412
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
413
+ }
414
+
415
+ .drillsharp-controls {
416
+ display: flex;
417
+ flex-direction: column;
418
+ gap: 1.25rem;
419
+ }
420
+
421
+ .drillsharp-group {
422
+ background: var(--drillsharp-bg-panel);
423
+ padding: 1.5rem;
424
+ border-radius: 2rem;
425
+ border: 1px solid var(--drillsharp-border);
426
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
427
+ display: flex;
428
+ flex-direction: column;
429
+ }
430
+
431
+ .drillsharp-group h4 {
432
+ font-size: 0.7rem;
433
+ text-transform: uppercase;
434
+ color: var(--drillsharp-primary);
435
+ margin-bottom: 1.25rem;
436
+ font-weight: 900;
437
+ letter-spacing: 0.1em;
438
+ }
439
+
440
+ .drillsharp-material-grid {
441
+ display: flex;
442
+ flex-direction: column;
443
+ gap: 0.6rem;
444
+ }
445
+
446
+ .drillsharp-mat-btn {
447
+ background: var(--drillsharp-button-bg);
448
+ border: 1px solid var(--drillsharp-border);
449
+ border-radius: 1.25rem;
450
+ padding: 1rem 0.5rem;
451
+ color: var(--drillsharp-text-muted);
452
+ cursor: pointer;
453
+ font-weight: 800;
454
+ font-size: 0.8rem;
455
+ transition: all 0.2s;
456
+ text-transform: uppercase;
457
+ }
458
+
459
+ .drillsharp-mat-btn.active {
460
+ background: var(--drillsharp-accent);
461
+ color: var(--drillsharp-bg-dark);
462
+ border-color: var(--drillsharp-accent);
463
+ box-shadow: 0 0 20px rgba(56, 189, 248, 0.3);
464
+ }
465
+
466
+ .drillsharp-stepper {
467
+ display: flex;
468
+ align-items: center;
469
+ background: var(--drillsharp-bg-dark);
470
+ border-radius: 1.25rem;
471
+ padding: 0.4rem;
472
+ border: 1px solid var(--drillsharp-border);
473
+ }
474
+
475
+ .drillsharp-step-btn {
476
+ width: 54px;
477
+ height: 54px;
478
+ background: var(--drillsharp-button-bg);
479
+ border: none;
480
+ color: var(--drillsharp-text);
481
+ border-radius: 1rem;
482
+ cursor: pointer;
483
+ font-size: 1.5rem;
484
+ display: flex;
485
+ align-items: center;
486
+ justify-content: center;
487
+ transition: all 0.2s;
488
+ }
489
+
490
+ .drillsharp-step-btn:active {
491
+ transform: scale(0.95);
492
+ background: var(--drillsharp-button-hover);
493
+ }
494
+
495
+ .drillsharp-stepper input {
496
+ flex: 1;
497
+ background: transparent;
498
+ border: none;
499
+ color: var(--drillsharp-accent);
500
+ text-align: center;
501
+ font-size: 2rem;
502
+ font-weight: 950;
503
+ width: 80px;
504
+ outline: none;
505
+ }
506
+
507
+ .drillsharp-results {
508
+ display: grid;
509
+ grid-template-columns: 1fr;
510
+ gap: 0.75rem;
511
+ margin-top: 1.5rem;
512
+ }
513
+
514
+ .drillsharp-res-item {
515
+ background: var(--drillsharp-bg-dark);
516
+ padding: 1.25rem;
517
+ border-radius: 1.5rem;
518
+ border: 1px solid var(--drillsharp-border);
519
+ display: flex;
520
+ flex-direction: column;
521
+ gap: 0.5rem;
522
+ align-items: flex-start;
523
+ }
524
+
525
+ .drillsharp-res-label {
526
+ font-size: 0.65rem;
527
+ color: var(--drillsharp-text-muted);
528
+ font-weight: 700;
529
+ text-transform: uppercase;
530
+ }
531
+
532
+ .drillsharp-res-value-box {
533
+ display: flex;
534
+ align-items: baseline;
535
+ gap: 0.25rem;
536
+ }
537
+
538
+ .drillsharp-res-value {
539
+ font-size: 1.5rem;
540
+ font-weight: 900;
541
+ color: var(--drillsharp-text);
542
+ }
543
+
544
+ .drillsharp-res-unit {
545
+ font-size: 0.7rem;
546
+ color: var(--drillsharp-accent);
547
+ font-weight: 800;
548
+ }
549
+
550
+ .drillsharp-diag-btn {
551
+ width: 100%;
552
+ padding: 1.25rem;
553
+ background: rgba(239, 68, 68, 0.1);
554
+ border: 1px dashed rgba(239, 68, 68, 0.3);
555
+ color: #ef4444;
556
+ border-radius: 1.5rem;
557
+ font-weight: 800;
558
+ font-size: 0.85rem;
559
+ cursor: pointer;
560
+ transition: all 0.2s;
561
+ text-transform: uppercase;
562
+ }
563
+
564
+ .drillsharp-diag-btn:hover {
565
+ background: rgba(239, 68, 68, 0.2);
566
+ border-style: solid;
567
+ transform: translateY(-2px);
568
+ }
569
+ .drillsharp-diag-btn:active {
570
+ transform: translateY(0);
571
+ }
572
+
573
+ .drillsharp-modal {
574
+ position: fixed;
575
+ top: 50%;
576
+ left: 50%;
577
+ transform: translate(-50%, -50%);
578
+ background: var(--drillsharp-bg-panel);
579
+ border: 1px solid var(--drillsharp-border);
580
+ padding: 2.5rem;
581
+ border-radius: 2.5rem;
582
+ z-index: 1000;
583
+ display: none;
584
+ width: 90%;
585
+ max-width: 500px;
586
+ box-shadow: 0 0 100px rgba(0, 0, 0, 0.5);
587
+ }
588
+
589
+ .drillsharp-modal.active {
590
+ display: block;
591
+ animation: drillsharp-modal-in 0.3s ease-out;
592
+ }
593
+
594
+ @keyframes drillsharp-modal-in {
595
+ from {
596
+ opacity: 0;
597
+ transform: translate(-50%, -45%) scale(0.95);
598
+ }
599
+ to {
600
+ opacity: 1;
601
+ transform: translate(-50%, -50%) scale(1);
602
+ }
603
+ }
604
+
605
+ .drillsharp-modal-header {
606
+ display: flex;
607
+ justify-content: space-between;
608
+ align-items: center;
609
+ margin-bottom: 2rem;
610
+ border-bottom: 1px solid var(--drillsharp-border);
611
+ padding-bottom: 1rem;
612
+ }
613
+
614
+ .drillsharp-modal-header h3 {
615
+ font-size: 1rem;
616
+ color: #ef4444;
617
+ text-transform: uppercase;
618
+ font-weight: 900;
619
+ margin: 0;
620
+ }
621
+
622
+ .drillsharp-modal-close {
623
+ background: none;
624
+ border: none;
625
+ font-size: 2rem;
626
+ color: var(--drillsharp-text-muted);
627
+ cursor: pointer;
628
+ transition: color 0.2s;
629
+ padding: 0;
630
+ width: 40px;
631
+ height: 40px;
632
+ display: flex;
633
+ align-items: center;
634
+ justify-content: center;
635
+ }
636
+
637
+ .drillsharp-modal-close:hover {
638
+ color: var(--drillsharp-text);
639
+ }
640
+
641
+ .drillsharp-diag-item {
642
+ display: flex;
643
+ flex-direction: column;
644
+ gap: 0.75rem;
645
+ margin-bottom: 2rem;
646
+ }
647
+
648
+ .drillsharp-diag-item:last-child {
649
+ margin-bottom: 0;
650
+ }
651
+
652
+ .drillsharp-diag-item strong {
653
+ color: var(--drillsharp-accent);
654
+ font-size: 0.85rem;
655
+ text-transform: uppercase;
656
+ }
657
+
658
+ .drillsharp-diag-item p {
659
+ font-size: 0.75rem;
660
+ color: var(--drillsharp-text-muted);
661
+ line-height: 1.5;
662
+ margin: 0;
663
+ }
664
+
665
+ .drillsharp-diag-img {
666
+ background: var(--drillsharp-bg-dark);
667
+ border-radius: 1rem;
668
+ padding: 1rem;
669
+ border: 1px solid var(--drillsharp-border);
670
+ }
671
+
672
+ @media (max-width: 1000px) {
673
+ .drillsharp-layout {
674
+ grid-template-columns: 1fr;
675
+ padding: 1rem;
676
+ border-radius: 1.5rem;
677
+ }
678
+ .drillsharp-gauge {
679
+ min-height: 380px;
680
+ }
681
+ }
682
+
683
+ @media (max-width: 480px) {
684
+ .drillsharp-root {
685
+ padding: 0 0.5rem;
686
+ }
687
+ .drillsharp-layout {
688
+ padding: 0.75rem;
689
+ gap: 1rem;
690
+ }
691
+ .drillsharp-gauge {
692
+ min-height: 320px;
693
+ }
694
+ .drillsharp-mat-btn {
695
+ font-size: 0.75rem;
696
+ padding: 0.8rem 0.5rem;
697
+ }
698
+ .drillsharp-step-btn {
699
+ width: 48px;
700
+ height: 48px;
701
+ }
702
+ .drillsharp-group {
703
+ padding: 1.25rem;
704
+ }
705
+ .drillsharp-res-item {
706
+ padding: 1rem;
707
+ }
708
+ .drillsharp-res-value {
709
+ font-size: 1.25rem;
710
+ }
711
+ }
712
+ </style>