diff --git a/changedetectionio/__init__.py b/changedetectionio/__init__.py index 02ad45093..b28f6756c 100644 --- a/changedetectionio/__init__.py +++ b/changedetectionio/__init__.py @@ -2,7 +2,7 @@ # Read more https://github.com/dgtlmoon/changedetection.io/wiki # Semver means never use .01, or 00. Should be .1. -__version__ = '0.52.4' +__version__ = '0.52.6' from changedetectionio.strtobool import strtobool from json.decoder import JSONDecodeError @@ -41,9 +41,10 @@ from loguru import logger # # IMPLEMENTATION: # 1. Explicit contexts everywhere (primary protection): -# - Watch.py: ctx = multiprocessing.get_context('spawn') # - playwright.py: ctx = multiprocessing.get_context('spawn') # - puppeteer.py: ctx = multiprocessing.get_context('spawn') +# - isolated_opencv.py: ctx = multiprocessing.get_context('spawn') +# - isolated_libvips.py: ctx = multiprocessing.get_context('spawn') # # 2. Global default (defense-in-depth, below): # - Safety net if future code forgets explicit context diff --git a/changedetectionio/blueprint/watchlist/__init__.py b/changedetectionio/blueprint/watchlist/__init__.py index 56a7f184d..e78bc9146 100644 --- a/changedetectionio/blueprint/watchlist/__init__.py +++ b/changedetectionio/blueprint/watchlist/__init__.py @@ -2,7 +2,6 @@ import os import time from flask import Blueprint, request, make_response, render_template, redirect, url_for, flash, session -from flask_login import current_user from flask_paginate import Pagination, get_page_parameter from changedetectionio import forms @@ -85,6 +84,7 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe app_rss_token=datastore.data['settings']['application'].get('rss_access_token'), datastore=datastore, errored_count=errored_count, + extra_classes='has-queue' if len(update_q.queue) else '', form=form, generate_tag_colors=processors.generate_processor_badge_colors, guid=datastore.data['app_guid'], @@ -92,9 +92,10 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe hosted_sticky=os.getenv("SALTED_PASS", False) == False, now_time_server=round(time.time()), pagination=pagination, + processor_badge_css=processors.get_processor_badge_css(), processor_badge_texts=processors.get_processor_badge_texts(), processor_descriptions=processors.get_processor_descriptions(), - processor_badge_css=processors.get_processor_badge_css(), + queue_size=len(update_q.queue), queued_uuids=[q_uuid.item['uuid'] for q_uuid in update_q.queue], search_q=request.args.get('q', '').strip(), sort_attribute=request.args.get('sort') if request.args.get('sort') else request.cookies.get('sort'), diff --git a/changedetectionio/blueprint/watchlist/templates/watch-overview.html b/changedetectionio/blueprint/watchlist/templates/watch-overview.html index 525e13680..5ec9f9169 100644 --- a/changedetectionio/blueprint/watchlist/templates/watch-overview.html +++ b/changedetectionio/blueprint/watchlist/templates/watch-overview.html @@ -99,9 +99,14 @@ html[data-darkmode="true"] .watch-tag-list.tag-{{ class_name }} { data-confirm-message="{{ _('

Are you sure you want to delete the selected watches?

This action cannot be undone.

') }}" data-confirm-button="{{ _('Delete') }}">{{ _('Delete') }} - {%- if watches|length >= pagination.per_page -%} - {{ pagination.info }} - {%- endif -%} + +
+
{%- if watches|length >= pagination.per_page -%}{{ pagination.info }}{%- endif -%}
+
{{ _('Queued size') }}: {{ queue_size }}
+
+ + + {%- if search_q -%}
{{ _('Searching') }} "{{search_q}}"
{%- endif -%}
{{ _('All') }} diff --git a/changedetectionio/content_fetchers/webdriver_selenium.py b/changedetectionio/content_fetchers/webdriver_selenium.py index 73c6dad40..eebf10579 100644 --- a/changedetectionio/content_fetchers/webdriver_selenium.py +++ b/changedetectionio/content_fetchers/webdriver_selenium.py @@ -156,6 +156,9 @@ class fetcher(Fetcher): from PIL import Image import io img = Image.open(io.BytesIO(screenshot_png)) + # Convert to RGB if needed (JPEG doesn't support transparency) + if img.mode != 'RGB': + img = img.convert('RGB') jpeg_buffer = io.BytesIO() img.save(jpeg_buffer, format='JPEG', quality=int(os.getenv("SCREENSHOT_QUALITY", 72))) self.screenshot = jpeg_buffer.getvalue() diff --git a/changedetectionio/flask_app.py b/changedetectionio/flask_app.py index a1545db26..d1e438ea5 100644 --- a/changedetectionio/flask_app.py +++ b/changedetectionio/flask_app.py @@ -9,6 +9,7 @@ import threading import time import timeago from blinker import signal +from pathlib import Path from changedetectionio.strtobool import strtobool from threading import Event @@ -84,6 +85,10 @@ app.config['NEW_VERSION_AVAILABLE'] = False if os.getenv('FLASK_SERVER_NAME'): app.config['SERVER_NAME'] = os.getenv('FLASK_SERVER_NAME') +# Babel/i18n configuration +app.config['BABEL_TRANSLATION_DIRECTORIES'] = str(Path(__file__).parent / 'translations') +app.config['BABEL_DEFAULT_LOCALE'] = 'en_GB' + #app.config["EXPLAIN_TEMPLATE_LOADING"] = True @@ -395,13 +400,9 @@ def changedetection_app(config=None, datastore_o=None): def get_locale(): # 1. Try to get locale from session (user explicitly selected) if 'locale' in session: - locale = session['locale'] - logger.trace(f"DEBUG: get_locale() returning from session: {locale}") - return locale + return session['locale'] # 2. Fall back to Accept-Language header - locale = request.accept_languages.best_match(language_codes) - logger.trace(f"DEBUG: get_locale() returning from Accept-Language: {locale}") - return locale + return request.accept_languages.best_match(language_codes) # Initialize Babel with locale selector babel = Babel(app, locale_selector=get_locale) @@ -518,9 +519,20 @@ def changedetection_app(config=None, datastore_o=None): @app.route('/set-language/') def set_language(locale): """Set the user's preferred language in the session""" + if not request.cookies: + logger.error("Cannot set language without session cookie") + flash("Cannot set language without session cookie", 'error') + return redirect(url_for('watchlist.index')) + # Validate the locale against available languages if locale in language_codes: session['locale'] = locale + + # CRITICAL: Flask-Babel caches the locale in the request context (ctx.babel_locale) + # We must refresh to clear this cache so the new locale takes effect immediately + # This is especially important for tests where multiple requests happen rapidly + from flask_babel import refresh + refresh() else: logger.error(f"Invalid locale {locale}, available: {language_codes}") diff --git a/changedetectionio/languages.py b/changedetectionio/languages.py index e6552d716..42a9d4c0c 100644 --- a/changedetectionio/languages.py +++ b/changedetectionio/languages.py @@ -29,7 +29,9 @@ def get_timeago_locale(flask_locale): """ locale_map = { 'zh': 'zh_CN', # Chinese Simplified - 'zh_Hant_TW': 'zh_TW', # Flask-Babel normalizes zh_TW to zh_Hant_TW + # timeago library just hasn't been updated to use the more modern locale naming convention, before BCP 47 / RFC 5646. + 'zh_TW': 'zh_TW', # Chinese Traditional (timeago uses zh_TW) + 'zh_Hant_TW': 'zh_TW', # Flask-Babel normalizes zh_TW to zh_Hant_TW, map back to timeago's zh_TW 'pt': 'pt_PT', # Portuguese (Portugal) 'sv': 'sv_SE', # Swedish 'no': 'nb_NO', # Norwegian Bokmål @@ -54,7 +56,7 @@ LANGUAGE_DATA = { 'it': {'flag': 'fi fi-it fis', 'name': 'Italiano'}, 'ja': {'flag': 'fi fi-jp fis', 'name': '日本語'}, 'zh': {'flag': 'fi fi-cn fis', 'name': '中文 (简体)'}, - 'zh_TW': {'flag': 'fi fi-tw fis', 'name': '繁體中文'}, + 'zh_Hant_TW': {'flag': 'fi fi-tw fis', 'name': '繁體中文'}, 'ru': {'flag': 'fi fi-ru fis', 'name': 'Русский'}, 'pl': {'flag': 'fi fi-pl fis', 'name': 'Polski'}, 'nl': {'flag': 'fi fi-nl fis', 'name': 'Nederlands'}, diff --git a/changedetectionio/model/Watch.py b/changedetectionio/model/Watch.py index 79e0f8737..f5bc8593b 100644 --- a/changedetectionio/model/Watch.py +++ b/changedetectionio/model/Watch.py @@ -18,21 +18,31 @@ BROTLI_COMPRESS_SIZE_THRESHOLD = int(os.getenv('SNAPSHOT_BROTLI_COMPRESSION_THRE minimum_seconds_recheck_time = int(os.getenv('MINIMUM_SECONDS_RECHECK_TIME', 3)) mtable = {'seconds': 1, 'minutes': 60, 'hours': 3600, 'days': 86400, 'weeks': 86400 * 7} -def _brotli_compress_worker(conn, filepath, mode=None): +def _brotli_save(contents, filepath, mode=None, fallback_uncompressed=False): """ - Worker function to compress data with brotli in a separate process. - This isolates memory - when process exits, OS reclaims all memory. + Save compressed data using native brotli. + Testing shows no memory leak when using gc.collect() after compression. Args: - conn: multiprocessing.Pipe connection to receive data + contents: data to compress (str or bytes) filepath: destination file path mode: brotli compression mode (e.g., brotli.MODE_TEXT) + fallback_uncompressed: if True, save uncompressed on failure; if False, raise exception + + Returns: + str: actual filepath saved (may differ from input if fallback used) + + Raises: + Exception: if compression fails and fallback_uncompressed is False """ import brotli + import gc + + # Ensure contents are bytes + if isinstance(contents, str): + contents = contents.encode('utf-8') try: - # Receive data from parent process via pipe (avoids pickle overhead) - contents = conn.recv() logger.debug(f"Starting brotli compression of {len(contents)} bytes.") if mode is not None: @@ -43,111 +53,25 @@ def _brotli_compress_worker(conn, filepath, mode=None): with open(filepath, 'wb') as f: f.write(compressed_data) - # Send success status back - conn.send(True) logger.debug(f"Finished brotli compression - From {len(contents)} to {len(compressed_data)} bytes.") - # No need for explicit cleanup - process exit frees all memory - except Exception as e: - logger.critical(f"Brotli compression worker failed: {e}") - conn.send(False) - finally: - conn.close() + # Force garbage collection to prevent memory buildup + gc.collect() -def _brotli_subprocess_save(contents, filepath, mode=None, timeout=30, fallback_uncompressed=False): - """ - Save compressed data using subprocess to isolate memory. - Uses Pipe to avoid pickle overhead for large data. - - Args: - contents: data to compress (str or bytes) - filepath: destination file path - mode: brotli compression mode (e.g., brotli.MODE_TEXT) - timeout: subprocess timeout in seconds - fallback_uncompressed: if True, save uncompressed on failure; if False, raise exception - - Returns: - str: actual filepath saved (may differ from input if fallback used) - - Raises: - Exception: if compression fails and fallback_uncompressed is False - """ - import multiprocessing - import sys - - # Ensure contents are bytes - if isinstance(contents, str): - contents = contents.encode('utf-8') - - # Use explicit spawn context for thread safety (avoids fork() with multi-threaded parent) - # Always use spawn - consistent behavior in tests and production - ctx = multiprocessing.get_context('spawn') - parent_conn, child_conn = ctx.Pipe() - - # Run compression in subprocess using spawn (not fork) - proc = ctx.Process(target=_brotli_compress_worker, args=(child_conn, filepath, mode)) - - # Windows-safe: Set daemon=False explicitly to avoid issues with process cleanup - proc.daemon = False - proc.start() - - try: - # Send data to subprocess via pipe (avoids pickle) - parent_conn.send(contents) - - # Wait for result with timeout - if parent_conn.poll(timeout): - success = parent_conn.recv() - else: - success = False - logger.warning(f"Brotli compression subprocess timed out after {timeout}s") - # Graceful termination with platform-aware cleanup - try: - proc.terminate() - except Exception as term_error: - logger.debug(f"Process termination issue (may be normal on Windows): {term_error}") - - parent_conn.close() - proc.join(timeout=5) - - # Force kill if still alive after graceful termination - if proc.is_alive(): - try: - if sys.platform == 'win32': - # Windows: use kill() which is more forceful - proc.kill() - else: - # Unix: terminate() already sent SIGTERM, now try SIGKILL - proc.kill() - proc.join(timeout=2) - except Exception as kill_error: - logger.warning(f"Failed to kill brotli compression process: {kill_error}") - - # Check if file was created successfully - if success and os.path.exists(filepath): - return filepath + return filepath except Exception as e: logger.error(f"Brotli compression error: {e}") - try: - parent_conn.close() - except: - pass - try: - proc.terminate() - proc.join(timeout=2) - except: - pass - # Compression failed - if fallback_uncompressed: - logger.warning(f"Brotli compression failed for {filepath}, saving uncompressed") - fallback_path = filepath.replace('.br', '') - with open(fallback_path, 'wb') as f: - f.write(contents) - return fallback_path - else: - raise Exception(f"Brotli compression subprocess failed for {filepath}") + # Compression failed + if fallback_uncompressed: + logger.warning(f"Brotli compression failed for {filepath}, saving uncompressed") + fallback_path = filepath.replace('.br', '') + with open(fallback_path, 'wb') as f: + f.write(contents) + return fallback_path + else: + raise Exception(f"Brotli compression failed for {filepath}: {e}") class model(watch_base): @@ -523,7 +447,7 @@ class model(watch_base): if not os.path.exists(dest): try: - actual_dest = _brotli_subprocess_save(contents, dest, mode=brotli.MODE_TEXT, fallback_uncompressed=True) + actual_dest = _brotli_save(contents, dest, mode=brotli.MODE_TEXT, fallback_uncompressed=True) if actual_dest != dest: snapshot_fname = os.path.basename(actual_dest) except Exception as e: @@ -949,13 +873,13 @@ class model(watch_base): def save_last_text_fetched_before_filters(self, contents): import brotli filepath = os.path.join(self.watch_data_dir, 'last-fetched.br') - _brotli_subprocess_save(contents, filepath, mode=brotli.MODE_TEXT, fallback_uncompressed=False) + _brotli_save(contents, filepath, mode=brotli.MODE_TEXT, fallback_uncompressed=False) def save_last_fetched_html(self, timestamp, contents): self.ensure_data_dir_exists() snapshot_fname = f"{timestamp}.html.br" filepath = os.path.join(self.watch_data_dir, snapshot_fname) - _brotli_subprocess_save(contents, filepath, mode=None, fallback_uncompressed=True) + _brotli_save(contents, filepath, mode=None, fallback_uncompressed=True) self._prune_last_fetched_html_snapshots() def get_fetched_html(self, timestamp): diff --git a/changedetectionio/processors/image_ssim_diff/image_handler/isolated_libvips.py b/changedetectionio/processors/image_ssim_diff/image_handler/isolated_libvips.py index ceb63b0b7..d0b55507d 100644 --- a/changedetectionio/processors/image_ssim_diff/image_handler/isolated_libvips.py +++ b/changedetectionio/processors/image_ssim_diff/image_handler/isolated_libvips.py @@ -13,14 +13,9 @@ Research: https://github.com/libvips/pyvips/issues/234 import multiprocessing -# CRITICAL: Use 'spawn' instead of 'fork' to avoid inheriting parent's +# CRITICAL: Use 'spawn' context instead of 'fork' to avoid inheriting parent's # LibVIPS threading state which can cause hangs in gaussblur operations # https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods -try: - multiprocessing.set_start_method('spawn', force=False) -except RuntimeError: - # Already set, ignore - pass def _worker_generate_diff(conn, img_bytes_from, img_bytes_to, threshold, blur_sigma, max_width, max_height): @@ -95,9 +90,10 @@ def generate_diff_isolated(img_bytes_from, img_bytes_to, threshold, blur_sigma, Returns: bytes: JPEG diff image or None on failure """ - parent_conn, child_conn = multiprocessing.Pipe() + ctx = multiprocessing.get_context('spawn') + parent_conn, child_conn = ctx.Pipe() - p = multiprocessing.Process( + p = ctx.Process( target=_worker_generate_diff, args=(child_conn, img_bytes_from, img_bytes_to, threshold, blur_sigma, max_width, max_height) ) @@ -140,7 +136,8 @@ def calculate_change_percentage_isolated(img_bytes_from, img_bytes_to, threshold Returns: float: Change percentage """ - parent_conn, child_conn = multiprocessing.Pipe() + ctx = multiprocessing.get_context('spawn') + parent_conn, child_conn = ctx.Pipe() def _worker_calculate(conn): try: @@ -185,7 +182,7 @@ def calculate_change_percentage_isolated(img_bytes_from, img_bytes_to, threshold finally: conn.close() - p = multiprocessing.Process(target=_worker_calculate, args=(child_conn,)) + p = ctx.Process(target=_worker_calculate, args=(child_conn,)) p.start() result = 0.0 @@ -233,7 +230,8 @@ def compare_images_isolated(img_bytes_from, img_bytes_to, threshold, blur_sigma, tuple: (changed_detected, change_percentage) """ print(f"[Parent] Starting compare_images_isolated subprocess", flush=True) - parent_conn, child_conn = multiprocessing.Pipe() + ctx = multiprocessing.get_context('spawn') + parent_conn, child_conn = ctx.Pipe() def _worker_compare(conn): try: @@ -301,7 +299,7 @@ def compare_images_isolated(img_bytes_from, img_bytes_to, threshold, blur_sigma, finally: conn.close() - p = multiprocessing.Process(target=_worker_compare, args=(child_conn,)) + p = ctx.Process(target=_worker_compare, args=(child_conn,)) print(f"[Parent] Starting subprocess (pid will be assigned)", flush=True) p.start() print(f"[Parent] Subprocess started (pid={p.pid}), waiting for result (30s timeout)", flush=True) diff --git a/changedetectionio/static/js/realtime.js b/changedetectionio/static/js/realtime.js index c64a9c297..474b2df0b 100644 --- a/changedetectionio/static/js/realtime.js +++ b/changedetectionio/static/js/realtime.js @@ -76,7 +76,7 @@ $(document).ready(function () { // Cache DOM elements for performance const queueBubble = document.getElementById('queue-bubble'); - + const queueSizePagerInfoText = document.getElementById('queue-size-int'); // Only try to connect if authentication isn't required or user is authenticated // The 'is_authenticated' variable will be set in the template if (typeof is_authenticated !== 'undefined' ? is_authenticated : true) { @@ -118,6 +118,10 @@ $(document).ready(function () { socket.on('queue_size', function (data) { console.log(`${data.event_timestamp} - Queue size update: ${data.q_length}`); + if(queueSizePagerInfoText) { + queueSizePagerInfoText.textContent = parseInt(data.q_length).toLocaleString() || 'None'; + } + document.body.classList.toggle('has-queue', parseInt(data.q_length) > 0); // Update queue bubble in action sidebar //if (queueBubble) { diff --git a/changedetectionio/static/styles/scss/parts/_pagination.scss b/changedetectionio/static/styles/scss/parts/_pagination.scss index 3624548a3..502a41f57 100644 --- a/changedetectionio/static/styles/scss/parts/_pagination.scss +++ b/changedetectionio/static/styles/scss/parts/_pagination.scss @@ -1,6 +1,4 @@ .pagination-page-info { - color: #fff; - font-size: 0.85rem; text-transform: capitalize; } diff --git a/changedetectionio/static/styles/scss/parts/_watch_table.scss b/changedetectionio/static/styles/scss/parts/_watch_table.scss index afcb66afc..bc66aa7fc 100644 --- a/changedetectionio/static/styles/scss/parts/_watch_table.scss +++ b/changedetectionio/static/styles/scss/parts/_watch_table.scss @@ -1,4 +1,32 @@ /* table related */ +#stats_row { + display: flex; + align-items: center; + width: 100%; + color: #fff; + font-size: 0.85rem; + >* { + padding-bottom: 0.5rem; + } + .left { + text-align: left; + } + + .right { + opacity: 0.5; + transition: opacity 0.6s ease; + margin-left: auto; /* pushes it to the far right */ + text-align: right; + } +} +body.has-queue { + #stats_row { + .right { + opacity: 1.0; + } + } +} + .watch-table { width: 100%; font-size: 80%; diff --git a/changedetectionio/static/styles/styles.css b/changedetectionio/static/styles/styles.css index 5850ac6dc..1ca89e5dc 100644 --- a/changedetectionio/static/styles/styles.css +++ b/changedetectionio/static/styles/styles.css @@ -1 +1 @@ -:root{--color-white: #fff;--color-grey-50: #111;--color-grey-100: #262626;--color-grey-200: #333;--color-grey-300: #444;--color-grey-325: #555;--color-grey-350: #565d64;--color-grey-400: #666;--color-grey-500: #777;--color-grey-600: #999;--color-grey-700: #cbcbcb;--color-grey-750: #ddd;--color-grey-800: #e0e0e0;--color-grey-850: #eee;--color-grey-900: #f2f2f2;--color-black: #000;--color-dark-red: #a00;--color-light-red: #dd0000;--color-background-page: var(--color-grey-100);--color-background-gradient-first: #5ad8f7;--color-background-gradient-second: #2f50af;--color-background-gradient-third: #9150bf;--color-background: var(--color-white);--color-text: var(--color-grey-200);--color-link: #1b98f8;--color-menu-accent: #ed5900;--color-background-code: var(--color-grey-850);--color-error: var(--color-dark-red);--color-error-input: #ffebeb;--color-error-list: var(--color-light-red);--color-table-background: var(--color-background);--color-table-stripe: var(--color-grey-900);--color-text-tab: var(--color-white);--color-background-tab: rgba(255, 255, 255, 0.2);--color-background-tab-hover: rgba(255, 255, 255, 0.5);--color-text-tab-active: #222;--color-api-key: #0078e7;--color-background-button-primary: #0078e7;--color-background-button-green: #42dd53;--color-background-button-red: #dd4242;--color-background-button-success: rgb(28, 184, 65);--color-background-button-error: rgb(202, 60, 60);--color-text-button-error: var(--color-white);--color-background-button-warning: rgb(202, 60, 60);--color-text-button-warning: var(--color-white);--color-background-button-secondary: rgb(66, 184, 221);--color-background-button-cancel: rgb(200, 200, 200);--color-text-button: var(--color-white);--color-background-button-tag: rgb(99, 99, 99);--color-background-snapshot-age: #dfdfdf;--color-error-text-snapshot-age: var(--color-white);--color-error-background-snapshot-age: #ff0000;--color-background-button-tag-active: #9c9c9c;--color-text-messages: var(--color-white);--color-background-messages-message: rgba(255, 255, 255, .2);--color-background-messages-error: rgba(255, 1, 1, .5);--color-background-messages-notice: rgba(255, 255, 255, .5);--color-border-notification: #ccc;--color-background-checkbox-operations: rgba(0, 0, 0, 0.05);--color-warning: #ff3300;--color-border-warning: var(--color-warning);--color-text-legend: var(--color-white);--color-link-new-version: #e07171;--color-last-checked: #bbb;--color-text-footer: #444;--color-border-watch-table-cell: #eee;--color-text-watch-tag-list: rgba(231, 0, 105, 0.4);--color-background-new-watch-form: rgba(0, 0, 0, 0.05);--color-background-new-watch-input: var(--color-white);--color-background-new-watch-input-transparent: rgba(255, 255, 255, 0.1);--color-text-new-watch-input: var(--color-text);--color-border-input: var(--color-grey-500);--color-shadow-input: var(--color-grey-400);--color-background-input: var(--color-white);--color-text-input: var(--color-text);--color-text-input-description: var(--color-grey-500);--color-text-input-placeholder: var(--color-grey-600);--color-background-table-thead: var(--color-grey-800);--color-border-table-cell: var(--color-grey-700);--color-text-menu-heading: var(--color-grey-350);--color-text-menu-link: var(--color-grey-500);--color-background-menu-link-hover: var(--color-grey-850);--color-text-menu-link-hover: var(--color-grey-300);--color-shadow-jump: var(--color-grey-500);--color-icon-github: var(--color-black);--color-icon-github-hover: var(--color-grey-300);--color-watch-table-error: var(--color-dark-red);--color-watch-table-row-text: var(--color-grey-100);--highlight-trigger-text-bg-color: #1b98f8;--highlight-ignored-text-bg-color: var(--color-grey-700);--highlight-blocked-text-bg-color: rgb(202, 60, 60)}html[data-darkmode=true]{--color-link: #59bdfb;--color-text: var(--color-white);--color-background-gradient-first: #3f90a5;--color-background-gradient-second: #1e316c;--color-background-gradient-third: #4d2c64;--color-background-new-watch-input: var(--color-grey-100);--color-background-new-watch-input-transparent: var(--color-grey-100);--color-text-new-watch-input: var(--color-text);--color-background-table-thead: var(--color-grey-200);--color-table-background: var(--color-grey-300);--color-table-stripe: var(--color-grey-325);--color-background: var(--color-grey-300);--color-text-menu-heading: var(--color-grey-850);--color-text-menu-link: var(--color-grey-800);--color-border-table-cell: var(--color-grey-400);--color-text-tab-active: var(--color-text);--color-border-input: var(--color-grey-400);--color-shadow-input: var(--color-grey-50);--color-background-input: var(--color-grey-350);--color-text-input-description: var(--color-grey-600);--color-text-input-placeholder: var(--color-grey-600);--color-text-watch-tag-list: rgba(250, 62, 146, 0.4);--color-background-code: var(--color-grey-200);--color-background-tab: rgba(0, 0, 0, 0.2);--color-background-tab-hover: rgba(0, 0, 0, 0.5);--color-background-snapshot-age: var(--color-grey-200);--color-shadow-jump: var(--color-grey-200);--color-icon-github: var(--color-white);--color-icon-github-hover: var(--color-grey-700);--color-watch-table-error: var(--color-light-red);--color-watch-table-row-text: var(--color-grey-800)}html[data-darkmode=true] .icon-spread{filter:hue-rotate(-10deg) brightness(1.5)}html[data-darkmode=true] .watch-table .title-col a[target=_blank]::after,html[data-darkmode=true] .watch-table .current-diff-url::after{filter:invert(0.5) hue-rotate(10deg) brightness(2)}html[data-darkmode=true] .watch-table .status-browsersteps{filter:invert(0.5) hue-rotate(10deg) brightness(1.5)}html[data-darkmode=true] .watch-table .watch-controls .state-off img{opacity:.3}html[data-darkmode=true] .watch-table .watch-controls .state-on img{opacity:1}html[data-darkmode=true] .watch-table .unviewed{color:#fff}html[data-darkmode=true] .watch-table .unviewed.error{color:var(--color-watch-table-error)}.arrow{border:solid #1b98f8;border-width:0 2px 2px 0;display:inline-block;padding:3px}.arrow.right{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}.arrow.left{transform:rotate(135deg);-webkit-transform:rotate(135deg)}.arrow.up,.arrow.asc{transform:rotate(-135deg);-webkit-transform:rotate(-135deg)}.arrow.down,.arrow.desc{transform:rotate(45deg);-webkit-transform:rotate(45deg)}#browser_steps th{display:none}#browser_steps li{list-style:decimal;padding:5px}#browser_steps li.browser-step-with-error{background-color:#ffd6d6;border-radius:4px}#browser_steps li:not(:first-child):hover{opacity:1}#browser_steps li .control{padding-left:5px;padding-right:5px}#browser_steps li .control a{font-size:70%}#browser_steps li.empty{padding:0px;opacity:.35}#browser_steps li.empty .control{display:none}#browser_steps li:hover{background:#eee}#browser_steps li>label{display:none}@media only screen and (min-width: 760px){#browser-steps .flex-wrapper{display:flex;flex-flow:row;height:70vh;font-size:80%}#browser-steps .flex-wrapper #browser-steps-ui{flex-grow:1;flex-shrink:1;flex-basis:0;background-color:#eee;border-radius:5px}#browser-steps-fieldlist{flex-grow:0;flex-shrink:0;flex-basis:auto;max-width:400px;padding-left:1rem;overflow-y:scroll}#browsersteps-selector-wrapper{height:100% !important}}#browsersteps-selector-wrapper{width:100%;overflow-y:scroll;position:relative;height:80vh}#browsersteps-selector-wrapper>img{position:absolute;max-width:100%}#browsersteps-selector-wrapper>canvas{position:relative;max-width:100%}#browsersteps-selector-wrapper>canvas:hover{cursor:pointer}#browsersteps-selector-wrapper .loader{position:absolute;left:50%;top:50%;transform:translate(-50%, -50%);z-index:100;max-width:350px;text-align:center}#browsersteps-selector-wrapper .spinner,#browsersteps-selector-wrapper .spinner:after{width:80px;height:80px;font-size:3px}#browsersteps-selector-wrapper #browsersteps-click-start{color:var(--color-grey-400)}#browsersteps-selector-wrapper #browsersteps-click-start:hover{cursor:pointer}ul#requests-extra_proxies{list-style:none}ul#requests-extra_proxies li>label{display:none}ul#requests-extra_proxies table tr{display:table-row}ul#requests-extra_proxies table tr input[type=text]{width:100%}@media only screen and (min-width: 1024px){ul#requests-extra_proxies table tr{display:inline}}#request label[for=proxy]{display:inline-block}body.proxy-check-active #request .proxy-check-details{font-size:80%;color:#555;display:block;padding-left:2em;max-width:500px}body.proxy-check-active #request .proxy-timing{font-size:80%;padding-left:1rem;color:var(--color-link)}#recommended-proxy{display:grid;gap:2rem;padding-bottom:1em}@media(min-width: 991px){#recommended-proxy{grid-template-columns:repeat(2, 1fr)}}#recommended-proxy>div{border:1px #aaa solid;border-radius:4px;padding:1em}#extra-proxies-setting{border:1px solid var(--color-grey-800);border-radius:4px;margin:1em;padding:1em}ul#requests-extra_browsers{list-style:none}ul#requests-extra_browsers li>label{display:none}ul#requests-extra_browsers table tr{display:table-row}ul#requests-extra_browsers table tr input[type=text]{width:100%}@media only screen and (min-width: 1280px){ul#requests-extra_browsers table tr{display:inline}ul#requests-extra_browsers table tr input[type=text]{width:100%}}#extra-browsers-setting{border:1px solid var(--color-grey-800);border-radius:4px;margin:1em;padding:1em}.pagination-page-info{color:#fff;font-size:.85rem;text-transform:capitalize}.pagination.menu>*{display:inline-block}.pagination.menu li{display:inline-block}.pagination.menu a{padding:.65rem;margin:3px;border:none;background:#444;border-radius:2px;color:var(--color-text-button)}.pagination.menu a.disabled{display:none}.pagination.menu a.active{font-weight:bold;background:#888}.pagination.menu a:hover{background:#999}.spinner,.spinner:after{border-radius:50%;width:10px;height:10px}.spinner{margin:0px auto;font-size:3px;vertical-align:middle;display:inline-block;text-indent:-9999em;border-top:1.1em solid rgba(38,104,237,.2);border-right:1.1em solid rgba(38,104,237,.2);border-bottom:1.1em solid rgba(38,104,237,.2);border-left:1.1em solid #2668ed;-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0);-webkit-animation:load8 1.1s infinite linear;animation:load8 1.1s infinite linear}@-webkit-keyframes load8{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes load8{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.toggle-light-mode .icon-dark{display:none}html[data-darkmode=true] .toggle-light-mode .icon-light{display:none}html[data-darkmode=true] .toggle-light-mode .icon-dark{display:block}.pure-menu-link{padding:.5rem 1em;line-height:1.2rem}.pure-menu-item svg{height:1.2rem}.pure-menu-item *{vertical-align:middle}.pure-menu-item .github-link{height:1.8rem;display:block}.pure-menu-item .github-link svg{height:100%}.pure-menu-item .bi-heart:hover{cursor:pointer}.pure-menu-item.active .pure-menu-link{background-color:var(--color-background-menu-link-hover);color:var(--color-text-menu-link-hover)}#cdio-logo{padding-left:.5em}#inline-menu-extras-group>*{display:inline-block}#overlay{opacity:.95;position:fixed;width:350px;max-width:100%;height:100%;top:0;right:-350px;background-color:var(--color-table-stripe);z-index:2;transform:translateX(0);transition:transform .5s ease}#overlay.visible{transform:translateX(-100%)}#overlay .content{font-size:.875rem;padding:1rem;margin-top:5rem;max-width:400px;color:var(--color-watch-table-row-text)}#heartpath{transition:all ease .3s !important}#heartpath:hover{fill:red !important;transition:all ease .3s !important}.minitabs-wrapper{width:100%}.minitabs-wrapper>div[id]{padding:20px;border:1px solid #ccc;border-top:none}.minitabs-wrapper .minitabs-content{width:100%;display:flex}.minitabs-wrapper .minitabs-content>div{flex:1 1 auto;min-width:0;overflow:scroll}.minitabs-wrapper .minitabs{display:flex;border-bottom:1px solid #ccc}.minitabs-wrapper .minitab{flex:1;text-align:center;padding:12px 0;text-decoration:none;color:#333;background-color:#f1f1f1;border:1px solid #ccc;border-bottom:none;cursor:pointer;transition:background-color .3s}.minitabs-wrapper .minitab:hover{background-color:#ddd}.minitabs-wrapper .minitab.active{background-color:#fff;font-weight:bold}@media(min-width: 800px){body.preview-text-enabled #filters-and-triggers>div{display:flex;gap:20px;position:relative}}body.preview-text-enabled #edit-text-filter,body.preview-text-enabled #text-preview{flex:1;align-self:flex-start}body.preview-text-enabled #edit-text-filter #pro-tips{display:none}body.preview-text-enabled #text-preview{position:sticky;top:20px;padding-top:1rem;padding-bottom:1rem;display:block !important}body.preview-text-enabled #activate-text-preview{background-color:var(--color-grey-500)}body.preview-text-enabled .monospace-preview{background:var(--color-background-input);border:1px solid var(--color-grey-600);padding:1rem;color:var(--color-text-input);font-family:"Courier New",Courier,monospace;font-size:70%;word-break:break-word;white-space:pre-wrap}#activate-text-preview{right:0;position:absolute;z-index:3;box-shadow:1px 1px 4px var(--color-shadow-jump)}.watch-table{width:100%;font-size:80%}.watch-table tr{color:var(--color-watch-table-row-text)}.watch-table tr.unviewed{font-weight:bold}.watch-table td{white-space:nowrap}.watch-table td.title-col{word-break:break-all;white-space:normal}.watch-table td a.external::after{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAQElEQVR42qXKwQkAIAxDUUdxtO6/RBQkQZvSi8I/pL4BoGw/XPkh4XigPmsUgh0626AjRsgxHTkUThsG2T/sIlzdTsp52kSS1wAAAABJRU5ErkJggg==);margin:0 3px 0 5px}.watch-table th{white-space:nowrap}.watch-table th a{font-weight:normal}.watch-table th a.active{font-weight:bolder}.watch-table th a.inactive .arrow{display:none}.watch-table tr.checking-now td:first-child{position:relative}.watch-table tr.checking-now td:first-child::before{content:"";position:absolute;top:0;bottom:0;left:0;width:3px;background-color:#293eff}.watch-table tr.checking-now td.last-checked .spinner-wrapper{display:inline-block !important}.watch-table tr.checking-now td.last-checked .innertext{display:none !important}.watch-table tr.queued a.recheck{display:none !important}.watch-table tr.queued a.already-in-queue-button{display:inline-block !important}.watch-table tr.paused a.pause-toggle.state-on{display:inline !important}.watch-table tr.paused a.pause-toggle.state-off{display:none !important}.watch-table tr.notification_muted a.mute-toggle.state-on{display:inline !important}.watch-table tr.notification_muted a.mute-toggle.state-off{display:none !important}.watch-table tr.has-error{color:var(--color-watch-table-error)}.watch-table tr.has-error .error-text{display:block !important}.watch-table tr.single-history a.preview-link{display:inline-block !important}.watch-table tr.multiple-history a.history-link{display:inline-block !important}#watch-table-wrapper #post-list-buttons{text-align:right;padding:0px;margin:0px}#watch-table-wrapper #post-list-buttons li{display:inline-block}#watch-table-wrapper #post-list-buttons a{border-top-left-radius:initial;border-top-right-radius:initial;border-bottom-left-radius:5px;border-bottom-right-radius:5px}#watch-table-wrapper.has-error #post-list-buttons #post-list-with-errors{display:inline-block !important}#watch-table-wrapper.has-unread-changes #post-list-buttons #post-list-unread,#watch-table-wrapper.has-unread-changes #post-list-buttons #post-list-mark-views,#watch-table-wrapper.has-unread-changes #post-list-buttons #post-list-unread{display:inline-block !important}@media(max-width: 767px){.watch-table thead{display:block}.watch-table thead tr th{display:inline-block}}@media(max-width: 767px)and (max-width: 768px){.watch-table thead tr th .hide-on-mobile{display:none}}@media(max-width: 767px){.watch-table thead .empty-cell{display:none}.watch-table .last-checked{margin-left:calc(20px + .5rem)}.watch-table .last-checked>span{vertical-align:middle}.watch-table .last-changed{margin-left:calc(20px + .5rem)}.watch-table .last-checked::before{color:var(--color-text);content:"Last Checked "}.watch-table .last-changed::before{color:var(--color-text);content:"Last Changed "}.watch-table td.inline{display:inline-block}.watch-table .pure-table td,.watch-table .pure-table th{border:none}.watch-table td{border:none;border-bottom:1px solid var(--color-border-watch-table-cell);vertical-align:middle}.watch-table td:before{top:6px;left:6px;width:45%;padding-right:10px;white-space:nowrap}.watch-table.pure-table-striped tr{background-color:var(--color-table-background)}.watch-table.pure-table-striped tr:nth-child(2n-1){background-color:var(--color-table-stripe)}.watch-table.pure-table-striped tr:nth-child(2n-1) td{background-color:inherit}}@media(max-width: 767px){.watch-table tbody tr{padding-bottom:10px;padding-top:10px;display:grid;grid-template-columns:20px 1fr 100px;grid-template-rows:auto auto auto auto;gap:.5rem}.watch-table tbody tr .counter-i{display:none}.watch-table tbody tr td.checkbox-uuid{display:grid;place-items:center}.watch-table tbody tr>td{border-bottom:none}.watch-table tbody tr>td.title-col{grid-column:1/-1;grid-row:1}.watch-table tbody tr>td.title-col .watch-title{font-size:.92rem}.watch-table tbody tr>td.title-col .link-spread{display:none}.watch-table tbody tr>td.last-checked{grid-column:1/-1;grid-row:2}.watch-table tbody tr>td.last-changed{grid-column:1/-1;grid-row:3}.watch-table tbody tr>td.checkbox-uuid{grid-column:1;grid-row:4}.watch-table tbody tr>td.buttons{grid-column:2;grid-row:4;display:flex;align-items:center;justify-content:flex-start}.watch-table tbody tr>td.watch-controls{grid-column:3;grid-row:4;display:grid;place-items:center}.watch-table tbody tr>td.watch-controls a img{padding:10px}.pure-table td{padding:3px !important}}ul#conditions_match_logic{list-style:none}ul#conditions_match_logic input,ul#conditions_match_logic label,ul#conditions_match_logic li{display:inline-block}ul#conditions_match_logic li{padding-right:1em}.fieldlist_formfields{width:100%;background-color:var(--color-background, #fff);border-radius:4px;border:1px solid var(--color-border-table-cell, #cbcbcb)}.fieldlist_formfields .fieldlist-header{display:flex;background-color:var(--color-background-table-thead, #e0e0e0);font-weight:bold;border-bottom:1px solid var(--color-border-table-cell, #cbcbcb)}.fieldlist_formfields .fieldlist-header-cell{flex:1;padding:.5em 1em;text-align:left}.fieldlist_formfields .fieldlist-header-cell:last-child{flex:0 0 120px}.fieldlist_formfields .fieldlist-body{display:flex;flex-direction:column}.fieldlist_formfields .fieldlist-row{display:flex;border-bottom:1px solid var(--color-border-table-cell, #cbcbcb)}.fieldlist_formfields .fieldlist-row:last-child{border-bottom:none}.fieldlist_formfields .fieldlist-row:nth-child(2n-1){background-color:var(--color-table-stripe, #f2f2f2)}.fieldlist_formfields .fieldlist-row.error-row{background-color:var(--color-error-input, #ffdddd)}.fieldlist_formfields .fieldlist-cell{flex:1;padding:.5em 1em;display:flex;flex-direction:column;justify-content:center}.fieldlist_formfields .fieldlist-cell input,.fieldlist_formfields .fieldlist-cell select{width:100%}.fieldlist_formfields .fieldlist-cell.fieldlist-actions{flex:0 0 120px;display:flex;flex-direction:row;align-items:center;gap:4px}.fieldlist_formfields ul.errors{margin-top:.5em;margin-bottom:0;padding:.5em;background-color:var(--color-error-background-snapshot-age, #ffdddd);border-radius:4px;list-style-position:inside}@media only screen and (max-width: 760px){.fieldlist_formfields .fieldlist-header,.fieldlist_formfields .fieldlist-row{flex-direction:column}.fieldlist_formfields .fieldlist-header-cell{display:none}.fieldlist_formfields .fieldlist-row{padding:.5em 0;border-bottom:2px solid var(--color-border-table-cell, #cbcbcb)}.fieldlist_formfields .fieldlist-cell{padding:.25em .5em}.fieldlist_formfields .fieldlist-cell.fieldlist-actions{flex:1;justify-content:flex-start;padding-top:.5em}.fieldlist_formfields .fieldlist-cell:not(:last-child){margin-bottom:.5em}.fieldlist_formfields .fieldlist-cell::before{content:attr(data-label);font-weight:bold;margin-bottom:.25em}}.fieldlist_formfields .addRuleRow,.fieldlist_formfields .removeRuleRow,.fieldlist_formfields .verifyRuleRow{cursor:pointer;border:none;padding:4px 8px;border-radius:3px;font-weight:bold;background-color:#aaa;color:var(--color-foreground-text, #fff)}.fieldlist_formfields .addRuleRow:hover,.fieldlist_formfields .removeRuleRow:hover,.fieldlist_formfields .verifyRuleRow:hover{background-color:#999}.watch-table.favicon-not-enabled tr .favicon{display:none}.watch-table tr td.inline.title-col .flex-wrapper{display:flex;align-items:center;gap:4px}.watch-table td,.watch-table th{vertical-align:middle}.watch-table tr.has-favicon.unviewed img.favicon{opacity:1 !important}.watch-table .status-icons{white-space:nowrap;display:flex;align-items:center;gap:4px}.watch-table .status-icons>*{vertical-align:middle}.title-col{padding:10px}.title-wrapper{display:flex;align-items:center;gap:10px}.title-col-inner{display:inline-block;vertical-align:middle}.watch-table img.favicon{vertical-align:middle;max-width:25px;max-height:25px;height:25px;padding-right:4px}body.checking-now #checking-now-fixed-tab{display:block !important}#checking-now-fixed-tab{background:#ccc;border-radius:5px;bottom:0;color:var(--color-text);display:none;font-size:.8rem;left:0;padding:5px;position:fixed}#selector-wrapper{height:100%;text-align:center;max-height:70vh;overflow-y:scroll;position:relative}#selector-wrapper>img{position:absolute;z-index:4;max-width:100%}#selector-wrapper>canvas{position:relative;z-index:5;max-width:100%}#selector-wrapper>canvas:hover{cursor:pointer}#selector-current-xpath{font-size:80%}.ternary-radio-group{display:flex;gap:0;border:1px solid var(--color-grey-750);border-radius:4px;overflow:hidden;width:fit-content;background:var(--color-background)}.ternary-radio-group .ternary-radio-option{position:relative;cursor:pointer;margin:0;display:flex;align-items:center}.ternary-radio-group .ternary-radio-option input[type=radio]{position:absolute;opacity:0;width:0;height:0}.ternary-radio-group .ternary-radio-option .ternary-radio-label{padding:8px 16px;background:var(--color-grey-900);border:none;border-right:1px solid var(--color-grey-750);font-size:13px;font-weight:500;color:var(--color-text);transition:all .2s ease;cursor:pointer;display:block;text-align:center}.ternary-radio-group .ternary-radio-option:last-child .ternary-radio-label{border-right:none}.ternary-radio-group .ternary-radio-option input:checked+.ternary-radio-label{background:var(--color-link);color:var(--color-text-button);font-weight:600}.ternary-radio-group .ternary-radio-option input:checked+.ternary-radio-label.ternary-default{background:var(--color-grey-600);color:var(--color-text-button)}.ternary-radio-group .ternary-radio-option input:checked+.ternary-radio-label:hover{background:#1a7bc4}.ternary-radio-group .ternary-radio-option input:checked+.ternary-radio-label:hover.ternary-default{background:var(--color-grey-500)}.ternary-radio-group .ternary-radio-option:hover .ternary-radio-label{background:var(--color-grey-800)}@media(max-width: 480px){.ternary-radio-group{width:100%}.ternary-radio-group .ternary-radio-label{flex:1;min-width:auto}}input[type=radio].pure-radio:checked+label,input[type=radio].pure-radio:checked{background:var(--color-link);color:var(--color-text-button)}html[data-darkmode=true] .ternary-radio-group .ternary-radio-option .ternary-radio-label{background:var(--color-grey-350)}html[data-darkmode=true] .ternary-radio-group .ternary-radio-option:hover .ternary-radio-label{background:var(--color-grey-400)}html[data-darkmode=true] .ternary-radio-group .ternary-radio-option input:checked+.ternary-radio-label{background:var(--color-link);color:var(--color-text-button)}html[data-darkmode=true] .ternary-radio-group .ternary-radio-option input:checked+.ternary-radio-label.ternary-default{background:var(--color-grey-600)}html[data-darkmode=true] .ternary-radio-group .ternary-radio-option input:checked+.ternary-radio-label:hover{background:#1a7bc4}html[data-darkmode=true] .ternary-radio-group .ternary-radio-option input:checked+.ternary-radio-label:hover.ternary-default{background:var(--color-grey-500)}body.processor-image_ssim_diff #edit-text-filter .text-filtering{display:none}body.processor-image_ssim_diff #conditions-tab{display:none}.modal-dialog{border:none;border-radius:10px;padding:0;background:var(--color-background);color:var(--color-text);box-shadow:0 5px 20px rgba(0,0,0,.3);max-width:500px;width:90%}.modal-dialog::backdrop{background:rgba(0,0,0,.6);backdrop-filter:blur(3px);animation:fadeIn .2s ease-out}.modal-dialog[open]{animation:slideIn .25s ease-out}.modal-dialog .modal-header{padding:1.5rem;border-bottom:1px solid var(--color-border-table-cell);display:flex;align-items:center;gap:1rem}.modal-dialog .modal-header .modal-icon{font-size:2rem;line-height:1;flex-shrink:0}.modal-dialog .modal-header .modal-icon.warning{color:var(--color-warning)}.modal-dialog .modal-header .modal-icon.danger{color:var(--color-background-button-error)}.modal-dialog .modal-header .modal-icon.info{color:var(--color-background-button-primary)}.modal-dialog .modal-header .modal-title{font-size:1.3rem;font-weight:bold;margin:0;color:var(--color-text)}.modal-dialog .modal-body{padding:1.5rem;line-height:1.6}.modal-dialog .modal-body p{margin:0 0 1rem 0}.modal-dialog .modal-body p:last-child{margin-bottom:0}.modal-dialog .modal-body strong{color:var(--color-text);font-weight:600}.modal-dialog .modal-footer{padding:1rem 1.5rem;border-top:1px solid var(--color-border-table-cell);display:flex;gap:.75rem;justify-content:flex-end;background:var(--color-grey-900)}.modal-dialog .modal-footer button{padding:.6rem 1.5rem;border:none;border-radius:4px;cursor:pointer;font-weight:500;transition:all .2s ease;font-size:.95rem}.modal-dialog .modal-footer button:hover{transform:translateY(-1px);box-shadow:0 2px 8px rgba(0,0,0,.15)}.modal-dialog .modal-footer button:active{transform:translateY(0)}.modal-dialog .modal-footer button.modal-btn-cancel{background:var(--color-background-button-cancel);color:var(--color-grey-200)}.modal-dialog .modal-footer button.modal-btn-cancel:hover{background:var(--color-grey-700)}.modal-dialog .modal-footer button.modal-btn-confirm{background:var(--color-background-button-primary);color:var(--color-white)}.modal-dialog .modal-footer button.modal-btn-confirm:hover{opacity:.9}.modal-dialog .modal-footer button.modal-btn-danger{background:var(--color-background-button-error);color:var(--color-white)}.modal-dialog .modal-footer button.modal-btn-danger:hover{background:var(--color-dark-red)}.modal-dialog .modal-footer button.modal-btn-warning{background:var(--color-background-button-warning);color:var(--color-white)}.modal-dialog .modal-footer button.modal-btn-warning:hover{opacity:.9}html[data-darkmode=true] .modal-dialog{box-shadow:0 5px 30px rgba(0,0,0,.7)}html[data-darkmode=true] .modal-dialog .modal-footer{background:var(--color-grey-200)}@keyframes fadeIn{from{opacity:0}to{opacity:1}}@keyframes slideIn{from{opacity:0;transform:translateY(-20px) scale(0.95)}to{opacity:1;transform:translateY(0) scale(1)}}@media only screen and (max-width: 760px){.modal-dialog{width:95%;max-width:none}.modal-dialog .modal-header{padding:1rem}.modal-dialog .modal-header .modal-title{font-size:1.1rem}.modal-dialog .modal-body{padding:1rem;font-size:.95rem}.modal-dialog .modal-footer{padding:.75rem 1rem;flex-wrap:wrap}.modal-dialog .modal-footer button{flex:1;min-width:120px}}#language-selector-flag{display:inline-block;width:1.2em;height:1.2em;vertical-align:middle;border-radius:50%;overflow:hidden;opacity:.6}#language-selector-flag:hover{opacity:1}.language-list{display:flex;flex-direction:column;gap:.5rem;padding:.5rem 0}.language-option{display:flex;align-items:center;gap:1rem;padding:.25rem;border-radius:4px;transition:background-color .2s ease;text-decoration:none;color:var(--color-text);border:1px solid rgba(0,0,0,0)}.language-option:hover{background-color:var(--color-background-menu-link-hover);border-color:var(--color-border-table-cell)}.language-option.active{background-color:var(--color-link);color:var(--color-text-button);font-weight:600}.language-option .flag{font-size:1.5rem;flex-shrink:0}.language-option .language-name{flex-grow:1;font-size:1rem}#language-modal .language-list .lang-option{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;margin-right:.5em;border-radius:50%;overflow:hidden}.content-wrapper{display:flex;gap:0;width:100%;max-width:100%;position:relative}@media only screen and (max-width: 900px){.content-wrapper{flex-direction:column}}.action-sidebar{position:sticky;top:100px;flex-shrink:0;width:80px;height:fit-content;background:rgba(0,0,0,0);padding:1.5rem 0;display:flex;flex-direction:column;gap:.5rem;align-items:center;z-index:0}@media only screen and (max-width: 900px){.action-sidebar{position:relative;top:0;width:100%;flex-direction:row;justify-content:space-around;padding:0;overflow-x:auto}}.action-sidebar-item{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.35rem;padding:.75rem .5rem;min-width:64px;text-decoration:none;opacity:.8;transition:opacity .2s ease}.action-sidebar-item:hover{opacity:1}.action-sidebar-item.active{opacity:1}.action-sidebar-item.active .action-icon{stroke:#fff;stroke-width:2.5}.action-sidebar-item.active .action-label{color:#fff;font-weight:700}.action-icon{width:28px;height:28px;stroke:#fff;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round;transition:stroke .2s ease}.action-label{font-size:.65rem;font-weight:500;text-align:center;line-height:1.1;letter-spacing:.02em;text-transform:uppercase;color:#fff;transition:color .2s ease;max-width:60px;word-wrap:break-word}.content-main{flex:0 1 auto;width:100%;min-width:0;padding:0;display:flex;flex-direction:column;align-items:center}.hamburger-menu{display:none;background:rgba(0,0,0,0);border:none;cursor:pointer;padding:.5rem;z-index:10001;position:relative}@media only screen and (max-width: 980px){.hamburger-menu{display:flex;flex-direction:column;justify-content:center;align-items:center}}.hamburger-icon{width:24px;height:20px;position:relative;display:flex;flex-direction:column;justify-content:space-between}.hamburger-icon span{display:block;height:3px;width:100%;background:var(--color-text);border-radius:2px;transition:all .3s cubic-bezier(0.68, -0.55, 0.265, 1.55);transform-origin:center}.hamburger-menu.active .hamburger-icon span:nth-child(1){transform:translateY(8.5px) rotate(45deg)}.hamburger-menu.active .hamburger-icon span:nth-child(2){opacity:0;transform:translateX(-10px)}.hamburger-menu.active .hamburger-icon span:nth-child(3){transform:translateY(-8.5px) rotate(-45deg)}.mobile-menu-overlay{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.5);z-index:9999;opacity:0;transition:opacity .3s ease}.mobile-menu-overlay.active{display:block;opacity:1}.mobile-menu-drawer{position:fixed;top:0;right:-280px;width:280px;height:100%;background:var(--color-background);opacity:1;box-shadow:-2px 0 8px rgba(0,0,0,.15);z-index:10000;transition:right .3s cubic-bezier(0.68, -0.55, 0.265, 1.55);overflow-y:auto;padding-top:60px}.mobile-menu-drawer.active{right:0}.mobile-menu-drawer .mobile-menu-items{list-style:none;padding:1rem 0;margin:0}.mobile-menu-drawer .mobile-menu-items li{border-bottom:1px solid var(--color-border-table-cell)}.mobile-menu-drawer .mobile-menu-items li>*{display:block;padding:1rem 1.5rem;color:var(--color-text);text-decoration:none;font-weight:500;transition:background .2s ease}.mobile-menu-drawer .mobile-menu-items li>*:hover{background:var(--color-background-menu-link-hover)}.logo-cdio{font-weight:bold;font-size:1.1rem}.logo-cdio .logo-cd{color:var(--color-grey-500)}.logo-cdio .logo-io{color:var(--color-text)}.menu-always-visible{display:flex;align-items:center;gap:.5rem;margin-left:auto}@media only screen and (max-width: 980px){#top-right-menu .menu-collapsible{display:none !important}.pure-menu-horizontal{overflow-x:visible !important}#nav-menu{overflow-x:visible !important}}@media only screen and (min-width: 1025px){.hamburger-menu,.mobile-menu-drawer,.mobile-menu-overlay{display:none !important}}html[data-darkmode=true] .mobile-menu-drawer{box-shadow:-2px 0 8px rgba(0,0,0,.4)}#search-modal .modal-body{padding:2rem 1.5rem}#search-modal .modal-body .pure-control-group{padding-bottom:0}#search-modal .modal-body .pure-control-group label{display:block;margin-bottom:.5rem;font-size:.9rem;font-weight:600;color:var(--color-text)}#search-modal .modal-body .pure-control-group #search-modal-input{width:100%;max-width:100%;box-sizing:border-box;padding:.6rem .8rem;font-size:1rem;border:1px solid var(--color-border-input);border-radius:4px;background-color:var(--color-background-input);color:var(--color-text-input);box-shadow:inset 0 1px 3px var(--color-shadow-input);transition:border-color .2s ease,box-shadow .2s ease}#search-modal .modal-body .pure-control-group #search-modal-input:focus{outline:none;border-color:var(--color-link);box-shadow:0 0 0 3px rgba(27,152,248,.1)}#search-modal .modal-body .pure-control-group #search-modal-input::placeholder{color:var(--color-text-input-placeholder);opacity:.7}html[data-darkmode=true] #search-modal #search-modal-input:focus{box-shadow:0 0 0 3px rgba(89,189,251,.15)}.action-sidebar-item{position:relative}.action-sidebar-item .notification-bubble{position:absolute;top:8px;left:8px;min-width:18px;height:18px;background:#f44;color:#fff;font-size:10px;font-weight:700;line-height:18px;text-align:center;border-radius:9px;padding:0 2px;box-shadow:0 2px 4px rgba(0,0,0,.3);pointer-events:none;transition:all .2s ease;display:none}.action-sidebar-item .notification-bubble.red-bubble{background:#f44}.action-sidebar-item .notification-bubble.blue-bubble{background:#4a9eff;color:#fff}.action-sidebar-item .notification-bubble.visible{display:block}.action-sidebar-item .notification-bubble.pulse{animation:bubblePulse .4s ease-out}.action-sidebar-item .notification-bubble.large-number{font-size:8px;min-width:20px;height:20px;line-height:20px;border-radius:10px}@keyframes bubblePulse{0%{transform:scale(1)}50%{transform:scale(1.3)}100%{transform:scale(1)}}html[data-darkmode=true] .notification-bubble{box-shadow:0 2px 6px rgba(0,0,0,.6)}.toast-container{position:fixed;display:flex;flex-direction:column;gap:.75rem;pointer-events:none;z-index:10000}.toast-container.toast-top-right{top:20px;right:20px}.toast-container.toast-top-center{top:100px;left:50%;transform:translateX(-50%)}.toast-container.toast-top-left{top:20px;left:20px}.toast-container.toast-bottom-right{bottom:20px;right:20px}.toast-container.toast-bottom-center{bottom:20px;left:50%;transform:translateX(-50%)}.toast-container.toast-bottom-left{bottom:20px;left:20px}.toast{position:relative;display:flex;align-items:center;gap:.75rem;min-width:300px;max-width:500px;padding:1rem 1.25rem;background:var(--color-background);border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,.15),0 0 0 1px rgba(0,0,0,.05);pointer-events:auto;overflow:hidden;opacity:0;transform:translateY(-50px);transition:all .3s cubic-bezier(0.68, -0.55, 0.265, 1.55);font-family:inherit}.toast.toast-show{opacity:1;transform:translateY(0)}.toast.toast-hide{opacity:0;transform:translateY(-50px) scale(0.95)}.toast.toast-success{border-left:4px solid #10b981}.toast.toast-success .toast-icon{color:#10b981}.toast.toast-error{border-left:4px solid #ef4444}.toast.toast-error .toast-icon{color:#ef4444}.toast.toast-warning{border-left:4px solid #f59e0b}.toast.toast-warning .toast-icon{color:#f59e0b}.toast.toast-info{border-left:4px solid #3b82f6}.toast.toast-info .toast-icon{color:#3b82f6}.toast.toast-default{border-left:4px solid var(--color-grey-500)}.toast-icon{flex-shrink:0;width:24px;height:24px}.toast-icon svg{width:100%;height:100%}.toast-message{flex:1;font-size:.875rem;line-height:1.5;color:var(--color-text);word-break:break-word;font-family:inherit}.toast-close{flex-shrink:0;width:24px;height:24px;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,0);border:none;border-radius:4px;color:var(--color-grey-500);font-size:1.5rem;line-height:1;cursor:pointer;transition:all .2s ease;padding:0;margin-left:.25rem}.toast-close:hover{background:var(--color-grey-800);color:var(--color-text)}.toast-close:active{transform:scale(0.95)}.toast-progress{position:absolute;bottom:0;left:0;right:0;height:3px;background:currentColor;opacity:.3;transform-origin:left;transition:transform linear}html[data-darkmode=true] .toast{background:var(--color-grey-300);box-shadow:0 4px 12px rgba(0,0,0,.4),0 0 0 1px hsla(0,0%,100%,.05)}html[data-darkmode=true] .toast-close:hover{background:var(--color-grey-400)}@media only screen and (max-width: 768px){.toast-container{left:10px !important;right:10px !important;top:10px !important;transform:none !important;align-items:stretch}.toast-container.toast-bottom-right,.toast-container.toast-bottom-center,.toast-container.toast-bottom-left{top:auto !important;bottom:10px !important}.toast{min-width:auto;max-width:none;width:100%;transform:translateY(-100px)}.toast.toast-show{transform:translateY(0)}.toast.toast-hide{transform:translateY(-100px) scale(0.95)}}@media(prefers-reduced-motion: reduce){.toast{transition:opacity .2s ease;transform:none !important}.toast.toast-show{opacity:1}.toast.toast-hide{opacity:0}}.login-form{min-height:52vh;display:flex;align-items:center;justify-content:center;padding:2rem 1rem}.login-form .inner{background:var(--color-background);border-radius:16px;box-shadow:0 10px 40px rgba(0,0,0,.08),0 2px 8px rgba(0,0,0,.04);padding:3rem 2.5rem;width:100%;max-width:420px;position:relative;overflow:hidden;transition:transform .3s ease,box-shadow .3s ease}.login-form .inner:hover{box-shadow:0 15px 50px rgba(0,0,0,.12),0 5px 15px rgba(0,0,0,.06)}.login-form form{margin:0}.login-form fieldset{border:none;padding:0;margin:0}.login-form .pure-control-group{margin-bottom:1.75rem}.login-form .pure-control-group:last-of-type{margin-bottom:0;margin-top:2rem}.login-form label{display:block;margin-bottom:.5rem;font-weight:600;font-size:.9rem;color:var(--color-text);letter-spacing:.01em}.login-form input[type=password]{width:100%;padding:.875rem 1rem;border:2px solid var(--color-grey-800);border-radius:8px;font-size:1rem;background:var(--color-background-input);color:var(--color-text-input);transition:all .2s ease;box-sizing:border-box}.login-form input[type=password]:focus{outline:none;border-color:var(--color-link);box-shadow:0 0 0 3px rgba(27,152,248,.1);transform:translateY(-1px)}.login-form input[type=password]::placeholder{color:var(--color-text-input-placeholder)}.login-form button[type=submit]{width:100%;padding:.875rem 1.5rem;font-size:1rem;font-weight:600;border-radius:8px;border:none;background:var(--color-background-button-primary);color:var(--color-text-button);cursor:pointer;transition:all .2s ease;box-shadow:0 2px 8px rgba(27,152,248,.2)}.login-form button[type=submit]:hover{box-shadow:0 4px 12px rgba(27,152,248,.3);background:#06c}.login-form button[type=submit]:active{transform:translateY(0);box-shadow:0 2px 4px rgba(27,152,248,.2)}.content-main>ul.messages{position:fixed;top:120px;left:50%;transform:translateX(-50%);list-style:none;padding:0;margin:0;z-index:1000;min-width:300px;max-width:500px}.content-main>ul.messages li{padding:1rem 1.25rem;border-radius:8px;font-size:.95rem;line-height:1.5;font-weight:500;box-shadow:0 4px 12px rgba(0,0,0,.15);animation:slideDown .3s ease-out;border:2px solid rgba(0,0,0,0)}.content-main>ul.messages li.error{background:#fee;border:2px solid #ef4444;color:#991b1b;font-weight:600}.content-main>ul.messages li.success{background:#f0fdf4;border:2px solid #10b981;color:#166534}.content-main>ul.messages li.info,.content-main>ul.messages li.message{background:#eff6ff;border:2px solid #3b82f6;color:#1e40af}@keyframes slideDown{from{opacity:0;transform:translateY(-20px)}to{opacity:1;transform:translateY(0)}}html[data-darkmode=true] .login-form .inner{box-shadow:0 10px 40px rgba(0,0,0,.4),0 2px 8px rgba(0,0,0,.2)}html[data-darkmode=true] .login-form .inner:hover{box-shadow:0 15px 50px rgba(0,0,0,.5),0 5px 15px rgba(0,0,0,.3)}html[data-darkmode=true] .login-form input[type=password]{border-color:var(--color-grey-400)}html[data-darkmode=true] .login-form input[type=password]:focus{border-color:var(--color-link)}html[data-darkmode=true] .content-main>ul.messages li{box-shadow:0 4px 12px rgba(0,0,0,.4)}html[data-darkmode=true] .content-main>ul.messages li.error{background:#4a1d1d;border-color:#ef4444;color:#fca5a5}html[data-darkmode=true] .content-main>ul.messages li.success{background:#1a3a2a;border-color:#10b981;color:#86efac}html[data-darkmode=true] .content-main>ul.messages li.info,html[data-darkmode=true] .content-main>ul.messages li.message{background:#1e3a5f;border-color:#3b82f6;color:#93c5fd}@media only screen and (max-width: 768px){.login-form{min-height:auto;padding:1rem .5rem;padding-top:5rem}.login-form .inner{padding:2rem 1.5rem;border-radius:12px}.content-main>ul.messages{top:70px;left:10px;right:10px;transform:none;min-width:auto}}body.wrapped-tabs .tabs ul{grid-template-columns:repeat(auto-fill, minmax(var(--tab-width, 180px), 1fr));grid-auto-flow:row;grid-auto-columns:unset;gap:0;column-gap:5px}body.wrapped-tabs .tabs ul li{border-radius:0}.tabs ul{margin:0px;padding:0px;display:grid;grid-auto-flow:column;grid-auto-columns:max-content;gap:5px;list-style:none}.tabs ul li{white-space:nowrap;color:var(--color-text-tab);border-top-left-radius:5px;border-top-right-radius:5px;background-color:var(--color-background-tab)}.tabs ul li:not(.active):hover{background-color:var(--color-background-tab-hover)}.tabs ul li.active,.tabs ul li :target{background-color:var(--color-background)}.tabs ul li.active a,.tabs ul li :target a{color:var(--color-text-tab-active);font-weight:bold}.tabs ul li a{display:block;padding:.7em;color:var(--color-text-tab)}body{color:var(--color-text);background:var(--color-background-page);font-family:Helvetica Neue,Helvetica,Lucida Grande,Arial,Ubuntu,Cantarell,Fira Sans,sans-serif}.visually-hidden{clip:rect(0 0 0 0);clip-path:inset(50%);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px}.status-icon{display:inline-block;height:1rem;vertical-align:middle}.pure-table-even{background:var(--color-background)}a{text-decoration:none;color:var(--color-link)}a.github-link{color:var(--color-icon-github);margin:0 1rem 0 .5rem}a.github-link svg{fill:currentColor}a.github-link:hover{color:var(--color-icon-github-hover)}#search-result-info{color:#fff}button.toggle-button{vertical-align:middle;background:rgba(0,0,0,0);border:none;cursor:pointer;color:var(--color-icon-github)}button.toggle-button:hover{color:var(--color-icon-github-hover)}button.toggle-button svg{fill:currentColor}button.toggle-button .icon-light{display:block}.pure-menu-horizontal{background:var(--color-background);padding:5px;display:flex;justify-content:space-between;align-items:center}#pure-menu-horizontal-spinner{height:3px;background:linear-gradient(-75deg, #ff6000, #ff8f00, #ffdd00, #ed0000);background-size:400% 400%;width:100%;animation:gradient 200s ease infinite}body.spinner-active #pure-menu-horizontal-spinner{animation:gradient 1s ease infinite}@keyframes gradient{0%{background-position:0% 50%}50%{background-position:100% 50%}100%{background-position:0% 50%}}.pure-menu-heading{color:var(--color-text-menu-heading)}.pure-menu-link{color:var(--color-text-menu-link)}.pure-menu-link:hover{background-color:var(--color-background-menu-link-hover);color:var(--color-text-menu-link-hover)}.tab-pane-inner{scroll-margin-top:200px}section.content{padding-bottom:1em;flex-direction:column;display:flex;align-items:center;justify-content:center}@media only screen and (max-width: 980px){section.content{padding-top:80px}}@media only screen and (min-width: 980px){section.content{padding-top:100px}}code{background:var(--color-background-code);color:var(--color-text)}.inline-tag,.restock-label,.tracking-ldjson-price-data,.watch-tag-list,.processor-badge{white-space:nowrap;border-radius:5px;padding:2px 5px;margin-right:4px;line-height:1.2rem}.processor-badge{font-weight:900}.watch-tag-list{color:var(--color-white);background:var(--color-text-watch-tag-list)}@media(min-width: 768px){.box{margin:0 1em !important}}.box{max-width:100%;margin:0 .3em;flex-direction:column;display:flex;justify-content:center}body:after{content:"";background:linear-gradient(130deg, var(--color-background-gradient-first), var(--color-background-gradient-second) 41.07%, var(--color-background-gradient-third) 84.05%)}body:after,body:before{display:block;height:650px;position:absolute;top:0;left:0;width:100%;z-index:-1}body::after{opacity:.91}body::before{content:""}body:after,body:before{-webkit-clip-path:polygon(100% 0, 0 0, 0 77.5%, 1% 77.4%, 2% 77.1%, 3% 76.6%, 4% 75.9%, 5% 75.05%, 6% 74.05%, 7% 72.95%, 8% 71.75%, 9% 70.55%, 10% 69.3%, 11% 68.05%, 12% 66.9%, 13% 65.8%, 14% 64.8%, 15% 64%, 16% 63.35%, 17% 62.85%, 18% 62.6%, 19% 62.5%, 20% 62.65%, 21% 63%, 22% 63.5%, 23% 64.2%, 24% 65.1%, 25% 66.1%, 26% 67.2%, 27% 68.4%, 28% 69.65%, 29% 70.9%, 30% 72.15%, 31% 73.3%, 32% 74.35%, 33% 75.3%, 34% 76.1%, 35% 76.75%, 36% 77.2%, 37% 77.45%, 38% 77.5%, 39% 77.3%, 40% 76.95%, 41% 76.4%, 42% 75.65%, 43% 74.75%, 44% 73.75%, 45% 72.6%, 46% 71.4%, 47% 70.15%, 48% 68.9%, 49% 67.7%, 50% 66.55%, 51% 65.5%, 52% 64.55%, 53% 63.75%, 54% 63.15%, 55% 62.75%, 56% 62.55%, 57% 62.5%, 58% 62.7%, 59% 63.1%, 60% 63.7%, 61% 64.45%, 62% 65.4%, 63% 66.45%, 64% 67.6%, 65% 68.8%, 66% 70.05%, 67% 71.3%, 68% 72.5%, 69% 73.6%, 70% 74.65%, 71% 75.55%, 72% 76.35%, 73% 76.9%, 74% 77.3%, 75% 77.5%, 76% 77.45%, 77% 77.25%, 78% 76.8%, 79% 76.2%, 80% 75.4%, 81% 74.45%, 82% 73.4%, 83% 72.25%, 84% 71.05%, 85% 69.8%, 86% 68.55%, 87% 67.35%, 88% 66.2%, 89% 65.2%, 90% 64.3%, 91% 63.55%, 92% 63%, 93% 62.65%, 94% 62.5%, 95% 62.55%, 96% 62.8%, 97% 63.3%, 98% 63.9%, 99% 64.75%, 100% 65.7%);clip-path:polygon(100% 0, 0 0, 0 77.5%, 1% 77.4%, 2% 77.1%, 3% 76.6%, 4% 75.9%, 5% 75.05%, 6% 74.05%, 7% 72.95%, 8% 71.75%, 9% 70.55%, 10% 69.3%, 11% 68.05%, 12% 66.9%, 13% 65.8%, 14% 64.8%, 15% 64%, 16% 63.35%, 17% 62.85%, 18% 62.6%, 19% 62.5%, 20% 62.65%, 21% 63%, 22% 63.5%, 23% 64.2%, 24% 65.1%, 25% 66.1%, 26% 67.2%, 27% 68.4%, 28% 69.65%, 29% 70.9%, 30% 72.15%, 31% 73.3%, 32% 74.35%, 33% 75.3%, 34% 76.1%, 35% 76.75%, 36% 77.2%, 37% 77.45%, 38% 77.5%, 39% 77.3%, 40% 76.95%, 41% 76.4%, 42% 75.65%, 43% 74.75%, 44% 73.75%, 45% 72.6%, 46% 71.4%, 47% 70.15%, 48% 68.9%, 49% 67.7%, 50% 66.55%, 51% 65.5%, 52% 64.55%, 53% 63.75%, 54% 63.15%, 55% 62.75%, 56% 62.55%, 57% 62.5%, 58% 62.7%, 59% 63.1%, 60% 63.7%, 61% 64.45%, 62% 65.4%, 63% 66.45%, 64% 67.6%, 65% 68.8%, 66% 70.05%, 67% 71.3%, 68% 72.5%, 69% 73.6%, 70% 74.65%, 71% 75.55%, 72% 76.35%, 73% 76.9%, 74% 77.3%, 75% 77.5%, 76% 77.45%, 77% 77.25%, 78% 76.8%, 79% 76.2%, 80% 75.4%, 81% 74.45%, 82% 73.4%, 83% 72.25%, 84% 71.05%, 85% 69.8%, 86% 68.55%, 87% 67.35%, 88% 66.2%, 89% 65.2%, 90% 64.3%, 91% 63.55%, 92% 63%, 93% 62.65%, 94% 62.5%, 95% 62.55%, 96% 62.8%, 97% 63.3%, 98% 63.9%, 99% 64.75%, 100% 65.7%)}.button-small{font-size:85%}.button-xsmall{font-size:70%}.fetch-error{padding-top:1em;font-size:80%;max-width:400px;display:block}.pure-button-primary,a.pure-button-primary,.pure-button-selected,a.pure-button-selected{background-color:var(--color-background-button-primary)}.button-secondary{color:var(--color-text-button);border-radius:4px;text-shadow:0 1px 1px rgba(0,0,0,.2)}.button-success{background:var(--color-background-button-success)}.button-tag{background:var(--color-background-button-tag);color:var(--color-text-button);font-size:65%;border-bottom-left-radius:initial;border-bottom-right-radius:initial;margin-right:4px}.button-tag.active{background:var(--color-background-button-tag-active);font-weight:bold}.button-error{background:var(--color-background-button-error);color:var(--color-text-button-error)}.button-warning{background:var(--color-background-button-warning);color:var(--color-text-button-warning)}.button-secondary{background:var(--color-background-button-secondary)}.button-cancel{background:var(--color-background-button-cancel)}.messages li{list-style:none;padding:1em;border-radius:10px;color:var(--color-text-messages);font-weight:bold}.messages li.message{background:var(--color-background-messages-message)}.messages li.error{background:var(--color-background-messages-error)}.messages li.notice{background:var(--color-background-messages-notice)}.messages.with-share-link>*:hover{cursor:pointer}.notifications-wrapper{padding-top:.5rem}.notifications-wrapper #notification-test-log{margin-top:1rem;padding:1rem;white-space:pre-wrap;word-break:break-word;overflow-wrap:break-word;max-width:100%;box-sizing:border-box;max-height:12rem;overflow-y:scroll;border:1px solid var(--color-border-notification);border-radius:5px}label:hover{cursor:pointer}.grey-form-border{border:1px solid var(--color-border-notification);padding:.5rem;border-radius:5px}#notification-error-log{border:1px solid var(--color-border-notification);padding:1rem;border-radius:5px;overflow-wrap:break-word}#token-table.pure-table td,#token-table.pure-table th{font-size:80%}.pure-form input[type=text].transparent-field{background-color:var(--color-background-new-watch-input-transparent) !important;color:var(--color-white) !important;border:1px solid hsla(0,0%,100%,.2) !important;box-shadow:none !important;-webkit-box-shadow:none !important}.pure-form input[type=text].transparent-field::placeholder{opacity:.5;color:hsla(0,0%,100%,.7);font-weight:lighter}#new-watch-form{background:var(--color-background-new-watch-form);padding:1em;border-radius:10px;margin-bottom:1em;max-width:100%}#new-watch-form #url::placeholder{font-weight:bold}#new-watch-form input{display:inline-block;margin-bottom:5px}#new-watch-form input:not(.pure-button){background-color:var(--color-background-new-watch-input);color:var(--color-text-new-watch-input)}#new-watch-form .label{display:none}#new-watch-form legend{color:var(--color-text-legend);font-weight:bold}@media only screen and (min-width: 760px){#new-watch-form #watch-add-wrapper-zone{display:flex;gap:.3rem;flex-direction:row;min-width:70vw}}#new-watch-form #watch-add-wrapper-zone>span{flex-grow:0}#new-watch-form #watch-add-wrapper-zone>span input{width:100%;padding-right:1em}#new-watch-form #watch-add-wrapper-zone>span:first-child{flex-grow:1}@media only screen and (max-width: 760px){#new-watch-form #watch-add-wrapper-zone #url{width:100%}}#new-watch-form #watch-group-tag{font-size:.9rem;padding:.3rem;display:flex;align-items:center;gap:.5rem;color:var(--color-white)}#new-watch-form #watch-group-tag label,#new-watch-form #watch-group-tag input{margin:0}#new-watch-form #watch-group-tag input{flex:1}#diff-col{padding-left:40px}#diff-jump{position:fixed;left:0px;top:120px;background:var(--color-background);padding:10px;border-top-right-radius:5px;border-bottom-right-radius:5px;box-shadow:1px 1px 4px var(--color-shadow-jump)}#diff-jump a{color:var(--color-link);cursor:pointer;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;-o-user-select:none}footer{padding:10px;background:var(--color-background);color:var(--color-text-footer);text-align:center}#feed-icon{vertical-align:middle}.sticky-tab{position:absolute;top:60px;font-size:65%;background:var(--color-background);padding:10px}@media only screen and (max-width: 980px){.sticky-tab{display:none}}.sticky-tab#left-sticky{left:0;position:fixed;border-top-right-radius:5px;border-bottom-right-radius:5px;box-shadow:1px 1px 4px var(--color-shadow-jump)}.sticky-tab#right-sticky{right:0px}.sticky-tab#hosted-sticky{right:0px;top:100px;font-weight:bold}#new-version-text a{color:var(--color-link-new-version)}.watch-controls{color:#f8321b}.watch-controls .state-on img{opacity:.8}.watch-controls img{opacity:.2}.watch-controls img:hover{transition:opacity .3s;opacity:.8}.monospaced-textarea textarea{width:100%;font-family:monospace;white-space:pre;overflow-wrap:normal;overflow-x:auto}.pure-form fieldset{padding-top:0px}.pure-form fieldset ul{padding-bottom:0px;margin-bottom:0px}.pure-form .pure-control-group,.pure-form .pure-group,.pure-form .pure-controls{padding-bottom:1em}.pure-form .pure-control-group div,.pure-form .pure-group div,.pure-form .pure-controls div{margin:0px}.pure-form .pure-control-group .checkbox>*,.pure-form .pure-group .checkbox>*,.pure-form .pure-controls .checkbox>*{display:inline;vertical-align:middle}.pure-form .pure-control-group .checkbox>label,.pure-form .pure-group .checkbox>label,.pure-form .pure-controls .checkbox>label{padding-left:5px}.pure-form .pure-control-group legend,.pure-form .pure-group legend,.pure-form .pure-controls legend{color:var(--color-text-legend)}.pure-form .error input{background-color:var(--color-error-input)}.pure-form ul.errors{padding:.5em .6em;border:1px solid var(--color-error-list);border-radius:4px;vertical-align:middle;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form ul.errors li{margin-left:1em;color:var(--color-error-list)}.pure-form label{font-weight:bold}.pure-form textarea{width:100%}.pure-form .inline-radio ul{margin:0px;list-style:none}.pure-form .inline-radio ul li{display:flex;align-items:center;gap:1em}@media only screen and (max-width: 760px),(min-device-width: 768px)and (max-device-width: 980px){.edit-form{padding:.5em;margin:0}#nav-menu{overflow-x:scroll}}@media only screen and (max-width: 760px),(min-device-width: 768px)and (max-device-width: 980px){input[type=text]{width:100%}}.pure-table{border-color:var(--color-border-table-cell)}.pure-table thead{background-color:var(--color-background-table-thead);color:var(--color-text);border-bottom:1px solid var(--color-background-table-thead)}.pure-table td,.pure-table th{border-left-color:var(--color-border-table-cell)}.pure-table-striped tr:nth-child(2n-1) td{background-color:var(--color-table-stripe)}.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form select,.pure-form textarea{border:var(--color-border-input);box-shadow:inset 0 1px 3px var(--color-shadow-input);background-color:var(--color-background-input);color:var(--color-text-input)}.pure-form input[type=color]:active,.pure-form input[type=date]:active,.pure-form input[type=datetime-local]:active,.pure-form input[type=datetime]:active,.pure-form input[type=email]:active,.pure-form input[type=month]:active,.pure-form input[type=number]:active,.pure-form input[type=password]:active,.pure-form input[type=search]:active,.pure-form input[type=tel]:active,.pure-form input[type=text]:active,.pure-form input[type=time]:active,.pure-form input[type=url]:active,.pure-form input[type=week]:active,.pure-form select:active,.pure-form textarea:active{background-color:var(--color-background-input)}input::placeholder,textarea::placeholder{color:var(--color-text-input-placeholder)}.m-d{min-width:100%}@media only screen and (min-width: 761px){.m-d{min-width:80%}}.pure-form-stacked>div:first-child{display:block}.tab-pane-inner{padding:0px}.tab-pane-inner:not(:target){display:none}.tab-pane-inner:target{display:block}.beta-logo{height:50px;right:-3px;top:-3px;position:absolute}#selector-header{padding-bottom:1em}body.full-width .edit-form{width:95%}.edit-form{min-width:70%;max-width:95%}.edit-form .box-wrap{position:relative}.edit-form .inner{background:var(--color-background);padding:20px}.edit-form #actions{display:block;background:var(--color-background)}.edit-form #actions .pure-control-group{display:flex;gap:.625em;flex-wrap:wrap}.edit-form .pure-form-message-inline{padding-left:0;color:var(--color-text-input-description)}.edit-form .pure-form-message-inline code{font-size:.875em}.border-fieldset{border:1px solid #ccc;padding:1rem;border-radius:5px;margin-bottom:1rem}.border-fieldset h3{margin-top:0}.border-fieldset fieldset:last-of-type{padding-bottom:0}.border-fieldset fieldset:last-of-type .pure-control-group{padding-bottom:0}ul{padding-left:1em;padding-top:0px;margin-top:4px}.time-check-widget tr{display:inline}.time-check-widget tr input[type=number]{width:5em}@media only screen and (max-width: 760px){.time-check-widget tbody{display:grid;grid-template-columns:auto 1fr auto 1fr;gap:.625em .3125em;align-items:center}.time-check-widget tr{display:contents}.time-check-widget tr th{text-align:right;padding-right:5px}.time-check-widget tr input[type=number]{width:100%;max-width:5em}}#webdriver_delay{width:5em}#api-key:hover{cursor:pointer}#api-key-copy{color:var(--color-api-key)}.button-green{background-color:var(--color-background-button-green)}.button-red{background-color:var(--color-background-button-red)}.noselect{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#checkbox-operations{background:var(--color-background-checkbox-operations);padding:1em;border-radius:10px;margin-bottom:1em;display:none}#checkbox-operations button{margin-bottom:3px;margin-top:3px;display:inline-flex;align-items:center}.checkbox-uuid>*{vertical-align:middle}.inline-warning{border:1px solid var(--color-border-warning);padding:.5rem;border-radius:5px;color:var(--color-warning)}.inline-warning>span{display:inline-block;vertical-align:middle}.inline-warning img.inline-warning-icon{display:inline;height:26px;vertical-align:middle}.tracking-ldjson-price-data{background-color:var(--color-background-button-green);color:#000;opacity:.6}.ldjson-price-track-offer{font-weight:bold;font-style:italic}.ldjson-price-track-offer a.pure-button{border-radius:3px;padding:3px;background-color:var(--color-background-button-green)}.price-follow-tag-icon{display:inline-block;height:.8rem;vertical-align:middle}#quick-watch-processor-type ul#processor{color:#fff;padding-left:0px}#quick-watch-processor-type ul#processor li{list-style:none;font-size:.9rem;display:grid;grid-template-columns:auto 1fr;align-items:center;gap:.5rem;margin-bottom:.5rem}#quick-watch-processor-type label,#quick-watch-processor-type input{padding:0;margin:0}.restock-label.in-stock{background-color:var(--color-background-button-green);color:#fff}.restock-label.not-in-stock{background-color:var(--color-background-button-cancel);color:#777}.restock-label.error{background-color:var(--color-background-button-error);color:#fff;opacity:.7}.restock-label svg{vertical-align:middle}#chrome-extension-link{padding:9px;border:1px solid var(--color-grey-800);border-radius:10px;vertical-align:middle}#chrome-extension-link img{height:21px;padding:2px;vertical-align:middle}#realtime-conn-error{position:fixed;bottom:0;left:0;background:var(--color-warning);padding:10px;font-size:.8rem;color:#fff;opacity:.8}#bottom-horizontal-offscreen{position:fixed;bottom:0;left:0;right:0;width:100%;min-height:50px;max-height:50vh;background:hsla(0,0%,100%,.7215686275);border-top:1px solid var(--color-border-table-cell);padding:10px;box-shadow:0 -2px 10px rgba(0,0,0,.2);z-index:100;overflow-y:auto;transition:opacity .3s ease-in-out;scroll-margin-bottom:10px;display:flex;justify-content:center;align-items:center}ul#highlightSnippetActions{list-style:none}ul#highlightSnippetActions li{display:inline-block} +:root{--color-white: #fff;--color-grey-50: #111;--color-grey-100: #262626;--color-grey-200: #333;--color-grey-300: #444;--color-grey-325: #555;--color-grey-350: #565d64;--color-grey-400: #666;--color-grey-500: #777;--color-grey-600: #999;--color-grey-700: #cbcbcb;--color-grey-750: #ddd;--color-grey-800: #e0e0e0;--color-grey-850: #eee;--color-grey-900: #f2f2f2;--color-black: #000;--color-dark-red: #a00;--color-light-red: #dd0000;--color-background-page: var(--color-grey-100);--color-background-gradient-first: #5ad8f7;--color-background-gradient-second: #2f50af;--color-background-gradient-third: #9150bf;--color-background: var(--color-white);--color-text: var(--color-grey-200);--color-link: #1b98f8;--color-menu-accent: #ed5900;--color-background-code: var(--color-grey-850);--color-error: var(--color-dark-red);--color-error-input: #ffebeb;--color-error-list: var(--color-light-red);--color-table-background: var(--color-background);--color-table-stripe: var(--color-grey-900);--color-text-tab: var(--color-white);--color-background-tab: rgba(255, 255, 255, 0.2);--color-background-tab-hover: rgba(255, 255, 255, 0.5);--color-text-tab-active: #222;--color-api-key: #0078e7;--color-background-button-primary: #0078e7;--color-background-button-green: #42dd53;--color-background-button-red: #dd4242;--color-background-button-success: rgb(28, 184, 65);--color-background-button-error: rgb(202, 60, 60);--color-text-button-error: var(--color-white);--color-background-button-warning: rgb(202, 60, 60);--color-text-button-warning: var(--color-white);--color-background-button-secondary: rgb(66, 184, 221);--color-background-button-cancel: rgb(200, 200, 200);--color-text-button: var(--color-white);--color-background-button-tag: rgb(99, 99, 99);--color-background-snapshot-age: #dfdfdf;--color-error-text-snapshot-age: var(--color-white);--color-error-background-snapshot-age: #ff0000;--color-background-button-tag-active: #9c9c9c;--color-text-messages: var(--color-white);--color-background-messages-message: rgba(255, 255, 255, .2);--color-background-messages-error: rgba(255, 1, 1, .5);--color-background-messages-notice: rgba(255, 255, 255, .5);--color-border-notification: #ccc;--color-background-checkbox-operations: rgba(0, 0, 0, 0.05);--color-warning: #ff3300;--color-border-warning: var(--color-warning);--color-text-legend: var(--color-white);--color-link-new-version: #e07171;--color-last-checked: #bbb;--color-text-footer: #444;--color-border-watch-table-cell: #eee;--color-text-watch-tag-list: rgba(231, 0, 105, 0.4);--color-background-new-watch-form: rgba(0, 0, 0, 0.05);--color-background-new-watch-input: var(--color-white);--color-background-new-watch-input-transparent: rgba(255, 255, 255, 0.1);--color-text-new-watch-input: var(--color-text);--color-border-input: var(--color-grey-500);--color-shadow-input: var(--color-grey-400);--color-background-input: var(--color-white);--color-text-input: var(--color-text);--color-text-input-description: var(--color-grey-500);--color-text-input-placeholder: var(--color-grey-600);--color-background-table-thead: var(--color-grey-800);--color-border-table-cell: var(--color-grey-700);--color-text-menu-heading: var(--color-grey-350);--color-text-menu-link: var(--color-grey-500);--color-background-menu-link-hover: var(--color-grey-850);--color-text-menu-link-hover: var(--color-grey-300);--color-shadow-jump: var(--color-grey-500);--color-icon-github: var(--color-black);--color-icon-github-hover: var(--color-grey-300);--color-watch-table-error: var(--color-dark-red);--color-watch-table-row-text: var(--color-grey-100);--highlight-trigger-text-bg-color: #1b98f8;--highlight-ignored-text-bg-color: var(--color-grey-700);--highlight-blocked-text-bg-color: rgb(202, 60, 60)}html[data-darkmode=true]{--color-link: #59bdfb;--color-text: var(--color-white);--color-background-gradient-first: #3f90a5;--color-background-gradient-second: #1e316c;--color-background-gradient-third: #4d2c64;--color-background-new-watch-input: var(--color-grey-100);--color-background-new-watch-input-transparent: var(--color-grey-100);--color-text-new-watch-input: var(--color-text);--color-background-table-thead: var(--color-grey-200);--color-table-background: var(--color-grey-300);--color-table-stripe: var(--color-grey-325);--color-background: var(--color-grey-300);--color-text-menu-heading: var(--color-grey-850);--color-text-menu-link: var(--color-grey-800);--color-border-table-cell: var(--color-grey-400);--color-text-tab-active: var(--color-text);--color-border-input: var(--color-grey-400);--color-shadow-input: var(--color-grey-50);--color-background-input: var(--color-grey-350);--color-text-input-description: var(--color-grey-600);--color-text-input-placeholder: var(--color-grey-600);--color-text-watch-tag-list: rgba(250, 62, 146, 0.4);--color-background-code: var(--color-grey-200);--color-background-tab: rgba(0, 0, 0, 0.2);--color-background-tab-hover: rgba(0, 0, 0, 0.5);--color-background-snapshot-age: var(--color-grey-200);--color-shadow-jump: var(--color-grey-200);--color-icon-github: var(--color-white);--color-icon-github-hover: var(--color-grey-700);--color-watch-table-error: var(--color-light-red);--color-watch-table-row-text: var(--color-grey-800)}html[data-darkmode=true] .icon-spread{filter:hue-rotate(-10deg) brightness(1.5)}html[data-darkmode=true] .watch-table .title-col a[target=_blank]::after,html[data-darkmode=true] .watch-table .current-diff-url::after{filter:invert(0.5) hue-rotate(10deg) brightness(2)}html[data-darkmode=true] .watch-table .status-browsersteps{filter:invert(0.5) hue-rotate(10deg) brightness(1.5)}html[data-darkmode=true] .watch-table .watch-controls .state-off img{opacity:.3}html[data-darkmode=true] .watch-table .watch-controls .state-on img{opacity:1}html[data-darkmode=true] .watch-table .unviewed{color:#fff}html[data-darkmode=true] .watch-table .unviewed.error{color:var(--color-watch-table-error)}.arrow{border:solid #1b98f8;border-width:0 2px 2px 0;display:inline-block;padding:3px}.arrow.right{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}.arrow.left{transform:rotate(135deg);-webkit-transform:rotate(135deg)}.arrow.up,.arrow.asc{transform:rotate(-135deg);-webkit-transform:rotate(-135deg)}.arrow.down,.arrow.desc{transform:rotate(45deg);-webkit-transform:rotate(45deg)}#browser_steps th{display:none}#browser_steps li{list-style:decimal;padding:5px}#browser_steps li.browser-step-with-error{background-color:#ffd6d6;border-radius:4px}#browser_steps li:not(:first-child):hover{opacity:1}#browser_steps li .control{padding-left:5px;padding-right:5px}#browser_steps li .control a{font-size:70%}#browser_steps li.empty{padding:0px;opacity:.35}#browser_steps li.empty .control{display:none}#browser_steps li:hover{background:#eee}#browser_steps li>label{display:none}@media only screen and (min-width: 760px){#browser-steps .flex-wrapper{display:flex;flex-flow:row;height:70vh;font-size:80%}#browser-steps .flex-wrapper #browser-steps-ui{flex-grow:1;flex-shrink:1;flex-basis:0;background-color:#eee;border-radius:5px}#browser-steps-fieldlist{flex-grow:0;flex-shrink:0;flex-basis:auto;max-width:400px;padding-left:1rem;overflow-y:scroll}#browsersteps-selector-wrapper{height:100% !important}}#browsersteps-selector-wrapper{width:100%;overflow-y:scroll;position:relative;height:80vh}#browsersteps-selector-wrapper>img{position:absolute;max-width:100%}#browsersteps-selector-wrapper>canvas{position:relative;max-width:100%}#browsersteps-selector-wrapper>canvas:hover{cursor:pointer}#browsersteps-selector-wrapper .loader{position:absolute;left:50%;top:50%;transform:translate(-50%, -50%);z-index:100;max-width:350px;text-align:center}#browsersteps-selector-wrapper .spinner,#browsersteps-selector-wrapper .spinner:after{width:80px;height:80px;font-size:3px}#browsersteps-selector-wrapper #browsersteps-click-start{color:var(--color-grey-400)}#browsersteps-selector-wrapper #browsersteps-click-start:hover{cursor:pointer}ul#requests-extra_proxies{list-style:none}ul#requests-extra_proxies li>label{display:none}ul#requests-extra_proxies table tr{display:table-row}ul#requests-extra_proxies table tr input[type=text]{width:100%}@media only screen and (min-width: 1024px){ul#requests-extra_proxies table tr{display:inline}}#request label[for=proxy]{display:inline-block}body.proxy-check-active #request .proxy-check-details{font-size:80%;color:#555;display:block;padding-left:2em;max-width:500px}body.proxy-check-active #request .proxy-timing{font-size:80%;padding-left:1rem;color:var(--color-link)}#recommended-proxy{display:grid;gap:2rem;padding-bottom:1em}@media(min-width: 991px){#recommended-proxy{grid-template-columns:repeat(2, 1fr)}}#recommended-proxy>div{border:1px #aaa solid;border-radius:4px;padding:1em}#extra-proxies-setting{border:1px solid var(--color-grey-800);border-radius:4px;margin:1em;padding:1em}ul#requests-extra_browsers{list-style:none}ul#requests-extra_browsers li>label{display:none}ul#requests-extra_browsers table tr{display:table-row}ul#requests-extra_browsers table tr input[type=text]{width:100%}@media only screen and (min-width: 1280px){ul#requests-extra_browsers table tr{display:inline}ul#requests-extra_browsers table tr input[type=text]{width:100%}}#extra-browsers-setting{border:1px solid var(--color-grey-800);border-radius:4px;margin:1em;padding:1em}.pagination-page-info{text-transform:capitalize}.pagination.menu>*{display:inline-block}.pagination.menu li{display:inline-block}.pagination.menu a{padding:.65rem;margin:3px;border:none;background:#444;border-radius:2px;color:var(--color-text-button)}.pagination.menu a.disabled{display:none}.pagination.menu a.active{font-weight:bold;background:#888}.pagination.menu a:hover{background:#999}.spinner,.spinner:after{border-radius:50%;width:10px;height:10px}.spinner{margin:0px auto;font-size:3px;vertical-align:middle;display:inline-block;text-indent:-9999em;border-top:1.1em solid rgba(38,104,237,.2);border-right:1.1em solid rgba(38,104,237,.2);border-bottom:1.1em solid rgba(38,104,237,.2);border-left:1.1em solid #2668ed;-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0);-webkit-animation:load8 1.1s infinite linear;animation:load8 1.1s infinite linear}@-webkit-keyframes load8{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes load8{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.toggle-light-mode .icon-dark{display:none}html[data-darkmode=true] .toggle-light-mode .icon-light{display:none}html[data-darkmode=true] .toggle-light-mode .icon-dark{display:block}.pure-menu-link{padding:.5rem 1em;line-height:1.2rem}.pure-menu-item svg{height:1.2rem}.pure-menu-item *{vertical-align:middle}.pure-menu-item .github-link{height:1.8rem;display:block}.pure-menu-item .github-link svg{height:100%}.pure-menu-item .bi-heart:hover{cursor:pointer}.pure-menu-item.active .pure-menu-link{background-color:var(--color-background-menu-link-hover);color:var(--color-text-menu-link-hover)}#cdio-logo{padding-left:.5em}#inline-menu-extras-group>*{display:inline-block}#overlay{opacity:.95;position:fixed;width:350px;max-width:100%;height:100%;top:0;right:-350px;background-color:var(--color-table-stripe);z-index:2;transform:translateX(0);transition:transform .5s ease}#overlay.visible{transform:translateX(-100%)}#overlay .content{font-size:.875rem;padding:1rem;margin-top:5rem;max-width:400px;color:var(--color-watch-table-row-text)}#heartpath{transition:all ease .3s !important}#heartpath:hover{fill:red !important;transition:all ease .3s !important}.minitabs-wrapper{width:100%}.minitabs-wrapper>div[id]{padding:20px;border:1px solid #ccc;border-top:none}.minitabs-wrapper .minitabs-content{width:100%;display:flex}.minitabs-wrapper .minitabs-content>div{flex:1 1 auto;min-width:0;overflow:scroll}.minitabs-wrapper .minitabs{display:flex;border-bottom:1px solid #ccc}.minitabs-wrapper .minitab{flex:1;text-align:center;padding:12px 0;text-decoration:none;color:#333;background-color:#f1f1f1;border:1px solid #ccc;border-bottom:none;cursor:pointer;transition:background-color .3s}.minitabs-wrapper .minitab:hover{background-color:#ddd}.minitabs-wrapper .minitab.active{background-color:#fff;font-weight:bold}@media(min-width: 800px){body.preview-text-enabled #filters-and-triggers>div{display:flex;gap:20px;position:relative}}body.preview-text-enabled #edit-text-filter,body.preview-text-enabled #text-preview{flex:1;align-self:flex-start}body.preview-text-enabled #edit-text-filter #pro-tips{display:none}body.preview-text-enabled #text-preview{position:sticky;top:20px;padding-top:1rem;padding-bottom:1rem;display:block !important}body.preview-text-enabled #activate-text-preview{background-color:var(--color-grey-500)}body.preview-text-enabled .monospace-preview{background:var(--color-background-input);border:1px solid var(--color-grey-600);padding:1rem;color:var(--color-text-input);font-family:"Courier New",Courier,monospace;font-size:70%;word-break:break-word;white-space:pre-wrap}#activate-text-preview{right:0;position:absolute;z-index:3;box-shadow:1px 1px 4px var(--color-shadow-jump)}#stats_row{display:flex;align-items:center;width:100%;color:#fff;font-size:.85rem}#stats_row>*{padding-bottom:.5rem}#stats_row .left{text-align:left}#stats_row .right{opacity:.5;transition:opacity .6s ease;margin-left:auto;text-align:right}body.has-queue #stats_row .right{opacity:1}.watch-table{width:100%;font-size:80%}.watch-table tr{color:var(--color-watch-table-row-text)}.watch-table tr.unviewed{font-weight:bold}.watch-table td{white-space:nowrap}.watch-table td.title-col{word-break:break-all;white-space:normal}.watch-table td a.external::after{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAQElEQVR42qXKwQkAIAxDUUdxtO6/RBQkQZvSi8I/pL4BoGw/XPkh4XigPmsUgh0626AjRsgxHTkUThsG2T/sIlzdTsp52kSS1wAAAABJRU5ErkJggg==);margin:0 3px 0 5px}.watch-table th{white-space:nowrap}.watch-table th a{font-weight:normal}.watch-table th a.active{font-weight:bolder}.watch-table th a.inactive .arrow{display:none}.watch-table tr.checking-now td:first-child{position:relative}.watch-table tr.checking-now td:first-child::before{content:"";position:absolute;top:0;bottom:0;left:0;width:3px;background-color:#293eff}.watch-table tr.checking-now td.last-checked .spinner-wrapper{display:inline-block !important}.watch-table tr.checking-now td.last-checked .innertext{display:none !important}.watch-table tr.queued a.recheck{display:none !important}.watch-table tr.queued a.already-in-queue-button{display:inline-block !important}.watch-table tr.paused a.pause-toggle.state-on{display:inline !important}.watch-table tr.paused a.pause-toggle.state-off{display:none !important}.watch-table tr.notification_muted a.mute-toggle.state-on{display:inline !important}.watch-table tr.notification_muted a.mute-toggle.state-off{display:none !important}.watch-table tr.has-error{color:var(--color-watch-table-error)}.watch-table tr.has-error .error-text{display:block !important}.watch-table tr.single-history a.preview-link{display:inline-block !important}.watch-table tr.multiple-history a.history-link{display:inline-block !important}#watch-table-wrapper #post-list-buttons{text-align:right;padding:0px;margin:0px}#watch-table-wrapper #post-list-buttons li{display:inline-block}#watch-table-wrapper #post-list-buttons a{border-top-left-radius:initial;border-top-right-radius:initial;border-bottom-left-radius:5px;border-bottom-right-radius:5px}#watch-table-wrapper.has-error #post-list-buttons #post-list-with-errors{display:inline-block !important}#watch-table-wrapper.has-unread-changes #post-list-buttons #post-list-unread,#watch-table-wrapper.has-unread-changes #post-list-buttons #post-list-mark-views,#watch-table-wrapper.has-unread-changes #post-list-buttons #post-list-unread{display:inline-block !important}@media(max-width: 767px){.watch-table thead{display:block}.watch-table thead tr th{display:inline-block}}@media(max-width: 767px)and (max-width: 768px){.watch-table thead tr th .hide-on-mobile{display:none}}@media(max-width: 767px){.watch-table thead .empty-cell{display:none}.watch-table .last-checked{margin-left:calc(20px + .5rem)}.watch-table .last-checked>span{vertical-align:middle}.watch-table .last-changed{margin-left:calc(20px + .5rem)}.watch-table .last-checked::before{color:var(--color-text);content:"Last Checked "}.watch-table .last-changed::before{color:var(--color-text);content:"Last Changed "}.watch-table td.inline{display:inline-block}.watch-table .pure-table td,.watch-table .pure-table th{border:none}.watch-table td{border:none;border-bottom:1px solid var(--color-border-watch-table-cell);vertical-align:middle}.watch-table td:before{top:6px;left:6px;width:45%;padding-right:10px;white-space:nowrap}.watch-table.pure-table-striped tr{background-color:var(--color-table-background)}.watch-table.pure-table-striped tr:nth-child(2n-1){background-color:var(--color-table-stripe)}.watch-table.pure-table-striped tr:nth-child(2n-1) td{background-color:inherit}}@media(max-width: 767px){.watch-table tbody tr{padding-bottom:10px;padding-top:10px;display:grid;grid-template-columns:20px 1fr 100px;grid-template-rows:auto auto auto auto;gap:.5rem}.watch-table tbody tr .counter-i{display:none}.watch-table tbody tr td.checkbox-uuid{display:grid;place-items:center}.watch-table tbody tr>td{border-bottom:none}.watch-table tbody tr>td.title-col{grid-column:1/-1;grid-row:1}.watch-table tbody tr>td.title-col .watch-title{font-size:.92rem}.watch-table tbody tr>td.title-col .link-spread{display:none}.watch-table tbody tr>td.last-checked{grid-column:1/-1;grid-row:2}.watch-table tbody tr>td.last-changed{grid-column:1/-1;grid-row:3}.watch-table tbody tr>td.checkbox-uuid{grid-column:1;grid-row:4}.watch-table tbody tr>td.buttons{grid-column:2;grid-row:4;display:flex;align-items:center;justify-content:flex-start}.watch-table tbody tr>td.watch-controls{grid-column:3;grid-row:4;display:grid;place-items:center}.watch-table tbody tr>td.watch-controls a img{padding:10px}.pure-table td{padding:3px !important}}ul#conditions_match_logic{list-style:none}ul#conditions_match_logic input,ul#conditions_match_logic label,ul#conditions_match_logic li{display:inline-block}ul#conditions_match_logic li{padding-right:1em}.fieldlist_formfields{width:100%;background-color:var(--color-background, #fff);border-radius:4px;border:1px solid var(--color-border-table-cell, #cbcbcb)}.fieldlist_formfields .fieldlist-header{display:flex;background-color:var(--color-background-table-thead, #e0e0e0);font-weight:bold;border-bottom:1px solid var(--color-border-table-cell, #cbcbcb)}.fieldlist_formfields .fieldlist-header-cell{flex:1;padding:.5em 1em;text-align:left}.fieldlist_formfields .fieldlist-header-cell:last-child{flex:0 0 120px}.fieldlist_formfields .fieldlist-body{display:flex;flex-direction:column}.fieldlist_formfields .fieldlist-row{display:flex;border-bottom:1px solid var(--color-border-table-cell, #cbcbcb)}.fieldlist_formfields .fieldlist-row:last-child{border-bottom:none}.fieldlist_formfields .fieldlist-row:nth-child(2n-1){background-color:var(--color-table-stripe, #f2f2f2)}.fieldlist_formfields .fieldlist-row.error-row{background-color:var(--color-error-input, #ffdddd)}.fieldlist_formfields .fieldlist-cell{flex:1;padding:.5em 1em;display:flex;flex-direction:column;justify-content:center}.fieldlist_formfields .fieldlist-cell input,.fieldlist_formfields .fieldlist-cell select{width:100%}.fieldlist_formfields .fieldlist-cell.fieldlist-actions{flex:0 0 120px;display:flex;flex-direction:row;align-items:center;gap:4px}.fieldlist_formfields ul.errors{margin-top:.5em;margin-bottom:0;padding:.5em;background-color:var(--color-error-background-snapshot-age, #ffdddd);border-radius:4px;list-style-position:inside}@media only screen and (max-width: 760px){.fieldlist_formfields .fieldlist-header,.fieldlist_formfields .fieldlist-row{flex-direction:column}.fieldlist_formfields .fieldlist-header-cell{display:none}.fieldlist_formfields .fieldlist-row{padding:.5em 0;border-bottom:2px solid var(--color-border-table-cell, #cbcbcb)}.fieldlist_formfields .fieldlist-cell{padding:.25em .5em}.fieldlist_formfields .fieldlist-cell.fieldlist-actions{flex:1;justify-content:flex-start;padding-top:.5em}.fieldlist_formfields .fieldlist-cell:not(:last-child){margin-bottom:.5em}.fieldlist_formfields .fieldlist-cell::before{content:attr(data-label);font-weight:bold;margin-bottom:.25em}}.fieldlist_formfields .addRuleRow,.fieldlist_formfields .removeRuleRow,.fieldlist_formfields .verifyRuleRow{cursor:pointer;border:none;padding:4px 8px;border-radius:3px;font-weight:bold;background-color:#aaa;color:var(--color-foreground-text, #fff)}.fieldlist_formfields .addRuleRow:hover,.fieldlist_formfields .removeRuleRow:hover,.fieldlist_formfields .verifyRuleRow:hover{background-color:#999}.watch-table.favicon-not-enabled tr .favicon{display:none}.watch-table tr td.inline.title-col .flex-wrapper{display:flex;align-items:center;gap:4px}.watch-table td,.watch-table th{vertical-align:middle}.watch-table tr.has-favicon.unviewed img.favicon{opacity:1 !important}.watch-table .status-icons{white-space:nowrap;display:flex;align-items:center;gap:4px}.watch-table .status-icons>*{vertical-align:middle}.title-col{padding:10px}.title-wrapper{display:flex;align-items:center;gap:10px}.title-col-inner{display:inline-block;vertical-align:middle}.watch-table img.favicon{vertical-align:middle;max-width:25px;max-height:25px;height:25px;padding-right:4px}body.checking-now #checking-now-fixed-tab{display:block !important}#checking-now-fixed-tab{background:#ccc;border-radius:5px;bottom:0;color:var(--color-text);display:none;font-size:.8rem;left:0;padding:5px;position:fixed}#selector-wrapper{height:100%;text-align:center;max-height:70vh;overflow-y:scroll;position:relative}#selector-wrapper>img{position:absolute;z-index:4;max-width:100%}#selector-wrapper>canvas{position:relative;z-index:5;max-width:100%}#selector-wrapper>canvas:hover{cursor:pointer}#selector-current-xpath{font-size:80%}.ternary-radio-group{display:flex;gap:0;border:1px solid var(--color-grey-750);border-radius:4px;overflow:hidden;width:fit-content;background:var(--color-background)}.ternary-radio-group .ternary-radio-option{position:relative;cursor:pointer;margin:0;display:flex;align-items:center}.ternary-radio-group .ternary-radio-option input[type=radio]{position:absolute;opacity:0;width:0;height:0}.ternary-radio-group .ternary-radio-option .ternary-radio-label{padding:8px 16px;background:var(--color-grey-900);border:none;border-right:1px solid var(--color-grey-750);font-size:13px;font-weight:500;color:var(--color-text);transition:all .2s ease;cursor:pointer;display:block;text-align:center}.ternary-radio-group .ternary-radio-option:last-child .ternary-radio-label{border-right:none}.ternary-radio-group .ternary-radio-option input:checked+.ternary-radio-label{background:var(--color-link);color:var(--color-text-button);font-weight:600}.ternary-radio-group .ternary-radio-option input:checked+.ternary-radio-label.ternary-default{background:var(--color-grey-600);color:var(--color-text-button)}.ternary-radio-group .ternary-radio-option input:checked+.ternary-radio-label:hover{background:#1a7bc4}.ternary-radio-group .ternary-radio-option input:checked+.ternary-radio-label:hover.ternary-default{background:var(--color-grey-500)}.ternary-radio-group .ternary-radio-option:hover .ternary-radio-label{background:var(--color-grey-800)}@media(max-width: 480px){.ternary-radio-group{width:100%}.ternary-radio-group .ternary-radio-label{flex:1;min-width:auto}}input[type=radio].pure-radio:checked+label,input[type=radio].pure-radio:checked{background:var(--color-link);color:var(--color-text-button)}html[data-darkmode=true] .ternary-radio-group .ternary-radio-option .ternary-radio-label{background:var(--color-grey-350)}html[data-darkmode=true] .ternary-radio-group .ternary-radio-option:hover .ternary-radio-label{background:var(--color-grey-400)}html[data-darkmode=true] .ternary-radio-group .ternary-radio-option input:checked+.ternary-radio-label{background:var(--color-link);color:var(--color-text-button)}html[data-darkmode=true] .ternary-radio-group .ternary-radio-option input:checked+.ternary-radio-label.ternary-default{background:var(--color-grey-600)}html[data-darkmode=true] .ternary-radio-group .ternary-radio-option input:checked+.ternary-radio-label:hover{background:#1a7bc4}html[data-darkmode=true] .ternary-radio-group .ternary-radio-option input:checked+.ternary-radio-label:hover.ternary-default{background:var(--color-grey-500)}body.processor-image_ssim_diff #edit-text-filter .text-filtering{display:none}body.processor-image_ssim_diff #conditions-tab{display:none}.modal-dialog{border:none;border-radius:10px;padding:0;background:var(--color-background);color:var(--color-text);box-shadow:0 5px 20px rgba(0,0,0,.3);max-width:500px;width:90%}.modal-dialog::backdrop{background:rgba(0,0,0,.6);backdrop-filter:blur(3px);animation:fadeIn .2s ease-out}.modal-dialog[open]{animation:slideIn .25s ease-out}.modal-dialog .modal-header{padding:1.5rem;border-bottom:1px solid var(--color-border-table-cell);display:flex;align-items:center;gap:1rem}.modal-dialog .modal-header .modal-icon{font-size:2rem;line-height:1;flex-shrink:0}.modal-dialog .modal-header .modal-icon.warning{color:var(--color-warning)}.modal-dialog .modal-header .modal-icon.danger{color:var(--color-background-button-error)}.modal-dialog .modal-header .modal-icon.info{color:var(--color-background-button-primary)}.modal-dialog .modal-header .modal-title{font-size:1.3rem;font-weight:bold;margin:0;color:var(--color-text)}.modal-dialog .modal-body{padding:1.5rem;line-height:1.6}.modal-dialog .modal-body p{margin:0 0 1rem 0}.modal-dialog .modal-body p:last-child{margin-bottom:0}.modal-dialog .modal-body strong{color:var(--color-text);font-weight:600}.modal-dialog .modal-footer{padding:1rem 1.5rem;border-top:1px solid var(--color-border-table-cell);display:flex;gap:.75rem;justify-content:flex-end;background:var(--color-grey-900)}.modal-dialog .modal-footer button{padding:.6rem 1.5rem;border:none;border-radius:4px;cursor:pointer;font-weight:500;transition:all .2s ease;font-size:.95rem}.modal-dialog .modal-footer button:hover{transform:translateY(-1px);box-shadow:0 2px 8px rgba(0,0,0,.15)}.modal-dialog .modal-footer button:active{transform:translateY(0)}.modal-dialog .modal-footer button.modal-btn-cancel{background:var(--color-background-button-cancel);color:var(--color-grey-200)}.modal-dialog .modal-footer button.modal-btn-cancel:hover{background:var(--color-grey-700)}.modal-dialog .modal-footer button.modal-btn-confirm{background:var(--color-background-button-primary);color:var(--color-white)}.modal-dialog .modal-footer button.modal-btn-confirm:hover{opacity:.9}.modal-dialog .modal-footer button.modal-btn-danger{background:var(--color-background-button-error);color:var(--color-white)}.modal-dialog .modal-footer button.modal-btn-danger:hover{background:var(--color-dark-red)}.modal-dialog .modal-footer button.modal-btn-warning{background:var(--color-background-button-warning);color:var(--color-white)}.modal-dialog .modal-footer button.modal-btn-warning:hover{opacity:.9}html[data-darkmode=true] .modal-dialog{box-shadow:0 5px 30px rgba(0,0,0,.7)}html[data-darkmode=true] .modal-dialog .modal-footer{background:var(--color-grey-200)}@keyframes fadeIn{from{opacity:0}to{opacity:1}}@keyframes slideIn{from{opacity:0;transform:translateY(-20px) scale(0.95)}to{opacity:1;transform:translateY(0) scale(1)}}@media only screen and (max-width: 760px){.modal-dialog{width:95%;max-width:none}.modal-dialog .modal-header{padding:1rem}.modal-dialog .modal-header .modal-title{font-size:1.1rem}.modal-dialog .modal-body{padding:1rem;font-size:.95rem}.modal-dialog .modal-footer{padding:.75rem 1rem;flex-wrap:wrap}.modal-dialog .modal-footer button{flex:1;min-width:120px}}#language-selector-flag{display:inline-block;width:1.2em;height:1.2em;vertical-align:middle;border-radius:50%;overflow:hidden;opacity:.6}#language-selector-flag:hover{opacity:1}.language-list{display:flex;flex-direction:column;gap:.5rem;padding:.5rem 0}.language-option{display:flex;align-items:center;gap:1rem;padding:.25rem;border-radius:4px;transition:background-color .2s ease;text-decoration:none;color:var(--color-text);border:1px solid rgba(0,0,0,0)}.language-option:hover{background-color:var(--color-background-menu-link-hover);border-color:var(--color-border-table-cell)}.language-option.active{background-color:var(--color-link);color:var(--color-text-button);font-weight:600}.language-option .flag{font-size:1.5rem;flex-shrink:0}.language-option .language-name{flex-grow:1;font-size:1rem}#language-modal .language-list .lang-option{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;margin-right:.5em;border-radius:50%;overflow:hidden}.content-wrapper{display:flex;gap:0;width:100%;max-width:100%;position:relative}@media only screen and (max-width: 900px){.content-wrapper{flex-direction:column}}.action-sidebar{position:sticky;top:100px;flex-shrink:0;width:80px;height:fit-content;background:rgba(0,0,0,0);padding:1.5rem 0;display:flex;flex-direction:column;gap:.5rem;align-items:center;z-index:0}@media only screen and (max-width: 900px){.action-sidebar{position:relative;top:0;width:100%;flex-direction:row;justify-content:space-around;padding:0;overflow-x:auto}}.action-sidebar-item{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.35rem;padding:.75rem .5rem;min-width:64px;text-decoration:none;opacity:.8;transition:opacity .2s ease}.action-sidebar-item:hover{opacity:1}.action-sidebar-item.active{opacity:1}.action-sidebar-item.active .action-icon{stroke:#fff;stroke-width:2.5}.action-sidebar-item.active .action-label{color:#fff;font-weight:700}.action-icon{width:28px;height:28px;stroke:#fff;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round;transition:stroke .2s ease}.action-label{font-size:.65rem;font-weight:500;text-align:center;line-height:1.1;letter-spacing:.02em;text-transform:uppercase;color:#fff;transition:color .2s ease;max-width:60px;word-wrap:break-word}.content-main{flex:0 1 auto;width:100%;min-width:0;padding:0;display:flex;flex-direction:column;align-items:center}.hamburger-menu{display:none;background:rgba(0,0,0,0);border:none;cursor:pointer;padding:.5rem;z-index:10001;position:relative}@media only screen and (max-width: 980px){.hamburger-menu{display:flex;flex-direction:column;justify-content:center;align-items:center}}.hamburger-icon{width:24px;height:20px;position:relative;display:flex;flex-direction:column;justify-content:space-between}.hamburger-icon span{display:block;height:3px;width:100%;background:var(--color-text);border-radius:2px;transition:all .3s cubic-bezier(0.68, -0.55, 0.265, 1.55);transform-origin:center}.hamburger-menu.active .hamburger-icon span:nth-child(1){transform:translateY(8.5px) rotate(45deg)}.hamburger-menu.active .hamburger-icon span:nth-child(2){opacity:0;transform:translateX(-10px)}.hamburger-menu.active .hamburger-icon span:nth-child(3){transform:translateY(-8.5px) rotate(-45deg)}.mobile-menu-overlay{display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.5);z-index:9999;opacity:0;transition:opacity .3s ease}.mobile-menu-overlay.active{display:block;opacity:1}.mobile-menu-drawer{position:fixed;top:0;right:-280px;width:280px;height:100%;background:var(--color-background);opacity:1;box-shadow:-2px 0 8px rgba(0,0,0,.15);z-index:10000;transition:right .3s cubic-bezier(0.68, -0.55, 0.265, 1.55);overflow-y:auto;padding-top:60px}.mobile-menu-drawer.active{right:0}.mobile-menu-drawer .mobile-menu-items{list-style:none;padding:1rem 0;margin:0}.mobile-menu-drawer .mobile-menu-items li{border-bottom:1px solid var(--color-border-table-cell)}.mobile-menu-drawer .mobile-menu-items li>*{display:block;padding:1rem 1.5rem;color:var(--color-text);text-decoration:none;font-weight:500;transition:background .2s ease}.mobile-menu-drawer .mobile-menu-items li>*:hover{background:var(--color-background-menu-link-hover)}.logo-cdio{font-weight:bold;font-size:1.1rem}.logo-cdio .logo-cd{color:var(--color-grey-500)}.logo-cdio .logo-io{color:var(--color-text)}.menu-always-visible{display:flex;align-items:center;gap:.5rem;margin-left:auto}@media only screen and (max-width: 980px){#top-right-menu .menu-collapsible{display:none !important}.pure-menu-horizontal{overflow-x:visible !important}#nav-menu{overflow-x:visible !important}}@media only screen and (min-width: 1025px){.hamburger-menu,.mobile-menu-drawer,.mobile-menu-overlay{display:none !important}}html[data-darkmode=true] .mobile-menu-drawer{box-shadow:-2px 0 8px rgba(0,0,0,.4)}#search-modal .modal-body{padding:2rem 1.5rem}#search-modal .modal-body .pure-control-group{padding-bottom:0}#search-modal .modal-body .pure-control-group label{display:block;margin-bottom:.5rem;font-size:.9rem;font-weight:600;color:var(--color-text)}#search-modal .modal-body .pure-control-group #search-modal-input{width:100%;max-width:100%;box-sizing:border-box;padding:.6rem .8rem;font-size:1rem;border:1px solid var(--color-border-input);border-radius:4px;background-color:var(--color-background-input);color:var(--color-text-input);box-shadow:inset 0 1px 3px var(--color-shadow-input);transition:border-color .2s ease,box-shadow .2s ease}#search-modal .modal-body .pure-control-group #search-modal-input:focus{outline:none;border-color:var(--color-link);box-shadow:0 0 0 3px rgba(27,152,248,.1)}#search-modal .modal-body .pure-control-group #search-modal-input::placeholder{color:var(--color-text-input-placeholder);opacity:.7}html[data-darkmode=true] #search-modal #search-modal-input:focus{box-shadow:0 0 0 3px rgba(89,189,251,.15)}.action-sidebar-item{position:relative}.action-sidebar-item .notification-bubble{position:absolute;top:8px;left:8px;min-width:18px;height:18px;background:#f44;color:#fff;font-size:10px;font-weight:700;line-height:18px;text-align:center;border-radius:9px;padding:0 2px;box-shadow:0 2px 4px rgba(0,0,0,.3);pointer-events:none;transition:all .2s ease;display:none}.action-sidebar-item .notification-bubble.red-bubble{background:#f44}.action-sidebar-item .notification-bubble.blue-bubble{background:#4a9eff;color:#fff}.action-sidebar-item .notification-bubble.visible{display:block}.action-sidebar-item .notification-bubble.pulse{animation:bubblePulse .4s ease-out}.action-sidebar-item .notification-bubble.large-number{font-size:8px;min-width:20px;height:20px;line-height:20px;border-radius:10px}@keyframes bubblePulse{0%{transform:scale(1)}50%{transform:scale(1.3)}100%{transform:scale(1)}}html[data-darkmode=true] .notification-bubble{box-shadow:0 2px 6px rgba(0,0,0,.6)}.toast-container{position:fixed;display:flex;flex-direction:column;gap:.75rem;pointer-events:none;z-index:10000}.toast-container.toast-top-right{top:20px;right:20px}.toast-container.toast-top-center{top:100px;left:50%;transform:translateX(-50%)}.toast-container.toast-top-left{top:20px;left:20px}.toast-container.toast-bottom-right{bottom:20px;right:20px}.toast-container.toast-bottom-center{bottom:20px;left:50%;transform:translateX(-50%)}.toast-container.toast-bottom-left{bottom:20px;left:20px}.toast{position:relative;display:flex;align-items:center;gap:.75rem;min-width:300px;max-width:500px;padding:1rem 1.25rem;background:var(--color-background);border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,.15),0 0 0 1px rgba(0,0,0,.05);pointer-events:auto;overflow:hidden;opacity:0;transform:translateY(-50px);transition:all .3s cubic-bezier(0.68, -0.55, 0.265, 1.55);font-family:inherit}.toast.toast-show{opacity:1;transform:translateY(0)}.toast.toast-hide{opacity:0;transform:translateY(-50px) scale(0.95)}.toast.toast-success{border-left:4px solid #10b981}.toast.toast-success .toast-icon{color:#10b981}.toast.toast-error{border-left:4px solid #ef4444}.toast.toast-error .toast-icon{color:#ef4444}.toast.toast-warning{border-left:4px solid #f59e0b}.toast.toast-warning .toast-icon{color:#f59e0b}.toast.toast-info{border-left:4px solid #3b82f6}.toast.toast-info .toast-icon{color:#3b82f6}.toast.toast-default{border-left:4px solid var(--color-grey-500)}.toast-icon{flex-shrink:0;width:24px;height:24px}.toast-icon svg{width:100%;height:100%}.toast-message{flex:1;font-size:.875rem;line-height:1.5;color:var(--color-text);word-break:break-word;font-family:inherit}.toast-close{flex-shrink:0;width:24px;height:24px;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,0);border:none;border-radius:4px;color:var(--color-grey-500);font-size:1.5rem;line-height:1;cursor:pointer;transition:all .2s ease;padding:0;margin-left:.25rem}.toast-close:hover{background:var(--color-grey-800);color:var(--color-text)}.toast-close:active{transform:scale(0.95)}.toast-progress{position:absolute;bottom:0;left:0;right:0;height:3px;background:currentColor;opacity:.3;transform-origin:left;transition:transform linear}html[data-darkmode=true] .toast{background:var(--color-grey-300);box-shadow:0 4px 12px rgba(0,0,0,.4),0 0 0 1px hsla(0,0%,100%,.05)}html[data-darkmode=true] .toast-close:hover{background:var(--color-grey-400)}@media only screen and (max-width: 768px){.toast-container{left:10px !important;right:10px !important;top:10px !important;transform:none !important;align-items:stretch}.toast-container.toast-bottom-right,.toast-container.toast-bottom-center,.toast-container.toast-bottom-left{top:auto !important;bottom:10px !important}.toast{min-width:auto;max-width:none;width:100%;transform:translateY(-100px)}.toast.toast-show{transform:translateY(0)}.toast.toast-hide{transform:translateY(-100px) scale(0.95)}}@media(prefers-reduced-motion: reduce){.toast{transition:opacity .2s ease;transform:none !important}.toast.toast-show{opacity:1}.toast.toast-hide{opacity:0}}.login-form{min-height:52vh;display:flex;align-items:center;justify-content:center;padding:2rem 1rem}.login-form .inner{background:var(--color-background);border-radius:16px;box-shadow:0 10px 40px rgba(0,0,0,.08),0 2px 8px rgba(0,0,0,.04);padding:3rem 2.5rem;width:100%;max-width:420px;position:relative;overflow:hidden;transition:transform .3s ease,box-shadow .3s ease}.login-form .inner:hover{box-shadow:0 15px 50px rgba(0,0,0,.12),0 5px 15px rgba(0,0,0,.06)}.login-form form{margin:0}.login-form fieldset{border:none;padding:0;margin:0}.login-form .pure-control-group{margin-bottom:1.75rem}.login-form .pure-control-group:last-of-type{margin-bottom:0;margin-top:2rem}.login-form label{display:block;margin-bottom:.5rem;font-weight:600;font-size:.9rem;color:var(--color-text);letter-spacing:.01em}.login-form input[type=password]{width:100%;padding:.875rem 1rem;border:2px solid var(--color-grey-800);border-radius:8px;font-size:1rem;background:var(--color-background-input);color:var(--color-text-input);transition:all .2s ease;box-sizing:border-box}.login-form input[type=password]:focus{outline:none;border-color:var(--color-link);box-shadow:0 0 0 3px rgba(27,152,248,.1);transform:translateY(-1px)}.login-form input[type=password]::placeholder{color:var(--color-text-input-placeholder)}.login-form button[type=submit]{width:100%;padding:.875rem 1.5rem;font-size:1rem;font-weight:600;border-radius:8px;border:none;background:var(--color-background-button-primary);color:var(--color-text-button);cursor:pointer;transition:all .2s ease;box-shadow:0 2px 8px rgba(27,152,248,.2)}.login-form button[type=submit]:hover{box-shadow:0 4px 12px rgba(27,152,248,.3);background:#06c}.login-form button[type=submit]:active{transform:translateY(0);box-shadow:0 2px 4px rgba(27,152,248,.2)}.content-main>ul.messages{position:fixed;top:120px;left:50%;transform:translateX(-50%);list-style:none;padding:0;margin:0;z-index:1000;min-width:300px;max-width:500px}.content-main>ul.messages li{padding:1rem 1.25rem;border-radius:8px;font-size:.95rem;line-height:1.5;font-weight:500;box-shadow:0 4px 12px rgba(0,0,0,.15);animation:slideDown .3s ease-out;border:2px solid rgba(0,0,0,0)}.content-main>ul.messages li.error{background:#fee;border:2px solid #ef4444;color:#991b1b;font-weight:600}.content-main>ul.messages li.success{background:#f0fdf4;border:2px solid #10b981;color:#166534}.content-main>ul.messages li.info,.content-main>ul.messages li.message{background:#eff6ff;border:2px solid #3b82f6;color:#1e40af}@keyframes slideDown{from{opacity:0;transform:translateY(-20px)}to{opacity:1;transform:translateY(0)}}html[data-darkmode=true] .login-form .inner{box-shadow:0 10px 40px rgba(0,0,0,.4),0 2px 8px rgba(0,0,0,.2)}html[data-darkmode=true] .login-form .inner:hover{box-shadow:0 15px 50px rgba(0,0,0,.5),0 5px 15px rgba(0,0,0,.3)}html[data-darkmode=true] .login-form input[type=password]{border-color:var(--color-grey-400)}html[data-darkmode=true] .login-form input[type=password]:focus{border-color:var(--color-link)}html[data-darkmode=true] .content-main>ul.messages li{box-shadow:0 4px 12px rgba(0,0,0,.4)}html[data-darkmode=true] .content-main>ul.messages li.error{background:#4a1d1d;border-color:#ef4444;color:#fca5a5}html[data-darkmode=true] .content-main>ul.messages li.success{background:#1a3a2a;border-color:#10b981;color:#86efac}html[data-darkmode=true] .content-main>ul.messages li.info,html[data-darkmode=true] .content-main>ul.messages li.message{background:#1e3a5f;border-color:#3b82f6;color:#93c5fd}@media only screen and (max-width: 768px){.login-form{min-height:auto;padding:1rem .5rem;padding-top:5rem}.login-form .inner{padding:2rem 1.5rem;border-radius:12px}.content-main>ul.messages{top:70px;left:10px;right:10px;transform:none;min-width:auto}}body.wrapped-tabs .tabs ul{grid-template-columns:repeat(auto-fill, minmax(var(--tab-width, 180px), 1fr));grid-auto-flow:row;grid-auto-columns:unset;gap:0;column-gap:5px}body.wrapped-tabs .tabs ul li{border-radius:0}.tabs ul{margin:0px;padding:0px;display:grid;grid-auto-flow:column;grid-auto-columns:max-content;gap:5px;list-style:none}.tabs ul li{white-space:nowrap;color:var(--color-text-tab);border-top-left-radius:5px;border-top-right-radius:5px;background-color:var(--color-background-tab)}.tabs ul li:not(.active):hover{background-color:var(--color-background-tab-hover)}.tabs ul li.active,.tabs ul li :target{background-color:var(--color-background)}.tabs ul li.active a,.tabs ul li :target a{color:var(--color-text-tab-active);font-weight:bold}.tabs ul li a{display:block;padding:.7em;color:var(--color-text-tab)}body{color:var(--color-text);background:var(--color-background-page);font-family:Helvetica Neue,Helvetica,Lucida Grande,Arial,Ubuntu,Cantarell,Fira Sans,sans-serif}.visually-hidden{clip:rect(0 0 0 0);clip-path:inset(50%);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px}.status-icon{display:inline-block;height:1rem;vertical-align:middle}.pure-table-even{background:var(--color-background)}a{text-decoration:none;color:var(--color-link)}a.github-link{color:var(--color-icon-github);margin:0 1rem 0 .5rem}a.github-link svg{fill:currentColor}a.github-link:hover{color:var(--color-icon-github-hover)}#search-result-info{color:#fff}button.toggle-button{vertical-align:middle;background:rgba(0,0,0,0);border:none;cursor:pointer;color:var(--color-icon-github)}button.toggle-button:hover{color:var(--color-icon-github-hover)}button.toggle-button svg{fill:currentColor}button.toggle-button .icon-light{display:block}.pure-menu-horizontal{background:var(--color-background);padding:5px;display:flex;justify-content:space-between;align-items:center}#pure-menu-horizontal-spinner{height:3px;background:linear-gradient(-75deg, #ff6000, #ff8f00, #ffdd00, #ed0000);background-size:400% 400%;width:100%;animation:gradient 200s ease infinite}body.spinner-active #pure-menu-horizontal-spinner{animation:gradient 1s ease infinite}@keyframes gradient{0%{background-position:0% 50%}50%{background-position:100% 50%}100%{background-position:0% 50%}}.pure-menu-heading{color:var(--color-text-menu-heading)}.pure-menu-link{color:var(--color-text-menu-link)}.pure-menu-link:hover{background-color:var(--color-background-menu-link-hover);color:var(--color-text-menu-link-hover)}.tab-pane-inner{scroll-margin-top:200px}section.content{padding-bottom:1em;flex-direction:column;display:flex;align-items:center;justify-content:center}@media only screen and (max-width: 980px){section.content{padding-top:80px}}@media only screen and (min-width: 980px){section.content{padding-top:100px}}code{background:var(--color-background-code);color:var(--color-text)}.inline-tag,.restock-label,.tracking-ldjson-price-data,.watch-tag-list,.processor-badge{white-space:nowrap;border-radius:5px;padding:2px 5px;margin-right:4px;line-height:1.2rem}.processor-badge{font-weight:900}.watch-tag-list{color:var(--color-white);background:var(--color-text-watch-tag-list)}@media(min-width: 768px){.box{margin:0 1em !important}}.box{max-width:100%;margin:0 .3em;flex-direction:column;display:flex;justify-content:center}body:after{content:"";background:linear-gradient(130deg, var(--color-background-gradient-first), var(--color-background-gradient-second) 41.07%, var(--color-background-gradient-third) 84.05%)}body:after,body:before{display:block;height:650px;position:absolute;top:0;left:0;width:100%;z-index:-1}body::after{opacity:.91}body::before{content:""}body:after,body:before{-webkit-clip-path:polygon(100% 0, 0 0, 0 77.5%, 1% 77.4%, 2% 77.1%, 3% 76.6%, 4% 75.9%, 5% 75.05%, 6% 74.05%, 7% 72.95%, 8% 71.75%, 9% 70.55%, 10% 69.3%, 11% 68.05%, 12% 66.9%, 13% 65.8%, 14% 64.8%, 15% 64%, 16% 63.35%, 17% 62.85%, 18% 62.6%, 19% 62.5%, 20% 62.65%, 21% 63%, 22% 63.5%, 23% 64.2%, 24% 65.1%, 25% 66.1%, 26% 67.2%, 27% 68.4%, 28% 69.65%, 29% 70.9%, 30% 72.15%, 31% 73.3%, 32% 74.35%, 33% 75.3%, 34% 76.1%, 35% 76.75%, 36% 77.2%, 37% 77.45%, 38% 77.5%, 39% 77.3%, 40% 76.95%, 41% 76.4%, 42% 75.65%, 43% 74.75%, 44% 73.75%, 45% 72.6%, 46% 71.4%, 47% 70.15%, 48% 68.9%, 49% 67.7%, 50% 66.55%, 51% 65.5%, 52% 64.55%, 53% 63.75%, 54% 63.15%, 55% 62.75%, 56% 62.55%, 57% 62.5%, 58% 62.7%, 59% 63.1%, 60% 63.7%, 61% 64.45%, 62% 65.4%, 63% 66.45%, 64% 67.6%, 65% 68.8%, 66% 70.05%, 67% 71.3%, 68% 72.5%, 69% 73.6%, 70% 74.65%, 71% 75.55%, 72% 76.35%, 73% 76.9%, 74% 77.3%, 75% 77.5%, 76% 77.45%, 77% 77.25%, 78% 76.8%, 79% 76.2%, 80% 75.4%, 81% 74.45%, 82% 73.4%, 83% 72.25%, 84% 71.05%, 85% 69.8%, 86% 68.55%, 87% 67.35%, 88% 66.2%, 89% 65.2%, 90% 64.3%, 91% 63.55%, 92% 63%, 93% 62.65%, 94% 62.5%, 95% 62.55%, 96% 62.8%, 97% 63.3%, 98% 63.9%, 99% 64.75%, 100% 65.7%);clip-path:polygon(100% 0, 0 0, 0 77.5%, 1% 77.4%, 2% 77.1%, 3% 76.6%, 4% 75.9%, 5% 75.05%, 6% 74.05%, 7% 72.95%, 8% 71.75%, 9% 70.55%, 10% 69.3%, 11% 68.05%, 12% 66.9%, 13% 65.8%, 14% 64.8%, 15% 64%, 16% 63.35%, 17% 62.85%, 18% 62.6%, 19% 62.5%, 20% 62.65%, 21% 63%, 22% 63.5%, 23% 64.2%, 24% 65.1%, 25% 66.1%, 26% 67.2%, 27% 68.4%, 28% 69.65%, 29% 70.9%, 30% 72.15%, 31% 73.3%, 32% 74.35%, 33% 75.3%, 34% 76.1%, 35% 76.75%, 36% 77.2%, 37% 77.45%, 38% 77.5%, 39% 77.3%, 40% 76.95%, 41% 76.4%, 42% 75.65%, 43% 74.75%, 44% 73.75%, 45% 72.6%, 46% 71.4%, 47% 70.15%, 48% 68.9%, 49% 67.7%, 50% 66.55%, 51% 65.5%, 52% 64.55%, 53% 63.75%, 54% 63.15%, 55% 62.75%, 56% 62.55%, 57% 62.5%, 58% 62.7%, 59% 63.1%, 60% 63.7%, 61% 64.45%, 62% 65.4%, 63% 66.45%, 64% 67.6%, 65% 68.8%, 66% 70.05%, 67% 71.3%, 68% 72.5%, 69% 73.6%, 70% 74.65%, 71% 75.55%, 72% 76.35%, 73% 76.9%, 74% 77.3%, 75% 77.5%, 76% 77.45%, 77% 77.25%, 78% 76.8%, 79% 76.2%, 80% 75.4%, 81% 74.45%, 82% 73.4%, 83% 72.25%, 84% 71.05%, 85% 69.8%, 86% 68.55%, 87% 67.35%, 88% 66.2%, 89% 65.2%, 90% 64.3%, 91% 63.55%, 92% 63%, 93% 62.65%, 94% 62.5%, 95% 62.55%, 96% 62.8%, 97% 63.3%, 98% 63.9%, 99% 64.75%, 100% 65.7%)}.button-small{font-size:85%}.button-xsmall{font-size:70%}.fetch-error{padding-top:1em;font-size:80%;max-width:400px;display:block}.pure-button-primary,a.pure-button-primary,.pure-button-selected,a.pure-button-selected{background-color:var(--color-background-button-primary)}.button-secondary{color:var(--color-text-button);border-radius:4px;text-shadow:0 1px 1px rgba(0,0,0,.2)}.button-success{background:var(--color-background-button-success)}.button-tag{background:var(--color-background-button-tag);color:var(--color-text-button);font-size:65%;border-bottom-left-radius:initial;border-bottom-right-radius:initial;margin-right:4px}.button-tag.active{background:var(--color-background-button-tag-active);font-weight:bold}.button-error{background:var(--color-background-button-error);color:var(--color-text-button-error)}.button-warning{background:var(--color-background-button-warning);color:var(--color-text-button-warning)}.button-secondary{background:var(--color-background-button-secondary)}.button-cancel{background:var(--color-background-button-cancel)}.messages li{list-style:none;padding:1em;border-radius:10px;color:var(--color-text-messages);font-weight:bold}.messages li.message{background:var(--color-background-messages-message)}.messages li.error{background:var(--color-background-messages-error)}.messages li.notice{background:var(--color-background-messages-notice)}.messages.with-share-link>*:hover{cursor:pointer}.notifications-wrapper{padding-top:.5rem}.notifications-wrapper #notification-test-log{margin-top:1rem;padding:1rem;white-space:pre-wrap;word-break:break-word;overflow-wrap:break-word;max-width:100%;box-sizing:border-box;max-height:12rem;overflow-y:scroll;border:1px solid var(--color-border-notification);border-radius:5px}label:hover{cursor:pointer}.grey-form-border{border:1px solid var(--color-border-notification);padding:.5rem;border-radius:5px}#notification-error-log{border:1px solid var(--color-border-notification);padding:1rem;border-radius:5px;overflow-wrap:break-word}#token-table.pure-table td,#token-table.pure-table th{font-size:80%}.pure-form input[type=text].transparent-field{background-color:var(--color-background-new-watch-input-transparent) !important;color:var(--color-white) !important;border:1px solid hsla(0,0%,100%,.2) !important;box-shadow:none !important;-webkit-box-shadow:none !important}.pure-form input[type=text].transparent-field::placeholder{opacity:.5;color:hsla(0,0%,100%,.7);font-weight:lighter}#new-watch-form{background:var(--color-background-new-watch-form);padding:1em;border-radius:10px;margin-bottom:1em;max-width:100%}#new-watch-form #url::placeholder{font-weight:bold}#new-watch-form input{display:inline-block;margin-bottom:5px}#new-watch-form input:not(.pure-button){background-color:var(--color-background-new-watch-input);color:var(--color-text-new-watch-input)}#new-watch-form .label{display:none}#new-watch-form legend{color:var(--color-text-legend);font-weight:bold}@media only screen and (min-width: 760px){#new-watch-form #watch-add-wrapper-zone{display:flex;gap:.3rem;flex-direction:row;min-width:70vw}}#new-watch-form #watch-add-wrapper-zone>span{flex-grow:0}#new-watch-form #watch-add-wrapper-zone>span input{width:100%;padding-right:1em}#new-watch-form #watch-add-wrapper-zone>span:first-child{flex-grow:1}@media only screen and (max-width: 760px){#new-watch-form #watch-add-wrapper-zone #url{width:100%}}#new-watch-form #watch-group-tag{font-size:.9rem;padding:.3rem;display:flex;align-items:center;gap:.5rem;color:var(--color-white)}#new-watch-form #watch-group-tag label,#new-watch-form #watch-group-tag input{margin:0}#new-watch-form #watch-group-tag input{flex:1}#diff-col{padding-left:40px}#diff-jump{position:fixed;left:0px;top:120px;background:var(--color-background);padding:10px;border-top-right-radius:5px;border-bottom-right-radius:5px;box-shadow:1px 1px 4px var(--color-shadow-jump)}#diff-jump a{color:var(--color-link);cursor:pointer;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;-o-user-select:none}footer{padding:10px;background:var(--color-background);color:var(--color-text-footer);text-align:center}#feed-icon{vertical-align:middle}.sticky-tab{position:absolute;top:60px;font-size:65%;background:var(--color-background);padding:10px}@media only screen and (max-width: 980px){.sticky-tab{display:none}}.sticky-tab#left-sticky{left:0;position:fixed;border-top-right-radius:5px;border-bottom-right-radius:5px;box-shadow:1px 1px 4px var(--color-shadow-jump)}.sticky-tab#right-sticky{right:0px}.sticky-tab#hosted-sticky{right:0px;top:100px;font-weight:bold}#new-version-text a{color:var(--color-link-new-version)}.watch-controls{color:#f8321b}.watch-controls .state-on img{opacity:.8}.watch-controls img{opacity:.2}.watch-controls img:hover{transition:opacity .3s;opacity:.8}.monospaced-textarea textarea{width:100%;font-family:monospace;white-space:pre;overflow-wrap:normal;overflow-x:auto}.pure-form fieldset{padding-top:0px}.pure-form fieldset ul{padding-bottom:0px;margin-bottom:0px}.pure-form .pure-control-group,.pure-form .pure-group,.pure-form .pure-controls{padding-bottom:1em}.pure-form .pure-control-group div,.pure-form .pure-group div,.pure-form .pure-controls div{margin:0px}.pure-form .pure-control-group .checkbox>*,.pure-form .pure-group .checkbox>*,.pure-form .pure-controls .checkbox>*{display:inline;vertical-align:middle}.pure-form .pure-control-group .checkbox>label,.pure-form .pure-group .checkbox>label,.pure-form .pure-controls .checkbox>label{padding-left:5px}.pure-form .pure-control-group legend,.pure-form .pure-group legend,.pure-form .pure-controls legend{color:var(--color-text-legend)}.pure-form .error input{background-color:var(--color-error-input)}.pure-form ul.errors{padding:.5em .6em;border:1px solid var(--color-error-list);border-radius:4px;vertical-align:middle;-webkit-box-sizing:border-box;box-sizing:border-box}.pure-form ul.errors li{margin-left:1em;color:var(--color-error-list)}.pure-form label{font-weight:bold}.pure-form textarea{width:100%}.pure-form .inline-radio ul{margin:0px;list-style:none}.pure-form .inline-radio ul li{display:flex;align-items:center;gap:1em}@media only screen and (max-width: 760px),(min-device-width: 768px)and (max-device-width: 980px){.edit-form{padding:.5em;margin:0}#nav-menu{overflow-x:scroll}}@media only screen and (max-width: 760px),(min-device-width: 768px)and (max-device-width: 980px){input[type=text]{width:100%}}.pure-table{border-color:var(--color-border-table-cell)}.pure-table thead{background-color:var(--color-background-table-thead);color:var(--color-text);border-bottom:1px solid var(--color-background-table-thead)}.pure-table td,.pure-table th{border-left-color:var(--color-border-table-cell)}.pure-table-striped tr:nth-child(2n-1) td{background-color:var(--color-table-stripe)}.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form select,.pure-form textarea{border:var(--color-border-input);box-shadow:inset 0 1px 3px var(--color-shadow-input);background-color:var(--color-background-input);color:var(--color-text-input)}.pure-form input[type=color]:active,.pure-form input[type=date]:active,.pure-form input[type=datetime-local]:active,.pure-form input[type=datetime]:active,.pure-form input[type=email]:active,.pure-form input[type=month]:active,.pure-form input[type=number]:active,.pure-form input[type=password]:active,.pure-form input[type=search]:active,.pure-form input[type=tel]:active,.pure-form input[type=text]:active,.pure-form input[type=time]:active,.pure-form input[type=url]:active,.pure-form input[type=week]:active,.pure-form select:active,.pure-form textarea:active{background-color:var(--color-background-input)}input::placeholder,textarea::placeholder{color:var(--color-text-input-placeholder)}.m-d{min-width:100%}@media only screen and (min-width: 761px){.m-d{min-width:80%}}.pure-form-stacked>div:first-child{display:block}.tab-pane-inner{padding:0px}.tab-pane-inner:not(:target){display:none}.tab-pane-inner:target{display:block}.beta-logo{height:50px;right:-3px;top:-3px;position:absolute}#selector-header{padding-bottom:1em}body.full-width .edit-form{width:95%}.edit-form{min-width:70%;max-width:95%}.edit-form .box-wrap{position:relative}.edit-form .inner{background:var(--color-background);padding:20px}.edit-form #actions{display:block;background:var(--color-background)}.edit-form #actions .pure-control-group{display:flex;gap:.625em;flex-wrap:wrap}.edit-form .pure-form-message-inline{padding-left:0;color:var(--color-text-input-description)}.edit-form .pure-form-message-inline code{font-size:.875em}.border-fieldset{border:1px solid #ccc;padding:1rem;border-radius:5px;margin-bottom:1rem}.border-fieldset h3{margin-top:0}.border-fieldset fieldset:last-of-type{padding-bottom:0}.border-fieldset fieldset:last-of-type .pure-control-group{padding-bottom:0}ul{padding-left:1em;padding-top:0px;margin-top:4px}.time-check-widget tr{display:inline}.time-check-widget tr input[type=number]{width:5em}@media only screen and (max-width: 760px){.time-check-widget tbody{display:grid;grid-template-columns:auto 1fr auto 1fr;gap:.625em .3125em;align-items:center}.time-check-widget tr{display:contents}.time-check-widget tr th{text-align:right;padding-right:5px}.time-check-widget tr input[type=number]{width:100%;max-width:5em}}#webdriver_delay{width:5em}#api-key:hover{cursor:pointer}#api-key-copy{color:var(--color-api-key)}.button-green{background-color:var(--color-background-button-green)}.button-red{background-color:var(--color-background-button-red)}.noselect{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#checkbox-operations{background:var(--color-background-checkbox-operations);padding:1em;border-radius:10px;margin-bottom:1em;display:none}#checkbox-operations button{margin-bottom:3px;margin-top:3px;display:inline-flex;align-items:center}.checkbox-uuid>*{vertical-align:middle}.inline-warning{border:1px solid var(--color-border-warning);padding:.5rem;border-radius:5px;color:var(--color-warning)}.inline-warning>span{display:inline-block;vertical-align:middle}.inline-warning img.inline-warning-icon{display:inline;height:26px;vertical-align:middle}.tracking-ldjson-price-data{background-color:var(--color-background-button-green);color:#000;opacity:.6}.ldjson-price-track-offer{font-weight:bold;font-style:italic}.ldjson-price-track-offer a.pure-button{border-radius:3px;padding:3px;background-color:var(--color-background-button-green)}.price-follow-tag-icon{display:inline-block;height:.8rem;vertical-align:middle}#quick-watch-processor-type ul#processor{color:#fff;padding-left:0px}#quick-watch-processor-type ul#processor li{list-style:none;font-size:.9rem;display:grid;grid-template-columns:auto 1fr;align-items:center;gap:.5rem;margin-bottom:.5rem}#quick-watch-processor-type label,#quick-watch-processor-type input{padding:0;margin:0}.restock-label.in-stock{background-color:var(--color-background-button-green);color:#fff}.restock-label.not-in-stock{background-color:var(--color-background-button-cancel);color:#777}.restock-label.error{background-color:var(--color-background-button-error);color:#fff;opacity:.7}.restock-label svg{vertical-align:middle}#chrome-extension-link{padding:9px;border:1px solid var(--color-grey-800);border-radius:10px;vertical-align:middle}#chrome-extension-link img{height:21px;padding:2px;vertical-align:middle}#realtime-conn-error{position:fixed;bottom:0;left:0;background:var(--color-warning);padding:10px;font-size:.8rem;color:#fff;opacity:.8}#bottom-horizontal-offscreen{position:fixed;bottom:0;left:0;right:0;width:100%;min-height:50px;max-height:50vh;background:hsla(0,0%,100%,.7215686275);border-top:1px solid var(--color-border-table-cell);padding:10px;box-shadow:0 -2px 10px rgba(0,0,0,.2);z-index:100;overflow-y:auto;transition:opacity .3s ease-in-out;scroll-margin-bottom:10px;display:flex;justify-content:center;align-items:center}ul#highlightSnippetActions{list-style:none}ul#highlightSnippetActions li{display:inline-block} diff --git a/changedetectionio/templates/base.html b/changedetectionio/templates/base.html index 35df0b70a..cc29d399d 100644 --- a/changedetectionio/templates/base.html +++ b/changedetectionio/templates/base.html @@ -1,5 +1,5 @@ - + diff --git a/changedetectionio/tests/test_i18n.py b/changedetectionio/tests/test_i18n.py index 76fa8f3e9..8643427c7 100644 --- a/changedetectionio/tests/test_i18n.py +++ b/changedetectionio/tests/test_i18n.py @@ -1,7 +1,71 @@ #!/usr/bin/env python3 from flask import url_for -from .util import live_server_setup +from .util import live_server_setup, wait_for_all_checks + + +def test_zh_TW(client, live_server, measure_memory_usage, datastore_path): + import time + test_url = url_for('test_endpoint', _external=True) + + # Be sure we got a session cookie + res = client.get(url_for("watchlist.index"), follow_redirects=True) + + res = client.get( + url_for("set_language", locale="zh_Hant_TW"), # Traditional + follow_redirects=True + ) + # HTML follows BCP 47 language tag rules, not underscore-based locale formats. + assert b'zh + res = client.get( + url_for("set_language", locale="zh"), # Simplified chinese + follow_redirects=True + ) + res = client.get(url_for("watchlist.index"), follow_redirects=True) + assert "选择语言".encode() in res.data, "Simplified chinese worked and it means the flask-babel cache worked" + + +# timeago library just hasn't been updated to use the more modern locale naming convention, before BCP 47 / RFC 5646. +# The Python timeago library (https://github.com/hustcc/timeago) supports 48 locales but uses different naming conventions than Flask-Babel. +def test_zh_Hant_TW_timeago_integration(): + """Test that zh_Hant_TW mapping works and timeago renders Traditional Chinese correctly""" + import timeago + from datetime import datetime, timedelta + from changedetectionio.languages import get_timeago_locale + + # 1. Test the mapping + mapped_locale = get_timeago_locale('zh_Hant_TW') + assert mapped_locale == 'zh_TW', "zh_Hant_TW should map to timeago's zh_TW" + assert get_timeago_locale('zh_TW') == 'zh_TW', "zh_TW should also map to zh_TW" + + # 2. Test timeago library renders Traditional Chinese with the mapped locale + now = datetime.now() + + # Test various time periods with Traditional Chinese strings + result_15s = timeago.format(now - timedelta(seconds=15), now, mapped_locale) + assert '秒前' in result_15s, f"Expected '秒前' in '{result_15s}'" + + result_5m = timeago.format(now - timedelta(minutes=5), now, mapped_locale) + assert '分鐘前' in result_5m, f"Expected '分鐘前' in '{result_5m}'" + + result_2h = timeago.format(now - timedelta(hours=2), now, mapped_locale) + assert '小時前' in result_2h, f"Expected '小時前' in '{result_2h}'" + + result_3d = timeago.format(now - timedelta(days=3), now, mapped_locale) + assert '天前' in result_3d, f"Expected '天前' in '{result_3d}'" def test_language_switching(client, live_server, measure_memory_usage, datastore_path): @@ -13,6 +77,9 @@ def test_language_switching(client, live_server, measure_memory_usage, datastore 3. Switch back to English and verify English text appears """ + # Establish session cookie + client.get(url_for("watchlist.index"), follow_redirects=True) + # Step 1: Set the language to Italian using the /set-language endpoint res = client.get( url_for("set_language", locale="it"), @@ -61,6 +128,9 @@ def test_invalid_locale(client, live_server, measure_memory_usage, datastore_pat The app should ignore invalid locales and continue working. """ + # Establish session cookie + client.get(url_for("watchlist.index"), follow_redirects=True) + # First set to English res = client.get( url_for("set_language", locale="en"), @@ -93,6 +163,9 @@ def test_language_persistence_in_session(client, live_server, measure_memory_usa within the same session. """ + # Establish session cookie + client.get(url_for("watchlist.index"), follow_redirects=True) + # Set language to Italian res = client.get( url_for("set_language", locale="it"), @@ -119,6 +192,9 @@ def test_set_language_with_redirect(client, live_server, measure_memory_usage, d """ from flask import url_for + # Establish session cookie + client.get(url_for("watchlist.index"), follow_redirects=True) + # Set language with a redirect parameter (simulating language change from /settings) res = client.get( url_for("set_language", locale="de", redirect="/settings"), diff --git a/changedetectionio/translations/zh_Hant_TW/LC_MESSAGES/messages.mo b/changedetectionio/translations/zh_Hant_TW/LC_MESSAGES/messages.mo new file mode 100644 index 000000000..ddfd0282d Binary files /dev/null and b/changedetectionio/translations/zh_Hant_TW/LC_MESSAGES/messages.mo differ diff --git a/changedetectionio/translations/zh_TW/LC_MESSAGES/messages.po b/changedetectionio/translations/zh_Hant_TW/LC_MESSAGES/messages.po similarity index 72% rename from changedetectionio/translations/zh_TW/LC_MESSAGES/messages.po rename to changedetectionio/translations/zh_Hant_TW/LC_MESSAGES/messages.po index c321a4392..c349a9c27 100644 --- a/changedetectionio/translations/zh_TW/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/zh_Hant_TW/LC_MESSAGES/messages.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2026-01-03 14:31+0100\n" -"PO-Revision-Date: 2026-01-02 12:37+0100\n" +"PO-Revision-Date: 2026-01-15 12:00+0800\n" "Last-Translator: FULL NAME \n" "Language: zh_Hant_TW\n" "Language-Team: zh_Hant_TW \n" @@ -27,59 +27,55 @@ msgstr "還沒有" #: changedetectionio/flask_app.py:534 msgid "Already logged in" -msgstr "" +msgstr "已經登入" #: changedetectionio/flask_app.py:536 msgid "You must be logged in, please log in." -msgstr "" +msgstr "您必須先登入,請登入。" #: changedetectionio/flask_app.py:551 -#, fuzzy msgid "Incorrect password" -msgstr "密碼" +msgstr "密碼錯誤" #: changedetectionio/forms.py:63 changedetectionio/forms.py:243 msgid "" "At least one time interval (weeks, days, hours, minutes, or seconds) must" " be specified." -msgstr "" +msgstr "必須指定至少一個時間間隔(週、天、小時、分鐘或秒)。" #: changedetectionio/forms.py:64 msgid "" "At least one time interval (weeks, days, hours, minutes, or seconds) must" " be specified when not using global settings." -msgstr "" +msgstr "當不使用全域設定時,必須指定至少一個時間間隔(週、天、小時、分鐘或秒)。" #: changedetectionio/forms.py:164 msgid "Invalid time format. Use HH:MM." -msgstr "時間格式無效。使用時:分。" +msgstr "時間格式無效。請使用 HH:MM。" #: changedetectionio/forms.py:180 msgid "Not a valid timezone name" msgstr "不是有效的時區名稱" #: changedetectionio/forms.py:183 -#, fuzzy msgid "not set" -msgstr "還沒有" +msgstr "未設定" #: changedetectionio/forms.py:184 -#, fuzzy msgid "Start At" -msgstr "統計數據" +msgstr "開始於" #: changedetectionio/forms.py:185 -#, fuzzy msgid "Run duration" -msgstr "暫無信息" +msgstr "執行時長" #: changedetectionio/forms.py:188 msgid "Use time scheduler" -msgstr "使用時間調度器" +msgstr "使用時間排程器" #: changedetectionio/forms.py:198 msgid "Optional timezone to run in" -msgstr "運行時的可選時區" +msgstr "執行時的選用時區" #: changedetectionio/forms.py:212 msgid "Monday" @@ -99,7 +95,7 @@ msgstr "週四" #: changedetectionio/forms.py:216 msgid "Friday" -msgstr "星期五" +msgstr "週五" #: changedetectionio/forms.py:217 msgid "Saturday" @@ -107,77 +103,74 @@ msgstr "週六" #: changedetectionio/forms.py:218 msgid "Sunday" -msgstr "星期日" +msgstr "週日" #: changedetectionio/forms.py:251 msgid "Weeks" -msgstr "週數" +msgstr "週" #: changedetectionio/forms.py:251 changedetectionio/forms.py:252 #: changedetectionio/forms.py:253 changedetectionio/forms.py:254 #: changedetectionio/forms.py:255 changedetectionio/forms.py:955 msgid "Should contain zero or more seconds" -msgstr "應包含零或更多秒" +msgstr "應包含 0 或更多秒" #: changedetectionio/forms.py:252 msgid "Days" msgstr "天" #: changedetectionio/forms.py:253 -#, fuzzy msgid "Hours" -msgstr "字" +msgstr "小時" #: changedetectionio/forms.py:254 -#, fuzzy msgid "Minutes" -msgstr "沉默的" +msgstr "分鐘" #: changedetectionio/forms.py:255 -#, fuzzy msgid "Seconds" msgstr "秒" #: changedetectionio/forms.py:460 msgid "Notification Body and Title is required when a Notification URL is used" -msgstr "使用通知 URL 時需要通知正文和標題" +msgstr "使用通知 URL 時,必須填寫通知內容與標題" #: changedetectionio/forms.py:489 #, python-format msgid "'%s' is not a valid AppRise URL." -msgstr "“%s”不是有效的 AppRise URL。" +msgstr "「%s」不是有效的 AppRise URL。" #: changedetectionio/forms.py:562 changedetectionio/forms.py:581 #, python-format msgid "RegEx '%s' is not a valid regular expression." -msgstr "RegEx“%s”不是有效的正則表達式。" +msgstr "RegEx 「%s」不是有效的正規表示式。" #: changedetectionio/forms.py:622 changedetectionio/forms.py:637 #, python-format msgid "'%s' is not a valid XPath expression. (%s)" -msgstr "“%s”不是有效的 XPath 表達式。 (%s)" +msgstr "「%s」不是有效的 XPath 表達式 (%s)。" #: changedetectionio/forms.py:657 #, python-format msgid "'%s' is not a valid JSONPath expression. (%s)" -msgstr "“%s”不是有效的 JSONPath 表達式。 (%s)" +msgstr "「%s」不是有效的 JSONPath 表達式 (%s)。" #: changedetectionio/forms.py:679 #, python-format msgid "'%s' is not a valid jq expression. (%s)" -msgstr "“%s”不是有效的 jq 表達式。 (%s)" +msgstr "「%s」不是有效的 jq 表達式 (%s)。" #: changedetectionio/forms.py:725 msgid "Empty value not allowed." -msgstr "不允許為空值。" +msgstr "不允許空值。" #: changedetectionio/forms.py:727 msgid "Invalid value." -msgstr "無效值。" +msgstr "數值無效。" #: changedetectionio/forms.py:732 msgid "Watch" -msgstr "監控" +msgstr "監測任務" #: changedetectionio/forms.py:733 changedetectionio/forms.py:766 msgid "Processor" @@ -185,101 +178,87 @@ msgstr "處理器" #: changedetectionio/forms.py:734 msgid "Edit > Watch" -msgstr "編輯 > 監控" +msgstr "編輯 > 監測任務" #: changedetectionio/forms.py:747 changedetectionio/forms.py:994 -#, fuzzy msgid "Fetch Method" -msgstr "設置獲取方法" +msgstr "抓取方式" #: changedetectionio/forms.py:748 -#, fuzzy msgid "Notification Body" -msgstr "通知" +msgstr "通知內容" #: changedetectionio/forms.py:749 -#, fuzzy msgid "Notification format" -msgstr "通知" +msgstr "通知格式" #: changedetectionio/forms.py:750 -#, fuzzy msgid "Notification Title" -msgstr "通知" +msgstr "通知標題" #: changedetectionio/forms.py:751 -#, fuzzy msgid "Notification URL List" -msgstr "通知" +msgstr "通知 URL 列表" #: changedetectionio/forms.py:752 msgid "Processor - What do you want to achieve?" -msgstr "處理器 - 您想要實現什麼?" +msgstr "處理器 - 您想要達成什麼目標?" #: changedetectionio/forms.py:753 msgid "Default timezone for watch check scheduler" -msgstr "手錶檢查調度程序的默認時區" +msgstr "監測排程的預設時區" #: changedetectionio/forms.py:754 -#, fuzzy msgid "Wait seconds before extracting text" -msgstr "提取文本前幾秒。" +msgstr "提取文字前的等待秒數" #: changedetectionio/forms.py:754 msgid "Should contain one or more seconds" -msgstr "應包含一秒或多秒" +msgstr "應包含 1 秒或更多秒" #: changedetectionio/forms.py:767 -#, fuzzy msgid "URLs" -msgstr "網址" +msgstr "URL 列表" #: changedetectionio/forms.py:768 msgid "Upload .xlsx file" -msgstr "上傳 .xlsx 文件" +msgstr "上傳 .xlsx 檔案" #: changedetectionio/forms.py:768 msgid "Must be .xlsx file!" -msgstr "必須是 .xlsx 文件!" +msgstr "必須是 .xlsx 檔案!" #: changedetectionio/forms.py:769 -#, fuzzy msgid "File mapping" -msgstr "文件映射類型。" +msgstr "檔案對應" #: changedetectionio/forms.py:773 -#, fuzzy msgid "Operation" -msgstr "用戶界面選項" +msgstr "操作" #: changedetectionio/forms.py:776 -#, fuzzy msgid "Selector" -msgstr "選擇方式:" +msgstr "選擇器" #: changedetectionio/forms.py:777 -#, fuzzy msgid "value" -msgstr "暫停" +msgstr "值" #: changedetectionio/forms.py:796 msgid "Use global settings for time between check and scheduler." -msgstr "使用全局設置檢查和調度程序之間的時間。" +msgstr "檢查與排程時間使用全域設定。" #: changedetectionio/forms.py:798 -#, fuzzy msgid "CSS/JSONPath/JQ/XPath Filters" -msgstr "CSS/xPath 過濾器" +msgstr "CSS / JSONPath / JQ / XPath 過濾器" #: changedetectionio/forms.py:800 changedetectionio/forms.py:996 -#, fuzzy msgid "Remove elements" -msgstr "按元素選擇" +msgstr "移除元素" #: changedetectionio/forms.py:802 -#, fuzzy msgid "Extract text" -msgstr "提取數據" +msgstr "提取文字" #: changedetectionio/blueprint/imports/templates/import.html:106 #: changedetectionio/forms.py:804 @@ -287,81 +266,74 @@ msgid "Title" msgstr "標題" #: changedetectionio/forms.py:806 -#, fuzzy msgid "Ignore lines containing" -msgstr "忽略任何匹配的行" +msgstr "忽略包含此內容的行" #: changedetectionio/forms.py:808 -#, fuzzy msgid "Request body" -msgstr "要求" +msgstr "請求內容" #: changedetectionio/forms.py:809 -#, fuzzy msgid "Request method" -msgstr "要求" +msgstr "請求方式" #: changedetectionio/forms.py:810 msgid "Ignore status codes (process non-2xx status codes as normal)" -msgstr "忽略狀態代碼(正常處理非 2xx 狀態代碼)" +msgstr "忽略狀態碼(將非 2xx 狀態碼視為正常處理)" #: changedetectionio/forms.py:811 -#, fuzzy msgid "Only trigger when unique lines appear in all history" -msgstr "僅當出現唯一線條時觸發" +msgstr "僅當歷史記錄中出現獨特行時觸發" #: changedetectionio/blueprint/ui/templates/edit.html:336 #: changedetectionio/forms.py:812 msgid "Remove duplicate lines of text" -msgstr "刪除重複的文本行" +msgstr "移除重複的文字行" #: changedetectionio/forms.py:813 msgid "Sort text alphabetically" -msgstr "按字母順序對文本進行排序" +msgstr "按字母順序排序文字" #: changedetectionio/forms.py:814 changedetectionio/forms.py:1023 msgid "Strip ignored lines" -msgstr "去掉忽略的行" +msgstr "移除被忽略的行" #: changedetectionio/forms.py:815 -#, fuzzy msgid "Trim whitespace before and after text" -msgstr "刪除每行文本前後的所有空格" +msgstr "移除文字前後的空白" #: changedetectionio/forms.py:817 -#, fuzzy msgid "Added lines" -msgstr "線路" +msgstr "新增的行" #: changedetectionio/forms.py:818 msgid "Replaced/changed lines" -msgstr "更換/更改線路" +msgstr "替換 / 變更的行" #: changedetectionio/forms.py:819 -#, fuzzy msgid "Removed lines" -msgstr "已刪除" +msgstr "移除的行" #: changedetectionio/forms.py:821 msgid "Keyword triggers - Trigger/wait for text" -msgstr "關鍵字觸發器 - 觸發/等待文本" +msgstr "關鍵字觸發 - 觸發 / 等待文字" #: changedetectionio/forms.py:824 msgid "Block change-detection while text matches" -msgstr "文本匹配時阻止更改檢測" +msgstr "當文字符合時,阻擋變更檢測" #: changedetectionio/forms.py:825 msgid "Execute JavaScript before change detection" -msgstr "在更改檢測之前執行 JavaScript" +msgstr "在變更檢測前執行 JavaScript" #: changedetectionio/blueprint/tags/templates/groups-overview.html:17 #: changedetectionio/forms.py:827 changedetectionio/forms.py:1051 msgid "Save" -msgstr "節省" +msgstr "儲存" #: changedetectionio/forms.py:829 msgid "Proxy" -msgstr "代理" +msgstr "代理伺服器" #: changedetectionio/forms.py:831 msgid "Send a notification when the filter can no longer be found on the page" @@ -375,54 +347,52 @@ msgid "Notifications" msgstr "通知" #: changedetectionio/forms.py:832 -#, fuzzy msgid "Muted" -msgstr "沉默的" +msgstr "已靜音" #: changedetectionio/forms.py:832 -#, fuzzy msgid "On" -msgstr "沒有任何" +msgstr "開啟" #: changedetectionio/forms.py:833 msgid "Attach screenshot to notification (where possible)" -msgstr "將屏幕截圖附加到通知(如果可能)" +msgstr "將截圖附加到通知中(如果支援)" #: changedetectionio/forms.py:835 msgid "Match" -msgstr "# 手錶" +msgstr "符合" #: changedetectionio/forms.py:835 msgid "Match all of the following" -msgstr "匹配以下所有內容" +msgstr "符合以下所有條件" #: changedetectionio/forms.py:835 msgid "Match any of the following" -msgstr "匹配以下任意一項" +msgstr "符合以下任一條件" #: changedetectionio/forms.py:837 msgid "Use page in list" -msgstr "使用列表中的頁面<標題>" +msgstr "在列表中使用頁面 <title>" #: changedetectionio/forms.py:854 msgid "Body must be empty when Request Method is set to GET" -msgstr "當請求方法設置為 GET 時,正文必須為空" +msgstr "當請求方法設為 GET 時,內容必須為空" #: changedetectionio/forms.py:863 changedetectionio/forms.py:877 #: changedetectionio/forms.py:892 #, python-format msgid "Invalid template syntax configuration: %(error)s" -msgstr "模板語法配置無效:%(error)s" +msgstr "範本語法設定無效:%(error)s" #: changedetectionio/forms.py:867 changedetectionio/forms.py:881 #, python-format msgid "Invalid template syntax: %(error)s" -msgstr "無效的模板語法:%(error)s" +msgstr "無效的範本語法:%(error)s" #: changedetectionio/forms.py:896 #, python-format msgid "Invalid template syntax in \"%(header)s\" header: %(error)s" -msgstr "" +msgstr "「%(header)s」標頭中的範本語法無效:%(error)s" #: changedetectionio/forms.py:920 changedetectionio/forms.py:932 msgid "Name" @@ -430,15 +400,15 @@ msgstr "名稱" #: changedetectionio/forms.py:921 msgid "Proxy URL" -msgstr "代理網址" +msgstr "代理伺服器 URL" #: changedetectionio/forms.py:926 msgid "Proxy URLs must start with http://, https:// or socks5://" -msgstr "代理 URL 必須以 http://、https:// 或ocks5:// 開頭" +msgstr "代理伺服器 URL 必須以 http://、https:// 或 socks5:// 開頭" #: changedetectionio/forms.py:933 msgid "Browser connection URL" -msgstr "瀏覽器連接網址" +msgstr "瀏覽器連線 URL" #: changedetectionio/forms.py:938 msgid "Browser URLs must start with wss:// or ws://" @@ -446,23 +416,23 @@ msgstr "瀏覽器 URL 必須以 wss:// 或 ws:// 開頭" #: changedetectionio/forms.py:944 msgid "Plaintext requests" -msgstr "明文請求" +msgstr "純文字請求" #: changedetectionio/forms.py:946 msgid "Chrome requests" -msgstr "Chrome請求" +msgstr "Chrome 請求" #: changedetectionio/forms.py:952 msgid "Default proxy" -msgstr "默認代理" +msgstr "預設代理伺服器" #: changedetectionio/forms.py:953 msgid "Random jitter seconds ± check" -msgstr "隨機抖動秒±檢查" +msgstr "隨機抖動秒數 ± 檢查" #: changedetectionio/forms.py:957 msgid "Number of fetch workers" -msgstr "取貨工人數量" +msgstr "抓取工作程序 (Worker) 數量" #: changedetectionio/forms.py:960 msgid "Should be between 1 and 50" @@ -470,7 +440,7 @@ msgstr "應介於 1 到 50 之間" #: changedetectionio/forms.py:962 msgid "Requests timeout in seconds" -msgstr "請求超時(以秒為單位)" +msgstr "請求逾時(秒)" #: changedetectionio/forms.py:965 msgid "Should be between 1 and 999" @@ -478,51 +448,47 @@ msgstr "應介於 1 到 999 之間" #: changedetectionio/forms.py:970 msgid "Default User-Agent overrides" -msgstr "默認用戶代理覆蓋" +msgstr "預設 User-Agent 覆寫" #: changedetectionio/forms.py:976 msgid "Both a name, and a Proxy URL is required." -msgstr "名稱和代理 URL 都是必需的。" +msgstr "名稱與代理伺服器 URL 皆為必填。" #: changedetectionio/forms.py:980 msgid "Open 'History' page in a new tab" -msgstr "在新選項卡中打開“歷史記錄”頁面" +msgstr "在新分頁開啟「歷史記錄」頁面" #: changedetectionio/forms.py:981 -#, fuzzy msgid "Realtime UI Updates Enabled" -msgstr "離線實時更新" +msgstr "已啟用即時 UI 更新" #: changedetectionio/forms.py:982 -#, fuzzy msgid "Favicons Enabled" -msgstr "考慮啟用" +msgstr "啟用網站圖示 (Favicons)" #: changedetectionio/forms.py:983 msgid "Use page <title> in watch overview list" -msgstr "在觀看概覽列表中使用頁面<標題>" +msgstr "在監測概覽列表中使用頁面 <title>" #: changedetectionio/forms.py:988 msgid "API access token security check enabled" -msgstr "已啟用 API 訪問令牌安全檢查" +msgstr "已啟用 API 存取權杖安全檢查" #: changedetectionio/forms.py:989 msgid "Notification base URL override" -msgstr "通知基礎URL" +msgstr "通知基礎 URL 覆寫" #: changedetectionio/forms.py:993 msgid "Treat empty pages as a change?" -msgstr "將空頁視為更改?" +msgstr "將空白頁面視為變更?" #: changedetectionio/forms.py:995 -#, fuzzy msgid "Ignore Text" -msgstr "錯誤文本" +msgstr "忽略文字" #: changedetectionio/forms.py:997 -#, fuzzy msgid "Ignore whitespace" -msgstr "忽略空格" +msgstr "忽略空白" #: changedetectionio/forms.py:1004 #: changedetectionio/processors/image_ssim_diff/forms.py:50 @@ -531,11 +497,11 @@ msgstr "必須介於 0 到 100 之間" #: changedetectionio/forms.py:1011 msgid "Pager size" -msgstr "尋呼機尺寸" +msgstr "分頁大小" #: changedetectionio/forms.py:1014 msgid "Should be atleast zero (disabled)" -msgstr "應至少為零(禁用)" +msgstr "應至少為 0(停用)" #: changedetectionio/forms.py:1016 msgid "RSS Content format" @@ -543,78 +509,76 @@ msgstr "RSS 內容格式" #: changedetectionio/forms.py:1017 msgid "RSS <description> body built from" -msgstr "RSS <描述> 正文構建於" +msgstr "RSS <description> 內容建立自" #: changedetectionio/forms.py:1018 msgid "RSS \"System default\" template override" -msgstr "" +msgstr "RSS「系統預設」範本覆寫" #: changedetectionio/forms.py:1020 -#, fuzzy msgid "Remove password" -msgstr "密碼" +msgstr "移除密碼" #: changedetectionio/forms.py:1021 msgid "Render anchor tag content" -msgstr "渲染錨標記內容" +msgstr "渲染錨點標籤內容" #: changedetectionio/forms.py:1022 msgid "Allow anonymous access to watch history page when password is enabled" -msgstr "啟用密碼後允許匿名訪問觀看歷史記錄頁面" +msgstr "啟用密碼時允許匿名存取監測歷史頁面" #: changedetectionio/forms.py:1024 msgid "Hide muted watches from RSS feed" -msgstr "從 RSS 源中隱藏靜音的手錶" +msgstr "從 RSS Feed 中隱藏已靜音的監測任務" #: changedetectionio/forms.py:1027 msgid "Enable RSS reader mode " -msgstr "啟用 RSS 閱讀器模式" +msgstr "啟用 RSS 閱讀器模式 " #: changedetectionio/forms.py:1028 msgid "Number of changes to show in watch RSS feed" -msgstr "觀看 RSS 源中顯示的更改數量" +msgstr "在 RSS Feed 中顯示的變更數量" #: changedetectionio/forms.py:1030 changedetectionio/forms.py:1035 msgid "Should contain zero or more attempts" -msgstr "應包含零次或多次嘗試" +msgstr "應包含 0 次或更多嘗試" #: changedetectionio/forms.py:1032 msgid "Number of times the filter can be missing before sending a notification" -msgstr "發送通知之前過濾器可能丟失的次數" +msgstr "發送通知前允許過濾器遺失的次數" #: changedetectionio/forms.py:1055 msgid "RegEx to extract" -msgstr "要提取的正則表達式" +msgstr "要提取的 RegEx" #: changedetectionio/forms.py:1056 -#, fuzzy msgid "Extract as CSV" -msgstr "提取數據" +msgstr "提取為 CSV" #: changedetectionio/store.py:386 #, python-brace-format msgid "Error fetching metadata for {}" -msgstr "" +msgstr "讀取 {} 的中繼資料時發生錯誤" #: changedetectionio/store.py:390 msgid "Watch protocol is not permitted or invalid URL format" -msgstr "" +msgstr "監測協定不被允許或 URL 格式無效" #: changedetectionio/blueprint/backups/__init__.py:86 msgid "A backup is already running, check back in a few minutes" -msgstr "" +msgstr "備份正在進行中,請稍後再回來查看" #: changedetectionio/blueprint/backups/__init__.py:90 msgid "Maximum number of backups reached, please remove some" -msgstr "" +msgstr "已達備份數量上限,請移除部分備份" #: changedetectionio/blueprint/backups/__init__.py:98 msgid "Backup building in background, check back in a few minutes." -msgstr "" +msgstr "正在背景建立備份,請稍後再回來查看。" #: changedetectionio/blueprint/backups/__init__.py:161 msgid "Backups were deleted." -msgstr "" +msgstr "備份已刪除。" #: changedetectionio/blueprint/backups/templates/overview.html:6 #: changedetectionio/templates/base.html:282 @@ -624,13 +588,13 @@ msgstr "備份" #: changedetectionio/blueprint/backups/templates/overview.html:9 msgid "A backup is running!" -msgstr "備份正在運行!" +msgstr "備份正在執行中!" #: changedetectionio/blueprint/backups/templates/overview.html:13 msgid "" "Here you can download and request a new backup, when a backup is " "completed you will see it listed below." -msgstr "" +msgstr "您可以在此下載並請求建立新備份,備份完成後將顯示於下方。" #: changedetectionio/blueprint/backups/templates/overview.html:19 msgid "Mb" @@ -638,50 +602,50 @@ msgstr "MB" #: changedetectionio/blueprint/backups/templates/overview.html:24 msgid "No backups found." -msgstr "未找到備份。" +msgstr "找不到備份。" #: changedetectionio/blueprint/backups/templates/overview.html:28 msgid "Create backup" -msgstr "創建備份" +msgstr "建立備份" #: changedetectionio/blueprint/backups/templates/overview.html:30 msgid "Remove backups" -msgstr "刪除備份" +msgstr "移除備份" #: changedetectionio/blueprint/imports/importer.py:45 msgid "" "Importing 5,000 of the first URLs from your list, the rest can be " "imported again." -msgstr "" +msgstr "正在匯入清單中的前 5,000 個 URL,其餘的可以再次匯入。" #: changedetectionio/blueprint/imports/importer.py:78 #, python-brace-format msgid "{} Imported from list in {:.2f}s, {} Skipped." -msgstr "" +msgstr "{} 已從清單匯入,耗時 {:.2f} 秒,跳過 {} 筆。" #: changedetectionio/blueprint/imports/importer.py:98 msgid "Unable to read JSON file, was it broken?" -msgstr "" +msgstr "無法讀取 JSON 檔案,檔案是否已損毀?" #: changedetectionio/blueprint/imports/importer.py:102 msgid "JSON structure looks invalid, was it broken?" -msgstr "" +msgstr "JSON 結構看起來無效,檔案是否已損毀?" #: changedetectionio/blueprint/imports/importer.py:139 #, python-brace-format msgid "{} Imported from Distill.io in {:.2f}s, {} Skipped." -msgstr "" +msgstr "{} 已從 Distill.io 匯入,耗時 {:.2f} 秒,跳過 {} 筆。" #: changedetectionio/blueprint/imports/importer.py:160 #: changedetectionio/blueprint/imports/importer.py:239 msgid "Unable to read export XLSX file, something wrong with the file?" -msgstr "" +msgstr "無法讀取匯出的 XLSX 檔案,檔案是否有問題?" #: changedetectionio/blueprint/imports/importer.py:200 #: changedetectionio/blueprint/imports/importer.py:268 #, python-brace-format msgid "Error processing row number {}, URL value was incorrect, row was skipped." -msgstr "" +msgstr "處理第 {} 行時發生錯誤,URL 數值不正確,已跳過該行。" #: changedetectionio/blueprint/imports/importer.py:214 #: changedetectionio/blueprint/imports/importer.py:297 @@ -689,21 +653,21 @@ msgstr "" msgid "" "Error processing row number {}, check all cell data types are correct, " "row was skipped." -msgstr "" +msgstr "處理第 {} 行時發生錯誤,請檢查所有儲存格資料類型是否正確,已跳過該行。" #: changedetectionio/blueprint/imports/importer.py:218 #, python-brace-format msgid "{} imported from Wachete .xlsx in {:.2f}s" -msgstr "" +msgstr "{} 已從 Wachete .xlsx 匯入,耗時 {:.2f} 秒" #: changedetectionio/blueprint/imports/importer.py:301 #, python-brace-format msgid "{} imported from custom .xlsx in {:.2f}s" -msgstr "" +msgstr "{} 已從自訂 .xlsx 匯入,耗時 {:.2f} 秒" #: changedetectionio/blueprint/imports/templates/import.html:9 msgid "URL List" -msgstr "網址列表" +msgstr "URL 列表" #: changedetectionio/blueprint/imports/templates/import.html:10 msgid "Distill.io" @@ -711,27 +675,27 @@ msgstr "Distill.io" #: changedetectionio/blueprint/imports/templates/import.html:11 msgid ".XLSX & Wachete" -msgstr ".XLSX 和瓦切特" +msgstr ".XLSX 和 Wachete" #: changedetectionio/blueprint/imports/templates/import.html:20 msgid "" "Enter one URL per line, and optionally add tags for each URL after a " "space, delineated by comma (,):" -msgstr "" +msgstr "每行輸入一個 URL,可選用空格分隔後為每個 URL 新增標籤,標籤間用逗號 (,) 分隔:" #: changedetectionio/blueprint/imports/templates/import.html:22 msgid "Example:" -msgstr "例子:" +msgstr "範例:" #: changedetectionio/blueprint/imports/templates/import.html:23 msgid "URLs which do not pass validation will stay in the textarea." -msgstr "未通過驗證的 URL 將保留在文本區域中。" +msgstr "未通過驗證的 URL 將保留在文字區塊中。" #: changedetectionio/blueprint/imports/templates/import.html:44 msgid "" "Copy and Paste your Distill.io watch 'export' file, this should be a JSON" " file." -msgstr "" +msgstr "複製並貼上您的 Distill.io 監測任務「匯出」檔案,這應該是一個 JSON 檔案。" #: changedetectionio/blueprint/imports/templates/import.html:45 msgid "This is" @@ -739,43 +703,43 @@ msgstr "這是" #: changedetectionio/blueprint/imports/templates/import.html:45 msgid "experimental" -msgstr "實驗性的" +msgstr "實驗性功能" #: changedetectionio/blueprint/imports/templates/import.html:45 msgid "supported fields are" -msgstr "支持的字段有" +msgstr "支援的欄位有" #: changedetectionio/blueprint/imports/templates/import.html:45 msgid "the rest (including" -msgstr "其餘的(包括" +msgstr "其餘(包括" #: changedetectionio/blueprint/imports/templates/import.html:45 msgid "are ignored." -msgstr "被忽略。" +msgstr "將被忽略。" #: changedetectionio/blueprint/imports/templates/import.html:48 msgid "How to export?" -msgstr "如何導出?" +msgstr "如何匯出?" #: changedetectionio/blueprint/imports/templates/import.html:49 msgid "Be sure to set your default fetcher to Chrome if required." -msgstr "如果需要,請務必將默認提取器設置為 Chrome。" +msgstr "如果需要,請務必將您的預設抓取器設為 Chrome。" #: changedetectionio/blueprint/imports/templates/import.html:91 msgid "Table of custom column and data types mapping for the" -msgstr "自定義列和數據類型映射表" +msgstr "自訂欄位與資料類型對應表,適用於" #: changedetectionio/blueprint/imports/templates/import.html:91 msgid "Custom mapping" -msgstr "自定義映射" +msgstr "自訂對應" #: changedetectionio/blueprint/imports/templates/import.html:91 msgid "File mapping type." -msgstr "文件映射類型。" +msgstr "檔案對應類型。" #: changedetectionio/blueprint/imports/templates/import.html:95 msgid "Column #" -msgstr "柱子 #" +msgstr "欄位 #" #: changedetectionio/blueprint/imports/templates/import.html:101 msgid "Type" @@ -783,74 +747,73 @@ msgstr "類型" #: changedetectionio/blueprint/imports/templates/import.html:104 msgid "none" -msgstr "沒有任何" +msgstr "無" #: changedetectionio/blueprint/imports/templates/import.html:105 msgid "URL" -msgstr "網址" +msgstr "URL" #: changedetectionio/blueprint/imports/templates/import.html:107 msgid "CSS/xPath filter" -msgstr "CSS/xPath 過濾器" +msgstr "CSS / xPath 過濾器" #: changedetectionio/blueprint/imports/templates/import.html:108 msgid "Group / Tag name(s)" -msgstr "組/標籤名稱" +msgstr "群組 / 標籤名稱" #: changedetectionio/blueprint/imports/templates/import.html:109 msgid "Recheck time (minutes)" -msgstr "複檢時間(分鐘)" +msgstr "複查時間(分鐘)" #: changedetectionio/blueprint/imports/templates/import.html:116 msgid "Import" -msgstr "進口" +msgstr "匯入" #: changedetectionio/blueprint/settings/__init__.py:64 msgid "Password protection removed." -msgstr "" +msgstr "密碼保護已移除。" #: changedetectionio/blueprint/settings/__init__.py:98 #, python-brace-format msgid "Worker count adjusted: {}" -msgstr "" +msgstr "工作程序數量已調整:{}" #: changedetectionio/blueprint/settings/__init__.py:100 msgid "Dynamic worker adjustment not supported for sync workers" -msgstr "" +msgstr "同步工作程序不支援動態調整" #: changedetectionio/blueprint/settings/__init__.py:102 #, python-brace-format msgid "Error adjusting workers: {}" -msgstr "" +msgstr "調整工作程序時發生錯誤:{}" #: changedetectionio/blueprint/settings/__init__.py:107 msgid "Password protection enabled." -msgstr "" +msgstr "已啟用密碼保護。" #: changedetectionio/blueprint/settings/__init__.py:126 -#, fuzzy msgid "Settings updated." -msgstr "設定" +msgstr "設定已更新。" #: changedetectionio/blueprint/settings/__init__.py:129 #: changedetectionio/blueprint/ui/edit.py:283 #: changedetectionio/processors/extract.py:105 msgid "An error occurred, please see below." -msgstr "" +msgstr "發生錯誤,請參見下方。" #: changedetectionio/blueprint/settings/__init__.py:179 msgid "API Key was regenerated." -msgstr "" +msgstr "API 金鑰已重新產生。" #: changedetectionio/blueprint/settings/templates/notification-log.html:7 msgid "Notification debug log" -msgstr "通知調試日誌" +msgstr "通知除錯記錄" #: changedetectionio/blueprint/settings/templates/settings.html:21 #: changedetectionio/blueprint/tags/templates/edit-tag.html:27 #: changedetectionio/blueprint/ui/templates/edit.html:47 msgid "General" -msgstr "一般的" +msgstr "一般" #: changedetectionio/blueprint/settings/templates/settings.html:23 msgid "Fetching" @@ -858,15 +821,15 @@ msgstr "抓取" #: changedetectionio/blueprint/settings/templates/settings.html:24 msgid "Global Filters" -msgstr "全局過濾器" +msgstr "全域過濾器" #: changedetectionio/blueprint/settings/templates/settings.html:25 msgid "UI Options" -msgstr "用戶界面選項" +msgstr "介面選項" #: changedetectionio/blueprint/settings/templates/settings.html:26 msgid "API" -msgstr "應用程序編程接口" +msgstr "API" #: changedetectionio/blueprint/settings/templates/settings.html:27 msgid "RSS" @@ -874,11 +837,11 @@ msgstr "RSS" #: changedetectionio/blueprint/settings/templates/settings.html:28 msgid "Time & Date" -msgstr "時間和日期" +msgstr "時間與日期" #: changedetectionio/blueprint/settings/templates/settings.html:29 msgid "CAPTCHA & Proxies" -msgstr "驗證碼和代理" +msgstr "驗證碼與代理伺服器" #: changedetectionio/blueprint/settings/templates/settings.html:35 msgid "Info" @@ -886,7 +849,7 @@ msgstr "資訊" #: changedetectionio/blueprint/settings/templates/settings.html:46 msgid "Default recheck time for all watches, current system minimum is" -msgstr "所有手錶默認複檢時間,當前系統最小值為" +msgstr "所有監測任務的預設複查時間,目前系統最小值為" #: changedetectionio/blueprint/settings/templates/settings.html:46 msgid "seconds" @@ -894,23 +857,23 @@ msgstr "秒" #: changedetectionio/blueprint/settings/templates/settings.html:46 msgid "more info" -msgstr "更多信息" +msgstr "更多資訊" #: changedetectionio/blueprint/settings/templates/settings.html:390 msgid "Python version:" -msgstr "Python版本:" +msgstr "Python 版本:" #: changedetectionio/blueprint/settings/templates/settings.html:391 msgid "Plugins active:" -msgstr "插件活躍:" +msgstr "啟用的外掛:" #: changedetectionio/blueprint/settings/templates/settings.html:399 msgid "No plugins active" -msgstr "沒有激活的插件" +msgstr "無啟用的外掛" #: changedetectionio/blueprint/settings/templates/settings.html:405 msgid "Back" -msgstr "後退" +msgstr "返回" #: changedetectionio/blueprint/settings/templates/settings.html:406 msgid "Clear Snapshot History" @@ -919,129 +882,127 @@ msgstr "清除快照歷史記錄" #: changedetectionio/blueprint/tags/__init__.py:46 #, python-brace-format msgid "The tag \"{}\" already exists" -msgstr "" +msgstr "標籤「{}」已存在" #: changedetectionio/blueprint/tags/__init__.py:50 -#, fuzzy msgid "Tag added" -msgstr "額外" +msgstr "標籤已新增" #: changedetectionio/blueprint/tags/__init__.py:75 #, python-brace-format msgid "Tag deleted and removed from {} watches" -msgstr "" +msgstr "標籤已刪除,並從 {} 個監測任務中移除" #: changedetectionio/blueprint/tags/__init__.py:87 #, python-brace-format msgid "Tag unlinked removed from {} watches" -msgstr "" +msgstr "標籤已取消連結,並從 {} 個監測任務中移除" #: changedetectionio/blueprint/tags/__init__.py:97 msgid "All tags deleted" -msgstr "" +msgstr "所有標籤已刪除" #: changedetectionio/blueprint/tags/__init__.py:109 msgid "Tag not found" -msgstr "" +msgstr "找不到標籤" #: changedetectionio/blueprint/tags/__init__.py:184 -#, fuzzy msgid "Updated" -msgstr "沉默的" +msgstr "已更新" #: changedetectionio/blueprint/tags/templates/edit-tag.html:28 #: changedetectionio/blueprint/ui/templates/edit.html:56 #: changedetectionio/blueprint/ui/templates/edit.html:386 msgid "Filters & Triggers" -msgstr "過濾器和触發器" +msgstr "過濾器與觸發器" #: changedetectionio/blueprint/tags/templates/edit-tag.html:50 msgid "These settings are" -msgstr "這些設置是" +msgstr "這些設定會" #: changedetectionio/blueprint/tags/templates/edit-tag.html:50 msgid "added" -msgstr "額外" +msgstr "新增" #: changedetectionio/blueprint/tags/templates/edit-tag.html:50 msgid "to any existing watch configurations." -msgstr "任何現有的手錶配置。" +msgstr "至任何現有的監測設定中。" #: changedetectionio/blueprint/tags/templates/edit-tag.html:53 #: changedetectionio/blueprint/ui/templates/edit.html:321 msgid "Text filtering" -msgstr "文本過濾" +msgstr "文字過濾" #: changedetectionio/blueprint/tags/templates/edit-tag.html:73 #: changedetectionio/blueprint/ui/templates/edit.html:269 msgid "Use with caution!" -msgstr "謹慎使用!" +msgstr "請謹慎使用!" #: changedetectionio/blueprint/tags/templates/edit-tag.html:73 #: changedetectionio/blueprint/ui/templates/edit.html:269 msgid "This will easily fill up your email storage quota or flood other storages." -msgstr "這將很容易填滿您的電子郵件存儲配額或淹沒其他存儲。" +msgstr "這很容易填滿您的電子郵件儲存配額或淹沒其他儲存空間。" #: changedetectionio/blueprint/tags/templates/edit-tag.html:80 #: changedetectionio/blueprint/ui/templates/edit.html:276 msgid "Look out!" -msgstr "當心!" +msgstr "注意!" #: changedetectionio/blueprint/tags/templates/edit-tag.html:80 #: changedetectionio/blueprint/ui/templates/edit.html:276 msgid "Lookout!" -msgstr "瞭望!" +msgstr "注意!" #: changedetectionio/blueprint/tags/templates/edit-tag.html:81 #: changedetectionio/blueprint/ui/templates/edit.html:277 msgid "There are" -msgstr "有" +msgstr "目前有" #: changedetectionio/blueprint/tags/templates/edit-tag.html:81 #: changedetectionio/blueprint/ui/templates/edit.html:277 msgid "system-wide notification URLs enabled" -msgstr "啟用系統範圍的通知 URL" +msgstr "已啟用的全系統通知 URL" #: changedetectionio/blueprint/tags/templates/edit-tag.html:81 #: changedetectionio/blueprint/ui/templates/edit.html:277 msgid "this form will override notification settings for this watch only" -msgstr "此表單將僅覆蓋此手錶的通知設置" +msgstr "此表單將僅覆寫此監測任務的通知設定" #: changedetectionio/blueprint/tags/templates/edit-tag.html:81 #: changedetectionio/blueprint/ui/templates/edit.html:277 msgid "an empty Notification URL list here will still send notifications." -msgstr "此處的通知 URL 列表為空仍會發送通知。" +msgstr "此處留空的通知 URL 列表仍會發送通知。" #: changedetectionio/blueprint/tags/templates/edit-tag.html:84 #: changedetectionio/blueprint/ui/templates/edit.html:280 msgid "Use system defaults" -msgstr "使用系統默認值" +msgstr "使用系統預設值" #: changedetectionio/blueprint/tags/templates/groups-overview.html:11 msgid "Add a new organisational tag" -msgstr "添加新的組織標籤" +msgstr "新增組織標籤" #: changedetectionio/blueprint/tags/templates/groups-overview.html:14 msgid "Watch group / tag" -msgstr "觀看組/標籤" +msgstr "監測群組 / 標籤" #: changedetectionio/blueprint/tags/templates/groups-overview.html:21 msgid "" "Groups allows you to manage filters and notifications for multiple " "watches under a single organisational tag." -msgstr "" +msgstr "群組功能讓您能在單一組織標籤下,管理多個監測任務的過濾器與通知設定。" #: changedetectionio/blueprint/tags/templates/groups-overview.html:31 msgid "# Watches" -msgstr "# 監控項" +msgstr "# 監測任務" #: changedetectionio/blueprint/tags/templates/groups-overview.html:32 msgid "Tag / Label name" -msgstr "標籤/標籤名稱" +msgstr "標籤 / 名稱" #: changedetectionio/blueprint/tags/templates/groups-overview.html:42 msgid "No website organisational tags/groups configured" -msgstr "未配置網站組織標籤/組" +msgstr "未設定網站組織標籤 / 群組" #: changedetectionio/blueprint/tags/templates/groups-overview.html:53 #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:249 @@ -1057,7 +1018,7 @@ msgstr "刪除群組?" msgid "" "<p>Are you sure you want to delete group " "<strong>%(title)s</strong>?</p><p>This action cannot be undone.</p>" -msgstr "" +msgstr "<p>您確定要刪除群組 <strong>%(title)s</strong> 嗎?</p><p>此動作無法復原。</p>" #: changedetectionio/blueprint/tags/templates/groups-overview.html:60 #: changedetectionio/blueprint/tags/templates/groups-overview.html:61 @@ -1072,7 +1033,7 @@ msgstr "刪除並移除標籤" #: changedetectionio/blueprint/tags/templates/groups-overview.html:66 msgid "Unlink Group?" -msgstr "取消群組鏈接?" +msgstr "解除群組連結?" #: changedetectionio/blueprint/tags/templates/groups-overview.html:67 #, python-format @@ -1080,130 +1041,126 @@ msgid "" "<p>Are you sure you want to unlink all watches from group " "<strong>%(title)s</strong>?</p><p>The tag will be kept but watches will " "be removed from it.</p>" -msgstr "" +msgstr "<p>您確定要將所有監測任務從群組 <strong>%(title)s</strong> 解除連結嗎?</p><p>標籤將被保留,但監測任務將從中移除。</p>" #: changedetectionio/blueprint/tags/templates/groups-overview.html:68 #: changedetectionio/blueprint/tags/templates/groups-overview.html:69 msgid "Unlink" -msgstr "取消鏈接" +msgstr "解除連結" #: changedetectionio/blueprint/tags/templates/groups-overview.html:69 msgid "Keep the tag but unlink any watches" -msgstr "保留標籤但取消所有手錶的鏈接" +msgstr "保留標籤但解除任何監測任務的連結" #: changedetectionio/blueprint/tags/templates/groups-overview.html:70 #: changedetectionio/blueprint/ui/templates/edit.html:500 msgid "RSS Feed for this watch" -msgstr "此手錶的 RSS 源" +msgstr "此監測任務的 RSS Feed" #: changedetectionio/blueprint/ui/__init__.py:20 #, python-brace-format msgid "{} watches deleted" -msgstr "" +msgstr "{} 個監測任務已刪除" #: changedetectionio/blueprint/ui/__init__.py:27 -#, fuzzy, python-brace-format +#, python-brace-format msgid "{} watches paused" -msgstr "# 手錶" +msgstr "{} 個監測任務已暫停" #: changedetectionio/blueprint/ui/__init__.py:34 #, python-brace-format msgid "{} watches unpaused" -msgstr "" +msgstr "{} 個監測任務已取消暫停" #: changedetectionio/blueprint/ui/__init__.py:41 #, python-brace-format msgid "{} watches updated" -msgstr "" +msgstr "{} 個監測任務已更新" #: changedetectionio/blueprint/ui/__init__.py:48 -#, fuzzy, python-brace-format +#, python-brace-format msgid "{} watches muted" -msgstr "# 手錶" +msgstr "{} 個監測任務已靜音" #: changedetectionio/blueprint/ui/__init__.py:55 #, python-brace-format msgid "{} watches un-muted" -msgstr "" +msgstr "{} 個監測任務已取消靜音" #: changedetectionio/blueprint/ui/__init__.py:63 #, python-brace-format msgid "{} watches queued for rechecking" -msgstr "" +msgstr "{} 個監測任務已排入複查佇列" #: changedetectionio/blueprint/ui/__init__.py:70 #, python-brace-format msgid "{} watches errors cleared" -msgstr "" +msgstr "{} 個監測任務錯誤已清除" #: changedetectionio/blueprint/ui/__init__.py:77 #, python-brace-format msgid "{} watches cleared/reset." -msgstr "" +msgstr "{} 個監測任務已清除 / 重置。" #: changedetectionio/blueprint/ui/__init__.py:90 -#, fuzzy, python-brace-format +#, python-brace-format msgid "{} watches set to use default notification settings" -msgstr "使用默認通知" +msgstr "{} 個監測任務已設為使用預設通知設定" #: changedetectionio/blueprint/ui/__init__.py:105 #, python-brace-format msgid "{} watches were tagged" -msgstr "" +msgstr "{} 個監測任務已加上標籤" #: changedetectionio/blueprint/ui/__init__.py:142 -#, fuzzy msgid "Watch not found" -msgstr "關注這個網址!" +msgstr "找不到監測任務" #: changedetectionio/blueprint/ui/__init__.py:144 -#, fuzzy, python-brace-format +#, python-brace-format msgid "Cleared snapshot history for watch {}" -msgstr "清除快照歷史記錄" +msgstr "已清除監測任務 {} 的快照歷史記錄" #: changedetectionio/blueprint/ui/__init__.py:156 -#, fuzzy msgid "Cleared snapshot history for all watches" -msgstr "清除快照歷史記錄" +msgstr "已清除所有監測任務的快照歷史記錄" #: changedetectionio/blueprint/ui/__init__.py:158 -#, fuzzy msgid "Incorrect confirmation text." -msgstr "確認文字" +msgstr "確認文字不正確。" #: changedetectionio/blueprint/ui/__init__.py:192 #, python-brace-format msgid "The watch by UUID {} does not exist." -msgstr "" +msgstr "UUID 為 {} 的監測任務不存在。" #: changedetectionio/blueprint/ui/__init__.py:199 -#, fuzzy msgid "Deleted." -msgstr "刪除" +msgstr "已刪除。" #: changedetectionio/blueprint/ui/__init__.py:216 msgid "Cloned, you are editing the new watch." -msgstr "" +msgstr "已複製,您正在編輯新的監測任務。" #: changedetectionio/blueprint/ui/__init__.py:255 msgid "Queued 1 watch for rechecking." -msgstr "" +msgstr "已將 1 個監測任務排入複查佇列。" #: changedetectionio/blueprint/ui/__init__.py:257 #, python-brace-format msgid "Queued {} watches for rechecking." -msgstr "" +msgstr "已將 {} 個監測任務排入複查佇列。" #: changedetectionio/blueprint/ui/__init__.py:259 msgid "No watches available to recheck." -msgstr "" +msgstr "沒有可複查的監測任務。" #: changedetectionio/blueprint/ui/__init__.py:330 #, python-brace-format msgid "" "Could not share, something went wrong while communicating with the share " "server - {}" -msgstr "" +msgstr "無法分享,與分享伺服器通訊時發生錯誤 - {}" #: changedetectionio/blueprint/ui/diff.py:93 #: changedetectionio/blueprint/ui/diff.py:154 @@ -1212,68 +1169,67 @@ msgstr "" #: changedetectionio/blueprint/ui/preview.py:36 #: changedetectionio/blueprint/ui/preview.py:160 msgid "No history found for the specified link, bad link?" -msgstr "" +msgstr "找不到指定連結的歷史記錄,連結無效?" #: changedetectionio/blueprint/ui/diff.py:98 msgid "" "Not enough history (2 snapshots required) to show difference page for " "this watch." -msgstr "" +msgstr "歷史記錄不足(需要 2 個快照)以顯示此監測任務的差異頁面。" #: changedetectionio/blueprint/ui/edit.py:35 msgid "No watches to edit" -msgstr "" +msgstr "沒有可編輯的監測任務" #: changedetectionio/blueprint/ui/edit.py:42 #, python-brace-format msgid "No watch with the UUID {} found." -msgstr "" +msgstr "找不到 UUID 為 {} 的監測任務。" #: changedetectionio/blueprint/ui/edit.py:50 #, python-brace-format msgid "Switched to mode - {}." -msgstr "" +msgstr "已切換至模式 - {}。" #: changedetectionio/blueprint/ui/edit.py:69 #, python-brace-format msgid "Cannot load the edit form for processor/plugin '{}', plugin missing?" -msgstr "" +msgstr "無法載入處理器 / 外掛 '{}' 的編輯表單,外掛是否遺失?" #: changedetectionio/blueprint/ui/edit.py:239 msgid "Updated watch - unpaused!" -msgstr "" +msgstr "已更新監測任務 - 已取消暫停!" #: changedetectionio/blueprint/ui/edit.py:239 -#, fuzzy msgid "Updated watch." -msgstr "刪除手錶?" +msgstr "已更新監測任務。" #: changedetectionio/blueprint/ui/preview.py:78 msgid "Preview unavailable - No fetch/check completed or triggers not reached" -msgstr "" +msgstr "預覽無法使用 - 未完成抓取 / 檢查或未觸發" #: changedetectionio/blueprint/ui/views.py:24 #, python-brace-format msgid "Warning, URL {} already exists" -msgstr "" +msgstr "警告,URL {} 已存在" #: changedetectionio/blueprint/ui/views.py:32 msgid "Watch added in Paused state, saving will unpause." -msgstr "" +msgstr "監測任務已在暫停狀態下新增,儲存後將取消暫停。" #: changedetectionio/blueprint/ui/views.py:37 msgid "Watch added." -msgstr "" +msgstr "監測任務已新增。" #: changedetectionio/blueprint/ui/templates/clear_all_history.html:12 msgid "" "This will remove version history (snapshots) for ALL watches, but keep " "your list of URLs!" -msgstr "" +msgstr "這將移除「所有」監測任務的版本歷史記錄(快照),但保留您的 URL 列表!" #: changedetectionio/blueprint/ui/templates/clear_all_history.html:13 msgid "You may like to use the" -msgstr "您可能喜歡使用" +msgstr "您可能想先使用" #: changedetectionio/blueprint/ui/templates/clear_all_history.html:13 msgid "BACKUP" @@ -1281,7 +1237,7 @@ msgstr "備份" #: changedetectionio/blueprint/ui/templates/clear_all_history.html:13 msgid "link first." -msgstr "先鏈接。" +msgstr "連結。" #: changedetectionio/blueprint/ui/templates/clear_all_history.html:17 msgid "Confirmation text" @@ -1289,19 +1245,19 @@ msgstr "確認文字" #: changedetectionio/blueprint/ui/templates/clear_all_history.html:27 msgid "Type in the word" -msgstr "輸入單詞" +msgstr "輸入單字" #: changedetectionio/blueprint/ui/templates/clear_all_history.html:27 msgid "clear" -msgstr "清除" +msgstr "clear" #: changedetectionio/blueprint/ui/templates/clear_all_history.html:27 msgid "to confirm that you understand." -msgstr "以確認您已理解。" +msgstr "以確認您已了解。" #: changedetectionio/blueprint/ui/templates/clear_all_history.html:33 msgid "Clear History!" -msgstr "清除歷史!" +msgstr "清除歷史記錄!" #: changedetectionio/blueprint/ui/templates/clear_all_history.html:39 #: changedetectionio/templates/base.html:379 @@ -1311,7 +1267,7 @@ msgstr "取消" #: changedetectionio/blueprint/ui/templates/diff-offscreen-options.html:3 msgid "Share diff as image" -msgstr "將差異共享為圖像" +msgstr "將差異分享為圖片" #: changedetectionio/blueprint/ui/templates/diff-offscreen-options.html:3 msgid "Share as Image" @@ -1319,11 +1275,11 @@ msgstr "分享為圖片" #: changedetectionio/blueprint/ui/templates/diff-offscreen-options.html:6 msgid "Ignore any lines matching" -msgstr "忽略任何匹配的行" +msgstr "忽略任何符合的行" #: changedetectionio/blueprint/ui/templates/diff-offscreen-options.html:9 msgid "Ignore any lines matching excluding digits" -msgstr "忽略任何匹配排除數字的行" +msgstr "忽略任何符合(排除數字)的行" #: changedetectionio/blueprint/ui/templates/diff.html:28 msgid "From" @@ -1339,29 +1295,29 @@ msgstr "字" #: changedetectionio/blueprint/ui/templates/diff.html:57 msgid "Lines" -msgstr "線路" +msgstr "行" #: changedetectionio/blueprint/ui/templates/diff.html:61 msgid "Ignore Whitespace" -msgstr "忽略空格" +msgstr "忽略空白" #: changedetectionio/blueprint/ui/templates/diff.html:65 msgid "Same/non-changed" -msgstr "相同/未改變" +msgstr "相同 / 未變更" #: changedetectionio/blueprint/ui/templates/diff.html:69 msgid "Removed" -msgstr "已刪除" +msgstr "已移除" #: changedetectionio/blueprint/ui/templates/diff.html:73 #: changedetectionio/blueprint/ui/templates/edit.html:327 msgid "Added" -msgstr "額外" +msgstr "已新增" #: changedetectionio/blueprint/ui/templates/diff.html:77 #: changedetectionio/blueprint/ui/templates/edit.html:327 msgid "Replaced" -msgstr "已更換" +msgstr "已替換" #: changedetectionio/blueprint/ui/templates/diff.html:82 #: changedetectionio/blueprint/ui/templates/preview.html:36 @@ -1371,7 +1327,7 @@ msgstr "鍵盤:" #: changedetectionio/blueprint/ui/templates/diff.html:83 #: changedetectionio/blueprint/ui/templates/preview.html:37 msgid "Previous" -msgstr "以前的" +msgstr "上一個" #: changedetectionio/blueprint/ui/templates/diff.html:84 #: changedetectionio/blueprint/ui/templates/preview.html:38 @@ -1380,16 +1336,16 @@ msgstr "下一個" #: changedetectionio/blueprint/ui/templates/diff.html:91 msgid "Jump to next difference" -msgstr "跳轉到下一個差異" +msgstr "跳至下一個差異" #: changedetectionio/blueprint/ui/templates/diff.html:91 msgid "Jump" -msgstr "跳" +msgstr "跳轉" #: changedetectionio/blueprint/ui/templates/diff.html:97 #: changedetectionio/blueprint/ui/templates/preview.html:45 msgid "Error Text" -msgstr "錯誤文本" +msgstr "錯誤文字" #: changedetectionio/blueprint/ui/templates/diff.html:98 #: changedetectionio/blueprint/ui/templates/preview.html:47 @@ -1404,25 +1360,25 @@ msgstr "文字" #: changedetectionio/blueprint/ui/templates/diff.html:100 #: changedetectionio/blueprint/ui/templates/preview.html:51 msgid "Current screenshot" -msgstr "當前截圖" +msgstr "目前截圖" #: changedetectionio/blueprint/ui/templates/diff.html:101 msgid "Extract Data" -msgstr "提取數據" +msgstr "提取資料" #: changedetectionio/blueprint/ui/templates/diff.html:107 msgid "seconds ago." -msgstr "幾秒鐘前。" +msgstr "秒前。" #: changedetectionio/blueprint/ui/templates/diff.html:114 #: changedetectionio/blueprint/ui/templates/preview.html:59 #: changedetectionio/blueprint/ui/templates/preview.html:66 msgid "seconds ago" -msgstr "幾秒鐘前" +msgstr "秒前" #: changedetectionio/blueprint/ui/templates/diff.html:115 msgid "Current error-ing screenshot from most recent request" -msgstr "最近請求的當前錯誤屏幕截圖" +msgstr "最近請求的目前錯誤截圖" #: changedetectionio/blueprint/ui/templates/diff.html:127 msgid "Pro-tip: You can enable" @@ -1430,15 +1386,15 @@ msgstr "專業提示:您可以啟用" #: changedetectionio/blueprint/ui/templates/diff.html:127 msgid "\"share access when password is enabled\"" -msgstr "" +msgstr "「啟用密碼時分享存取權限」" #: changedetectionio/blueprint/ui/templates/diff.html:127 msgid "from settings." -msgstr "從設置。" +msgstr "於設定中。" #: changedetectionio/blueprint/ui/templates/diff.html:133 msgid "Goto single snapshot" -msgstr "轉到單個快照" +msgstr "前往單一快照" #: changedetectionio/blueprint/ui/templates/diff.html:138 #: changedetectionio/blueprint/ui/templates/edit.html:125 @@ -1447,32 +1403,32 @@ msgstr "提示:" #: changedetectionio/blueprint/ui/templates/diff.html:138 msgid "Highlight text to share or add to ignore lists." -msgstr "突出顯示要共享或添加到忽略列表的文本。" +msgstr "反白文字以分享或新增至忽略列表。" #: changedetectionio/blueprint/ui/templates/diff.html:144 #: changedetectionio/blueprint/ui/templates/preview.html:80 msgid "" "For now, Differences are performed on text, not graphically, only the " "latest screenshot is available." -msgstr "" +msgstr "目前,差異比對是針對文字執行,而非圖形,僅提供最新的截圖。" #: changedetectionio/blueprint/ui/templates/diff.html:149 #: changedetectionio/blueprint/ui/templates/preview.html:86 msgid "Current screenshot from most recent request" -msgstr "最近請求的當前屏幕截圖" +msgstr "最近請求的目前截圖" #: changedetectionio/blueprint/ui/templates/diff.html:151 #: changedetectionio/blueprint/ui/templates/preview.html:88 msgid "No screenshot available just yet! Try rechecking the page." -msgstr "目前還沒有可用的屏幕截圖!嘗試重新檢查頁面。" +msgstr "目前還沒有可用的截圖!請嘗試複查頁面。" #: changedetectionio/blueprint/ui/templates/diff.html:154 msgid "Screenshot requires Playwright/WebDriver enabled" -msgstr "屏幕截圖需要啟用 Playwright/WebDriver" +msgstr "截圖需要啟用 Playwright / WebDriver" #: changedetectionio/blueprint/ui/templates/edit.html:48 msgid "Request" -msgstr "要求" +msgstr "請求" #: changedetectionio/blueprint/ui/templates/edit.html:52 msgid "Browser Steps" @@ -1480,11 +1436,11 @@ msgstr "瀏覽器步驟" #: changedetectionio/blueprint/ui/templates/edit.html:55 msgid "Visual Filter Selector" -msgstr "視覺過濾器選擇器" +msgstr "視覺過濾選擇器" #: changedetectionio/blueprint/ui/templates/edit.html:57 msgid "Conditions" -msgstr "狀況" +msgstr "條件" #: changedetectionio/blueprint/ui/templates/edit.html:60 msgid "Stats" @@ -1493,43 +1449,43 @@ msgstr "統計數據" #: changedetectionio/blueprint/ui/templates/edit.html:73 #: changedetectionio/blueprint/ui/templates/edit.html:313 msgid "Some sites use JavaScript to create the content, for this you should" -msgstr "有些網站使用 JavaScript 來創建內容,為此您應該" +msgstr "有些網站使用 JavaScript 來建立內容,為此您應該" #: changedetectionio/blueprint/ui/templates/edit.html:73 #: changedetectionio/blueprint/ui/templates/edit.html:313 msgid "use the Chrome/WebDriver Fetcher" -msgstr "使用 Chrome/WebDriver Fetcher" +msgstr "使用 Chrome / WebDriver 抓取器" #: changedetectionio/blueprint/ui/templates/edit.html:74 msgid "Variables are supported in the URL" -msgstr "URL 中支持變量" +msgstr "URL 中支援變數" #: changedetectionio/blueprint/ui/templates/edit.html:74 #: changedetectionio/blueprint/ui/templates/edit.html:180 #: changedetectionio/blueprint/ui/templates/edit.html:189 msgid "help and examples here" -msgstr "幫助和示例在這裡" +msgstr "幫助與範例請見此處" #: changedetectionio/blueprint/ui/templates/edit.html:78 msgid "Organisational tag/group name used in the main listing page" -msgstr "主列表頁面中使用的組織標籤/組名稱" +msgstr "主列表頁面中使用的組織標籤 / 群組名稱" #: changedetectionio/blueprint/ui/templates/edit.html:85 msgid "" "Automatically uses the page title if found, you can also use your own " "title/description here" -msgstr "" +msgstr "如果找到頁面標題將自動使用,您也可以在此使用您自己的標題 / 描述" #: changedetectionio/blueprint/ui/templates/edit.html:95 msgid "The interval/amount of time between each check." -msgstr "每次檢查之間的間隔/時間量。" +msgstr "每次檢查之間的間隔 / 時間量。" #: changedetectionio/blueprint/ui/templates/edit.html:110 msgid "" "Sends a notification when the filter can no longer be seen on the page, " "good for knowing when the page changed and your filter will not work " "anymore." -msgstr "" +msgstr "當頁面上找不到過濾器時發送通知,這有助於了解頁面何時變更導致您的過濾器失效。" #: changedetectionio/blueprint/ui/templates/edit.html:123 msgid "Use the" @@ -1537,45 +1493,45 @@ msgstr "使用" #: changedetectionio/blueprint/ui/templates/edit.html:123 msgid "Basic" -msgstr "基本的" +msgstr "基本" #: changedetectionio/blueprint/ui/templates/edit.html:123 msgid "" "method (default) where your watched site doesn't need Javascript to " "render." -msgstr "" +msgstr "方法(預設),適用於您監測的網站不需要 Javascript 渲染的情況。" #: changedetectionio/blueprint/ui/templates/edit.html:124 msgid "The" -msgstr "這" +msgstr "這個" #: changedetectionio/blueprint/ui/templates/edit.html:124 msgid "Chrome/Javascript" -msgstr "Chrome/Javascript" +msgstr "Chrome / Javascript" #: changedetectionio/blueprint/ui/templates/edit.html:124 msgid "" "method requires a network connection to a running WebDriver+Chrome " "server, set by the ENV var 'WEBDRIVER_URL'." -msgstr "" +msgstr "方法需要連線到執行中的 WebDriver + Chrome 伺服器,由環境變數 'WEBDRIVER_URL' 設定。" #: changedetectionio/blueprint/ui/templates/edit.html:125 msgid "Connect using Bright Data and Oxylabs Proxies, find out more here." -msgstr "使用 Bright Data 和 Oxylabs Proxies 進行連接,在此處了解更多信息。" +msgstr "使用 Bright Data 和 Oxylabs 代理連接,在此處了解更多資訊。" #: changedetectionio/blueprint/ui/templates/edit.html:130 msgid "Check/Scan all" -msgstr "檢查/掃描全部" +msgstr "檢查 / 掃描全部" #: changedetectionio/blueprint/ui/templates/edit.html:133 msgid "Choose a proxy for this watch" -msgstr "為該手錶選擇代理" +msgstr "為此監測任務選擇代理伺服器" #: changedetectionio/blueprint/ui/templates/edit.html:143 msgid "" "If you're having trouble waiting for the page to be fully rendered (text " "missing etc), try increasing the 'wait' time here." -msgstr "" +msgstr "如果您在等待頁面完全渲染時遇到問題(文字遺失等),請嘗試在此增加「等待」時間。" #: changedetectionio/blueprint/ui/templates/edit.html:145 msgid "This will wait" @@ -1583,113 +1539,113 @@ msgstr "這會等待" #: changedetectionio/blueprint/ui/templates/edit.html:145 msgid "seconds before extracting the text." -msgstr "提取文本前幾秒。" +msgstr "秒後才提取文字。" #: changedetectionio/blueprint/ui/templates/edit.html:147 msgid "Using the current global default settings" -msgstr "使用當前全局默認設置" +msgstr "使用目前全域預設設定" #: changedetectionio/blueprint/ui/templates/edit.html:152 #: changedetectionio/blueprint/ui/templates/edit.html:165 msgid "Show advanced options" -msgstr "顯示高級選項" +msgstr "顯示進階選項" #: changedetectionio/blueprint/ui/templates/edit.html:157 msgid "" "Run this code before performing change detection, handy for filling in " "fields and other actions" -msgstr "" +msgstr "在執行變更檢測之前執行此程式碼,方便填寫欄位和其他動作" #: changedetectionio/blueprint/ui/templates/edit.html:158 msgid "More help and examples here" -msgstr "更多幫助和示例請參見此處" +msgstr "更多幫助和範例請見此處" #: changedetectionio/blueprint/ui/templates/edit.html:180 msgid "Variables are supported in the request body" -msgstr "請求正文中支持變量" +msgstr "請求內容中支援變數" #: changedetectionio/blueprint/ui/templates/edit.html:189 msgid "Variables are supported in the request header values" -msgstr "請求標頭值支持變量" +msgstr "請求標頭值支援變數" #: changedetectionio/blueprint/ui/templates/edit.html:192 msgid "Alert! Extra headers file found and will be added to this watch!" -msgstr "警報!找到額外的頭文件並將其添加到此手錶中!" +msgstr "警報!找到額外的標頭檔案,將新增至此監測任務!" #: changedetectionio/blueprint/ui/templates/edit.html:194 msgid "Headers can be also read from a file in your data-directory" -msgstr "還可以從數據目錄中的文件中讀取標頭" +msgstr "標頭也可以從您的資料目錄中的檔案讀取" #: changedetectionio/blueprint/ui/templates/edit.html:194 msgid "Read more here" -msgstr "在這裡閱讀更多內容" +msgstr "在此閱讀更多內容" #: changedetectionio/blueprint/ui/templates/edit.html:197 msgid "Not supported by Selenium browser" -msgstr "Selenium 瀏覽器不支持" +msgstr "Selenium 瀏覽器不支援" #: changedetectionio/blueprint/ui/templates/edit.html:221 msgid "Turn on text finder" -msgstr "打開文本查找器" +msgstr "開啟文字尋找器" #: changedetectionio/blueprint/ui/templates/edit.html:224 msgid "Please wait, first browser step can take a little time to load.." -msgstr "請稍候,第一個瀏覽器步驟可能需要一些時間來加載。" +msgstr "請稍候,第一個瀏覽器步驟可能需要一點時間載入.." #: changedetectionio/blueprint/ui/templates/edit.html:231 msgid "Click here to Start" -msgstr "單擊此處開始" +msgstr "點擊此處開始" #: changedetectionio/blueprint/ui/templates/edit.html:233 msgid "Please allow 10-15 seconds for the browser to connect." -msgstr "請等待 10-15 秒讓瀏覽器連接。" +msgstr "請等待 10-15 秒讓瀏覽器連線。" #: changedetectionio/blueprint/ui/templates/edit.html:242 msgid "Press \"Play\" to start." -msgstr "" +msgstr "按 \"Play\" 開始。" #: changedetectionio/blueprint/ui/templates/edit.html:249 #: changedetectionio/blueprint/ui/templates/edit.html:419 msgid "Visual Selector data is not ready, watch needs to be checked atleast once." -msgstr "視覺選擇器數據尚未準備好,至少需要檢查一次手錶。" +msgstr "視覺選擇器資料尚未準備好,監測任務至少需要檢查一次。" #: changedetectionio/blueprint/ui/templates/edit.html:253 msgid "" "Sorry, this functionality only works with fetchers that support " "interactive Javascript (so far only Playwright based fetchers)" -msgstr "" +msgstr "抱歉,此功能僅適用於支援互動式 Javascript 的抓取器(目前僅限基於 Playwright 的抓取器)" #: changedetectionio/blueprint/ui/templates/edit.html:254 #: changedetectionio/blueprint/ui/templates/edit.html:424 msgid "You need to" -msgstr "你需要" +msgstr "您需要" #: changedetectionio/blueprint/ui/templates/edit.html:254 #: changedetectionio/blueprint/ui/templates/edit.html:424 msgid "Set the fetch method" -msgstr "設置獲取方法" +msgstr "設定抓取方式" #: changedetectionio/blueprint/ui/templates/edit.html:254 msgid "to one that supports interactive Javascript." -msgstr "到支持交互式 Javascript 的一個。" +msgstr "為支援互動式 Javascript 的方式。" #: changedetectionio/blueprint/ui/templates/edit.html:297 msgid "" "Use the verify (✓) button to test if a condition passes against the " "current snapshot." -msgstr "" +msgstr "使用驗證 (✓) 按鈕測試條件是否符合目前的快照。" #: changedetectionio/blueprint/ui/templates/edit.html:298 msgid "Read a quick tutorial about" -msgstr "閱讀有關以下內容的快速教程" +msgstr "閱讀有關" #: changedetectionio/blueprint/ui/templates/edit.html:298 msgid "using conditional web page changes here" -msgstr "此處使用條件網頁更改" +msgstr "使用條件式網頁變更的快速教學" #: changedetectionio/blueprint/ui/templates/edit.html:303 msgid "Activate preview" -msgstr "激活預覽" +msgstr "啟用預覽" #: changedetectionio/blueprint/ui/templates/edit.html:307 msgid "Pro-tips:" @@ -1697,30 +1653,30 @@ msgstr "專業提示:" #: changedetectionio/blueprint/ui/templates/edit.html:310 msgid "Use the preview page to see your filters and triggers highlighted." -msgstr "使用預覽頁面查看突出顯示的過濾器和触發器。" +msgstr "使用預覽頁面查看反白的過濾器和觸發器。" #: changedetectionio/blueprint/ui/templates/edit.html:322 msgid "Limit trigger/ignore/block/extract to;" -msgstr "將觸發/忽略/阻止/提取限制為;" +msgstr "將觸發 / 忽略 / 阻擋 / 提取限制為;" #: changedetectionio/blueprint/ui/templates/edit.html:326 msgid "" "Note: Depending on the length and similarity of the text on each line, " "the algorithm may consider an" -msgstr "" +msgstr "注意:根據每行文字的長度和相似度,演算法可能會將" #: changedetectionio/blueprint/ui/templates/edit.html:326 #: changedetectionio/blueprint/ui/templates/edit.html:328 msgid "addition" -msgstr "添加" +msgstr "新增" #: changedetectionio/blueprint/ui/templates/edit.html:326 msgid "instead of" -msgstr "而不是" +msgstr "誤判為" #: changedetectionio/blueprint/ui/templates/edit.html:326 msgid "replacement" -msgstr "替代品" +msgstr "替換" #: changedetectionio/blueprint/ui/templates/edit.html:326 msgid "for example." @@ -1728,7 +1684,7 @@ msgstr "例如。" #: changedetectionio/blueprint/ui/templates/edit.html:327 msgid "So it's always better to select" -msgstr "所以選擇總是更好" +msgstr "所以最好選擇" #: changedetectionio/blueprint/ui/templates/edit.html:327 msgid "when you're interested in new content." @@ -1744,42 +1700,42 @@ msgstr "考慮啟用" #: changedetectionio/blueprint/ui/templates/edit.html:328 msgid "Only trigger when unique lines appear" -msgstr "僅當出現唯一線條時觸發" +msgstr "僅當出現獨特行時觸發" #: changedetectionio/blueprint/ui/templates/edit.html:332 msgid "" "Good for websites that just move the content around, and you want to know" " when NEW content is added, compares new lines against all history for " "this watch." -msgstr "" +msgstr "適用於內容僅會移動的網站,且您想知道何時新增了「新」內容,此功能會將新行與此監測任務的所有歷史記錄進行比較。" #: changedetectionio/blueprint/ui/templates/edit.html:340 msgid "" "Helps reduce changes detected caused by sites shuffling lines around, " "combine with" -msgstr "" +msgstr "有助於減少因網站重新排列行而檢測到的變更,結合" #: changedetectionio/blueprint/ui/templates/edit.html:340 msgid "check unique lines" -msgstr "檢查獨特的線路" +msgstr "檢查獨特行" #: changedetectionio/blueprint/ui/templates/edit.html:340 msgid "below." -msgstr "以下。" +msgstr "於下方。" #: changedetectionio/blueprint/ui/templates/edit.html:344 msgid "Remove any whitespace before and after each line of text" -msgstr "刪除每行文本前後的所有空格" +msgstr "移除每行文字前後的所有空白" #: changedetectionio/blueprint/ui/templates/edit.html:358 #: changedetectionio/blueprint/ui/templates/edit.html:361 #: changedetectionio/blueprint/ui/templates/edit.html:417 msgid "Loading..." -msgstr "載入中..." +msgstr "載入中 ..." #: changedetectionio/blueprint/ui/templates/edit.html:386 msgid "The Visual Selector tool lets you select the" -msgstr "視覺選擇器工具可讓您選擇" +msgstr "視覺選擇器工具讓您可以選擇" #: changedetectionio/blueprint/ui/templates/edit.html:386 msgid "text" @@ -1789,15 +1745,15 @@ msgstr "文字" msgid "" "elements that will be used for the change detection. It automatically " "fills-in the filters in the \"CSS/JSONPath/JQ/XPath Filters\" box of the" -msgstr "" +msgstr "將用於變更檢測的元素。它會自動填入" #: changedetectionio/blueprint/ui/templates/edit.html:386 msgid "tab. Use" -msgstr "選項卡。使用" +msgstr "分頁的「CSS / JSONPath / JQ / XPath 過濾器」欄位。使用" #: changedetectionio/blueprint/ui/templates/edit.html:386 msgid "Shift+Click" -msgstr "Shift+單擊" +msgstr "Shift + 點擊" #: changedetectionio/blueprint/ui/templates/edit.html:386 msgid "to select multiple items." @@ -1805,7 +1761,7 @@ msgstr "選擇多個項目。" #: changedetectionio/blueprint/ui/templates/edit.html:391 msgid "Selection Mode:" -msgstr "選擇方式:" +msgstr "選擇模式:" #: changedetectionio/blueprint/ui/templates/edit.html:394 msgid "Select by element" @@ -1813,7 +1769,7 @@ msgstr "按元素選擇" #: changedetectionio/blueprint/ui/templates/edit.html:398 msgid "Draw area" -msgstr "繪圖區" +msgstr "繪製區域" #: changedetectionio/blueprint/ui/templates/edit.html:406 msgid "Clear selection" @@ -1821,29 +1777,29 @@ msgstr "清除選擇" #: changedetectionio/blueprint/ui/templates/edit.html:408 msgid "One moment, fetching screenshot and element information.." -msgstr "一會兒,正在獲取屏幕截圖和元素信息.." +msgstr "請稍候,正在抓取截圖和元素資訊.." #: changedetectionio/blueprint/ui/templates/edit.html:417 msgid "Currently:" -msgstr "現在:" +msgstr "目前:" #: changedetectionio/blueprint/ui/templates/edit.html:423 msgid "" "Sorry, this functionality only works with fetchers that support " "Javascript and screenshots (such as playwright etc)." -msgstr "" +msgstr "抱歉,此功能僅適用於支援 Javascript 和截圖的抓取器(如 playwright 等)。" #: changedetectionio/blueprint/ui/templates/edit.html:424 msgid "to one that supports Javascript and screenshots." -msgstr "到支持 Javascript 和屏幕截圖的一個。" +msgstr "為支援 Javascript 和截圖的方式。" #: changedetectionio/blueprint/ui/templates/edit.html:441 msgid "Check count" -msgstr "檢查計數" +msgstr "檢查次數" #: changedetectionio/blueprint/ui/templates/edit.html:445 msgid "Consecutive filter failures" -msgstr "連續過濾器故障" +msgstr "連續過濾失敗" #: changedetectionio/blueprint/ui/templates/edit.html:449 msgid "History length" @@ -1851,31 +1807,31 @@ msgstr "歷史長度" #: changedetectionio/blueprint/ui/templates/edit.html:453 msgid "Last fetch duration" -msgstr "上次獲取持續時間" +msgstr "上次抓取耗時" #: changedetectionio/blueprint/ui/templates/edit.html:457 msgid "Notification alert count" -msgstr "通知警報計數" +msgstr "通知警報次數" #: changedetectionio/blueprint/ui/templates/edit.html:461 msgid "Server type reply" -msgstr "服務器類型回复" +msgstr "伺服器類型回應" #: changedetectionio/blueprint/ui/templates/edit.html:475 msgid "Download latest HTML snapshot" -msgstr "下載最新的 HTML 快照" +msgstr "下載最新 HTML 快照" #: changedetectionio/blueprint/ui/templates/edit.html:488 msgid "Delete Watch?" -msgstr "刪除手錶?" +msgstr "刪除監測任務?" #: changedetectionio/blueprint/ui/templates/edit.html:489 msgid "Are you sure you want to delete the watch for:" -msgstr "您確定要刪除以下對象的手錶嗎:" +msgstr "您確定要刪除以下對象的監測任務:" #: changedetectionio/blueprint/ui/templates/edit.html:489 msgid "This action cannot be undone." -msgstr "此操作無法撤消。" +msgstr "此動作無法復原。" #: changedetectionio/blueprint/ui/templates/edit.html:495 msgid "Clear History?" @@ -1883,13 +1839,13 @@ msgstr "清除歷史記錄?" #: changedetectionio/blueprint/ui/templates/edit.html:496 msgid "Are you sure you want to clear all history for:" -msgstr "您確定要清除以下內容的所有歷史記錄:" +msgstr "您確定要清除以下項目的所有歷史記錄:" #: changedetectionio/blueprint/ui/templates/edit.html:496 msgid "" "This will remove all snapshots and previous versions. This action cannot " "be undone." -msgstr "" +msgstr "這將移除所有快照和先前版本。此動作無法復原。" #: changedetectionio/blueprint/ui/templates/edit.html:497 msgid "Clear History" @@ -1897,49 +1853,49 @@ msgstr "清除歷史記錄" #: changedetectionio/blueprint/ui/templates/edit.html:499 msgid "Clone & Edit" -msgstr "克隆和編輯" +msgstr "複製並編輯" #: changedetectionio/blueprint/ui/templates/preview.html:22 msgid "Select timestamp" -msgstr "選擇時間戳" +msgstr "選擇時間戳記" #: changedetectionio/blueprint/ui/templates/preview.html:31 msgid "Go" -msgstr "去" +msgstr "前往" #: changedetectionio/blueprint/ui/templates/preview.html:69 msgid "Current erroring screenshot from most recent request" -msgstr "最近請求的當前錯誤屏幕截圖" +msgstr "最近請求的目前錯誤截圖" #: changedetectionio/blueprint/ui/templates/preview.html:91 msgid "" "Screenshot requires a Content Fetcher ( Sockpuppetbrowser, selenium, etc " ") that supports screenshots." -msgstr "" +msgstr "截圖需要支援截圖的內容抓取器 (Sockpuppetbrowser, selenium 等)。" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:31 msgid "Add a new web page change detection watch" -msgstr "添加新的網頁更改檢測監視" +msgstr "新增網頁變更檢測任務" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:34 msgid "Watch this URL!" -msgstr "監控此URL!" +msgstr "監測此 URL!" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:35 msgid "Edit first then Watch" -msgstr "編輯後監控" +msgstr "先編輯後監測" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:45 msgid "Create a shareable link" -msgstr "創建可共享鏈接" +msgstr "建立可分享連結" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:45 msgid "Tip: You can also add 'shared' watches." -msgstr "提示:您還可以添加“共享”手錶。" +msgstr "提示:您也可以新增「共享」監測任務。" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:45 msgid "More info" -msgstr "更多信息" +msgstr "更多資訊" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:53 msgid "Pause" @@ -1951,7 +1907,7 @@ msgstr "取消暫停" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:55 msgid "Mute" -msgstr "沉默的" +msgstr "靜音" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:56 msgid "UnMute" @@ -1968,11 +1924,11 @@ msgstr "標籤" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:59 msgid "Mark viewed" -msgstr "標記已查看" +msgstr "標記為已讀" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:60 msgid "Use default notification" -msgstr "使用默認通知" +msgstr "使用預設通知" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:61 msgid "Clear errors" @@ -1980,31 +1936,31 @@ msgstr "清除錯誤" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:65 msgid "Clear Histories" -msgstr "清晰的歷史記錄" +msgstr "清除歷史記錄" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:66 msgid "" "<p>Are you sure you want to clear history for the selected " "items?</p><p>This action cannot be undone.</p>" -msgstr "" +msgstr "<p>您確定要清除所選項目的歷史記錄嗎?</p><p>此動作無法復原。</p>" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:67 msgid "OK" -msgstr "好的" +msgstr "確定" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:67 msgid "Clear/reset history" -msgstr "清除/重置歷史記錄" +msgstr "清除 / 重置歷史記錄" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:71 msgid "Delete Watches?" -msgstr "刪除手錶?" +msgstr "刪除監測任務?" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:72 msgid "" "<p>Are you sure you want to delete the selected " "watches?</strong></p><p>This action cannot be undone.</p>" -msgstr "" +msgstr "<p>您確定要刪除所選的監測任務嗎?</strong></p><p>此動作無法復原。</p>" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:78 msgid "Searching" @@ -2020,40 +1976,40 @@ msgstr "網站" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:120 msgid "Restock & Price" -msgstr "補貨及價格" +msgstr "補貨與價格" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:122 #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:123 msgid "Last" -msgstr "最後的" +msgstr "上次" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:122 msgid "Checked" -msgstr "已檢查" +msgstr "檢查" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:123 msgid "Changed" -msgstr "改變了" +msgstr "變更" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:130 msgid "No website watches configured, please add a URL in the box above, or" -msgstr "未配置網站監視,請在上面的框中添加 URL,或者" +msgstr "未設定網站監測任務,請在上方欄位新增 URL,或" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:130 msgid "import a list" -msgstr "導入列表" +msgstr "匯入列表" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:213 msgid "Detecting restock and price" -msgstr "檢測補貨和價格" +msgstr "檢測補貨與價格" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:215 msgid "In stock" -msgstr "有存貨" +msgstr "有庫存" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:215 msgid "Not in stock" -msgstr "沒有庫存" +msgstr "無庫存" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:221 msgid "Price" @@ -2061,20 +2017,20 @@ msgstr "價格" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:226 msgid "No information" -msgstr "暫無信息" +msgstr "無資訊" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:234 #: changedetectionio/templates/base.html:353 msgid "Checking now" -msgstr "立即檢查" +msgstr "正在檢查" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:247 msgid "Queued" -msgstr "排隊" +msgstr "已排程" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:250 msgid "History" -msgstr "歷史" +msgstr "歷史記錄" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:251 msgid "Preview" @@ -2086,12 +2042,12 @@ msgstr "有錯誤" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:263 msgid "Mark all viewed" -msgstr "標記所有已查看" +msgstr "標記所有為已讀" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:267 #, python-format msgid "Mark all viewed in '%(title)s'" -msgstr "標記所有在“%(title)s”中查看過的內容" +msgstr "標記 '%(title)s' 中的所有項目為已讀" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:271 msgid "Unread" @@ -2099,93 +2055,91 @@ msgstr "未讀" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:274 msgid "Recheck all" -msgstr "重新檢查所有" +msgstr "複查全部" #: changedetectionio/blueprint/watchlist/templates/watch-overview.html:274 #, python-format msgid "in '%(title)s'" -msgstr "在“%(title)s”中" +msgstr "於 '%(title)s'" #: changedetectionio/processors/extract.py:131 msgid "No matches found while scanning all of the watch history for that RegEx." -msgstr "" +msgstr "掃描此 RegEx 的所有監測歷史記錄時找不到相符項目。" #: changedetectionio/processors/image_ssim_diff/difference.py:328 msgid "Not enough history to compare. Need at least 2 snapshots." -msgstr "" +msgstr "歷史記錄不足以進行比較。至少需要 2 個快照。" #: changedetectionio/processors/image_ssim_diff/difference.py:363 #, python-brace-format msgid "Failed to load screenshots: {}" -msgstr "" +msgstr "無法載入截圖:{}" #: changedetectionio/processors/image_ssim_diff/difference.py:412 #, python-brace-format msgid "Failed to calculate diff: {}" -msgstr "" +msgstr "無法計算差異:{}" #: changedetectionio/processors/image_ssim_diff/forms.py:19 #: changedetectionio/processors/image_ssim_diff/forms.py:69 msgid "Bounding box value is too long" -msgstr "邊界框值太長" +msgstr "邊界框數值太長" #: changedetectionio/processors/image_ssim_diff/forms.py:23 msgid "Bounding box must be in format: x,y,width,height (integers only)" -msgstr "邊界框的格式必須為:x,y,寬度,高度(僅限整數)" +msgstr "邊界框格式必須為:x,y,width,height(僅限整數)" #: changedetectionio/processors/image_ssim_diff/forms.py:29 msgid "Bounding box values must be non-negative" -msgstr "邊界框值必須是非負數" +msgstr "邊界框數值必須為非負數" #: changedetectionio/processors/image_ssim_diff/forms.py:31 msgid "Bounding box values are too large" -msgstr "邊界框值太大" +msgstr "邊界框數值太大" #: changedetectionio/processors/image_ssim_diff/forms.py:40 msgid "Selection mode must be either \"element\" or \"draw\"" -msgstr "" +msgstr "選擇模式必須是 \"element\" 或 \"draw\"" #: changedetectionio/processors/image_ssim_diff/forms.py:47 msgid "Minimum Change Percentage" -msgstr "最小變化百分比" +msgstr "最小變更百分比" #: changedetectionio/processors/image_ssim_diff/forms.py:56 msgid "Pixel Difference Sensitivity" msgstr "像素差異靈敏度" #: changedetectionio/processors/image_ssim_diff/forms.py:58 -#, fuzzy msgid "Use global default" -msgstr "使用系統默認值" +msgstr "使用全域預設值" #: changedetectionio/processors/image_ssim_diff/forms.py:66 msgid "Bounding Box" msgstr "邊界框" #: changedetectionio/processors/image_ssim_diff/forms.py:76 -#, fuzzy msgid "Selection Mode" -msgstr "選擇方式:" +msgstr "選擇模式" #: changedetectionio/processors/image_ssim_diff/forms.py:79 msgid "Selection mode value is too long" -msgstr "選擇模式值太長" +msgstr "選擇模式數值太長" #: changedetectionio/processors/image_ssim_diff/forms.py:87 msgid "Screenshot Comparison" -msgstr "截圖對比" +msgstr "截圖比對" #: changedetectionio/processors/image_ssim_diff/preview.py:91 msgid "Preview unavailable - No snapshots captured yet" -msgstr "" +msgstr "無法預覽 - 尚未擷取快照" #: changedetectionio/processors/image_ssim_diff/processor.py:21 msgid "Visual / Image screenshot change detection" -msgstr "視覺/圖像截圖變化檢測" +msgstr "視覺 / 圖片截圖變更檢測" #: changedetectionio/processors/image_ssim_diff/processor.py:22 msgid "Compares screenshots using fast OpenCV algorithm, 10-100x faster than SSIM" -msgstr "" +msgstr "使用快速 OpenCV 演算法比對截圖,比 SSIM 快 10-100 倍" #: changedetectionio/processors/restock_diff/forms.py:15 msgid "Re-stock detection" @@ -2201,11 +2155,11 @@ msgstr "任何可用性變更" #: changedetectionio/processors/restock_diff/forms.py:18 msgid "Off, don't follow availability/restock" -msgstr "關閉,不遵循庫存/補貨情況" +msgstr "關閉,不追蹤可用性 / 補貨" #: changedetectionio/processors/restock_diff/forms.py:21 msgid "Below price to trigger notification" -msgstr "低於價格觸發通知" +msgstr "低於此價格觸發通知" #: changedetectionio/processors/restock_diff/forms.py:22 #: changedetectionio/processors/restock_diff/forms.py:24 @@ -2214,12 +2168,12 @@ msgstr "無限制" #: changedetectionio/processors/restock_diff/forms.py:23 msgid "Above price to trigger notification" -msgstr "高於價格觸發通知" +msgstr "高於此價格觸發通知" #: changedetectionio/processors/restock_diff/forms.py:25 #, python-format msgid "Threshold in %% for price changes since the original price" -msgstr "自原始價格以來價格變化的閾值(百分比)" +msgstr "自原始價格以來價格變化的閾值(%%)" #: changedetectionio/processors/restock_diff/forms.py:28 msgid "Should be between 0 and 100" @@ -2227,16 +2181,15 @@ msgstr "應介於 0 到 100 之間" #: changedetectionio/processors/restock_diff/forms.py:31 msgid "Follow price changes" -msgstr "關注價格變化" +msgstr "追蹤價格變化" #: changedetectionio/processors/restock_diff/forms.py:37 -#, fuzzy msgid "Restock & Price Detection" -msgstr "補貨及價格" +msgstr "補貨與價格檢測" #: changedetectionio/processors/restock_diff/processor.py:13 msgid "Re-stock & Price detection for pages with a SINGLE product" -msgstr "單個產品頁面的補貨和價格檢測" +msgstr "針對單一產品頁面的補貨與價格檢測" #: changedetectionio/processors/restock_diff/processor.py:14 msgid "Detects if the product goes back to in-stock" @@ -2244,153 +2197,140 @@ msgstr "檢測產品是否恢復庫存" #: changedetectionio/processors/text_json_diff/processor.py:22 msgid "Webpage Text/HTML, JSON and PDF changes" -msgstr "網頁文本/HTML、JSON 和 PDF 更改" +msgstr "網頁文字 / HTML、JSON 和 PDF 變更" #: changedetectionio/processors/text_json_diff/processor.py:23 msgid "Detects all text changes where possible" -msgstr "盡可能檢測所有文本更改" +msgstr "盡可能檢測所有文字變更" #: changedetectionio/templates/_helpers.html:25 msgid "Entry" -msgstr "" +msgstr "項目" #: changedetectionio/templates/_helpers.html:153 -#, fuzzy msgid "Actions" -msgstr "狀況" +msgstr "動作" #: changedetectionio/templates/_helpers.html:172 msgid "Add a row/rule after" -msgstr "" +msgstr "在後方新增一行 / 規則" #: changedetectionio/templates/_helpers.html:173 msgid "Remove this row/rule" -msgstr "" +msgstr "移除此行 / 規則" #: changedetectionio/templates/_helpers.html:174 msgid "Verify this rule against current snapshot" -msgstr "" +msgstr "針對目前快照驗證此規則" #: changedetectionio/templates/_helpers.html:184 msgid "" "Error - This watch needs Chrome (with playwright/sockpuppetbrowser), but " "Chrome based fetching is not enabled." -msgstr "" +msgstr "錯誤 - 此監測任務需要 Chrome(搭配 playwright / sockpuppetbrowser),但未啟用基於 Chrome 的抓取功能。" #: changedetectionio/templates/_helpers.html:184 msgid "Alternatively try our" -msgstr "" +msgstr "或者嘗試我們" #: changedetectionio/templates/_helpers.html:184 msgid "" "very affordable subscription based service which has all this setup for " "you" -msgstr "" +msgstr "非常實惠的訂閱服務,為您準備好所有設定" #: changedetectionio/templates/_helpers.html:185 -#, fuzzy msgid "You may need to" -msgstr "你需要" +msgstr "您可能需要" #: changedetectionio/templates/_helpers.html:185 msgid "Enable playwright environment variable" -msgstr "" +msgstr "啟用 playwright 環境變數" #: changedetectionio/templates/_helpers.html:185 msgid "and uncomment the" -msgstr "" +msgstr "並取消註解" #: changedetectionio/templates/_helpers.html:185 -#, fuzzy msgid "in the" -msgstr "這" +msgstr "於" #: changedetectionio/templates/_helpers.html:185 -#, fuzzy msgid "file" -msgstr "標題" +msgstr "檔案" #: changedetectionio/templates/_helpers.html:240 msgid "Set a hourly/week day schedule" -msgstr "" +msgstr "設定每小時 / 平日排程" #: changedetectionio/templates/_helpers.html:247 -#, fuzzy msgid "Schedule time limits" -msgstr "複檢時間(分鐘)" +msgstr "排程時間限制" #: changedetectionio/templates/_helpers.html:248 msgid "Business hours" -msgstr "" +msgstr "營業時間" #: changedetectionio/templates/_helpers.html:249 -#, fuzzy msgid "Weekends" -msgstr "週數" +msgstr "週末" #: changedetectionio/templates/_helpers.html:250 -#, fuzzy msgid "Reset" -msgstr "要求" +msgstr "重置" #: changedetectionio/templates/_helpers.html:259 msgid "" "Warning, one or more of your 'days' has a duration that would extend into" " the next day." -msgstr "" +msgstr "警告,您設定的一個或多個「天」持續時間將延伸至隔天。" #: changedetectionio/templates/_helpers.html:260 msgid "This could have unintended consequences." -msgstr "" +msgstr "這可能會產生非預期的後果。" #: changedetectionio/templates/_helpers.html:270 -#, fuzzy msgid "More help and examples about using the scheduler" -msgstr "更多幫助和示例請參見此處" +msgstr "關於使用排程器的更多幫助和範例" #: changedetectionio/templates/_helpers.html:275 -#, fuzzy msgid "Want to use a time schedule?" -msgstr "使用時間調度器" +msgstr "想要使用時間排程嗎?" #: changedetectionio/templates/_helpers.html:275 msgid "First confirm/save your Time Zone Settings" -msgstr "" +msgstr "請先確認 / 儲存您的時區設定" #: changedetectionio/templates/_helpers.html:284 msgid "" "Triggers a change if this text appears, AND something changed in the " "document." -msgstr "" +msgstr "如果出現此文字,且文件中有些內容變更,則觸發變更。" #: changedetectionio/templates/_helpers.html:284 -#, fuzzy msgid "Triggered text" -msgstr "錯誤文本" +msgstr "觸發的文字" #: changedetectionio/templates/_helpers.html:285 msgid "Ignored for calculating changes, but still shown." -msgstr "" +msgstr "計算變更時忽略,但仍會顯示。" #: changedetectionio/templates/_helpers.html:285 -#, fuzzy msgid "Ignored text" -msgstr "錯誤文本" +msgstr "忽略的文字" #: changedetectionio/templates/_helpers.html:286 -#, fuzzy msgid "No change-detection will occur because this text exists." -msgstr "文本匹配時阻止更改檢測" +msgstr "因為存在此文字,將不會進行變更檢測。" #: changedetectionio/templates/_helpers.html:286 -#, fuzzy msgid "Blocked text" -msgstr "錯誤文本" +msgstr "被阻擋的文字" #: changedetectionio/templates/base.html:78 #: changedetectionio/templates/base.html:168 msgid "GROUPS" -msgstr "團體" +msgstr "群組" #: changedetectionio/templates/base.html:81 #: changedetectionio/templates/base.html:169 @@ -2400,7 +2340,7 @@ msgstr "設定" #: changedetectionio/templates/base.html:84 #: changedetectionio/templates/base.html:170 msgid "IMPORT" -msgstr "導入" +msgstr "匯入" #: changedetectionio/templates/base.html:87 #: changedetectionio/templates/base.html:171 @@ -2415,19 +2355,19 @@ msgstr "編輯" #: changedetectionio/templates/base.html:101 #: changedetectionio/templates/base.html:177 msgid "LOG OUT" -msgstr "退出" +msgstr "登出" #: changedetectionio/templates/base.html:108 msgid "Search, or Use Alt+S Key" -msgstr "搜索或使用 Alt+S 鍵" +msgstr "搜尋,或使用 Alt+S 鍵" #: changedetectionio/templates/base.html:114 msgid "Toggle Light/Dark Mode" -msgstr "切換亮/暗模式" +msgstr "切換亮 / 暗模式" #: changedetectionio/templates/base.html:115 msgid "Toggle light/dark mode" -msgstr "切換亮/暗模式" +msgstr "切換亮 / 暗模式" #: changedetectionio/templates/base.html:125 msgid "Change Language" @@ -2438,41 +2378,37 @@ msgid "Change language" msgstr "更改語言" #: changedetectionio/templates/base.html:253 -#, fuzzy msgid "Watch List" -msgstr "監控列表" +msgstr "監測列表" #: changedetectionio/templates/base.html:258 -#, fuzzy msgid "Watches" -msgstr "監控項" +msgstr "監測任務" #: changedetectionio/templates/base.html:261 msgid "Queue Status" -msgstr "" +msgstr "佇列狀態" #: changedetectionio/templates/base.html:270 -#, fuzzy msgid "Queue" -msgstr "排隊" +msgstr "佇列" #: changedetectionio/templates/base.html:274 #: changedetectionio/templates/base.html:279 -#, fuzzy msgid "Settings" msgstr "設定" #: changedetectionio/templates/base.html:293 msgid "Sitemap Crawler" -msgstr "" +msgstr "Sitemap 爬蟲" #: changedetectionio/templates/base.html:318 msgid "Sitemap" -msgstr "" +msgstr "Sitemap" #: changedetectionio/templates/base.html:354 msgid "Real-time updates offline" -msgstr "離線實時更新" +msgstr "離線即時更新" #: changedetectionio/templates/base.html:364 msgid "Select Language" @@ -2482,26 +2418,24 @@ msgstr "選擇語言" msgid "" "Language support is in beta, please help us improve by opening a PR on " "GitHub with any updates." -msgstr "" +msgstr "語言支援尚在 Beta 階段,請在 GitHub 上提交 PR 以協助我們改進。" #: changedetectionio/templates/base.html:387 #: changedetectionio/templates/base.html:400 -#, fuzzy msgid "Search" -msgstr "搜尋中" +msgstr "搜尋" #: changedetectionio/templates/base.html:392 msgid "URL or Title" -msgstr "" +msgstr "URL 或標題" #: changedetectionio/templates/base.html:392 -#, fuzzy msgid "in" -msgstr "資訊" +msgstr "於" #: changedetectionio/templates/base.html:393 msgid "Enter search term..." -msgstr "" +msgstr "輸入搜尋關鍵字 ..." #: changedetectionio/templates/login.html:11 msgid "Password" @@ -2509,409 +2443,4 @@ msgstr "密碼" #: changedetectionio/templates/login.html:17 msgid "Login" -msgstr "登入" - -#~ msgid "Invalid time format. Use HH:MM." -#~ msgstr "時間格式無效。使用時:分。" - -#~ msgid "Not a valid timezone name" -#~ msgstr "不是有效的時區名稱" - -#~ msgid "not set" -#~ msgstr "還沒有" - -#~ msgid "Start At" -#~ msgstr "統計數據" - -#~ msgid "Run duration" -#~ msgstr "暫無信息" - -#~ msgid "Use time scheduler" -#~ msgstr "使用時間調度器" - -#~ msgid "Optional timezone to run in" -#~ msgstr "運行時的可選時區" - -#~ msgid "Monday" -#~ msgstr "週一" - -#~ msgid "Tuesday" -#~ msgstr "週二" - -#~ msgid "Wednesday" -#~ msgstr "週三" - -#~ msgid "Thursday" -#~ msgstr "週四" - -#~ msgid "Friday" -#~ msgstr "星期五" - -#~ msgid "Saturday" -#~ msgstr "週六" - -#~ msgid "Sunday" -#~ msgstr "星期日" - -#~ msgid "Weeks" -#~ msgstr "週數" - -#~ msgid "Should contain zero or more seconds" -#~ msgstr "應包含零或更多秒" - -#~ msgid "Days" -#~ msgstr "天" - -#~ msgid "Hours" -#~ msgstr "字" - -#~ msgid "Minutes" -#~ msgstr "沉默的" - -#~ msgid "Seconds" -#~ msgstr "秒" - -#~ msgid "Empty value not allowed." -#~ msgstr "不允許為空值。" - -#~ msgid "Invalid value." -#~ msgstr "無效值。" - -#~ msgid "Watch" -#~ msgstr "# 手錶" - -#~ msgid "Processor" -#~ msgstr "處理器" - -#~ msgid "Edit > Watch" -#~ msgstr "先編輯後觀看" - -#~ msgid "Fetch Method" -#~ msgstr "設置獲取方法" - -#~ msgid "Notification Body" -#~ msgstr "通知" - -#~ msgid "Notification format" -#~ msgstr "通知" - -#~ msgid "Notification Title" -#~ msgstr "通知" - -#~ msgid "Notification URL List" -#~ msgstr "通知" - -#~ msgid "Processor - What do you want to achieve?" -#~ msgstr "處理器 - 您想要實現什麼?" - -#~ msgid "Default timezone for watch check scheduler" -#~ msgstr "手錶檢查調度程序的默認時區" - -#~ msgid "Wait seconds before extracting text" -#~ msgstr "提取文本前幾秒。" - -#~ msgid "Should contain one or more seconds" -#~ msgstr "應包含一秒或多秒" - -#~ msgid "URLs" -#~ msgstr "網址" - -#~ msgid "Upload .xlsx file" -#~ msgstr "上傳 .xlsx 文件" - -#~ msgid "Must be .xlsx file!" -#~ msgstr "必須是 .xlsx 文件!" - -#~ msgid "File mapping" -#~ msgstr "文件映射類型。" - -#~ msgid "Operation" -#~ msgstr "用戶界面選項" - -#~ msgid "Selector" -#~ msgstr "選擇方式:" - -#~ msgid "value" -#~ msgstr "暫停" - -#~ msgid "Use global settings for time between check and scheduler." -#~ msgstr "使用全局設置檢查和調度程序之間的時間。" - -#~ msgid "CSS/JSONPath/JQ/XPath Filters" -#~ msgstr "CSS/xPath 過濾器" - -#~ msgid "Remove elements" -#~ msgstr "已刪除" - -#~ msgid "Extract text" -#~ msgstr "提取數據" - -#~ msgid "Ignore lines containing" -#~ msgstr "忽略任何匹配的行" - -#~ msgid "Request body" -#~ msgstr "要求" - -#~ msgid "Request method" -#~ msgstr "要求" - -#~ msgid "Ignore status codes (process non-2xx status codes as normal)" -#~ msgstr "忽略狀態代碼(正常處理非 2xx 狀態代碼)" - -#~ msgid "Only trigger when unique lines appear in all history" -#~ msgstr "僅當出現唯一線條時觸發" - -#~ msgid "Sort text alphabetically" -#~ msgstr "按字母順序對文本進行排序" - -#~ msgid "Strip ignored lines" -#~ msgstr "去掉忽略的行" - -#~ msgid "Trim whitespace before and after text" -#~ msgstr "刪除每行文本前後的所有空格" - -#~ msgid "Added lines" -#~ msgstr "線路" - -#~ msgid "Replaced/changed lines" -#~ msgstr "更換/更改線路" - -#~ msgid "Removed lines" -#~ msgstr "已刪除" - -#~ msgid "Keyword triggers - Trigger/wait for text" -#~ msgstr "關鍵字觸發器 - 觸發/等待文本" - -#~ msgid "Block change-detection while text matches" -#~ msgstr "文本匹配時阻止更改檢測" - -#~ msgid "Execute JavaScript before change detection" -#~ msgstr "在更改檢測之前執行 JavaScript" - -#~ msgid "Proxy" -#~ msgstr "代理人" - -#~ msgid "Send a notification when the filter can no longer be found on the page" -#~ msgstr "當頁面上找不到過濾器時發送通知" - -#~ msgid "On" -#~ msgstr "沒有任何" - -#~ msgid "Attach screenshot to notification (where possible)" -#~ msgstr "將屏幕截圖附加到通知(如果可能)" - -#~ msgid "Match" -#~ msgstr "# 手錶" - -#~ msgid "Match all of the following" -#~ msgstr "匹配以下所有內容" - -#~ msgid "Match any of the following" -#~ msgstr "匹配以下任意一項" - -#~ msgid "Use page <title> in list" -#~ msgstr "使用列表中的頁面<標題>" - -#~ msgid "Name" -#~ msgstr "取消靜音" - -#~ msgid "Proxy URL" -#~ msgstr "代理網址" - -#~ msgid "Proxy URLs must start with http://, https:// or socks5://" -#~ msgstr "代理 URL 必須以 http://、https:// 或ocks5:// 開頭" - -#~ msgid "Browser connection URL" -#~ msgstr "瀏覽器連接網址" - -#~ msgid "Browser URLs must start with wss:// or ws://" -#~ msgstr "瀏覽器 URL 必須以 wss:// 或 ws:// 開頭" - -#~ msgid "Plaintext requests" -#~ msgstr "明文請求" - -#~ msgid "Chrome requests" -#~ msgstr "要求" - -#~ msgid "Default proxy" -#~ msgstr "默認代理" - -#~ msgid "Random jitter seconds ± check" -#~ msgstr "隨機抖動秒±檢查" - -#~ msgid "Number of fetch workers" -#~ msgstr "取貨工人數量" - -#~ msgid "Should be between 1 and 50" -#~ msgstr "應介於 1 到 50 之間" - -#~ msgid "Requests timeout in seconds" -#~ msgstr "請求超時(以秒為單位)" - -#~ msgid "Should be between 1 and 999" -#~ msgstr "應介於 1 到 999 之間" - -#~ msgid "Default User-Agent overrides" -#~ msgstr "默認用戶代理覆蓋" - -#~ msgid "Open 'History' page in a new tab" -#~ msgstr "在新選項卡中打開“歷史記錄”頁面" - -#~ msgid "Realtime UI Updates Enabled" -#~ msgstr "離線實時更新" - -#~ msgid "Favicons Enabled" -#~ msgstr "考慮啟用" - -#~ msgid "Use page <title> in watch overview list" -#~ msgstr "在觀看概覽列表中使用頁面<標題>" - -#~ msgid "API access token security check enabled" -#~ msgstr "已啟用 API 訪問令牌安全檢查" - -#~ msgid "Notification base URL override" -#~ msgstr "通知警報計數" - -#~ msgid "Treat empty pages as a change?" -#~ msgstr "將空頁視為更改?" - -#~ msgid "Ignore Text" -#~ msgstr "錯誤文本" - -#~ msgid "Ignore whitespace" -#~ msgstr "忽略空格" - -#~ msgid "Must be between 0 and 100" -#~ msgstr "必須介於 0 到 100 之間" - -#~ msgid "Pager size" -#~ msgstr "尋呼機尺寸" - -#~ msgid "Should be atleast zero (disabled)" -#~ msgstr "應至少為零(禁用)" - -#~ msgid "RSS Content format" -#~ msgstr "RSS 內容格式" - -#~ msgid "RSS <description> body built from" -#~ msgstr "RSS <描述> 正文構建於" - -#~ msgid "Render anchor tag content" -#~ msgstr "渲染錨標記內容" - -#~ msgid "Allow anonymous access to watch history page when password is enabled" -#~ msgstr "啟用密碼後允許匿名訪問觀看歷史記錄頁面" - -#~ msgid "Hide muted watches from RSS feed" -#~ msgstr "從 RSS 源中隱藏靜音的手錶" - -#~ msgid "Enable RSS reader mode " -#~ msgstr "啟用 RSS 閱讀器模式" - -#~ msgid "Number of changes to show in watch RSS feed" -#~ msgstr "觀看 RSS 源中顯示的更改數量" - -#~ msgid "Should contain zero or more attempts" -#~ msgstr "應包含零次或多次嘗試" - -#~ msgid "Number of times the filter can be missing before sending a notification" -#~ msgstr "發送通知之前過濾器可能丟失的次數" - -#~ msgid "RegEx to extract" -#~ msgstr "要提取的正則表達式" - -#~ msgid "Extract as CSV" -#~ msgstr "提取數據" - -#~ msgid "Bounding box value is too long" -#~ msgstr "邊界框值太長" - -#~ msgid "Bounding box must be in format: x,y,width,height (integers only)" -#~ msgstr "邊界框的格式必須為:x,y,寬度,高度(僅限整數)" - -#~ msgid "Bounding box values must be non-negative" -#~ msgstr "邊界框值必須是非負數" - -#~ msgid "Bounding box values are too large" -#~ msgstr "邊界框值太大" - -#~ msgid "Minimum Change Percentage" -#~ msgstr "最小變化百分比" - -#~ msgid "Pixel Difference Sensitivity" -#~ msgstr "像素差異靈敏度" - -#~ msgid "Use global default" -#~ msgstr "使用系統默認值" - -#~ msgid "Bounding Box" -#~ msgstr "邊界框" - -#~ msgid "Selection Mode" -#~ msgstr "選擇方式:" - -#~ msgid "Selection mode value is too long" -#~ msgstr "選擇模式值太長" - -#~ msgid "Screenshot Comparison" -#~ msgstr "截圖對比" - -#~ msgid "Re-stock detection" -#~ msgstr "補貨檢測" - -#~ msgid "In Stock only (Out Of Stock -> In Stock only)" -#~ msgstr "僅有庫存(缺貨 -> 僅有庫存)" - -#~ msgid "Any availability changes" -#~ msgstr "任何可用性變更" - -#~ msgid "Off, don't follow availability/restock" -#~ msgstr "關閉,不遵循庫存/補貨情況" - -#~ msgid "Below price to trigger notification" -#~ msgstr "低於價格觸發通知" - -#~ msgid "No limit" -#~ msgstr "無限制" - -#~ msgid "Above price to trigger notification" -#~ msgstr "高於價格觸發通知" - -#~ msgid "Threshold in %% for price changes since the original price" -#~ msgstr "自原始價格以來價格變化的閾值(百分比)" - -#~ msgid "Should be between 0 and 100" -#~ msgstr "應介於 0 到 100 之間" - -#~ msgid "Follow price changes" -#~ msgstr "關注價格變化" - -#~ msgid "Restock & Price Detection" -#~ msgstr "補貨及價格" - -#~ msgid "Visual / Image screenshot change detection" -#~ msgstr "視覺/圖像截圖變化檢測" - -#~ msgid "" -#~ "Compares screenshots using fast OpenCV " -#~ "algorithm, 10-100x faster than SSIM" -#~ msgstr "使用快速 OpenCV 算法比較屏幕截圖,比 SSIM 快 10-100 倍" - -#~ msgid "Visual" -#~ msgstr "視覺的" - -#~ msgid "Re-stock & Price detection for pages with a SINGLE product" -#~ msgstr "單個產品頁面的補貨和價格檢測" - -#~ msgid "Detects if the product goes back to in-stock" -#~ msgstr "檢測產品是否恢復庫存" - -#~ msgid "Restock" -#~ msgstr "補貨" - -#~ msgid "Webpage Text/HTML, JSON and PDF changes" -#~ msgstr "網頁文本/HTML、JSON 和 PDF 更改" - -#~ msgid "Detects all text changes where possible" -#~ msgstr "盡可能檢測所有文本更改" - +msgstr "登入" \ No newline at end of file diff --git a/changedetectionio/translations/zh_TW/LC_MESSAGES/messages.mo b/changedetectionio/translations/zh_TW/LC_MESSAGES/messages.mo deleted file mode 100644 index 781a94ecc..000000000 Binary files a/changedetectionio/translations/zh_TW/LC_MESSAGES/messages.mo and /dev/null differ diff --git a/requirements.txt b/requirements.txt index d2fbfa4ea..d5babc987 100644 --- a/requirements.txt +++ b/requirements.txt @@ -91,7 +91,7 @@ jq~=1.3; python_version >= "3.8" and sys_platform == "linux" # playwright is installed at Dockerfile build time because it's not available on all platforms -pyppeteer-ng==2.0.0rc10 +pyppeteer-ng==2.0.0rc11 pyppeteerstealth>=0.0.4 # Include pytest, so if theres a support issue we can ask them to run these tests on their setup @@ -100,7 +100,7 @@ pytest-flask ~=1.3 pytest-mock ~=3.15 # Anything 4.0 and up but not 5.0 -jsonschema ~= 4.25 +jsonschema ~= 4.26 # OpenAPI validation support openapi-core[flask] >= 0.19.0