{#
    A single watch list <tr>, extracted from watch-overview.html so the same markup can be
    re-rendered on its own and pushed over Socket.IO (realtime row resync) - one renderer,
    so the row can never drift from the server-rendered list.

    Rendered via {% include %} from the watch list loop, which inherits the full context:
      watch, loop, is_checking_now(), queued_uuids, has_proxies, datastore, active_tag_uuid,
      system_default_fetcher, ui_settings, favicons_enabled, fetcher_status_icons,
      processor_descriptions, get_all_tags_for_watch(), any_has_restock_price_processor
#}
                {%- set checking_now = is_checking_now(watch) -%}
                {%- set history_n = watch.history_n -%}
                {%- set favicon = watch.get_favicon_filename() -%}
                {%- set error_texts = watch.compile_error_texts(has_proxies=has_proxies) -%}
                {%- set system_use_url_watchlist = datastore.data['settings']['application']['ui'].get('use_page_title_in_list')  -%}
                {#  Class settings mirrored in changedetectionio/static/js/realtime.js for the frontend #}
{#                    loop.cycle('pure-table-odd', 'pure-table-even'),#}
                {%- set row_classes = [
                    'processor-' ~ watch['processor'],
                    'has-error' if error_texts|length > 2 else '',
                    'paused' if watch.paused is defined and watch.paused != False else '',
                    'unviewed' if watch.has_unviewed else '',
                    'has-restock-info' if watch.has_restock_info else 'no-restock-info',
                    'has-favicon' if favicon else '',
                    'in-stock' if watch.has_restock_info and watch['restock']['in_stock'] else '',
                    'not-in-stock' if watch.has_restock_info and not watch['restock']['in_stock'] else '',
                    'queued' if watch.uuid in queued_uuids else '',
                    'checking-now' if checking_now else '',
                    'notification_muted' if watch.notification_muted else '',
                    'single-history' if history_n == 1 else '',
                    'multiple-history' if history_n >= 2 else '',
                    'use-html-title' if system_use_url_watchlist else 'no-html-title',
                ] -%}
            <tr id="{{ watch.uuid }}" data-watch-uuid="{{ watch.uuid }}" class="{{ row_classes | reject('equalto', '') | join(' ') }}">
                <td class="inline checkbox-uuid" ><div><input name="uuids"  type="checkbox" value="{{ watch.uuid}} " >{# <span class="counter-i">{{ loop.index+pagination.skip }}</span>#}</div></td>
                <td class="inline watch-controls">
                    <div>
                        <a class="ajax-op state-off pause-toggle" data-op="pause" aria-label="{{ _('Pause checks') }}" title="{{ _('Pause checks') }}" href="{{url_for('watchlist.index', op='pause', uuid=watch.uuid, tag=active_tag_uuid)}}"><i data-feather="pause" class="icon icon-pause"></i></a>
                        <a class="ajax-op state-on pause-toggle"  data-op="pause" style="display: none" aria-label="{{ _('UnPause checks') }}" title="{{ _('UnPause checks') }}" href="{{url_for('watchlist.index', op='pause', uuid=watch.uuid, tag=active_tag_uuid)}}"><i data-feather="play" class="icon icon-unpause"></i></a>
                        <a class="ajax-op state-off mute-toggle" data-op="mute" aria-label="{{ _('Mute notification') }}" title="{{ _('Mute notification') }}" href="{{url_for('watchlist.index', op='mute', uuid=watch.uuid, tag=active_tag_uuid)}}"><i data-feather="bell" class="icon icon-mute"></i></a>
                        <a class="ajax-op state-on mute-toggle" data-op="mute"  style="display: none" aria-label="{{ _('UnMute notification') }}" title="{{ _('UnMute notification') }}" href="{{url_for('watchlist.index', op='mute', uuid=watch.uuid, tag=active_tag_uuid)}}"><i data-feather="bell-off" class="icon icon-mute"></i></a>
                    </div>
                </td>

                <td class="title-col inline">
                    <div class="grid-wrapper">
                    {% if 'favicons_enabled' not in ui_settings or ui_settings['favicons_enabled'] %}
                        <div class="favicon">
                            <a target="_blank" rel="noopener" href="{{ watch.link.replace('source:','') }}">
                                {# Intersection Observer lazy loading: store real URL in data-src, load only when visible in viewport #}
                                <img alt="Favicon thumbnail"
                                     class="favicon lazy-favicon"
                                     loading="lazy"
                                     decoding="async"
                                     title="{{ _('Goto web page') }}"
                                     alt="{{ _('Goto web page') }}"
                                     fetchpriority="low"
                                     {% if favicon %}
                                     data-src="{{url_for('static_content', group='favicon', filename=watch.uuid)}}"
                                     {% endif %}
                                     src='data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="7.087" height="7.087" viewBox="0 0 7.087 7.087"%3E%3Ccircle cx="3.543" cy="3.543" r="3.279" stroke="%23e1e1e1" stroke-width="0.45" fill="none" opacity="0.74"/%3E%3C/svg%3E'>
                            </a>
                        </div>
                    {%  endif %}
                        <div class="watch-text-info">
                            {%- if watch['processor'] and watch['processor'] in processor_badge_texts -%}
                                <a href="{{ url_for('watchlist.index', tag=active_tag_uuid, processor=watch['processor']) }}" class="processor-badge processor-badge-{{ watch['processor'] }}{{ ' active' if active_processor == watch['processor'] else '' }}" title="{{ processor_descriptions.get(watch['processor'], watch['processor']) }}">{{ processor_badge_texts[watch['processor']] }}</a>
                            {%- endif -%}
                            <span class="watch-title">
                                {% if system_use_url_watchlist or watch.get('use_page_title_in_list') %}
                                    {{ watch.label }}
                                {% else %}
                                    {{ watch.get('title') or watch.link }}
                                {% endif %}
                                <a class="external" target="_blank" rel="noopener" href="{{ watch.link.replace('source:','') }}">&nbsp;</a>
                            </span>

                            {%- for watch_tag_uuid, watch_tag in datastore.get_all_tags_for_watch(watch['uuid']).items() -%}
                              <a href="{{url_for('watchlist.index', tag=watch_tag_uuid) }}" class="watch-tag-list tag-{{ watch_tag.title|sanitize_tag_class }}">{{ watch_tag.title }}</a>
                            {%- endfor -%}
                            <div class="error-text" style="display:none;">{{ error_texts|safe }}</div>
                            {%- if watch['processor'] == 'text_json_diff'  -%}
                                {%- if watch['has_ldjson_price_data'] and not watch['track_ldjson_price_data']  -%}
                                <div class="ldjson-price-track-offer">Switch to Restock & Price watch mode? <a href="{{url_for('price_data_follower.accept', uuid=watch.uuid)}}" class="pure-button button-xsmall">Yes</a> <a href="{{url_for('price_data_follower.reject', uuid=watch.uuid)}}" class="">No</a></div>
                                {%- endif -%}
                            {%- endif -%}

                        </div>
                    <div class="status-icons">
                            <a class="link-spread" href="{{url_for('ui.form_share_put_watch', uuid=watch.uuid)}}"><img src="{{url_for('static_content', group='images', filename='spread.svg')}}" class="status-icon icon icon-spread" title="{{ _('Create a link to share watch config with others') }}" ></a>
                            {%- set effective_fetcher = watch.get_fetch_backend if watch.get_fetch_backend != "system" else system_default_fetcher -%}
                            {%- if effective_fetcher and ("html_webdriver" in effective_fetcher or "html_" in effective_fetcher or "extra_browser_" in effective_fetcher) -%}
                                {{ effective_fetcher|fetcher_status_icons }}
                            {%- endif -%}
                            {%- if watch.is_pdf  -%}<img class="status-icon" src="{{url_for('static_content', group='images', filename='pdf-icon.svg')}}" alt="Converting PDF to text" >{%- endif -%}
                            {%- if watch.has_browser_steps -%}<img class="status-icon status-browsersteps" src="{{url_for('static_content', group='images', filename='steps.svg')}}" alt="Browser Steps is enabled" >{%- endif -%}
                    </div>
{%- if watch['processor'] == 'restock_diff'  -%}
    {#-  @todo - this could be injected somehow watch.extra_row_info or something -#}
                    <div class="restock-info-wrap">
                            {%- if watch.has_restock_info -%}
                                <span class="restock-label {{'in-stock' if watch['restock']['in_stock'] else 'not-in-stock' }}" title="{{ _('Detecting restock and price') }}">
                                    <!-- maybe some object watch['processor'][restock_diff] or.. -->
                                     {%- if watch['restock']['in_stock']-%}  {{ _('In stock') }} {%- else-%}  {{ _('Not in stock') }} {%- endif -%}
                                </span>
                            {%- endif -%}

                            {%- if watch.get('restock') and watch['restock'].get('price') -%}
                                {%- set restock = watch['restock'] -%}
                                {%- set price = restock.get('price') -%}
                                {%- set currency = restock.get('currency') if restock.get('currency','') else '' -%}

                                {%- if price is not none and (price|string)|regex_search('\d') -%}
                                  <span class="restock-label price" title="{{ _('Price') }}">
                                  {# @todo: make parse_currency/parse_decimal aware of the locale of the actual web page and use that instead changedetectionio/processors/restock_diff/__init__.py #}
                                    {%- if price is number -%}{# It's a number so we can convert it to their locale' #}
                                      {{ price|format_number_locale }} {{ currency }}<!-- as number -->
                                    {%- else -%}{# It's totally fine if it arrives as something else, the website might be something weird in this field #}
                                      {{ price }} {{ currency }}<!-- as string -->
                                    {%- endif -%}
                                  </span>
                                  {%- set price_change_pct = restock.get_price_change_percent() -%}
                                  {%- if price_change_pct is not none -%}
                                    {%- set prev_price = restock.get('last_price') -%}
                                    {%- set prev_disp = (prev_price|format_number_locale ~ ' ' ~ currency) if prev_price is number else prev_price -%}
                                    {%- if price_change_pct < 0 -%}
                                      <span class="price-change down" title="{{ _('Price change since previous price (%(prev)s)', prev=prev_disp) }}">▼ {{ '%g'|format(price_change_pct) }}%</span>
                                    {%- else -%}
                                      <span class="price-change up" title="{{ _('Price change since previous price (%(prev)s)', prev=prev_disp) }}">▲ +{{ '%g'|format(price_change_pct) }}%</span>
                                    {%- endif -%}
                                  {%- endif -%}
                                {%- endif -%}
                            {%- elif not watch.has_restock_info -%}
                                <span class="restock-label error">{{ _('No information') }}</span>
                            {%- endif -%}
                    </div>
{%- endif -%}
                </div>

                </td>
{#
{%- if any_has_restock_price_processor -%}
                <td class="restock-and-price">
                </td>
{%- endif -%}
#}
            {#last_checked becomes fetch-start-time#}
                <td class="last-checked" data-timestamp="{{ watch.last_checked }}" data-fetchduration={{ watch.fetch_time }} data-eta_complete="{{ watch.last_checked+watch.fetch_time }}" data-label="{{ _('Checked') }}">
                    <div class="spinner-wrapper" style="display:none;" >
                        <span class="spinner"></span><span class="status-text">&nbsp;{{ watch['__check_status'] or _('Checking now') }}</span>
                    </div>
                    <span class="innertext">{{watch|format_last_checked_time|safe}}</span>
                </td>
                <td class="last-changed" data-timestamp="{{ watch.last_changed }}" data-label="{{ _('Changed') }}">
                    <span class="innertext">{%- if watch.history_n >=2 and watch.last_changed >0 -%}
                    {{watch.last_changed|format_timestamp_timeago}}
                    {%- else -%}
                    {{ _('Not yet') }}
                    {%- endif -%}
                    </span>
                </td>
                <td class="buttons">
                    <div>
                    {%- set target_attr = ' target="' ~ watch.uuid ~ '"' if datastore.data['settings']['application']['ui'].get('open_diff_in_new_tab') else '' -%}
                    <a href="" class="already-in-queue-button recheck cdio-btn cdio-btn--primary cdio-btn--sm" style="display: none;" disabled="disabled"><i data-feather="clock"></i>{{ _('Queued') }}</a>
                    <a href="{{ url_for('ui.form_watch_checknow', uuid=watch.uuid, tag=request.args.get('tag')) }}" data-op='recheck' class="ajax-op recheck cdio-btn cdio-btn--primary cdio-btn--sm"><i data-feather="refresh-cw"></i>{{ _('Recheck') }}</a>
                    <a href="{{ url_for('ui.ui_edit.edit_page', uuid=watch.uuid, tag=active_tag_uuid)}}#general" class="cdio-btn cdio-btn--primary cdio-btn--sm">{{ _('Edit') }}</a>
                    <a href="{{ url_for('ui.ui_diff.diff_history_page', uuid=watch.uuid)}}" {{target_attr}} class="cdio-btn cdio-btn--primary cdio-btn--sm history-link ai-history-btn" style="display: none;" data-uuid="{{ watch.uuid }}" data-summary-url="{{ url_for('ui.ui_diff.diff_llm_summary', uuid=watch.uuid) }}" data-processor-data-url="{{ url_for('ui.ui_diff.diff_history_page_processor_data', uuid=watch.uuid) }}"><span class="btn-label-history">{{ _('History') }}</span><span class="btn-label-summary">&#x2728; {{ _('Summary') }}</span></a>
                    <a href="{{ url_for('ui.ui_preview.preview_page', uuid=watch.uuid)}}" {{target_attr}} class="cdio-btn cdio-btn--primary cdio-btn--sm preview-link" style="display: none;">{{ _('Preview') }}</a>
                    </div>
                </td>
            </tr>
