-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathindex.html
More file actions
213 lines (203 loc) · 21 KB
/
index.html
File metadata and controls
213 lines (203 loc) · 21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Free Developer and Security Tools | Secutils.dev</title>
<meta name="description" content="Free, no-signup single-page tools for developers and security engineers. Decode JWTs, SAML, X.509 chains, mock HTTP responses, convert Markdown, extract PDF text. Browser-only.">
<meta name="robots" content="index, follow, max-image-preview:large">
<link rel="canonical" href="https://{{TOOLS_HOST}}/">
<meta name="su-tool-path" content="/">
<meta name="su-tool-name" content="Free Developer and Security Tools">
<meta name="su-tool-description" content="Index of free, no-signup single-page tools for developers and security engineers.">
<meta name="su-tool-promote" content="false">
<meta property="og:type" content="website">
<meta property="og:site_name" content="Secutils.dev">
<meta property="og:title" content="Free Developer & Security Tools — Secutils.dev">
<meta property="og:description" content="Free, no-signup single-page tools for developers and security engineers. Decode JWTs, SAML, X.509 chains, mock HTTP responses, convert Markdown, extract PDF text.">
<meta property="og:url" content="https://{{TOOLS_HOST}}/">
<meta property="og:image" content="https://secutils.dev/docs/img/og/og-index.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="Free developer and security tools by Secutils.dev.">
<meta property="og:locale" content="en_US">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Free Developer & Security Tools — Secutils.dev">
<meta name="twitter:description" content="Free, no-signup single-page tools for developers and security engineers.">
<meta name="twitter:image" content="https://secutils.dev/docs/img/og/og-index.png">
<script type="application/ld+json">{"@context":"https://schema.org","@type":"ItemList","name":"Secutils.dev Free Tools","url":"https://{{TOOLS_HOST}}/","itemListElement":[{"@type":"ListItem","position":1,"url":"https://{{TOOLS_HOST}}/jwt","name":"JWT Debugger"},{"@type":"ListItem","position":2,"url":"https://{{TOOLS_HOST}}/saml","name":"SAML Decoder"},{"@type":"ListItem","position":3,"url":"https://{{TOOLS_HOST}}/pem","name":"PEM Certificate Decoder"},{"@type":"ListItem","position":4,"url":"https://{{TOOLS_HOST}}/md-to-html","name":"Markdown to HTML"},{"@type":"ListItem","position":5,"url":"https://{{TOOLS_HOST}}/pdf","name":"PDF Extractor"},{"@type":"ListItem","position":6,"url":"https://{{TOOLS_HOST}}/echo","name":"HTTP Echo / Mock Response"}]}</script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300..700&family=Roboto+Mono:wght@400..700&display=swap" rel="stylesheet">
<!-- Privacy-friendly analytics by Plausible -->
<script defer src="https://tools.secutils.dev/js/script.js"></script>
<script>
window.plausible = window.plausible || function () { (plausible.q = plausible.q || []).push(arguments) };
plausible.init = plausible.init || function (i) { plausible.o = i || {} };
plausible.init();
</script>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root, [data-theme="dark"] {
--bg: #141519; --surface: #1d1e24; --surface-hover: #2c2d33;
--border: #343741; --text: #dfe5ef; --text-muted: #98a2b3;
--primary: #fed047; --primary-hover: #fdc615;
--primary-text: #642340;
--accent: #642340;
--badge-bg: #2B394F; --badge-text: #98A8C3;
--font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
--mono: 'Roboto Mono', 'SF Mono', 'Fira Code', Consolas, monospace;
}
[data-theme="light"] {
--bg: #f5f7fa; --surface: #ffffff; --surface-hover: #f1f3f5;
--border: #d3dae6; --text: #343741; --text-muted: #69707d;
--primary: #fed047; --primary-hover: #fdc615;
--primary-text: #642340;
--accent: #642340;
--badge-bg: #E3E8F2; --badge-text: #505F79;
}
body { font-family: var(--font); background: var(--bg); color: var(--text); min-height: 100vh; display: flex; flex-direction: column; transition: background .25s, color .25s; }
header { display: flex; align-items: center; justify-content: space-between; padding: 0 16px; height: 48px; background: var(--surface); border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 100; transition: background .25s, border-color .25s; }
.logo { display: flex; align-items: center; gap: 10px; text-decoration: none; }
.logo-svg { flex-shrink: 0; }
.logo-svg .logo-text-fill { fill: var(--text); }
.logo-badge { display: inline-flex; align-items: center; padding: 4px 16px; border-radius: 4px; border: none; background: var(--badge-bg); color: var(--badge-text); font-size: 12px; font-weight: 450; line-height: 16px; white-space: nowrap; }
.header-right { display: flex; align-items: center; gap: 8px; }
.theme-toggle { width: 36px; height: 36px; padding: 0; display: flex; align-items: center; justify-content: center; border-radius: 50%; border: 1px solid var(--border); background: var(--surface); color: var(--text-muted); cursor: pointer; transition: all .2s; }
.theme-toggle:hover { background: var(--surface-hover); color: var(--text); }
.theme-toggle svg { width: 16px; height: 16px; fill: currentColor; }
.theme-toggle .icon-sun { display: none; }
.theme-toggle .icon-moon { display: block; }
[data-theme="dark"] .theme-toggle .icon-sun { display: block; }
[data-theme="dark"] .theme-toggle .icon-moon { display: none; }
.su-noscript { max-width: 720px; margin: 24px auto; padding: 16px; border: 1px solid var(--border); border-radius: 8px; font: 14px/1.5 var(--font, system-ui), sans-serif; background: var(--surface); color: var(--text); }
main { flex: 1; padding: 48px 16px; max-width: 720px; margin: 0 auto; width: 100%; }
.page-title { font-size: 1.5rem; font-weight: 700; margin-bottom: 6px; }
.page-subtitle { color: var(--text-muted); font-size: 0.9rem; margin-bottom: 32px; }
.tool-list { display: flex; flex-direction: column; gap: 12px; }
.tool-card { display: block; text-decoration: none; color: inherit; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 20px 24px; transition: background .15s, border-color .15s, box-shadow .15s; }
.tool-card:hover { background: var(--surface-hover); border-color: var(--text-muted); box-shadow: 0 2px 12px rgba(0,0,0,0.12); }
.tool-name { font-size: 1rem; font-weight: 600; margin-bottom: 4px; display: flex; align-items: center; gap: 8px; }
.tool-name .arrow { color: var(--text-muted); transition: transform .15s, color .15s; font-size: 0.85rem; }
.tool-card:hover .tool-name .arrow { transform: translateX(3px); color: var(--primary); }
.tool-desc { color: var(--text-muted); font-size: 0.85rem; line-height: 1.5; }
.tool-path { font-family: var(--mono); font-size: 0.75rem; color: var(--badge-text); background: var(--badge-bg); padding: 2px 8px; border-radius: 3px; }
.su-footer { text-align: center; padding: 16px; border-top: 1px solid var(--border); color: var(--text-muted); font-size: 0.8rem; transition: border-color .25s, color .25s; }
.su-footer p { margin: 0; }
.su-footer-fineprint { margin-top: 6px !important; font-size: 0.7rem; opacity: 0.75; }
.su-footer-link { background: none; border: none; padding: 0; color: inherit; font: inherit; cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
.su-footer-link:hover { color: var(--text); }
.su-dialog { max-width: 520px; width: calc(100% - 32px); max-height: calc(100% - 32px); inset: 0; margin: auto; padding: 0; border: 1px solid var(--border); border-radius: 12px; background: var(--surface); color: var(--text); box-shadow: 0 20px 60px rgba(0,0,0,0.4); }
.su-dialog::backdrop { background: rgba(0,0,0,0.45); backdrop-filter: blur(2px); }
.su-dialog-header { display: flex; align-items: center; justify-content: space-between; padding: 14px 18px; border-bottom: 1px solid var(--border); }
.su-dialog-header h2 { font-size: 1rem; font-weight: 600; }
.su-dialog-close { width: 28px; height: 28px; padding: 0; display: flex; align-items: center; justify-content: center; border-radius: 50%; border: 1px solid var(--border); background: var(--surface); color: var(--text-muted); cursor: pointer; transition: all .15s; }
.su-dialog-close:hover { background: var(--surface-hover); color: var(--text); }
.su-dialog-body { padding: 16px 18px; font-size: 0.875rem; line-height: 1.55; color: var(--text); }
.su-dialog-body p { margin-bottom: 12px; }
.su-dialog-body p:last-child { margin-bottom: 0; }
.su-dialog-body code { font-family: var(--mono); background: var(--surface-hover); padding: 1px 5px; border-radius: 4px; font-size: 0.85em; }
.su-dialog-body a { color: var(--primary); text-decoration: none; }
.su-dialog-body a:hover { text-decoration: underline; }
.su-dialog-fineprint { font-size: 0.8rem; color: var(--text-muted); }
@media (max-width: 640px) {
header { padding: 0 12px; }
.logo-svg { height: 20px; }
.logo-badge { font-size: 11px; padding: 2px 7px; }
main { padding: 24px 12px; }
.tool-card { padding: 16px; }
}
</style>
</head>
<body>
<noscript>
<p class="su-noscript"><strong>Free developer and security tools</strong> — A collection of single-page utilities (JWT, SAML, X.509, Markdown to HTML, PDF Extractor, HTTP echo) by Secutils.dev. Open any tool in your browser, no signup. Requires JavaScript; please enable it. Source on <a href="https://github.com/secutils-dev/secutils/tree/main/dev/tools">GitHub</a>.</p>
</noscript>
<header>
<a class="logo" href="https://secutils.dev" target="_blank" rel="noopener">
<svg class="logo-svg" height="24" role="img" viewBox="0 0 98 16" xmlns="http://www.w3.org/2000/svg">
<path d="m3 0h10c1.662 0 3 1.338 3 3v10c0 1.662-1.338 3-3 3h-10c-1.662 0-3-1.338-3-3v-10c0-1.662 1.338-3 3-3z" fill="#fed047"/>
<path aria-label="SU" d="m11.285 12q-1.12 0-1.728-0.608-0.608-0.61867-0.608-1.6747v-5.6107h1.152v5.6q0 0.59733 0.29867 0.93867 0.29867 0.34133 0.88534 0.34133 0.58667 0 0.88534-0.34133 0.29867-0.34134 0.29867-0.93867v-5.6h1.152v5.6107q0 1.0667-0.608 1.6747t-1.728 0.608zm-6.368 0q-1.152 0-1.8453-0.608-0.69334-0.608-0.69334-1.664h1.1307q0 0.58667 0.384 0.928 0.384 0.33067 1.024 0.33067 0.62934 0 0.992-0.34133 0.36267-0.34134 0.36267-0.90667 0-0.42667-0.23467-0.74667t-0.672-0.43733l-1.12-0.29867q-0.78934-0.21333-1.248-0.77867-0.448-0.56534-0.448-1.3547 0-0.64 0.27733-1.1093 0.288-0.48 0.81067-0.74667t1.216-0.26667 1.216 0.26667q0.53334 0.26667 0.82134 0.74667 0.29867 0.46933 0.29867 1.0987h-1.1307q0-0.50133-0.34133-0.8-0.33067-0.30933-0.864-0.30933t-0.864 0.30933q-0.32 0.29867-0.32 0.78934 0 0.39467 0.21333 0.66134 0.224 0.26667 0.61867 0.37333l1.152 0.30933q0.81067 0.21333 1.28 0.832t0.46933 1.4613q0 0.69334-0.30933 1.2053-0.30933 0.50133-0.864 0.77867-0.55467 0.27733-1.312 0.27733z" fill="#642340"/>
<path class="logo-text-fill" aria-label="SECUTILS.DEV" d="m93.158 12.117-1.9733-7.7867h1.1733l1.2587 5.184q0.11733 0.46933 0.20267 0.91734 0.08533 0.448 0.128 0.69334 0.04267-0.24533 0.128-0.69334 0.096-0.45867 0.21333-0.928l1.2053-5.1733h1.184l-1.984 7.7867zm-7.8294 0v-7.7867h4.576v1.024h-3.4453v2.2187h3.072v0.992h-3.072v2.528h3.4453v1.024zm-6.5174 0v-7.7867h2.176q0.768 0 1.3333 0.29867 0.56534 0.288 0.87467 0.832 0.32 0.53334 0.32 1.248v3.008q0 0.736-0.32 1.2693-0.30933 0.53334-0.87467 0.832-0.56534 0.29867-1.3333 0.29867zm1.152-1.0347h1.024q0.62934 0 1.0027-0.36267 0.37333-0.36267 0.37333-1.0027v-3.008q0-0.61867-0.37333-0.98134-0.37334-0.37333-1.0027-0.37333h-1.024zm-5.2374 1.1413q-0.416 0-0.68267-0.24533-0.256-0.256-0.256-0.672 0-0.416 0.256-0.672 0.26667-0.26667 0.68267-0.26667 0.416 0 0.672 0.26667 0.26667 0.256 0.26667 0.672 0 0.416-0.26667 0.672-0.256 0.24533-0.672 0.24533zm-6.368 0q-1.152 0-1.8453-0.608-0.69334-0.608-0.69334-1.664h1.1307q0 0.58667 0.384 0.928 0.384 0.33067 1.024 0.33067 0.62934 0 0.992-0.34133 0.36267-0.34134 0.36267-0.90667 0-0.42667-0.23467-0.74667t-0.672-0.43733l-1.12-0.29867q-0.78934-0.21333-1.248-0.77867-0.448-0.56534-0.448-1.3547 0-0.64 0.27733-1.1093 0.288-0.48 0.81067-0.74667 0.52267-0.26667 1.216-0.26667 0.69334 0 1.216 0.26667 0.53334 0.26667 0.82134 0.74667 0.29867 0.46933 0.29867 1.0987h-1.1307q0-0.50134-0.34133-0.8-0.33067-0.30933-0.864-0.30933t-0.864 0.30933q-0.32 0.29867-0.32 0.78934 0 0.39467 0.21333 0.66134 0.224 0.26667 0.61867 0.37333l1.152 0.30933q0.81067 0.21333 1.28 0.832 0.46934 0.61867 0.46934 1.4613 0 0.69334-0.30934 1.2053-0.30933 0.50134-0.864 0.77867-0.55467 0.27733-1.312 0.27733zm-8.288-0.10667v-7.7867h1.152v6.7414h3.4027v1.0453zm-6.6987 0v-1.0453h1.568v-5.696h-1.568v-1.0453h4.32v1.0453h-1.5787v5.696h1.5787v1.0453zm-4.8214 0v-6.7414h-2.08v-1.0453h5.3227v1.0453h-2.0907v6.7414zm-5.824 0.10667q-1.12 0-1.728-0.608-0.608-0.61867-0.608-1.6747v-5.6107h1.152v5.6q0 0.59733 0.29867 0.93867 0.29867 0.34133 0.88534 0.34133 0.58667 0 0.88534-0.34133 0.29867-0.34134 0.29867-0.93867v-5.6h1.152v5.6107q0 1.0667-0.608 1.6747t-1.728 0.608zm-6.3147 0q-1.0987 0-1.7493-0.608-0.64-0.61867-0.64-1.664v-3.456q0-1.056 0.64-1.664 0.65067-0.608 1.7493-0.608 1.088 0 1.728 0.61867 0.65067 0.608 0.65067 1.6533h-1.152q0-0.608-0.33067-0.928-0.32-0.32-0.896-0.32-0.58667 0-0.91734 0.32-0.32 0.32-0.32 0.928v3.456q0 0.608 0.32 0.928 0.33067 0.32 0.91734 0.32 0.576 0 0.896-0.32 0.33067-0.32 0.33067-0.928h1.152q0 1.0453-0.65067 1.664-0.64 0.608-1.728 0.608zm-8.6827-0.10667v-7.7867h4.576v1.024h-3.4453v2.2187h3.072v0.992h-3.072v2.528h3.4453v1.024zm-4.1707 0.10667q-1.152 0-1.8453-0.608-0.69334-0.608-0.69334-1.664h1.1307q0 0.58667 0.384 0.928 0.384 0.33067 1.024 0.33067 0.62934 0 0.992-0.34133 0.36267-0.34134 0.36267-0.90667 0-0.42667-0.23467-0.74667-0.23467-0.32-0.672-0.43733l-1.12-0.29867q-0.78934-0.21333-1.248-0.77867-0.448-0.56534-0.448-1.3547 0-0.64 0.27733-1.1093 0.288-0.48 0.81067-0.74667 0.52267-0.26667 1.216-0.26667 0.69334 0 1.216 0.26667 0.53334 0.26667 0.82134 0.74667 0.29867 0.46933 0.29867 1.0987h-1.1307q0-0.50134-0.34134-0.8-0.33067-0.30933-0.864-0.30933t-0.864 0.30933q-0.32 0.29867-0.32 0.78934 0 0.39467 0.21333 0.66134 0.224 0.26667 0.61867 0.37333l1.152 0.30933q0.81067 0.21333 1.28 0.832 0.46934 0.61867 0.46934 1.4613 0 0.69334-0.30934 1.2053-0.30933 0.50134-0.864 0.77867-0.55467 0.27733-1.312 0.27733z"/>
</svg>
<span class="logo-badge">Tools</span>
</a>
<div class="header-right">
<button class="theme-toggle" id="themeToggle" aria-label="Toggle theme">
<svg class="icon-sun" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M8.5 15h-1v-2h1v2Zm-3.674-3.107-1.414 1.414-.707-.707 1.414-1.415.707.708Zm8.479.707-.707.707-1.414-1.414.707-.708 1.414 1.415Z"/><path fill-rule="evenodd" d="M8 4a4 4 0 1 1 0 8 4 4 0 0 1 0-8Zm0 1a3 3 0 1 0 0 6 3 3 0 0 0 0-6Z" clip-rule="evenodd"/><path d="M3.005 8.505h-2v-1h2v1Zm12 0h-2v-1h2v1ZM4.82 4.114l-.708.707-1.414-1.414.707-.707L4.82 4.114Zm8.492-.707-1.414 1.414-.708-.707L12.605 2.7l.707.707ZM8.5 3h-1V1h1v2Z"/></svg>
<svg class="icon-moon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M4.05 12.95A6.982 6.982 0 0 1 2 8c0-1.79.684-3.583 2.05-4.95A6.982 6.982 0 0 1 9 1a1 1 0 0 1 .708 1.707 4.982 4.982 0 0 0-1.465 3.536 4.98 4.98 0 0 0 1.465 3.535 4.98 4.98 0 0 0 3.535 1.465 1 1 0 0 1 .707 1.707A6.981 6.981 0 0 1 9 15a6.983 6.983 0 0 1-4.95-2.05Zm.708-.707A5.983 5.983 0 0 0 9 14c1.535 0 3.07-.586 4.242-1.757a5.98 5.98 0 0 1-4.018-1.545L9 10.485a5.982 5.982 0 0 1-1.758-4.242A5.986 5.986 0 0 1 9 2a5.983 5.983 0 0 0-4.243 1.757A5.98 5.98 0 0 0 3 8l.006.288a5.978 5.978 0 0 0 1.75 3.955Z"/></svg>
</button>
</div>
</header>
<main>
<h1 class="page-title">Developer Tools</h1>
<p class="page-subtitle">Single-page utilities for security and development workflows.</p>
<div class="tool-list">
<a class="tool-card" href="/jwt">
<div class="tool-name">JWT Debugger <span class="tool-path">/jwt</span> <span class="arrow">→</span></div>
<div class="tool-desc">Decode, verify, and generate JSON Web Tokens. Supports HMAC algorithms with real-time signature validation and shareable links.</div>
</a>
<a class="tool-card" href="/saml">
<div class="tool-name">SAML Decoder <span class="tool-path">/saml</span> <span class="arrow">→</span></div>
<div class="tool-desc">Decode Base64-encoded SAML responses, requests, and metadata. View formatted XML with syntax highlighting or browse attributes in a table.</div>
</a>
<a class="tool-card" href="/pem">
<div class="tool-name">Certificate Decoder <span class="tool-path">/pem</span> <span class="arrow">→</span></div>
<div class="tool-desc">Decode and inspect PEM-encoded X.509 certificate chains. Automatically sorts chain order and shows subject, issuer, SANs, validity, and fingerprints.</div>
</a>
<a class="tool-card" href="/md-to-html">
<div class="tool-name">Markdown → HTML <span class="tool-path">/md-to-html</span> <span class="arrow">→</span></div>
<div class="tool-desc">Convert Markdown files to beautifully formatted, self-contained HTML pages or print-ready PDFs with syntax highlighting, dark mode, and table of contents.</div>
</a>
<a class="tool-card" href="/pdf">
<div class="tool-name">PDF Extractor <span class="tool-path">/pdf</span> <span class="arrow">→</span></div>
<div class="tool-desc">Extract spatial text and structured JSON (with per-item bounding boxes) from PDFs entirely in your browser. Optional Tesseract.js OCR for scanned documents.</div>
</a>
<a class="tool-card" href="/echo">
<div class="tool-name">Echo <span class="tool-path">/echo</span> <span class="arrow">→</span></div>
<div class="tool-desc">Build a fully customizable HTTP response (status, headers, body) and serve it as a shareable URL.</div>
</a>
</div>
</main>
<footer class="su-footer">
<p>A collection of single-file developer tools by Secutils.dev.</p>
<p class="su-footer-fineprint"><button type="button" class="su-footer-link" id="privacyOpen">Privacy</button></p>
</footer>
<dialog id="privacyDialog" class="su-dialog" aria-labelledby="privacyDialogTitle">
<header class="su-dialog-header">
<h2 id="privacyDialogTitle">Privacy</h2>
<button type="button" class="su-dialog-close" id="privacyClose" aria-label="Close">
<svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3l10 10M13 3L3 13"/></svg>
</button>
</header>
<div class="su-dialog-body">
<p><strong>Your data stays in your browser.</strong> These tools run entirely client-side. Tokens, PEMs, SAML payloads, Markdown source, and mock-response bodies are never sent to the Secutils.dev server. State that needs to survive a reload (or be shared) lives in the URL fragment (<code>#…</code>), which browsers never transmit to the server.</p>
<p><strong>Anonymous usage analytics.</strong> We use <a href="https://plausible.io/" target="_blank" rel="noopener noreferrer">Plausible Analytics</a>, a privacy-first, GDPR-compliant tool, to collect aggregate usage data. No cookies, no personal data, no individual tracking. The data is limited to top pages, referral sources, visit duration, and device-class metadata (device type, OS, country, browser). Full details in the <a href="https://plausible.io/data-policy" target="_blank" rel="noopener noreferrer">Plausible Data Policy</a>.</p>
<p class="su-dialog-fineprint">See the full <a href="https://secutils.dev/privacy" target="_blank" rel="noopener noreferrer">Secutils.dev privacy policy</a> for details on the wider service.</p>
</div>
</dialog>
<script>
(function() {
var toggle = document.getElementById('themeToggle');
var root = document.documentElement;
function setTheme(t) {
root.setAttribute('data-theme', t);
try { localStorage.setItem('su-tool-theme', t); } catch(e) {}
}
toggle.addEventListener('click', function() {
setTheme(root.getAttribute('data-theme') === 'dark' ? 'light' : 'dark');
});
try {
var saved = localStorage.getItem('su-tool-theme');
if (saved) setTheme(saved);
else if (window.matchMedia('(prefers-color-scheme: light)').matches) setTheme('light');
} catch(e) {}
})();
(function () {
var dlg = document.getElementById('privacyDialog');
document.getElementById('privacyOpen').addEventListener('click', function () { dlg.showModal(); });
document.getElementById('privacyClose').addEventListener('click', function () { dlg.close(); });
})();
</script>
</body>
</html>