From 22ab668f8391d37c16a5895c9c4104da7ccd184f Mon Sep 17 00:00:00 2001 From: iG8R <11407417+iG8R@users.noreply.github.com> Date: Mon, 24 Aug 2026 23:59:20 +0300 Subject: [PATCH 1/4] Add Ukrainian support for the 'In stock'/'Not in stock' status (#4330) --- .../content_fetchers/res/stock-not-in-stock.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/changedetectionio/content_fetchers/res/stock-not-in-stock.js b/changedetectionio/content_fetchers/res/stock-not-in-stock.js index 82673c10..4fd20d10 100644 --- a/changedetectionio/content_fetchers/res/stock-not-in-stock.js +++ b/changedetectionio/content_fetchers/res/stock-not-in-stock.js @@ -108,7 +108,14 @@ async () => { '品切れ', '已售', '已售完', - '품절' + '품절', + "товар закінчився", + "немає в наявності", + "нема в наявності", + "закінчився", + "знято з виробництва", + "недоступний", + "немає на складі" ]; From bb2e6adece8998a0282de0af73695fa0a0e32fc4 Mon Sep 17 00:00:00 2001 From: dgtlmoon Date: Tue, 25 Aug 2026 20:15:59 +0200 Subject: [PATCH 2/4] Add watch UI should show which browser(s) are available and set default browser (#4334) --- .../blueprint/add_watch_ui/__init__.py | 36 +++- .../blueprint/add_watch_ui/browser_config.py | 130 +++++++++++++ .../add_watch_ui/static/add-watch.js | 16 +- .../add_watch_ui/templates/add-watch-ui.html | 20 ++ changedetectionio/blueprint/ui/views.py | 7 + changedetectionio/forms.py | 63 +++++++ .../static/js/visual-selector.js | 6 +- .../static/styles/scss/parts/_add-watch.scss | 48 +++++ changedetectionio/static/styles/styles.css | 2 +- changedetectionio/store/__init__.py | 19 +- .../tests/llm/test_llm_features_disabled.py | 18 ++ .../tests/test_add_watch_ui_browser.py | 172 ++++++++++++++++++ .../translations/cs/LC_MESSAGES/messages.po | 27 ++- .../translations/de/LC_MESSAGES/messages.po | 27 ++- .../en_GB/LC_MESSAGES/messages.po | 27 ++- .../en_US/LC_MESSAGES/messages.po | 27 ++- .../translations/es/LC_MESSAGES/messages.po | 27 ++- .../translations/fr/LC_MESSAGES/messages.po | 27 ++- .../translations/it/LC_MESSAGES/messages.po | 27 ++- .../translations/ja/LC_MESSAGES/messages.po | 27 ++- .../translations/ko/LC_MESSAGES/messages.po | 27 ++- changedetectionio/translations/messages.pot | 29 ++- .../translations/pl/LC_MESSAGES/messages.po | 27 ++- .../pt_BR/LC_MESSAGES/messages.po | 27 ++- .../translations/ru/LC_MESSAGES/messages.po | 27 ++- .../translations/tr/LC_MESSAGES/messages.po | 27 ++- .../translations/uk/LC_MESSAGES/messages.po | 27 ++- .../translations/zh/LC_MESSAGES/messages.po | 27 ++- .../zh_Hant_TW/LC_MESSAGES/messages.po | 27 ++- 29 files changed, 917 insertions(+), 81 deletions(-) create mode 100644 changedetectionio/blueprint/add_watch_ui/browser_config.py create mode 100644 changedetectionio/tests/test_add_watch_ui_browser.py diff --git a/changedetectionio/blueprint/add_watch_ui/__init__.py b/changedetectionio/blueprint/add_watch_ui/__init__.py index f59645f2..dddeac1f 100644 --- a/changedetectionio/blueprint/add_watch_ui/__init__.py +++ b/changedetectionio/blueprint/add_watch_ui/__init__.py @@ -3,6 +3,7 @@ from loguru import logger from changedetectionio import forms from changedetectionio.auth_decorator import login_optionally_required +from . import browser_config from changedetectionio.store import ChangeDetectionStore from changedetectionio.validate_url import is_fetch_url_allowed @@ -19,11 +20,17 @@ def construct_blueprint(datastore: ChangeDetectionStore): form = forms.quickWatchForm(None) llm_configured = bool(_get_llm_config(datastore)) + # Start on the browser the live preview would actually use + form.fetch_backend.data = browser_config.default_visual_browser(datastore) + return render_template( "add-watch-ui.html", form=form, llm_configured=llm_configured, llm_intent_watch_placeholder=LLM_INTENT_WATCH_PLACEHOLDER, + # Listed but not selectable (the system default when it can't render a preview) + unusable_browsers=browser_config.unusable_values(datastore), + system_default_browser=browser_config.system_default_description(datastore), ) @add_watch_ui_blueprint.route("/snapshot", methods=['GET']) @@ -61,15 +68,27 @@ def construct_blueprint(datastore: ChangeDetectionStore): logger.warning(f"Add-watch snapshot: refused '{url}' - {reason}") return make_response(reason, 400) - # Use whatever fetcher the application is configured to use by default - # (e.g. CloakBrowser, Playwright/sockpuppet) so the preview matches real checks. - fetcher_name = datastore.data['settings']['application'].get('fetch_backend', 'html_requests') - logger.debug(f"Add-watch snapshot: fetching '{url}' using system default fetcher '{fetcher_name}'") + # Which browser to preview with. The page posts the one picked in its browser list; + # with nothing asked for we fall back to whatever it would have preselected. + # Either way it has to be able to render a preview - the plain HTTP client + # produces no screenshot and no element data, so previewing with it is pointless + # (and it used to be the silent default here, see the system-default bug). + fetcher_name = (request.args.get('fetch_backend') or '').strip() or browser_config.default_visual_browser(datastore) + if not fetcher_name or not browser_config.is_visual_capable(fetcher_name, datastore): + logger.warning(f"Add-watch snapshot: refused browser '{fetcher_name}' for '{url}'") + return make_response('No interactive browser available that can render a live preview ' + '(needs screenshots + element data)', 400) + + # acquire_browser_for_fetcher() looks the name up as a fetcher class, so 'system' + # has to be collapsed to the real backend first or a fetcher that launches its own + # browser would be skipped in favour of the CDP endpoint. + resolved_fetcher = browser_config.resolve_backend(fetcher_name, datastore) + logger.debug(f"Add-watch snapshot: fetching '{url}' using '{fetcher_name}' (resolved: '{resolved_fetcher}')") async def _fetch_snapshot(): keepalive_ms = 30 * 1000 browser, playwright_context = await acquire_browser_for_fetcher( - fetcher_name, proxy=None, keepalive_ms=keepalive_ms + resolved_fetcher, proxy=None, keepalive_ms=keepalive_ms ) stepper = browsersteps_live_ui(playwright_browser=browser, proxy=None, start_url=url) @@ -119,6 +138,13 @@ def construct_blueprint(datastore: ChangeDetectionStore): with open(os.path.join(temp_dir, "preload-fetch.json"), 'w', encoding='utf-8') as f: json.dump({"content": html, "status_code": 200, "headers": {"content-type": "text/html"}}, f) + # This directory becomes the new watch's data_dir on submit, so the watch's own + # settings file is where the previewing browser belongs: record it here and the + # saved watch checks with the browser that actually rendered this snapshot, + # instead of falling back to a system default that may not even do screenshots. + # Read back by make_temporary_watch_active_watch(); commit() then rewrites it in full. + with open(os.path.join(temp_dir, "watch.json"), 'w', encoding='utf-8') as f: + json.dump({"fetch_backend": fetcher_name}, f) except Exception as e: logger.error(f"Add-watch snapshot: could not park temporary data for {url}: {e}") temp_uuid = None diff --git a/changedetectionio/blueprint/add_watch_ui/browser_config.py b/changedetectionio/blueprint/add_watch_ui/browser_config.py new file mode 100644 index 00000000..2b36a60e --- /dev/null +++ b/changedetectionio/blueprint/add_watch_ui/browser_config.py @@ -0,0 +1,130 @@ +"""Which content fetchers can drive the Add-Watch live preview / visual selector. + +Single source of truth for "can this browser render a live preview": the Add-Watch +browser list, the /snapshot endpoint and the submit-time form validator all resolve +through here, so the UI can never offer - and the server can never accept - a fetcher +that is unable to produce what the visual selector needs. + +The preview is rendered by browsersteps_live_ui() (see blueprint/browser_steps), so a +usable browser needs `supports_browser_steps` *as well as* screenshots and xpath +element data. That third flag is what rules out Selenium/WebDriver: it can screenshot +during a normal check, but it cannot drive the interactive session the preview needs +(acquire_browser_for_fetcher() would quietly connect to PLAYWRIGHT_DRIVER_URL instead, +which is not the browser the user picked). It also rules out settings.requests +extra_browsers, which are WebDriver connection URLs, so they are not offered here. +""" + +from loguru import logger + +SYSTEM_DEFAULT = 'system' + +# Every flag a fetcher must set to be usable for the Add-Watch live preview. +REQUIRED_CAPABILITIES = ( + 'supports_browser_steps', + 'supports_screenshots', + 'supports_xpath_element_data', +) + + +def is_visual_capable(fetch_backend, datastore): + """True when this backend can render the Add-Watch live preview. + + An unknown name - including anything a client made up - resolves to no fetcher + class and so to all-False capabilities, so it can never pass. That is what makes + the posted value safe without any string filtering of our own. + + Reads the flags off the class the same way Watch.fetcher_supports_screenshots does, + rather than via pluggy_interface.get_fetcher_capabilities(): that logs every lookup + at INFO, and this runs for the whole fetcher list on any page carrying the quick-add + form. Plugin fetchers are registered as module attributes, so they resolve here too. + """ + from changedetectionio import content_fetchers + from changedetectionio.content_fetchers.base import FetcherCapabilities + + name = fetch_backend or SYSTEM_DEFAULT + if name == SYSTEM_DEFAULT: + name = datastore.data['settings']['application'].get('fetch_backend') or 'html_requests' + + caps = FetcherCapabilities.from_fetcher(getattr(content_fetchers, name, None)) + missing = [flag for flag in REQUIRED_CAPABILITIES if not getattr(caps, flag, False)] + logger.debug(f"Add-watch browser '{fetch_backend or SYSTEM_DEFAULT}' -> '{name}': " + f"{', '.join(f'{k}={v}' for k, v in caps.model_dump().items())} - " + f"{'usable for live preview' if not missing else 'not offered, missing ' + ', '.join(missing)}") + return not missing + + +def resolve_backend(fetch_backend, datastore): + """The concrete fetcher name behind a choice, so 'system' can be acted on. + + Needed because acquire_browser_for_fetcher() looks the name up as a class: handing + it 'system' would skip a fetcher that launches its own browser (CloakBrowser) and + fall through to the CDP endpoint instead. + """ + from changedetectionio import content_fetchers + + _fetcher_class, resolved, _custom_url = content_fetchers.resolve_content_fetcher( + {'fetch_backend': fetch_backend or SYSTEM_DEFAULT}, datastore) + return resolved + + +def list_visual_browser_choices(datastore): + """(value, label) for every fetcher that can drive the visual selector. + + is_visual_capable() logs each candidate's capabilities as it goes, so a user + wondering why their browser isn't in the list can see the missing flag at debug + level. + """ + from changedetectionio import content_fetchers + + choices = [(name, str(description)) for name, description in content_fetchers.available_fetchers() + if is_visual_capable(name, datastore)] + logger.debug(f"Add-watch browsers offered for the live preview: " + f"{[name for name, _label in choices] or 'none'}") + return choices + + +def default_visual_browser(datastore): + """Which browser the Add-Watch page should start on. + + 'system' when the global default happens to be capable (so the new watch keeps + following the system setting), otherwise the first capable browser, and None when + there is nothing usable at all. + """ + if is_visual_capable(SYSTEM_DEFAULT, datastore): + return SYSTEM_DEFAULT + choices = list_visual_browser_choices(datastore) + return choices[0][0] if choices else None + + +def system_default_description(datastore): + """Label for whatever backend 'system' currently points at.""" + from changedetectionio import content_fetchers + + system_backend = datastore.data['settings']['application'].get('fetch_backend') or 'html_requests' + return str(dict(content_fetchers.available_fetchers()).get(system_backend, system_backend)) + + +def radio_choices(datastore): + """(value, label) for the Add-Watch browser radio list, system default first. + + 'System settings default' is always listed - with the reason in its own label when + the global default cannot render a preview, because greying it out explains why it + is unavailable where silently dropping it does not. Which entries are unusable is + reported separately by unusable_values(); WTForms cannot carry per-option render_kw + through a RadioField, so the disabled attribute is applied when rendering. + """ + from flask_babel import gettext + + described = system_default_description(datastore) + + if is_visual_capable(SYSTEM_DEFAULT, datastore): + system_label = gettext('System settings default (%(browser)s)', browser=described) + else: + system_label = gettext('System settings default (%(browser)s - no live preview)', browser=described) + + return [(SYSTEM_DEFAULT, system_label)] + list_visual_browser_choices(datastore) + + +def unusable_values(datastore): + """Values that are listed for explanation only and must render disabled.""" + return set() if is_visual_capable(SYSTEM_DEFAULT, datastore) else {SYSTEM_DEFAULT} diff --git a/changedetectionio/blueprint/add_watch_ui/static/add-watch.js b/changedetectionio/blueprint/add_watch_ui/static/add-watch.js index 5f827da9..59c25037 100644 --- a/changedetectionio/blueprint/add_watch_ui/static/add-watch.js +++ b/changedetectionio/blueprint/add_watch_ui/static/add-watch.js @@ -14,6 +14,12 @@ $(document).ready(() => { const $includeFilters = $('#include_filters'); const $temporaryUuid = $('#temporary_uuid'); + // When the LLM intent box isn't available (LLM_FEATURES_DISABLED / not configured) the + // template renders no "Select by element" checkbox - element selection is the only thing + // this page can do, so it is on from the start and can't be turned off. + const selectionAlwaysOn = $byElement.length === 0; + const selectionEnabled = () => selectionAlwaysOn || $byElement.is(':checked'); + const vs = window.initVisualSelector({ $canvas: $('#selector-canvas'), $includeFilters: $includeFilters, @@ -22,7 +28,7 @@ $(document).ready(() => { $fetchingNotice: $('#add-watch-spinner .fetching-update-notice'), $wrapper: $wrapper, $clearButton: $clear, - enableSelection: false, // off until the user opts into "Select by element" + enableSelection: selectionAlwaysOn, // otherwise off until the user opts into "Select by element" processorIsImage: false, // The snapshot comes from the live browser-steps capture, so scale X by the page // CSS width (browser_width) like browser-steps.js - handles device-scale-factor != 1. @@ -36,8 +42,8 @@ $(document).ready(() => { $error.toggle(which === 'error'); const ready = which === 'ready'; $wrapper.toggle(ready); - $xpathRow.toggle(ready && $byElement.is(':checked')); - $clear.toggle(ready && $byElement.is(':checked')); + $xpathRow.toggle(ready && selectionEnabled()); + $clear.toggle(ready && selectionEnabled()); } function fetchSnapshot() { @@ -53,7 +59,9 @@ $(document).ready(() => { $.ajax({ url: add_watch_snapshot_url, - data: {url: url}, + // Preview with the browser picked in the list - that same browser is what + // gets saved on the watch, so what you see here is what it will check with. + data: {url: url, fetch_backend: $('input[name="fetch_backend"]:checked').val() || ''}, dataType: 'json', }).done((data) => { showState('ready'); diff --git a/changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html b/changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html index a8630052..45ebaa62 100644 --- a/changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html +++ b/changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html @@ -54,10 +54,30 @@ {{ render_simple_field(form.processor) }} +
+ {# Rendered by hand rather than with render_field(): the system-default entry + is listed for explanation and has to render disabled, and WTForms can't + carry a per-option disabled attribute through a RadioField's choices. #} + + +
+
+ {%- if llm_configured -%} + {%- endif -%} + {# No LLM intent available? Then narrowing by element is the only thing this + page can do - selection is always on, so nothing is labelled or offered + here, just the hint on how to use the preview. #} {{ _('Hover & click the preview to watch just one part of the page.') }}
diff --git a/changedetectionio/blueprint/ui/views.py b/changedetectionio/blueprint/ui/views.py index 1be4ee1a..a3bfd420 100644 --- a/changedetectionio/blueprint/ui/views.py +++ b/changedetectionio/blueprint/ui/views.py @@ -91,6 +91,13 @@ def construct_blueprint(datastore: ChangeDetectionStore, update_q, queuedWatchMe processor = request.form.get('processor', processors.get_default_processor()) llm_intent = request.form.get('llm_intent', '').strip() extras = {'paused': add_paused, 'processor': processor} + + # Browser picked on the Add Watch page (validated against the live-preview capable + # list by the form). Absent from the watch-list quick-add, which leaves the new + # watch on the system default as before. A snapshot that recorded its own browser + # overrides this inside make_temporary_watch_active_watch(). + if form.fetch_backend.data: + extras['fetch_backend'] = form.fetch_backend.data if llm_intent: extras['llm_intent'] = llm_intent diff --git a/changedetectionio/forms.py b/changedetectionio/forms.py index 80e3c02c..109fe0bf 100644 --- a/changedetectionio/forms.py +++ b/changedetectionio/forms.py @@ -487,6 +487,39 @@ class ValidateContentFetcherIsReady(object): # raise ValidationError(message % (field.data, e)) +class ValidateKnownContentFetcher(object): + """The posted fetch_backend has to name a fetcher this install actually has. + + Deliberately *not* a live-preview capability check. This validator sits on the + shared quick-add form, whose POST endpoint is also how the watch list (and tests, + and scripts) add a watch with any legal backend - 'html_requests' included. Which + browsers the Add-Watch page *offers* is a rendering decision (see the add_watch_ui + blueprint's browser_config), and whether one can render a live preview is enforced + where that matters, in /snapshot. + + Optional: no value posted means "leave it on the system default", as before. + """ + + def __init__(self, message=None): + self.message = message + + def __call__(self, form, field): + from flask import current_app + from changedetectionio import content_fetchers + + if not field.data: + return + + allowed = {'system'} | {name for name, _description in content_fetchers.available_fetchers()} + datastore = current_app.config.get('DATASTORE') + if datastore: + allowed |= {value for value, _label in datastore.extra_browsers} + + if field.data not in allowed: + logger.warning(f"Rejected unknown fetch_backend {field.data!r} - known: {sorted(allowed)}") + raise ValidationError(self.message or gettext("Unknown fetch method.")) + + class ValidateNotificationBodyAndTitleWhenURLisSet(object): """ Validates that they entered something in both notification title+body when the URL is set @@ -784,11 +817,41 @@ class ValidateStartsWithRegex(object): if not self.pattern.match(stripped): raise ValidationError(self.message or _l("Invalid value.")) +def visual_browser_choices(): + """Browsers that can render the Add-Watch live preview, as RadioField choices. + + Lazy import (the add_watch_ui blueprint imports this module) and empty outside an + app context, because WTForms evaluates a choices callable on field construction. + """ + from flask import current_app, has_app_context + from changedetectionio.blueprint.add_watch_ui import browser_config + + if not has_app_context(): + return [] + datastore = current_app.config.get('DATASTORE') + return browser_config.radio_choices(datastore) if datastore else [] + + class quickWatchForm(Form): url = StringField('URL', validators=[validateURL()]) tags = StringTagUUID(_l('Group tag'), validators=[validators.Optional()]) watch_submit_button = SubmitField(_l('Watch'), render_kw={"class": "pure-button pure-button-primary"}) processor = RadioField(_l('Processor'), choices=lambda: processors.available_processors(), default=processors.get_default_processor) + # Only the Add-Watch page renders this; the watch-list quick-add posts nothing, which + # leaves the new watch on 'system' exactly as before. + # + # A radio list rather than a dropdown: fetcher descriptions run long (they include the + # driver URL) and a wrapping label reads fine in a narrow pane, where a that would + // overflow it. The system-default entry is listed even when it can't render a preview. + #quick-watch-fetch-backend { + ul { + margin: 0.35rem 0 0 0; + padding: 0; + list-style: none; + } + + li { + display: flex; + align-items: flex-start; + gap: 0.5em; + padding: 0.15rem 0; + + input[type="radio"] { + flex: 0 0 auto; + margin-top: 0.2em; + } + + label { + // Wrap rather than push the pane wider + display: block; + min-width: 0; + overflow-wrap: anywhere; + font-size: 0.85rem; + line-height: 1.35; + } + } + + li.unusable { + opacity: 0.55; + cursor: not-allowed; + + label { + cursor: not-allowed; + } + } + + .pure-form-message-inline { + display: block; + margin-top: 0.35rem; + font-size: 0.8rem; + opacity: 0.8; + } + } + #by-element-toggle-group { .pure-form-message-inline { display: block; diff --git a/changedetectionio/static/styles/styles.css b/changedetectionio/static/styles/styles.css index d3a61f42..e0c017a5 100644 --- a/changedetectionio/static/styles/styles.css +++ b/changedetectionio/static/styles/styles.css @@ -1 +1 @@ -.header{color:var(--color-text-menu-heading)}.header a{color:var(--color-text-menu-heading)}.header::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;pointer-events:none;background:linear-gradient(to right, rgba(200, 200, 200, 0.02), rgba(200, 200, 200, 0.6))}ul#top-right-menu{list-style:none;margin-left:auto;padding:0;margin-top:0;margin-right:0;margin-bottom:0;display:grid;gap:1.1rem;grid-auto-flow:column;grid-auto-columns:max-content;align-items:center}ul#top-right-menu .toggle-button{padding:0}.current-diff-url{flex:1 1 auto;min-width:0;overflow:hidden;white-space:nowrap;text-align:left;margin:0 .55rem;-webkit-mask-image:linear-gradient(to right, #000 calc(100% - 2.5em), transparent);mask-image:linear-gradient(to right, #000 calc(100% - 2.5em), transparent)}.current-diff-url span{overflow:visible;white-space:nowrap}.pure-menu-horizontal{padding:.55rem;display:flex;justify-content:space-between;align-items:center}.pure-menu-horizontal svg{height:1.3rem}.fi{height:1.3rem;cursor:pointer}#pure-menu-horizontal-spinner{height:2px;background:linear-gradient(-75deg, #ff6000, #ff8f00, #ffdd00, #ed0000);background-size:400% 400%;animation:gradient 200s ease infinite;opacity:.8;position:fixed;bottom:0;left:0;width:100%;z-index:100;pointer-events:none}.status-pill{display:inline-flex;align-items:center;gap:8px;height:30px;padding:0 12px;border-radius:var(--common-round-border);border:1px solid hsla(0,0%,100%,.25);background:hsla(0,0%,100%,.1);color:var(--color-text-menu-heading);font-size:.78rem;font-weight:600;white-space:nowrap;text-decoration:none}.status-pill:hover{background:hsla(0,0%,100%,.18)}.status-pill .live-dot{width:8px;height:8px;border-radius:50%;background:#42dd53;box-shadow:0 0 0 3px rgba(66,221,83,.3);animation:status-pill-pulse 2s infinite}.status-pill.paused .live-dot{background:#e8a33d;box-shadow:0 0 0 3px rgba(232,163,61,.3);animation:none}.status-pill .action-icon{width:16px;height:16px}.status-pill.muted{opacity:.8}.status-pill.muted .action-icon{color:#e8a33d}@keyframes status-pill-pulse{0%,100%{opacity:1}50%{opacity:.4}}.menu-pop-wrap{position:relative}.icon-btn{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border:0;border-radius:var(--common-round-border);background:rgba(0,0,0,0);color:var(--color-text-menu-heading);cursor:pointer}.icon-btn svg{width:18px;height:18px;fill:none;stroke:currentColor}.icon-btn:hover{background:hsla(0,0%,100%,.14)}.menu-pop{display:none;position:absolute;top:calc(100% + 8px);right:0;min-width:220px;padding:6px;border:1px solid var(--color-border-table-cell);border-radius:12px;background:var(--color-background);box-shadow:0 18px 50px rgba(0,0,0,.18);z-index:80}.menu-pop.open{display:block}.menu-pop .mi{display:flex;align-items:center;gap:10px;width:100%;padding:9px 10px;border:0;border-radius:8px;background:rgba(0,0,0,0);color:var(--color-text);font-size:.85rem;text-align:left;text-decoration:none;white-space:nowrap;cursor:pointer}.menu-pop .mi:hover{background:var(--color-background-menu-link-hover)}.menu-pop .mi .ico{display:inline-flex;color:var(--color-text-input-description)}.menu-pop .mi .ico svg{width:16px;height:16px;fill:none;stroke:currentColor}.menu-pop .mi .right{margin-left:auto;font-size:.75rem;color:var(--color-text-input-description)}.top-menu-list .action-label{color:var(--color-text-menu-heading)}@media only screen and (max-width: 768px){.top-menu-list .action-label{display:none}}#inline-menu-extras-group{list-style:none;margin:0;padding:0;display:grid;gap:.55rem;grid-auto-flow:column;grid-auto-columns:max-content;align-items:center}@media only screen and (max-width: 980px){#nav-menu #menu-settings span{display:none}}:root{--body-main-text-size: 0.9rem;--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);--watchlist-row-selected: #e3f0ff;--watchlist-row-hover: #f2f2f2;--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-white);--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-watch-table-error: var(--color-dark-red);--color-watch-table-row-text: var(--color-grey-100);--color-table-line: #e7e9ee;--highlight-trigger-text-bg-color: #1b98f8;--highlight-ignored-text-bg-color: var(--color-grey-700);--highlight-blocked-text-bg-color: rgb(202, 60, 60);--color-sidebar-bg: rgba(255, 255, 255, 0.97);--color-sidebar-text: var(--color-text);--color-sidebar-shadow: 6px 0 28px rgba(0, 0, 0, 0.18);--color-sidebar-item-hover-bg: rgba(0, 0, 0, 0.06);--color-sidebar-item-active-bg: rgba(0, 0, 0, 0.10);--common-round-border: 8px}html[data-darkmode=true]{--color-link: #59bdfb;--color-text: var(--color-white);--color-table-line: #262c37;--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);--watchlist-row-selected: #1e3a5f;--watchlist-row-hover: #2a2a2a;--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-watch-table-error: var(--color-light-red);--color-watch-table-row-text: var(--color-grey-800);--color-sidebar-bg: rgba(8, 10, 14, 0.97);--color-sidebar-text: var(--color-white);--color-sidebar-shadow: 6px 0 28px rgba(0, 0, 0, 0.45);--color-sidebar-item-hover-bg: rgba(255, 255, 255, 0.06);--color-sidebar-item-active-bg: rgba(255, 255, 255, 0.10)}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 svg{opacity:.3}html[data-darkmode=true] .watch-table .watch-controls .state-on svg{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 var(--color-border-input);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}#menu-mute img,#menu-pause img{height:1.2rem}.pure-menu-item{height:initial}.pure-menu-item svg{height:1.2rem}.pure-menu-item *{vertical-align:middle}.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-heading)}.pure-menu-item .action-icon{stroke:var(--color-text-menu-heading)}#overlay{opacity:.95;position:fixed;width:350px;max-width:100%;height:100%;top:50px;right:-350px;background-color:var(--color-table-stripe);border:1px solid #aaa;z-index:2;transform:translateX(0);transition:transform .5s ease}#overlay.visible{transform:translateX(-100%)}#overlay .content{font-size:.875rem;padding:1.1rem;max-width:400px;color:var(--color-watch-table-row-text)}#heartpath{height:1.6rem;width:1.6rem;z-index:100;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)}.cdio-table{width:100%;font-size:var(--body-main-text-size)}.cdio-table thead{text-transform:uppercase}.cdio-table thead a{color:var(--color-text)}.cdio-table td,.cdio-table th{vertical-align:middle;border:none}.cdio-table tbody tr{color:var(--color-watch-table-row-text);border-bottom:1px solid var(--color-table-line);background-color:var(--color-table-background)}.cdio-table tbody tr td{background-color:var(--color-table-background)}.cdio-table tbody tr:hover>td{background-color:var(--watchlist-row-hover)}.cdio-table-clip{border-radius:var(--common-round-border);overflow:hidden;margin-bottom:1.1rem}.seg{display:inline-flex;align-items:center;gap:2px;padding:2px;border:1px solid var(--color-border-table-cell);border-radius:var(--common-round-border);background:var(--color-background-table-thead)}.seg a,.seg button{display:inline-flex;align-items:center;gap:6px;border:0;background:rgba(0,0,0,0);color:var(--color-text-input-description);font-size:.8rem;font-weight:600;line-height:1.4;padding:5px 11px;border-radius:calc(var(--common-round-border) - 1px);text-decoration:none;cursor:pointer;white-space:nowrap}.seg a:hover,.seg button:hover{color:var(--color-text)}.seg a.active,.seg a:hover,.seg button.active,.seg button:hover{background:var(--color-background);color:var(--color-text);box-shadow:0 1px 2px rgba(0,0,0,.15)}html[data-darkmode=true] .seg a.active,html[data-darkmode=true] .seg button.active{background:var(--color-grey-400);box-shadow:0 1px 2px rgba(0,0,0,.5)}.seg-count{font-size:.62rem;line-height:1;font-weight:700;padding:2px 6px;border-radius:999px;background:var(--color-background-button-tag);color:var(--color-white)}.seg-count--unread{background:#3e95bb}.seg-count--error{background:var(--color-background-button-error)}.seg-count--deal{background:var(--color-background-button-success)}.cdio-btn{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 12px;border-radius:var(--common-round-border);border:1px solid var(--color-border-table-cell);background:var(--color-background);color:var(--color-text-input-description);font-family:inherit;font-size:.8rem;font-weight:600;line-height:1;white-space:nowrap;text-decoration:none;cursor:pointer;transition:border-color .12s ease,color .12s ease,background-color .12s ease}.cdio-btn:hover{border-color:var(--color-border-input);color:var(--color-text)}.cdio-btn:focus-visible{outline:2px solid var(--color-link);outline-offset:2px}.cdio-btn svg{width:15px;height:15px;stroke:currentColor}.cdio-btn img{height:15px;display:block}.cdio-btn--icon{width:32px;padding:0;justify-content:center}.cdio-btn--sm{height:26px;padding:0 9px;font-size:.72rem;gap:5px}.cdio-btn--sm svg{width:13px;height:13px}.cdio-btn--primary{background:var(--color-background-button-primary);border-color:var(--color-background-button-primary);color:var(--color-text-button)}.cdio-btn--primary:hover{background:var(--color-link);border-color:var(--color-link);color:var(--color-text-button)}.cdio-btn--danger{color:var(--color-background-button-error)}.cdio-btn--danger:hover{color:var(--color-background-button-error);border-color:var(--color-background-button-error)}.cdio-btn--warning{color:#d68a00}.cdio-btn--warning:hover{color:#d68a00;border-color:#d68a00}.watch-table tr:has(input[name=uuids]:checked)>td{background-color:var(--watchlist-row-selected)}.watch-table tbody tr:hover td.buttons *,.watch-table tbody tr:focus-within td.buttons *,.watch-table tbody tr:has(input[name=uuids]:checked) td.buttons *{opacity:1}.select-all-banner{margin:.4rem 0;padding:.5rem .75rem;border-radius:var(--common-round-border);background:var(--watchlist-row-selected);color:var(--color-watch-table-row-text);font-size:var(--body-main-text-size)}.select-all-banner button{margin-left:.5rem;vertical-align:baseline}.watch-controls svg{width:18px;height:18px;stroke:currentColor;fill:none;vertical-align:middle}#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 .left .records-selected{margin-top:.25rem;opacity:.9}#stats_row .right{opacity:.5;transition:opacity .6s ease;margin-left:auto;text-align:right}body.has-queue #stats_row .right{opacity:1}#checkbox-operations{margin-bottom:.55rem;background:var(--color-background-new-watch-form);padding:1em;border-radius:10px;max-width:100%;position:sticky;top:20px;display:none}#checkbox-operations button{margin-bottom:3px;margin-top:3px;display:inline-flex;align-items:center}#checkbox-operations i,#checkbox-operations svg{width:14px;height:14px;stroke:#fff}body.watch-selection-active #checkbox-operations{display:block}.watch-table .checkbox-uuid{text-align:center}.watch-table .checkbox-uuid>*{vertical-align:middle}@media only screen and (max-width: 1200px){.watch-table .last-checked,.watch-table .last-changed{text-align:center}}.watch-table #th-webpage{text-align:center}.watch-table tbody tr.unviewed{font-weight:bold}.watch-table tbody tr td.inline.title-col{width:100%}.watch-table tbody tr td.inline.title-col .grid-wrapper{display:grid;grid-template-columns:auto minmax(0, 1fr) auto;grid-auto-columns:auto;align-items:center;gap:.55rem}.watch-table tbody tr td.inline.title-col .grid-wrapper>.favicon{grid-column:1}.watch-table tbody tr td.inline.title-col .grid-wrapper>.watch-text-info{grid-column:2}.watch-table tbody tr td.inline.title-col .grid-wrapper>.status-icons{grid-column:3}.watch-table tbody tr td.inline.title-col .grid-wrapper>.restock-info-wrap{grid-column:4}@media only screen and (max-width: 1200px){.watch-table tbody tr td.inline.title-col .grid-wrapper>.restock-info-wrap{grid-column:1/-1;justify-self:center}}.watch-table tbody tr .watch-text-info{line-height:1.5}.watch-table tbody tr.checking-now td:first-child{position:relative}.watch-table tbody tr.checking-now td:first-child::before{content:"";position:absolute;top:0;bottom:0;left:0;width:3px;background-color:#293eff}.watch-table tbody tr.checking-now td.last-checked .spinner-wrapper{display:inline-block !important;white-space:nowrap !important}.watch-table tbody tr.checking-now td.last-checked .spinner{margin-right:.275rem}.watch-table tbody tr.checking-now td.last-checked .innertext{display:none !important}.watch-table tbody tr.queued a.recheck{display:none !important}.watch-table tbody tr.queued a.already-in-queue-button{display:inline-flex !important;opacity:.8}.watch-table tbody tr.paused a.pause-toggle.state-on{display:inline !important}.watch-table tbody tr.paused a.pause-toggle.state-off{display:none !important}.watch-table tbody tr.notification_muted a.mute-toggle.state-on{display:inline !important}.watch-table tbody tr.notification_muted a.mute-toggle.state-off{display:none !important}.watch-table tbody tr.has-error .error-text{display:block !important;color:var(--color-watch-table-error)}.watch-table tbody tr.single-history a.preview-link{display:inherit !important}.watch-table tbody tr.multiple-history a.history-link{display:inherit !important}.watch-table tbody tr.has-favicon.unviewed img.favicon{opacity:1 !important;border-radius:4px}.watch-table td.buttons{font-size:12px;white-space:nowrap}.watch-table td.buttons>div{display:inline-flex;align-items:center;gap:6px}.watch-table td.buttons>div>*{opacity:0;transition:opacity .12s ease}.watch-table td.title-col{word-break:break-all;white-space:normal}.watch-table td a.external::after{content:"";display:inline-block;width:var(--body-main-text-size);height:var(--body-main-text-size);vertical-align:-0.1em;background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23777' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'/%3E%3Cpolyline points='15 3 21 3 21 9'/%3E%3Cline x1='10' y1='14' x2='21' y2='3'/%3E%3C/svg%3E") no-repeat center/contain;margin:0 3px 0 5px}.watch-table td.watch-controls>div{display:flex;justify-content:space-between;align-items:center}@media(min-width: 1020px){.watch-table th{white-space:nowrap}}.watch-table th#h-lastchanged,.watch-table th#h-lastchecked{text-align:center}.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 th#mute-pause{white-space:nowrap}.watch-table th#mute-pause>div{display:flex;justify-content:space-between;align-items:center}.watch-table.favicon-not-enabled tr .favicon{display:none}.watch-table .status-icons{white-space:nowrap;display:flex;align-items:center;gap:4px}.watch-table .status-icons>*{vertical-align:middle}.watch-table .title-wrapper{display:flex;align-items:center;gap:10px}.watch-table .title-col-inner{display:inline-block;vertical-align:middle}.watch-table img.favicon{vertical-align:middle;max-width:36px;max-height:36px;height:36px}.watch-table img.favicon:hover{outline:2px solid color-mix(in srgb, var(--color-watch-table-row-text) 50%, transparent);outline-offset:1px;border-radius:4px}body.watch-selection-active #buttons-for-all-watches{display:none !important}#buttons-for-all-watches{display:flex;align-items:center;justify-content:flex-start;flex-wrap:wrap;gap:.55rem;margin:0}#buttons-for-all-watches #post-list-mark-views{display:none}body.has-any-unviewed #post-list-mark-views{display:inline-flex !important}#watch-table-wrapper{display:inline-block;width:100%}#watch-table-wrapper #list-related-buttons{display:flex;align-items:center;justify-content:flex-start;flex-wrap:wrap;gap:.55rem;margin:0;padding:1.1rem 0 .55rem 0}#watch-table-wrapper.has-error #list-related-buttons #post-list-with-errors{display:inline-flex !important}#watch-table-wrapper.has-unread-changes #list-related-buttons #post-list-unread{display:inline-flex !important}#watch-table-wrapper #tag-lister #tag-all{opacity:1}#watch-table-wrapper #tag-lister.active-tag .button-tag{opacity:.35}#watch-table-wrapper #tag-lister.active-tag .button-tag.active,#watch-table-wrapper #tag-lister.active-tag .button-tag:hover{opacity:1}.content .group-overview-table{width:100%}.content .group-overview-table .pure-button{margin-top:.3rem;margin-bottom:.3rem}.content .group-overview-table .watch-controls,.content .group-overview-table .watch-count{text-align:center}.content .group-overview-table td{padding:5px !important;color:var(--color-watch-table-row-text)}.pure-button{border-radius:var(--common-round-border)}body.blueprint-watchlist #add-watch-ui{margin-bottom:1.1rem;padding:0}body.blueprint-watchlist #add-watch-url-row{margin-bottom:0 !important}body.blueprint-watchlist #quick-watch-llm-intent{margin-top:.55rem}body.blueprint-watchlist #url{width:auto}@media only screen and (min-width: 980px){body.blueprint-watchlist #url{min-width:32rem;max-width:min(80%,80vw);box-sizing:border-box}}body.blueprint-watchlist #quick-watch-llm-intent,body.blueprint-watchlist #quick-watch-processor-type{display:none}body.blueprint-watchlist #new-watch-form:has(#url:not(:placeholder-shown)) #quick-watch-llm-intent,body.blueprint-watchlist #new-watch-form:has(#url:not(:placeholder-shown)) #quick-watch-processor-type{display:block}@media(max-width: 767px){.watch-table thead{display:block}.watch-table thead tr th{display:inline-block}.watch-table thead tr th .hide-on-mobile{display:none}.watch-table thead .empty-cell{display:none}.watch-table .last-checked::before{color:var(--color-text);content:attr(data-label) " "}.watch-table .last-changed::before{color:var(--color-text);content:attr(data-label) " "}.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:40px 1fr 100px;grid-template-rows:auto auto auto auto;gap:.5rem}.watch-table tbody tr .counter-i{display:none}.watch-table tbody tr>td{border-bottom:none}.watch-table tbody tr>td[colspan]{grid-column:1/-1}.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:0 !important}}@media(min-width: 768px){.watch-table thead tr th .hide-on-desktop{display:none}.watch-table td.last-checked .innertext,.watch-table td.last-changed .innertext{white-space:nowrap}}#llm-intent-section textarea{white-space:normal;overflow-wrap:break-word;overflow-x:hidden;overflow-y:auto;resize:vertical;font-family:inherit}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}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%}@media(min-width: 901px){body.blueprint-add_watch_ui #add-watch-ui{width:80%}}#add-watch-ui{padding:0}#add-watch-ui #add-watch-url-row{display:flex;gap:.5rem;align-items:stretch;margin-bottom:1rem}#add-watch-ui #add-watch-url-row>span{flex:1 1 auto;min-width:0}#add-watch-ui #add-watch-url-row>span input{width:100%}#add-watch-ui #add-watch-url-row #add-watch-go{flex:0 0 auto;white-space:nowrap}#add-watch-ui #add-watch-panes{display:flex;gap:.55rem;align-items:stretch}@media(max-width: 900px){#add-watch-ui #add-watch-panes{flex-direction:column}}#add-watch-ui #add-watch-selector-pane{flex:1 1 62%;min-width:0;min-height:380px;position:relative;display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--color-background-tab);border-radius:6px;background:rgba(0,0,0,.15);padding:.75rem}#add-watch-ui #add-watch-selector-pane #add-watch-empty-state,#add-watch-ui #add-watch-selector-pane #add-watch-spinner,#add-watch-ui #add-watch-selector-pane #add-watch-error{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.6rem;text-align:center;padding:2rem 1rem}#add-watch-ui #add-watch-selector-pane #add-watch-empty-state{opacity:.8}#add-watch-ui #add-watch-selector-pane #add-watch-empty-state svg{opacity:.55}#add-watch-ui #add-watch-selector-pane #add-watch-empty-state strong{font-size:1.05rem}#add-watch-ui #add-watch-selector-pane #add-watch-empty-state span{font-size:.85rem;opacity:.8;max-width:32ch}#add-watch-ui #add-watch-selector-pane #add-watch-spinner{gap:1.2rem}#add-watch-ui #add-watch-selector-pane #add-watch-spinner .spinner{font-size:5px}#add-watch-ui #add-watch-selector-pane #add-watch-spinner .fetching-update-notice{font-size:.85rem;opacity:.85}#add-watch-ui #add-watch-selector-pane #add-watch-error{color:#ffb4b4;font-size:.9rem;word-break:break-word}#add-watch-ui #add-watch-selector-pane #selector-wrapper{position:relative;display:block;width:100%;flex:1 1 auto;min-height:0;max-height:none;overflow-y:auto;overflow-x:hidden;text-align:left}#add-watch-ui #add-watch-selector-pane #selector-wrapper>img{position:relative;display:block;max-width:100%;height:auto;z-index:4}#add-watch-ui #add-watch-selector-pane #selector-wrapper>canvas{position:absolute;top:0;left:0;max-width:none;z-index:5}#add-watch-ui #add-watch-options-pane{flex:0 0 34%;min-width:0;display:flex;flex-direction:column;gap:1.1rem}@media(max-width: 900px){#add-watch-ui #add-watch-options-pane{flex:1 1 auto}}#add-watch-ui #add-watch-options-pane .add-watch-option-group label{display:inline-block}#add-watch-ui #add-watch-options-pane #by-element-toggle-group .pure-form-message-inline{display:block;margin-top:.25rem;font-size:.8rem;opacity:.8}#add-watch-ui #add-watch-options-pane #by-element-toggle-group #clear-selector{margin-top:.5rem}#add-watch-ui #add-watch-options-pane #quick-watch-llm-intent label{display:block;margin-bottom:.35rem}#add-watch-ui #add-watch-options-pane #add-watch-submit-row{display:flex;flex-wrap:wrap;gap:.5rem}body.blueprint-add_watch_ui #add-watch-ui{height:90vh;display:flex;flex-direction:column}body.blueprint-add_watch_ui #add-watch-fieldset{flex:1 1 auto;min-height:0;min-width:0;display:flex;flex-direction:column;border:0;margin:0;padding:0}body.blueprint-add_watch_ui #add-watch-legend{margin:0 0 .75rem;font-size:1.1rem;font-weight:600}body.blueprint-add_watch_ui #new-watch-form{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}@media(min-width: 901px){body.blueprint-add_watch_ui #add-watch-panes{flex:1 1 auto;min-height:0}body.blueprint-add_watch_ui #add-watch-selector-pane{min-height:0}}@media(max-width: 900px){body.blueprint-add_watch_ui #add-watch-ui{height:auto}body.blueprint-add_watch_ui #add-watch-panes{flex:0 0 auto}}.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}}.bulk-choice-list{display:flex;flex-direction:column;gap:2px;max-height:50vh;overflow-y:auto;text-align:left}.bulk-choice-list .bulk-choice-row{display:block;padding:6px 8px;cursor:pointer;border-radius:4px}.bulk-choice-list .bulk-choice-row input[type=radio]{margin-right:8px}.bulk-choice-list .bulk-choice-row:hover{background:rgba(127,127,127,.15)}.bulk-choice-list .bulk-choice-row em{opacity:.7;font-size:.9em}#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}.action-sidebar{display:flex;flex-direction:column;align-items:center;align-self:flex-start;position:sticky;top:0;height:100vh;background:hsla(0,0%,100%,.05);z-index:60;pointer-events:none}@media only screen and (max-width: 980px){.action-sidebar{display:none}}.action-sidebar-inner{pointer-events:auto;width:64px;overflow:hidden;flex:1 1 auto;display:flex;flex-direction:column;transition:width .08s ease-out;padding-left:.55rem;padding-right:.55rem}body.actionsidebar-minimal .action-sidebar-inner:hover,body.actionsidebar-minimal .action-sidebar-inner:focus-within{width:200px;transition:width .22s cubic-bezier(0.2, 0.7, 0.2, 1)}body.actionside-bar-on .action-sidebar-inner{width:200px;transition:none}ul.action-sidebar-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:0}.action-sidebar-list.action-sidebar-list--bottom{margin-top:auto}.action-sidebar-li{list-style:none;margin:0;position:relative;color:var(--color-white)}.action-sidebar-li:nth-child(2){padding-top:2rem}.action-sidebar-li button{padding:0;margin:0}.action-sidebar-li a{color:var(--color-white)}.action-sidebar-li--spark .queue-spark{display:block;width:100%;height:15px;box-sizing:border-box;padding:0;margin:0;border-radius:3px;background:hsla(0,0%,100%,.05);box-shadow:inset 0 0 0 1px hsla(0,0%,100%,.06)}.action-sidebar-divider{height:1px;background:hsla(0,0%,100%,.18);margin:6px 16px;list-style:none}.action-sidebar .action-sidebar-item{position:relative;display:flex;align-items:center;padding:.55rem;font-size:var(--body-main-text-size);border-radius:var(--common-round-border);color:var(--color-white);text-decoration:none;white-space:nowrap;background:rgba(0,0,0,0);border:0;text-align:left;cursor:pointer;transition:background-color .12s ease,color .12s ease}.action-sidebar .action-sidebar-item:hover{background-color:var(--color-sidebar-item-hover-bg)}.action-sidebar .action-sidebar-item:hover .action-icon{stroke-width:2.3}.action-sidebar .action-sidebar-item:focus-visible{outline:2px solid var(--color-link);outline-offset:2px}.action-sidebar .action-sidebar-item.active .action-icon{stroke-width:2.4;filter:drop-shadow(0 0 0.4px currentColor)}.action-sidebar .action-sidebar-item.active .action-label{font-weight:700}.action-sidebar .action-sidebar-item.is-disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.action-sidebar .action-sidebar-item.action-sidebar-item--accent .action-icon{stroke:#fff;stroke-width:2.6}.action-sidebar .action-sidebar-item .action-label{flex:0 0 auto;margin-left:14px;font-family:inherit;font-weight:400;letter-spacing:0;text-transform:none;color:inherit;opacity:0;transform:translateX(-4px);transition:opacity .05s ease-out,transform .05s ease-out}.action-sidebar .action-sidebar-item .action-badge{margin-left:10px;font-size:.7rem;line-height:1;padding:3px 7px;border-radius:999px;background:hsla(0,0%,100%,.14);color:hsla(0,0%,100%,.85);text-transform:uppercase;letter-spacing:.06em;font-weight:700;pointer-events:none;opacity:0;transition:opacity .05s ease-out}.action-sidebar .action-sidebar-item .action-badge.action-badge--count{margin-left:auto;text-transform:none;letter-spacing:0;background:#3e95bb;color:var(--color-white);font-variant-numeric:tabular-nums}body.actionsidebar-minimal .action-sidebar-inner:hover .action-sidebar-item .action-label,body.actionsidebar-minimal .action-sidebar-inner:focus-within .action-sidebar-item .action-label{opacity:1;transform:translateX(0);transition:opacity .18s ease .05s,transform .18s cubic-bezier(0.2, 0.7, 0.2, 1) .05s}body.actionsidebar-minimal .action-sidebar-inner:hover .action-sidebar-item .action-badge,body.actionsidebar-minimal .action-sidebar-inner:focus-within .action-sidebar-item .action-badge{opacity:1;transition:opacity .18s ease .05s}body.actionside-bar-on .action-sidebar .action-sidebar-item .action-label{opacity:1;transform:translateX(0);transition:none}body.actionside-bar-on .action-sidebar .action-sidebar-item .action-badge{opacity:1;transition:none}.action-icon{flex:0 0 auto;width:24px;height:24px;stroke:currentColor;stroke-width:1.9;fill:none;stroke-linecap:round;stroke-linejoin:round}.action-badge{flex:0 0 auto;font-size:.62rem;text-transform:uppercase;letter-spacing:.08em;padding:2px 6px;border-radius:999px;background:hsla(0,0%,100%,.15);color:hsla(0,0%,100%,.85);font-weight:700}.mobile-menu-section{padding:.5rem .75rem;border-bottom:1px solid var(--color-border-table-cell)}.mobile-menu-section ul.action-sidebar-list{gap:1px}.mobile-menu-section ul.action-sidebar-list .action-sidebar-li a,.mobile-menu-section ul.action-sidebar-list .action-sidebar-li button{padding:.55rem}.mobile-menu-section .action-sidebar-item{position:relative;display:flex;align-items:center;justify-content:flex-start;gap:.55rem;padding:.55rem .55rem;border-radius:var(--common-round-border);color:var(--color-text)}.mobile-menu-section .action-sidebar-item:hover{background-color:var(--color-background-menu-link-hover);color:var(--color-text)}.mobile-menu-section .action-sidebar-item.active{background-color:var(--color-background-menu-link-hover);color:var(--color-text)}.mobile-menu-section .action-sidebar-item .action-label{position:static;transform:none;background:rgba(0,0,0,0);box-shadow:none;color:inherit;opacity:1;pointer-events:auto;padding:0;font-weight:500}.mobile-menu-section .action-sidebar-item .action-label::before{display:none}.mobile-menu-section .action-sidebar-item .action-badge{position:static;margin-left:auto;font-size:.62rem;background:rgba(0,0,0,.08);color:var(--color-text)}.mobile-menu-section .action-sidebar-item.action-sidebar-item--accent{background:var(--color-background-menu-link-hover);box-shadow:inset 0 0 0 1px var(--color-border-table-cell);color:var(--color-text)}.mobile-menu-section .action-sidebar-item.action-sidebar-item--accent .action-label{color:inherit}.mobile-menu-section .action-sidebar-item--button{background:rgba(0,0,0,0);border:none;cursor:pointer;text-align:left;font:inherit}#add-watch-live-info{width:100%;margin-top:1rem}#add-watch-live-info .add-watch-live-placeholder{border:1px dashed hsla(0,0%,100%,.25);background:hsla(0,0%,100%,.04);border-radius:10px;padding:1.25rem;color:var(--color-white)}#add-watch-live-info .add-watch-live-placeholder h3{margin:0 0 .4rem 0;font-size:1rem;letter-spacing:.02em}#add-watch-live-info .add-watch-live-placeholder .muted{opacity:.7;margin:0 0 .75rem 0;font-size:.85rem}#add-watch-live-info .add-watch-live-placeholder .add-watch-live-stream{font-size:.85rem;opacity:.6;padding:.6rem 0}.mobile-menu-drawer .action-sidebar-list{padding:0}.mobile-menu-drawer .mobile-menu-section .action-sidebar-item{padding-left:0}#action-sidebar-logo{padding-top:1.1rem;padding-left:.55rem}.actionsidebar-minimal #checking-now-stats-sidebar{display:none}.actionsidebar-minimal #cdio-logo #logo-expanded{display:none}.actionsidebar-minimal.action-side-bar-expanded #checking-now-stats-sidebar{display:block}.actionsidebar-minimal.action-side-bar-expanded #cdio-logo #logo-expanded{display:inline-block}.action-side-bar-expanded #cdio-logo #logo-short{display:none}#queue-page{width:100%;color:var(--color-white)}#queue-page h2,#queue-page h3{color:var(--color-white)}#queue-page .queue-panel{background:var(--color-background-new-watch-form);padding:1em;border-radius:10px;margin-bottom:1em;width:100%;box-sizing:border-box;color:var(--color-white)}#queue-page .queue-stats{display:grid;grid-template-columns:repeat(auto-fit, minmax(160px, 1fr));gap:.75rem}#queue-page .queue-stat .label{font-size:.7rem;text-transform:uppercase;letter-spacing:.06em;opacity:.7}#queue-page .queue-stat .value{font-size:1.6rem;font-weight:700;color:var(--color-white)}#queue-page .queue-stat.queue-stat--action{display:flex;align-items:center;justify-content:flex-start}#queue-page .queue-stat.queue-stat--action .pure-button{white-space:nowrap}#queue-page table.pure-table{width:100%;background:rgba(0,0,0,0);color:var(--color-white);font-size:80%}#queue-page table.pure-table thead th{background:rgba(0,0,0,0);color:var(--color-white);border-bottom:1px solid hsla(0,0%,100%,.18);font-weight:700;white-space:nowrap}#queue-page table.pure-table td{color:var(--color-white);border-color:hsla(0,0%,100%,.08);white-space:nowrap}#queue-page table.pure-table td.title-col,#queue-page table.pure-table td.watch-cell{white-space:normal;word-break:break-all}#queue-page table.pure-table td.time-cell{font-variant-numeric:tabular-nums;color:hsla(0,0%,100%,.75);font-size:.95em}#queue-page table.pure-table code,#queue-page table.pure-table small,#queue-page table.pure-table em,#queue-page table.pure-table strong{color:var(--color-white)}#queue-page table.pure-table code{background:rgba(0,0,0,.18)}#queue-page table.pure-table small{opacity:.7}#queue-page table.pure-table-striped tr:nth-child(2n-1) td{background:hsla(0,0%,100%,.04)}#queue-page tr.is-completed td{opacity:.45;transition:opacity .4s ease}#queue-page tbody[data-section=workers]{border-bottom:1px solid hsla(0,0%,100%,.18)}#queue-page tr.worker-slot td{border-color:hsla(0,0%,100%,.05)}#queue-page tr.worker-idle td{background:hsla(0,0%,100%,.02)}#queue-page .inline-tag,#queue-page .processor-badge,#queue-page .watch-tag-list,#queue-page .tracking-ldjson-price-data,#queue-page .restock-label{background:hsla(0,0%,100%,.14);color:var(--color-white)}#queue-page .inline-tag--running{background:rgba(28,184,65,.45)}#queue-page .inline-tag--idle{background:hsla(0,0%,100%,.08);color:hsla(0,0%,100%,.6)}#queue-page .inline-tag--done{background:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.7)}#queue-page a.queue-cancel{display:inline-block;margin-left:8px;font-size:.75rem;color:hsla(0,0%,100%,.65);text-decoration:underline;text-decoration-style:dotted;text-underline-offset:2px}#queue-page a.queue-cancel:hover{color:var(--color-white);text-decoration-style:solid}#queue-page a.queue-cancel.is-busy{pointer-events:none;opacity:.5}#queue-page tr.is-new td{animation:queue-row-in .45s ease}@keyframes queue-row-in{from{background-color:rgba(28,184,65,.18)}to{background-color:rgba(0,0,0,0)}}#queue-page .queue-waiting{display:none;align-items:center;gap:.5rem;margin-top:1rem;padding:.5rem 0;color:hsla(0,0%,100%,.7);font-size:.85rem}#queue-page .queue-waiting[data-show=true]{display:flex}#queue-page .queue-waiting .spinner{margin:0;flex:0 0 auto;border-top-color:hsla(0,0%,100%,.18);border-right-color:hsla(0,0%,100%,.18);border-bottom-color:hsla(0,0%,100%,.18);border-left-color:var(--color-white)}.hamburger-menu{display:none;background:rgba(0,0,0,0);border:none;cursor:pointer;padding:.55rem;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-white);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{background-color:var(--color-text)}.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 #cdio-logo{color:var(--color-text)}.mobile-menu-drawer #cdio-logo #logo-short{display:none}.mobile-menu-drawer #cdio-logo #logo-expanded{display:inline-block}.mobile-menu-drawer .action-icon{stroke:var(--color-text)}.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)}.mobile-menu-drawer .mobile-menu-items li#menu-pause,.mobile-menu-drawer .mobile-menu-items li#menu-mute{display:none}.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)}#llm-diff-summary-area{margin:.6rem 0 .4rem;padding:.65rem .9rem;background:linear-gradient(135deg, rgba(120, 80, 200, 0.18), rgba(80, 160, 220, 0.14));border-left:3px solid rgba(140,90,220,.8);border-radius:0 4px 4px 0;min-width:0;max-width:100%;box-sizing:border-box;overflow:hidden}#llm-diff-summary-area .llm-diff-summary-label{display:block;font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;opacity:.55;margin-bottom:.25rem}#llm-diff-summary-area .llm-diff-summary-text{margin:0;font-size:.9rem;line-height:1.5;white-space:pre-wrap;overflow-wrap:break-word;word-break:break-word}.llm-diff-summary-prompt{margin:.4em 0 0;font-size:.78rem;font-style:italic;overflow:hidden;max-height:3.8em;animation:llm-prompt-reveal .7s ease-out both}.llm-diff-summary-prompt .llm-diff-summary-prompt-text{display:block;opacity:.55;mask-image:linear-gradient(to bottom, rgba(0, 0, 0, 0.85) 30%, rgba(0, 0, 0, 0) 100%);-webkit-mask-image:linear-gradient(to bottom, rgba(0, 0, 0, 0.85) 30%, rgba(0, 0, 0, 0) 100%);white-space:pre-wrap;overflow-wrap:break-word;line-height:1.45}@keyframes llm-prompt-reveal{from{opacity:0;transform:translateY(-3px)}to{opacity:1;transform:translateY(0)}}.llm-diff-summary-loading{opacity:.5;font-style:italic;animation:llm-pulse 1.4s ease-in-out infinite;font-weight:bold}@keyframes llm-pulse{0%,100%{opacity:.5}50%{opacity:.2}}.llm-budget-exceeded,.llm-error{color:#c0392b;font-weight:600;font-style:normal;opacity:1}.toggle-ai-mode{opacity:.4;transition:opacity .2s ease,filter .2s ease;display:inline-flex;align-items:center;color:var(--color-text-menu-link)}.toggle-ai-mode svg{height:1.2rem;width:1.2rem}.toggle-ai-mode .ai-mode-label{font-size:.75rem;font-weight:600;letter-spacing:.04em;line-height:1}html[data-ai-mode=true] .toggle-ai-mode{opacity:1;filter:drop-shadow(0 0 4px rgba(160, 100, 255, 0.7))}.btn-label-summary{display:none}html[data-ai-mode=true] body.llm-configured .btn-label-history{display:none}html[data-ai-mode=true] body.llm-configured .btn-label-summary{display:inline}.ai-inline-summary-row td{white-space:normal !important;word-break:break-word;padding:.5rem 1rem .6rem 1.4rem !important;background:linear-gradient(135deg, #f0ebff, #eaf0ff) !important;border-top:1px solid #c4b5fd !important;border-left:3px solid #8b5cf6 !important;color:#1a0640 !important;line-height:1.5}html[data-darkmode=true] .ai-inline-summary-row td{background:linear-gradient(135deg, #1c0d35, #0d1535) !important;border-top:1px solid #3b1f6e !important;border-left-color:#8b5cf6 !important;color:#e9d5ff !important}.ai-inline-summary-row .ai-inline-summary-content{display:flex;gap:.5rem;align-items:flex-start}.ai-inline-summary-row .ai-inline-summary-content .ai-inline-spinner{flex-shrink:0;animation:llm-pulse 1.4s ease-in-out infinite}.ai-inline-summary-row .ai-inline-summary-content .ai-inline-body{display:flex;flex-direction:column;min-width:0}.ai-inline-summary-row .ai-inline-summary-content .ai-inline-text{font-style:italic;opacity:.75;white-space:pre-wrap}.ai-inline-summary-row .ai-inline-summary-content.loaded .ai-inline-spinner{animation:none}.ai-inline-summary-row .ai-inline-summary-content.loaded .ai-inline-text{font-style:normal;opacity:1}.ai-inline-summary-row .ai-inline-history-link{display:inline-block;margin-top:.4rem;font-size:.78rem;font-weight:700;opacity:.7;white-space:nowrap}.ai-inline-summary-row .ai-inline-history-link:hover{opacity:1}.ai-inline-summary-row .ai-inline-error{color:#c0392b}.ai-inline-summary-row .ai-inline-prompt{display:block;margin-top:.3em;font-size:.75rem;font-style:italic;overflow:hidden;max-height:3.6em;animation:llm-prompt-reveal .6s ease-out both;mask-image:linear-gradient(to bottom, rgba(0, 0, 0, 0.7) 30%, rgba(0, 0, 0, 0) 100%);-webkit-mask-image:linear-gradient(to bottom, rgba(0, 0, 0, 0.7) 30%, rgba(0, 0, 0, 0) 100%);opacity:.55;line-height:1.4;white-space:pre-wrap;overflow-wrap:break-word}.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)}.notification-add-buttons{margin-bottom:.5rem;display:flex;align-items:center;flex-wrap:wrap;gap:.4rem}.notification-add-buttons .add-destination-inline{display:inline-flex;align-items:center;gap:.3rem}.notification-add-buttons .add-destination-inline input[type=email]{margin:0;min-width:16rem}#notification-add-email-preset{padding-top:.55rem;padding-bottom:.55rem}#notification-recipients{padding-bottom:.55rem}.notification-recipients{display:flex;flex-wrap:wrap;gap:.4rem;margin-bottom:.5rem}.notification-recipients .notification-chip{display:inline-flex;align-items:center;gap:.35rem;padding:.2rem .5rem;line-height:1.4;border:1px solid var(--color-border-notification);border-radius:var(--common-round-border);max-width:100%}.notification-recipients .notification-chip .notification-chip-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:22rem}.notification-recipients .notification-chip .notification-chip-remove{cursor:pointer;font-weight:bold;opacity:.55;text-decoration:none}.notification-recipients .notification-chip .notification-chip-remove:hover{opacity:1}.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}#notification-error-log{border:1px solid var(--color-border-notification);padding:1rem;border-radius:5px;overflow-wrap:break-word}#restock-diff{width:100%;box-sizing:border-box}#restock-diff-summary{margin-top:.6rem;display:flex;align-items:center;gap:.6rem;flex-wrap:wrap}.restock-latest-price{font-size:1.4rem;font-weight:700}.restock-badge{display:inline-block;padding:.15rem .55rem;border-radius:1rem;font-size:.8rem;font-weight:600;white-space:nowrap}.restock-badge.in-stock{background:rgba(31,164,99,.15);color:#1fa463}.restock-badge.out-of-stock{background:rgba(231,76,60,.15);color:#e74c3c}#restock-tabs{background:var(--color-background);color:var(--color-text);padding:1rem;border-radius:5px}#restock-tabs .tab-pane-inner#screenshot{text-align:center}#restock-tabs .tab-pane-inner#screenshot img{max-width:99%}#restock-graph{margin-top:1rem;box-sizing:border-box}@media(min-width: 1200px){#restock-graph{max-width:80%;margin-left:auto;margin-right:auto}}.js-restock-graph{position:relative;width:100%}.js-restock-graph svg{display:block;max-width:100%}.js-restock-graph .rg-axis{stroke:var(--color-border-notification, rgba(127, 127, 127, 0.4));stroke-width:1}.js-restock-graph .rg-label{fill:currentColor;opacity:.7;font-size:12px}.js-restock-graph .rg-line{stroke:currentColor;opacity:.55}.js-restock-graph .rg-dot{stroke:var(--color-background, #fff);stroke-width:1.5}.js-restock-graph .rg-legend{display:flex;justify-content:center;gap:1.1rem;margin-top:.4rem;font-size:.78rem;opacity:.85}.js-restock-graph .rg-legend .rg-legend-item{display:inline-flex;align-items:center;gap:.35rem}.js-restock-graph .rg-legend .rg-legend-dot{width:9px;height:9px;border-radius:50%;display:inline-block}.js-restock-graph .rg-legend .rg-legend-dot.in{background:#1fa463}.js-restock-graph .rg-legend .rg-legend-dot.out{background:#e74c3c}.js-restock-graph .rg-header{display:flex;align-items:center;justify-content:space-between;gap:.5rem;flex-wrap:wrap;margin-bottom:.5rem}.js-restock-graph .rg-stats{font-size:.8rem;opacity:.7;text-align:right;margin-left:auto}.js-restock-graph .rg-band{fill:rgba(120,130,150,.14)}.js-restock-graph .rg-avg-line{stroke:var(--color-text, #555);opacity:.45;stroke-width:1}.js-restock-graph .rg-avg-text{opacity:.5}.rg-status{display:inline-flex;align-items:baseline;gap:.4rem;padding:.2rem .6rem;border-radius:1rem;font-size:.85rem}.rg-status .rg-status-label{font-weight:700}.rg-status .rg-status-sub{font-size:.78rem;opacity:.8}.rg-status.rg-status-low{background:rgba(31,164,99,.16);color:#1fa463}.rg-status.rg-status-typical{background:rgba(120,130,150,.16);color:var(--color-text, #555)}.rg-status.rg-status-high{background:rgba(231,76,60,.16);color:#e74c3c}.rg-tooltip{position:absolute;display:none;pointer-events:none;z-index:5;transform:translateY(-50%);white-space:nowrap;background:var(--color-background, #fff);color:var(--color-text, #222);border:1px solid var(--color-border-notification, rgba(127, 127, 127, 0.4));border-radius:5px;padding:4px 8px;font-size:12px;line-height:1.4;box-shadow:0 2px 6px rgba(0,0,0,.15)}#restock-history-table{margin-left:auto;margin-right:auto}#restock-history-table td,#restock-history-table th{text-align:left}.restock-table-toolbar{display:flex;align-items:center;justify-content:center;gap:.75rem;margin-bottom:.5rem}html[data-ai-mode=true] body.llm-configured tr.processor-restock_diff .btn-label-history{display:inline}html[data-ai-mode=true] body.llm-configured tr.processor-restock_diff .btn-label-summary{display:none}.restock-inline-row td{white-space:normal !important;word-break:break-word;padding:.6rem 1rem .8rem 1.4rem !important;background:linear-gradient(135deg, #e6fbf0, #e8f6ff) !important;border-top:1px solid #9fe3c2 !important;border-left:3px solid #1fa463 !important;color:#06281a !important;line-height:1.5}html[data-darkmode=true] .restock-inline-row td{background:linear-gradient(135deg, #0c2a1c, #0d2230) !important;border-top:1px solid #1f5e40 !important;border-left-color:#1fa463 !important;color:#d6ffe9 !important}.restock-inline-row .restock-inline-graph{width:100%;min-height:40px}.restock-inline-row .restock-inline-history-link{display:inline-block;margin-top:.5rem;font-size:.78rem;font-weight:700;opacity:.75;white-space:nowrap}.restock-inline-row .restock-inline-history-link:hover{opacity:1}.restock-inline-row .restock-inline-error{color:#c0392b}.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:50% !important;right:auto !important;top:80px !important;transform:translateX(-50%) !important;align-items:center}.toast-container.toast-bottom-right,.toast-container.toast-bottom-center,.toast-container.toast-bottom-left{top:auto !important;bottom:80px !important}.toast{min-width:auto;max-width:none;width:80vw;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)}.stab-shell{display:flex;align-items:stretch;background:var(--color-background);border:1px solid rgba(0,0,0,.08);border-radius:8px;overflow:hidden;box-shadow:0 2px 8px rgba(0,0,0,.05);margin-bottom:1.5rem}.stab-nav{display:flex;flex-direction:column;width:11rem;flex-shrink:0;padding:.75rem 0;gap:1px;background:linear-gradient(180deg, rgba(0, 0, 0, 0.03) 0%, rgba(0, 0, 0, 0.05) 100%);border-right:1px solid rgba(0,0,0,.07)}.stab-btn{position:relative;display:flex;align-items:center;gap:.5rem;padding:.65rem .9rem .65rem 1rem;width:100%;background:none;border:none;border-left:3px solid rgba(0,0,0,0);border-radius:0;cursor:pointer;font:inherit;color:var(--color-text);text-align:left;opacity:.65;transition:background .12s ease,opacity .12s ease,border-color .12s ease,color .12s ease}.stab-btn:hover{background:rgba(0,0,0,.04);opacity:.85}.stab-btn.active{border-left-color:var(--color-menu-accent);background:rgba(237,89,0,.07);color:var(--color-menu-accent);font-weight:700;opacity:1}.stab-btn .stab-icon{display:inline-flex;align-items:center;justify-content:center;width:1.1rem;flex-shrink:0;opacity:.8}.stab-btn .stab-icon svg{width:.95rem;height:.95rem;stroke:currentColor;fill:none}.stab-body{flex:1;min-width:0;padding:1.4rem 1.6rem;overflow-x:hidden}.stab-pane{visibility:hidden;height:0;overflow:hidden}.stab-pane.active{visibility:visible;height:auto;overflow:visible;animation:stab-enter .16s ease both}@keyframes stab-enter{from{opacity:0;transform:translateY(5px)}to{opacity:1;transform:translateY(0)}}.stab-overview-hero{margin-bottom:1.5rem}.stab-overview-hero h3{margin:0 0 .3rem;font-size:1.05rem}.stab-overview-hero .stab-overview-glyph{color:var(--color-menu-accent);margin-right:.2rem}.stab-overview-hero .stab-overview-glyph svg{width:1.1rem;height:1.1rem;stroke:currentColor;fill:none;vertical-align:-0.15em}.stab-overview-hero p{margin:0;font-size:.88rem;color:var(--color-text-input-description);max-width:44rem;line-height:1.55}.stab-overview-features{display:flex;flex-direction:column;gap:.7rem;margin-bottom:1.6rem}.stab-overview-feature{display:flex;gap:.85rem;align-items:flex-start;padding:.75rem 1rem;border-radius:6px;background:rgba(0,0,0,.022);border:1px solid rgba(0,0,0,.05);transition:background .12s ease}.stab-overview-feature:hover{background:rgba(0,0,0,.035)}.stab-overview-feature .stab-overview-icon{width:1.6rem;flex-shrink:0;padding-top:.05rem;opacity:.7;display:flex;justify-content:center}.stab-overview-feature .stab-overview-icon svg{width:1.3rem;height:1.3rem;stroke:currentColor;fill:none}.stab-overview-feature .stab-overview-text>strong{display:block;margin-bottom:.2rem}.stab-overview-feature .stab-overview-text p{color:var(--color-text-input-description)}.stab-overview-disclaimer{display:flex;gap:.75rem;align-items:flex-start;margin:0 0 1.1rem;padding:.85rem 1rem;border-radius:6px;border:1px solid rgba(211,136,0,.35);background:rgba(255,180,0,.07)}.stab-overview-disclaimer .stab-disclaimer-icon{flex-shrink:0;padding-top:.05rem;color:#c07800}.stab-overview-disclaimer .stab-disclaimer-icon svg{width:1.2rem;height:1.2rem;stroke:currentColor;fill:none}.stab-overview-disclaimer .stab-disclaimer-body{font-size:.85rem;line-height:1.55}.stab-overview-disclaimer .stab-disclaimer-body>strong{display:block;margin-bottom:.35rem;color:#8a5500;font-size:.87rem}.stab-overview-disclaimer .stab-disclaimer-body p{margin:0 0 .45rem;color:var(--color-text-input-description)}.stab-overview-disclaimer .stab-disclaimer-body ul{margin:0 0 .6rem;padding-left:1.25rem;color:var(--color-text-input-description)}.stab-overview-disclaimer .stab-disclaimer-body ul li{margin-bottom:.2rem}.stab-overview-disclaimer .stab-disclaimer-check{display:flex;gap:.5rem;align-items:flex-start;cursor:pointer;font-size:.82rem;color:var(--color-text-input-description);font-weight:600}.stab-overview-disclaimer .stab-disclaimer-check input[type=checkbox]{flex-shrink:0;margin-top:.18rem;cursor:pointer}.stab-overview-cta{margin-top:.4rem;display:flex;align-items:center;gap:.8rem;flex-wrap:wrap}.stab-configured-badge{display:inline-flex;align-items:center;gap:.4rem;padding:.35rem .75rem;background:rgba(39,174,96,.09);border:1px solid rgba(39,174,96,.28);border-radius:4px;color:#2a7a4e;font-size:.82rem;font-weight:600}.stab-section-title{font-size:.72rem;font-weight:700;letter-spacing:.07em;text-transform:uppercase;opacity:.45;margin:1.4rem 0 .6rem}.stab-section-title:first-child{margin-top:0}@media(max-width: 600px){.stab-shell{flex-direction:column;min-height:unset}.stab-nav{width:100%;border-right:none;border-bottom:1px solid rgba(0,0,0,.07);padding:.4rem 0}.stab-body{padding-left:1rem}}.llm-usage-grid{display:grid;grid-template-columns:repeat(auto-fit, minmax(12rem, 1fr));gap:.9rem;margin-bottom:1.4rem}.llm-stat-card{padding:1rem 1.1rem .85rem;border-radius:7px;background:rgba(0,0,0,.025);border:1px solid rgba(0,0,0,.07)}.llm-stat-card .llm-stat-label{font-size:.7rem;font-weight:700;letter-spacing:.07em;text-transform:uppercase;opacity:.4;margin-bottom:.4rem}.llm-stat-card .llm-stat-value{font-size:1.65rem;font-weight:700;letter-spacing:-0.02em;line-height:1;margin-bottom:.25rem}.llm-stat-card .llm-stat-sub{font-size:.79rem;opacity:.5}.llm-stat-card .llm-stat-budget-text{font-size:.77rem;opacity:.55;margin-top:.3rem}.llm-stat-bar-wrap{height:4px;border-radius:2px;background:rgba(0,0,0,.1);overflow:hidden;margin-top:.65rem}.llm-stat-bar-fill{height:100%;border-radius:2px;transition:width .5s ease}.llm-stat-bar-fill.bar-ok{background:#27ae60}.llm-stat-bar-fill.bar-warn{background:#e67e22}.llm-stat-bar-fill.bar-over{background:#c0392b}.llm-usage-settings{border-top:1px solid rgba(0,0,0,.07);padding-top:.9rem;display:flex;flex-direction:column;gap:.65rem}.llm-usage-row{display:flex;align-items:baseline;gap:.9rem;flex-wrap:wrap}.llm-usage-row .llm-usage-row-label{font-size:.82rem;font-weight:600;opacity:.6;min-width:12rem;flex-shrink:0}.llm-usage-row .llm-usage-row-value{display:flex;align-items:baseline;gap:.5rem;flex-wrap:wrap;font-size:.88rem}.llm-field-hint{font-size:.8rem;opacity:.55}.llm-env-badge{font-size:.79rem;opacity:.6}.llm-budget-alert{color:#c0392b;font-weight:600;font-size:.88rem;margin:0 0 1rem}.llm-no-usage{opacity:.5;font-style:italic;font-size:.88rem;margin-bottom:1rem}html[data-darkmode=true] .stab-shell{border-color:hsla(0,0%,100%,.07);box-shadow:0 2px 8px rgba(0,0,0,.25)}html[data-darkmode=true] .stab-nav{background:linear-gradient(180deg, rgba(255, 255, 255, 0.025) 0%, rgba(255, 255, 255, 0.04) 100%);border-right-color:hsla(0,0%,100%,.07)}html[data-darkmode=true] .stab-btn:hover{background:hsla(0,0%,100%,.05)}html[data-darkmode=true] .stab-btn.active{background:rgba(237,89,0,.12)}html[data-darkmode=true] .stab-overview-feature{background:hsla(0,0%,100%,.025);border-color:hsla(0,0%,100%,.05)}html[data-darkmode=true] .stab-overview-feature:hover{background:hsla(0,0%,100%,.04)}html[data-darkmode=true] .stab-configured-badge{background:rgba(39,174,96,.1);border-color:rgba(39,174,96,.22);color:#5db880}html[data-darkmode=true] .stab-overview-disclaimer{border-color:rgba(255,190,50,.22);background:rgba(255,180,0,.05)}html[data-darkmode=true] .stab-overview-disclaimer .stab-disclaimer-icon{color:#c9963a}html[data-darkmode=true] .stab-overview-disclaimer .stab-disclaimer-body>strong{color:#c9a050}html[data-darkmode=true] .llm-stat-card{background:hsla(0,0%,100%,.03);border-color:hsla(0,0%,100%,.07)}html[data-darkmode=true] .llm-stat-bar-wrap{background:hsla(0,0%,100%,.1)}html[data-darkmode=true] .llm-usage-settings{border-top-color:hsla(0,0%,100%,.07)}body,.pure-table,.pure-table thead,.pure-table td,.pure-table th,.pure-form input,.pure-form textarea,.pure-form select,.edit-form .inner,.pure-menu-horizontal,footer,.sticky-tab,#diff-jump,.button-tag,#new-watch-form,#new-watch-form input:not(.pure-button),code,.messages li,#checkbox-operations,.inline-warning,a,.watch-controls img{transition:color .4s ease,background-color .4s ease,background .4s ease,border-color .4s ease,box-shadow .4s ease}body{color:var(--color-text);background:var(--color-background-page);font-family:Helvetica Neue,Helvetica,Lucida Grande,Arial,Ubuntu,Cantarell,Fira Sans,sans-serif}.app{display:flex;align-items:stretch;min-height:100vh}.app-main{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:.55rem}.content-wrapper{display:flex;width:100%;max-width:100%;position:relative;align-items:flex-start}@media only screen and (max-width: 980px){.content-wrapper{flex-direction:column}}.content-main{flex:1 1 auto;width:100%;min-width:0;display:flex;flex-direction:column;align-items:center}@media only screen and (min-width: 980px){.content-main{flex-direction:column}}.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}a{text-decoration:none;color:var(--color-link)}#search-result-info{color:#fff}button.toggle-button{vertical-align:middle;background:rgba(0,0,0,0);border:none;cursor:pointer;color:var(--color-text-menu-heading)}button.toggle-button svg{fill:currentColor}button.toggle-button svg.feather{fill:none;stroke:currentColor}button.toggle-button .icon-light{display:block}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%}}#cdio-logo{color:var(--color-white);text-transform:uppercase}.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;padding-left:.55rem;padding-right:.55rem;flex-direction:column;display:flex;align-items:center;justify-content:flex-start}details summary{cursor:pointer;font-weight:600;color:var(--color-link);width:fit-content}details summary:hover{text-decoration:underline}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}.processor-badge{font-weight:900;text-decoration:none}.processor-badge:hover{text-decoration:none;opacity:.8;cursor:pointer}.processor-badge.active{outline:2px solid var(--color-link);outline-offset:1px}.watch-tag-list{color:var(--color-white);background:var(--color-text-watch-tag-list);text-decoration:none}.watch-tag-list:hover{text-decoration:none;opacity:.8;cursor:pointer}.watch-tag-list:visited{color:var(--color-white)}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;position:fixed;top:0;left:0;width:100%;height:100vh;z-index:-1}body::after{opacity:.91}body::before{content:""}.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:75%;border-radius:6px;margin-right:4px;margin-bottom:1px}.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}label:hover{cursor:pointer}.grey-form-border{border:1px solid var(--color-border-notification);padding:.5rem;border-radius:5px}#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;max-width:100%}#new-watch-form #url::placeholder{font-weight:bold}#new-watch-form input{display:inline-block}#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}#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-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}.edit-form{max-width:95%}.edit-form .box-wrap{position:relative}.edit-form .inner{background:var(--color-background);padding:1.1rem}.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}[type=checkbox],[type=radio]{width:17px;height:17px;border-radius:5px;cursor:pointer}.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:#7a0cc5;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.price{border:1px solid var(--color-background-button-cancel)}.restock-label svg{vertical-align:middle}.price-change{white-space:nowrap;font-weight:700;font-size:90%;margin-left:4px;vertical-align:middle}.price-change.down{color:var(--color-background-button-green)}.price-change.up{color:var(--color-background-button-error)}#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;z-index:100}#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}@media only screen and (max-width: 768px){.box{padding:.25rem !important}}.box{color:var(--color-white);border-width:1px;border-style:dashed;border-color:hsla(0,0%,100%,.25);border-image:initial;background:hsla(0,0%,100%,.04);border-radius:var(--common-round-border);padding:1.1rem}header{color:var(--color-white)}#heart-us svg{display:inline-block;vertical-align:middle;cursor:pointer;width:1.4rem} +.header{color:var(--color-text-menu-heading)}.header a{color:var(--color-text-menu-heading)}.header::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;pointer-events:none;background:linear-gradient(to right, rgba(200, 200, 200, 0.02), rgba(200, 200, 200, 0.6))}ul#top-right-menu{list-style:none;margin-left:auto;padding:0;margin-top:0;margin-right:0;margin-bottom:0;display:grid;gap:1.1rem;grid-auto-flow:column;grid-auto-columns:max-content;align-items:center}ul#top-right-menu .toggle-button{padding:0}.current-diff-url{flex:1 1 auto;min-width:0;overflow:hidden;white-space:nowrap;text-align:left;margin:0 .55rem;-webkit-mask-image:linear-gradient(to right, #000 calc(100% - 2.5em), transparent);mask-image:linear-gradient(to right, #000 calc(100% - 2.5em), transparent)}.current-diff-url span{overflow:visible;white-space:nowrap}.pure-menu-horizontal{padding:.55rem;display:flex;justify-content:space-between;align-items:center}.pure-menu-horizontal svg{height:1.3rem}.fi{height:1.3rem;cursor:pointer}#pure-menu-horizontal-spinner{height:2px;background:linear-gradient(-75deg, #ff6000, #ff8f00, #ffdd00, #ed0000);background-size:400% 400%;animation:gradient 200s ease infinite;opacity:.8;position:fixed;bottom:0;left:0;width:100%;z-index:100;pointer-events:none}.status-pill{display:inline-flex;align-items:center;gap:8px;height:30px;padding:0 12px;border-radius:var(--common-round-border);border:1px solid hsla(0,0%,100%,.25);background:hsla(0,0%,100%,.1);color:var(--color-text-menu-heading);font-size:.78rem;font-weight:600;white-space:nowrap;text-decoration:none}.status-pill:hover{background:hsla(0,0%,100%,.18)}.status-pill .live-dot{width:8px;height:8px;border-radius:50%;background:#42dd53;box-shadow:0 0 0 3px rgba(66,221,83,.3);animation:status-pill-pulse 2s infinite}.status-pill.paused .live-dot{background:#e8a33d;box-shadow:0 0 0 3px rgba(232,163,61,.3);animation:none}.status-pill .action-icon{width:16px;height:16px}.status-pill.muted{opacity:.8}.status-pill.muted .action-icon{color:#e8a33d}@keyframes status-pill-pulse{0%,100%{opacity:1}50%{opacity:.4}}.menu-pop-wrap{position:relative}.icon-btn{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border:0;border-radius:var(--common-round-border);background:rgba(0,0,0,0);color:var(--color-text-menu-heading);cursor:pointer}.icon-btn svg{width:18px;height:18px;fill:none;stroke:currentColor}.icon-btn:hover{background:hsla(0,0%,100%,.14)}.menu-pop{display:none;position:absolute;top:calc(100% + 8px);right:0;min-width:220px;padding:6px;border:1px solid var(--color-border-table-cell);border-radius:12px;background:var(--color-background);box-shadow:0 18px 50px rgba(0,0,0,.18);z-index:80}.menu-pop.open{display:block}.menu-pop .mi{display:flex;align-items:center;gap:10px;width:100%;padding:9px 10px;border:0;border-radius:8px;background:rgba(0,0,0,0);color:var(--color-text);font-size:.85rem;text-align:left;text-decoration:none;white-space:nowrap;cursor:pointer}.menu-pop .mi:hover{background:var(--color-background-menu-link-hover)}.menu-pop .mi .ico{display:inline-flex;color:var(--color-text-input-description)}.menu-pop .mi .ico svg{width:16px;height:16px;fill:none;stroke:currentColor}.menu-pop .mi .right{margin-left:auto;font-size:.75rem;color:var(--color-text-input-description)}.top-menu-list .action-label{color:var(--color-text-menu-heading)}@media only screen and (max-width: 768px){.top-menu-list .action-label{display:none}}#inline-menu-extras-group{list-style:none;margin:0;padding:0;display:grid;gap:.55rem;grid-auto-flow:column;grid-auto-columns:max-content;align-items:center}@media only screen and (max-width: 980px){#nav-menu #menu-settings span{display:none}}:root{--body-main-text-size: 0.9rem;--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);--watchlist-row-selected: #e3f0ff;--watchlist-row-hover: #f2f2f2;--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-white);--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-watch-table-error: var(--color-dark-red);--color-watch-table-row-text: var(--color-grey-100);--color-table-line: #e7e9ee;--highlight-trigger-text-bg-color: #1b98f8;--highlight-ignored-text-bg-color: var(--color-grey-700);--highlight-blocked-text-bg-color: rgb(202, 60, 60);--color-sidebar-bg: rgba(255, 255, 255, 0.97);--color-sidebar-text: var(--color-text);--color-sidebar-shadow: 6px 0 28px rgba(0, 0, 0, 0.18);--color-sidebar-item-hover-bg: rgba(0, 0, 0, 0.06);--color-sidebar-item-active-bg: rgba(0, 0, 0, 0.10);--common-round-border: 8px}html[data-darkmode=true]{--color-link: #59bdfb;--color-text: var(--color-white);--color-table-line: #262c37;--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);--watchlist-row-selected: #1e3a5f;--watchlist-row-hover: #2a2a2a;--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-watch-table-error: var(--color-light-red);--color-watch-table-row-text: var(--color-grey-800);--color-sidebar-bg: rgba(8, 10, 14, 0.97);--color-sidebar-text: var(--color-white);--color-sidebar-shadow: 6px 0 28px rgba(0, 0, 0, 0.45);--color-sidebar-item-hover-bg: rgba(255, 255, 255, 0.06);--color-sidebar-item-active-bg: rgba(255, 255, 255, 0.10)}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 svg{opacity:.3}html[data-darkmode=true] .watch-table .watch-controls .state-on svg{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 var(--color-border-input);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}#menu-mute img,#menu-pause img{height:1.2rem}.pure-menu-item{height:initial}.pure-menu-item svg{height:1.2rem}.pure-menu-item *{vertical-align:middle}.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-heading)}.pure-menu-item .action-icon{stroke:var(--color-text-menu-heading)}#overlay{opacity:.95;position:fixed;width:350px;max-width:100%;height:100%;top:50px;right:-350px;background-color:var(--color-table-stripe);border:1px solid #aaa;z-index:2;transform:translateX(0);transition:transform .5s ease}#overlay.visible{transform:translateX(-100%)}#overlay .content{font-size:.875rem;padding:1.1rem;max-width:400px;color:var(--color-watch-table-row-text)}#heartpath{height:1.6rem;width:1.6rem;z-index:100;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)}.cdio-table{width:100%;font-size:var(--body-main-text-size)}.cdio-table thead{text-transform:uppercase}.cdio-table thead a{color:var(--color-text)}.cdio-table td,.cdio-table th{vertical-align:middle;border:none}.cdio-table tbody tr{color:var(--color-watch-table-row-text);border-bottom:1px solid var(--color-table-line);background-color:var(--color-table-background)}.cdio-table tbody tr td{background-color:var(--color-table-background)}.cdio-table tbody tr:hover>td{background-color:var(--watchlist-row-hover)}.cdio-table-clip{border-radius:var(--common-round-border);overflow:hidden;margin-bottom:1.1rem}.seg{display:inline-flex;align-items:center;gap:2px;padding:2px;border:1px solid var(--color-border-table-cell);border-radius:var(--common-round-border);background:var(--color-background-table-thead)}.seg a,.seg button{display:inline-flex;align-items:center;gap:6px;border:0;background:rgba(0,0,0,0);color:var(--color-text-input-description);font-size:.8rem;font-weight:600;line-height:1.4;padding:5px 11px;border-radius:calc(var(--common-round-border) - 1px);text-decoration:none;cursor:pointer;white-space:nowrap}.seg a:hover,.seg button:hover{color:var(--color-text)}.seg a.active,.seg a:hover,.seg button.active,.seg button:hover{background:var(--color-background);color:var(--color-text);box-shadow:0 1px 2px rgba(0,0,0,.15)}html[data-darkmode=true] .seg a.active,html[data-darkmode=true] .seg button.active{background:var(--color-grey-400);box-shadow:0 1px 2px rgba(0,0,0,.5)}.seg-count{font-size:.62rem;line-height:1;font-weight:700;padding:2px 6px;border-radius:999px;background:var(--color-background-button-tag);color:var(--color-white)}.seg-count--unread{background:#3e95bb}.seg-count--error{background:var(--color-background-button-error)}.seg-count--deal{background:var(--color-background-button-success)}.cdio-btn{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 12px;border-radius:var(--common-round-border);border:1px solid var(--color-border-table-cell);background:var(--color-background);color:var(--color-text-input-description);font-family:inherit;font-size:.8rem;font-weight:600;line-height:1;white-space:nowrap;text-decoration:none;cursor:pointer;transition:border-color .12s ease,color .12s ease,background-color .12s ease}.cdio-btn:hover{border-color:var(--color-border-input);color:var(--color-text)}.cdio-btn:focus-visible{outline:2px solid var(--color-link);outline-offset:2px}.cdio-btn svg{width:15px;height:15px;stroke:currentColor}.cdio-btn img{height:15px;display:block}.cdio-btn--icon{width:32px;padding:0;justify-content:center}.cdio-btn--sm{height:26px;padding:0 9px;font-size:.72rem;gap:5px}.cdio-btn--sm svg{width:13px;height:13px}.cdio-btn--primary{background:var(--color-background-button-primary);border-color:var(--color-background-button-primary);color:var(--color-text-button)}.cdio-btn--primary:hover{background:var(--color-link);border-color:var(--color-link);color:var(--color-text-button)}.cdio-btn--danger{color:var(--color-background-button-error)}.cdio-btn--danger:hover{color:var(--color-background-button-error);border-color:var(--color-background-button-error)}.cdio-btn--warning{color:#d68a00}.cdio-btn--warning:hover{color:#d68a00;border-color:#d68a00}.watch-table tr:has(input[name=uuids]:checked)>td{background-color:var(--watchlist-row-selected)}.watch-table tbody tr:hover td.buttons *,.watch-table tbody tr:focus-within td.buttons *,.watch-table tbody tr:has(input[name=uuids]:checked) td.buttons *{opacity:1}.select-all-banner{margin:.4rem 0;padding:.5rem .75rem;border-radius:var(--common-round-border);background:var(--watchlist-row-selected);color:var(--color-watch-table-row-text);font-size:var(--body-main-text-size)}.select-all-banner button{margin-left:.5rem;vertical-align:baseline}.watch-controls svg{width:18px;height:18px;stroke:currentColor;fill:none;vertical-align:middle}#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 .left .records-selected{margin-top:.25rem;opacity:.9}#stats_row .right{opacity:.5;transition:opacity .6s ease;margin-left:auto;text-align:right}body.has-queue #stats_row .right{opacity:1}#checkbox-operations{margin-bottom:.55rem;background:var(--color-background-new-watch-form);padding:1em;border-radius:10px;max-width:100%;position:sticky;top:20px;display:none}#checkbox-operations button{margin-bottom:3px;margin-top:3px;display:inline-flex;align-items:center}#checkbox-operations i,#checkbox-operations svg{width:14px;height:14px;stroke:#fff}body.watch-selection-active #checkbox-operations{display:block}.watch-table .checkbox-uuid{text-align:center}.watch-table .checkbox-uuid>*{vertical-align:middle}@media only screen and (max-width: 1200px){.watch-table .last-checked,.watch-table .last-changed{text-align:center}}.watch-table #th-webpage{text-align:center}.watch-table tbody tr.unviewed{font-weight:bold}.watch-table tbody tr td.inline.title-col{width:100%}.watch-table tbody tr td.inline.title-col .grid-wrapper{display:grid;grid-template-columns:auto minmax(0, 1fr) auto;grid-auto-columns:auto;align-items:center;gap:.55rem}.watch-table tbody tr td.inline.title-col .grid-wrapper>.favicon{grid-column:1}.watch-table tbody tr td.inline.title-col .grid-wrapper>.watch-text-info{grid-column:2}.watch-table tbody tr td.inline.title-col .grid-wrapper>.status-icons{grid-column:3}.watch-table tbody tr td.inline.title-col .grid-wrapper>.restock-info-wrap{grid-column:4}@media only screen and (max-width: 1200px){.watch-table tbody tr td.inline.title-col .grid-wrapper>.restock-info-wrap{grid-column:1/-1;justify-self:center}}.watch-table tbody tr .watch-text-info{line-height:1.5}.watch-table tbody tr.checking-now td:first-child{position:relative}.watch-table tbody tr.checking-now td:first-child::before{content:"";position:absolute;top:0;bottom:0;left:0;width:3px;background-color:#293eff}.watch-table tbody tr.checking-now td.last-checked .spinner-wrapper{display:inline-block !important;white-space:nowrap !important}.watch-table tbody tr.checking-now td.last-checked .spinner{margin-right:.275rem}.watch-table tbody tr.checking-now td.last-checked .innertext{display:none !important}.watch-table tbody tr.queued a.recheck{display:none !important}.watch-table tbody tr.queued a.already-in-queue-button{display:inline-flex !important;opacity:.8}.watch-table tbody tr.paused a.pause-toggle.state-on{display:inline !important}.watch-table tbody tr.paused a.pause-toggle.state-off{display:none !important}.watch-table tbody tr.notification_muted a.mute-toggle.state-on{display:inline !important}.watch-table tbody tr.notification_muted a.mute-toggle.state-off{display:none !important}.watch-table tbody tr.has-error .error-text{display:block !important;color:var(--color-watch-table-error)}.watch-table tbody tr.single-history a.preview-link{display:inherit !important}.watch-table tbody tr.multiple-history a.history-link{display:inherit !important}.watch-table tbody tr.has-favicon.unviewed img.favicon{opacity:1 !important;border-radius:4px}.watch-table td.buttons{font-size:12px;white-space:nowrap}.watch-table td.buttons>div{display:inline-flex;align-items:center;gap:6px}.watch-table td.buttons>div>*{opacity:0;transition:opacity .12s ease}.watch-table td.title-col{word-break:break-all;white-space:normal}.watch-table td a.external::after{content:"";display:inline-block;width:var(--body-main-text-size);height:var(--body-main-text-size);vertical-align:-0.1em;background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23777' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'/%3E%3Cpolyline points='15 3 21 3 21 9'/%3E%3Cline x1='10' y1='14' x2='21' y2='3'/%3E%3C/svg%3E") no-repeat center/contain;margin:0 3px 0 5px}.watch-table td.watch-controls>div{display:flex;justify-content:space-between;align-items:center}@media(min-width: 1020px){.watch-table th{white-space:nowrap}}.watch-table th#h-lastchanged,.watch-table th#h-lastchecked{text-align:center}.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 th#mute-pause{white-space:nowrap}.watch-table th#mute-pause>div{display:flex;justify-content:space-between;align-items:center}.watch-table.favicon-not-enabled tr .favicon{display:none}.watch-table .status-icons{white-space:nowrap;display:flex;align-items:center;gap:4px}.watch-table .status-icons>*{vertical-align:middle}.watch-table .title-wrapper{display:flex;align-items:center;gap:10px}.watch-table .title-col-inner{display:inline-block;vertical-align:middle}.watch-table img.favicon{vertical-align:middle;max-width:36px;max-height:36px;height:36px}.watch-table img.favicon:hover{outline:2px solid color-mix(in srgb, var(--color-watch-table-row-text) 50%, transparent);outline-offset:1px;border-radius:4px}body.watch-selection-active #buttons-for-all-watches{display:none !important}#buttons-for-all-watches{display:flex;align-items:center;justify-content:flex-start;flex-wrap:wrap;gap:.55rem;margin:0}#buttons-for-all-watches #post-list-mark-views{display:none}body.has-any-unviewed #post-list-mark-views{display:inline-flex !important}#watch-table-wrapper{display:inline-block;width:100%}#watch-table-wrapper #list-related-buttons{display:flex;align-items:center;justify-content:flex-start;flex-wrap:wrap;gap:.55rem;margin:0;padding:1.1rem 0 .55rem 0}#watch-table-wrapper.has-error #list-related-buttons #post-list-with-errors{display:inline-flex !important}#watch-table-wrapper.has-unread-changes #list-related-buttons #post-list-unread{display:inline-flex !important}#watch-table-wrapper #tag-lister #tag-all{opacity:1}#watch-table-wrapper #tag-lister.active-tag .button-tag{opacity:.35}#watch-table-wrapper #tag-lister.active-tag .button-tag.active,#watch-table-wrapper #tag-lister.active-tag .button-tag:hover{opacity:1}.content .group-overview-table{width:100%}.content .group-overview-table .pure-button{margin-top:.3rem;margin-bottom:.3rem}.content .group-overview-table .watch-controls,.content .group-overview-table .watch-count{text-align:center}.content .group-overview-table td{padding:5px !important;color:var(--color-watch-table-row-text)}.pure-button{border-radius:var(--common-round-border)}body.blueprint-watchlist #add-watch-ui{margin-bottom:1.1rem;padding:0}body.blueprint-watchlist #add-watch-url-row{margin-bottom:0 !important}body.blueprint-watchlist #quick-watch-llm-intent{margin-top:.55rem}body.blueprint-watchlist #url{width:auto}@media only screen and (min-width: 980px){body.blueprint-watchlist #url{min-width:32rem;max-width:min(80%,80vw);box-sizing:border-box}}body.blueprint-watchlist #quick-watch-llm-intent,body.blueprint-watchlist #quick-watch-processor-type{display:none}body.blueprint-watchlist #new-watch-form:has(#url:not(:placeholder-shown)) #quick-watch-llm-intent,body.blueprint-watchlist #new-watch-form:has(#url:not(:placeholder-shown)) #quick-watch-processor-type{display:block}@media(max-width: 767px){.watch-table thead{display:block}.watch-table thead tr th{display:inline-block}.watch-table thead tr th .hide-on-mobile{display:none}.watch-table thead .empty-cell{display:none}.watch-table .last-checked::before{color:var(--color-text);content:attr(data-label) " "}.watch-table .last-changed::before{color:var(--color-text);content:attr(data-label) " "}.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:40px 1fr 100px;grid-template-rows:auto auto auto auto;gap:.5rem}.watch-table tbody tr .counter-i{display:none}.watch-table tbody tr>td{border-bottom:none}.watch-table tbody tr>td[colspan]{grid-column:1/-1}.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:0 !important}}@media(min-width: 768px){.watch-table thead tr th .hide-on-desktop{display:none}.watch-table td.last-checked .innertext,.watch-table td.last-changed .innertext{white-space:nowrap}}#llm-intent-section textarea{white-space:normal;overflow-wrap:break-word;overflow-x:hidden;overflow-y:auto;resize:vertical;font-family:inherit}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}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%}@media(min-width: 901px){body.blueprint-add_watch_ui #add-watch-ui{width:80%}}#add-watch-ui{padding:0}#add-watch-ui #add-watch-url-row{display:flex;gap:.5rem;align-items:stretch;margin-bottom:1rem}#add-watch-ui #add-watch-url-row>span{flex:1 1 auto;min-width:0}#add-watch-ui #add-watch-url-row>span input{width:100%}#add-watch-ui #add-watch-url-row #add-watch-go{flex:0 0 auto;white-space:nowrap}#add-watch-ui #add-watch-panes{display:flex;gap:.55rem;align-items:stretch}@media(max-width: 900px){#add-watch-ui #add-watch-panes{flex-direction:column}}#add-watch-ui #add-watch-selector-pane{flex:1 1 62%;min-width:0;min-height:380px;position:relative;display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--color-background-tab);border-radius:6px;background:rgba(0,0,0,.15);padding:.75rem}#add-watch-ui #add-watch-selector-pane #add-watch-empty-state,#add-watch-ui #add-watch-selector-pane #add-watch-spinner,#add-watch-ui #add-watch-selector-pane #add-watch-error{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.6rem;text-align:center;padding:2rem 1rem}#add-watch-ui #add-watch-selector-pane #add-watch-empty-state{opacity:.8}#add-watch-ui #add-watch-selector-pane #add-watch-empty-state svg{opacity:.55}#add-watch-ui #add-watch-selector-pane #add-watch-empty-state strong{font-size:1.05rem}#add-watch-ui #add-watch-selector-pane #add-watch-empty-state span{font-size:.85rem;opacity:.8;max-width:32ch}#add-watch-ui #add-watch-selector-pane #add-watch-spinner{gap:1.2rem}#add-watch-ui #add-watch-selector-pane #add-watch-spinner .spinner{font-size:5px}#add-watch-ui #add-watch-selector-pane #add-watch-spinner .fetching-update-notice{font-size:.85rem;opacity:.85}#add-watch-ui #add-watch-selector-pane #add-watch-error{color:#ffb4b4;font-size:.9rem;word-break:break-word}#add-watch-ui #add-watch-selector-pane #selector-wrapper{position:relative;display:block;width:100%;flex:1 1 auto;min-height:0;max-height:none;overflow-y:auto;overflow-x:hidden;text-align:left}#add-watch-ui #add-watch-selector-pane #selector-wrapper>img{position:relative;display:block;max-width:100%;height:auto;z-index:4}#add-watch-ui #add-watch-selector-pane #selector-wrapper>canvas{position:absolute;top:0;left:0;max-width:none;z-index:5}#add-watch-ui #add-watch-options-pane{flex:0 0 34%;min-width:0;display:flex;flex-direction:column;gap:1.1rem}@media(max-width: 900px){#add-watch-ui #add-watch-options-pane{flex:1 1 auto}}#add-watch-ui #add-watch-options-pane .add-watch-option-group label{display:inline-block}#add-watch-ui #add-watch-options-pane #quick-watch-fetch-backend ul{margin:.35rem 0 0 0;padding:0;list-style:none}#add-watch-ui #add-watch-options-pane #quick-watch-fetch-backend li{display:flex;align-items:flex-start;gap:.5em;padding:.15rem 0}#add-watch-ui #add-watch-options-pane #quick-watch-fetch-backend li input[type=radio]{flex:0 0 auto;margin-top:.2em}#add-watch-ui #add-watch-options-pane #quick-watch-fetch-backend li label{display:block;min-width:0;overflow-wrap:anywhere;font-size:.85rem;line-height:1.35}#add-watch-ui #add-watch-options-pane #quick-watch-fetch-backend li.unusable{opacity:.55;cursor:not-allowed}#add-watch-ui #add-watch-options-pane #quick-watch-fetch-backend li.unusable label{cursor:not-allowed}#add-watch-ui #add-watch-options-pane #quick-watch-fetch-backend .pure-form-message-inline{display:block;margin-top:.35rem;font-size:.8rem;opacity:.8}#add-watch-ui #add-watch-options-pane #by-element-toggle-group .pure-form-message-inline{display:block;margin-top:.25rem;font-size:.8rem;opacity:.8}#add-watch-ui #add-watch-options-pane #by-element-toggle-group #clear-selector{margin-top:.5rem}#add-watch-ui #add-watch-options-pane #quick-watch-llm-intent label{display:block;margin-bottom:.35rem}#add-watch-ui #add-watch-options-pane #add-watch-submit-row{display:flex;flex-wrap:wrap;gap:.5rem}body.blueprint-add_watch_ui #add-watch-ui{height:90vh;display:flex;flex-direction:column}body.blueprint-add_watch_ui #add-watch-fieldset{flex:1 1 auto;min-height:0;min-width:0;display:flex;flex-direction:column;border:0;margin:0;padding:0}body.blueprint-add_watch_ui #add-watch-legend{margin:0 0 .75rem;font-size:1.1rem;font-weight:600}body.blueprint-add_watch_ui #new-watch-form{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}@media(min-width: 901px){body.blueprint-add_watch_ui #add-watch-panes{flex:1 1 auto;min-height:0}body.blueprint-add_watch_ui #add-watch-selector-pane{min-height:0}}@media(max-width: 900px){body.blueprint-add_watch_ui #add-watch-ui{height:auto}body.blueprint-add_watch_ui #add-watch-panes{flex:0 0 auto}}.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}}.bulk-choice-list{display:flex;flex-direction:column;gap:2px;max-height:50vh;overflow-y:auto;text-align:left}.bulk-choice-list .bulk-choice-row{display:block;padding:6px 8px;cursor:pointer;border-radius:4px}.bulk-choice-list .bulk-choice-row input[type=radio]{margin-right:8px}.bulk-choice-list .bulk-choice-row:hover{background:rgba(127,127,127,.15)}.bulk-choice-list .bulk-choice-row em{opacity:.7;font-size:.9em}#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}.action-sidebar{display:flex;flex-direction:column;align-items:center;align-self:flex-start;position:sticky;top:0;height:100vh;background:hsla(0,0%,100%,.05);z-index:60;pointer-events:none}@media only screen and (max-width: 980px){.action-sidebar{display:none}}.action-sidebar-inner{pointer-events:auto;width:64px;overflow:hidden;flex:1 1 auto;display:flex;flex-direction:column;transition:width .08s ease-out;padding-left:.55rem;padding-right:.55rem}body.actionsidebar-minimal .action-sidebar-inner:hover,body.actionsidebar-minimal .action-sidebar-inner:focus-within{width:200px;transition:width .22s cubic-bezier(0.2, 0.7, 0.2, 1)}body.actionside-bar-on .action-sidebar-inner{width:200px;transition:none}ul.action-sidebar-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:0}.action-sidebar-list.action-sidebar-list--bottom{margin-top:auto}.action-sidebar-li{list-style:none;margin:0;position:relative;color:var(--color-white)}.action-sidebar-li:nth-child(2){padding-top:2rem}.action-sidebar-li button{padding:0;margin:0}.action-sidebar-li a{color:var(--color-white)}.action-sidebar-li--spark .queue-spark{display:block;width:100%;height:15px;box-sizing:border-box;padding:0;margin:0;border-radius:3px;background:hsla(0,0%,100%,.05);box-shadow:inset 0 0 0 1px hsla(0,0%,100%,.06)}.action-sidebar-divider{height:1px;background:hsla(0,0%,100%,.18);margin:6px 16px;list-style:none}.action-sidebar .action-sidebar-item{position:relative;display:flex;align-items:center;padding:.55rem;font-size:var(--body-main-text-size);border-radius:var(--common-round-border);color:var(--color-white);text-decoration:none;white-space:nowrap;background:rgba(0,0,0,0);border:0;text-align:left;cursor:pointer;transition:background-color .12s ease,color .12s ease}.action-sidebar .action-sidebar-item:hover{background-color:var(--color-sidebar-item-hover-bg)}.action-sidebar .action-sidebar-item:hover .action-icon{stroke-width:2.3}.action-sidebar .action-sidebar-item:focus-visible{outline:2px solid var(--color-link);outline-offset:2px}.action-sidebar .action-sidebar-item.active .action-icon{stroke-width:2.4;filter:drop-shadow(0 0 0.4px currentColor)}.action-sidebar .action-sidebar-item.active .action-label{font-weight:700}.action-sidebar .action-sidebar-item.is-disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.action-sidebar .action-sidebar-item.action-sidebar-item--accent .action-icon{stroke:#fff;stroke-width:2.6}.action-sidebar .action-sidebar-item .action-label{flex:0 0 auto;margin-left:14px;font-family:inherit;font-weight:400;letter-spacing:0;text-transform:none;color:inherit;opacity:0;transform:translateX(-4px);transition:opacity .05s ease-out,transform .05s ease-out}.action-sidebar .action-sidebar-item .action-badge{margin-left:10px;font-size:.7rem;line-height:1;padding:3px 7px;border-radius:999px;background:hsla(0,0%,100%,.14);color:hsla(0,0%,100%,.85);text-transform:uppercase;letter-spacing:.06em;font-weight:700;pointer-events:none;opacity:0;transition:opacity .05s ease-out}.action-sidebar .action-sidebar-item .action-badge.action-badge--count{margin-left:auto;text-transform:none;letter-spacing:0;background:#3e95bb;color:var(--color-white);font-variant-numeric:tabular-nums}body.actionsidebar-minimal .action-sidebar-inner:hover .action-sidebar-item .action-label,body.actionsidebar-minimal .action-sidebar-inner:focus-within .action-sidebar-item .action-label{opacity:1;transform:translateX(0);transition:opacity .18s ease .05s,transform .18s cubic-bezier(0.2, 0.7, 0.2, 1) .05s}body.actionsidebar-minimal .action-sidebar-inner:hover .action-sidebar-item .action-badge,body.actionsidebar-minimal .action-sidebar-inner:focus-within .action-sidebar-item .action-badge{opacity:1;transition:opacity .18s ease .05s}body.actionside-bar-on .action-sidebar .action-sidebar-item .action-label{opacity:1;transform:translateX(0);transition:none}body.actionside-bar-on .action-sidebar .action-sidebar-item .action-badge{opacity:1;transition:none}.action-icon{flex:0 0 auto;width:24px;height:24px;stroke:currentColor;stroke-width:1.9;fill:none;stroke-linecap:round;stroke-linejoin:round}.action-badge{flex:0 0 auto;font-size:.62rem;text-transform:uppercase;letter-spacing:.08em;padding:2px 6px;border-radius:999px;background:hsla(0,0%,100%,.15);color:hsla(0,0%,100%,.85);font-weight:700}.mobile-menu-section{padding:.5rem .75rem;border-bottom:1px solid var(--color-border-table-cell)}.mobile-menu-section ul.action-sidebar-list{gap:1px}.mobile-menu-section ul.action-sidebar-list .action-sidebar-li a,.mobile-menu-section ul.action-sidebar-list .action-sidebar-li button{padding:.55rem}.mobile-menu-section .action-sidebar-item{position:relative;display:flex;align-items:center;justify-content:flex-start;gap:.55rem;padding:.55rem .55rem;border-radius:var(--common-round-border);color:var(--color-text)}.mobile-menu-section .action-sidebar-item:hover{background-color:var(--color-background-menu-link-hover);color:var(--color-text)}.mobile-menu-section .action-sidebar-item.active{background-color:var(--color-background-menu-link-hover);color:var(--color-text)}.mobile-menu-section .action-sidebar-item .action-label{position:static;transform:none;background:rgba(0,0,0,0);box-shadow:none;color:inherit;opacity:1;pointer-events:auto;padding:0;font-weight:500}.mobile-menu-section .action-sidebar-item .action-label::before{display:none}.mobile-menu-section .action-sidebar-item .action-badge{position:static;margin-left:auto;font-size:.62rem;background:rgba(0,0,0,.08);color:var(--color-text)}.mobile-menu-section .action-sidebar-item.action-sidebar-item--accent{background:var(--color-background-menu-link-hover);box-shadow:inset 0 0 0 1px var(--color-border-table-cell);color:var(--color-text)}.mobile-menu-section .action-sidebar-item.action-sidebar-item--accent .action-label{color:inherit}.mobile-menu-section .action-sidebar-item--button{background:rgba(0,0,0,0);border:none;cursor:pointer;text-align:left;font:inherit}#add-watch-live-info{width:100%;margin-top:1rem}#add-watch-live-info .add-watch-live-placeholder{border:1px dashed hsla(0,0%,100%,.25);background:hsla(0,0%,100%,.04);border-radius:10px;padding:1.25rem;color:var(--color-white)}#add-watch-live-info .add-watch-live-placeholder h3{margin:0 0 .4rem 0;font-size:1rem;letter-spacing:.02em}#add-watch-live-info .add-watch-live-placeholder .muted{opacity:.7;margin:0 0 .75rem 0;font-size:.85rem}#add-watch-live-info .add-watch-live-placeholder .add-watch-live-stream{font-size:.85rem;opacity:.6;padding:.6rem 0}.mobile-menu-drawer .action-sidebar-list{padding:0}.mobile-menu-drawer .mobile-menu-section .action-sidebar-item{padding-left:0}#action-sidebar-logo{padding-top:1.1rem;padding-left:.55rem}.actionsidebar-minimal #checking-now-stats-sidebar{display:none}.actionsidebar-minimal #cdio-logo #logo-expanded{display:none}.actionsidebar-minimal.action-side-bar-expanded #checking-now-stats-sidebar{display:block}.actionsidebar-minimal.action-side-bar-expanded #cdio-logo #logo-expanded{display:inline-block}.action-side-bar-expanded #cdio-logo #logo-short{display:none}#queue-page{width:100%;color:var(--color-white)}#queue-page h2,#queue-page h3{color:var(--color-white)}#queue-page .queue-panel{background:var(--color-background-new-watch-form);padding:1em;border-radius:10px;margin-bottom:1em;width:100%;box-sizing:border-box;color:var(--color-white)}#queue-page .queue-stats{display:grid;grid-template-columns:repeat(auto-fit, minmax(160px, 1fr));gap:.75rem}#queue-page .queue-stat .label{font-size:.7rem;text-transform:uppercase;letter-spacing:.06em;opacity:.7}#queue-page .queue-stat .value{font-size:1.6rem;font-weight:700;color:var(--color-white)}#queue-page .queue-stat.queue-stat--action{display:flex;align-items:center;justify-content:flex-start}#queue-page .queue-stat.queue-stat--action .pure-button{white-space:nowrap}#queue-page table.pure-table{width:100%;background:rgba(0,0,0,0);color:var(--color-white);font-size:80%}#queue-page table.pure-table thead th{background:rgba(0,0,0,0);color:var(--color-white);border-bottom:1px solid hsla(0,0%,100%,.18);font-weight:700;white-space:nowrap}#queue-page table.pure-table td{color:var(--color-white);border-color:hsla(0,0%,100%,.08);white-space:nowrap}#queue-page table.pure-table td.title-col,#queue-page table.pure-table td.watch-cell{white-space:normal;word-break:break-all}#queue-page table.pure-table td.time-cell{font-variant-numeric:tabular-nums;color:hsla(0,0%,100%,.75);font-size:.95em}#queue-page table.pure-table code,#queue-page table.pure-table small,#queue-page table.pure-table em,#queue-page table.pure-table strong{color:var(--color-white)}#queue-page table.pure-table code{background:rgba(0,0,0,.18)}#queue-page table.pure-table small{opacity:.7}#queue-page table.pure-table-striped tr:nth-child(2n-1) td{background:hsla(0,0%,100%,.04)}#queue-page tr.is-completed td{opacity:.45;transition:opacity .4s ease}#queue-page tbody[data-section=workers]{border-bottom:1px solid hsla(0,0%,100%,.18)}#queue-page tr.worker-slot td{border-color:hsla(0,0%,100%,.05)}#queue-page tr.worker-idle td{background:hsla(0,0%,100%,.02)}#queue-page .inline-tag,#queue-page .processor-badge,#queue-page .watch-tag-list,#queue-page .tracking-ldjson-price-data,#queue-page .restock-label{background:hsla(0,0%,100%,.14);color:var(--color-white)}#queue-page .inline-tag--running{background:rgba(28,184,65,.45)}#queue-page .inline-tag--idle{background:hsla(0,0%,100%,.08);color:hsla(0,0%,100%,.6)}#queue-page .inline-tag--done{background:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.7)}#queue-page a.queue-cancel{display:inline-block;margin-left:8px;font-size:.75rem;color:hsla(0,0%,100%,.65);text-decoration:underline;text-decoration-style:dotted;text-underline-offset:2px}#queue-page a.queue-cancel:hover{color:var(--color-white);text-decoration-style:solid}#queue-page a.queue-cancel.is-busy{pointer-events:none;opacity:.5}#queue-page tr.is-new td{animation:queue-row-in .45s ease}@keyframes queue-row-in{from{background-color:rgba(28,184,65,.18)}to{background-color:rgba(0,0,0,0)}}#queue-page .queue-waiting{display:none;align-items:center;gap:.5rem;margin-top:1rem;padding:.5rem 0;color:hsla(0,0%,100%,.7);font-size:.85rem}#queue-page .queue-waiting[data-show=true]{display:flex}#queue-page .queue-waiting .spinner{margin:0;flex:0 0 auto;border-top-color:hsla(0,0%,100%,.18);border-right-color:hsla(0,0%,100%,.18);border-bottom-color:hsla(0,0%,100%,.18);border-left-color:var(--color-white)}.hamburger-menu{display:none;background:rgba(0,0,0,0);border:none;cursor:pointer;padding:.55rem;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-white);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{background-color:var(--color-text)}.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 #cdio-logo{color:var(--color-text)}.mobile-menu-drawer #cdio-logo #logo-short{display:none}.mobile-menu-drawer #cdio-logo #logo-expanded{display:inline-block}.mobile-menu-drawer .action-icon{stroke:var(--color-text)}.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)}.mobile-menu-drawer .mobile-menu-items li#menu-pause,.mobile-menu-drawer .mobile-menu-items li#menu-mute{display:none}.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)}#llm-diff-summary-area{margin:.6rem 0 .4rem;padding:.65rem .9rem;background:linear-gradient(135deg, rgba(120, 80, 200, 0.18), rgba(80, 160, 220, 0.14));border-left:3px solid rgba(140,90,220,.8);border-radius:0 4px 4px 0;min-width:0;max-width:100%;box-sizing:border-box;overflow:hidden}#llm-diff-summary-area .llm-diff-summary-label{display:block;font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;opacity:.55;margin-bottom:.25rem}#llm-diff-summary-area .llm-diff-summary-text{margin:0;font-size:.9rem;line-height:1.5;white-space:pre-wrap;overflow-wrap:break-word;word-break:break-word}.llm-diff-summary-prompt{margin:.4em 0 0;font-size:.78rem;font-style:italic;overflow:hidden;max-height:3.8em;animation:llm-prompt-reveal .7s ease-out both}.llm-diff-summary-prompt .llm-diff-summary-prompt-text{display:block;opacity:.55;mask-image:linear-gradient(to bottom, rgba(0, 0, 0, 0.85) 30%, rgba(0, 0, 0, 0) 100%);-webkit-mask-image:linear-gradient(to bottom, rgba(0, 0, 0, 0.85) 30%, rgba(0, 0, 0, 0) 100%);white-space:pre-wrap;overflow-wrap:break-word;line-height:1.45}@keyframes llm-prompt-reveal{from{opacity:0;transform:translateY(-3px)}to{opacity:1;transform:translateY(0)}}.llm-diff-summary-loading{opacity:.5;font-style:italic;animation:llm-pulse 1.4s ease-in-out infinite;font-weight:bold}@keyframes llm-pulse{0%,100%{opacity:.5}50%{opacity:.2}}.llm-budget-exceeded,.llm-error{color:#c0392b;font-weight:600;font-style:normal;opacity:1}.toggle-ai-mode{opacity:.4;transition:opacity .2s ease,filter .2s ease;display:inline-flex;align-items:center;color:var(--color-text-menu-link)}.toggle-ai-mode svg{height:1.2rem;width:1.2rem}.toggle-ai-mode .ai-mode-label{font-size:.75rem;font-weight:600;letter-spacing:.04em;line-height:1}html[data-ai-mode=true] .toggle-ai-mode{opacity:1;filter:drop-shadow(0 0 4px rgba(160, 100, 255, 0.7))}.btn-label-summary{display:none}html[data-ai-mode=true] body.llm-configured .btn-label-history{display:none}html[data-ai-mode=true] body.llm-configured .btn-label-summary{display:inline}.ai-inline-summary-row td{white-space:normal !important;word-break:break-word;padding:.5rem 1rem .6rem 1.4rem !important;background:linear-gradient(135deg, #f0ebff, #eaf0ff) !important;border-top:1px solid #c4b5fd !important;border-left:3px solid #8b5cf6 !important;color:#1a0640 !important;line-height:1.5}html[data-darkmode=true] .ai-inline-summary-row td{background:linear-gradient(135deg, #1c0d35, #0d1535) !important;border-top:1px solid #3b1f6e !important;border-left-color:#8b5cf6 !important;color:#e9d5ff !important}.ai-inline-summary-row .ai-inline-summary-content{display:flex;gap:.5rem;align-items:flex-start}.ai-inline-summary-row .ai-inline-summary-content .ai-inline-spinner{flex-shrink:0;animation:llm-pulse 1.4s ease-in-out infinite}.ai-inline-summary-row .ai-inline-summary-content .ai-inline-body{display:flex;flex-direction:column;min-width:0}.ai-inline-summary-row .ai-inline-summary-content .ai-inline-text{font-style:italic;opacity:.75;white-space:pre-wrap}.ai-inline-summary-row .ai-inline-summary-content.loaded .ai-inline-spinner{animation:none}.ai-inline-summary-row .ai-inline-summary-content.loaded .ai-inline-text{font-style:normal;opacity:1}.ai-inline-summary-row .ai-inline-history-link{display:inline-block;margin-top:.4rem;font-size:.78rem;font-weight:700;opacity:.7;white-space:nowrap}.ai-inline-summary-row .ai-inline-history-link:hover{opacity:1}.ai-inline-summary-row .ai-inline-error{color:#c0392b}.ai-inline-summary-row .ai-inline-prompt{display:block;margin-top:.3em;font-size:.75rem;font-style:italic;overflow:hidden;max-height:3.6em;animation:llm-prompt-reveal .6s ease-out both;mask-image:linear-gradient(to bottom, rgba(0, 0, 0, 0.7) 30%, rgba(0, 0, 0, 0) 100%);-webkit-mask-image:linear-gradient(to bottom, rgba(0, 0, 0, 0.7) 30%, rgba(0, 0, 0, 0) 100%);opacity:.55;line-height:1.4;white-space:pre-wrap;overflow-wrap:break-word}.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)}.notification-add-buttons{margin-bottom:.5rem;display:flex;align-items:center;flex-wrap:wrap;gap:.4rem}.notification-add-buttons .add-destination-inline{display:inline-flex;align-items:center;gap:.3rem}.notification-add-buttons .add-destination-inline input[type=email]{margin:0;min-width:16rem}#notification-add-email-preset{padding-top:.55rem;padding-bottom:.55rem}#notification-recipients{padding-bottom:.55rem}.notification-recipients{display:flex;flex-wrap:wrap;gap:.4rem;margin-bottom:.5rem}.notification-recipients .notification-chip{display:inline-flex;align-items:center;gap:.35rem;padding:.2rem .5rem;line-height:1.4;border:1px solid var(--color-border-notification);border-radius:var(--common-round-border);max-width:100%}.notification-recipients .notification-chip .notification-chip-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:22rem}.notification-recipients .notification-chip .notification-chip-remove{cursor:pointer;font-weight:bold;opacity:.55;text-decoration:none}.notification-recipients .notification-chip .notification-chip-remove:hover{opacity:1}.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}#notification-error-log{border:1px solid var(--color-border-notification);padding:1rem;border-radius:5px;overflow-wrap:break-word}#restock-diff{width:100%;box-sizing:border-box}#restock-diff-summary{margin-top:.6rem;display:flex;align-items:center;gap:.6rem;flex-wrap:wrap}.restock-latest-price{font-size:1.4rem;font-weight:700}.restock-badge{display:inline-block;padding:.15rem .55rem;border-radius:1rem;font-size:.8rem;font-weight:600;white-space:nowrap}.restock-badge.in-stock{background:rgba(31,164,99,.15);color:#1fa463}.restock-badge.out-of-stock{background:rgba(231,76,60,.15);color:#e74c3c}#restock-tabs{background:var(--color-background);color:var(--color-text);padding:1rem;border-radius:5px}#restock-tabs .tab-pane-inner#screenshot{text-align:center}#restock-tabs .tab-pane-inner#screenshot img{max-width:99%}#restock-graph{margin-top:1rem;box-sizing:border-box}@media(min-width: 1200px){#restock-graph{max-width:80%;margin-left:auto;margin-right:auto}}.js-restock-graph{position:relative;width:100%}.js-restock-graph svg{display:block;max-width:100%}.js-restock-graph .rg-axis{stroke:var(--color-border-notification, rgba(127, 127, 127, 0.4));stroke-width:1}.js-restock-graph .rg-label{fill:currentColor;opacity:.7;font-size:12px}.js-restock-graph .rg-line{stroke:currentColor;opacity:.55}.js-restock-graph .rg-dot{stroke:var(--color-background, #fff);stroke-width:1.5}.js-restock-graph .rg-legend{display:flex;justify-content:center;gap:1.1rem;margin-top:.4rem;font-size:.78rem;opacity:.85}.js-restock-graph .rg-legend .rg-legend-item{display:inline-flex;align-items:center;gap:.35rem}.js-restock-graph .rg-legend .rg-legend-dot{width:9px;height:9px;border-radius:50%;display:inline-block}.js-restock-graph .rg-legend .rg-legend-dot.in{background:#1fa463}.js-restock-graph .rg-legend .rg-legend-dot.out{background:#e74c3c}.js-restock-graph .rg-header{display:flex;align-items:center;justify-content:space-between;gap:.5rem;flex-wrap:wrap;margin-bottom:.5rem}.js-restock-graph .rg-stats{font-size:.8rem;opacity:.7;text-align:right;margin-left:auto}.js-restock-graph .rg-band{fill:rgba(120,130,150,.14)}.js-restock-graph .rg-avg-line{stroke:var(--color-text, #555);opacity:.45;stroke-width:1}.js-restock-graph .rg-avg-text{opacity:.5}.rg-status{display:inline-flex;align-items:baseline;gap:.4rem;padding:.2rem .6rem;border-radius:1rem;font-size:.85rem}.rg-status .rg-status-label{font-weight:700}.rg-status .rg-status-sub{font-size:.78rem;opacity:.8}.rg-status.rg-status-low{background:rgba(31,164,99,.16);color:#1fa463}.rg-status.rg-status-typical{background:rgba(120,130,150,.16);color:var(--color-text, #555)}.rg-status.rg-status-high{background:rgba(231,76,60,.16);color:#e74c3c}.rg-tooltip{position:absolute;display:none;pointer-events:none;z-index:5;transform:translateY(-50%);white-space:nowrap;background:var(--color-background, #fff);color:var(--color-text, #222);border:1px solid var(--color-border-notification, rgba(127, 127, 127, 0.4));border-radius:5px;padding:4px 8px;font-size:12px;line-height:1.4;box-shadow:0 2px 6px rgba(0,0,0,.15)}#restock-history-table{margin-left:auto;margin-right:auto}#restock-history-table td,#restock-history-table th{text-align:left}.restock-table-toolbar{display:flex;align-items:center;justify-content:center;gap:.75rem;margin-bottom:.5rem}html[data-ai-mode=true] body.llm-configured tr.processor-restock_diff .btn-label-history{display:inline}html[data-ai-mode=true] body.llm-configured tr.processor-restock_diff .btn-label-summary{display:none}.restock-inline-row td{white-space:normal !important;word-break:break-word;padding:.6rem 1rem .8rem 1.4rem !important;background:linear-gradient(135deg, #e6fbf0, #e8f6ff) !important;border-top:1px solid #9fe3c2 !important;border-left:3px solid #1fa463 !important;color:#06281a !important;line-height:1.5}html[data-darkmode=true] .restock-inline-row td{background:linear-gradient(135deg, #0c2a1c, #0d2230) !important;border-top:1px solid #1f5e40 !important;border-left-color:#1fa463 !important;color:#d6ffe9 !important}.restock-inline-row .restock-inline-graph{width:100%;min-height:40px}.restock-inline-row .restock-inline-history-link{display:inline-block;margin-top:.5rem;font-size:.78rem;font-weight:700;opacity:.75;white-space:nowrap}.restock-inline-row .restock-inline-history-link:hover{opacity:1}.restock-inline-row .restock-inline-error{color:#c0392b}.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:50% !important;right:auto !important;top:80px !important;transform:translateX(-50%) !important;align-items:center}.toast-container.toast-bottom-right,.toast-container.toast-bottom-center,.toast-container.toast-bottom-left{top:auto !important;bottom:80px !important}.toast{min-width:auto;max-width:none;width:80vw;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)}.stab-shell{display:flex;align-items:stretch;background:var(--color-background);border:1px solid rgba(0,0,0,.08);border-radius:8px;overflow:hidden;box-shadow:0 2px 8px rgba(0,0,0,.05);margin-bottom:1.5rem}.stab-nav{display:flex;flex-direction:column;width:11rem;flex-shrink:0;padding:.75rem 0;gap:1px;background:linear-gradient(180deg, rgba(0, 0, 0, 0.03) 0%, rgba(0, 0, 0, 0.05) 100%);border-right:1px solid rgba(0,0,0,.07)}.stab-btn{position:relative;display:flex;align-items:center;gap:.5rem;padding:.65rem .9rem .65rem 1rem;width:100%;background:none;border:none;border-left:3px solid rgba(0,0,0,0);border-radius:0;cursor:pointer;font:inherit;color:var(--color-text);text-align:left;opacity:.65;transition:background .12s ease,opacity .12s ease,border-color .12s ease,color .12s ease}.stab-btn:hover{background:rgba(0,0,0,.04);opacity:.85}.stab-btn.active{border-left-color:var(--color-menu-accent);background:rgba(237,89,0,.07);color:var(--color-menu-accent);font-weight:700;opacity:1}.stab-btn .stab-icon{display:inline-flex;align-items:center;justify-content:center;width:1.1rem;flex-shrink:0;opacity:.8}.stab-btn .stab-icon svg{width:.95rem;height:.95rem;stroke:currentColor;fill:none}.stab-body{flex:1;min-width:0;padding:1.4rem 1.6rem;overflow-x:hidden}.stab-pane{visibility:hidden;height:0;overflow:hidden}.stab-pane.active{visibility:visible;height:auto;overflow:visible;animation:stab-enter .16s ease both}@keyframes stab-enter{from{opacity:0;transform:translateY(5px)}to{opacity:1;transform:translateY(0)}}.stab-overview-hero{margin-bottom:1.5rem}.stab-overview-hero h3{margin:0 0 .3rem;font-size:1.05rem}.stab-overview-hero .stab-overview-glyph{color:var(--color-menu-accent);margin-right:.2rem}.stab-overview-hero .stab-overview-glyph svg{width:1.1rem;height:1.1rem;stroke:currentColor;fill:none;vertical-align:-0.15em}.stab-overview-hero p{margin:0;font-size:.88rem;color:var(--color-text-input-description);max-width:44rem;line-height:1.55}.stab-overview-features{display:flex;flex-direction:column;gap:.7rem;margin-bottom:1.6rem}.stab-overview-feature{display:flex;gap:.85rem;align-items:flex-start;padding:.75rem 1rem;border-radius:6px;background:rgba(0,0,0,.022);border:1px solid rgba(0,0,0,.05);transition:background .12s ease}.stab-overview-feature:hover{background:rgba(0,0,0,.035)}.stab-overview-feature .stab-overview-icon{width:1.6rem;flex-shrink:0;padding-top:.05rem;opacity:.7;display:flex;justify-content:center}.stab-overview-feature .stab-overview-icon svg{width:1.3rem;height:1.3rem;stroke:currentColor;fill:none}.stab-overview-feature .stab-overview-text>strong{display:block;margin-bottom:.2rem}.stab-overview-feature .stab-overview-text p{color:var(--color-text-input-description)}.stab-overview-disclaimer{display:flex;gap:.75rem;align-items:flex-start;margin:0 0 1.1rem;padding:.85rem 1rem;border-radius:6px;border:1px solid rgba(211,136,0,.35);background:rgba(255,180,0,.07)}.stab-overview-disclaimer .stab-disclaimer-icon{flex-shrink:0;padding-top:.05rem;color:#c07800}.stab-overview-disclaimer .stab-disclaimer-icon svg{width:1.2rem;height:1.2rem;stroke:currentColor;fill:none}.stab-overview-disclaimer .stab-disclaimer-body{font-size:.85rem;line-height:1.55}.stab-overview-disclaimer .stab-disclaimer-body>strong{display:block;margin-bottom:.35rem;color:#8a5500;font-size:.87rem}.stab-overview-disclaimer .stab-disclaimer-body p{margin:0 0 .45rem;color:var(--color-text-input-description)}.stab-overview-disclaimer .stab-disclaimer-body ul{margin:0 0 .6rem;padding-left:1.25rem;color:var(--color-text-input-description)}.stab-overview-disclaimer .stab-disclaimer-body ul li{margin-bottom:.2rem}.stab-overview-disclaimer .stab-disclaimer-check{display:flex;gap:.5rem;align-items:flex-start;cursor:pointer;font-size:.82rem;color:var(--color-text-input-description);font-weight:600}.stab-overview-disclaimer .stab-disclaimer-check input[type=checkbox]{flex-shrink:0;margin-top:.18rem;cursor:pointer}.stab-overview-cta{margin-top:.4rem;display:flex;align-items:center;gap:.8rem;flex-wrap:wrap}.stab-configured-badge{display:inline-flex;align-items:center;gap:.4rem;padding:.35rem .75rem;background:rgba(39,174,96,.09);border:1px solid rgba(39,174,96,.28);border-radius:4px;color:#2a7a4e;font-size:.82rem;font-weight:600}.stab-section-title{font-size:.72rem;font-weight:700;letter-spacing:.07em;text-transform:uppercase;opacity:.45;margin:1.4rem 0 .6rem}.stab-section-title:first-child{margin-top:0}@media(max-width: 600px){.stab-shell{flex-direction:column;min-height:unset}.stab-nav{width:100%;border-right:none;border-bottom:1px solid rgba(0,0,0,.07);padding:.4rem 0}.stab-body{padding-left:1rem}}.llm-usage-grid{display:grid;grid-template-columns:repeat(auto-fit, minmax(12rem, 1fr));gap:.9rem;margin-bottom:1.4rem}.llm-stat-card{padding:1rem 1.1rem .85rem;border-radius:7px;background:rgba(0,0,0,.025);border:1px solid rgba(0,0,0,.07)}.llm-stat-card .llm-stat-label{font-size:.7rem;font-weight:700;letter-spacing:.07em;text-transform:uppercase;opacity:.4;margin-bottom:.4rem}.llm-stat-card .llm-stat-value{font-size:1.65rem;font-weight:700;letter-spacing:-0.02em;line-height:1;margin-bottom:.25rem}.llm-stat-card .llm-stat-sub{font-size:.79rem;opacity:.5}.llm-stat-card .llm-stat-budget-text{font-size:.77rem;opacity:.55;margin-top:.3rem}.llm-stat-bar-wrap{height:4px;border-radius:2px;background:rgba(0,0,0,.1);overflow:hidden;margin-top:.65rem}.llm-stat-bar-fill{height:100%;border-radius:2px;transition:width .5s ease}.llm-stat-bar-fill.bar-ok{background:#27ae60}.llm-stat-bar-fill.bar-warn{background:#e67e22}.llm-stat-bar-fill.bar-over{background:#c0392b}.llm-usage-settings{border-top:1px solid rgba(0,0,0,.07);padding-top:.9rem;display:flex;flex-direction:column;gap:.65rem}.llm-usage-row{display:flex;align-items:baseline;gap:.9rem;flex-wrap:wrap}.llm-usage-row .llm-usage-row-label{font-size:.82rem;font-weight:600;opacity:.6;min-width:12rem;flex-shrink:0}.llm-usage-row .llm-usage-row-value{display:flex;align-items:baseline;gap:.5rem;flex-wrap:wrap;font-size:.88rem}.llm-field-hint{font-size:.8rem;opacity:.55}.llm-env-badge{font-size:.79rem;opacity:.6}.llm-budget-alert{color:#c0392b;font-weight:600;font-size:.88rem;margin:0 0 1rem}.llm-no-usage{opacity:.5;font-style:italic;font-size:.88rem;margin-bottom:1rem}html[data-darkmode=true] .stab-shell{border-color:hsla(0,0%,100%,.07);box-shadow:0 2px 8px rgba(0,0,0,.25)}html[data-darkmode=true] .stab-nav{background:linear-gradient(180deg, rgba(255, 255, 255, 0.025) 0%, rgba(255, 255, 255, 0.04) 100%);border-right-color:hsla(0,0%,100%,.07)}html[data-darkmode=true] .stab-btn:hover{background:hsla(0,0%,100%,.05)}html[data-darkmode=true] .stab-btn.active{background:rgba(237,89,0,.12)}html[data-darkmode=true] .stab-overview-feature{background:hsla(0,0%,100%,.025);border-color:hsla(0,0%,100%,.05)}html[data-darkmode=true] .stab-overview-feature:hover{background:hsla(0,0%,100%,.04)}html[data-darkmode=true] .stab-configured-badge{background:rgba(39,174,96,.1);border-color:rgba(39,174,96,.22);color:#5db880}html[data-darkmode=true] .stab-overview-disclaimer{border-color:rgba(255,190,50,.22);background:rgba(255,180,0,.05)}html[data-darkmode=true] .stab-overview-disclaimer .stab-disclaimer-icon{color:#c9963a}html[data-darkmode=true] .stab-overview-disclaimer .stab-disclaimer-body>strong{color:#c9a050}html[data-darkmode=true] .llm-stat-card{background:hsla(0,0%,100%,.03);border-color:hsla(0,0%,100%,.07)}html[data-darkmode=true] .llm-stat-bar-wrap{background:hsla(0,0%,100%,.1)}html[data-darkmode=true] .llm-usage-settings{border-top-color:hsla(0,0%,100%,.07)}body,.pure-table,.pure-table thead,.pure-table td,.pure-table th,.pure-form input,.pure-form textarea,.pure-form select,.edit-form .inner,.pure-menu-horizontal,footer,.sticky-tab,#diff-jump,.button-tag,#new-watch-form,#new-watch-form input:not(.pure-button),code,.messages li,#checkbox-operations,.inline-warning,a,.watch-controls img{transition:color .4s ease,background-color .4s ease,background .4s ease,border-color .4s ease,box-shadow .4s ease}body{color:var(--color-text);background:var(--color-background-page);font-family:Helvetica Neue,Helvetica,Lucida Grande,Arial,Ubuntu,Cantarell,Fira Sans,sans-serif}.app{display:flex;align-items:stretch;min-height:100vh}.app-main{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:.55rem}.content-wrapper{display:flex;width:100%;max-width:100%;position:relative;align-items:flex-start}@media only screen and (max-width: 980px){.content-wrapper{flex-direction:column}}.content-main{flex:1 1 auto;width:100%;min-width:0;display:flex;flex-direction:column;align-items:center}@media only screen and (min-width: 980px){.content-main{flex-direction:column}}.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}a{text-decoration:none;color:var(--color-link)}#search-result-info{color:#fff}button.toggle-button{vertical-align:middle;background:rgba(0,0,0,0);border:none;cursor:pointer;color:var(--color-text-menu-heading)}button.toggle-button svg{fill:currentColor}button.toggle-button svg.feather{fill:none;stroke:currentColor}button.toggle-button .icon-light{display:block}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%}}#cdio-logo{color:var(--color-white);text-transform:uppercase}.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;padding-left:.55rem;padding-right:.55rem;flex-direction:column;display:flex;align-items:center;justify-content:flex-start}details summary{cursor:pointer;font-weight:600;color:var(--color-link);width:fit-content}details summary:hover{text-decoration:underline}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}.processor-badge{font-weight:900;text-decoration:none}.processor-badge:hover{text-decoration:none;opacity:.8;cursor:pointer}.processor-badge.active{outline:2px solid var(--color-link);outline-offset:1px}.watch-tag-list{color:var(--color-white);background:var(--color-text-watch-tag-list);text-decoration:none}.watch-tag-list:hover{text-decoration:none;opacity:.8;cursor:pointer}.watch-tag-list:visited{color:var(--color-white)}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;position:fixed;top:0;left:0;width:100%;height:100vh;z-index:-1}body::after{opacity:.91}body::before{content:""}.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:75%;border-radius:6px;margin-right:4px;margin-bottom:1px}.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}label:hover{cursor:pointer}.grey-form-border{border:1px solid var(--color-border-notification);padding:.5rem;border-radius:5px}#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;max-width:100%}#new-watch-form #url::placeholder{font-weight:bold}#new-watch-form input{display:inline-block}#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}#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-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}.edit-form{max-width:95%}.edit-form .box-wrap{position:relative}.edit-form .inner{background:var(--color-background);padding:1.1rem}.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}[type=checkbox],[type=radio]{width:17px;height:17px;border-radius:5px;cursor:pointer}.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:#7a0cc5;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.price{border:1px solid var(--color-background-button-cancel)}.restock-label svg{vertical-align:middle}.price-change{white-space:nowrap;font-weight:700;font-size:90%;margin-left:4px;vertical-align:middle}.price-change.down{color:var(--color-background-button-green)}.price-change.up{color:var(--color-background-button-error)}#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;z-index:100}#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}@media only screen and (max-width: 768px){.box{padding:.25rem !important}}.box{color:var(--color-white);border-width:1px;border-style:dashed;border-color:hsla(0,0%,100%,.25);border-image:initial;background:hsla(0,0%,100%,.04);border-radius:var(--common-round-border);padding:1.1rem}header{color:var(--color-white)}#heart-us svg{display:inline-block;vertical-align:middle;cursor:pointer;width:1.4rem} diff --git a/changedetectionio/store/__init__.py b/changedetectionio/store/__init__.py index 4af86498..28ac5df0 100644 --- a/changedetectionio/store/__init__.py +++ b/changedetectionio/store/__init__.py @@ -35,7 +35,8 @@ except ImportError: from ..processors import get_custom_watch_obj_for_processor, find_processors # Import the base class and helpers -from .file_saving_datastore import FileSavingDataStore, load_all_watches, load_all_tags, save_json_atomic +from .file_saving_datastore import (FileSavingDataStore, load_all_watches, load_all_tags, load_watch_from_file, + save_json_atomic) from .updates import DatastoreUpdatesMixin # Because the server will run as a daemon and wont know the URL for notification links when firing off a notification @@ -852,10 +853,26 @@ class ChangeDetectionStore(DatastoreUpdatesMixin, FileSavingDataStore): last-screenshot.png + elements.deflate in final on-disk format) is renamed into place as the new watch's data_dir - no re-fetch, no copy. If the temp_uuid is missing/expired/invalid we fall back to a normal add_watch() so the UI still works. + + Settings the snapshot recorded for itself in its own watch.json (currently just + fetch_backend - the browser that rendered the preview) win over the posted form, + because they describe what actually fetched. add_watch() -> commit() rewrites that + file in full once the directory has been promoted. """ seed_dir = self.get_temporary_watch_dir(temp_uuid) if not (seed_dir and os.path.isdir(seed_dir)): seed_dir = None + + extras = dict(extras or {}) + seed_watch_json = os.path.join(seed_dir, "watch.json") if seed_dir else None + # isfile() first - a snapshot parked before this file existed is normal, not an error + if seed_watch_json and os.path.isfile(seed_watch_json): + seed_watch = load_watch_from_file(seed_watch_json, temp_uuid, self.rehydrate_entity) + if seed_watch and seed_watch.get('fetch_backend'): + extras['fetch_backend'] = seed_watch.get('fetch_backend') + logger.debug(f"Promoting temporary watch {temp_uuid} with its recorded " + f"fetch_backend '{extras['fetch_backend']}'") + return self.add_watch(url=url, tag=tag, extras=extras, seed_data_dir=seed_dir) def cleanup_temporary_watches(self, ttl_seconds=3600): diff --git a/changedetectionio/tests/llm/test_llm_features_disabled.py b/changedetectionio/tests/llm/test_llm_features_disabled.py index 6e87296f..757709b9 100644 --- a/changedetectionio/tests/llm/test_llm_features_disabled.py +++ b/changedetectionio/tests/llm/test_llm_features_disabled.py @@ -48,6 +48,16 @@ def test_llm_features_disabled_hides_ui(client, live_server, monkeypatch): assert b'name="llm_intent"' not in res.data assert b'name="llm_change_summary"' not in res.data + # 4. Add-watch page - with no "what matters" intent box there is nothing to choose + # between, so element selection is always on and the opt-in checkbox is not rendered. + res = client.get(url_for('add_watch_ui.add_watch_ui_index')) + assert res.status_code == 200 + _llm_markers_absent(res.data, where='add-watch-ui') + assert b'name="llm_intent"' not in res.data + assert b'id="by-element-toggle"' not in res.data + assert b'for="by-element-toggle"' not in res.data # no label either - it isn't a choice + assert b'id="by-element-toggle-group"' in res.data + def test_llm_features_enabled_by_default(client, live_server, monkeypatch): """When LLM_FEATURES_DISABLED is unset, the AI / LLM surfaces are still rendered.""" @@ -60,3 +70,11 @@ def test_llm_features_enabled_by_default(client, live_server, monkeypatch): assert res.status_code == 200 # The AI / LLM settings tab anchor should be present when not disabled assert b'href="#ai"' in res.data + + # With an LLM configured, the Add-watch page offers both ways of narrowing a watch, + # so "Select by element" goes back to being an opt-in checkbox. + monkeypatch.setenv('LLM_MODEL', 'gemini/gemini-2.5-flash') + res = client.get(url_for('add_watch_ui.add_watch_ui_index')) + assert res.status_code == 200 + assert b'name="llm_intent"' in res.data + assert b'id="by-element-toggle"' in res.data diff --git a/changedetectionio/tests/test_add_watch_ui_browser.py b/changedetectionio/tests/test_add_watch_ui_browser.py new file mode 100644 index 00000000..637905f2 --- /dev/null +++ b/changedetectionio/tests/test_add_watch_ui_browser.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python3 +"""The Add-Watch page's browser picker. + +The live preview needs a browser that can render screenshots + xpath element data, and +whatever rendered the preview is what the saved watch must check with - otherwise you +visually pick an element with Chrome and the watch then re-checks it with the plain HTTP +client. These tests cover the offered list, the server-side gate, and that the browser +which rendered a parked snapshot wins over the posted form. +""" +import json +import os + +from flask import url_for + + +def _datastore(client): + return client.application.config.get('DATASTORE') + + +def test_browser_picker_lists_only_live_preview_capable(client, live_server, measure_memory_usage, datastore_path, monkeypatch): + """Capable browsers are offered; the plain HTTP client never is.""" + from changedetectionio.blueprint.add_watch_ui import browser_config + + # html_webdriver is only preview-capable when it resolves to playwright/puppeteer, so + # pretend it does (a WEBDRIVER_URL-only deployment resolves it to selenium, which can't). + monkeypatch.setattr(browser_config, 'is_visual_capable', + lambda name, datastore: name == 'html_webdriver') + + res = client.get(url_for('add_watch_ui.add_watch_ui_index')) + assert res.status_code == 200 + assert b'name="fetch_backend"' in res.data + assert b'value="html_webdriver"' in res.data + # The plain HTTP client can't render a preview, so it is not an option + assert b'value="html_requests"' not in res.data + # The system default resolves to html_requests here, so it is listed but disabled + assert b'value="system"' in res.data + assert b'disabled' in res.data + + +def test_browser_picker_disables_incapable_system_default(client, live_server, measure_memory_usage, datastore_path, monkeypatch): + """With nothing capable at all, 'system' is still shown (disabled) rather than vanishing.""" + from changedetectionio.blueprint.add_watch_ui import browser_config + monkeypatch.setattr(browser_config, 'is_visual_capable', lambda name, datastore: False) + + res = client.get(url_for('add_watch_ui.add_watch_ui_index')) + assert res.status_code == 200 + assert b'name="fetch_backend"' in res.data + assert b'value="system"' in res.data + assert b'disabled' in res.data + # ...and nothing else is offered + assert b'value="html_' not in res.data + + +def test_snapshot_refuses_browser_that_cannot_preview(client, live_server, measure_memory_usage, datastore_path, monkeypatch): + """/snapshot won't spend a fetch on a browser that produces no screenshot.""" + from changedetectionio.blueprint.add_watch_ui import browser_config + monkeypatch.setattr(browser_config, 'is_visual_capable', lambda name, datastore: False) + + # Nothing capable, and no explicit browser asked for -> nothing to preview with + res = client.get(url_for('add_watch_ui.add_watch_ui_snapshot', url='https://example.com')) + assert res.status_code == 400 + assert b'No interactive browser' in res.data + + # Explicitly asking for a browser that can't preview is refused just the same + res = client.get(url_for('add_watch_ui.add_watch_ui_snapshot', url='https://example.com', + fetch_backend='html_requests')) + assert res.status_code == 400 + + # A made-up name never resolves to a capable fetcher either (real capability lookup here) + monkeypatch.undo() + res = client.get(url_for('add_watch_ui.add_watch_ui_snapshot', url='https://example.com', + fetch_backend='../../etc/passwd')) + assert res.status_code == 400 + res = client.get(url_for('add_watch_ui.add_watch_ui_snapshot', url='https://example.com', + fetch_backend='os')) + assert res.status_code == 400 + + +def test_submit_rejects_unknown_fetcher(client, live_server, measure_memory_usage, datastore_path): + """A posted browser is checked server side, so a doctored form can't pin a junk fetcher.""" + datastore = _datastore(client) + test_url = url_for('test_endpoint', _external=True) + + for bad in ('os', 'html_requests\n', '{{7*7}}', '../../etc/passwd', 'html_nope'): + before = len(datastore.data['watching']) + res = client.post( + url_for("ui.ui_views.form_quick_watch_add"), + data={"url": test_url, "fetch_backend": bad}, + follow_redirects=True + ) + assert res.status_code == 200 + assert b"Watch added" not in res.data + assert len(datastore.data['watching']) == before, f"{bad!r} should not have created a watch" + + +def test_submit_still_accepts_any_installed_fetcher(client, live_server, measure_memory_usage, datastore_path): + """This endpoint is shared with the watch-list quick-add, which may legitimately name a + backend that can't render a live preview (restock tests add watches with html_requests) - + only *offering* it on the Add-Watch page is restricted, not adding a watch with it.""" + datastore = _datastore(client) + test_url = url_for('test_endpoint', _external=True) + + res = client.post( + url_for("ui.ui_views.form_quick_watch_add"), + data={"url": test_url, "processor": "restock_diff", "fetch_backend": "html_requests"}, + follow_redirects=True + ) + assert b"Watch added" in res.data + + uuid = next(iter(datastore.data['watching'])) + assert datastore.data['watching'][uuid].get('fetch_backend') == 'html_requests' + + +def test_submit_saves_chosen_browser(client, live_server, measure_memory_usage, datastore_path): + """The picked browser lands on the watch instead of leaving it on 'system'.""" + datastore = _datastore(client) + test_url = url_for('test_endpoint', _external=True) + + res = client.post( + url_for("ui.ui_views.form_quick_watch_add"), + data={"url": test_url, "fetch_backend": "html_webdriver"}, + follow_redirects=True + ) + assert b"Watch added" in res.data + + uuid = next(iter(datastore.data['watching'])) + assert datastore.data['watching'][uuid].get('fetch_backend') == 'html_webdriver' + + +def test_parked_snapshot_browser_wins_over_form(client, live_server, measure_memory_usage, datastore_path): + """The browser that actually rendered the snapshot is the one the watch keeps. + + /snapshot records it in the temporary watch's own watch.json; promoting the snapshot + must prefer that over whatever the form posted, since the parked screenshot and + element data came from it. + """ + datastore = _datastore(client) + test_url = url_for('test_endpoint', _external=True) + + temp_uuid = '11111111-2222-3333-4444-555555555555' + temp_dir = datastore.get_temporary_watch_dir(temp_uuid) + os.makedirs(temp_dir, exist_ok=True) + with open(os.path.join(temp_dir, "watch.json"), 'w') as f: + json.dump({"fetch_backend": "html_webdriver"}, f) + + res = client.post( + url_for("ui.ui_views.form_quick_watch_add"), + data={"url": test_url, "fetch_backend": "html_requests", "temporary_uuid": temp_uuid}, + follow_redirects=True + ) + assert b"Watch added" in res.data + + uuid = next(iter(datastore.data['watching'])) + assert datastore.data['watching'][uuid].get('fetch_backend') == 'html_webdriver' + # The snapshot dir was promoted into the watch, not left behind + assert not os.path.isdir(temp_dir) + + +def test_watchlist_quick_add_is_unaffected(client, live_server, measure_memory_usage, datastore_path): + """The watch-list quick-add posts no browser at all - that still means 'system'.""" + datastore = _datastore(client) + test_url = url_for('test_endpoint', _external=True) + + res = client.post( + url_for("ui.ui_views.form_quick_watch_add"), + data={"url": test_url}, + follow_redirects=True + ) + assert b"Watch added" in res.data + + uuid = next(iter(datastore.data['watching'])) + assert datastore.data['watching'][uuid].get('fetch_backend') in (None, '', 'system') diff --git a/changedetectionio/translations/cs/LC_MESSAGES/messages.po b/changedetectionio/translations/cs/LC_MESSAGES/messages.po index 7aa5647a..887641e8 100644 --- a/changedetectionio/translations/cs/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/cs/LC_MESSAGES/messages.po @@ -18,6 +18,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.18.0\n" +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s)" +msgstr "" + +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s - no live preview)" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html msgid "Add a new web page change detection watch" msgstr "Přidejte nové sledování zjišťování změn webové stránky" @@ -43,6 +53,11 @@ msgstr "" msgid "Currently:" msgstr "V současné době:" +#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html +#, python-format +msgid "%(browser)s cannot render a live preview, choose a browser below" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html msgid "Select by element" msgstr "Vyberte podle prvku" @@ -2604,10 +2619,6 @@ msgstr "Štítek" msgid "Set browser / fetch method for selected" msgstr "" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "Browser" -msgstr "" - #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Apply" msgstr "" @@ -3002,6 +3013,10 @@ msgstr "Minuty" msgid "Seconds" msgstr "Sekundy" +#: changedetectionio/forms.py +msgid "Unknown fetch method." +msgstr "" + #: changedetectionio/forms.py msgid "Notification Body and Title is required when a Notification URL is used" msgstr "Při použití adresy URL oznámení je vyžadováno tělo a název oznámení" @@ -3052,6 +3067,10 @@ msgstr "Monitorovat" msgid "Processor" msgstr "Procesor" +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/forms.py +msgid "Browser" +msgstr "" + #: changedetectionio/forms.py msgid "Edit > Watch" msgstr "Upravit > Monitorovat" diff --git a/changedetectionio/translations/de/LC_MESSAGES/messages.po b/changedetectionio/translations/de/LC_MESSAGES/messages.po index 9a73c716..56a9545c 100644 --- a/changedetectionio/translations/de/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/de/LC_MESSAGES/messages.po @@ -18,6 +18,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.18.0\n" +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s)" +msgstr "" + +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s - no live preview)" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html msgid "Add a new web page change detection watch" msgstr "Fügen Sie eine neue Überwachung zur Erkennung von Webseitenänderungen hinzu" @@ -43,6 +53,11 @@ msgstr "" msgid "Currently:" msgstr "Momentan:" +#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html +#, python-format +msgid "%(browser)s cannot render a live preview, choose a browser below" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html msgid "Select by element" msgstr "Nach Element auswählen" @@ -2649,10 +2664,6 @@ msgstr "Tag" msgid "Set browser / fetch method for selected" msgstr "" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "Browser" -msgstr "" - #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Apply" msgstr "" @@ -3051,6 +3062,10 @@ msgstr "Minuten" msgid "Seconds" msgstr "Sekunden" +#: changedetectionio/forms.py +msgid "Unknown fetch method." +msgstr "" + #: changedetectionio/forms.py msgid "Notification Body and Title is required when a Notification URL is used" msgstr "Benachrichtigungstext und Titel sind erforderlich, wenn eine Benachrichtigungs-URL verwendet wird" @@ -3101,6 +3116,10 @@ msgstr "Überwachen" msgid "Processor" msgstr "Prozessor" +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/forms.py +msgid "Browser" +msgstr "" + #: changedetectionio/forms.py msgid "Edit > Watch" msgstr "Bearbeiten" diff --git a/changedetectionio/translations/en_GB/LC_MESSAGES/messages.po b/changedetectionio/translations/en_GB/LC_MESSAGES/messages.po index 22f50c9f..765f37c4 100644 --- a/changedetectionio/translations/en_GB/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/en_GB/LC_MESSAGES/messages.po @@ -18,6 +18,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.18.0\n" +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s)" +msgstr "" + +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s - no live preview)" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html msgid "Add a new web page change detection watch" msgstr "" @@ -43,6 +53,11 @@ msgstr "" msgid "Currently:" msgstr "" +#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html +#, python-format +msgid "%(browser)s cannot render a live preview, choose a browser below" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html msgid "Select by element" msgstr "" @@ -2598,10 +2613,6 @@ msgstr "" msgid "Set browser / fetch method for selected" msgstr "" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "Browser" -msgstr "" - #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Apply" msgstr "" @@ -2994,6 +3005,10 @@ msgstr "" msgid "Seconds" msgstr "" +#: changedetectionio/forms.py +msgid "Unknown fetch method." +msgstr "" + #: changedetectionio/forms.py msgid "Notification Body and Title is required when a Notification URL is used" msgstr "" @@ -3044,6 +3059,10 @@ msgstr "" msgid "Processor" msgstr "" +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/forms.py +msgid "Browser" +msgstr "" + #: changedetectionio/forms.py msgid "Edit > Watch" msgstr "" diff --git a/changedetectionio/translations/en_US/LC_MESSAGES/messages.po b/changedetectionio/translations/en_US/LC_MESSAGES/messages.po index 74d59065..a351a08d 100644 --- a/changedetectionio/translations/en_US/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/en_US/LC_MESSAGES/messages.po @@ -18,6 +18,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.18.0\n" +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s)" +msgstr "" + +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s - no live preview)" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html msgid "Add a new web page change detection watch" msgstr "" @@ -43,6 +53,11 @@ msgstr "" msgid "Currently:" msgstr "" +#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html +#, python-format +msgid "%(browser)s cannot render a live preview, choose a browser below" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html msgid "Select by element" msgstr "" @@ -2598,10 +2613,6 @@ msgstr "" msgid "Set browser / fetch method for selected" msgstr "" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "Browser" -msgstr "" - #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Apply" msgstr "" @@ -2994,6 +3005,10 @@ msgstr "" msgid "Seconds" msgstr "" +#: changedetectionio/forms.py +msgid "Unknown fetch method." +msgstr "" + #: changedetectionio/forms.py msgid "Notification Body and Title is required when a Notification URL is used" msgstr "" @@ -3044,6 +3059,10 @@ msgstr "" msgid "Processor" msgstr "" +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/forms.py +msgid "Browser" +msgstr "" + #: changedetectionio/forms.py msgid "Edit > Watch" msgstr "" diff --git a/changedetectionio/translations/es/LC_MESSAGES/messages.po b/changedetectionio/translations/es/LC_MESSAGES/messages.po index 82fc7e7c..67ede8d3 100644 --- a/changedetectionio/translations/es/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/es/LC_MESSAGES/messages.po @@ -14,6 +14,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.18.0\n" +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s)" +msgstr "" + +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s - no live preview)" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html msgid "Add a new web page change detection watch" msgstr "Agregar un nuevo monitor de detección de cambios en páginas web" @@ -39,6 +49,11 @@ msgstr "" msgid "Currently:" msgstr "Actualmente:" +#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html +#, python-format +msgid "%(browser)s cannot render a live preview, choose a browser below" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html msgid "Select by element" msgstr "Seleccionar por elemento" @@ -2665,10 +2680,6 @@ msgstr "Etiqueta" msgid "Set browser / fetch method for selected" msgstr "" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "Browser" -msgstr "" - #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Apply" msgstr "" @@ -3067,6 +3078,10 @@ msgstr "Minutos" msgid "Seconds" msgstr "Segundos" +#: changedetectionio/forms.py +msgid "Unknown fetch method." +msgstr "" + #: changedetectionio/forms.py msgid "Notification Body and Title is required when a Notification URL is used" msgstr "Se requiere el cuerpo y el título de la notificación cuando se utiliza una URL de notificación" @@ -3117,6 +3132,10 @@ msgstr "Monitor" msgid "Processor" msgstr "Procesador" +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/forms.py +msgid "Browser" +msgstr "" + #: changedetectionio/forms.py msgid "Edit > Watch" msgstr "Editar > Ver" diff --git a/changedetectionio/translations/fr/LC_MESSAGES/messages.po b/changedetectionio/translations/fr/LC_MESSAGES/messages.po index 6831bbdd..1a63ee42 100644 --- a/changedetectionio/translations/fr/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/fr/LC_MESSAGES/messages.po @@ -18,6 +18,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.18.0\n" +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s)" +msgstr "" + +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s - no live preview)" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html msgid "Add a new web page change detection watch" msgstr "Ajouter une nouvelle surveillance de détection de changement de page Web" @@ -43,6 +53,11 @@ msgstr "" msgid "Currently:" msgstr "Actuellement:" +#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html +#, python-format +msgid "%(browser)s cannot render a live preview, choose a browser below" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html msgid "Select by element" msgstr "Sélectionner par élément" @@ -2609,10 +2624,6 @@ msgstr "Étiqueter" msgid "Set browser / fetch method for selected" msgstr "" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "Browser" -msgstr "" - #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Apply" msgstr "" @@ -3007,6 +3018,10 @@ msgstr "Minutes" msgid "Seconds" msgstr "secondes" +#: changedetectionio/forms.py +msgid "Unknown fetch method." +msgstr "" + #: changedetectionio/forms.py msgid "Notification Body and Title is required when a Notification URL is used" msgstr "Le corps et le titre de la notification sont requis lorsqu'une URL de notification est utilisée" @@ -3057,6 +3072,10 @@ msgstr "Moniteur" msgid "Processor" msgstr "Processeur" +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/forms.py +msgid "Browser" +msgstr "" + #: changedetectionio/forms.py msgid "Edit > Watch" msgstr "Modifier > Surveiller" diff --git a/changedetectionio/translations/it/LC_MESSAGES/messages.po b/changedetectionio/translations/it/LC_MESSAGES/messages.po index 19968688..5a53193f 100644 --- a/changedetectionio/translations/it/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/it/LC_MESSAGES/messages.po @@ -18,6 +18,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.18.0\n" +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s)" +msgstr "" + +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s - no live preview)" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html msgid "Add a new web page change detection watch" msgstr "Aggiungi un nuovo monitoraggio modifiche pagina web" @@ -43,6 +53,11 @@ msgstr "" msgid "Currently:" msgstr "" +#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html +#, python-format +msgid "%(browser)s cannot render a live preview, choose a browser below" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html msgid "Select by element" msgstr "" @@ -2600,10 +2615,6 @@ msgstr "Tag" msgid "Set browser / fetch method for selected" msgstr "" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "Browser" -msgstr "" - #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Apply" msgstr "" @@ -2996,6 +3007,10 @@ msgstr "Minuti" msgid "Seconds" msgstr "Secondi" +#: changedetectionio/forms.py +msgid "Unknown fetch method." +msgstr "" + #: changedetectionio/forms.py msgid "Notification Body and Title is required when a Notification URL is used" msgstr "Corpo e titolo notifica sono richiesti quando si usa un URL di notifica" @@ -3046,6 +3061,10 @@ msgstr "Monitora" msgid "Processor" msgstr "Processore" +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/forms.py +msgid "Browser" +msgstr "" + #: changedetectionio/forms.py msgid "Edit > Watch" msgstr "Modifica > Monitora" diff --git a/changedetectionio/translations/ja/LC_MESSAGES/messages.po b/changedetectionio/translations/ja/LC_MESSAGES/messages.po index 1c2f5492..91c2d692 100644 --- a/changedetectionio/translations/ja/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/ja/LC_MESSAGES/messages.po @@ -19,6 +19,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.18.0\n" +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s)" +msgstr "" + +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s - no live preview)" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html msgid "Add a new web page change detection watch" msgstr "新しいウェブページ変更検知ウォッチを追加" @@ -44,6 +54,11 @@ msgstr "" msgid "Currently:" msgstr "現在:" +#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html +#, python-format +msgid "%(browser)s cannot render a live preview, choose a browser below" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html msgid "Select by element" msgstr "要素で選択" @@ -2617,10 +2632,6 @@ msgstr "タグ" msgid "Set browser / fetch method for selected" msgstr "" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "Browser" -msgstr "" - #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Apply" msgstr "" @@ -3013,6 +3024,10 @@ msgstr "分" msgid "Seconds" msgstr "秒" +#: changedetectionio/forms.py +msgid "Unknown fetch method." +msgstr "" + #: changedetectionio/forms.py msgid "Notification Body and Title is required when a Notification URL is used" msgstr "通知URLを使用する場合は通知本文とタイトルが必要です" @@ -3063,6 +3078,10 @@ msgstr "ウォッチ" msgid "Processor" msgstr "プロセッサー" +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/forms.py +msgid "Browser" +msgstr "" + #: changedetectionio/forms.py msgid "Edit > Watch" msgstr "編集 > ウォッチ" diff --git a/changedetectionio/translations/ko/LC_MESSAGES/messages.po b/changedetectionio/translations/ko/LC_MESSAGES/messages.po index 88c43607..e7b61fe1 100644 --- a/changedetectionio/translations/ko/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/ko/LC_MESSAGES/messages.po @@ -18,6 +18,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.18.0\n" +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s)" +msgstr "" + +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s - no live preview)" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html msgid "Add a new web page change detection watch" msgstr "새 웹페이지 변경 감지 모니터링 추가" @@ -43,6 +53,11 @@ msgstr "" msgid "Currently:" msgstr "현재:" +#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html +#, python-format +msgid "%(browser)s cannot render a live preview, choose a browser below" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html msgid "Select by element" msgstr "요소별로 선택" @@ -2608,10 +2623,6 @@ msgstr "태그" msgid "Set browser / fetch method for selected" msgstr "" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "Browser" -msgstr "" - #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Apply" msgstr "" @@ -3004,6 +3015,10 @@ msgstr "분" msgid "Seconds" msgstr "초" +#: changedetectionio/forms.py +msgid "Unknown fetch method." +msgstr "" + #: changedetectionio/forms.py msgid "Notification Body and Title is required when a Notification URL is used" msgstr "알림 URL을 사용하는 경우 알림 본문 및 제목이 필요합니다." @@ -3054,6 +3069,10 @@ msgstr "모니터링" msgid "Processor" msgstr "프로세서" +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/forms.py +msgid "Browser" +msgstr "" + #: changedetectionio/forms.py msgid "Edit > Watch" msgstr "편집 > 모니터링" diff --git a/changedetectionio/translations/messages.pot b/changedetectionio/translations/messages.pot index 45e82992..d4f4ce33 100644 --- a/changedetectionio/translations/messages.pot +++ b/changedetectionio/translations/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: changedetection.io 0.55.8\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2026-08-24 21:15+0200\n" +"POT-Creation-Date: 2026-08-25 14:13+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,6 +17,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.18.0\n" +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s)" +msgstr "" + +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s - no live preview)" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html msgid "Add a new web page change detection watch" msgstr "" @@ -42,6 +52,11 @@ msgstr "" msgid "Currently:" msgstr "" +#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html +#, python-format +msgid "%(browser)s cannot render a live preview, choose a browser below" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html msgid "Select by element" msgstr "" @@ -2597,10 +2612,6 @@ msgstr "" msgid "Set browser / fetch method for selected" msgstr "" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "Browser" -msgstr "" - #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Apply" msgstr "" @@ -2993,6 +3004,10 @@ msgstr "" msgid "Seconds" msgstr "" +#: changedetectionio/forms.py +msgid "Unknown fetch method." +msgstr "" + #: changedetectionio/forms.py msgid "Notification Body and Title is required when a Notification URL is used" msgstr "" @@ -3043,6 +3058,10 @@ msgstr "" msgid "Processor" msgstr "" +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/forms.py +msgid "Browser" +msgstr "" + #: changedetectionio/forms.py msgid "Edit > Watch" msgstr "" diff --git a/changedetectionio/translations/pl/LC_MESSAGES/messages.po b/changedetectionio/translations/pl/LC_MESSAGES/messages.po index 5f62031e..9ff0b57f 100644 --- a/changedetectionio/translations/pl/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/pl/LC_MESSAGES/messages.po @@ -14,6 +14,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.18.0\n" +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s)" +msgstr "" + +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s - no live preview)" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html msgid "Add a new web page change detection watch" msgstr "Dodaj obserwację wykrywającą zmiany na nowej stronie internetowej" @@ -39,6 +49,11 @@ msgstr "Pobieranie zrzutu ekranu i informacji o elemencie…" msgid "Currently:" msgstr "Obecnie:" +#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html +#, python-format +msgid "%(browser)s cannot render a live preview, choose a browser below" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html msgid "Select by element" msgstr "Wybierz według elementu" @@ -2753,10 +2768,6 @@ msgstr "Etykieta" msgid "Set browser / fetch method for selected" msgstr "Ustaw przeglądarkę / metodę pobierania dla zaznaczonych obserwacji" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "Browser" -msgstr "Przeglądarka" - #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Apply" msgstr "Zastosuj" @@ -3153,6 +3164,10 @@ msgstr "Minut" msgid "Seconds" msgstr "Sekundy" +#: changedetectionio/forms.py +msgid "Unknown fetch method." +msgstr "" + #: changedetectionio/forms.py msgid "Notification Body and Title is required when a Notification URL is used" msgstr "W przypadku korzystania z adresu URL powiadomienia należy podać treść i tytuł powiadomienia" @@ -3203,6 +3218,10 @@ msgstr "Obserwacja" msgid "Processor" msgstr "Procesor" +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/forms.py +msgid "Browser" +msgstr "Przeglądarka" + #: changedetectionio/forms.py msgid "Edit > Watch" msgstr "Edycja > Obserwuj" diff --git a/changedetectionio/translations/pt_BR/LC_MESSAGES/messages.po b/changedetectionio/translations/pt_BR/LC_MESSAGES/messages.po index 0a87e629..14d06e21 100644 --- a/changedetectionio/translations/pt_BR/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/pt_BR/LC_MESSAGES/messages.po @@ -19,6 +19,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.18.0\n" +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s)" +msgstr "" + +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s - no live preview)" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html msgid "Add a new web page change detection watch" msgstr "Adicionar um novo monitoramento de detecção de mudança de página" @@ -44,6 +54,11 @@ msgstr "" msgid "Currently:" msgstr "Atualmente:" +#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html +#, python-format +msgid "%(browser)s cannot render a live preview, choose a browser below" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html msgid "Select by element" msgstr "Selecionar por elemento" @@ -2646,10 +2661,6 @@ msgstr "Tag" msgid "Set browser / fetch method for selected" msgstr "" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "Browser" -msgstr "" - #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Apply" msgstr "" @@ -3044,6 +3055,10 @@ msgstr "Minutos" msgid "Seconds" msgstr "Segundos" +#: changedetectionio/forms.py +msgid "Unknown fetch method." +msgstr "" + #: changedetectionio/forms.py msgid "Notification Body and Title is required when a Notification URL is used" msgstr "Corpo e Título da Notificação são obrigatórios quando uma URL de Notificação é usada" @@ -3094,6 +3109,10 @@ msgstr "Monitoramento" msgid "Processor" msgstr "Processador" +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/forms.py +msgid "Browser" +msgstr "" + #: changedetectionio/forms.py msgid "Edit > Watch" msgstr "Editar > Monitoramento" diff --git a/changedetectionio/translations/ru/LC_MESSAGES/messages.po b/changedetectionio/translations/ru/LC_MESSAGES/messages.po index f03c031d..878b3efe 100644 --- a/changedetectionio/translations/ru/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/ru/LC_MESSAGES/messages.po @@ -17,6 +17,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.18.0\n" +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s)" +msgstr "" + +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s - no live preview)" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html msgid "Add a new web page change detection watch" msgstr "Добавить новый контроль обнаружения изменений веб-страницы" @@ -42,6 +52,11 @@ msgstr "" msgid "Currently:" msgstr "В настоящее время:" +#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html +#, python-format +msgid "%(browser)s cannot render a live preview, choose a browser below" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html msgid "Select by element" msgstr "Выбрать по элементу" @@ -2712,10 +2727,6 @@ msgstr "Ярлык" msgid "Set browser / fetch method for selected" msgstr "" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "Browser" -msgstr "" - #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Apply" msgstr "" @@ -3112,6 +3123,10 @@ msgstr "Минуты" msgid "Seconds" msgstr "Секунды" +#: changedetectionio/forms.py +msgid "Unknown fetch method." +msgstr "" + #: changedetectionio/forms.py msgid "Notification Body and Title is required when a Notification URL is used" msgstr "Текст и заголовок уведомления требуются при использовании URL-адреса уведомления." @@ -3162,6 +3177,10 @@ msgstr "Смотреть" msgid "Processor" msgstr "Процессор" +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/forms.py +msgid "Browser" +msgstr "" + #: changedetectionio/forms.py msgid "Edit > Watch" msgstr "Редактировать > Смотреть" diff --git a/changedetectionio/translations/tr/LC_MESSAGES/messages.po b/changedetectionio/translations/tr/LC_MESSAGES/messages.po index 46eddae2..64e40de5 100644 --- a/changedetectionio/translations/tr/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/tr/LC_MESSAGES/messages.po @@ -19,6 +19,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.18.0\n" +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s)" +msgstr "" + +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s - no live preview)" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html msgid "Add a new web page change detection watch" msgstr "Yeni bir web sayfası değişiklik tespiti izleyicisi ekle" @@ -44,6 +54,11 @@ msgstr "" msgid "Currently:" msgstr "Şu anda:" +#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html +#, python-format +msgid "%(browser)s cannot render a live preview, choose a browser below" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html msgid "Select by element" msgstr "Öğeye göre seç" @@ -2651,10 +2666,6 @@ msgstr "Etiket" msgid "Set browser / fetch method for selected" msgstr "" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "Browser" -msgstr "" - #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Apply" msgstr "" @@ -3047,6 +3058,10 @@ msgstr "Dakika" msgid "Seconds" msgstr "Saniye" +#: changedetectionio/forms.py +msgid "Unknown fetch method." +msgstr "" + #: changedetectionio/forms.py msgid "Notification Body and Title is required when a Notification URL is used" msgstr "Bir Bildirim URL'si kullanıldığında Bildirim Gövdesi ve Başlığı gereklidir" @@ -3097,6 +3112,10 @@ msgstr "İzleyici" msgid "Processor" msgstr "İşlemci" +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/forms.py +msgid "Browser" +msgstr "" + #: changedetectionio/forms.py msgid "Edit > Watch" msgstr "Düzenle > İzleyici" diff --git a/changedetectionio/translations/uk/LC_MESSAGES/messages.po b/changedetectionio/translations/uk/LC_MESSAGES/messages.po index adeea22e..4b4e5a0d 100644 --- a/changedetectionio/translations/uk/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/uk/LC_MESSAGES/messages.po @@ -17,6 +17,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.18.0\n" +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s)" +msgstr "" + +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s - no live preview)" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html msgid "Add a new web page change detection watch" msgstr "Додати нове завдання відстеження змін веб-сторінки" @@ -42,6 +52,11 @@ msgstr "" msgid "Currently:" msgstr "В даний час:" +#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html +#, python-format +msgid "%(browser)s cannot render a live preview, choose a browser below" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html msgid "Select by element" msgstr "Вибір за елементом" @@ -2630,10 +2645,6 @@ msgstr "Тег" msgid "Set browser / fetch method for selected" msgstr "" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "Browser" -msgstr "" - #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Apply" msgstr "" @@ -3026,6 +3037,10 @@ msgstr "Хвилини" msgid "Seconds" msgstr "Секунди" +#: changedetectionio/forms.py +msgid "Unknown fetch method." +msgstr "" + #: changedetectionio/forms.py msgid "Notification Body and Title is required when a Notification URL is used" msgstr "Тіло та заголовок сповіщення обов'язкові, якщо використовується URL сповіщення" @@ -3076,6 +3091,10 @@ msgstr "Завдання" msgid "Processor" msgstr "Процесор" +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/forms.py +msgid "Browser" +msgstr "" + #: changedetectionio/forms.py msgid "Edit > Watch" msgstr "Редагувати > Завдання" diff --git a/changedetectionio/translations/zh/LC_MESSAGES/messages.po b/changedetectionio/translations/zh/LC_MESSAGES/messages.po index 154d4a2e..99422560 100644 --- a/changedetectionio/translations/zh/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/zh/LC_MESSAGES/messages.po @@ -18,6 +18,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.18.0\n" +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s)" +msgstr "" + +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s - no live preview)" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html msgid "Add a new web page change detection watch" msgstr "新增网页变更监控" @@ -43,6 +53,11 @@ msgstr "" msgid "Currently:" msgstr "当前:" +#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html +#, python-format +msgid "%(browser)s cannot render a live preview, choose a browser below" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html msgid "Select by element" msgstr "按元素选择" @@ -2604,10 +2619,6 @@ msgstr "标签" msgid "Set browser / fetch method for selected" msgstr "" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "Browser" -msgstr "" - #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Apply" msgstr "" @@ -3000,6 +3011,10 @@ msgstr "分钟" msgid "Seconds" msgstr "秒" +#: changedetectionio/forms.py +msgid "Unknown fetch method." +msgstr "" + #: changedetectionio/forms.py msgid "Notification Body and Title is required when a Notification URL is used" msgstr "使用通知 URL 时,必须填写通知正文和标题" @@ -3050,6 +3065,10 @@ msgstr "监控项" msgid "Processor" msgstr "处理器" +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/forms.py +msgid "Browser" +msgstr "" + #: changedetectionio/forms.py msgid "Edit > Watch" msgstr "编辑 > 监控项" diff --git a/changedetectionio/translations/zh_Hant_TW/LC_MESSAGES/messages.po b/changedetectionio/translations/zh_Hant_TW/LC_MESSAGES/messages.po index 645a630a..b9356d82 100644 --- a/changedetectionio/translations/zh_Hant_TW/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/zh_Hant_TW/LC_MESSAGES/messages.po @@ -18,6 +18,16 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.18.0\n" +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s)" +msgstr "" + +#: changedetectionio/blueprint/add_watch_ui/browser_config.py +#, python-format +msgid "System settings default (%(browser)s - no live preview)" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html msgid "Add a new web page change detection watch" msgstr "新增網頁變更檢測任務" @@ -43,6 +53,11 @@ msgstr "" msgid "Currently:" msgstr "目前:" +#: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html +#, python-format +msgid "%(browser)s cannot render a live preview, choose a browser below" +msgstr "" + #: changedetectionio/blueprint/add_watch_ui/templates/add-watch-ui.html changedetectionio/blueprint/ui/templates/edit.html msgid "Select by element" msgstr "按元素選擇" @@ -2604,10 +2619,6 @@ msgstr "標籤" msgid "Set browser / fetch method for selected" msgstr "" -#: changedetectionio/blueprint/watchlist/templates/watch-overview.html -msgid "Browser" -msgstr "" - #: changedetectionio/blueprint/watchlist/templates/watch-overview.html msgid "Apply" msgstr "" @@ -3000,6 +3011,10 @@ msgstr "分鐘" msgid "Seconds" msgstr "秒" +#: changedetectionio/forms.py +msgid "Unknown fetch method." +msgstr "" + #: changedetectionio/forms.py msgid "Notification Body and Title is required when a Notification URL is used" msgstr "使用通知 URL 時,必須填寫通知內容與標題" @@ -3050,6 +3065,10 @@ msgstr "監測任務" msgid "Processor" msgstr "處理器" +#: changedetectionio/blueprint/watchlist/templates/watch-overview.html changedetectionio/forms.py +msgid "Browser" +msgstr "" + #: changedetectionio/forms.py msgid "Edit > Watch" msgstr "編輯 > 監測任務" From 465ff40bdeaba3ce5e4d7f14290b0496a97178f5 Mon Sep 17 00:00:00 2001 From: "Karl Q." Date: Tue, 25 Aug 2026 13:24:10 -0700 Subject: [PATCH 3/4] feat: make Playwright CSP bypass configurable (#4298) --- .../browser_steps/browser_steps.py | 5 +- changedetectionio/content_fetchers/base.py | 11 ++ .../content_fetchers/playwright.py | 7 +- .../content_fetchers/puppeteer.py | 10 +- .../tests/unit/test_playwright_bypass_csp.py | 154 ++++++++++++++++++ docker-compose.yml | 3 +- 6 files changed, 181 insertions(+), 9 deletions(-) create mode 100644 changedetectionio/tests/unit/test_playwright_bypass_csp.py diff --git a/changedetectionio/browser_steps/browser_steps.py b/changedetectionio/browser_steps/browser_steps.py index 062a7b88..3aace66d 100644 --- a/changedetectionio/browser_steps/browser_steps.py +++ b/changedetectionio/browser_steps/browser_steps.py @@ -5,7 +5,7 @@ from random import randint from loguru import logger from changedetectionio.content_fetchers import SCREENSHOT_MAX_HEIGHT_DEFAULT -from changedetectionio.content_fetchers.base import manage_user_agent +from changedetectionio.content_fetchers.base import get_playwright_bypass_csp, manage_user_agent from changedetectionio.jinja2_custom import render as jinja_render from changedetectionio.validate_url import validate_fetch_url_async @@ -367,7 +367,7 @@ class browsersteps_live_ui(steppable_browser_interface): # @todo handle multiple contexts, bind a unique id from the browser on each req? self.context = await self.playwright_browser.new_context( accept_downloads=False, # Should never be needed - bypass_csp=True, # This is needed to enable JavaScript execution on GitHub and others + bypass_csp=get_playwright_bypass_csp(), extra_http_headers=self.headers, ignore_https_errors=True, proxy=proxy, @@ -514,4 +514,3 @@ class browsersteps_live_ui(steppable_browser_interface): pass return (screenshot, xpath_data) - diff --git a/changedetectionio/content_fetchers/base.py b/changedetectionio/content_fetchers/base.py index f4cd459f..079bed19 100644 --- a/changedetectionio/content_fetchers/base.py +++ b/changedetectionio/content_fetchers/base.py @@ -4,6 +4,7 @@ from loguru import logger from pydantic import BaseModel from changedetectionio.content_fetchers import BrowserStepsStepException +from changedetectionio.strtobool import strtobool class FetcherCapabilities(BaseModel): @@ -27,6 +28,16 @@ class FetcherCapabilities(BaseModel): }) +def get_playwright_bypass_csp(): + """Return whether Playwright-compatible browser contexts should bypass CSP. + + Bypassing CSP remains enabled by default for backward compatibility. Some + remote CDP implementations do not support ``Page.setBypassCSP``; operators + can disable the option by setting ``PLAYWRIGHT_BYPASS_CSP=false``. + """ + return strtobool(os.getenv('PLAYWRIGHT_BYPASS_CSP', 'true')) + + def manage_user_agent(headers, current_ua=''): """ Basic setting of user-agent diff --git a/changedetectionio/content_fetchers/playwright.py b/changedetectionio/content_fetchers/playwright.py index 6c5256b4..f20981df 100644 --- a/changedetectionio/content_fetchers/playwright.py +++ b/changedetectionio/content_fetchers/playwright.py @@ -8,7 +8,7 @@ from loguru import logger from changedetectionio.content_fetchers import SCREENSHOT_MAX_HEIGHT_DEFAULT, visualselector_xpath_selectors, \ SCREENSHOT_SIZE_STITCH_THRESHOLD, SCREENSHOT_MAX_TOTAL_HEIGHT, XPATH_ELEMENT_JS, INSTOCK_DATA_JS, FAVICON_FETCHER_JS -from changedetectionio.content_fetchers.base import Fetcher, manage_user_agent +from changedetectionio.content_fetchers.base import Fetcher, get_playwright_bypass_csp, manage_user_agent from changedetectionio.content_fetchers.exceptions import PageUnloadable, Non200ErrorCodeReceived, EmptyReply, ScreenshotUnavailable, \ BrowserStepsStepException @@ -284,7 +284,9 @@ class fetcher(Fetcher): # Use the default one configured in the App.py model that's passed from fetch_site_status.py context = await browser.new_context( accept_downloads=False, # Should never be needed - bypass_csp=True, # This is needed to enable JavaScript execution on GitHub and others + # Enabled by default because sites such as GitHub need it for injected JavaScript. + # Some CDP implementations do not support Page.setBypassCSP, so allow operators to disable it. + bypass_csp=get_playwright_bypass_csp(), extra_http_headers=request_headers, ignore_https_errors=True, proxy=self.proxy, @@ -471,4 +473,3 @@ class PlaywrightFetcherPlugin: playwright_plugin = PlaywrightFetcherPlugin() - diff --git a/changedetectionio/content_fetchers/puppeteer.py b/changedetectionio/content_fetchers/puppeteer.py index 39699645..849c21ed 100644 --- a/changedetectionio/content_fetchers/puppeteer.py +++ b/changedetectionio/content_fetchers/puppeteer.py @@ -10,11 +10,17 @@ from loguru import logger from changedetectionio.content_fetchers import SCREENSHOT_MAX_HEIGHT_DEFAULT, visualselector_xpath_selectors, \ SCREENSHOT_SIZE_STITCH_THRESHOLD, SCREENSHOT_DEFAULT_QUALITY, XPATH_ELEMENT_JS, INSTOCK_DATA_JS, \ SCREENSHOT_MAX_TOTAL_HEIGHT, FAVICON_FETCHER_JS -from changedetectionio.content_fetchers.base import Fetcher, manage_user_agent +from changedetectionio.content_fetchers.base import Fetcher, get_playwright_bypass_csp, manage_user_agent from changedetectionio.content_fetchers.exceptions import PageUnloadable, Non200ErrorCodeReceived, EmptyReply, BrowserFetchTimedOut, \ BrowserConnectError +async def _configure_puppeteer_csp(page): + """Enable CSP bypass without requiring unsupported CDP methods when disabled.""" + if get_playwright_bypass_csp(): + await page.setBypassCSP(True) + + # Bug 3 in Playwright screenshot handling # Some bug where it gives the wrong screenshot size, but making a request with the clip set first seems to solve it @@ -347,7 +353,7 @@ class fetcher(Fetcher): # Attempt to strip 'HeadlessChrome' etc await self.page.setUserAgent(manage_user_agent(headers=request_headers, current_ua=await self.page.evaluate('navigator.userAgent'))) - await self.page.setBypassCSP(True) + await _configure_puppeteer_csp(self.page) if request_headers: await self.page.setExtraHTTPHeaders(request_headers) diff --git a/changedetectionio/tests/unit/test_playwright_bypass_csp.py b/changedetectionio/tests/unit/test_playwright_bypass_csp.py new file mode 100644 index 00000000..4fe7893d --- /dev/null +++ b/changedetectionio/tests/unit/test_playwright_bypass_csp.py @@ -0,0 +1,154 @@ +import asyncio +import sys +from types import ModuleType, SimpleNamespace +from unittest.mock import AsyncMock, Mock + +import pytest + +from changedetectionio.browser_steps.browser_steps import browsersteps_live_ui +from changedetectionio.content_fetchers.base import get_playwright_bypass_csp + + +def test_playwright_bypass_csp_defaults_to_enabled(monkeypatch): + monkeypatch.delenv('PLAYWRIGHT_BYPASS_CSP', raising=False) + + assert get_playwright_bypass_csp() is True + + +@pytest.mark.parametrize( + ('configured_value', 'expected'), + [ + ('true', True), + ('1', True), + ('yes', True), + ('false', False), + ('0', False), + ('no', False), + ], +) +def test_playwright_bypass_csp_parses_boolean_environment_values( + monkeypatch, configured_value, expected +): + monkeypatch.setenv('PLAYWRIGHT_BYPASS_CSP', configured_value) + + assert get_playwright_bypass_csp() is expected + + +@pytest.mark.parametrize('configured_value', ('true', 'false')) +def test_playwright_fetcher_passes_bypass_csp_to_browser_context(monkeypatch, configured_value): + monkeypatch.setenv('PLAYWRIGHT_BYPASS_CSP', configured_value) + + class ContextCreationStopped(Exception): + pass + + browser = SimpleNamespace( + new_context=AsyncMock(side_effect=ContextCreationStopped), + ) + browser_type = SimpleNamespace( + connect_over_cdp=AsyncMock(return_value=browser), + ) + + class AsyncPlaywrightContextManager: + async def __aenter__(self): + return SimpleNamespace(chromium=browser_type) + + async def __aexit__(self, exc_type, exc_value, traceback): + return False + + async_api_module = ModuleType('playwright.async_api') + async_api_module.async_playwright = AsyncPlaywrightContextManager + + errors_module = ModuleType('playwright._impl._errors') + errors_module.TimeoutError = TimeoutError + impl_module = ModuleType('playwright._impl') + impl_module._errors = errors_module + playwright_module = ModuleType('playwright') + playwright_module._impl = impl_module + + monkeypatch.setitem(sys.modules, 'playwright', playwright_module) + monkeypatch.setitem(sys.modules, 'playwright.async_api', async_api_module) + monkeypatch.setitem(sys.modules, 'playwright._impl', impl_module) + monkeypatch.setitem(sys.modules, 'playwright._impl._errors', errors_module) + + from changedetectionio.content_fetchers.playwright import fetcher + + with pytest.raises(ContextCreationStopped): + asyncio.run(fetcher().run(request_headers={}, url='https://example.com')) + + assert browser.new_context.await_args.kwargs['bypass_csp'] is (configured_value == 'true') + + +@pytest.mark.parametrize('configured_value', ('true', 'false')) +def test_browser_steps_passes_bypass_csp_to_browser_context(monkeypatch, configured_value): + monkeypatch.setenv('PLAYWRIGHT_BYPASS_CSP', configured_value) + + page = Mock() + page.wait_for_timeout = AsyncMock() + context = SimpleNamespace(new_page=AsyncMock(return_value=page)) + browser = SimpleNamespace(new_context=AsyncMock(return_value=context)) + browser_steps = browsersteps_live_ui( + playwright_browser=browser, start_url='https://example.com' + ) + + asyncio.run(browser_steps.connect()) + + assert browser.new_context.await_args.kwargs['bypass_csp'] is (configured_value == 'true') + + +@pytest.mark.parametrize('configured_value', ('true', 'false')) +def test_puppeteer_only_sends_set_bypass_csp_when_enabled(monkeypatch, configured_value): + monkeypatch.setenv('PLAYWRIGHT_BYPASS_CSP', configured_value) + + from changedetectionio.content_fetchers.puppeteer import _configure_puppeteer_csp + + page = SimpleNamespace(setBypassCSP=AsyncMock()) + asyncio.run(_configure_puppeteer_csp(page)) + + if configured_value == 'true': + page.setBypassCSP.assert_awaited_once_with(True) + else: + page.setBypassCSP.assert_not_awaited() + + +def test_puppeteer_fetcher_configures_csp_on_created_page(monkeypatch): + from changedetectionio.content_fetchers import puppeteer + + class CSPConfigurationReached(Exception): + pass + + page = SimpleNamespace( + evaluate=AsyncMock(return_value='Mozilla/5.0'), + setUserAgent=AsyncMock(), + ) + browser = SimpleNamespace(newPage=AsyncMock(return_value=page)) + pyppeteer_instance = SimpleNamespace(connect=AsyncMock(return_value=browser)) + + pyppeteer_module = ModuleType('pyppeteer') + pyppeteer_module.Pyppeteer = Mock(return_value=pyppeteer_instance) + stealth_module = ModuleType('pyppeteerstealth') + stealth_module.inject_evasions_into_page = AsyncMock() + monkeypatch.setitem(sys.modules, 'pyppeteer', pyppeteer_module) + monkeypatch.setitem(sys.modules, 'pyppeteerstealth', stealth_module) + + configure_csp = AsyncMock(side_effect=CSPConfigurationReached) + monkeypatch.setattr(puppeteer, '_configure_puppeteer_csp', configure_csp) + + with pytest.raises(CSPConfigurationReached): + asyncio.run( + puppeteer.fetcher().fetch_page( + current_include_filters=None, + empty_pages_are_a_change=False, + fetch_favicon=False, + ignore_status_codes=False, + is_binary=False, + request_body=None, + request_headers={}, + request_method='GET', + screenshot_format=None, + timeout=45, + url='https://example.com', + watch_uuid='test-watch', + ) + ) + + configure_csp.assert_awaited_once_with(page) diff --git a/docker-compose.yml b/docker-compose.yml index d6defee4..00ec49f8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -26,6 +26,8 @@ services: # # Uncomment below and the "sockpuppetbrowser" to use a real Chrome browser (It uses the "playwright" protocol) # - PLAYWRIGHT_DRIVER_URL=ws://browser-sockpuppet-chrome:3000 + # # Disable when the remote CDP implementation does not support `Page.setBypassCSP` - like with Obscura browser. + # - PLAYWRIGHT_BYPASS_CSP=false # # # Alternative WebDriver/selenium URL, do not use "'s or 's! (old, deprecated, does not support screenshots very well, Can't handle custom headers etc) @@ -158,4 +160,3 @@ services: volumes: changedetection-data: - From 5e9a8583e23850af1905628d75724f01c5cafc1f Mon Sep 17 00:00:00 2001 From: TowyTowy <85077986+TowyTowy@users.noreply.github.com> Date: Wed, 26 Aug 2026 10:59:29 +0200 Subject: [PATCH 4/4] Restock detection - fix inverted condition that skipped the OpenGraph availability fallback (#4262) * Restock detection - fix inverted condition that skipped the OpenGraph availability fallback get_itemprop_availability() only dug through OpenGraph properties when price was missing OR when availability was ALREADY found - so on pages that expose price via JSON-LD but stock state only via the OpenGraph commerce tags (), the availability (and currency) was silently dropped. The inner loop already guards each field with 'if not value.get(...)', so the outer gate now matches that intent: dig OpenGraph when any of price/availability/currency is still missing. Co-Authored-By: Claude * Normalise availability after the OpenGraph fallback, not before An availability found via OpenGraph was left raw, so the Facebook commerce spelling 'in stock' never matched the 'instock' test and the product read as out of stock. --------- Co-authored-by: Claude --- .../processors/restock_diff/processor.py | 14 ++++++---- .../tests/unit/test_restock_logic.py | 27 +++++++++++++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/changedetectionio/processors/restock_diff/processor.py b/changedetectionio/processors/restock_diff/processor.py index d09022bd..e428e336 100644 --- a/changedetectionio/processors/restock_diff/processor.py +++ b/changedetectionio/processors/restock_diff/processor.py @@ -364,12 +364,8 @@ def get_itemprop_availability(html_content) -> Restock: if availability_result: value['availability'] = availability_result[0].value - if value.get('availability'): - value['availability'] = re.sub(r'(?i)^(https|http)://schema.org/', '', - value.get('availability').strip(' "\'').lower()) if value.get('availability') else None - # Second, go dig OpenGraph which is something that jsonpath_ng cant do because of the tuples and double-dots (:) - if not value.get('price') or value.get('availability'): + if not value.get('price') or not value.get('availability') or not value.get('currency'): logger.debug("Alternatively digging through OpenGraph properties for restock/price info..") jsonpath_expr = parse('$..properties') @@ -380,6 +376,14 @@ def get_itemprop_availability(html_content) -> Restock: value['availability'] = _search_prop_by_value([match.value], "product:availability") if not value.get('currency'): value['currency'] = _search_prop_by_value([match.value], "price:currency") + + # Normalise after both sources have been tried, otherwise an availability that came from + # OpenGraph stays raw. The OpenGraph vocabulary spells it "in stock" while the in-stock + # matcher looks for "instock", so the spaces have to go too. + if value.get('availability'): + value['availability'] = re.sub(r'(?i)^(https|http)://schema.org/', '', + value.get('availability').strip(' "\'').lower()) + value['availability'] = re.sub(r'\s+', '', value['availability']) logger.trace(f"Processed with Extruct in {time.time()-now:.3f}s") return value diff --git a/changedetectionio/tests/unit/test_restock_logic.py b/changedetectionio/tests/unit/test_restock_logic.py index db8a63ee..2b316d5e 100644 --- a/changedetectionio/tests/unit/test_restock_logic.py +++ b/changedetectionio/tests/unit/test_restock_logic.py @@ -17,5 +17,32 @@ class TestDiffBuilder(unittest.TestCase): assert restock_diff.is_between(number=10, lower=None, upper=11) == True, "Between None and 11" assert not restock_diff.is_between(number=12, lower=None, upper=11) == True, "12 is not between None and 11" + def test_itemprop_availability_opengraph_fallback(self): + """Availability/currency missing from JSON-LD should be filled from OpenGraph + (Facebook commerce 'product:availability' / 'product:price:currency' meta tags).""" + html_content = """ + + + + + + + + +

Some Product

+ """ + + value = restock_diff.get_itemprop_availability(html_content) + assert value.get('price') == 155.55, "price should be found via JSON-LD" + assert value.get('currency') == 'EUR', "currency should be found via OpenGraph fallback" + # Normalised the same way a schema.org value is, so that the in-stock matcher + # (which looks for 'instock') sees it. OpenGraph spells it 'in stock'. + assert value.get('availability') == 'instock', "availability should be found via OpenGraph fallback and normalised" + assert any(s in value.get('availability') for s in ['instock', 'instoreonly']), \ + "a product advertised as available must read as in stock, not out of stock" + if __name__ == '__main__': unittest.main()