mevebu 1.3.0 → 1.4.1

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 (164) hide show
  1. package/mevebu/app/mevebu.js +260 -208
  2. package/mevebu/app/tailwind.css +1658 -2079
  3. package/mevebu/app/tailwind.src.css +161 -1127
  4. package/mevebu/index.html +2 -2
  5. package/mevebu/libs/js/core.js +245 -96
  6. package/mevebu/libs/js/tools/abstract-checklist.js +5 -7
  7. package/mevebu/libs/js/tools/add-subtract-days.js +9 -11
  8. package/mevebu/libs/js/tools/age-calculator.js +7 -8
  9. package/mevebu/libs/js/tools/api-request-builder.js +3 -4
  10. package/mevebu/libs/js/tools/area-converter.js +7 -9
  11. package/mevebu/libs/js/tools/aspect-ratio.js +8 -9
  12. package/mevebu/libs/js/tools/average-calculator.js +4 -5
  13. package/mevebu/libs/js/tools/base64.js +2 -3
  14. package/mevebu/libs/js/tools/binary-calculator.js +6 -7
  15. package/mevebu/libs/js/tools/border-radius.js +7 -9
  16. package/mevebu/libs/js/tools/box-shadow.js +6 -7
  17. package/mevebu/libs/js/tools/break-even.js +4 -5
  18. package/mevebu/libs/js/tools/business-days.js +7 -8
  19. package/mevebu/libs/js/tools/canonical-tag.js +5 -6
  20. package/mevebu/libs/js/tools/caption-counter.js +5 -7
  21. package/mevebu/libs/js/tools/case-converter.js +10 -11
  22. package/mevebu/libs/js/tools/case-inspector.js +14 -16
  23. package/mevebu/libs/js/tools/cash-denomination.js +7 -8
  24. package/mevebu/libs/js/tools/cash-flow.js +7 -8
  25. package/mevebu/libs/js/tools/cert-expiry.js +5 -7
  26. package/mevebu/libs/js/tools/changelog-generator.js +4 -6
  27. package/mevebu/libs/js/tools/character-counter.js +10 -13
  28. package/mevebu/libs/js/tools/checklist.js +6 -7
  29. package/mevebu/libs/js/tools/citation-number-check.js +10 -13
  30. package/mevebu/libs/js/tools/coin-flip.js +9 -11
  31. package/mevebu/libs/js/tools/color-converter.js +6 -7
  32. package/mevebu/libs/js/tools/color-palette.js +6 -8
  33. package/mevebu/libs/js/tools/color-picker.js +4 -5
  34. package/mevebu/libs/js/tools/content-calendar.js +3 -4
  35. package/mevebu/libs/js/tools/contrast-checker.js +5 -6
  36. package/mevebu/libs/js/tools/cron-builder.js +4 -6
  37. package/mevebu/libs/js/tools/css-clamp.js +5 -6
  38. package/mevebu/libs/js/tools/css-formatter.js +4 -7
  39. package/mevebu/libs/js/tools/css-grid.js +6 -7
  40. package/mevebu/libs/js/tools/css-minifier.js +5 -8
  41. package/mevebu/libs/js/tools/csv-to-json.js +2 -3
  42. package/mevebu/libs/js/tools/csv-viewer.js +9 -11
  43. package/mevebu/libs/js/tools/currency-format.js +5 -7
  44. package/mevebu/libs/js/tools/daily-planner.js +9 -10
  45. package/mevebu/libs/js/tools/data-masker.js +6 -8
  46. package/mevebu/libs/js/tools/data-storage.js +7 -9
  47. package/mevebu/libs/js/tools/data-validator.js +9 -11
  48. package/mevebu/libs/js/tools/date-difference.js +6 -7
  49. package/mevebu/libs/js/tools/date-format.js +11 -13
  50. package/mevebu/libs/js/tools/delimiter-converter.js +3 -5
  51. package/mevebu/libs/js/tools/discount-calculator.js +4 -5
  52. package/mevebu/libs/js/tools/doi-resolver.js +4 -5
  53. package/mevebu/libs/js/tools/env-formatter.js +3 -6
  54. package/mevebu/libs/js/tools/equation-formatter.js +5 -9
  55. package/mevebu/libs/js/tools/expense-split.js +6 -7
  56. package/mevebu/libs/js/tools/fake-data.js +8 -13
  57. package/mevebu/libs/js/tools/find-replace.js +3 -5
  58. package/mevebu/libs/js/tools/flashcard-creator.js +9 -10
  59. package/mevebu/libs/js/tools/font-pairing.js +6 -8
  60. package/mevebu/libs/js/tools/fraction-calculator.js +10 -13
  61. package/mevebu/libs/js/tools/git-command-builder.js +11 -22
  62. package/mevebu/libs/js/tools/gpa-calculator.js +8 -10
  63. package/mevebu/libs/js/tools/grade-calculator.js +7 -8
  64. package/mevebu/libs/js/tools/gradient-generator.js +10 -12
  65. package/mevebu/libs/js/tools/habit-tracker.js +8 -9
  66. package/mevebu/libs/js/tools/hash-generator.js +3 -5
  67. package/mevebu/libs/js/tools/hashtag-formatter.js +6 -8
  68. package/mevebu/libs/js/tools/hmac-generator.js +3 -5
  69. package/mevebu/libs/js/tools/hpp-calculator.js +4 -5
  70. package/mevebu/libs/js/tools/html-entity.js +2 -3
  71. package/mevebu/libs/js/tools/html-formatter.js +3 -6
  72. package/mevebu/libs/js/tools/http-status.js +5 -7
  73. package/mevebu/libs/js/tools/inventory-quantity.js +7 -8
  74. package/mevebu/libs/js/tools/json-formatter.js +3 -6
  75. package/mevebu/libs/js/tools/json-minifier.js +5 -8
  76. package/mevebu/libs/js/tools/json-to-csv.js +3 -5
  77. package/mevebu/libs/js/tools/json-to-typescript.js +2 -5
  78. package/mevebu/libs/js/tools/json-validator.js +2 -3
  79. package/mevebu/libs/js/tools/jwt-decoder.js +6 -7
  80. package/mevebu/libs/js/tools/jwt-expiry.js +5 -6
  81. package/mevebu/libs/js/tools/jwt-generator.js +4 -6
  82. package/mevebu/libs/js/tools/length-converter.js +7 -9
  83. package/mevebu/libs/js/tools/license-reference.js +10 -13
  84. package/mevebu/libs/js/tools/line-counter.js +5 -7
  85. package/mevebu/libs/js/tools/list-difference.js +5 -7
  86. package/mevebu/libs/js/tools/list-merger.js +4 -5
  87. package/mevebu/libs/js/tools/locale-number.js +5 -8
  88. package/mevebu/libs/js/tools/markdown-preview.js +5 -8
  89. package/mevebu/libs/js/tools/markdown-table.js +5 -7
  90. package/mevebu/libs/js/tools/markup-calculator.js +4 -5
  91. package/mevebu/libs/js/tools/meeting-agenda.js +8 -9
  92. package/mevebu/libs/js/tools/meta-preview.js +12 -13
  93. package/mevebu/libs/js/tools/meta-tags.js +6 -7
  94. package/mevebu/libs/js/tools/mime-types.js +5 -7
  95. package/mevebu/libs/js/tools/name-picker.js +2 -3
  96. package/mevebu/libs/js/tools/number-base-converter.js +9 -12
  97. package/mevebu/libs/js/tools/password-generator.js +9 -12
  98. package/mevebu/libs/js/tools/password-strength.js +21 -25
  99. package/mevebu/libs/js/tools/percent-to-fraction.js +6 -7
  100. package/mevebu/libs/js/tools/percentage-calculator.js +6 -9
  101. package/mevebu/libs/js/tools/percentage-change.js +4 -5
  102. package/mevebu/libs/js/tools/permutation-combination.js +9 -12
  103. package/mevebu/libs/js/tools/prefix-suffix.js +2 -3
  104. package/mevebu/libs/js/tools/priority-matrix.js +6 -10
  105. package/mevebu/libs/js/tools/profit-margin.js +4 -5
  106. package/mevebu/libs/js/tools/qr-generator.js +3 -4
  107. package/mevebu/libs/js/tools/qr-scanner.js +11 -12
  108. package/mevebu/libs/js/tools/quadratic-solver.js +7 -8
  109. package/mevebu/libs/js/tools/query-builder.js +2 -3
  110. package/mevebu/libs/js/tools/quiz-formatter.js +4 -6
  111. package/mevebu/libs/js/tools/ratio-calculator.js +7 -8
  112. package/mevebu/libs/js/tools/readability.js +12 -15
  113. package/mevebu/libs/js/tools/reading-time.js +5 -7
  114. package/mevebu/libs/js/tools/reference-completeness.js +6 -8
  115. package/mevebu/libs/js/tools/regex-tester.js +7 -10
  116. package/mevebu/libs/js/tools/remove-duplicate-lines.js +2 -3
  117. package/mevebu/libs/js/tools/remove-extra-spaces.js +3 -5
  118. package/mevebu/libs/js/tools/robots-txt.js +3 -4
  119. package/mevebu/libs/js/tools/roman-numeral-converter.js +6 -8
  120. package/mevebu/libs/js/tools/sales-commission.js +8 -9
  121. package/mevebu/libs/js/tools/scientific-calculator.js +10 -14
  122. package/mevebu/libs/js/tools/scientific-notation.js +8 -9
  123. package/mevebu/libs/js/tools/script-planner.js +8 -10
  124. package/mevebu/libs/js/tools/selling-price.js +4 -5
  125. package/mevebu/libs/js/tools/semver-helper.js +3 -5
  126. package/mevebu/libs/js/tools/sentence-length.js +9 -10
  127. package/mevebu/libs/js/tools/sequence-analyzer.js +7 -8
  128. package/mevebu/libs/js/tools/sitemap-xml.js +4 -7
  129. package/mevebu/libs/js/tools/slug-converter.js +3 -5
  130. package/mevebu/libs/js/tools/slug-preview.js +6 -7
  131. package/mevebu/libs/js/tools/sort-lines.js +3 -5
  132. package/mevebu/libs/js/tools/speed-converter.js +7 -9
  133. package/mevebu/libs/js/tools/spin-wheel.js +19 -17
  134. package/mevebu/libs/js/tools/sql-formatter.js +5 -9
  135. package/mevebu/libs/js/tools/sql-minifier.js +5 -8
  136. package/mevebu/libs/js/tools/standard-deviation.js +6 -9
  137. package/mevebu/libs/js/tools/stopwatch.js +4 -6
  138. package/mevebu/libs/js/tools/study-schedule.js +8 -9
  139. package/mevebu/libs/js/tools/subtitle-formatter.js +10 -11
  140. package/mevebu/libs/js/tools/table-to-markdown.js +8 -12
  141. package/mevebu/libs/js/tools/tax-calculator.js +4 -5
  142. package/mevebu/libs/js/tools/temperature-converter.js +8 -11
  143. package/mevebu/libs/js/tools/text-diff.js +11 -7
  144. package/mevebu/libs/js/tools/text-direction.js +3 -5
  145. package/mevebu/libs/js/tools/text-reverser.js +3 -5
  146. package/mevebu/libs/js/tools/time-duration.js +8 -9
  147. package/mevebu/libs/js/tools/timestamp-converter.js +4 -6
  148. package/mevebu/libs/js/tools/timezone-converter.js +9 -13
  149. package/mevebu/libs/js/tools/title-length.js +6 -7
  150. package/mevebu/libs/js/tools/unicode-inspector.js +4 -5
  151. package/mevebu/libs/js/tools/url-inspector.js +8 -9
  152. package/mevebu/libs/js/tools/url-parser.js +12 -13
  153. package/mevebu/libs/js/tools/utf8-bytes.js +6 -9
  154. package/mevebu/libs/js/tools/uuid-generator.js +5 -9
  155. package/mevebu/libs/js/tools/version-compare.js +3 -4
  156. package/mevebu/libs/js/tools/video-duration.js +5 -7
  157. package/mevebu/libs/js/tools/volume-converter.js +7 -9
  158. package/mevebu/libs/js/tools/weekly-planner.js +8 -10
  159. package/mevebu/libs/js/tools/weight-converter.js +7 -9
  160. package/mevebu/libs/js/tools/weighted-average.js +4 -5
  161. package/mevebu/libs/js/tools/word-counter.js +10 -13
  162. package/mevebu/libs/js/tools/word-limit.js +4 -5
  163. package/mevebu/libs/js/tools/yaml-formatter.js +6 -7
  164. package/package.json +1 -1
@@ -15,15 +15,14 @@ const reverseLines = (text) => text ? text.split("\n").reverse().join("\n") : ""
15
15
 
16
16
  export function mount(slot) {
17
17
  const source = textArea({ rows: 10, "aria-label": "Text", placeholder: "Type or paste text" });
18
- const result = textArea({ rows: 10, readonly: true, class: "mvb-in mvb-in--area mvb-in--mono", "aria-label": "Result" });
18
+ const result = textArea({ rows: 10, readonly: true, "aria-label": "Result" });
19
19
 
20
20
  let mode = "chars";
21
21
  const chips = chipRow(
22
22
  [
23
23
  { value: "chars", label: "Characters" },
24
24
  { value: "words", label: "Words" },
25
- { value: "lines", label: "Lines" },
26
- ],
25
+ { value: "lines", label: "Lines" }],
27
26
  { value: "chars", label: "Reverse by", onChange: (value) => { mode = value; run(); } }
28
27
  );
29
28
 
@@ -40,8 +39,7 @@ export function mount(slot) {
40
39
  stack(panel("Text", source), panel("Reverse by", chips)),
41
40
  stack(panel("Result", result))
42
41
  ),
43
- foot: actions(copyButton(() => result.value, "Copy result", "fill")),
44
- });
42
+ foot: actions(copyButton(() => result.value, "Copy result", "fill"))});
45
43
  slot.append(card.node);
46
44
  run();
47
45
 
@@ -11,19 +11,19 @@ function parseTime(value) {
11
11
  }
12
12
 
13
13
  const kvRow = (key, value) =>
14
- el("div", { class: "mvb-kv__row" }, el("span", { class: "mvb-kv__k" }, key), el("span", { class: "mvb-kv__v" }, value));
14
+ el("div", { class: "grid gap-3 bg-deck px-3 py-[9px] [grid-template-columns:minmax(90px,34%)_minmax(0,1fr)]" }, el("span", { class: "wrap-anywhere text-2xs font-semibold text-ink-2" }, key), el("span", { class: "wrap-anywhere font-mono text-2xs" }, value));
15
15
 
16
16
  export function mount(slot) {
17
17
  const start = textInput({ type: "time", value: "09:00", "aria-label": "Start time" });
18
18
  const end = textInput({ type: "time", value: "17:30", "aria-label": "End time" });
19
19
  const breakMin = numberInput({ value: "30", min: "0", "aria-label": "Break in minutes" });
20
20
 
21
- const result = el("span", { class: "mvb-stat__v" }, "-");
22
- const tile = el("div", { class: "mvb-stat" }, result, el("span", { class: "mvb-stat__k" }, "Duration"));
23
- const stats = el("div", { class: "mvb-stats" }, tile);
24
- const minutesOut = el("span", { class: "mvb-kv__v" }, "-");
25
- const decimalOut = el("span", { class: "mvb-kv__v" }, "-");
26
- const kv = el("div", { class: "mvb-kv" }, kvRow("Total minutes", minutesOut), kvRow("Decimal hours", decimalOut));
21
+ const result = el("span", { class: "wrap-anywhere text-xl font-bold tracking-[-0.02em] tabular-nums" }, "-");
22
+ const tile = el("div", { class: "grid gap-0.5 rounded-r1 border border-orbit bg-deck-2 px-3.5 py-3" }, result, el("span", { class: "text-2xs font-semibold text-ink-3" }, "Duration"));
23
+ const stats = el("div", { class: "grid gap-2.5 [grid-template-columns:repeat(auto-fit,minmax(120px,1fr))]" }, tile);
24
+ const minutesOut = el("span", { class: "wrap-anywhere font-mono text-2xs" }, "-");
25
+ const decimalOut = el("span", { class: "wrap-anywhere font-mono text-2xs" }, "-");
26
+ const kv = el("div", { class: "grid gap-px overflow-hidden rounded-r1 border border-orbit bg-orbit" }, kvRow("Total minutes", minutesOut), kvRow("Decimal hours", decimalOut));
27
27
  const error = notice("error");
28
28
  let text = "";
29
29
 
@@ -72,8 +72,7 @@ export function mount(slot) {
72
72
  stack(panel("Start", start), panel("End", end), panel("Break in minutes", breakMin), error),
73
73
  stack(stats, panel("Breakdown", kv))
74
74
  ),
75
- foot: actions(copyButton(() => text, "Copy result", "fill")),
76
- });
75
+ foot: actions(copyButton(() => text, "Copy result", "fill"))});
77
76
  slot.append(card.node);
78
77
  run();
79
78
 
@@ -6,8 +6,7 @@ function relative(date) {
6
6
  const abs = Math.abs(diff);
7
7
  const units = [
8
8
  ["year", 31536000000], ["month", 2592000000], ["day", 86400000],
9
- ["hour", 3600000], ["minute", 60000], ["second", 1000],
10
- ];
9
+ ["hour", 3600000], ["minute", 60000], ["second", 1000]];
11
10
  for (const [unit, ms] of units) {
12
11
  if (abs >= ms) {
13
12
  const value = Math.round(abs / ms);
@@ -32,11 +31,11 @@ function parse(text) {
32
31
  }
33
32
 
34
33
  const row = (key, value) =>
35
- el("div", { class: "mvb-kv__row" }, el("span", { class: "mvb-kv__k" }, key), el("span", { class: "mvb-kv__v" }, value));
34
+ el("div", { class: "grid gap-3 bg-deck px-3 py-[9px] [grid-template-columns:minmax(90px,34%)_minmax(0,1fr)]" }, el("span", { class: "wrap-anywhere text-2xs font-semibold text-ink-2" }, key), el("span", { class: "wrap-anywhere font-mono text-2xs" }, value));
36
35
 
37
36
  export function mount(slot) {
38
37
  const source = textInput({ value: "1700000000", "aria-label": "Timestamp or date", placeholder: "1700000000 or 2026-01-01T00:00:00Z" });
39
- const kv = el("div", { class: "mvb-kv" });
38
+ const kv = el("div", { class: "grid gap-px overflow-hidden rounded-r1 border border-orbit bg-orbit" });
40
39
  const error = notice("error");
41
40
  let iso = "";
42
41
 
@@ -74,8 +73,7 @@ export function mount(slot) {
74
73
  stack(panel("Timestamp or date", source), error),
75
74
  stack(panel("Reading", kv))
76
75
  ),
77
- foot: actions(nowButton, copyButton(() => iso, "Copy ISO 8601", "fill")),
78
- });
76
+ foot: actions(nowButton, copyButton(() => iso, "Copy ISO 8601", "fill"))});
79
77
  slot.append(card.node);
80
78
  run();
81
79
 
@@ -18,8 +18,7 @@ const FALLBACK_ZONES = [
18
18
  "Asia/Shanghai",
19
19
  "Asia/Tokyo",
20
20
  "Asia/Singapore",
21
- "Australia/Sydney",
22
- ];
21
+ "Australia/Sydney"];
23
22
 
24
23
  function zoneList() {
25
24
  let zones = FALLBACK_ZONES;
@@ -68,8 +67,7 @@ function offsetMs(timeZone, date) {
68
67
  day: "2-digit",
69
68
  hour: "2-digit",
70
69
  minute: "2-digit",
71
- second: "2-digit",
72
- });
70
+ second: "2-digit"});
73
71
  for (const part of format.formatToParts(date)) parts[part.type] = part.value;
74
72
  const hour = parts.hour === "24" ? 0 : Number(parts.hour);
75
73
  const asUTC = Date.UTC(Number(parts.year), Number(parts.month) - 1, Number(parts.day), hour, Number(parts.minute), Number(parts.second));
@@ -85,7 +83,7 @@ function wallToInstant(day, time, timeZone) {
85
83
  const pad = (n) => String(n).padStart(2, "0");
86
84
 
87
85
  const kvRow = (key, value) =>
88
- el("div", { class: "mvb-kv__row" }, el("span", { class: "mvb-kv__k" }, key), el("span", { class: "mvb-kv__v" }, value));
86
+ el("div", { class: "grid gap-3 bg-deck px-3 py-[9px] [grid-template-columns:minmax(90px,34%)_minmax(0,1fr)]" }, el("span", { class: "wrap-anywhere text-2xs font-semibold text-ink-2" }, key), el("span", { class: "wrap-anywhere font-mono text-2xs" }, value));
89
87
 
90
88
  export function mount(slot) {
91
89
  const zones = zoneList();
@@ -95,10 +93,10 @@ export function mount(slot) {
95
93
  const fromZone = selectInput(zones, { value: Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC", "aria-label": "Source zone" });
96
94
  const toZone = selectInput(zones, { value: "UTC", "aria-label": "Target zone" });
97
95
 
98
- const target = el("span", { class: "mvb-kv__v" }, "-");
99
- const utc = el("span", { class: "mvb-kv__v" }, "-");
100
- const diff = el("span", { class: "mvb-kv__v" }, "-");
101
- const kv = el("div", { class: "mvb-kv" }, kvRow("Target time", target), kvRow("UTC", utc), kvRow("Offset", diff));
96
+ const target = el("span", { class: "wrap-anywhere font-mono text-2xs" }, "-");
97
+ const utc = el("span", { class: "wrap-anywhere font-mono text-2xs" }, "-");
98
+ const diff = el("span", { class: "wrap-anywhere font-mono text-2xs" }, "-");
99
+ const kv = el("div", { class: "grid gap-px overflow-hidden rounded-r1 border border-orbit bg-orbit" }, kvRow("Target time", target), kvRow("UTC", utc), kvRow("Offset", diff));
102
100
  const error = notice("error");
103
101
  let text = "";
104
102
 
@@ -127,8 +125,7 @@ export function mount(slot) {
127
125
  month: "short",
128
126
  year: "numeric",
129
127
  hour: "2-digit",
130
- minute: "2-digit",
131
- }).format(instant);
128
+ minute: "2-digit"}).format(instant);
132
129
  const utcText = `${instant.getUTCFullYear()}-${pad(instant.getUTCMonth() + 1)}-${pad(instant.getUTCDate())} ${pad(instant.getUTCHours())}:${pad(instant.getUTCMinutes())} UTC`;
133
130
  const deltaHours = (offsetMs(toZone.value, instant) - offsetMs(fromZone.value, instant)) / 3600000;
134
131
  const sign = deltaHours > 0 ? "+" : deltaHours < 0 ? "-" : "";
@@ -152,8 +149,7 @@ export function mount(slot) {
152
149
  stack(panel("Date", date), panel("Time", time), panel("From", fromZone), panel("To", toZone), error),
153
150
  stack(panel("Result", kv))
154
151
  ),
155
- foot: actions(copyButton(() => text, "Copy result", "fill")),
156
- });
152
+ foot: actions(copyButton(() => text, "Copy result", "fill"))});
157
153
  slot.append(card.node);
158
154
  run();
159
155
 
@@ -4,8 +4,8 @@ import { el, blank, bench, stack, panel, textArea, numberInput, copyButton, acti
4
4
  const countWords = (text) => (text.trim() ? text.trim().split(/\s+/).length : 0);
5
5
 
6
6
  function tile(label) {
7
- const value = el("span", { class: "mvb-stat__v" }, "0");
8
- const node = el("div", { class: "mvb-stat" }, value, el("span", { class: "mvb-stat__k" }, label));
7
+ const value = el("span", { class: "wrap-anywhere text-xl font-bold tracking-[-0.02em] tabular-nums" }, "0");
8
+ const node = el("div", { class: "grid gap-0.5 rounded-r1 border border-orbit bg-deck-2 px-3.5 py-3" }, value, el("span", { class: "text-2xs font-semibold text-ink-3" }, label));
9
9
  node.set = (text) => { value.textContent = text; };
10
10
  return node;
11
11
  }
@@ -17,9 +17,9 @@ export function mount(slot) {
17
17
  const titlesTile = tile("Titles");
18
18
  const overTile = tile("Over the limit");
19
19
  const longestTile = tile("Longest");
20
- const stats = el("div", { class: "mvb-stats" }, titlesTile, overTile, longestTile);
20
+ const stats = el("div", { class: "grid gap-2.5 [grid-template-columns:repeat(auto-fit,minmax(120px,1fr))]" }, titlesTile, overTile, longestTile);
21
21
 
22
- const listWrap = el("div", { class: "mvb-scroll" });
22
+ const listWrap = el("div", { class: "max-h-80 overflow-auto" });
23
23
  let listText = "";
24
24
 
25
25
  function run() {
@@ -42,7 +42,7 @@ export function mount(slot) {
42
42
  el("th", {}, item.title),
43
43
  el("td", {}, cap > 0 && item.chars > cap ? `${item.chars} over` : String(item.chars)),
44
44
  el("td", {}, String(item.words))));
45
- listWrap.replaceChildren(el("table", { class: "mvb-ttable" },
45
+ listWrap.replaceChildren(el("table", { class: "w-full border-collapse font-mono text-sm [&_th]:wrap-anywhere [&_td]:wrap-anywhere [&_th]:border-b [&_td]:border-b [&_th]:border-orbit [&_td]:border-orbit [&_th]:px-2.5 [&_td]:px-2.5 [&_th]:py-2 [&_td]:py-2 [&_th]:text-start [&_td]:text-start [&_th]:font-sans [&_th]:text-2xs [&_th]:font-semibold [&_th]:text-ink-2 [&_tbody>tr:last-child>th]:border-b-0 [&_tbody>tr:last-child>td]:border-b-0" },
46
46
  el("thead", {}, el("tr", {}, el("th", {}, "Title"), el("th", {}, "Characters"), el("th", {}, "Words"))),
47
47
  el("tbody", {}, ...rows)));
48
48
  listText = items.map((item) => `${item.chars} characters, ${item.words} words ${item.title}`).join("\n");
@@ -56,8 +56,7 @@ export function mount(slot) {
56
56
  stack(panel("Titles", source), panel("Character limit", limit)),
57
57
  stack(stats, panel("By length", listWrap))
58
58
  ),
59
- foot: actions(copyButton(() => listText, "Copy list", "fill")),
60
- });
59
+ foot: actions(copyButton(() => listText, "Copy list", "fill"))});
61
60
  slot.append(card.node);
62
61
  run();
63
62
 
@@ -11,18 +11,18 @@ function describe(char) {
11
11
 
12
12
  export function mount(slot) {
13
13
  const source = textArea({ rows: 8, value: "mevebu", "aria-label": "Text" });
14
- const scroll = el("div", { class: "mvb-scroll" });
14
+ const scroll = el("div", { class: "max-h-80 overflow-auto" });
15
15
  let rows = [];
16
16
 
17
17
  function run() {
18
18
  rows = Array.from(source.value).map(describe);
19
19
  if (!rows.length) {
20
- scroll.replaceChildren(el("p", { class: "mvb-note" }, "Type or paste text."));
20
+ scroll.replaceChildren(el("p", { class: "border-s-[3px] border-transparent ps-2 text-sm text-ink-3" }, "Type or paste text."));
21
21
  return;
22
22
  }
23
23
  scroll.replaceChildren(el(
24
24
  "table",
25
- { class: "mvb-ttable" },
25
+ { class: "w-full border-collapse font-mono text-sm [&_th]:wrap-anywhere [&_td]:wrap-anywhere [&_th]:border-b [&_td]:border-b [&_th]:border-orbit [&_td]:border-orbit [&_th]:px-2.5 [&_td]:px-2.5 [&_th]:py-2 [&_td]:py-2 [&_th]:text-start [&_td]:text-start [&_th]:font-sans [&_th]:text-2xs [&_th]:font-semibold [&_th]:text-ink-2 [&_tbody>tr:last-child>th]:border-b-0 [&_tbody>tr:last-child>td]:border-b-0" },
26
26
  el("thead", {}, el("tr", {},
27
27
  el("th", {}, "Character"),
28
28
  el("th", {}, "Code point"),
@@ -47,8 +47,7 @@ export function mount(slot) {
47
47
  () => rows.map((entry) => `${entry.char}\t${entry.point}\t${entry.decimal}\t${entry.bytes}`).join("\n"),
48
48
  "Copy table",
49
49
  "fill"
50
- )),
51
- });
50
+ ))});
52
51
  slot.append(card.node);
53
52
  run();
54
53
 
@@ -4,23 +4,23 @@ import { el, textInput, notice, copyButton, bench, stack, panel, actions, toolca
4
4
  const IPV4 = /^\d{1,3}(\.\d{1,3}){3}$/;
5
5
 
6
6
  const kvRow = (key, value) =>
7
- el("div", { class: "mvb-kv__row" }, el("span", { class: "mvb-kv__k" }, key), el("span", { class: "mvb-kv__v" }, value));
7
+ el("div", { class: "grid gap-3 bg-deck px-3 py-[9px] [grid-template-columns:minmax(90px,34%)_minmax(0,1fr)]" }, el("span", { class: "wrap-anywhere text-2xs font-semibold text-ink-2" }, key), el("span", { class: "wrap-anywhere font-mono text-2xs" }, value));
8
8
 
9
9
  export function mount(slot) {
10
10
  const source = textInput({ value: "https://example.com/login?next=/home", "aria-label": "URL" });
11
- const scheme = el("span", { class: "mvb-kv__v" }, "-");
12
- const host = el("span", { class: "mvb-kv__v" }, "-");
13
- const port = el("span", { class: "mvb-kv__v" }, "-");
14
- const path = el("span", { class: "mvb-kv__v" }, "-");
11
+ const scheme = el("span", { class: "wrap-anywhere font-mono text-2xs" }, "-");
12
+ const host = el("span", { class: "wrap-anywhere font-mono text-2xs" }, "-");
13
+ const port = el("span", { class: "wrap-anywhere font-mono text-2xs" }, "-");
14
+ const path = el("span", { class: "wrap-anywhere font-mono text-2xs" }, "-");
15
15
  const kv = el(
16
16
  "div",
17
- { class: "mvb-kv" },
17
+ { class: "grid gap-px overflow-hidden rounded-r1 border border-orbit bg-orbit" },
18
18
  kvRow("Scheme", scheme),
19
19
  kvRow("Host", host),
20
20
  kvRow("Port", port),
21
21
  kvRow("Path", path)
22
22
  );
23
- const flags = el("div", { class: "mvb-stack" });
23
+ const flags = el("div", { class: "grid content-start gap-4" });
24
24
  const error = notice("error");
25
25
  let summary = "";
26
26
 
@@ -86,8 +86,7 @@ export function mount(slot) {
86
86
  ),
87
87
  stack(kv, panel("Checks", flags))
88
88
  ),
89
- foot: actions(copyButton(() => summary, "Copy host", "fill")),
90
- });
89
+ foot: actions(copyButton(() => summary, "Copy host", "fill"))});
91
90
  slot.append(card.node);
92
91
  run();
93
92
 
@@ -2,32 +2,32 @@
2
2
  import { el, bench, stack, panel, textInput, notice, copyButton, actions, toolcard } from "../core.js";
3
3
 
4
4
  const kvRow = (key, value) =>
5
- el("div", { class: "mvb-kv__row" }, el("span", { class: "mvb-kv__k" }, key), el("span", { class: "mvb-kv__v" }, value));
5
+ el("div", { class: "grid gap-3 bg-deck px-3 py-[9px] [grid-template-columns:minmax(90px,34%)_minmax(0,1fr)]" }, el("span", { class: "wrap-anywhere text-2xs font-semibold text-ink-2" }, key), el("span", { class: "wrap-anywhere font-mono text-2xs" }, value));
6
6
 
7
7
  export function mount(slot) {
8
8
  const source = textInput({ value: "https://example.com:8443/blog/post?utm_source=news&page=2#top", "aria-label": "URL" });
9
9
  const error = notice("error");
10
10
 
11
- const protocol = el("span", { class: "mvb-kv__v" }, "-");
12
- const host = el("span", { class: "mvb-kv__v" }, "-");
13
- const port = el("span", { class: "mvb-kv__v" }, "-");
14
- const path = el("span", { class: "mvb-kv__v" }, "-");
15
- const hash = el("span", { class: "mvb-kv__v" }, "-");
11
+ const protocol = el("span", { class: "wrap-anywhere font-mono text-2xs" }, "-");
12
+ const host = el("span", { class: "wrap-anywhere font-mono text-2xs" }, "-");
13
+ const port = el("span", { class: "wrap-anywhere font-mono text-2xs" }, "-");
14
+ const path = el("span", { class: "wrap-anywhere font-mono text-2xs" }, "-");
15
+ const hash = el("span", { class: "wrap-anywhere font-mono text-2xs" }, "-");
16
16
  const kv = el(
17
17
  "div",
18
- { class: "mvb-kv" },
18
+ { class: "grid gap-px overflow-hidden rounded-r1 border border-orbit bg-orbit" },
19
19
  kvRow("Protocol", protocol),
20
20
  kvRow("Host", host),
21
21
  kvRow("Port", port),
22
22
  kvRow("Path", path),
23
23
  kvRow("Hash", hash)
24
24
  );
25
- const tableWrap = el("div", { class: "mvb-scroll" });
25
+ const tableWrap = el("div", { class: "max-h-80 overflow-auto" });
26
26
  let paramsText = "";
27
27
 
28
28
  function clear() {
29
29
  for (const node of [protocol, host, port, path, hash]) node.textContent = "-";
30
- tableWrap.replaceChildren(el("p", { class: "mvb-note" }, "No query parameters."));
30
+ tableWrap.replaceChildren(el("p", { class: "border-s-[3px] border-transparent ps-2 text-sm text-ink-3" }, "No query parameters."));
31
31
  paramsText = "";
32
32
  }
33
33
 
@@ -49,13 +49,13 @@ export function mount(slot) {
49
49
  hash.textContent = url.hash || "-";
50
50
  const params = [...url.searchParams];
51
51
  if (!params.length) {
52
- tableWrap.replaceChildren(el("p", { class: "mvb-note" }, "No query parameters."));
52
+ tableWrap.replaceChildren(el("p", { class: "border-s-[3px] border-transparent ps-2 text-sm text-ink-3" }, "No query parameters."));
53
53
  paramsText = "";
54
54
  return;
55
55
  }
56
56
  tableWrap.replaceChildren(el(
57
57
  "table",
58
- { class: "mvb-ttable" },
58
+ { class: "w-full border-collapse font-mono text-sm [&_th]:wrap-anywhere [&_td]:wrap-anywhere [&_th]:border-b [&_td]:border-b [&_th]:border-orbit [&_td]:border-orbit [&_th]:px-2.5 [&_td]:px-2.5 [&_th]:py-2 [&_td]:py-2 [&_th]:text-start [&_td]:text-start [&_th]:font-sans [&_th]:text-2xs [&_th]:font-semibold [&_th]:text-ink-2 [&_tbody>tr:last-child>th]:border-b-0 [&_tbody>tr:last-child>td]:border-b-0" },
59
59
  el("thead", {}, el("tr", {}, el("th", {}, "Key"), el("th", {}, "Value"))),
60
60
  el("tbody", {}, ...params.map(([key, value]) => el("tr", {}, el("td", {}, key), el("td", {}, value))))
61
61
  ));
@@ -72,8 +72,7 @@ export function mount(slot) {
72
72
  foot: actions(
73
73
  copyButton(() => source.value.trim(), "Copy URL"),
74
74
  copyButton(() => paramsText, "Copy params", "fill")
75
- ),
76
- });
75
+ )});
77
76
  slot.append(card.node);
78
77
  run();
79
78
 
@@ -2,8 +2,8 @@
2
2
  import { el, bench, stack, panel, textArea, copyButton, actions, toolcard } from "../core.js";
3
3
 
4
4
  function tile(label) {
5
- const value = el("span", { class: "mvb-stat__v" }, "0");
6
- const node = el("div", { class: "mvb-stat" }, value, el("span", { class: "mvb-stat__k" }, label));
5
+ const value = el("span", { class: "wrap-anywhere text-xl font-bold tracking-[-0.02em] tabular-nums" }, "0");
6
+ const node = el("div", { class: "grid gap-0.5 rounded-r1 border border-orbit bg-deck-2 px-3.5 py-3" }, value, el("span", { class: "text-2xs font-semibold text-ink-3" }, label));
7
7
  node.set = (text) => { value.textContent = text; };
8
8
  return node;
9
9
  }
@@ -22,7 +22,7 @@ export function mount(slot) {
22
22
  const pointTile = tile("Code points");
23
23
  const byteTile = tile("UTF-8 bytes");
24
24
  const unitTile = tile("UTF-16 units");
25
- const stats = el("div", { class: "mvb-stats" }, characterTile, pointTile, byteTile, unitTile);
25
+ const stats = el("div", { class: "grid gap-2.5 [grid-template-columns:repeat(auto-fit,minmax(120px,1fr))]" }, characterTile, pointTile, byteTile, unitTile);
26
26
 
27
27
  let counts = { characters: 0, points: 0, bytes: 0, units: 0 };
28
28
 
@@ -31,8 +31,7 @@ export function mount(slot) {
31
31
  `${counts.characters} characters`,
32
32
  `${counts.points} code points`,
33
33
  `${counts.bytes} UTF-8 bytes`,
34
- `${counts.units} UTF-16 units`,
35
- ].join("\n");
34
+ `${counts.units} UTF-16 units`].join("\n");
36
35
  }
37
36
 
38
37
  function run() {
@@ -41,8 +40,7 @@ export function mount(slot) {
41
40
  characters: graphemes(text),
42
41
  points: Array.from(text).length,
43
42
  bytes: new TextEncoder().encode(text).length,
44
- units: text.length,
45
- };
43
+ units: text.length};
46
44
  characterTile.set(String(counts.characters));
47
45
  pointTile.set(String(counts.points));
48
46
  byteTile.set(String(counts.bytes));
@@ -56,8 +54,7 @@ export function mount(slot) {
56
54
  stack(panel("Text", source)),
57
55
  stack(stats)
58
56
  ),
59
- foot: actions(copyButton(summary, "Copy counts", "fill")),
60
- });
57
+ foot: actions(copyButton(summary, "Copy counts", "fill"))});
61
58
  slot.append(card.node);
62
59
  run();
63
60
 
@@ -12,8 +12,7 @@ const VERSIONS = [
12
12
  { value: "v1", label: "v1" },
13
13
  { value: "v6", label: "v6" },
14
14
  { value: "nil", label: "Nil" },
15
- { value: "max", label: "Max" },
16
- ];
15
+ { value: "max", label: "Max" }];
17
16
 
18
17
  const toHex = (bytes) => [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
19
18
  const group = (hex) => `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
@@ -105,8 +104,7 @@ export function mount(slot) {
105
104
  onChange: (value) => {
106
105
  version = value;
107
106
  generate();
108
- },
109
- });
107
+ }});
110
108
 
111
109
  function totalCount() {
112
110
  return Math.max(1, Math.min(1000, parseInt(countField.value || "1", 10) || 1));
@@ -122,8 +120,7 @@ export function mount(slot) {
122
120
  count: String(total),
123
121
  caps: capsBox.input.checked,
124
122
  noHyphens: hyphensBox.input.checked,
125
- version,
126
- });
123
+ version});
127
124
  }
128
125
 
129
126
  const generateButton = button("Generate", { icon: "refresh-cw", kind: "fill" });
@@ -156,11 +153,10 @@ export function mount(slot) {
156
153
 
157
154
  const card = toolcard({
158
155
  body: bench(
159
- stack(panel("Version", versions), panel("How many", countField), el("div", { class: "mvb-chips" }, capsBox, hyphensBox)),
156
+ stack(panel("Version", versions), panel("How many", countField), el("div", { class: "flex flex-wrap gap-1.5" }, capsBox, hyphensBox)),
160
157
  result
161
158
  ),
162
- foot: actions(copyButton, jsonButton, saveButton, generateButton),
163
- });
159
+ foot: actions(copyButton, jsonButton, saveButton, generateButton)});
164
160
  slot.append(card.node);
165
161
  generate();
166
162
 
@@ -8,8 +8,8 @@ function parse(text) {
8
8
  }
9
9
 
10
10
  export function mount(slot) {
11
- const left = textInput({ value: "1.2.0", class: "mvb-in mvb-in--mono", "aria-label": "First version" });
12
- const right = textInput({ value: "1.1.5", class: "mvb-in mvb-in--mono", "aria-label": "Second version" });
11
+ const left = textInput({ value: "1.2.0", mono: true, "aria-label": "First version" });
12
+ const right = textInput({ value: "1.1.5", mono: true, "aria-label": "Second version" });
13
13
  const error = notice("error");
14
14
  const out = output({ rows: 8 });
15
15
  let text = "";
@@ -59,8 +59,7 @@ export function mount(slot) {
59
59
  stack(panel("First version", left), panel("Second version", right), error),
60
60
  stack(panel("Comparison", out))
61
61
  ),
62
- foot: actions(copyButton(() => text, "Copy comparison", "fill")),
63
- });
62
+ foot: actions(copyButton(() => text, "Copy comparison", "fill"))});
64
63
  slot.append(card.node);
65
64
  run();
66
65
 
@@ -7,8 +7,8 @@ const clock = (seconds) => {
7
7
  };
8
8
 
9
9
  function tile(label) {
10
- const value = el("span", { class: "mvb-stat__v" }, "0:00");
11
- const node = el("div", { class: "mvb-stat" }, value, el("span", { class: "mvb-stat__k" }, label));
10
+ const value = el("span", { class: "wrap-anywhere text-xl font-bold tracking-[-0.02em] tabular-nums" }, "0:00");
11
+ const node = el("div", { class: "grid gap-0.5 rounded-r1 border border-orbit bg-deck-2 px-3.5 py-3" }, value, el("span", { class: "text-2xs font-semibold text-ink-3" }, label));
12
12
  node.set = (text) => { value.textContent = text; };
13
13
  return node;
14
14
  }
@@ -22,7 +22,7 @@ export function mount(slot) {
22
22
  const wordsTile = tile("Words");
23
23
  const speakTile = tile("Speaking");
24
24
  const totalTile = tile("With pauses");
25
- const stats = el("div", { class: "mvb-stats" }, wordsTile, speakTile, totalTile);
25
+ const stats = el("div", { class: "grid gap-2.5 [grid-template-columns:repeat(auto-fit,minmax(120px,1fr))]" }, wordsTile, speakTile, totalTile);
26
26
  const note = notice("note");
27
27
  note.write("Speaking rates vary by person and script.");
28
28
 
@@ -42,8 +42,7 @@ export function mount(slot) {
42
42
  summary = [
43
43
  `${words} words`,
44
44
  `Speaking ${clock(speaking)} at ${wpm} words per minute`,
45
- `Total ${clock(total)} with ${pauseSeconds} seconds of pause per minute`,
46
- ].join("\n");
45
+ `Total ${clock(total)} with ${pauseSeconds} seconds of pause per minute`].join("\n");
47
46
  }
48
47
 
49
48
  source.addEventListener("input", run);
@@ -61,8 +60,7 @@ export function mount(slot) {
61
60
  ),
62
61
  stack(stats, note)
63
62
  ),
64
- foot: actions(copyButton(() => summary, "Copy estimate", "fill")),
65
- });
63
+ foot: actions(copyButton(() => summary, "Copy estimate", "fill"))});
66
64
  slot.append(card.node);
67
65
  run();
68
66
 
@@ -11,8 +11,7 @@ const UNITS = [
11
11
  { value: "cup", label: "Cup", factor: 0.2365882365 },
12
12
  { value: "pt", label: "Pint", factor: 0.473176473 },
13
13
  { value: "qt", label: "Quart", factor: 0.946352946 },
14
- { value: "gal", label: "Gallon", factor: 3.785411784 },
15
- ];
14
+ { value: "gal", label: "Gallon", factor: 3.785411784 }];
16
15
 
17
16
  const byId = Object.fromEntries(UNITS.map((unit) => [unit.value, unit]));
18
17
  const options = UNITS.map(({ value, label }) => ({ value, label }));
@@ -29,11 +28,11 @@ export function mount(slot) {
29
28
  const value = numberInput({ value: "1", step: "any", "aria-label": "Value" });
30
29
  const from = selectInput(options, { value: "l", "aria-label": "From unit" });
31
30
  const to = selectInput(options, { value: "gal", "aria-label": "To unit" });
32
- const result = el("span", { class: "mvb-stat__v" }, "-");
33
- const stats = el("div", { class: "mvb-stats" }, el("div", { class: "mvb-stat" }, el("span", { class: "mvb-stat__k" }, "Result"), result));
34
- const factor = el("p", { class: "mvb-note" });
31
+ const result = el("span", { class: "wrap-anywhere text-xl font-bold tracking-[-0.02em] tabular-nums" }, "-");
32
+ const stats = el("div", { class: "grid gap-2.5 [grid-template-columns:repeat(auto-fit,minmax(120px,1fr))]" }, el("div", { class: "grid gap-0.5 rounded-r1 border border-orbit bg-deck-2 px-3.5 py-3" }, el("span", { class: "text-2xs font-semibold text-ink-3" }, "Result"), result));
33
+ const factor = el("p", { class: "border-s-[3px] border-transparent ps-2 text-sm text-ink-3" });
35
34
  const error = notice("error");
36
- const scroll = el("div", { class: "mvb-scroll" });
35
+ const scroll = el("div", { class: "max-h-80 overflow-auto" });
37
36
  let text = "";
38
37
 
39
38
  function run() {
@@ -53,7 +52,7 @@ export function mount(slot) {
53
52
  const out = (n * a.factor) / b.factor;
54
53
  result.textContent = `${fmt(out)} ${b.value}`;
55
54
  factor.textContent = `1 ${a.value} = ${fmt(a.factor / b.factor)} ${b.value}`;
56
- scroll.replaceChildren(el("table", { class: "mvb-ttable" },
55
+ scroll.replaceChildren(el("table", { class: "w-full border-collapse font-mono text-sm [&_th]:wrap-anywhere [&_td]:wrap-anywhere [&_th]:border-b [&_td]:border-b [&_th]:border-orbit [&_td]:border-orbit [&_th]:px-2.5 [&_td]:px-2.5 [&_th]:py-2 [&_td]:py-2 [&_th]:text-start [&_td]:text-start [&_th]:font-sans [&_th]:text-2xs [&_th]:font-semibold [&_th]:text-ink-2 [&_tbody>tr:last-child>th]:border-b-0 [&_tbody>tr:last-child>td]:border-b-0" },
57
56
  el("thead", {}, el("tr", {}, el("th", {}, "Unit"), el("th", {}, "Value"))),
58
57
  el("tbody", {}, ...UNITS.map((unit) => el("tr", {},
59
58
  el("td", {}, unit.label),
@@ -77,8 +76,7 @@ export function mount(slot) {
77
76
  stack(panel("Value", value), panel("From", from), panel("To", to), error),
78
77
  stack(panel("Result", stats), factor, panel("All units", scroll))
79
78
  ),
80
- foot: actions(swap, copyButton(() => text, "Copy result", "fill")),
81
- });
79
+ foot: actions(swap, copyButton(() => text, "Copy result", "fill"))});
82
80
  slot.append(card.node);
83
81
  run();
84
82
 
@@ -11,8 +11,8 @@ export function mount(slot) {
11
11
  let day = Number.isInteger(saved.day) && saved.day >= 0 && saved.day < 7 ? saved.day : 0;
12
12
 
13
13
  const entry = textInput({ placeholder: "New item", "aria-label": "New item" });
14
- const listWrap = el("div", { class: "mvb-scroll" });
15
- const stats = el("div", { class: "mvb-stats" });
14
+ const listWrap = el("div", { class: "max-h-80 overflow-auto" });
15
+ const stats = el("div", { class: "grid gap-2.5 [grid-template-columns:repeat(auto-fit,minmax(120px,1fr))]" });
16
16
 
17
17
  const dayChips = chipRow(DAYS.map((label, value) => ({ value, label })), {
18
18
  value: day,
@@ -21,15 +21,14 @@ export function mount(slot) {
21
21
  day = next;
22
22
  save();
23
23
  render();
24
- },
25
- });
24
+ }});
26
25
 
27
26
  const addButton = button("Add", { icon: "plus", kind: "fill" });
28
27
  const copyWeek = copyButton(() => weekText(), "Copy week");
29
28
 
30
- const tile = (key, value) => el("div", { class: "mvb-stat" },
31
- el("span", { class: "mvb-stat__v" }, String(value)),
32
- el("span", { class: "mvb-stat__k" }, key));
29
+ const tile = (key, value) => el("div", { class: "grid gap-0.5 rounded-r1 border border-orbit bg-deck-2 px-3.5 py-3" },
30
+ el("span", { class: "wrap-anywhere text-xl font-bold tracking-[-0.02em] tabular-nums" }, String(value)),
31
+ el("span", { class: "text-2xs font-semibold text-ink-3" }, key));
33
32
 
34
33
  const save = () => writePin(PIN, { day, days });
35
34
 
@@ -53,7 +52,7 @@ export function mount(slot) {
53
52
  save();
54
53
  render();
55
54
  });
56
- return el("div", { class: "mvb-row" }, box, remove);
55
+ return el("div", { class: "flex min-w-0 flex-wrap items-center gap-2" }, box, remove);
57
56
  }
58
57
 
59
58
  function renderStats() {
@@ -90,8 +89,7 @@ export function mount(slot) {
90
89
  stack(panel("Day", dayChips), panel("New item", entry)),
91
90
  stack(stats, panel("Items", listWrap))
92
91
  ),
93
- foot: actions(copyWeek, addButton),
94
- });
92
+ foot: actions(copyWeek, addButton)});
95
93
  slot.append(card.node);
96
94
  render();
97
95