|
1 | 1 | <!DOCTYPE html> |
| 2 | +<!-- |
| 3 | + kheMessage — https://msg.khe.money |
| 4 | + FILE STRUCTURE: |
| 5 | + - Lines 1–10: DOCTYPE, meta, links, title |
| 6 | + - Lines 11–~800: <style> — Reset, themes, layout, components, responsive |
| 7 | + - Lines ~800–1800: <header>, <main>, <aside> — HTML structure |
| 8 | + - Lines ~1800–4400: <script> — Block model, compression, encryption, UI logic, init |
| 9 | +--> |
2 | 10 | <meta charset="utf-8"> |
3 | 11 | <meta name="viewport" content="width=device-width, initial-scale=1"> |
4 | 12 | <meta name="theme-color" content="#fafaf9" id="theme-color-meta"> |
|
181 | 189 | gap: 10px; |
182 | 190 | } |
183 | 191 |
|
184 | | - #brand .github-icon { |
185 | | - display: flex; |
186 | | - align-items: center; |
187 | | - justify-content: center; |
188 | | - width: 36px; |
189 | | - height: 36px; |
190 | | - padding: 0; |
191 | | - border-radius: 50%; |
192 | | - color: var(--text); |
193 | | - transition: color 0.15s ease, background 0.15s ease; |
194 | | - -webkit-tap-highlight-color: transparent; |
195 | | - touch-action: manipulation; |
| 192 | + /* Brand hover morph: kheMessage → msg.khe.money */ |
| 193 | + #brand .brand-link { |
| 194 | + display: inline-block; |
| 195 | + position: relative; |
| 196 | + min-width: 6.5em; |
196 | 197 | } |
197 | | - |
198 | | - #brand .github-icon:focus-visible { |
199 | | - outline: 2px solid var(--outline); |
200 | | - outline-offset: 2px; |
| 198 | + #brand .brand-link .brand-default, |
| 199 | + #brand .brand-link .brand-hover { |
| 200 | + display: inline-block; |
| 201 | + transition: opacity 0.25s ease, transform 0.25s ease; |
201 | 202 | } |
202 | | - |
203 | | - #brand .github-icon:hover { |
204 | | - color: var(--text-muted); |
| 203 | + #brand .brand-link .brand-hover { |
| 204 | + position: absolute; |
| 205 | + left: 0; |
| 206 | + top: 0; |
| 207 | + opacity: 0; |
| 208 | + transform: translateY(4px); |
| 209 | + } |
| 210 | + #brand .brand-link:hover .brand-default { |
| 211 | + opacity: 0; |
| 212 | + transform: translateY(-4px); |
| 213 | + } |
| 214 | + #brand .brand-link:hover .brand-hover { |
| 215 | + opacity: 1; |
| 216 | + transform: translateY(0); |
205 | 217 | } |
206 | | - |
207 | | - #brand .github-icon svg { width: 18px; height: 18px; } |
208 | 218 |
|
209 | 219 | #save-btn { |
210 | 220 | min-width: 64px; |
|
312 | 322 |
|
313 | 323 | #brand .nav-btn svg { width: 18px; height: 18px; } |
314 | 324 |
|
| 325 | + #lock-btn .lock-icon-open { display: block; } |
| 326 | + #lock-btn .lock-icon-closed { display: none; } |
| 327 | + #lock-btn.is-locked .lock-icon-open { display: none; } |
| 328 | + #lock-btn.is-locked .lock-icon-closed { display: block; } |
| 329 | + #lock-btn.is-locked { color: var(--outline); } |
| 330 | + #lock-btn.is-locked:hover { background: var(--btn-hover); color: var(--outline); } |
| 331 | + |
315 | 332 | #brand .nav-dropdown { |
316 | 333 | position: absolute; |
317 | 334 | top: 100%; |
|
642 | 659 | font-size: 1.1rem; |
643 | 660 | } |
644 | 661 |
|
645 | | - #theme-toggle { |
| 662 | + #theme-toggle, |
| 663 | + #lock-btn { |
646 | 664 | width: 32px; |
647 | 665 | height: 32px; |
648 | 666 | } |
649 | 667 |
|
650 | | - #theme-toggle svg { |
| 668 | + #theme-toggle svg, |
| 669 | + #lock-btn svg { |
651 | 670 | width: 16px; |
652 | 671 | height: 16px; |
653 | 672 | } |
|
1390 | 1409 | } |
1391 | 1410 |
|
1392 | 1411 | /* Status bar */ |
| 1412 | + #status-bar .status-bar-github { |
| 1413 | + display: flex; |
| 1414 | + align-items: center; |
| 1415 | + justify-content: center; |
| 1416 | + width: 28px; |
| 1417 | + height: 28px; |
| 1418 | + padding: 0; |
| 1419 | + border: 1px solid var(--btn-border); |
| 1420 | + border-radius: 50%; |
| 1421 | + background: var(--btn-bg); |
| 1422 | + color: var(--text); |
| 1423 | + transition: background 0.15s ease, border-color 0.15s ease, transform 0.1s ease; |
| 1424 | + -webkit-tap-highlight-color: transparent; |
| 1425 | + touch-action: manipulation; |
| 1426 | + } |
| 1427 | + #status-bar .status-bar-github:focus-visible { |
| 1428 | + outline: 2px solid var(--outline); |
| 1429 | + outline-offset: 2px; |
| 1430 | + } |
| 1431 | + #status-bar .status-bar-github:hover { |
| 1432 | + background: var(--btn-hover); |
| 1433 | + border-color: var(--border); |
| 1434 | + } |
| 1435 | + #status-bar .status-bar-github:active { |
| 1436 | + transform: scale(0.96); |
| 1437 | + } |
| 1438 | + #status-bar .status-bar-github svg { |
| 1439 | + width: 16px; |
| 1440 | + height: 16px; |
| 1441 | + } |
| 1442 | + |
1393 | 1443 | #status-bar { |
1394 | 1444 | position: fixed; |
1395 | 1445 | bottom: 0; |
|
1575 | 1625 | </style> |
1576 | 1626 | <header id="brand" class="noprint"> |
1577 | 1627 | <div class="brand-left"> |
1578 | | - <a href="https://khe.money">kheMessage</a> |
1579 | | - <a href="https://github.com/HKTITAN/kheMessage" target="_blank" rel="noopener" class="github-icon" aria-label="GitHub"> |
1580 | | - <svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M9 19c-4.3 1.4-4.3-2.5-6-3m12 5v-3.5c0-1 .1-1.4-.5-2c2.8-.3 5.5-1.4 5.5-6a4.6 4.6 0 0 0-1.3-3.2a4.2 4.2 0 0 0-.1-3.2s-1.1-.3-3.5 1.3a12.3 12.3 0 0 0-6.2 0c-2.4-1.6-3.5-1.3-3.5-1.3a4.2 4.2 0 0 0-.1 3.2a4.6 4.6 0 0 0-1.3 3.2c0 4.6 2.7 5.7 5.5 6c-.6.6-.6 1.2-.5 2v3.5"/></svg> |
1581 | | - </a> |
| 1628 | + <a href="https://khe.money" class="brand-link" aria-label="kheMessage — msg.khe.money" title="msg.khe.money"><span class="brand-default" aria-hidden="true">kheMessage</span><span class="brand-hover" aria-hidden="true">msg.khe.money</span></a> |
1582 | 1629 | </div> |
1583 | 1630 | <div class="nav-actions"> |
1584 | 1631 | <button type="button" id="save-btn" aria-label="Save" title="Save (Ctrl+S)"><span id="save-btn-text">Save</span></button> |
|
1615 | 1662 | <a href="#" id="share-export-txt" role="menuitem">Export TXT</a> |
1616 | 1663 | <a href="#" id="share-export-html" role="menuitem">Export HTML</a> |
1617 | 1664 | <a href="#" id="share-export-md" role="menuitem">Export MD</a> |
1618 | | - <button type="button" id="share-lock" class="share-dropdown-btn" role="menuitem">Lock with password</button> |
1619 | 1665 | </div> |
1620 | 1666 | </div> |
| 1667 | + <button type="button" id="lock-btn" class="nav-btn" aria-label="Lock note with password" title="Lock note with password"> |
| 1668 | + <svg class="lock-icon-open" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 11V7a4 4 0 1 1 8 0"/><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/></svg> |
| 1669 | + <svg class="lock-icon-closed" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg> |
| 1670 | + </button> |
1621 | 1671 | <button type="button" id="theme-toggle" class="nav-btn" aria-label="Toggle light/dark mode"> |
1622 | 1672 | <svg class="icon-sun" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"/></svg> |
1623 | 1673 | <svg class="icon-moon" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg> |
@@ -1776,6 +1826,9 @@ <h4 id="size-tooltip-title">Document is getting large</h4> |
1776 | 1826 |
|
1777 | 1827 | <!-- Status Bar --> |
1778 | 1828 | <div id="status-bar" class="noprint"> |
| 1829 | + <a href="https://github.com/HKTITAN/kheMessage" target="_blank" rel="noopener" class="github-icon status-bar-github" aria-label="GitHub"> |
| 1830 | + <svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M9 19c-4.3 1.4-4.3-2.5-6-3m12 5v-3.5c0-1 .1-1.4-.5-2c2.8-.3 5.5-1.4 5.5-6a4.6 4.6 0 0 0-1.3-3.2a4.2 4.2 0 0 0-.1-3.2s-1.1-.3-3.5 1.3a12.3 12.3 0 0 0-6.2 0c-2.4-1.6-3.5-1.3-3.5-1.3a4.2 4.2 0 0 0-.1 3.2a4.6 4.6 0 0 0-1.3 3.2c0 4.6 2.7 5.7 5.5 6c-.6.6-.6 1.2-.5 2v3.5"/></svg> |
| 1831 | + </a> |
1779 | 1832 | <div id="size-progress" title="URL size"> |
1780 | 1833 | <div id="size-progress-fill" class="safe"></div> |
1781 | 1834 | </div> |
@@ -3887,8 +3940,11 @@ <h4 id="size-tooltip-title">Document is getting large</h4> |
3887 | 3940 | } |
3888 | 3941 |
|
3889 | 3942 | function updateLockButtonVisibility() { |
3890 | | - const lockBtn = document.getElementById('share-lock') |
3891 | | - if (lockBtn) lockBtn.style.display = encryptedContent ? 'none' : '' |
| 3943 | + const lockBtn = document.getElementById('lock-btn') |
| 3944 | + if (!lockBtn) return |
| 3945 | + lockBtn.classList.toggle('is-locked', !!encryptedContent) |
| 3946 | + lockBtn.setAttribute('aria-label', encryptedContent ? 'Note is locked. Unlock via the banner above.' : 'Lock note with password') |
| 3947 | + lockBtn.title = encryptedContent ? 'Note is locked. Unlock via the banner above.' : 'Lock note with password' |
3892 | 3948 | } |
3893 | 3949 |
|
3894 | 3950 | function updateUnlockBannerText() { |
@@ -4161,8 +4217,7 @@ <h4 id="size-tooltip-title">Document is getting large</h4> |
4161 | 4217 | closeAllDropdowns() |
4162 | 4218 | }) |
4163 | 4219 |
|
4164 | | - const lockBtn = document.getElementById('share-lock') |
4165 | | - lockBtn?.addEventListener('click', e => { |
| 4220 | + document.getElementById('lock-btn')?.addEventListener('click', e => { |
4166 | 4221 | e.preventDefault() |
4167 | 4222 | if (encryptedContent) return |
4168 | 4223 | if (!window.crypto?.subtle) { |
|
0 commit comments