2 Commits
Author SHA1 Message Date
SecureBitChatVolodymyr c5b759e120 build: 6.7.0 bundles carrying the 1.0.0 download links
CodeQL Analysis / Analyze CodeQL (push) Canceled after 0s
Deploy Application / deploy (push) Canceled after 0s
Mirror to Codeberg / mirror (push) Canceled after 0s
Mirror to PrivacyGuides / mirror (push) Canceled after 0s
The deployed bundles are what the page loads; the source .jsx files are not
fetched at runtime. Rebuilding is what actually ships the change.
2026-09-01 23:50:07 -04:00
SecureBitChatVolodymyr b4e12c2a98 web: the desktop version lives in two files, and only one was bumped
src/app.jsx carries its own SB_DESKTOP_VERSION for the compact download
table; src/components/ui/DownloadApps.jsx carries DESKTOP_VERSION for the
grid. Bumping one leaves the other pointing at a tag whose filenames no
longer exist — the failure tests/desktop-download-links.test.mjs was written
for, and which it caught here.

The i18n scan also learns that these dictionaries feed two clients. The
desktop client is a separate repository, so its keys can never appear in a
scan of this src/ and were being reported as dead strings to delete.
2026-09-01 23:49:50 -04:00
21 changed files with 2325 additions and 353 deletions

No files matched your search

+24 -24
View File
@@ -30,7 +30,7 @@
<!-- PWA Manifest -->
<link rel="manifest" href="/ar/manifest.json">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- PWA Meta Tags -->
<meta name="mobile-web-app-capable" content="yes">
@@ -96,7 +96,7 @@
<link rel="apple-touch-startup-image" media="screen and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/8.3__iPad_Mini_portrait.png">
<!-- Apple Touch Icons -->
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788321006836">
<link rel="apple-touch-icon" sizes="57x57" href="/logo/icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/logo/icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/logo/icon-72x72.png">
@@ -105,7 +105,7 @@
<link rel="apple-touch-icon" sizes="120x120" href="/logo/icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/logo/icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/logo/icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788321006836">
<!-- Microsoft Tiles -->
<meta name="msapplication-TileColor" content="#ff6b35">
@@ -222,7 +222,7 @@
<!-- Render-blocking JS is deferred: classic deferred scripts and module scripts
both execute in document order after parsing, so React still runs before the
app modules below, but the parser / first paint is no longer blocked. -->
<script defer src="/config/ice-servers.js?v=1788239352576"></script>
<script defer src="/config/ice-servers.js?v=1788321006836"></script>
<script defer src="/libs/react/react.production.min.js"></script>
<script defer src="/libs/react-dom/react-dom.production.min.js"></script>
<!-- Prism syntax highlighting (vendored, offline). Tokenizes code as TEXT only —
@@ -230,8 +230,8 @@
Its CSS is loaded async via load-async-css.js (not paint-critical). -->
<script defer src="/libs/prism/prism.js"></script>
<!-- Critical, paint-defining CSS stays render-blocking (avoids FOUC / layout shift). -->
<link rel="stylesheet" href="/assets/tailwind.css?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="stylesheet" href="/assets/tailwind.css?v=1788321006836">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- Preload only the fonts needed for first paint. fa-solid covers the bulk of UI
icons; fa-regular/fa-brands are loaded on demand by their CSS (rarely on the
first screen). Inter latin 400/700 cover body text and headings/buttons. -->
@@ -239,38 +239,38 @@
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-400.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-700.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="/assets/fonts/inter/inter.css">
<link rel="stylesheet" href="/src/styles/main.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/components.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/main.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/components.css?v=1788321006836">
<!-- Loads after components.css on purpose: press feedback, material weight,
size-specific tracking and the reduced-motion / -transparency / -contrast
answers all need to settle arguments with the sheets above on source order. -->
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788321006836">
<!-- Last of the hand-written sheets: the mirroring rules must win over anything
above them, and they only ever apply under [dir="rtl"]. -->
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788321006836">
<!-- Non-critical CSS (FontAwesome ~102KB, Prism) loaded async — no longer blocks paint. -->
<script defer src="/src/scripts/load-async-css.js?v=1788239352576"></script>
<script defer src="/src/scripts/load-async-css.js?v=1788321006836"></script>
<noscript>
<link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
<link rel="stylesheet" href="/libs/prism/prism.css">
</noscript>
<script defer src="/src/scripts/fa-check.js?v=1788239352576"></script>
<script defer src="/src/scripts/fa-check.js?v=1788321006836"></script>
<!-- Update Manager - система принудительного обновления -->
<script defer src="/src/utils/updateManager.js?v=1788239352576"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788239352576"></script>
<script type="module" src="/dist/qr-local.js?v=1788239352576"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788239352576"></script>
<script defer src="/src/utils/updateManager.js?v=1788321006836"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788321006836"></script>
<script type="module" src="/dist/qr-local.js?v=1788321006836"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788321006836"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/dist/app-boot.js?v=1788239352576"></script>
<script type="module" src="/dist/app.js?v=1788239352576"></script>
<script type="module" src="/dist/app-boot.js?v=1788321006836"></script>
<script type="module" src="/dist/app.js?v=1788321006836"></script>
<script defer src="/src/scripts/pwa-register.js?v=1788239352576"></script>
<script src="/src/pwa/install-prompt.js?v=1788239352576" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788239352576" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788239352576"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788239352576">
<script defer src="/src/scripts/pwa-register.js?v=1788321006836"></script>
<script src="/src/pwa/install-prompt.js?v=1788321006836" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788321006836" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788321006836"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788321006836">
</body>
</html>
+24 -24
View File
@@ -30,7 +30,7 @@
<!-- PWA Manifest -->
<link rel="manifest" href="/de/manifest.json">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- PWA Meta Tags -->
<meta name="mobile-web-app-capable" content="yes">
@@ -96,7 +96,7 @@
<link rel="apple-touch-startup-image" media="screen and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/8.3__iPad_Mini_portrait.png">
<!-- Apple Touch Icons -->
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788321006836">
<link rel="apple-touch-icon" sizes="57x57" href="/logo/icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/logo/icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/logo/icon-72x72.png">
@@ -105,7 +105,7 @@
<link rel="apple-touch-icon" sizes="120x120" href="/logo/icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/logo/icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/logo/icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788321006836">
<!-- Microsoft Tiles -->
<meta name="msapplication-TileColor" content="#ff6b35">
@@ -222,7 +222,7 @@
<!-- Render-blocking JS is deferred: classic deferred scripts and module scripts
both execute in document order after parsing, so React still runs before the
app modules below, but the parser / first paint is no longer blocked. -->
<script defer src="/config/ice-servers.js?v=1788239352576"></script>
<script defer src="/config/ice-servers.js?v=1788321006836"></script>
<script defer src="/libs/react/react.production.min.js"></script>
<script defer src="/libs/react-dom/react-dom.production.min.js"></script>
<!-- Prism syntax highlighting (vendored, offline). Tokenizes code as TEXT only —
@@ -230,8 +230,8 @@
Its CSS is loaded async via load-async-css.js (not paint-critical). -->
<script defer src="/libs/prism/prism.js"></script>
<!-- Critical, paint-defining CSS stays render-blocking (avoids FOUC / layout shift). -->
<link rel="stylesheet" href="/assets/tailwind.css?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="stylesheet" href="/assets/tailwind.css?v=1788321006836">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- Preload only the fonts needed for first paint. fa-solid covers the bulk of UI
icons; fa-regular/fa-brands are loaded on demand by their CSS (rarely on the
first screen). Inter latin 400/700 cover body text and headings/buttons. -->
@@ -239,38 +239,38 @@
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-400.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-700.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="/assets/fonts/inter/inter.css">
<link rel="stylesheet" href="/src/styles/main.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/components.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/main.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/components.css?v=1788321006836">
<!-- Loads after components.css on purpose: press feedback, material weight,
size-specific tracking and the reduced-motion / -transparency / -contrast
answers all need to settle arguments with the sheets above on source order. -->
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788321006836">
<!-- Last of the hand-written sheets: the mirroring rules must win over anything
above them, and they only ever apply under [dir="rtl"]. -->
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788321006836">
<!-- Non-critical CSS (FontAwesome ~102KB, Prism) loaded async — no longer blocks paint. -->
<script defer src="/src/scripts/load-async-css.js?v=1788239352576"></script>
<script defer src="/src/scripts/load-async-css.js?v=1788321006836"></script>
<noscript>
<link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
<link rel="stylesheet" href="/libs/prism/prism.css">
</noscript>
<script defer src="/src/scripts/fa-check.js?v=1788239352576"></script>
<script defer src="/src/scripts/fa-check.js?v=1788321006836"></script>
<!-- Update Manager - система принудительного обновления -->
<script defer src="/src/utils/updateManager.js?v=1788239352576"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788239352576"></script>
<script type="module" src="/dist/qr-local.js?v=1788239352576"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788239352576"></script>
<script defer src="/src/utils/updateManager.js?v=1788321006836"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788321006836"></script>
<script type="module" src="/dist/qr-local.js?v=1788321006836"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788321006836"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/dist/app-boot.js?v=1788239352576"></script>
<script type="module" src="/dist/app.js?v=1788239352576"></script>
<script type="module" src="/dist/app-boot.js?v=1788321006836"></script>
<script type="module" src="/dist/app.js?v=1788321006836"></script>
<script defer src="/src/scripts/pwa-register.js?v=1788239352576"></script>
<script src="/src/pwa/install-prompt.js?v=1788239352576" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788239352576" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788239352576"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788239352576">
<script defer src="/src/scripts/pwa-register.js?v=1788321006836"></script>
<script src="/src/pwa/install-prompt.js?v=1788321006836" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788321006836" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788321006836"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788321006836">
</body>
</html>
+989 -14
View File
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -1,7 +1,7 @@
{
"version": 3,
"sources": ["../src/notifications/SecureNotificationManager.js", "../src/notifications/NotificationIntegration.js", "../node_modules/dompurify/src/utils.ts", "../node_modules/dompurify/src/tags.ts", "../node_modules/dompurify/src/attrs.ts", "../node_modules/dompurify/src/regexp.ts", "../node_modules/dompurify/src/purify.ts", "../src/crypto/EnhancedSecureCryptoUtils.js", "../src/i18n/generated.js", "../src/i18n/index.js", "../src/transfer/EnhancedSecureFileTransfer.js", "../src/network/webrtc/config.js", "../src/network/webrtc/sdp.js", "../src/network/webrtc/audio.js", "../src/network/webrtc/video.js", "../src/network/webrtc/adaptation/metrics.js", "../src/network/webrtc/adaptation/controller.js", "../src/crypto/DoubleRatchet.js", "../src/network/descriptor/sbq2.js", "../src/network/descriptor/keyexchange.js", "../src/network/EnhancedSecureWebRTCManager.js", "../src/scripts/app-boot.js", "../package.json", "../src/components/ui/LanguageSwitcher.jsx", "../src/components/ui/Header.jsx", "../src/components/ui/DownloadApps.jsx", "../src/components/ui/BecomePartner.jsx", "../src/components/ui/UniqueFeatureSlider.jsx", "../src/components/ui/Roadmap.jsx", "../src/components/ui/CommunityCTA.jsx", "../src/components/ui/FileTransfer.jsx", "../src/network/iceServers.js", "../src/components/ui/IceServerSettings.jsx", "../src/components/ui/CallUI.jsx"],
"sourcesContent": ["/**\n * Secure and Reliable Notification Manager for P2P WebRTC Chat\n * Follows best practices: OWASP, MDN, Chrome DevRel\n * \n * @version 1.0.0\n * @author SecureBit Team\n * @license MIT\n */\n\nclass SecureChatNotificationManager {\n constructor(config = {}) {\n // Safely read Notification permission (iOS Safari may not define Notification)\n this.permission = (typeof Notification !== 'undefined' && Notification && typeof Notification.permission === 'string')\n ? Notification.permission\n : 'denied';\n this.isTabActive = this.checkTabActive(); // Initialize with proper check\n this.unreadCount = 0;\n this.originalTitle = document.title;\n this.notificationQueue = [];\n this.maxQueueSize = config.maxQueueSize || 5;\n this.rateLimitMs = config.rateLimitMs || 2000; // Spam protection\n this.lastNotificationTime = 0;\n this.trustedOrigins = config.trustedOrigins || [];\n \n // Secure context flag\n this.isSecureContext = window.isSecureContext;\n \n // Cross-browser compatibility for Page Visibility API\n this.hidden = this.getHiddenProperty();\n this.visibilityChange = this.getVisibilityChangeEvent();\n \n this.initVisibilityTracking();\n this.initSecurityChecks();\n }\n\n /**\n * Initialize security checks and validation\n * @private\n */\n initSecurityChecks() {\n // Security checks are performed silently\n }\n\n /**\n * Get hidden property name for cross-browser compatibility\n * @returns {string} Hidden property name\n * @private\n */\n getHiddenProperty() {\n if (typeof document.hidden !== \"undefined\") {\n return \"hidden\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msHidden\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitHidden\";\n }\n return \"hidden\"; // fallback\n }\n\n /**\n * Get visibility change event name for cross-browser compatibility\n * @returns {string} Visibility change event name\n * @private\n */\n getVisibilityChangeEvent() {\n if (typeof document.hidden !== \"undefined\") {\n return \"visibilitychange\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msvisibilitychange\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitvisibilitychange\";\n }\n return \"visibilitychange\"; // fallback\n }\n\n /**\n * Check if tab is currently active using multiple methods\n * @returns {boolean} True if tab is active\n * @private\n */\n checkTabActive() {\n // Primary method: Page Visibility API\n if (this.hidden && typeof document[this.hidden] !== \"undefined\") {\n return !document[this.hidden];\n }\n \n // Fallback method: document.hasFocus()\n if (typeof document.hasFocus === \"function\") {\n return document.hasFocus();\n }\n \n // Ultimate fallback: assume active\n return true;\n }\n\n /**\n * Initialize page visibility tracking (Page Visibility API)\n * @private\n */\n initVisibilityTracking() {\n // Primary method: Page Visibility API with cross-browser support\n if (typeof document.addEventListener !== \"undefined\" && typeof document[this.hidden] !== \"undefined\") {\n document.addEventListener(this.visibilityChange, () => {\n this.isTabActive = this.checkTabActive();\n \n if (this.isTabActive) {\n this.resetUnreadCount();\n this.clearNotificationQueue();\n }\n });\n }\n\n // Fallback method: Window focus/blur events\n window.addEventListener('focus', () => {\n this.isTabActive = this.checkTabActive();\n if (this.isTabActive) {\n this.resetUnreadCount();\n }\n });\n\n window.addEventListener('blur', () => {\n this.isTabActive = this.checkTabActive();\n });\n\n // Page unload cleanup\n window.addEventListener('beforeunload', () => {\n this.clearNotificationQueue();\n });\n }\n\n /**\n * Request notification permission (BEST PRACTICE: Only call in response to user action)\n * Never call on page load!\n * @returns {Promise<boolean>} Permission granted status\n */\n async requestPermission() {\n // Secure context check\n if (!this.isSecureContext || !('Notification' in window)) {\n return false;\n }\n\n if (this.permission === 'granted') {\n return true;\n }\n\n if (this.permission === 'denied') {\n return false;\n }\n\n try {\n this.permission = await Notification.requestPermission();\n return this.permission === 'granted';\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Update page title with unread count\n * @private\n */\n updateTitle() {\n if (this.unreadCount > 0) {\n document.title = `(${this.unreadCount}) ${this.originalTitle}`;\n } else {\n document.title = this.originalTitle;\n }\n }\n\n /**\n Line truncated
"mappings": "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 truncated
"sourcesContent": ["/**\n * Secure and Reliable Notification Manager for P2P WebRTC Chat\n * Follows best practices: OWASP, MDN, Chrome DevRel\n * \n * @version 1.0.0\n * @author SecureBit Team\n * @license MIT\n */\n\nclass SecureChatNotificationManager {\n constructor(config = {}) {\n // Safely read Notification permission (iOS Safari may not define Notification)\n this.permission = (typeof Notification !== 'undefined' && Notification && typeof Notification.permission === 'string')\n ? Notification.permission\n : 'denied';\n this.isTabActive = this.checkTabActive(); // Initialize with proper check\n this.unreadCount = 0;\n this.originalTitle = document.title;\n this.notificationQueue = [];\n this.maxQueueSize = config.maxQueueSize || 5;\n this.rateLimitMs = config.rateLimitMs || 2000; // Spam protection\n this.lastNotificationTime = 0;\n this.trustedOrigins = config.trustedOrigins || [];\n \n // Secure context flag\n this.isSecureContext = window.isSecureContext;\n \n // Cross-browser compatibility for Page Visibility API\n this.hidden = this.getHiddenProperty();\n this.visibilityChange = this.getVisibilityChangeEvent();\n \n this.initVisibilityTracking();\n this.initSecurityChecks();\n }\n\n /**\n * Initialize security checks and validation\n * @private\n */\n initSecurityChecks() {\n // Security checks are performed silently\n }\n\n /**\n * Get hidden property name for cross-browser compatibility\n * @returns {string} Hidden property name\n * @private\n */\n getHiddenProperty() {\n if (typeof document.hidden !== \"undefined\") {\n return \"hidden\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msHidden\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitHidden\";\n }\n return \"hidden\"; // fallback\n }\n\n /**\n * Get visibility change event name for cross-browser compatibility\n * @returns {string} Visibility change event name\n * @private\n */\n getVisibilityChangeEvent() {\n if (typeof document.hidden !== \"undefined\") {\n return \"visibilitychange\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msvisibilitychange\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitvisibilitychange\";\n }\n return \"visibilitychange\"; // fallback\n }\n\n /**\n * Check if tab is currently active using multiple methods\n * @returns {boolean} True if tab is active\n * @private\n */\n checkTabActive() {\n // Primary method: Page Visibility API\n if (this.hidden && typeof document[this.hidden] !== \"undefined\") {\n return !document[this.hidden];\n }\n \n // Fallback method: document.hasFocus()\n if (typeof document.hasFocus === \"function\") {\n return document.hasFocus();\n }\n \n // Ultimate fallback: assume active\n return true;\n }\n\n /**\n * Initialize page visibility tracking (Page Visibility API)\n * @private\n */\n initVisibilityTracking() {\n // Primary method: Page Visibility API with cross-browser support\n if (typeof document.addEventListener !== \"undefined\" && typeof document[this.hidden] !== \"undefined\") {\n document.addEventListener(this.visibilityChange, () => {\n this.isTabActive = this.checkTabActive();\n \n if (this.isTabActive) {\n this.resetUnreadCount();\n this.clearNotificationQueue();\n }\n });\n }\n\n // Fallback method: Window focus/blur events\n window.addEventListener('focus', () => {\n this.isTabActive = this.checkTabActive();\n if (this.isTabActive) {\n this.resetUnreadCount();\n }\n });\n\n window.addEventListener('blur', () => {\n this.isTabActive = this.checkTabActive();\n });\n\n // Page unload cleanup\n window.addEventListener('beforeunload', () => {\n this.clearNotificationQueue();\n });\n }\n\n /**\n * Request notification permission (BEST PRACTICE: Only call in response to user action)\n * Never call on page load!\n * @returns {Promise<boolean>} Permission granted status\n */\n async requestPermission() {\n // Secure context check\n if (!this.isSecureContext || !('Notification' in window)) {\n return false;\n }\n\n if (this.permission === 'granted') {\n return true;\n }\n\n if (this.permission === 'denied') {\n return false;\n }\n\n try {\n this.permission = await Notification.requestPermission();\n return this.permission === 'granted';\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Update page title with unread count\n * @private\n */\n updateTitle() {\n if (this.unreadCount > 0) {\n document.title = `(${this.unreadCount}) ${this.originalTitle}`;\n } else {\n document.title = this.originalTitle;\n }\n }\n\n /**\n Line truncated
"mappings": "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 truncated
"names": ["text", "NotificationIntegration", "entries", "Object", "setPrototypeOf", "isFrozen", "getPrototypeOf", "getOwnPropertyDescriptor", "freeze", "seal", "create", "_ref", "Reflect", "apply", "construct", "x", "func", "thisArg", "_len", "arguments", "length", "args", "Array", "_key", "Func", "_len2", "_key2", "arrayForEach", "unapply", "prototype", "forEach", "arrayLastIndexOf", "lastIndexOf", "arrayPop", "pop", "arrayPush", "push", "arraySplice", "splice", "arrayIsArray", "isArray", "stringToLowerCase", "String", "toLowerCase", "stringToString", "toString", "stringMatch", "match", "stringReplace", "replace", "stringIndexOf", "indexOf", "stringTrim", "trim", "numberToString", "Number", "booleanToString", "Boolean", "bigintToString", "BigInt", "symbolToString", "Symbol", "objectHasOwnProperty", "hasOwnProperty", "objectToString", "regExpTest", "RegExp", "test", "typeErrorCreate", "unconstruct", "TypeError", "lastIndex", "_len3", "_key3", "_len4", "_key4", "addToSet", "set", "array", "transformCaseFunc", "l", "element", "lcElement", "cleanArray", "index", "isPropertyExist", "clone", "object", "newObject", "_ref2", "_ref3", "_slicedToArray", "property", "value", "constructor", "stringifyValue", "valueAsRecord", "valueToString", "lookupGetter", "stringified", "prop", "desc", "get", "fallbackValue", "isRegex", "_unused", "html", "svg", "svgFilters", "svgDisallowed", "mathMl", "mathMlDisallowed", "text", "xml", "MUSTACHE_EXPR", "ERB_EXPR", "TMPLIT_EXPR", "DATA_ATTR", "ARIA_ATTR", "IS_ALLOWED_URI", "IS_SCRIPT_OR_DATA", "ATTR_WHITESPACE", "DOCTYPE_NAME", "CUSTOM_ELEMENT", "ELEMENT_MARKUP_PROBE", "COMMENT_MARKUP_PROBE", "FALLBACK_TAG_CLOSE", "SELF_CLOSING_TAG", "NODE_TYPE", "attribute", "cdataSection", "entityReference", "entityNode", "processingInstruction", "comment", "document", "documentType", "documentFragment", "notation", "getGlobal", "window", "_createTrustedTypesPolicy", "trustedTypes", "purifyHostElement", "createPolicy", "suffix", "ATTR_NAME", "hasAttribute", "getAttribute", "policyName", "createHTML", "createScriptURL", "scriptUrl", "_", "console", "warn", "_createHooksMap", "afterSanitizeAttributes", "afterSanitizeElements", "afterSanitizeShadowDOM", "beforeSanitizeAttributes", "beforeSanitizeElements", "beforeSanitizeShadowDOM", "uponSanitizeAttribute", "uponSanitizeElement", "uponSanitizeShadowNode", "_resolveSetOption", "cfg", "key", "fallback", "options", "base", "transform", "createDOMPurify", "undefined", "DOMPurify", "root", "version", "VERSION", "removed", "nodeType", "Element", "isSupported", "originalDocument", "currentScript", "DocumentFragment", "HTMLTemplateElement", "Node", "NodeFilter", "_window$NamedNodeMap", "NamedNodeMap", "MozNamedAttrMap", "HTMLFormElement", "DOMParser", "ElementPrototype", "cloneNode", "remove", "getNextSibling", "getChildNodes", "getParentNode", "getShadowRoot", "getAttributes", "getNodeType", "getNodeName", "template", "createElement", "content", "ownerDocument", "trustedTypesPolicy", "emptyHTML", "defaultTrustedTypesPolicy", "defaultTrustedTypesPolicyResolved", "IN_TRUSTED_TYPES_POLICY", "_assertNotInTrustedTypesPolicy", "_createTrustedHTML", "_createTrustedScriptURL", "_getDefaultTrustedTypesPolicy", "_document", "implementation", "createNodeIterator", "createDocumentFragment", "getElementsByTagName", "importNode", "hooks", "createHTMLDocument", "EXPRESSIONS", "ALLOWED_TAGS", "DEFAULT_ALLOWED_TAGS", "TAGS", "ALLOWED_ATTR", "DEFAULT_ALLOWED_ATTR", "ATTRS", "CUSTOM_ELEMENT_HANDLING", "tagNameCheck", "writable", "configurable", "enumerable", "attributeNameCheck", "allowCustomizedBuiltInElements", "FORBID_TAGS", "FORBID_ATTR", "EXTRA_ELEMENT_HANDLING", "tagCheck", "attributeCheck", "ALLOW_ARIA_ATTR", "ALLOW_DATA_ATTR", "ALLOW_UNKNOWN_PROTOCOLS", "ALLOW_SELF_CLOSE_IN_ATTR", "SAFE_FOR_TEMPLATES", "SAFE_FOR_XML", "WHOLE_DOCUMENT", "SET_CONFIG", "FORCE_BODY", "RETURN_DOM", "RETURN_DOM_FRAGMENT", "RETURN_TRUSTED_TYPE", "SANITIZE_DOM", "SANITIZE_NAMED_PROPS", "SANITIZE_NAMED_PROPS_PREFIX", "KEEP_CONTENT", "IN_PLACE", "USE_PROFILES", "FORBID_CONTENTS", "DEFAULT_FORBID_CONTENTS", "DATA_URI_TAGS", "DEFAULT_DATA_URI_TAGS", "URI_SAFE_ATTRIBUTES", "DEFAULT_URI_SAFE_ATTRIBUTES", "MATHML_NAMESPACE", "SVG_NAMESPACE", "HTML_NAMESPACE", "NAMESPACE", "IS_EMPTY_INPUT", "ALLOWED_NAMESPACES", "DEFAULT_ALLOWED_NAMESPACES", "DEFAULT_MATHML_TEXT_INTEGRATION_POINTS", "MATHML_TEXT_INTEGRATION_POINTS", "DEFAULT_HTML_INTEGRATION_POINTS", "HTML_INTEGRATION_POINTS", "COMMON_SVG_AND_HTML_ELEMENTS", "PARSER_MEDIA_TYPE", "SUPPORTED_PARSER_MEDIA_TYPES", "DEFAULT_PARSER_MEDIA_TYPE", "CONFIG", "formElement", "isRegexOrFunction", "testValue", "Function", "_parseConfig", "ALLOWED_URI_REGEXP", "customElementHandling", "ADD_TAGS", "ADD_ATTR", "ADD_URI_SAFE_ATTR", "ADD_FORBID_CONTENTS", "table", "tbody", "TRUSTED_TYPES_POLICY", "previousTrustedTypesPolicy", "error", "ALL_SVG_TAGS", "ALL_MATHML_TAGS", "_checkSvgNamespace", "tagName", "parent", "parentTagName", "namespaceURI", "_checkMathMlNamespaceLine truncated
}
Vendored
+989 -14
View File
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -1,7 +1,7 @@
{
"version": 3,
"sources": ["../src/utils/debugWindowHooks.js", "../src/network/iceSettingsStore.js", "../src/i18n/generated.js", "../src/i18n/index.js", "../src/state/sessionsStore.js", "../src/group/groupCrypto.js", "../src/state/groupsStore.js", "../src/group/GroupSession.js", "../src/group/groupSender.js", "../src/ui/motion.js", "../src/components/ui/LanguageSuggestion.jsx", "../src/components/ui/GroupChat.jsx", "../src/group/groupCallMedia.js", "../src/components/ui/callLayout.js", "../src/components/ui/GroupCallUI.jsx", "../src/app.jsx"],
"sourcesContent": ["function isSecureBitDebugEnabled(targetWindow = globalThis.window) {\n return targetWindow?.SECUREBIT_DEBUG === true;\n}\n\nfunction installDebugWindowHooks({\n targetWindow = globalThis.window,\n webrtcManagerRef,\n onClearData,\n clearConsole = () => {\n if (typeof console.clear === 'function') {\n console.clear();\n }\n }\n}) {\n if (!isSecureBitDebugEnabled(targetWindow)) {\n return () => {};\n }\n\n targetWindow.forceCleanup = () => {\n onClearData();\n if (webrtcManagerRef.current) {\n webrtcManagerRef.current.disconnect();\n }\n };\n targetWindow.clearLogs = clearConsole;\n targetWindow.webrtcManagerRef = webrtcManagerRef;\n\n return () => {\n delete targetWindow.forceCleanup;\n delete targetWindow.clearLogs;\n delete targetWindow.webrtcManagerRef;\n };\n}\n\nexport { installDebugWindowHooks, isSecureBitDebugEnabled };\n", "// Persistent, at-rest-encrypted storage for the user's custom ICE (STUN/TURN)\n// configuration. Persistence is OPTIONAL: the UI only calls saveIceSettings when\n// the user explicitly opts in (\"Save on this device\"). Session-only use never\n// touches this store \u2014 the settings live in React state and vanish on reload.\n//\n// At-rest protection model:\n// - A non-extractable AES-GCM device key is generated once and kept in\n// IndexedDB. It can never be exported back into JS, so a copy of the\n// on-disk database is useless without executing code in this exact origin.\n// - The settings blob (which may contain TURN credentials) is encrypted with\n// that key before being written.\n// This protects against disk/profile inspection. It does NOT protect against a\n// live code-execution compromise of the page (consistent with the project's\n// stated threat model \u2014 see SECURITY.md). Credentials are never persisted in\n// plaintext, and the user can delete them at any time via clearIceSettings().\n\nconst DB_NAME = 'securebit-net';\nconst DB_VERSION = 1;\nconst STORE = 'kv';\nconst KEY_RECORD = 'ice-device-key';\nconst SETTINGS_RECORD = 'ice-settings';\nconst SETTINGS_VERSION = 1;\n\nfunction isSupported() {\n return typeof indexedDB !== 'undefined' &&\n typeof crypto !== 'undefined' &&\n !!crypto.subtle;\n}\n\nfunction openDb() {\n return new Promise((resolve, reject) => {\n let request;\n try {\n request = indexedDB.open(DB_NAME, DB_VERSION);\n } catch (error) {\n reject(error);\n return;\n }\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(STORE)) {\n db.createObjectStore(STORE);\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n}\n\nfunction idbGet(db, key) {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE, 'readonly');\n const req = tx.objectStore(STORE).get(key);\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n });\n}\n\nfunction idbPut(db, key, value) {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE, 'readwrite');\n tx.objectStore(STORE).put(value, key);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\nfunction idbDelete(db, key) {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE, 'readwrite');\n tx.objectStore(STORE).delete(key);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\nasync function getOrCreateDeviceKey(db) {\n const existing = await idbGet(db, KEY_RECORD);\n if (existing instanceof CryptoKey) {\n return existing;\n }\n const key = await crypto.subtle.generateKey(\n { name: 'AES-GCM', length: 256 },\n false, // non-extractable\n ['encrypt', 'decrypt']\n );\n await idbPut(db, KEY_RECORD, key);\n return key;\n}\n\n/**\n * Persist custom ICE settings, encrypted at rest.\n * @param {{ servers: Array, privacyMode: string }} settings\n */\nexport async function saveIceSettings(settings) {\n if (!isSupported()) throw new Error('Persistent storage is not available in this browser');\n\n const db = await openDb();\n const key = await getOrCreateDeviceKey(db);\n\n const payload = JSON.stringify({\n version: SETTINGS_VERSION,\n servers: Array.isArray(settings?.servers) ? settings.servers : [],\n privacyMode: settings?.privacyMode === 'relay-only' ? 'relay-only' : 'standard'\n });\n\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const ciphertext = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv },\n keLine truncated
"mappings": "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 truncated
"sourcesContent": ["function isSecureBitDebugEnabled(targetWindow = globalThis.window) {\n return targetWindow?.SECUREBIT_DEBUG === true;\n}\n\nfunction installDebugWindowHooks({\n targetWindow = globalThis.window,\n webrtcManagerRef,\n onClearData,\n clearConsole = () => {\n if (typeof console.clear === 'function') {\n console.clear();\n }\n }\n}) {\n if (!isSecureBitDebugEnabled(targetWindow)) {\n return () => {};\n }\n\n targetWindow.forceCleanup = () => {\n onClearData();\n if (webrtcManagerRef.current) {\n webrtcManagerRef.current.disconnect();\n }\n };\n targetWindow.clearLogs = clearConsole;\n targetWindow.webrtcManagerRef = webrtcManagerRef;\n\n return () => {\n delete targetWindow.forceCleanup;\n delete targetWindow.clearLogs;\n delete targetWindow.webrtcManagerRef;\n };\n}\n\nexport { installDebugWindowHooks, isSecureBitDebugEnabled };\n", "// Persistent, at-rest-encrypted storage for the user's custom ICE (STUN/TURN)\n// configuration. Persistence is OPTIONAL: the UI only calls saveIceSettings when\n// the user explicitly opts in (\"Save on this device\"). Session-only use never\n// touches this store \u2014 the settings live in React state and vanish on reload.\n//\n// At-rest protection model:\n// - A non-extractable AES-GCM device key is generated once and kept in\n// IndexedDB. It can never be exported back into JS, so a copy of the\n// on-disk database is useless without executing code in this exact origin.\n// - The settings blob (which may contain TURN credentials) is encrypted with\n// that key before being written.\n// This protects against disk/profile inspection. It does NOT protect against a\n// live code-execution compromise of the page (consistent with the project's\n// stated threat model \u2014 see SECURITY.md). Credentials are never persisted in\n// plaintext, and the user can delete them at any time via clearIceSettings().\n\nconst DB_NAME = 'securebit-net';\nconst DB_VERSION = 1;\nconst STORE = 'kv';\nconst KEY_RECORD = 'ice-device-key';\nconst SETTINGS_RECORD = 'ice-settings';\nconst SETTINGS_VERSION = 1;\n\nfunction isSupported() {\n return typeof indexedDB !== 'undefined' &&\n typeof crypto !== 'undefined' &&\n !!crypto.subtle;\n}\n\nfunction openDb() {\n return new Promise((resolve, reject) => {\n let request;\n try {\n request = indexedDB.open(DB_NAME, DB_VERSION);\n } catch (error) {\n reject(error);\n return;\n }\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(STORE)) {\n db.createObjectStore(STORE);\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n}\n\nfunction idbGet(db, key) {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE, 'readonly');\n const req = tx.objectStore(STORE).get(key);\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n });\n}\n\nfunction idbPut(db, key, value) {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE, 'readwrite');\n tx.objectStore(STORE).put(value, key);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\nfunction idbDelete(db, key) {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE, 'readwrite');\n tx.objectStore(STORE).delete(key);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\nasync function getOrCreateDeviceKey(db) {\n const existing = await idbGet(db, KEY_RECORD);\n if (existing instanceof CryptoKey) {\n return existing;\n }\n const key = await crypto.subtle.generateKey(\n { name: 'AES-GCM', length: 256 },\n false, // non-extractable\n ['encrypt', 'decrypt']\n );\n await idbPut(db, KEY_RECORD, key);\n return key;\n}\n\n/**\n * Persist custom ICE settings, encrypted at rest.\n * @param {{ servers: Array, privacyMode: string }} settings\n */\nexport async function saveIceSettings(settings) {\n if (!isSupported()) throw new Error('Persistent storage is not available in this browser');\n\n const db = await openDb();\n const key = await getOrCreateDeviceKey(db);\n\n const payload = JSON.stringify({\n version: SETTINGS_VERSION,\n servers: Array.isArray(settings?.servers) ? settings.servers : [],\n privacyMode: settings?.privacyMode === 'relay-only' ? 'relay-only' : 'standard'\n });\n\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const ciphertext = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv },\n keLine truncated
"mappings": "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 truncated
"names": ["label", "label", "label", "t", "t", "h", "ICON", "svg", "h", "label", "t", "o", "MONO", "svg", "setMessages", "addMessageWithAutoScroll", "updateMessageStatus", "patchMessageById", "patchMessageByFileId", "setConnectionStatus", "setKeyFingerprint", "setVerificationCode", "setIsVerified", "setLocalVerificationConfirmed", "setRemoteVerificationConfirmed", "setBothVerificationsConfirmed", "setShowVerification", "setShowOfferStep", "setShowAnswerStep", "setShowQRCode", "setQrCodeUrl", "setOfferData", "setAnswerData", "setOfferInput", "setAnswerInput", "setPendingIncomingFiles", "opts", "offerData", "payload", "UpdateCheckerWrapper"]
}
+24 -24
View File
@@ -30,7 +30,7 @@
<!-- PWA Manifest -->
<link rel="manifest" href="/es/manifest.json">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- PWA Meta Tags -->
<meta name="mobile-web-app-capable" content="yes">
@@ -96,7 +96,7 @@
<link rel="apple-touch-startup-image" media="screen and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/8.3__iPad_Mini_portrait.png">
<!-- Apple Touch Icons -->
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788321006836">
<link rel="apple-touch-icon" sizes="57x57" href="/logo/icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/logo/icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/logo/icon-72x72.png">
@@ -105,7 +105,7 @@
<link rel="apple-touch-icon" sizes="120x120" href="/logo/icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/logo/icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/logo/icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788321006836">
<!-- Microsoft Tiles -->
<meta name="msapplication-TileColor" content="#ff6b35">
@@ -222,7 +222,7 @@
<!-- Render-blocking JS is deferred: classic deferred scripts and module scripts
both execute in document order after parsing, so React still runs before the
app modules below, but the parser / first paint is no longer blocked. -->
<script defer src="/config/ice-servers.js?v=1788239352576"></script>
<script defer src="/config/ice-servers.js?v=1788321006836"></script>
<script defer src="/libs/react/react.production.min.js"></script>
<script defer src="/libs/react-dom/react-dom.production.min.js"></script>
<!-- Prism syntax highlighting (vendored, offline). Tokenizes code as TEXT only —
@@ -230,8 +230,8 @@
Its CSS is loaded async via load-async-css.js (not paint-critical). -->
<script defer src="/libs/prism/prism.js"></script>
<!-- Critical, paint-defining CSS stays render-blocking (avoids FOUC / layout shift). -->
<link rel="stylesheet" href="/assets/tailwind.css?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="stylesheet" href="/assets/tailwind.css?v=1788321006836">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- Preload only the fonts needed for first paint. fa-solid covers the bulk of UI
icons; fa-regular/fa-brands are loaded on demand by their CSS (rarely on the
first screen). Inter latin 400/700 cover body text and headings/buttons. -->
@@ -239,38 +239,38 @@
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-400.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-700.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="/assets/fonts/inter/inter.css">
<link rel="stylesheet" href="/src/styles/main.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/components.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/main.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/components.css?v=1788321006836">
<!-- Loads after components.css on purpose: press feedback, material weight,
size-specific tracking and the reduced-motion / -transparency / -contrast
answers all need to settle arguments with the sheets above on source order. -->
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788321006836">
<!-- Last of the hand-written sheets: the mirroring rules must win over anything
above them, and they only ever apply under [dir="rtl"]. -->
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788321006836">
<!-- Non-critical CSS (FontAwesome ~102KB, Prism) loaded async — no longer blocks paint. -->
<script defer src="/src/scripts/load-async-css.js?v=1788239352576"></script>
<script defer src="/src/scripts/load-async-css.js?v=1788321006836"></script>
<noscript>
<link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
<link rel="stylesheet" href="/libs/prism/prism.css">
</noscript>
<script defer src="/src/scripts/fa-check.js?v=1788239352576"></script>
<script defer src="/src/scripts/fa-check.js?v=1788321006836"></script>
<!-- Update Manager - система принудительного обновления -->
<script defer src="/src/utils/updateManager.js?v=1788239352576"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788239352576"></script>
<script type="module" src="/dist/qr-local.js?v=1788239352576"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788239352576"></script>
<script defer src="/src/utils/updateManager.js?v=1788321006836"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788321006836"></script>
<script type="module" src="/dist/qr-local.js?v=1788321006836"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788321006836"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/dist/app-boot.js?v=1788239352576"></script>
<script type="module" src="/dist/app.js?v=1788239352576"></script>
<script type="module" src="/dist/app-boot.js?v=1788321006836"></script>
<script type="module" src="/dist/app.js?v=1788321006836"></script>
<script defer src="/src/scripts/pwa-register.js?v=1788239352576"></script>
<script src="/src/pwa/install-prompt.js?v=1788239352576" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788239352576" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788239352576"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788239352576">
<script defer src="/src/scripts/pwa-register.js?v=1788321006836"></script>
<script src="/src/pwa/install-prompt.js?v=1788321006836" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788321006836" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788321006836"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788321006836">
</body>
</html>
+24 -24
View File
@@ -30,7 +30,7 @@
<!-- PWA Manifest -->
<link rel="manifest" href="/fa/manifest.json">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- PWA Meta Tags -->
<meta name="mobile-web-app-capable" content="yes">
@@ -96,7 +96,7 @@
<link rel="apple-touch-startup-image" media="screen and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/8.3__iPad_Mini_portrait.png">
<!-- Apple Touch Icons -->
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788321006836">
<link rel="apple-touch-icon" sizes="57x57" href="/logo/icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/logo/icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/logo/icon-72x72.png">
@@ -105,7 +105,7 @@
<link rel="apple-touch-icon" sizes="120x120" href="/logo/icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/logo/icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/logo/icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788321006836">
<!-- Microsoft Tiles -->
<meta name="msapplication-TileColor" content="#ff6b35">
@@ -222,7 +222,7 @@
<!-- Render-blocking JS is deferred: classic deferred scripts and module scripts
both execute in document order after parsing, so React still runs before the
app modules below, but the parser / first paint is no longer blocked. -->
<script defer src="/config/ice-servers.js?v=1788239352576"></script>
<script defer src="/config/ice-servers.js?v=1788321006836"></script>
<script defer src="/libs/react/react.production.min.js"></script>
<script defer src="/libs/react-dom/react-dom.production.min.js"></script>
<!-- Prism syntax highlighting (vendored, offline). Tokenizes code as TEXT only —
@@ -230,8 +230,8 @@
Its CSS is loaded async via load-async-css.js (not paint-critical). -->
<script defer src="/libs/prism/prism.js"></script>
<!-- Critical, paint-defining CSS stays render-blocking (avoids FOUC / layout shift). -->
<link rel="stylesheet" href="/assets/tailwind.css?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="stylesheet" href="/assets/tailwind.css?v=1788321006836">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- Preload only the fonts needed for first paint. fa-solid covers the bulk of UI
icons; fa-regular/fa-brands are loaded on demand by their CSS (rarely on the
first screen). Inter latin 400/700 cover body text and headings/buttons. -->
@@ -239,38 +239,38 @@
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-400.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-700.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="/assets/fonts/inter/inter.css">
<link rel="stylesheet" href="/src/styles/main.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/components.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/main.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/components.css?v=1788321006836">
<!-- Loads after components.css on purpose: press feedback, material weight,
size-specific tracking and the reduced-motion / -transparency / -contrast
answers all need to settle arguments with the sheets above on source order. -->
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788321006836">
<!-- Last of the hand-written sheets: the mirroring rules must win over anything
above them, and they only ever apply under [dir="rtl"]. -->
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788321006836">
<!-- Non-critical CSS (FontAwesome ~102KB, Prism) loaded async — no longer blocks paint. -->
<script defer src="/src/scripts/load-async-css.js?v=1788239352576"></script>
<script defer src="/src/scripts/load-async-css.js?v=1788321006836"></script>
<noscript>
<link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
<link rel="stylesheet" href="/libs/prism/prism.css">
</noscript>
<script defer src="/src/scripts/fa-check.js?v=1788239352576"></script>
<script defer src="/src/scripts/fa-check.js?v=1788321006836"></script>
<!-- Update Manager - система принудительного обновления -->
<script defer src="/src/utils/updateManager.js?v=1788239352576"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788239352576"></script>
<script type="module" src="/dist/qr-local.js?v=1788239352576"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788239352576"></script>
<script defer src="/src/utils/updateManager.js?v=1788321006836"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788321006836"></script>
<script type="module" src="/dist/qr-local.js?v=1788321006836"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788321006836"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/dist/app-boot.js?v=1788239352576"></script>
<script type="module" src="/dist/app.js?v=1788239352576"></script>
<script type="module" src="/dist/app-boot.js?v=1788321006836"></script>
<script type="module" src="/dist/app.js?v=1788321006836"></script>
<script defer src="/src/scripts/pwa-register.js?v=1788239352576"></script>
<script src="/src/pwa/install-prompt.js?v=1788239352576" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788239352576" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788239352576"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788239352576">
<script defer src="/src/scripts/pwa-register.js?v=1788321006836"></script>
<script src="/src/pwa/install-prompt.js?v=1788321006836" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788321006836" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788321006836"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788321006836">
</body>
</html>
+24 -24
View File
@@ -30,7 +30,7 @@
<!-- PWA Manifest -->
<link rel="manifest" href="/fr/manifest.json">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- PWA Meta Tags -->
<meta name="mobile-web-app-capable" content="yes">
@@ -96,7 +96,7 @@
<link rel="apple-touch-startup-image" media="screen and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/8.3__iPad_Mini_portrait.png">
<!-- Apple Touch Icons -->
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788321006836">
<link rel="apple-touch-icon" sizes="57x57" href="/logo/icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/logo/icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/logo/icon-72x72.png">
@@ -105,7 +105,7 @@
<link rel="apple-touch-icon" sizes="120x120" href="/logo/icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/logo/icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/logo/icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788321006836">
<!-- Microsoft Tiles -->
<meta name="msapplication-TileColor" content="#ff6b35">
@@ -222,7 +222,7 @@
<!-- Render-blocking JS is deferred: classic deferred scripts and module scripts
both execute in document order after parsing, so React still runs before the
app modules below, but the parser / first paint is no longer blocked. -->
<script defer src="/config/ice-servers.js?v=1788239352576"></script>
<script defer src="/config/ice-servers.js?v=1788321006836"></script>
<script defer src="/libs/react/react.production.min.js"></script>
<script defer src="/libs/react-dom/react-dom.production.min.js"></script>
<!-- Prism syntax highlighting (vendored, offline). Tokenizes code as TEXT only —
@@ -230,8 +230,8 @@
Its CSS is loaded async via load-async-css.js (not paint-critical). -->
<script defer src="/libs/prism/prism.js"></script>
<!-- Critical, paint-defining CSS stays render-blocking (avoids FOUC / layout shift). -->
<link rel="stylesheet" href="/assets/tailwind.css?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="stylesheet" href="/assets/tailwind.css?v=1788321006836">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- Preload only the fonts needed for first paint. fa-solid covers the bulk of UI
icons; fa-regular/fa-brands are loaded on demand by their CSS (rarely on the
first screen). Inter latin 400/700 cover body text and headings/buttons. -->
@@ -239,38 +239,38 @@
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-400.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-700.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="/assets/fonts/inter/inter.css">
<link rel="stylesheet" href="/src/styles/main.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/components.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/main.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/components.css?v=1788321006836">
<!-- Loads after components.css on purpose: press feedback, material weight,
size-specific tracking and the reduced-motion / -transparency / -contrast
answers all need to settle arguments with the sheets above on source order. -->
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788321006836">
<!-- Last of the hand-written sheets: the mirroring rules must win over anything
above them, and they only ever apply under [dir="rtl"]. -->
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788321006836">
<!-- Non-critical CSS (FontAwesome ~102KB, Prism) loaded async — no longer blocks paint. -->
<script defer src="/src/scripts/load-async-css.js?v=1788239352576"></script>
<script defer src="/src/scripts/load-async-css.js?v=1788321006836"></script>
<noscript>
<link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
<link rel="stylesheet" href="/libs/prism/prism.css">
</noscript>
<script defer src="/src/scripts/fa-check.js?v=1788239352576"></script>
<script defer src="/src/scripts/fa-check.js?v=1788321006836"></script>
<!-- Update Manager - система принудительного обновления -->
<script defer src="/src/utils/updateManager.js?v=1788239352576"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788239352576"></script>
<script type="module" src="/dist/qr-local.js?v=1788239352576"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788239352576"></script>
<script defer src="/src/utils/updateManager.js?v=1788321006836"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788321006836"></script>
<script type="module" src="/dist/qr-local.js?v=1788321006836"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788321006836"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/dist/app-boot.js?v=1788239352576"></script>
<script type="module" src="/dist/app.js?v=1788239352576"></script>
<script type="module" src="/dist/app-boot.js?v=1788321006836"></script>
<script type="module" src="/dist/app.js?v=1788321006836"></script>
<script defer src="/src/scripts/pwa-register.js?v=1788239352576"></script>
<script src="/src/pwa/install-prompt.js?v=1788239352576" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788239352576" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788239352576"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788239352576">
<script defer src="/src/scripts/pwa-register.js?v=1788321006836"></script>
<script src="/src/pwa/install-prompt.js?v=1788321006836" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788321006836" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788321006836"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788321006836">
</body>
</html>
+24 -24
View File
@@ -30,7 +30,7 @@
<!-- PWA Manifest -->
<link rel="manifest" href="/he/manifest.json">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- PWA Meta Tags -->
<meta name="mobile-web-app-capable" content="yes">
@@ -96,7 +96,7 @@
<link rel="apple-touch-startup-image" media="screen and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/8.3__iPad_Mini_portrait.png">
<!-- Apple Touch Icons -->
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788321006836">
<link rel="apple-touch-icon" sizes="57x57" href="/logo/icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/logo/icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/logo/icon-72x72.png">
@@ -105,7 +105,7 @@
<link rel="apple-touch-icon" sizes="120x120" href="/logo/icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/logo/icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/logo/icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788321006836">
<!-- Microsoft Tiles -->
<meta name="msapplication-TileColor" content="#ff6b35">
@@ -222,7 +222,7 @@
<!-- Render-blocking JS is deferred: classic deferred scripts and module scripts
both execute in document order after parsing, so React still runs before the
app modules below, but the parser / first paint is no longer blocked. -->
<script defer src="/config/ice-servers.js?v=1788239352576"></script>
<script defer src="/config/ice-servers.js?v=1788321006836"></script>
<script defer src="/libs/react/react.production.min.js"></script>
<script defer src="/libs/react-dom/react-dom.production.min.js"></script>
<!-- Prism syntax highlighting (vendored, offline). Tokenizes code as TEXT only —
@@ -230,8 +230,8 @@
Its CSS is loaded async via load-async-css.js (not paint-critical). -->
<script defer src="/libs/prism/prism.js"></script>
<!-- Critical, paint-defining CSS stays render-blocking (avoids FOUC / layout shift). -->
<link rel="stylesheet" href="/assets/tailwind.css?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="stylesheet" href="/assets/tailwind.css?v=1788321006836">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- Preload only the fonts needed for first paint. fa-solid covers the bulk of UI
icons; fa-regular/fa-brands are loaded on demand by their CSS (rarely on the
first screen). Inter latin 400/700 cover body text and headings/buttons. -->
@@ -239,38 +239,38 @@
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-400.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-700.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="/assets/fonts/inter/inter.css">
<link rel="stylesheet" href="/src/styles/main.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/components.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/main.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/components.css?v=1788321006836">
<!-- Loads after components.css on purpose: press feedback, material weight,
size-specific tracking and the reduced-motion / -transparency / -contrast
answers all need to settle arguments with the sheets above on source order. -->
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788321006836">
<!-- Last of the hand-written sheets: the mirroring rules must win over anything
above them, and they only ever apply under [dir="rtl"]. -->
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788321006836">
<!-- Non-critical CSS (FontAwesome ~102KB, Prism) loaded async — no longer blocks paint. -->
<script defer src="/src/scripts/load-async-css.js?v=1788239352576"></script>
<script defer src="/src/scripts/load-async-css.js?v=1788321006836"></script>
<noscript>
<link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
<link rel="stylesheet" href="/libs/prism/prism.css">
</noscript>
<script defer src="/src/scripts/fa-check.js?v=1788239352576"></script>
<script defer src="/src/scripts/fa-check.js?v=1788321006836"></script>
<!-- Update Manager - система принудительного обновления -->
<script defer src="/src/utils/updateManager.js?v=1788239352576"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788239352576"></script>
<script type="module" src="/dist/qr-local.js?v=1788239352576"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788239352576"></script>
<script defer src="/src/utils/updateManager.js?v=1788321006836"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788321006836"></script>
<script type="module" src="/dist/qr-local.js?v=1788321006836"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788321006836"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/dist/app-boot.js?v=1788239352576"></script>
<script type="module" src="/dist/app.js?v=1788239352576"></script>
<script type="module" src="/dist/app-boot.js?v=1788321006836"></script>
<script type="module" src="/dist/app.js?v=1788321006836"></script>
<script defer src="/src/scripts/pwa-register.js?v=1788239352576"></script>
<script src="/src/pwa/install-prompt.js?v=1788239352576" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788239352576" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788239352576"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788239352576">
<script defer src="/src/scripts/pwa-register.js?v=1788321006836"></script>
<script src="/src/pwa/install-prompt.js?v=1788321006836" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788321006836" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788321006836"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788321006836">
</body>
</html>
+24 -24
View File
@@ -30,7 +30,7 @@
<!-- PWA Manifest -->
<link rel="manifest" href="/hi/manifest.json">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- PWA Meta Tags -->
<meta name="mobile-web-app-capable" content="yes">
@@ -96,7 +96,7 @@
<link rel="apple-touch-startup-image" media="screen and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/8.3__iPad_Mini_portrait.png">
<!-- Apple Touch Icons -->
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788321006836">
<link rel="apple-touch-icon" sizes="57x57" href="/logo/icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/logo/icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/logo/icon-72x72.png">
@@ -105,7 +105,7 @@
<link rel="apple-touch-icon" sizes="120x120" href="/logo/icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/logo/icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/logo/icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788321006836">
<!-- Microsoft Tiles -->
<meta name="msapplication-TileColor" content="#ff6b35">
@@ -222,7 +222,7 @@
<!-- Render-blocking JS is deferred: classic deferred scripts and module scripts
both execute in document order after parsing, so React still runs before the
app modules below, but the parser / first paint is no longer blocked. -->
<script defer src="/config/ice-servers.js?v=1788239352576"></script>
<script defer src="/config/ice-servers.js?v=1788321006836"></script>
<script defer src="/libs/react/react.production.min.js"></script>
<script defer src="/libs/react-dom/react-dom.production.min.js"></script>
<!-- Prism syntax highlighting (vendored, offline). Tokenizes code as TEXT only —
@@ -230,8 +230,8 @@
Its CSS is loaded async via load-async-css.js (not paint-critical). -->
<script defer src="/libs/prism/prism.js"></script>
<!-- Critical, paint-defining CSS stays render-blocking (avoids FOUC / layout shift). -->
<link rel="stylesheet" href="/assets/tailwind.css?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="stylesheet" href="/assets/tailwind.css?v=1788321006836">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- Preload only the fonts needed for first paint. fa-solid covers the bulk of UI
icons; fa-regular/fa-brands are loaded on demand by their CSS (rarely on the
first screen). Inter latin 400/700 cover body text and headings/buttons. -->
@@ -239,38 +239,38 @@
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-400.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-700.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="/assets/fonts/inter/inter.css">
<link rel="stylesheet" href="/src/styles/main.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/components.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/main.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/components.css?v=1788321006836">
<!-- Loads after components.css on purpose: press feedback, material weight,
size-specific tracking and the reduced-motion / -transparency / -contrast
answers all need to settle arguments with the sheets above on source order. -->
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788321006836">
<!-- Last of the hand-written sheets: the mirroring rules must win over anything
above them, and they only ever apply under [dir="rtl"]. -->
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788321006836">
<!-- Non-critical CSS (FontAwesome ~102KB, Prism) loaded async — no longer blocks paint. -->
<script defer src="/src/scripts/load-async-css.js?v=1788239352576"></script>
<script defer src="/src/scripts/load-async-css.js?v=1788321006836"></script>
<noscript>
<link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
<link rel="stylesheet" href="/libs/prism/prism.css">
</noscript>
<script defer src="/src/scripts/fa-check.js?v=1788239352576"></script>
<script defer src="/src/scripts/fa-check.js?v=1788321006836"></script>
<!-- Update Manager - система принудительного обновления -->
<script defer src="/src/utils/updateManager.js?v=1788239352576"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788239352576"></script>
<script type="module" src="/dist/qr-local.js?v=1788239352576"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788239352576"></script>
<script defer src="/src/utils/updateManager.js?v=1788321006836"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788321006836"></script>
<script type="module" src="/dist/qr-local.js?v=1788321006836"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788321006836"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/dist/app-boot.js?v=1788239352576"></script>
<script type="module" src="/dist/app.js?v=1788239352576"></script>
<script type="module" src="/dist/app-boot.js?v=1788321006836"></script>
<script type="module" src="/dist/app.js?v=1788321006836"></script>
<script defer src="/src/scripts/pwa-register.js?v=1788239352576"></script>
<script src="/src/pwa/install-prompt.js?v=1788239352576" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788239352576" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788239352576"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788239352576">
<script defer src="/src/scripts/pwa-register.js?v=1788321006836"></script>
<script src="/src/pwa/install-prompt.js?v=1788321006836" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788321006836" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788321006836"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788321006836">
</body>
</html>
+24 -24
View File
@@ -30,7 +30,7 @@
<!-- PWA Manifest -->
<link rel="manifest" href="/manifest.json">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- PWA Meta Tags -->
<meta name="mobile-web-app-capable" content="yes">
@@ -96,7 +96,7 @@
<link rel="apple-touch-startup-image" media="screen and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/8.3__iPad_Mini_portrait.png">
<!-- Apple Touch Icons -->
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788321006836">
<link rel="apple-touch-icon" sizes="57x57" href="/logo/icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/logo/icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/logo/icon-72x72.png">
@@ -105,7 +105,7 @@
<link rel="apple-touch-icon" sizes="120x120" href="/logo/icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/logo/icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/logo/icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788321006836">
<!-- Microsoft Tiles -->
<meta name="msapplication-TileColor" content="#ff6b35">
@@ -222,7 +222,7 @@
<!-- Render-blocking JS is deferred: classic deferred scripts and module scripts
both execute in document order after parsing, so React still runs before the
app modules below, but the parser / first paint is no longer blocked. -->
<script defer src="/config/ice-servers.js?v=1788239352576"></script>
<script defer src="/config/ice-servers.js?v=1788321006836"></script>
<script defer src="/libs/react/react.production.min.js"></script>
<script defer src="/libs/react-dom/react-dom.production.min.js"></script>
<!-- Prism syntax highlighting (vendored, offline). Tokenizes code as TEXT only —
@@ -230,8 +230,8 @@
Its CSS is loaded async via load-async-css.js (not paint-critical). -->
<script defer src="/libs/prism/prism.js"></script>
<!-- Critical, paint-defining CSS stays render-blocking (avoids FOUC / layout shift). -->
<link rel="stylesheet" href="/assets/tailwind.css?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="stylesheet" href="/assets/tailwind.css?v=1788321006836">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- Preload only the fonts needed for first paint. fa-solid covers the bulk of UI
icons; fa-regular/fa-brands are loaded on demand by their CSS (rarely on the
first screen). Inter latin 400/700 cover body text and headings/buttons. -->
@@ -239,38 +239,38 @@
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-400.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-700.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="/assets/fonts/inter/inter.css">
<link rel="stylesheet" href="/src/styles/main.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/components.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/main.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/components.css?v=1788321006836">
<!-- Loads after components.css on purpose: press feedback, material weight,
size-specific tracking and the reduced-motion / -transparency / -contrast
answers all need to settle arguments with the sheets above on source order. -->
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788321006836">
<!-- Last of the hand-written sheets: the mirroring rules must win over anything
above them, and they only ever apply under [dir="rtl"]. -->
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788321006836">
<!-- Non-critical CSS (FontAwesome ~102KB, Prism) loaded async — no longer blocks paint. -->
<script defer src="/src/scripts/load-async-css.js?v=1788239352576"></script>
<script defer src="/src/scripts/load-async-css.js?v=1788321006836"></script>
<noscript>
<link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
<link rel="stylesheet" href="/libs/prism/prism.css">
</noscript>
<script defer src="/src/scripts/fa-check.js?v=1788239352576"></script>
<script defer src="/src/scripts/fa-check.js?v=1788321006836"></script>
<!-- Update Manager - система принудительного обновления -->
<script defer src="/src/utils/updateManager.js?v=1788239352576"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788239352576"></script>
<script type="module" src="/dist/qr-local.js?v=1788239352576"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788239352576"></script>
<script defer src="/src/utils/updateManager.js?v=1788321006836"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788321006836"></script>
<script type="module" src="/dist/qr-local.js?v=1788321006836"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788321006836"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/dist/app-boot.js?v=1788239352576"></script>
<script type="module" src="/dist/app.js?v=1788239352576"></script>
<script type="module" src="/dist/app-boot.js?v=1788321006836"></script>
<script type="module" src="/dist/app.js?v=1788321006836"></script>
<script defer src="/src/scripts/pwa-register.js?v=1788239352576"></script>
<script src="/src/pwa/install-prompt.js?v=1788239352576" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788239352576" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788239352576"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788239352576">
<script defer src="/src/scripts/pwa-register.js?v=1788321006836"></script>
<script src="/src/pwa/install-prompt.js?v=1788321006836" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788321006836" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788321006836"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788321006836">
</body>
</html>
+24 -24
View File
@@ -30,7 +30,7 @@
<!-- PWA Manifest -->
<link rel="manifest" href="/ko/manifest.json">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- PWA Meta Tags -->
<meta name="mobile-web-app-capable" content="yes">
@@ -96,7 +96,7 @@
<link rel="apple-touch-startup-image" media="screen and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/8.3__iPad_Mini_portrait.png">
<!-- Apple Touch Icons -->
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788321006836">
<link rel="apple-touch-icon" sizes="57x57" href="/logo/icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/logo/icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/logo/icon-72x72.png">
@@ -105,7 +105,7 @@
<link rel="apple-touch-icon" sizes="120x120" href="/logo/icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/logo/icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/logo/icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788321006836">
<!-- Microsoft Tiles -->
<meta name="msapplication-TileColor" content="#ff6b35">
@@ -222,7 +222,7 @@
<!-- Render-blocking JS is deferred: classic deferred scripts and module scripts
both execute in document order after parsing, so React still runs before the
app modules below, but the parser / first paint is no longer blocked. -->
<script defer src="/config/ice-servers.js?v=1788239352576"></script>
<script defer src="/config/ice-servers.js?v=1788321006836"></script>
<script defer src="/libs/react/react.production.min.js"></script>
<script defer src="/libs/react-dom/react-dom.production.min.js"></script>
<!-- Prism syntax highlighting (vendored, offline). Tokenizes code as TEXT only —
@@ -230,8 +230,8 @@
Its CSS is loaded async via load-async-css.js (not paint-critical). -->
<script defer src="/libs/prism/prism.js"></script>
<!-- Critical, paint-defining CSS stays render-blocking (avoids FOUC / layout shift). -->
<link rel="stylesheet" href="/assets/tailwind.css?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="stylesheet" href="/assets/tailwind.css?v=1788321006836">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- Preload only the fonts needed for first paint. fa-solid covers the bulk of UI
icons; fa-regular/fa-brands are loaded on demand by their CSS (rarely on the
first screen). Inter latin 400/700 cover body text and headings/buttons. -->
@@ -239,38 +239,38 @@
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-400.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-700.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="/assets/fonts/inter/inter.css">
<link rel="stylesheet" href="/src/styles/main.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/components.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/main.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/components.css?v=1788321006836">
<!-- Loads after components.css on purpose: press feedback, material weight,
size-specific tracking and the reduced-motion / -transparency / -contrast
answers all need to settle arguments with the sheets above on source order. -->
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788321006836">
<!-- Last of the hand-written sheets: the mirroring rules must win over anything
above them, and they only ever apply under [dir="rtl"]. -->
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788321006836">
<!-- Non-critical CSS (FontAwesome ~102KB, Prism) loaded async — no longer blocks paint. -->
<script defer src="/src/scripts/load-async-css.js?v=1788239352576"></script>
<script defer src="/src/scripts/load-async-css.js?v=1788321006836"></script>
<noscript>
<link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
<link rel="stylesheet" href="/libs/prism/prism.css">
</noscript>
<script defer src="/src/scripts/fa-check.js?v=1788239352576"></script>
<script defer src="/src/scripts/fa-check.js?v=1788321006836"></script>
<!-- Update Manager - система принудительного обновления -->
<script defer src="/src/utils/updateManager.js?v=1788239352576"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788239352576"></script>
<script type="module" src="/dist/qr-local.js?v=1788239352576"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788239352576"></script>
<script defer src="/src/utils/updateManager.js?v=1788321006836"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788321006836"></script>
<script type="module" src="/dist/qr-local.js?v=1788321006836"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788321006836"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/dist/app-boot.js?v=1788239352576"></script>
<script type="module" src="/dist/app.js?v=1788239352576"></script>
<script type="module" src="/dist/app-boot.js?v=1788321006836"></script>
<script type="module" src="/dist/app.js?v=1788321006836"></script>
<script defer src="/src/scripts/pwa-register.js?v=1788239352576"></script>
<script src="/src/pwa/install-prompt.js?v=1788239352576" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788239352576" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788239352576"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788239352576">
<script defer src="/src/scripts/pwa-register.js?v=1788321006836"></script>
<script src="/src/pwa/install-prompt.js?v=1788321006836" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788321006836" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788321006836"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788321006836">
</body>
</html>
+6 -6
View File
@@ -1,10 +1,10 @@
{
"version": "1788239352576",
"buildVersion": "1788239352576",
"version": "1788321006836",
"buildVersion": "1788321006836",
"appVersion": "6.7.0",
"buildTime": "2026-09-01T05:09:12.623Z",
"buildId": "1788239352576-113bb10",
"gitHash": "113bb10",
"buildTime": "2026-09-02T03:50:06.875Z",
"buildId": "1788321006836-b4e12c2",
"gitHash": "b4e12c2",
"generated": true,
"generatedAt": "2026-09-01T05:09:12.625Z"
"generatedAt": "2026-09-02T03:50:06.877Z"
}
+24 -24
View File
@@ -30,7 +30,7 @@
<!-- PWA Manifest -->
<link rel="manifest" href="/ru/manifest.json">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- PWA Meta Tags -->
<meta name="mobile-web-app-capable" content="yes">
@@ -96,7 +96,7 @@
<link rel="apple-touch-startup-image" media="screen and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/8.3__iPad_Mini_portrait.png">
<!-- Apple Touch Icons -->
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788321006836">
<link rel="apple-touch-icon" sizes="57x57" href="/logo/icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/logo/icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/logo/icon-72x72.png">
@@ -105,7 +105,7 @@
<link rel="apple-touch-icon" sizes="120x120" href="/logo/icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/logo/icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/logo/icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788321006836">
<!-- Microsoft Tiles -->
<meta name="msapplication-TileColor" content="#ff6b35">
@@ -222,7 +222,7 @@
<!-- Render-blocking JS is deferred: classic deferred scripts and module scripts
both execute in document order after parsing, so React still runs before the
app modules below, but the parser / first paint is no longer blocked. -->
<script defer src="/config/ice-servers.js?v=1788239352576"></script>
<script defer src="/config/ice-servers.js?v=1788321006836"></script>
<script defer src="/libs/react/react.production.min.js"></script>
<script defer src="/libs/react-dom/react-dom.production.min.js"></script>
<!-- Prism syntax highlighting (vendored, offline). Tokenizes code as TEXT only —
@@ -230,8 +230,8 @@
Its CSS is loaded async via load-async-css.js (not paint-critical). -->
<script defer src="/libs/prism/prism.js"></script>
<!-- Critical, paint-defining CSS stays render-blocking (avoids FOUC / layout shift). -->
<link rel="stylesheet" href="/assets/tailwind.css?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="stylesheet" href="/assets/tailwind.css?v=1788321006836">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- Preload only the fonts needed for first paint. fa-solid covers the bulk of UI
icons; fa-regular/fa-brands are loaded on demand by their CSS (rarely on the
first screen). Inter latin 400/700 cover body text and headings/buttons. -->
@@ -239,38 +239,38 @@
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-400.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-700.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="/assets/fonts/inter/inter.css">
<link rel="stylesheet" href="/src/styles/main.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/components.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/main.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/components.css?v=1788321006836">
<!-- Loads after components.css on purpose: press feedback, material weight,
size-specific tracking and the reduced-motion / -transparency / -contrast
answers all need to settle arguments with the sheets above on source order. -->
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788321006836">
<!-- Last of the hand-written sheets: the mirroring rules must win over anything
above them, and they only ever apply under [dir="rtl"]. -->
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788321006836">
<!-- Non-critical CSS (FontAwesome ~102KB, Prism) loaded async — no longer blocks paint. -->
<script defer src="/src/scripts/load-async-css.js?v=1788239352576"></script>
<script defer src="/src/scripts/load-async-css.js?v=1788321006836"></script>
<noscript>
<link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
<link rel="stylesheet" href="/libs/prism/prism.css">
</noscript>
<script defer src="/src/scripts/fa-check.js?v=1788239352576"></script>
<script defer src="/src/scripts/fa-check.js?v=1788321006836"></script>
<!-- Update Manager - система принудительного обновления -->
<script defer src="/src/utils/updateManager.js?v=1788239352576"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788239352576"></script>
<script type="module" src="/dist/qr-local.js?v=1788239352576"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788239352576"></script>
<script defer src="/src/utils/updateManager.js?v=1788321006836"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788321006836"></script>
<script type="module" src="/dist/qr-local.js?v=1788321006836"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788321006836"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/dist/app-boot.js?v=1788239352576"></script>
<script type="module" src="/dist/app.js?v=1788239352576"></script>
<script type="module" src="/dist/app-boot.js?v=1788321006836"></script>
<script type="module" src="/dist/app.js?v=1788321006836"></script>
<script defer src="/src/scripts/pwa-register.js?v=1788239352576"></script>
<script src="/src/pwa/install-prompt.js?v=1788239352576" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788239352576" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788239352576"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788239352576">
<script defer src="/src/scripts/pwa-register.js?v=1788321006836"></script>
<script src="/src/pwa/install-prompt.js?v=1788321006836" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788321006836" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788321006836"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788321006836">
</body>
</html>
+1 -1
View File
@@ -1680,7 +1680,7 @@ import { GroupCallMedia, mediaErrorCode } from './group/groupCallMedia.js';
// /download/v0.3.0/SecureBit.Chat_0.1.0_x64-setup.exe, a file that never
// existed, and the download 404s. A pinned tag keeps serving a real
// installer instead.
const SB_DESKTOP_VERSION = '0.5.0';
const SB_DESKTOP_VERSION = '1.0.0';
const SB_DESKTOP_RELEASE = `https://github.com/SecureBitChat/securebit-desktop/releases/download/v${SB_DESKTOP_VERSION}`;
const DOWNLOADS = {
mac: { name: 'macOS', format: '.dmg · Apple Silicon & Intel', icon: 'fab fa-apple', url: `${SB_DESKTOP_RELEASE}/SecureBit.Chat_${SB_DESKTOP_VERSION}_x64.dmg` },
+1 -1
View File
@@ -11,7 +11,7 @@ let DYNAMIC_CACHE = 'securebit-pwa-dynamic-v4.7.56';
// Build stamp — rewritten by scripts/post-build.js on every release so this file's
// bytes change each deploy. That is what makes the browser detect a new Service Worker,
// reinstall it, drop stale caches and (via controllerchange) prompt the page to update.
const SW_BUILD_VERSION = '1788239352576';
const SW_BUILD_VERSION = '1788321006836';
// Locale subdirectories, rewritten by scripts/build-i18n.js. Each localized page is a
// separate document at its own URL, so the shell has to be cached and served per
+23 -1
View File
@@ -148,8 +148,23 @@ for (const code of site.locales) {
}
}
// These dictionaries are the SHARED source for two clients: this one and the
// Tauri desktop client, which lives in a separate repository and is not
// scanned here. Its keys are therefore unused *by this scan* and always
// will be — that is the cost of one dictionary rather than two drifting
// ones, not a defect to fix by deleting them.
//
// The exemption is deliberately narrow: the `desktop.` prefix, plus the
// message-lifetime labels below by exact name. Anything else that stops
// being used still fails, which is the point of the check.
const CONSUMED_BY_DESKTOP = new Set([
'msg.after5s', 'msg.after15s', 'msg.after30s', 'msg.after1m',
'msg.sec30', 'msg.min5', 'msg.hour1',
]);
const belongsToDesktop = (key) => key.startsWith('desktop.') || CONSUMED_BY_DESKTOP.has(key);
const defined = new Set(Object.keys(JSON.parse(read(`locales/${site.defaultLocale}.json`)).ui || {}));
const isUsed = (key) => used.has(key) || patterns.some((re) => re.test(key));
const isUsed = (key) => used.has(key) || belongsToDesktop(key) || patterns.some((re) => re.test(key));
const missing = [...used].filter((key) => !defined.has(key)).sort();
const unused = [...defined].filter((key) => !isUsed(key)).sort();
@@ -158,6 +173,13 @@ for (const code of site.locales) {
assert.deepEqual(unused, [],
`these keys are defined but never used — remove them rather than have them translated`);
assert.ok(used.size > 0, 'the scan found no t() calls at all, which means it is not scanning anything');
// If the desktop client ever stops sharing these dictionaries, the exemption
// above turns into a hiding place for dead strings. This fails when that
// day comes, instead of letting them accumulate unnoticed.
assert.ok(
[...defined].some(belongsToDesktop),
'no desktop-owned keys are defined any more — drop CONSUMED_BY_DESKTOP and the desktop. exemption'
);
assert.ok(patterns.length > 0, 'no template-literal keys were found — the dynamic-key scan is not working');
}
+24 -24
View File
@@ -30,7 +30,7 @@
<!-- PWA Manifest -->
<link rel="manifest" href="/uk/manifest.json">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- PWA Meta Tags -->
<meta name="mobile-web-app-capable" content="yes">
@@ -96,7 +96,7 @@
<link rel="apple-touch-startup-image" media="screen and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/8.3__iPad_Mini_portrait.png">
<!-- Apple Touch Icons -->
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788321006836">
<link rel="apple-touch-icon" sizes="57x57" href="/logo/icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/logo/icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/logo/icon-72x72.png">
@@ -105,7 +105,7 @@
<link rel="apple-touch-icon" sizes="120x120" href="/logo/icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/logo/icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/logo/icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788321006836">
<!-- Microsoft Tiles -->
<meta name="msapplication-TileColor" content="#ff6b35">
@@ -222,7 +222,7 @@
<!-- Render-blocking JS is deferred: classic deferred scripts and module scripts
both execute in document order after parsing, so React still runs before the
app modules below, but the parser / first paint is no longer blocked. -->
<script defer src="/config/ice-servers.js?v=1788239352576"></script>
<script defer src="/config/ice-servers.js?v=1788321006836"></script>
<script defer src="/libs/react/react.production.min.js"></script>
<script defer src="/libs/react-dom/react-dom.production.min.js"></script>
<!-- Prism syntax highlighting (vendored, offline). Tokenizes code as TEXT only —
@@ -230,8 +230,8 @@
Its CSS is loaded async via load-async-css.js (not paint-critical). -->
<script defer src="/libs/prism/prism.js"></script>
<!-- Critical, paint-defining CSS stays render-blocking (avoids FOUC / layout shift). -->
<link rel="stylesheet" href="/assets/tailwind.css?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="stylesheet" href="/assets/tailwind.css?v=1788321006836">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- Preload only the fonts needed for first paint. fa-solid covers the bulk of UI
icons; fa-regular/fa-brands are loaded on demand by their CSS (rarely on the
first screen). Inter latin 400/700 cover body text and headings/buttons. -->
@@ -239,38 +239,38 @@
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-400.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-700.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="/assets/fonts/inter/inter.css">
<link rel="stylesheet" href="/src/styles/main.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/components.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/main.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/components.css?v=1788321006836">
<!-- Loads after components.css on purpose: press feedback, material weight,
size-specific tracking and the reduced-motion / -transparency / -contrast
answers all need to settle arguments with the sheets above on source order. -->
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788321006836">
<!-- Last of the hand-written sheets: the mirroring rules must win over anything
above them, and they only ever apply under [dir="rtl"]. -->
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788321006836">
<!-- Non-critical CSS (FontAwesome ~102KB, Prism) loaded async — no longer blocks paint. -->
<script defer src="/src/scripts/load-async-css.js?v=1788239352576"></script>
<script defer src="/src/scripts/load-async-css.js?v=1788321006836"></script>
<noscript>
<link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
<link rel="stylesheet" href="/libs/prism/prism.css">
</noscript>
<script defer src="/src/scripts/fa-check.js?v=1788239352576"></script>
<script defer src="/src/scripts/fa-check.js?v=1788321006836"></script>
<!-- Update Manager - система принудительного обновления -->
<script defer src="/src/utils/updateManager.js?v=1788239352576"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788239352576"></script>
<script type="module" src="/dist/qr-local.js?v=1788239352576"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788239352576"></script>
<script defer src="/src/utils/updateManager.js?v=1788321006836"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788321006836"></script>
<script type="module" src="/dist/qr-local.js?v=1788321006836"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788321006836"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/dist/app-boot.js?v=1788239352576"></script>
<script type="module" src="/dist/app.js?v=1788239352576"></script>
<script type="module" src="/dist/app-boot.js?v=1788321006836"></script>
<script type="module" src="/dist/app.js?v=1788321006836"></script>
<script defer src="/src/scripts/pwa-register.js?v=1788239352576"></script>
<script src="/src/pwa/install-prompt.js?v=1788239352576" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788239352576" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788239352576"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788239352576">
<script defer src="/src/scripts/pwa-register.js?v=1788321006836"></script>
<script src="/src/pwa/install-prompt.js?v=1788321006836" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788321006836" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788321006836"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788321006836">
</body>
</html>
+24 -24
View File
@@ -30,7 +30,7 @@
<!-- PWA Manifest -->
<link rel="manifest" href="/ur/manifest.json">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- PWA Meta Tags -->
<meta name="mobile-web-app-capable" content="yes">
@@ -96,7 +96,7 @@
<link rel="apple-touch-startup-image" media="screen and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/8.3__iPad_Mini_portrait.png">
<!-- Apple Touch Icons -->
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788321006836">
<link rel="apple-touch-icon" sizes="57x57" href="/logo/icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/logo/icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/logo/icon-72x72.png">
@@ -105,7 +105,7 @@
<link rel="apple-touch-icon" sizes="120x120" href="/logo/icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/logo/icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/logo/icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788321006836">
<!-- Microsoft Tiles -->
<meta name="msapplication-TileColor" content="#ff6b35">
@@ -222,7 +222,7 @@
<!-- Render-blocking JS is deferred: classic deferred scripts and module scripts
both execute in document order after parsing, so React still runs before the
app modules below, but the parser / first paint is no longer blocked. -->
<script defer src="/config/ice-servers.js?v=1788239352576"></script>
<script defer src="/config/ice-servers.js?v=1788321006836"></script>
<script defer src="/libs/react/react.production.min.js"></script>
<script defer src="/libs/react-dom/react-dom.production.min.js"></script>
<!-- Prism syntax highlighting (vendored, offline). Tokenizes code as TEXT only —
@@ -230,8 +230,8 @@
Its CSS is loaded async via load-async-css.js (not paint-critical). -->
<script defer src="/libs/prism/prism.js"></script>
<!-- Critical, paint-defining CSS stays render-blocking (avoids FOUC / layout shift). -->
<link rel="stylesheet" href="/assets/tailwind.css?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="stylesheet" href="/assets/tailwind.css?v=1788321006836">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- Preload only the fonts needed for first paint. fa-solid covers the bulk of UI
icons; fa-regular/fa-brands are loaded on demand by their CSS (rarely on the
first screen). Inter latin 400/700 cover body text and headings/buttons. -->
@@ -239,38 +239,38 @@
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-400.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-700.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="/assets/fonts/inter/inter.css">
<link rel="stylesheet" href="/src/styles/main.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/components.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/main.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/components.css?v=1788321006836">
<!-- Loads after components.css on purpose: press feedback, material weight,
size-specific tracking and the reduced-motion / -transparency / -contrast
answers all need to settle arguments with the sheets above on source order. -->
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788321006836">
<!-- Last of the hand-written sheets: the mirroring rules must win over anything
above them, and they only ever apply under [dir="rtl"]. -->
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788321006836">
<!-- Non-critical CSS (FontAwesome ~102KB, Prism) loaded async — no longer blocks paint. -->
<script defer src="/src/scripts/load-async-css.js?v=1788239352576"></script>
<script defer src="/src/scripts/load-async-css.js?v=1788321006836"></script>
<noscript>
<link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
<link rel="stylesheet" href="/libs/prism/prism.css">
</noscript>
<script defer src="/src/scripts/fa-check.js?v=1788239352576"></script>
<script defer src="/src/scripts/fa-check.js?v=1788321006836"></script>
<!-- Update Manager - система принудительного обновления -->
<script defer src="/src/utils/updateManager.js?v=1788239352576"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788239352576"></script>
<script type="module" src="/dist/qr-local.js?v=1788239352576"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788239352576"></script>
<script defer src="/src/utils/updateManager.js?v=1788321006836"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788321006836"></script>
<script type="module" src="/dist/qr-local.js?v=1788321006836"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788321006836"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/dist/app-boot.js?v=1788239352576"></script>
<script type="module" src="/dist/app.js?v=1788239352576"></script>
<script type="module" src="/dist/app-boot.js?v=1788321006836"></script>
<script type="module" src="/dist/app.js?v=1788321006836"></script>
<script defer src="/src/scripts/pwa-register.js?v=1788239352576"></script>
<script src="/src/pwa/install-prompt.js?v=1788239352576" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788239352576" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788239352576"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788239352576">
<script defer src="/src/scripts/pwa-register.js?v=1788321006836"></script>
<script src="/src/pwa/install-prompt.js?v=1788321006836" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788321006836" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788321006836"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788321006836">
</body>
</html>
+24 -24
View File
@@ -30,7 +30,7 @@
<!-- PWA Manifest -->
<link rel="manifest" href="/zh/manifest.json">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- PWA Meta Tags -->
<meta name="mobile-web-app-capable" content="yes">
@@ -96,7 +96,7 @@
<link rel="apple-touch-startup-image" media="screen and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/8.3__iPad_Mini_portrait.png">
<!-- Apple Touch Icons -->
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788321006836">
<link rel="apple-touch-icon" sizes="57x57" href="/logo/icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/logo/icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/logo/icon-72x72.png">
@@ -105,7 +105,7 @@
<link rel="apple-touch-icon" sizes="120x120" href="/logo/icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/logo/icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/logo/icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788239352576">
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788321006836">
<!-- Microsoft Tiles -->
<meta name="msapplication-TileColor" content="#ff6b35">
@@ -222,7 +222,7 @@
<!-- Render-blocking JS is deferred: classic deferred scripts and module scripts
both execute in document order after parsing, so React still runs before the
app modules below, but the parser / first paint is no longer blocked. -->
<script defer src="/config/ice-servers.js?v=1788239352576"></script>
<script defer src="/config/ice-servers.js?v=1788321006836"></script>
<script defer src="/libs/react/react.production.min.js"></script>
<script defer src="/libs/react-dom/react-dom.production.min.js"></script>
<!-- Prism syntax highlighting (vendored, offline). Tokenizes code as TEXT only —
@@ -230,8 +230,8 @@
Its CSS is loaded async via load-async-css.js (not paint-critical). -->
<script defer src="/libs/prism/prism.js"></script>
<!-- Critical, paint-defining CSS stays render-blocking (avoids FOUC / layout shift). -->
<link rel="stylesheet" href="/assets/tailwind.css?v=1788239352576">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788239352576">
<link rel="stylesheet" href="/assets/tailwind.css?v=1788321006836">
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788321006836">
<!-- Preload only the fonts needed for first paint. fa-solid covers the bulk of UI
icons; fa-regular/fa-brands are loaded on demand by their CSS (rarely on the
first screen). Inter latin 400/700 cover body text and headings/buttons. -->
@@ -239,38 +239,38 @@
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-400.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-700.woff2" as="font" type="font/woff2" crossorigin>
<link rel="stylesheet" href="/assets/fonts/inter/inter.css">
<link rel="stylesheet" href="/src/styles/main.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/components.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/main.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/animations.css?v=1788321006836">
<link rel="stylesheet" href="/src/styles/components.css?v=1788321006836">
<!-- Loads after components.css on purpose: press feedback, material weight,
size-specific tracking and the reduced-motion / -transparency / -contrast
answers all need to settle arguments with the sheets above on source order. -->
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788321006836">
<!-- Last of the hand-written sheets: the mirroring rules must win over anything
above them, and they only ever apply under [dir="rtl"]. -->
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788239352576">
<link rel="stylesheet" href="/src/styles/rtl.css?v=1788321006836">
<!-- Non-critical CSS (FontAwesome ~102KB, Prism) loaded async — no longer blocks paint. -->
<script defer src="/src/scripts/load-async-css.js?v=1788239352576"></script>
<script defer src="/src/scripts/load-async-css.js?v=1788321006836"></script>
<noscript>
<link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
<link rel="stylesheet" href="/libs/prism/prism.css">
</noscript>
<script defer src="/src/scripts/fa-check.js?v=1788239352576"></script>
<script defer src="/src/scripts/fa-check.js?v=1788321006836"></script>
<!-- Update Manager - система принудительного обновления -->
<script defer src="/src/utils/updateManager.js?v=1788239352576"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788239352576"></script>
<script type="module" src="/dist/qr-local.js?v=1788239352576"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788239352576"></script>
<script defer src="/src/utils/updateManager.js?v=1788321006836"></script>
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788321006836"></script>
<script type="module" src="/dist/qr-local.js?v=1788321006836"></script>
<script type="module" src="/src/components/QRScanner.js?v=1788321006836"></script>
</head>
<body>
<div id="root"></div>
<script type="module" src="/dist/app-boot.js?v=1788239352576"></script>
<script type="module" src="/dist/app.js?v=1788239352576"></script>
<script type="module" src="/dist/app-boot.js?v=1788321006836"></script>
<script type="module" src="/dist/app.js?v=1788321006836"></script>
<script defer src="/src/scripts/pwa-register.js?v=1788239352576"></script>
<script src="/src/pwa/install-prompt.js?v=1788239352576" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788239352576" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788239352576"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788239352576">
<script defer src="/src/scripts/pwa-register.js?v=1788321006836"></script>
<script src="/src/pwa/install-prompt.js?v=1788321006836" type="module"></script>
<script src="/src/pwa/pwa-manager.js?v=1788321006836" type="module"></script>
<script defer src="/src/scripts/pwa-offline-test.js?v=1788321006836"></script>
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788321006836">
</body>
</html>