aztomiq 1.0.2 → 1.0.4

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.
@@ -0,0 +1,138 @@
1
+ document.addEventListener("DOMContentLoaded", () => {
2
+ // Main Homepage Logic (View Toggle & Sorting)
3
+ const toolGrids = document.querySelectorAll(".tools-grid");
4
+ const viewToggleBtns = document.querySelectorAll("[data-view]");
5
+ const sortSelect = document.getElementById("sort-select");
6
+
7
+ // Only proceed if we are on the homepage (elements exist)
8
+ if (toolGrids.length === 0) return;
9
+
10
+
11
+ // --- 3. View Toggle Logic ---
12
+ const savedView = localStorage.getItem("aztomiq_view_mode") || "grid";
13
+ const savedSort = localStorage.getItem("aztomiq_sort_mode") || "default";
14
+
15
+ applyView(savedView);
16
+ if (sortSelect) {
17
+ sortSelect.value = savedSort;
18
+ applySort(savedSort);
19
+ }
20
+
21
+ viewToggleBtns.forEach((btn) => {
22
+ btn.addEventListener("click", () => {
23
+ const view = btn.dataset.view;
24
+ applyView(view);
25
+ localStorage.setItem("aztomiq_view_mode", view);
26
+ });
27
+ });
28
+
29
+ function applyView(viewMode) {
30
+ toolGrids.forEach((grid) => {
31
+ if (viewMode === "list") grid.classList.add("list-view");
32
+ else grid.classList.remove("list-view");
33
+ });
34
+ viewToggleBtns.forEach((btn) => {
35
+ if (btn.dataset.view === viewMode) {
36
+ btn.classList.add("active");
37
+ btn.style.backgroundColor = "var(--primary-color)";
38
+ btn.style.color = "white";
39
+ } else {
40
+ btn.classList.remove("active");
41
+ btn.style.backgroundColor = "transparent";
42
+ btn.style.color = "var(--text-color)";
43
+ }
44
+ });
45
+ }
46
+
47
+ // --- 4. Sort Logic ---
48
+ if (sortSelect) {
49
+ sortSelect.addEventListener("change", (e) => {
50
+ const sortMode = e.target.value;
51
+ applySort(sortMode);
52
+ localStorage.setItem("aztomiq_sort_mode", sortMode);
53
+ });
54
+ }
55
+
56
+ function applySort(sortMode) {
57
+ const recent = JSON.parse(localStorage.getItem('aztomiq_recent') || '{}');
58
+ const usage = JSON.parse(localStorage.getItem('aztomiq_usage') || '{}');
59
+ // Mock global popularity if provided in DOM later, for now defaults to 0
60
+ // We can assume static popularity is not yet available in DOM dataset.
61
+
62
+ toolGrids.forEach((grid) => {
63
+ const items = Array.from(grid.children);
64
+
65
+ // Save original index
66
+ if (!grid.dataset.indexed) {
67
+ items.forEach((item, index) => item.dataset.originalIndex = index);
68
+ grid.dataset.indexed = "true";
69
+ }
70
+
71
+ items.sort((a, b) => {
72
+ // Extract ID for usage lookup
73
+ // Href is safe bet if we can parse it, or we rely on text content for AZ
74
+ // Better: let's try to infer ID from href
75
+ const getID = (el) => {
76
+ const href = el.getAttribute('href');
77
+ if (!href) return '';
78
+ const parts = href.split('/').filter(Boolean);
79
+ return parts[parts.length - 1];
80
+ };
81
+
82
+ const idA = getID(a);
83
+ const idB = getID(b);
84
+
85
+ if (sortMode === "az") {
86
+ const titleA = a.querySelector("h3")?.innerText.trim() || "";
87
+ const titleB = b.querySelector("h3")?.innerText.trim() || "";
88
+ return titleA.localeCompare(titleB);
89
+ } else if (sortMode === "za") {
90
+ const titleA = a.querySelector("h3")?.innerText.trim() || "";
91
+ const titleB = b.querySelector("h3")?.innerText.trim() || "";
92
+ return titleB.localeCompare(titleA);
93
+ } else if (sortMode === "recent") {
94
+ // Descending timestamp
95
+ const timeA = recent[idA] || 0;
96
+ const timeB = recent[idB] || 0;
97
+ return timeB - timeA;
98
+ } else if (sortMode === "popular") {
99
+ // Descending count
100
+ const countA = usage[idA] || 0;
101
+ const countB = usage[idB] || 0;
102
+ return countB - countA;
103
+ } else {
104
+ // Default
105
+ return parseInt(a.dataset.originalIndex) - parseInt(b.dataset.originalIndex);
106
+ }
107
+ });
108
+ items.forEach((item) => grid.appendChild(item));
109
+ });
110
+ }
111
+
112
+ // --- 5. Hero Search Logic (Bridge to Global Search) ---
113
+ const homeSearch = document.getElementById("home-search");
114
+ if (homeSearch) {
115
+ homeSearch.addEventListener("focus", () => {
116
+ homeSearch.blur();
117
+ document.getElementById("header-search-box")?.click() ||
118
+ document.getElementById("search-btn")?.click() ||
119
+ document.getElementById("search-btn-mobile")?.click();
120
+ });
121
+ }
122
+
123
+ // --- 6. Category Filter Logic ---
124
+ const catFilter = document.getElementById("category-filter");
125
+ if (catFilter) {
126
+ catFilter.addEventListener("change", (e) => {
127
+ const cat = e.target.value;
128
+ const sections = document.querySelectorAll(".category-section");
129
+ sections.forEach(sec => {
130
+ if (cat === "all" || sec.id === cat + "-tools") {
131
+ sec.style.display = "block";
132
+ } else {
133
+ sec.style.display = "none";
134
+ }
135
+ });
136
+ });
137
+ }
138
+ });
@@ -0,0 +1,54 @@
1
+ (function () {
2
+ const MODE_KEY = 'aztomiq_user_mode';
3
+ const modes = { STANDARD: 'standard', ADVANCED: 'advanced' };
4
+
5
+ // Get saved mode or default to standard
6
+ let currentMode = localStorage.getItem(MODE_KEY) || modes.STANDARD;
7
+
8
+ // Apply mode to document
9
+ function applyMode(mode) {
10
+ document.documentElement.setAttribute('data-user-mode', mode);
11
+ localStorage.setItem(MODE_KEY, mode);
12
+
13
+ // Update toggle button if exists
14
+ const toggleBtn = document.getElementById('mode-toggle');
15
+ if (toggleBtn) {
16
+ const isAdvanced = mode === modes.ADVANCED;
17
+ toggleBtn.classList.toggle('is-advanced', isAdvanced);
18
+ toggleBtn.setAttribute('aria-label', isAdvanced ? 'Switch to Standard Mode' : 'Switch to Advanced Mode');
19
+ }
20
+
21
+ // Dispatch event for other components
22
+ window.dispatchEvent(new CustomEvent('aztomiq-mode-change', { detail: { mode } }));
23
+ }
24
+
25
+ // Initial apply
26
+ applyMode(currentMode);
27
+
28
+ // Expose to window
29
+ window.AZtomiqMode = {
30
+ get: () => currentMode,
31
+ set: (mode) => {
32
+ currentMode = mode;
33
+ applyMode(mode);
34
+ },
35
+ toggle: () => {
36
+ const newMode = currentMode === modes.STANDARD ? modes.ADVANCED : modes.STANDARD;
37
+ window.AZtomiqMode.set(newMode);
38
+ },
39
+ MODES: modes
40
+ };
41
+
42
+ // Wait for DOM to attach listener
43
+ document.addEventListener('DOMContentLoaded', () => {
44
+ const toggleBtn = document.getElementById('mode-toggle');
45
+ if (toggleBtn) {
46
+ toggleBtn.addEventListener('click', (e) => {
47
+ e.preventDefault();
48
+ window.AZtomiqMode.toggle();
49
+ });
50
+ // Re-apply to ensure UI is in sync
51
+ applyMode(currentMode);
52
+ }
53
+ });
54
+ })();
@@ -0,0 +1 @@
1
+ var QRCode; !function () { function a(a) { this.mode = c.MODE_8BIT_BYTE, this.data = a, this.parsedData = []; for (var b = [], d = 0, e = this.data.length; e > d; d++) { var f = this.data.charCodeAt(d); f > 65536 ? (b[0] = 240 | (1835008 & f) >>> 18, b[1] = 128 | (258048 & f) >>> 12, b[2] = 128 | (4032 & f) >>> 6, b[3] = 128 | 63 & f) : f > 2048 ? (b[0] = 224 | (61440 & f) >>> 12, b[1] = 128 | (4032 & f) >>> 6, b[2] = 128 | 63 & f) : f > 128 ? (b[0] = 192 | (1984 & f) >>> 6, b[1] = 128 | 63 & f) : b[0] = f, this.parsedData = this.parsedData.concat(b) } this.parsedData.length != this.data.length && (this.parsedData.unshift(191), this.parsedData.unshift(187), this.parsedData.unshift(239)) } function b(a, b) { this.typeNumber = a, this.errorCorrectLevel = b, this.modules = null, this.moduleCount = 0, this.dataCache = null, this.dataList = [] } function i(a, b) { if (void 0 == a.length) throw new Error(a.length + "/" + b); for (var c = 0; c < a.length && 0 == a[c];)c++; this.num = new Array(a.length - c + b); for (var d = 0; d < a.length - c; d++)this.num[d] = a[d + c] } function j(a, b) { this.totalCount = a, this.dataCount = b } function k() { this.buffer = [], this.length = 0 } function m() { return "undefined" != typeof CanvasRenderingContext2D } function n() { var a = !1, b = navigator.userAgent; return /android/i.test(b) && (a = !0, aMat = b.toString().match(/android ([0-9]\.[0-9])/i), aMat && aMat[1] && (a = parseFloat(aMat[1]))), a } function r(a, b) { for (var c = 1, e = s(a), f = 0, g = l.length; g >= f; f++) { var h = 0; switch (b) { case d.L: h = l[f][0]; break; case d.M: h = l[f][1]; break; case d.Q: h = l[f][2]; break; case d.H: h = l[f][3] }if (h >= e) break; c++ } if (c > l.length) throw new Error("Too long data"); return c } function s(a) { var b = encodeURI(a).toString().replace(/\%[0-9a-fA-F]{2}/g, "a"); return b.length + (b.length != a ? 3 : 0) } a.prototype = { getLength: function () { return this.parsedData.length }, write: function (a) { for (var b = 0, c = this.parsedData.length; c > b; b++)a.put(this.parsedData[b], 8) } }, b.prototype = { addData: function (b) { var c = new a(b); this.dataList.push(c), this.dataCache = null }, isDark: function (a, b) { if (0 > a || this.moduleCount <= a || 0 > b || this.moduleCount <= b) throw new Error(a + "," + b); return this.modules[a][b] }, getModuleCount: function () { return this.moduleCount }, make: function () { this.makeImpl(!1, this.getBestMaskPattern()) }, makeImpl: function (a, c) { this.moduleCount = 4 * this.typeNumber + 17, this.modules = new Array(this.moduleCount); for (var d = 0; d < this.moduleCount; d++) { this.modules[d] = new Array(this.moduleCount); for (var e = 0; e < this.moduleCount; e++)this.modules[d][e] = null } this.setupPositionProbePattern(0, 0), this.setupPositionProbePattern(this.moduleCount - 7, 0), this.setupPositionProbePattern(0, this.moduleCount - 7), this.setupPositionAdjustPattern(), this.setupTimingPattern(), this.setupTypeInfo(a, c), this.typeNumber >= 7 && this.setupTypeNumber(a), null == this.dataCache && (this.dataCache = b.createData(this.typeNumber, this.errorCorrectLevel, this.dataList)), this.mapData(this.dataCache, c) }, setupPositionProbePattern: function (a, b) { for (var c = -1; 7 >= c; c++)if (!(-1 >= a + c || this.moduleCount <= a + c)) for (var d = -1; 7 >= d; d++)-1 >= b + d || this.moduleCount <= b + d || (this.modules[a + c][b + d] = c >= 0 && 6 >= c && (0 == d || 6 == d) || d >= 0 && 6 >= d && (0 == c || 6 == c) || c >= 2 && 4 >= c && d >= 2 && 4 >= d ? !0 : !1) }, getBestMaskPattern: function () { for (var a = 0, b = 0, c = 0; 8 > c; c++) { this.makeImpl(!0, c); var d = f.getLostPoint(this); (0 == c || a > d) && (a = d, b = c) } return b }, createMovieClip: function (a, b, c) { var d = a.createEmptyMovieClip(b, c), e = 1; this.make(); for (var f = 0; f < this.modules.length; f++)for (var g = f * e, h = 0; h < this.modules[f].length; h++) { var i = h * e, j = this.modules[f][h]; j && (d.beginFill(0, 100), d.moveTo(i, g), d.lineTo(i + e, g), d.lineTo(i + e, g + e), d.lineTo(i, g + e), d.endFill()) } return d }, setupTimingPattern: function () { for (var a = 8; a < this.moduleCount - 8; a++)null == this.modules[a][6] && (this.modules[a][6] = 0 == a % 2); for (var b = 8; b < this.moduleCount - 8; b++)null == this.modules[6][b] && (this.modules[6][b] = 0 == b % 2) }, setupPositionAdjustPattern: function () { for (var a = f.getPatternPosition(this.typeNumber), b = 0; b < a.length; b++)for (var c = 0; c < a.length; c++) { var d = a[b], e = a[c]; if (null == this.modules[d][e]) for (var g = -2; 2 >= g; g++)for (var h = -2; 2 >= h; h++)this.modules[d + g][e + h] = -2 == g || 2 == g || -2 == h || 2 == h || 0 == g && 0 == h ? !0 : !1 } }, setupTypeNumber: function (a) { for (var b = f.getBCHTypeNumber(this.typeNumber), c = 0; 18 > c; c++) { var d = !a && 1 == (1 & b >> c); this.modules[Math.floor(c / 3)][c % 3 + this.moduleCount - 8 - 3] = d } for (var c = 0; 18 > c; c++) { var d = !a && 1 == (1 & b >> c); this.modules[c % 3 + this.moduleCount - 8 - 3][Math.floor(c / 3)] = d } }, setupTypeInfo: function (a, b) { for (var c = this.errorCorrectLevel << 3 | b, d = f.getBCHTypeInfo(c), e = 0; 15 > e; e++) { var g = !a && 1 == (1 & d >> e); 6 > e ? this.modules[e][8] = g : 8 > e ? this.modules[e + 1][8] = g : this.modules[this.moduleCount - 15 + e][8] = g } for (var e = 0; 15 > e; e++) { var g = !a && 1 == (1 & d >> e); 8 > e ? this.modules[8][this.moduleCount - e - 1] = g : 9 > e ? this.modules[8][15 - e - 1 + 1] = g : this.modules[8][15 - e - 1] = g } this.modules[this.moduleCount - 8][8] = !a }, mapData: function (a, b) { for (var c = -1, d = this.moduleCount - 1, e = 7, g = 0, h = this.moduleCount - 1; h > 0; h -= 2)for (6 == h && h--; ;) { for (var i = 0; 2 > i; i++)if (null == this.modules[d][h - i]) { var j = !1; g < a.length && (j = 1 == (1 & a[g] >>> e)); var k = f.getMask(b, d, h - i); k && (j = !j), this.modules[d][h - i] = j, e--, -1 == e && (g++, e = 7) } if (d += c, 0 > d || this.moduleCount <= d) { d -= c, c = -c; break } } } }, b.PAD0 = 236, b.PAD1 = 17, b.createData = function (a, c, d) { for (var e = j.getRSBlocks(a, c), g = new k, h = 0; h < d.length; h++) { var i = d[h]; g.put(i.mode, 4), g.put(i.getLength(), f.getLengthInBits(i.mode, a)), i.write(g) } for (var l = 0, h = 0; h < e.length; h++)l += e[h].dataCount; if (g.getLengthInBits() > 8 * l) throw new Error("code length overflow. (" + g.getLengthInBits() + ">" + 8 * l + ")"); for (g.getLengthInBits() + 4 <= 8 * l && g.put(0, 4); 0 != g.getLengthInBits() % 8;)g.putBit(!1); for (; ;) { if (g.getLengthInBits() >= 8 * l) break; if (g.put(b.PAD0, 8), g.getLengthInBits() >= 8 * l) break; g.put(b.PAD1, 8) } return b.createBytes(g, e) }, b.createBytes = function (a, b) { for (var c = 0, d = 0, e = 0, g = new Array(b.length), h = new Array(b.length), j = 0; j < b.length; j++) { var k = b[j].dataCount, l = b[j].totalCount - k; d = Math.max(d, k), e = Math.max(e, l), g[j] = new Array(k); for (var m = 0; m < g[j].length; m++)g[j][m] = 255 & a.buffer[m + c]; c += k; var n = f.getErrorCorrectPolynomial(l), o = new i(g[j], n.getLength() - 1), p = o.mod(n); h[j] = new Array(n.getLength() - 1); for (var m = 0; m < h[j].length; m++) { var q = m + p.getLength() - h[j].length; h[j][m] = q >= 0 ? p.get(q) : 0 } } for (var r = 0, m = 0; m < b.length; m++)r += b[m].totalCount; for (var s = new Array(r), t = 0, m = 0; d > m; m++)for (var j = 0; j < b.length; j++)m < g[j].length && (s[t++] = g[j][m]); for (var m = 0; e > m; m++)for (var j = 0; j < b.length; j++)m < h[j].length && (s[t++] = h[j][m]); return s }; for (var c = { MODE_NUMBER: 1, MODE_ALPHA_NUM: 2, MODE_8BIT_BYTE: 4, MODE_KANJI: 8 }, d = { L: 1, M: 0, Q: 3, H: 2 }, e = { PATTERN000: 0, PATTERN001: 1, PATTERN010: 2, PATTERN011: 3, PATTERN100: 4, PATTERN101: 5, PATTERN110: 6, PATTERN111: 7 }, f = { PATTERN_POSITION_TABLE: [[], [6, 18], [6, 22], [6, 26], [6, 30], [6, 34], [6, 22, 38], [6, 24, 42], [6, 26, 46], [6, 28, 50], [6, 30, 54], [6, 32, 58], [6, 34, 62], [6, 26, 46, 66], [6, 26, 48, 70], [6, 26, 50, 74], [6, 30, 54, 78], [6, 30, 56, 82], [6, 30, 58, 86], [6, 34, 62, 90], [6, 28, 50, 72, 94], [6, 26, 50, 74, 98], [6, 30, 54, 78, 102], [6, 28, 54, 80, 106], [6, 32, 58, 84, 110], [6, 30, 58, 86, 114], [6, 34, 62, 90, 118], [6, 26, 50, 74, 98, 122], [6, 30, 54, 78, 102, 126], [6, 26, 52, 78, 104, 130], [6, 30, 56, 82, 108, 134], [6, 34, 60, 86, 112, 138], [6, 30, 58, 86, 114, 142], [6, 34, 62, 90, 118, 146], [6, 30, 54, 78, 102, 126, 150], [6, 24, 50, 76, 102, 128, 154], [6, 28, 54, 80, 106, 132, 158], [6, 32, 58, 84, 110, 136, 162], [6, 26, 54, 82, 110, 138, 166], [6, 30, 58, 86, 114, 142, 170]], G15: 1335, G18: 7973, G15_MASK: 21522, getBCHTypeInfo: function (a) { for (var b = a << 10; f.getBCHDigit(b) - f.getBCHDigit(f.G15) >= 0;)b ^= f.G15 << f.getBCHDigit(b) - f.getBCHDigit(f.G15); return (a << 10 | b) ^ f.G15_MASK }, getBCHTypeNumber: function (a) { for (var b = a << 12; f.getBCHDigit(b) - f.getBCHDigit(f.G18) >= 0;)b ^= f.G18 << f.getBCHDigit(b) - f.getBCHDigit(f.G18); return a << 12 | b }, getBCHDigit: function (a) { for (var b = 0; 0 != a;)b++, a >>>= 1; return b }, getPatternPosition: function (a) { return f.PATTERN_POSITION_TABLE[a - 1] }, getMask: function (a, b, c) { switch (a) { case e.PATTERN000: return 0 == (b + c) % 2; case e.PATTERN001: return 0 == b % 2; case e.PATTERN010: return 0 == c % 3; case e.PATTERN011: return 0 == (b + c) % 3; case e.PATTERN100: return 0 == (Math.floor(b / 2) + Math.floor(c / 3)) % 2; case e.PATTERN101: return 0 == b * c % 2 + b * c % 3; case e.PATTERN110: return 0 == (b * c % 2 + b * c % 3) % 2; case e.PATTERN111: return 0 == (b * c % 3 + (b + c) % 2) % 2; default: throw new Error("bad maskPattern:" + a) } }, getErrorCorrectPolynomial: function (a) { for (var b = new i([1], 0), c = 0; a > c; c++)b = b.multiply(new i([1, g.gexp(c)], 0)); return b }, getLengthInBits: function (a, b) { if (b >= 1 && 10 > b) switch (a) { case c.MODE_NUMBER: return 10; case c.MODE_ALPHA_NUM: return 9; case c.MODE_8BIT_BYTE: return 8; case c.MODE_KANJI: return 8; default: throw new Error("mode:" + a) } else if (27 > b) switch (a) { case c.MODE_NUMBER: return 12; case c.MODE_ALPHA_NUM: return 11; case c.MODE_8BIT_BYTE: return 16; case c.MODE_KANJI: return 10; default: throw new Error("mode:" + a) } else { if (!(41 > b)) throw new Error("type:" + b); switch (a) { case c.MODE_NUMBER: return 14; case c.MODE_ALPHA_NUM: return 13; case c.MODE_8BIT_BYTE: return 16; case c.MODE_KANJI: return 12; default: throw new Error("mode:" + a) } } }, getLostPoint: function (a) { for (var b = a.getModuleCount(), c = 0, d = 0; b > d; d++)for (var e = 0; b > e; e++) { for (var f = 0, g = a.isDark(d, e), h = -1; 1 >= h; h++)if (!(0 > d + h || d + h >= b)) for (var i = -1; 1 >= i; i++)0 > e + i || e + i >= b || (0 != h || 0 != i) && g == a.isDark(d + h, e + i) && f++; f > 5 && (c += 3 + f - 5) } for (var d = 0; b - 1 > d; d++)for (var e = 0; b - 1 > e; e++) { var j = 0; a.isDark(d, e) && j++, a.isDark(d + 1, e) && j++, a.isDark(d, e + 1) && j++, a.isDark(d + 1, e + 1) && j++, (0 == j || 4 == j) && (c += 3) } for (var d = 0; b > d; d++)for (var e = 0; b - 6 > e; e++)a.isDark(d, e) && !a.isDark(d, e + 1) && a.isDark(d, e + 2) && a.isDark(d, e + 3) && a.isDark(d, e + 4) && !a.isDark(d, e + 5) && a.isDark(d, e + 6) && (c += 40); for (var e = 0; b > e; e++)for (var d = 0; b - 6 > d; d++)a.isDark(d, e) && !a.isDark(d + 1, e) && a.isDark(d + 2, e) && a.isDark(d + 3, e) && a.isDark(d + 4, e) && !a.isDark(d + 5, e) && a.isDark(d + 6, e) && (c += 40); for (var k = 0, e = 0; b > e; e++)for (var d = 0; b > d; d++)a.isDark(d, e) && k++; var l = Math.abs(100 * k / b / b - 50) / 5; return c += 10 * l } }, g = { glog: function (a) { if (1 > a) throw new Error("glog(" + a + ")"); return g.LOG_TABLE[a] }, gexp: function (a) { for (; 0 > a;)a += 255; for (; a >= 256;)a -= 255; return g.EXP_TABLE[a] }, EXP_TABLE: new Array(256), LOG_TABLE: new Array(256) }, h = 0; 8 > h; h++)g.EXP_TABLE[h] = 1 << h; for (var h = 8; 256 > h; h++)g.EXP_TABLE[h] = g.EXP_TABLE[h - 4] ^ g.EXP_TABLE[h - 5] ^ g.EXP_TABLE[h - 6] ^ g.EXP_TABLE[h - 8]; for (var h = 0; 255 > h; h++)g.LOG_TABLE[g.EXP_TABLE[h]] = h; i.prototype = { get: function (a) { return this.num[a] }, getLength: function () { return this.num.length }, multiply: function (a) { for (var b = new Array(this.getLength() + a.getLength() - 1), c = 0; c < this.getLength(); c++)for (var d = 0; d < a.getLength(); d++)b[c + d] ^= g.gexp(g.glog(this.get(c)) + g.glog(a.get(d))); return new i(b, 0) }, mod: function (a) { if (this.getLength() - a.getLength() < 0) return this; for (var b = g.glog(this.get(0)) - g.glog(a.get(0)), c = new Array(this.getLength()), d = 0; d < this.getLength(); d++)c[d] = this.get(d); for (var d = 0; d < a.getLength(); d++)c[d] ^= g.gexp(g.glog(a.get(d)) + b); return new i(c, 0).mod(a) } }, j.RS_BLOCK_TABLE = [[1, 26, 19], [1, 26, 16], [1, 26, 13], [1, 26, 9], [1, 44, 34], [1, 44, 28], [1, 44, 22], [1, 44, 16], [1, 70, 55], [1, 70, 44], [2, 35, 17], [2, 35, 13], [1, 100, 80], [2, 50, 32], [2, 50, 24], [4, 25, 9], [1, 134, 108], [2, 67, 43], [2, 33, 15, 2, 34, 16], [2, 33, 11, 2, 34, 12], [2, 86, 68], [4, 43, 27], [4, 43, 19], [4, 43, 15], [2, 98, 78], [4, 49, 31], [2, 32, 14, 4, 33, 15], [4, 39, 13, 1, 40, 14], [2, 121, 97], [2, 60, 38, 2, 61, 39], [4, 40, 18, 2, 41, 19], [4, 40, 14, 2, 41, 15], [2, 146, 116], [3, 58, 36, 2, 59, 37], [4, 36, 16, 4, 37, 17], [4, 36, 12, 4, 37, 13], [2, 86, 68, 2, 87, 69], [4, 69, 43, 1, 70, 44], [6, 43, 19, 2, 44, 20], [6, 43, 15, 2, 44, 16], [4, 101, 81], [1, 80, 50, 4, 81, 51], [4, 50, 22, 4, 51, 23], [3, 36, 12, 8, 37, 13], [2, 116, 92, 2, 117, 93], [6, 58, 36, 2, 59, 37], [4, 46, 20, 6, 47, 21], [7, 42, 14, 4, 43, 15], [4, 133, 107], [8, 59, 37, 1, 60, 38], [8, 44, 20, 4, 45, 21], [12, 33, 11, 4, 34, 12], [3, 145, 115, 1, 146, 116], [4, 64, 40, 5, 65, 41], [11, 36, 16, 5, 37, 17], [11, 36, 12, 5, 37, 13], [5, 109, 87, 1, 110, 88], [5, 65, 41, 5, 66, 42], [5, 54, 24, 7, 55, 25], [11, 36, 12], [5, 122, 98, 1, 123, 99], [7, 73, 45, 3, 74, 46], [15, 43, 19, 2, 44, 20], [3, 45, 15, 13, 46, 16], [1, 135, 107, 5, 136, 108], [10, 74, 46, 1, 75, 47], [1, 50, 22, 15, 51, 23], [2, 42, 14, 17, 43, 15], [5, 150, 120, 1, 151, 121], [9, 69, 43, 4, 70, 44], [17, 50, 22, 1, 51, 23], [2, 42, 14, 19, 43, 15], [3, 141, 113, 4, 142, 114], [3, 70, 44, 11, 71, 45], [17, 47, 21, 4, 48, 22], [9, 39, 13, 16, 40, 14], [3, 135, 107, 5, 136, 108], [3, 67, 41, 13, 68, 42], [15, 54, 24, 5, 55, 25], [15, 43, 15, 10, 44, 16], [4, 144, 116, 4, 145, 117], [17, 68, 42], [17, 50, 22, 6, 51, 23], [19, 46, 16, 6, 47, 17], [2, 139, 111, 7, 140, 112], [17, 74, 46], [7, 54, 24, 16, 55, 25], [34, 37, 13], [4, 151, 121, 5, 152, 122], [4, 75, 47, 14, 76, 48], [11, 54, 24, 14, 55, 25], [16, 45, 15, 14, 46, 16], [6, 147, 117, 4, 148, 118], [6, 73, 45, 14, 74, 46], [11, 54, 24, 16, 55, 25], [30, 46, 16, 2, 47, 17], [8, 132, 106, 4, 133, 107], [8, 75, 47, 13, 76, 48], [7, 54, 24, 22, 55, 25], [22, 45, 15, 13, 46, 16], [10, 142, 114, 2, 143, 115], [19, 74, 46, 4, 75, 47], [28, 50, 22, 6, 51, 23], [33, 46, 16, 4, 47, 17], [8, 152, 122, 4, 153, 123], [22, 73, 45, 3, 74, 46], [8, 53, 23, 26, 54, 24], [12, 45, 15, 28, 46, 16], [3, 147, 117, 10, 148, 118], [3, 73, 45, 23, 74, 46], [4, 54, 24, 31, 55, 25], [11, 45, 15, 31, 46, 16], [7, 146, 116, 7, 147, 117], [21, 73, 45, 7, 74, 46], [1, 53, 23, 37, 54, 24], [19, 45, 15, 26, 46, 16], [5, 145, 115, 10, 146, 116], [19, 75, 47, 10, 76, 48], [15, 54, 24, 25, 55, 25], [23, 45, 15, 25, 46, 16], [13, 145, 115, 3, 146, 116], [2, 74, 46, 29, 75, 47], [42, 54, 24, 1, 55, 25], [23, 45, 15, 28, 46, 16], [17, 145, 115], [10, 74, 46, 23, 75, 47], [10, 54, 24, 35, 55, 25], [19, 45, 15, 35, 46, 16], [17, 145, 115, 1, 146, 116], [14, 74, 46, 21, 75, 47], [29, 54, 24, 19, 55, 25], [11, 45, 15, 46, 46, 16], [13, 145, 115, 6, 146, 116], [14, 74, 46, 23, 75, 47], [44, 54, 24, 7, 55, 25], [59, 46, 16, 1, 47, 17], [12, 151, 121, 7, 152, 122], [12, 75, 47, 26, 76, 48], [39, 54, 24, 14, 55, 25], [22, 45, 15, 41, 46, 16], [6, 151, 121, 14, 152, 122], [6, 75, 47, 34, 76, 48], [46, 54, 24, 10, 55, 25], [2, 45, 15, 64, 46, 16], [17, 152, 122, 4, 153, 123], [29, 74, 46, 14, 75, 47], [49, 54, 24, 10, 55, 25], [24, 45, 15, 46, 46, 16], [4, 152, 122, 18, 153, 123], [13, 74, 46, 32, 75, 47], [48, 54, 24, 14, 55, 25], [42, 45, 15, 32, 46, 16], [20, 147, 117, 4, 148, 118], [40, 75, 47, 7, 76, 48], [43, 54, 24, 22, 55, 25], [10, 45, 15, 67, 46, 16], [19, 148, 118, 6, 149, 119], [18, 75, 47, 31, 76, 48], [34, 54, 24, 34, 55, 25], [20, 45, 15, 61, 46, 16]], j.getRSBlocks = function (a, b) { var c = j.getRsBlockTable(a, b); if (void 0 == c) throw new Error("bad rs block @ typeNumber:" + a + "/errorCorrectLevel:" + b); for (var d = c.length / 3, e = [], f = 0; d > f; f++)for (var g = c[3 * f + 0], h = c[3 * f + 1], i = c[3 * f + 2], k = 0; g > k; k++)e.push(new j(h, i)); return e }, j.getRsBlockTable = function (a, b) { switch (b) { case d.L: return j.RS_BLOCK_TABLE[4 * (a - 1) + 0]; case d.M: return j.RS_BLOCK_TABLE[4 * (a - 1) + 1]; case d.Q: return j.RS_BLOCK_TABLE[4 * (a - 1) + 2]; case d.H: return j.RS_BLOCK_TABLE[4 * (a - 1) + 3]; default: return void 0 } }, k.prototype = { get: function (a) { var b = Math.floor(a / 8); return 1 == (1 & this.buffer[b] >>> 7 - a % 8) }, put: function (a, b) { for (var c = 0; b > c; c++)this.putBit(1 == (1 & a >>> b - c - 1)) }, getLengthInBits: function () { return this.length }, putBit: function (a) { var b = Math.floor(this.length / 8); this.buffer.length <= b && this.buffer.push(0), a && (this.buffer[b] |= 128 >>> this.length % 8), this.length++ } }; var l = [[17, 14, 11, 7], [32, 26, 20, 14], [53, 42, 32, 24], [78, 62, 46, 34], [106, 84, 60, 44], [134, 106, 74, 58], [154, 122, 86, 64], [192, 152, 108, 84], [230, 180, 130, 98], [271, 213, 151, 119], [321, 251, 177, 137], [367, 287, 203, 155], [425, 331, 241, 177], [458, 362, 258, 194], [520, 412, 292, 220], [586, 450, 322, 250], [644, 504, 364, 280], [718, 560, 394, 310], [792, 624, 442, 338], [858, 666, 482, 382], [929, 711, 509, 403], [1003, 779, 565, 439], [1091, 857, 611, 461], [1171, 911, 661, 511], [1273, 997, 715, 535], [1367, 1059, 751, 593], [1465, 1125, 805, 625], [1528, 1190, 868, 658], [1628, 1264, 908, 698], [1732, 1370, 982, 742], [1840, 1452, 1030, 790], [1952, 1538, 1112, 842], [2068, 1628, 1168, 898], [2188, 1722, 1228, 958], [2303, 1809, 1283, 983], [2431, 1911, 1351, 1051], [2563, 1989, 1423, 1093], [2699, 2099, 1499, 1139], [2809, 2213, 1579, 1219], [2953, 2331, 1663, 1273]], o = function () { var a = function (a, b) { this._el = a, this._htOption = b }; return a.prototype.draw = function (a) { function g(a, b) { var c = document.createElementNS("http://www.w3.org/2000/svg", a); for (var d in b) b.hasOwnProperty(d) && c.setAttribute(d, b[d]); return c } var b = this._htOption, c = this._el, d = a.getModuleCount(); Math.floor(b.width / d), Math.floor(b.height / d), this.clear(); var h = g("svg", { viewBox: "0 0 " + String(d) + " " + String(d), width: "100%", height: "100%", fill: b.colorLight }); h.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink"), c.appendChild(h), h.appendChild(g("rect", { fill: b.colorDark, width: "1", height: "1", id: "template" })); for (var i = 0; d > i; i++)for (var j = 0; d > j; j++)if (a.isDark(i, j)) { var k = g("use", { x: String(i), y: String(j) }); k.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#template"), h.appendChild(k) } }, a.prototype.clear = function () { for (; this._el.hasChildNodes();)this._el.removeChild(this._el.lastChild) }, a }(), p = "svg" === document.documentElement.tagName.toLowerCase(), q = p ? o : m() ? function () { function a() { this._elImage.src = this._elCanvas.toDataURL("image/png"), this._elImage.style.display = "block", this._elCanvas.style.display = "none" } function d(a, b) { var c = this; if (c._fFail = b, c._fSuccess = a, null === c._bSupportDataURI) { var d = document.createElement("img"), e = function () { c._bSupportDataURI = !1, c._fFail && _fFail.call(c) }, f = function () { c._bSupportDataURI = !0, c._fSuccess && c._fSuccess.call(c) }; return d.onabort = e, d.onerror = e, d.onload = f, d.src = "data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==", void 0 } c._bSupportDataURI === !0 && c._fSuccess ? c._fSuccess.call(c) : c._bSupportDataURI === !1 && c._fFail && c._fFail.call(c) } if (this._android && this._android <= 2.1) { var b = 1 / window.devicePixelRatio, c = CanvasRenderingContext2D.prototype.drawImage; CanvasRenderingContext2D.prototype.drawImage = function (a, d, e, f, g, h, i, j) { if ("nodeName" in a && /img/i.test(a.nodeName)) for (var l = arguments.length - 1; l >= 1; l--)arguments[l] = arguments[l] * b; else "undefined" == typeof j && (arguments[1] *= b, arguments[2] *= b, arguments[3] *= b, arguments[4] *= b); c.apply(this, arguments) } } var e = function (a, b) { this._bIsPainted = !1, this._android = n(), this._htOption = b, this._elCanvas = document.createElement("canvas"), this._elCanvas.width = b.width, this._elCanvas.height = b.height, a.appendChild(this._elCanvas), this._el = a, this._oContext = this._elCanvas.getContext("2d"), this._bIsPainted = !1, this._elImage = document.createElement("img"), this._elImage.style.display = "none", this._el.appendChild(this._elImage), this._bSupportDataURI = null }; return e.prototype.draw = function (a) { var b = this._elImage, c = this._oContext, d = this._htOption, e = a.getModuleCount(), f = d.width / e, g = d.height / e, h = Math.round(f), i = Math.round(g); b.style.display = "none", this.clear(); for (var j = 0; e > j; j++)for (var k = 0; e > k; k++) { var l = a.isDark(j, k), m = k * f, n = j * g; c.strokeStyle = l ? d.colorDark : d.colorLight, c.lineWidth = 1, c.fillStyle = l ? d.colorDark : d.colorLight, c.fillRect(m, n, f, g), c.strokeRect(Math.floor(m) + .5, Math.floor(n) + .5, h, i), c.strokeRect(Math.ceil(m) - .5, Math.ceil(n) - .5, h, i) } this._bIsPainted = !0 }, e.prototype.makeImage = function () { this._bIsPainted && d.call(this, a) }, e.prototype.isPainted = function () { return this._bIsPainted }, e.prototype.clear = function () { this._oContext.clearRect(0, 0, this._elCanvas.width, this._elCanvas.height), this._bIsPainted = !1 }, e.prototype.round = function (a) { return a ? Math.floor(1e3 * a) / 1e3 : a }, e }() : function () { var a = function (a, b) { this._el = a, this._htOption = b }; return a.prototype.draw = function (a) { for (var b = this._htOption, c = this._el, d = a.getModuleCount(), e = Math.floor(b.width / d), f = Math.floor(b.height / d), g = ['<table style="border:0;border-collapse:collapse;">'], h = 0; d > h; h++) { g.push("<tr>"); for (var i = 0; d > i; i++)g.push('<td style="border:0;border-collapse:collapse;padding:0;margin:0;width:' + e + "px;height:" + f + "px;background-color:" + (a.isDark(h, i) ? b.colorDark : b.colorLight) + ';"></td>'); g.push("</tr>") } g.push("</table>"), c.innerHTML = g.join(""); var j = c.childNodes[0], k = (b.width - j.offsetWidth) / 2, l = (b.height - j.offsetHeight) / 2; k > 0 && l > 0 && (j.style.margin = l + "px " + k + "px") }, a.prototype.clear = function () { this._el.innerHTML = "" }, a }(); QRCode = function (a, b) { if (this._htOption = { width: 256, height: 256, typeNumber: 4, colorDark: "#000000", colorLight: "#ffffff", correctLevel: d.H }, "string" == typeof b && (b = { text: b }), b) for (var c in b) this._htOption[c] = b[c]; "string" == typeof a && (a = document.getElementById(a)), this._android = n(), this._el = a, this._oQRCode = null, this._oDrawing = new q(this._el, this._htOption), this._htOption.text && this.makeCode(this._htOption.text) }, QRCode.prototype.makeCode = function (a) { this._oQRCode = new b(r(a, this._htOption.correctLevel), this._htOption.correctLevel), this._oQRCode.addData(a), this._oQRCode.make(), this._el.title = a, this._oDrawing.draw(this._oQRCode), this.makeImage() }, QRCode.prototype.makeImage = function () { "function" == typeof this._oDrawing.makeImage && (!this._android || this._android >= 3) && this._oDrawing.makeImage() }, QRCode.prototype.clear = function () { this._oDrawing.clear() }, QRCode.CorrectLevel = d }();
@@ -0,0 +1,93 @@
1
+ meta:
2
+ title: AZtomiq - Modern Framework
3
+ description: "A comprehensive A-Z framework for building utility sites."
4
+ about:
5
+ title: About
6
+ intro_h2: "👋 Hello!"
7
+ intro_p1: "<strong>AZtomiq</strong> is an online utility toolkit built with a focus on: <strong>Simplicity - Speed - Privacy - Convenience</strong>."
8
+ intro_p2: "We understand that when you need to calculate finance, format JSON, or <strong>quickly test code (Playground)</strong>, you want a focused, professional, and instant environment."
9
+ why_h3: "🚀 Why choose AZtomiq?"
10
+ why_li1: "<strong>Free Forever:</strong> All tools are completely free."
11
+ why_li2: "<strong>Absolute Privacy:</strong> All processing happens in your browser (Client-side). No data is sent to our servers."
12
+ why_li3: "<strong>User-Friendly Interface:</strong> Clean, intuitive design with Dark Mode support."
13
+ contact_h3: "📬 Contact"
14
+ contact_p: "For any feedback, bug reports, or feature suggestions, please contact us via email:"
15
+ privacy:
16
+ title: Privacy Policy
17
+ last_updated: "Last updated: 12/23/2025"
18
+ section1_h3: "1. Data Collection"
19
+ section1_p: "At <strong>AZtomiq</strong>, your privacy is our top priority. <strong>We do NOT collect, store, or share any personal data you enter into the tools.</strong>"
20
+ section1_li1: "Calculation data for tax, salary, BMI... is only processed on your browser."
21
+ section1_li2: "<strong>Web Playground:</strong> Any code you write and run is executed locally (client-side). Our servers do not store your source code."
22
+ section1_li3: "When you close the tab or reload the page, temporary data disappears (unless you choose to save it to LocalStorage History)."
23
+ section2_h3: "2. Local Storage & Cookies"
24
+ section2_p: "We use <strong>Local Storage</strong> for the following purposes:"
25
+ section2_li1: "Saving theme preferences (Dark/Light mode)."
26
+ section2_li2: "Saving calculation history (if enabled). This data remains entirely on your device."
27
+ section2_p2: "We do not use Cookies for tracking personal behavior."
28
+ section3_h3: "3. Third-party Services"
29
+ section3_p: "The website may use anonymous analytics to improve performance. These services operate under their own privacy policies."
30
+ section4_h3: "4. Policy Changes"
31
+ section4_p: "We reserve the right to update this policy at any time. Changes will be posted on this page."
32
+ terms:
33
+ title: Terms of Service
34
+ section1_h3: "1. Acceptance of Terms"
35
+ section1_p: "By accessing and using <strong>AZtomiq</strong>, you agree to comply with these terms. If you do not agree, please stop using the service."
36
+ section2_h3: "2. Purpose of Use"
37
+ section2_p: "AZtomiq provides utility tools for reference purposes only."
38
+ section2_li1: "<strong>Financial Tools (Tax, Salary...):</strong> Results are for reference. We strive for accuracy but are not legally responsible for absolute correctness. Consult a professional for important decisions."
39
+ section2_li2: "<strong>Health Tools (BMI...):</strong> Does not replace professional medical advice."
40
+ section2_li3: "<strong>Web Playground:</strong> You are responsible for the code you execute. We provide a sandbox but are not liable for security issues from user-inserted malicious code."
41
+ section3_h3: "3. Disclaimer"
42
+ section3_p: "AZtomiq is provided 'as is'. We do not guarantee uninterrupted service and are not liable for damages arising from website use."
43
+ section4_h3: "4. Copyright"
44
+ section4_p: "Source code and content belong to the developers, except for validly used open-source libraries."
45
+ changelog:
46
+ title: Version History
47
+ common:
48
+ legacy_title: Legacy Version
49
+ legacy_desc: This tool has been integrated into a new version.
50
+ try_master: Try Now
51
+ reset: Reset
52
+ back: Back
53
+ nav:
54
+ home: Home
55
+ menu_categories: Categories
56
+ search_placeholder: "Search... (Ctrl + K)"
57
+ search_no_results: No results found for
58
+ search_title: Search
59
+ changelog_title: Version History
60
+ menu_blog: Articles
61
+ reset: Reset
62
+ how_to_use: How to use
63
+ mode_standard: Standard
64
+ mode_advanced: Advanced
65
+ mode_standard_desc: Standard Mode
66
+ mode_advanced_desc: Advanced Mode
67
+ home:
68
+ hero_title: AZtomiq
69
+ hero_desc: "A to Z • Atomic • Fast"
70
+ favorites: My Favorites
71
+ cats:
72
+ finance:
73
+ title: Finance
74
+ dev:
75
+ title: Developer
76
+ tools:
77
+ title: General
78
+ sort:
79
+ default: Default
80
+ az: Name (A-Z)
81
+ za: Name (Z-A)
82
+ recent: Recently Used
83
+ popular: Most Used
84
+ reset: Reset
85
+ footer:
86
+ about_title: AZtomiq
87
+ about_desc: "A modern framework for building utility sites."
88
+ links_title: Links
89
+ intro: About
90
+ policy: Privacy Policy
91
+ terms: Terms of Service
92
+ changelog: Versions
93
+ copyright: "© 2025. Built with ❤️."
@@ -0,0 +1,93 @@
1
+ meta:
2
+ title: AZtomiq - Nền tảng hiện đại
3
+ description: "Bộ khung A-Z hiện đại để xây dựng trang web tiện ích."
4
+ about:
5
+ title: Giới thiệu
6
+ intro_h2: "👋 Xin chào!"
7
+ intro_p1: "<strong>AZtomiq</strong> là bộ công cụ tiện ích trực tuyến được xây dựng với mục tiêu: <strong>Đơn giản - Nhanh chóng - Riêng tư - Tiện lợi</strong>."
8
+ intro_p2: "Chúng tôi hiểu rằng khi bạn cần tính toán tài chính, format JSON, hay <strong>thử nghiệm code nhanh (Playground)</strong>, bạn muốn có một môi trường làm việc tập trung, chuyên nghiệp và tức thì."
9
+ why_h3: "🚀 Tại sao chọn AZtomiq?"
10
+ why_li1: "<strong>Miễn phí trọn đời:</strong> Tất cả công cụ đều miễn phí."
11
+ why_li2: "<strong>Bảo mật tuyệt đối:</strong> Mọi tính toán diễn ra ngay trên trình duyệt của bạn (Client-side). Không có dữ liệu nào được gửi về máy chủ."
12
+ why_li3: "<strong>Giao diện thân thiện:</strong> Sạch sẽ, dễ nhìn, hỗ trợ Dark Mode."
13
+ contact_h3: "📬 Liên hệ"
14
+ contact_p: "Mọi ý kiến đóng góp, báo lỗi hoặc đề xuất tính năng, vui lòng liên hệ qua email:"
15
+ privacy:
16
+ title: Chính sách bảo mật
17
+ last_updated: "Cập nhật lần cuối: 23/12/2025"
18
+ section1_h3: "1. Thu thập dữ liệu"
19
+ section1_p: "Tại <strong>AZtomiq</strong>, chúng tôi ưu tiên sự riêng tư của bạn lên hàng đầu. <strong>Chúng tôi KHÔNG thu thập, lưu trữ hay chia sẻ bất kỳ dữ liệu cá nhân nào bạn nhập vào các công cụ.</strong>"
20
+ section1_li1: "Dữ liệu tính thuế, lương, BMI... chỉ được xử lý trên trình duyệt của bạn."
21
+ section1_li2: "<strong>Web Playground:</strong> Mọi đoạn mã bạn viết và chạy đều được thực thi cục bộ (client-side) trong trình duyệt. Server của chúng tôi không lưu trữ mã nguồn của bạn."
22
+ section1_li3: "Khi bạn đóng tab hoặc tải lại trang, dữ liệu tạm thời này sẽ biến mất (trừ khi bạn chọn lưu vào LocalStorage)."
23
+ section2_h3: "2. Local Storage & Cookies"
24
+ section2_p: "Chúng tôi sử dụng <strong>Local Storage</strong> (bộ nhớ trình duyệt) cho các mục đích sau:"
25
+ section2_li1: "Lưu tùy chọn giao diện (Dark/Light mode)."
26
+ section2_li2: "Lưu lịch sử tính toán (nếu bạn bật tính năng này). Dữ liệu này nằm hoàn toàn trên thiết bị của bạn."
27
+ section2_p2: "Chúng tôi không sử dụng Cookies để theo dõi hành vi cá nhân."
28
+ section3_h3: "3. Dịch vụ bên thứ ba"
29
+ section3_p: "Website có thể sử dụng các dịch vụ phân tích ẩn danh để cải thiện hiệu suất. Các dịch vụ này hoạt động theo chính sách bảo mật riêng của họ."
30
+ section4_h3: "4. Thay đổi chính sách"
31
+ section4_p: "Chúng tôi có quyền cập nhật chính sách này bất cứ lúc nào. Các thay đổi sẽ được thông báo trên trang này."
32
+ terms:
33
+ title: Điều khoản sử dụng
34
+ section1_h3: "1. Chấp nhận điều khoản"
35
+ section1_p: "Bằng việc truy cập và sử dụng <strong>AZtomiq</strong>, bạn đồng ý tuân thủ các điều khoản sử dụng này. Nếu bạn không đồng ý, vui lòng ngưng sử dụng dịch vụ."
36
+ section2_h3: "2. Mục đích sử dụng"
37
+ section2_p: "AZtomiq cung cấp các công cụ tính toán và tiện ích cho mục đích tham khảo."
38
+ section2_li1: "<strong>Công cụ Tài chính (Thuế, Lương...):</strong> Kết quả tính toán chỉ mang tính chất tham khảo. Chúng tôi nỗ lực cập nhật theo luật mới nhất nhưng không chịu trách nhiệm pháp lý về tính chính xác tuyệt đối. Vui lòng tham khảo ý kiến chuyên gia cho các quyết định quan trọng."
39
+ section2_li2: "<strong>Công cụ Sức khỏe (BMI...):</strong> Không thay thế cho lời khuyên y tế chuyên nghiệp."
40
+ section2_li3: "<strong>Web Playground:</strong> Bạn tự chịu trách nhiệm về mã nguồn bạn thực thi. Chúng tôi cung cấp môi trường chạy an toàn (sandbox) nhưng không chịu trách nhiệm về các vấn đề bảo mật phát sinh từ mã độc do người dùng tự chèn vào."
41
+ section3_h3: "3. Miễn trừ trách nhiệm"
42
+ section3_p: "AZtomiq được cung cấp 'nguyên trạng'. Chúng tôi không cam kết rằng dịch vụ sẽ không bị gián đoạn hoặc không có lỗi. Chúng tôi không chịu trách nhiệm về bất kỳ thiệt hại nào phát sinh từ việc sử dụng các công cụ trên trang web này."
43
+ section4_h3: "4. Bản quyền"
44
+ section4_p: "Mã nguồn và nội dung của AZtomiq thuộc quyền sở hữu của đội ngũ phát triển, trừ các thư viện mã nguồn mở được sử dụng hợp lệ."
45
+ changelog:
46
+ title: Nhật ký thay đổi
47
+ common:
48
+ legacy_title: Phiên bản cũ
49
+ legacy_desc: Công cụ này đã được tích hợp vào phiên bản mới.
50
+ try_master: Thử ngay
51
+ reset: Đặt lại
52
+ back: Quay lại
53
+ nav:
54
+ home: Trang chủ
55
+ menu_categories: Danh mục
56
+ search_placeholder: "Tìm kiếm... (Ctrl + K)"
57
+ search_no_results: Không tìm thấy kết quả cho
58
+ search_title: Tìm kiếm
59
+ changelog_title: Nhật ký thay đổi
60
+ menu_blog: Bài viết
61
+ reset: Đặt lại
62
+ how_to_use: Hướng dẫn sử dụng
63
+ mode_standard: Standard
64
+ mode_advanced: Advanced
65
+ mode_standard_desc: Chế độ Tiêu chuẩn
66
+ mode_advanced_desc: Chế độ Nâng cao
67
+ home:
68
+ hero_title: AZtomiq
69
+ hero_desc: "A to Z • Atomic • Tốc độ"
70
+ favorites: Công cụ yêu thích
71
+ cats:
72
+ finance:
73
+ title: Tài chính
74
+ dev:
75
+ title: Lập trình
76
+ tools:
77
+ title: Tiện ích
78
+ sort:
79
+ default: Mặc định
80
+ az: Tên (A-Z)
81
+ za: Tên (Z-A)
82
+ recent: Vừa xem
83
+ popular: Phổ biến nhất
84
+ reset: Đặt lại
85
+ footer:
86
+ about_title: AZtomiq
87
+ about_desc: "Bộ khung A-Z hiện đại để xây dựng trang web tiện ích."
88
+ links_title: Liên kết
89
+ intro: Giới thiệu
90
+ policy: Chính sách
91
+ terms: Điều khoản
92
+ changelog: Cập nhật
93
+ copyright: "© 2025. Được xây dựng với ❤️."