(function () {
	'use strict';

	var SAVE_DELAY = 900;
	var RESUME_VISIBLE = 2;
	var state = null;
	var root = null;
	var saveTimer = null;
	var panelSaveRequestId = 0;
	var bound = false;
	var selectedChecklistDate = '';
	var checklistWeekOffset = 0;
	var MAX_CHECKLIST_WEEK_OFFSET = 52;
	var clientBootMs = 0;
	var clockTimer = null;
	var pendingResumePoints = null;
	var resumePointsOffset = 0;
	var floatingTipEl = null;
	var floatingTipTrigger = null;
	var quickLinksEditing = false;
	var quickLinksDraft = [];
	var panelLoadingTimer = null;
	var saveStatusClearTimer = null;
	var editingItems = {
		pendientes: '',
		agenda: '',
		compras: '',
		proveedores: ''
	};
	var editSnapshots = {};
	var editingChecklistKey = '';
	var editChecklistSnapshots = {};
	var unsavedNewItems = {
		pendientes: '',
		agenda: '',
		compras: '',
		proveedores: ''
	};
	var unsavedNewChecklistKey = '';
	var proveedoresSearchQuery = '';
	var proveedoresPage = 1;
	var proveedoresPageSize = 3;
	var proveedoresSearchTimer = null;
	var PANEL_LIST_PAGE_SIZES = [3, 5, 10, 25, 50];
	var panelListPagination = {
		agenda: { page: 1, pageSize: 3, storageKey: 'logistica_panel_agenda_page_size_v1' },
		compras: { page: 1, pageSize: 3, storageKey: 'logistica_panel_compras_page_size_v1' }
	};
	var panelListFilters = {
		agenda: { status: '', priority: '', fecha_requerida: '' },
		compras: { status: '', priority: '', fecha_requerida: '' }
	};
	var QUICK_LINK_EXCLUDED_TABS = ['logistica', 'logistica-configuracion', 'logistica-ayuda', 'logistica-perfil'];
	var pendingAvisoEmailIds = [];
	var avisosShowRead = false;
	var informeFilters = {
		tipo: '',
		status: '',
		proveedor_id: '',
		fecha_desde: '',
		fecha_hasta: '',
		solo_activos: true
	};
	var informeDefaultsReady = false;

	document.addEventListener('logistica:resume-updated', function (event) {
		if (!event.detail || !Array.isArray(event.detail.resume_points)) {
			return;
		}

		if (state) {
			resumePointsOffset = 0;
			mergeResumePoints(event.detail.resume_points);
			return;
		}

		pendingResumePoints = event.detail.resume_points;
	});

	function config() {
		var panel = window.LogisticaUserPanel || {};
		var admin = window.LogisticaAdmin || {};

		return {
			ajaxUrl: panel.ajaxUrl || admin.ajaxUrl || '',
			userPanelNonce: panel.userPanelNonce || admin.userPanelNonce || '',
			navTabs: panel.navTabs || admin.navTabs || {},
			navTabUrls: panel.navTabUrls || admin.navTabUrls || {},
			pendiente_statuses: panel.pendiente_statuses || admin.pendiente_statuses,
			day_types: panel.day_types || admin.day_types,
			priorities: panel.priorities || admin.priorities,
			agenda_statuses: panel.agenda_statuses || admin.agenda_statuses,
			compra_statuses: panel.compra_statuses || admin.compra_statuses,
			checklist_recurrences: panel.checklist_recurrences || admin.checklist_recurrences,
			proveedores_export_url: panel.proveedores_export_url || admin.proveedores_export_url,
			compras_export_url: panel.compras_export_url || admin.compras_export_url,
			holiday_settings: panel.holiday_settings || admin.holiday_settings,
			festivo_dates: panel.festivo_dates || admin.festivo_dates,
			profile_label: panel.profile_label || admin.profile_label,
			profile_tab: panel.profile_tab || admin.profile_tab || 'logistica-perfil'
		};
	}

	function getUserPanelNonce() {
		if (state && state.user_panel_nonce) {
			return state.user_panel_nonce;
		}

		return config().userPanelNonce || '';
	}

	function panelQuery(selector) {
		if (root && typeof root.querySelector === 'function') {
			var match = root.querySelector(selector);
			if (match) {
				return match;
			}
		}

		return document.querySelector(selector);
	}

	function buildResumeUrl(item, tabUrls) {
		var tabSlug = item && item.tab_slug ? item.tab_slug : '';
		var base = (tabUrls && tabUrls[tabSlug]) || '';
		var deepLink = item && item.deep_link ? String(item.deep_link).trim() : '';

		if (!base) {
			return '';
		}

		if (!deepLink) {
			return base;
		}

		if (deepLink.charAt(0) !== '#') {
			deepLink = '#' + deepLink;
		}

		try {
			var parsed = new URL(base, window.location.href);
			parsed.hash = deepLink;
			return parsed.pathname + parsed.search + parsed.hash;
		} catch (error) {
			return base + deepLink;
		}
	}

	function navigateToResumePoint(item) {
		var tabUrls = config().navTabUrls || {};
		var tabSlug = item && item.tab_slug ? item.tab_slug : '';
		var resumeUrl = buildResumeUrl(item, tabUrls);

		if (!resumeUrl && tabSlug) {
			try {
				var fallback = new URL(window.location.href);
				fallback.searchParams.set('tab', tabSlug);
				fallback.hash = '';
				resumeUrl = fallback.pathname + fallback.search;
			} catch (error) {
				resumeUrl = '?tab=' + encodeURIComponent(tabSlug);
			}
		}

		if (!resumeUrl) {
			return;
		}

		var app = document.querySelector('[data-logistica-app]');

		if (!app) {
			window.location.href = resumeUrl;
			return;
		}

		try {
			var parsed = new URL(resumeUrl, window.location.href);
			var tab = parsed.searchParams.get('tab') || tabSlug;
			var hash = parsed.hash || '';
			var tabLink = tab ? app.querySelector('[data-logistica-tab="' + tab + '"]') : null;
			var tabPanel = tab ? app.querySelector('[data-tab-panel="' + tab + '"]') : null;

			if (tabLink) {
				tabLink.click();
			} else if (tabPanel) {
				window.location.href = resumeUrl;
				return;
			} else {
				window.location.href = resumeUrl;
				return;
			}

			if (!hash) {
				return;
			}

			[200, 500, 900, 1400].forEach(function (delay) {
				window.setTimeout(function () {
					var target = document.querySelector(hash);

					if (!target) {
						return;
					}

					if (window.LogisticaUserPanelNav && typeof window.LogisticaUserPanelNav.activateForHash === 'function') {
						window.LogisticaUserPanelNav.activateForHash(hash, { updateHash: false, scroll: false });
					}

					target.scrollIntoView({ behavior: 'smooth', block: 'start' });

					if (hash.indexOf('#logistica-calc-') === 0) {
						var calcSlug = hash.replace('#logistica-calc-', '');
						var calcLink = app.querySelector('[data-calc-nav="' + calcSlug + '"]');

						if (calcLink) {
							calcLink.click();
						}
					}
				}, delay);
			});
		} catch (error) {
			window.location.href = resumeUrl;
		}
	}

	function enrichBootstrap(data) {
		if (!data) {
			return null;
		}

		var cfg = config();
		[
			'pendiente_statuses',
			'day_types',
			'priorities',
			'agenda_statuses',
			'compra_statuses',
			'checklist_recurrences',
			'proveedores_export_url',
			'compras_export_url',
			'holiday_settings',
			'festivo_dates'
		].forEach(function (key) {
			if (!data[key] && cfg[key]) {
				data[key] = cfg[key];
			}
		});

		return data;
	}

	function escapeHtml(text) {
		var div = document.createElement('div');
		div.textContent = text == null ? '' : String(text);
		return div.innerHTML;
	}

	function readBootstrap(container) {
		var scope = container && typeof container.querySelector === 'function' ? container : document;
		var node = scope.querySelector ? scope.querySelector('#logistica-user-panel-bootstrap') : null;

		if (!node) {
			node = document.getElementById('logistica-user-panel-bootstrap');
		}

		if (!node) {
			return null;
		}

		try {
			return enrichBootstrap(JSON.parse(node.textContent || '{}'));
		} catch (error) {
			return null;
		}
	}

	function generateId(prefix) {
		return (prefix || 'item') + '_' + Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
	}

	function applyClockContext(data) {
		if (!data || !state) {
			return;
		}

		['today', 'today_label', 'today_weekday', 'today_time', 'now_datetime', 'now_timestamp', 'timezone', 'timezone_label', 'week_days'].forEach(function (key) {
			if (data[key] !== undefined) {
				state[key] = data[key];
			}
		});

		if (data.now_timestamp) {
			clientBootMs = Date.now();
		}
	}

	function colombiaNowMs() {
		if (!state || !state.now_timestamp) {
			return Date.now();
		}

		return (state.now_timestamp * 1000) + (Date.now() - clientBootMs);
	}

	function formatPanelSqlDateTime(ms) {
		if (ms === undefined || ms === null) {
			ms = colombiaNowMs();
		}

		var partsMap = {};
		new Intl.DateTimeFormat('en-GB', {
			timeZone: 'America/Bogota',
			year: 'numeric',
			month: '2-digit',
			day: '2-digit',
			hour: '2-digit',
			minute: '2-digit',
			second: '2-digit',
			hour12: false
		}).formatToParts(new Date(ms)).forEach(function (part) {
			if (part.type !== 'literal') {
				partsMap[part.type] = part.value;
			}
		});

		return partsMap.year + '-' + partsMap.month + '-' + partsMap.day + ' ' +
			partsMap.hour + ':' + partsMap.minute + ':' + partsMap.second;
	}

	function nowSql() {
		return formatPanelSqlDateTime(colombiaNowMs());
	}

	function parsePanelDateTime(value) {
		if (!value) {
			return null;
		}

		var normalized = String(value).trim();
		if (!normalized) {
			return null;
		}

		var match = normalized.match(/^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2})(?::(\d{2}))?)?/);
		if (!match) {
			return null;
		}

		var iso = match[1] + '-' + match[2] + '-' + match[3];
		if (match[4] !== undefined) {
			iso += 'T' + match[4] + ':' + match[5] + ':' + (match[6] || '00') + '-05:00';
		} else {
			iso += 'T00:00:00-05:00';
		}

		var date = new Date(iso);
		return Number.isNaN(date.getTime()) ? null : date;
	}

	function formatColombiaTime(dateMs) {
		return new Intl.DateTimeFormat('es-CO', {
			timeZone: 'America/Bogota',
			hour: '2-digit',
			minute: '2-digit',
			hour12: true
		}).format(new Date(dateMs));
	}

	function formatColombiaTimeHms(dateMs) {
		if (dateMs === undefined || dateMs === null) {
			dateMs = colombiaNowMs();
		}

		var parts = {};
		new Intl.DateTimeFormat('en-GB', {
			timeZone: 'America/Bogota',
			hour: '2-digit',
			minute: '2-digit',
			second: '2-digit',
			hour12: false
		}).formatToParts(new Date(dateMs)).forEach(function (part) {
			if (part.type !== 'literal') {
				parts[part.type] = part.value;
			}
		});

		return parts.hour + ':' + parts.minute + ':' + parts.second;
	}

	function formatColombiaDateTime(value) {
		if (!value) {
			return '—';
		}

		var date = parsePanelDateTime(value);
		if (!date) {
			return String(value).trim();
		}

		return new Intl.DateTimeFormat('es-CO', {
			timeZone: 'America/Bogota',
			day: '2-digit',
			month: 'short',
			year: 'numeric',
			hour: '2-digit',
			minute: '2-digit',
			hour12: true
		}).format(date);
	}

	function updateClockDisplay() {
		if (!root) {
			return;
		}

		var clock = root.querySelector('[data-user-panel-clock]');
		if (!clock) {
			return;
		}

		var timeLabel = formatColombiaTime(colombiaNowMs());
		var weekday = state.today_weekday || '';
		var dateLabel = state.today_label || '';

		clock.innerHTML =
			'<strong data-user-panel-clock-time>' + escapeHtml(timeLabel) + '</strong>' +
			'<span data-user-panel-clock-date>' + escapeHtml(weekday) + (dateLabel ? ' · ' + dateLabel : '') + '</span>' +
			'<em>' + escapeHtml(state.timezone_label || 'Colombia') + '</em>';
	}

	function startClock() {
		if (clockTimer) {
			clearInterval(clockTimer);
		}

		updateClockDisplay();
		clockTimer = setInterval(updateClockDisplay, 30000);
	}

	function formatDuration(minutes) {
		minutes = Math.max(0, Math.round(parseInt(minutes, 10) || 0));
		if (minutes <= 0) {
			return '—';
		}
		if (minutes >= 60) {
			var h = Math.floor(minutes / 60);
			var m = minutes % 60;
			return h + ' h ' + m + ' min';
		}
		return minutes + ' min';
	}

	function formatDurationSeconds(seconds) {
		seconds = Math.max(0, Math.round(parseInt(seconds, 10) || 0));
		if (seconds <= 0) {
			return '0 min';
		}
		if (seconds < 60) {
			return seconds + ' s';
		}
		return formatDuration(Math.round(seconds / 60));
	}

	function secondsBetweenSql(startSql, endSql) {
		var start = parsePanelDateTime(startSql);
		var end = parsePanelDateTime(endSql || nowSql());
		if (!start || !end) {
			return 0;
		}
		return Math.max(0, Math.floor((end.getTime() - start.getTime()) / 1000));
	}

	function secondsOverlapSql(startSql, endSql, rangeStartSql, rangeEndSql) {
		var start = parsePanelDateTime(startSql);
		var end = parsePanelDateTime(endSql || nowSql());
		var rangeStart = parsePanelDateTime(rangeStartSql);
		var rangeEnd = parsePanelDateTime(rangeEndSql || nowSql());
		if (!start || !end || !rangeStart || !rangeEnd) {
			return 0;
		}
		var from = Math.max(start.getTime(), rangeStart.getTime());
		var to = Math.min(end.getTime(), rangeEnd.getTime());
		return Math.max(0, Math.floor((to - from) / 1000));
	}

	function ensureInformeDefaultFilters() {
		if (informeDefaultsReady || !state || !state.today) {
			return;
		}
		informeFilters.fecha_desde = state.today;
		informeFilters.fecha_hasta = state.today;
		informeFilters.solo_activos = true;
		informeDefaultsReady = true;
	}

	function isInformeDayView() {
		return !!(informeFilters.solo_activos &&
			state && state.today &&
			informeFilters.fecha_desde === state.today &&
			informeFilters.fecha_hasta === state.today &&
			!informeFilters.tipo &&
			!informeFilters.status &&
			!informeFilters.proveedor_id);
	}

	function getInformeStatusSecondsMap(item) {
		var fromYmd = informeFilters.fecha_desde || '';
		var toYmd = informeFilters.fecha_hasta || '';
		if (!fromYmd && !toYmd) {
			return getStatusSecondsMap(item, true);
		}

		ensureGestionFields(item, item && item.status ? item.status : 'pendiente');
		var map = {};
		var rangeStart = (fromYmd || '1970-01-01') + ' 00:00:00';
		var rangeEnd = toYmd ? (toYmd + ' 23:59:59') : nowSql();
		var now = nowSql();

		(item.status_timeline || []).forEach(function (seg) {
			if (!seg || !seg.status) {
				return;
			}
			if (isGestionTerminalStatus(seg.status)) {
				map[seg.status] = map[seg.status] || 0;
				return;
			}
			var segEnd = seg.ended_at || now;
			var seconds = secondsOverlapSql(seg.started_at, segEnd, rangeStart, rangeEnd);
			map[seg.status] = (map[seg.status] || 0) + Math.max(0, seconds);
		});

		return map;
	}

	function getInformeGestionTotalSeconds(item) {
		var map = getInformeStatusSecondsMap(item);
		var total = 0;
		Object.keys(map).forEach(function (key) {
			if (isGestionTerminalStatus(key)) {
				return;
			}
			total += map[key];
		});
		return total;
	}

	function ensurePanelAvisos() {
		if (!state.panel.avisos || !Array.isArray(state.panel.avisos)) {
			state.panel.avisos = [];
		}
		return state.panel.avisos;
	}

	function ensureCompraGestionFields(item) {
		return ensureGestionFields(item, 'pendiente');
	}

	function ensureAgendaGestionFields(item) {
		if (!item) {
			return item;
		}
		if (!item.status) {
			item.status = item.done ? 'completado' : 'pendiente';
		}
		item.done = isAgendaComplete(item);
		return ensureGestionFields(item, item.status || 'pendiente');
	}

	function isGestionTerminalStatus(status) {
		return status === 'completado' || status === 'recibido';
	}

	function freezeOpenTerminalTimeline(item) {
		if (!item || !Array.isArray(item.status_timeline)) {
			return;
		}

		item.status_timeline.forEach(function (seg) {
			if (!seg || !isGestionTerminalStatus(seg.status)) {
				return;
			}

			// En Completado / Recibido no se acumula tiempo de gestión.
			seg.ended_at = seg.started_at || seg.ended_at || nowSql();
			seg.seconds = 0;
		});
	}

	function ensureGestionFields(item, defaultStatus) {
		if (!item) {
			return item;
		}

		var now = nowSql();
		if (!item.created_at) {
			item.created_at = item.updated_at || now;
		}
		if (!item.gestion_started_at) {
			item.gestion_started_at = item.created_at || now;
		}
		if (!Array.isArray(item.novedades)) {
			item.novedades = [];
		}
		if (!Array.isArray(item.status_timeline) || !item.status_timeline.length) {
			var initialStatus = item.status || defaultStatus || 'pendiente';
			var terminal = isGestionTerminalStatus(initialStatus);
			item.status_timeline = [{
				status: initialStatus,
				started_at: item.gestion_started_at,
				ended_at: terminal ? item.gestion_started_at : '',
				seconds: 0
			}];
		}

		freezeOpenTerminalTimeline(item);
		return item;
	}

	function recordCompraStatusChange(item, previousStatus, nextStatus, atSql) {
		recordStatusChange(item, previousStatus, nextStatus, atSql);
	}

	function recordStatusChange(item, previousStatus, nextStatus, atSql) {
		ensureGestionFields(item, nextStatus || previousStatus || 'pendiente');
		previousStatus = previousStatus || '';
		nextStatus = nextStatus || item.status || 'pendiente';
		atSql = atSql || nowSql();

		if (previousStatus === nextStatus) {
			return;
		}

		var timeline = item.status_timeline;
		var open = timeline.length ? timeline[timeline.length - 1] : null;
		if (open && !open.ended_at) {
			open.ended_at = atSql;
			open.seconds = secondsBetweenSql(open.started_at, open.ended_at);
		}

		var terminal = isGestionTerminalStatus(nextStatus);
		timeline.push({
			status: nextStatus,
			started_at: atSql,
			ended_at: terminal ? atSql : '',
			seconds: 0
		});
	}

	function getCompraStatusSecondsMap(item, live) {
		return getStatusSecondsMap(item, live);
	}

	function getStatusSecondsMap(item, live) {
		ensureGestionFields(item, item && item.status ? item.status : 'pendiente');
		var map = {};
		var now = nowSql();

		(item.status_timeline || []).forEach(function (seg) {
			if (!seg || !seg.status) {
				return;
			}
			var seconds = parseInt(seg.seconds, 10) || 0;
			if (!seg.ended_at && live !== false && !isGestionTerminalStatus(seg.status)) {
				seconds = secondsBetweenSql(seg.started_at, now);
			}
			if (isGestionTerminalStatus(seg.status)) {
				seconds = 0;
			}
			map[seg.status] = (map[seg.status] || 0) + Math.max(0, seconds);
		});

		return map;
	}

	function getCompraGestionTotalSeconds(item) {
		return getGestionTotalSeconds(item);
	}

	function getGestionTotalSeconds(item) {
		var map = getStatusSecondsMap(item, true);
		var total = 0;
		Object.keys(map).forEach(function (key) {
			if (isGestionTerminalStatus(key)) {
				return;
			}
			total += map[key];
		});
		return total;
	}

	function formatCompliancePercent(value) {
		if (value === null || value === undefined || isNaN(value)) {
			return '—';
		}
		return Math.round(value) + '%';
	}

	function addDaysYmd(ymd, days) {
		if (!ymd) {
			return '';
		}

		var parts = String(ymd).split('-');
		if (parts.length !== 3) {
			return ymd;
		}

		var d = new Date(parseInt(parts[0], 10), parseInt(parts[1], 10) - 1, parseInt(parts[2], 10), 12, 0, 0);
		d.setDate(d.getDate() + days);
		var month = String(d.getMonth() + 1);
		var day = String(d.getDate());
		if (month.length < 2) {
			month = '0' + month;
		}
		if (day.length < 2) {
			day = '0' + day;
		}
		return d.getFullYear() + '-' + month + '-' + day;
	}

	function getMondayForWeekOffset(offset) {
		offset = offset || 0;
		if (!state || !state.today) {
			return '';
		}

		var parts = String(state.today).split('-');
		var d = new Date(parseInt(parts[0], 10), parseInt(parts[1], 10) - 1, parseInt(parts[2], 10), 12, 0, 0);
		var dow = d.getDay();
		var toMonday = dow === 0 ? -6 : 1 - dow;
		d.setDate(d.getDate() + toMonday + (offset * 7));
		var month = String(d.getMonth() + 1);
		var day = String(d.getDate());
		if (month.length < 2) {
			month = '0' + month;
		}
		if (day.length < 2) {
			day = '0' + day;
		}
		return d.getFullYear() + '-' + month + '-' + day;
	}

	var checklistWeekdayInitials = ['L', 'M', 'X', 'J', 'V', 'S', 'D'];
	var checklistWeekdayLabels = ['Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado', 'Domingo'];

	function buildWeekDays(offset) {
		offset = offset || 0;
		var monday = getMondayForWeekOffset(offset);
		var days = [];
		var baseLabels = state && Array.isArray(state.week_days) ? state.week_days : [];

		for (var i = 0; i < 7; i++) {
			var date = addDaysYmd(monday, i);
			var base = baseLabels[i] || {};
			var dayLabel = base.label || checklistWeekdayLabels[i] || date;
			days.push({
				date: date,
				label: dayLabel,
				weekday_label: dayLabel,
				weekday_initial: base.weekday_initial || checklistWeekdayInitials[i] || '',
				short: formatShortDate(date),
				is_today: state && date === state.today
			});
		}

		return days;
	}

	function isChecklistHistoryWeek() {
		return checklistWeekOffset < 0;
	}

	function isChecklistFutureWeek() {
		return checklistWeekOffset > 0;
	}

	function isChecklistReadOnlyWeek() {
		return checklistWeekOffset !== 0;
	}

	function isChecklistDayTypeEditable() {
		return !isChecklistHistoryWeek();
	}

	function weekdayIndexYmd(date) {
		if (!date) {
			return 0;
		}

		var parts = String(date).split('-');
		if (parts.length !== 3) {
			return 0;
		}

		var d = new Date(parseInt(parts[0], 10), parseInt(parts[1], 10) - 1, parseInt(parts[2], 10), 12, 0, 0);
		var dow = d.getDay();

		return dow === 0 ? 6 : dow - 1;
	}

	function cloneChecklistItem(item) {
		var copy = {};

		Object.keys(item || {}).forEach(function (key) {
			copy[key] = item[key];
		});

		return copy;
	}

	function isNonWorkingDayType(dayType) {
		return dayType === 'festivo' || dayType === 'libre' || dayType === 'vacaciones' || dayType === 'permisos';
	}

	function getNonWorkingDayViewConfig(dayType) {
		var label = labelMap(state.day_types, dayType) || 'No laborable';
		var configs = {
			festivo: {
				title: label,
				description: 'Festivo o domingo. No aplica lista de chequeo ni actividades programadas.',
				icon: 'dashicons-star-filled'
			},
			libre: {
				title: label,
				description: 'Día libre personal. Sin actividades de chequeo en este día.',
				icon: 'dashicons-heart'
			},
			vacaciones: {
				title: label,
				description: 'Periodo de vacaciones. El checklist queda suspendido este día.',
				icon: 'dashicons-location-alt'
			},
			permisos: {
				title: label,
				description: 'Día con permiso o licencia. No se registran actividades de chequeo.',
				icon: 'dashicons-id-alt'
			}
		};

		return configs[dayType] || {
			title: label,
			description: 'Día no laborable. Sin actividades de chequeo.',
			icon: 'dashicons-dismiss'
		};
	}

	function renderNonWorkingDayView(dayType) {
		var config = getNonWorkingDayViewConfig(dayType);
		var modifier = dayType ? ' logistica-user-panel__day-off--' + escapeHtml(dayType) : '';

		return (
			'<div class="logistica-user-panel__day-off' + modifier + '" role="status">' +
				'<div class="logistica-user-panel__day-off-icon" aria-hidden="true">' +
					'<span class="dashicons ' + escapeHtml(config.icon) + '"></span>' +
				'</div>' +
				'<div class="logistica-user-panel__day-off-body">' +
					'<strong>' + escapeHtml(config.title) + '</strong>' +
					'<p>' + escapeHtml(config.description) + '</p>' +
				'</div>' +
			'</div>'
		);
	}

	function getChecklistItemsForDisplay(dayDate, dayData) {
		if (isNonWorkingDayType(resolveDayType(dayDate, dayData || {}))) {
			return [];
		}

		return (dayData && Array.isArray(dayData.items)) ? dayData.items : [];
	}

	function getAutomaticDayType(date) {
		if (!date) {
			return '';
		}

		var settings = state && state.holiday_settings ? state.holiday_settings : {};
		if (settings.auto_sundays !== false && weekdayIndexYmd(date) === 6) {
			return 'festivo';
		}

		var festivoDates = state && state.festivo_dates ? state.festivo_dates : {};
		if (festivoDates[date]) {
			return 'festivo';
		}

		return '';
	}

	function resolveDayType(date, day) {
		day = day || {};

		if (day.day_type_manual) {
			return day.day_type || '';
		}

		var stored = day.day_type || '';
		if (stored) {
			return stored;
		}

		return getAutomaticDayType(date) || '';
	}

	function applyAutomaticDayTypes(days, weekDays) {
		days = days || {};
		(weekDays || []).forEach(function (day) {
			if (!days[day.date]) {
				days[day.date] = { day_type: '', day_type_manual: false, items: [] };
			}

			days[day.date].day_type = resolveDayType(day.date, days[day.date]);
		});

		return days;
	}

	function collectRepetitiveTemplates(liveDays) {
		var templates = {};

		Object.keys(liveDays || {}).forEach(function (date) {
			var day = liveDays[date];
			if (!day || !Array.isArray(day.items)) {
				return;
			}

			day.items.forEach(function (item) {
				if (!item || (item.recurrence || '') !== 'repetitivo' || item.linked) {
					return;
				}

				var seriesId = item.series_id || item.id;
				if (!seriesId) {
					return;
				}

				if (!templates[seriesId] || date > templates[seriesId].source_date) {
					templates[seriesId] = {
						series_id: seriesId,
						title: item.title || 'Sin actividad',
						duration_minutes: item.duration_minutes || 0,
						priority: item.priority || 'media',
						weekday: weekdayIndexYmd(date),
						source_date: date
					};
				}
			});
		});

		return templates;
	}

	function getPendingDailyItemsFromToday(liveDays) {
		var today = state && state.today ? state.today : '';
		var todayData = (liveDays || {})[today] || { items: [] };

		return (todayData.items || []).filter(function (item) {
			return item &&
				(item.recurrence || 'diario') === 'diario' &&
				!item.done &&
				!item.linked;
		}).map(cloneChecklistItem);
	}

	function dayHasChecklistItemId(day, itemId) {
		if (!day || !itemId || !Array.isArray(day.items)) {
			return false;
		}

		return day.items.some(function (item) {
			return item && item.id === itemId;
		});
	}

	function appendProjectedDailyCarry(days, targetDate, pendingDaily, originDate) {
		if (!days[targetDate] || !pendingDaily.length || isNonWorkingDayType(days[targetDate].day_type || '')) {
			return;
		}

		pendingDaily.forEach(function (item) {
			if (dayHasChecklistItemId(days[targetDate], item.id)) {
				return;
			}

			var projected = cloneChecklistItem(item);
			projected.carried_from = projected.carried_from || originDate;
			projected.preview = true;
			days[targetDate].items.push(projected);
		});
	}

	function appendProjectedRepetitiveItems(days, weekDays, templates) {
		weekDays.forEach(function (day) {
			var weekday = weekdayIndexYmd(day.date);

			Object.keys(templates).forEach(function (seriesId) {
				var template = templates[seriesId];
				if (template.weekday !== weekday) {
					return;
				}

				if (dayHasChecklistItemId(days[day.date], seriesId)) {
					return;
				}

				var exists = (days[day.date].items || []).some(function (item) {
					return item && (item.series_id || item.id) === seriesId;
				});
				if (exists) {
					return;
				}

				days[day.date].items.push({
					id: 'preview_rep_' + seriesId + '_' + day.date,
					series_id: seriesId,
					title: template.title,
					duration_minutes: template.duration_minutes,
					priority: template.priority,
					recurrence: 'repetitivo',
					done: false,
					carried_from: '',
					preview: true
				});
			});
		});
	}

	function buildProjectedChecklistDays(weekDays, liveDays, includeStoredFutureItems) {
		var days = {};
		var today = state && state.today ? state.today : '';
		var templates = collectRepetitiveTemplates(liveDays);
		var pendingDaily = getPendingDailyItemsFromToday(liveDays);

		weekDays.forEach(function (day) {
			var liveDay = liveDays[day.date] || {};
			days[day.date] = {
				day_type: resolveDayType(day.date, liveDay),
				day_type_manual: !!liveDay.day_type_manual,
				items: []
			};
		});

		if (includeStoredFutureItems) {
			weekDays.forEach(function (day) {
				var liveDay = liveDays[day.date];
				if (!liveDay || !Array.isArray(liveDay.items)) {
					return;
				}

				liveDay.items.forEach(function (item) {
					if (!item || item.linked) {
						return;
					}

					var recurrence = item.recurrence || 'diario';
					if (recurrence === 'repetitivo') {
						return;
					}

					if (recurrence === 'unico' && item.done) {
						return;
					}

					if (recurrence === 'diario' && day.date < today) {
						return;
					}

					if (!dayHasChecklistItemId(days[day.date], item.id)) {
						days[day.date].items.push(cloneChecklistItem(item));
					}
				});
			});
		}

		appendProjectedRepetitiveItems(days, weekDays, templates);

		weekDays.forEach(function (day) {
			if (day.date <= today) {
				return;
			}

			appendProjectedDailyCarry(days, day.date, pendingDaily, today);
		});

		return mergeLinkedItemsIntoChecklistDays(days, weekDays);
	}

	function enrichCurrentWeekFutureDays(days, weekDays, liveDays) {
		var today = state && state.today ? state.today : '';
		var pendingDaily = getPendingDailyItemsFromToday(liveDays);

		weekDays.forEach(function (day) {
			if (day.date <= today) {
				return;
			}

			appendProjectedDailyCarry(days, day.date, pendingDaily, today);
		});

		return days;
	}

	function getChecklistDaysForView() {
		var weekDays = buildWeekDays(checklistWeekOffset);
		var liveDays = (state.panel && state.panel.checklist_days) ? state.panel.checklist_days : {};
		var days = {};

		if (isChecklistFutureWeek()) {
			return applyAutomaticDayTypes(buildProjectedChecklistDays(weekDays, liveDays, true), weekDays);
		}

		if (!isChecklistHistoryWeek()) {
			days = mergeLinkedItemsIntoChecklistDays(liveDays, weekDays);
			days = enrichCurrentWeekFutureDays(days, weekDays, liveDays);
			return applyAutomaticDayTypes(days, weekDays);
		}

		var monday = getMondayForWeekOffset(checklistWeekOffset);
		var history = (state.panel && state.panel.checklist_week_history) ? state.panel.checklist_week_history : {};
		var archived = history[monday] && history[monday].days ? history[monday].days : null;

		weekDays.forEach(function (day) {
			if (archived && archived[day.date]) {
				days[day.date] = archived[day.date];
			} else if (liveDays[day.date]) {
				days[day.date] = liveDays[day.date];
			} else {
				days[day.date] = { day_type: '', items: [] };
			}
		});

		return mergeLinkedItemsIntoChecklistDays(days, weekDays);
	}

	function parseLinkedChecklistId(id) {
		if (!id) {
			return null;
		}

		if (id.indexOf('link_agenda_') === 0) {
			return { section: 'agenda', sourceId: id.slice('link_agenda_'.length) };
		}

		if (id.indexOf('link_compra_') === 0) {
			return { section: 'compras', sourceId: id.slice('link_compra_'.length) };
		}

		return null;
	}

	function buildLinkedChecklistItemFromAgenda(agendaItem) {
		return {
			id: 'link_agenda_' + agendaItem.id,
			source_section: 'agenda',
			source_id: agendaItem.id,
			title: agendaItem.title || 'Actividad',
			duration_minutes: 0,
			priority: agendaItem.priority || 'media',
			recurrence: 'unico',
			done: isAgendaComplete(agendaItem),
			carried_from: '',
			last_reset_week: '',
			linked: true,
			link_label: 'Agenda'
		};
	}

	function buildLinkedChecklistItemFromCompra(compraItem) {
		return {
			id: 'link_compra_' + compraItem.id,
			source_section: 'compras',
			source_id: compraItem.id,
			title: compraProductoLabel(compraItem),
			duration_minutes: 0,
			priority: compraItem.priority || 'media',
			recurrence: 'unico',
			done: compraItem.status === 'recibido',
			carried_from: '',
			last_reset_week: '',
			linked: true,
			link_label: 'Compra'
		};
	}

	function getLinkedChecklistItemsForDate(date) {
		if (!date || !state.panel) {
			return [];
		}

		var linked = [];

		(state.panel.agenda || []).forEach(function (item) {
			if (item && item.date === date && item.id) {
				linked.push(buildLinkedChecklistItemFromAgenda(item));
			}
		});

		(state.panel.compras || []).forEach(function (item) {
			if (item && item.fecha_requerida === date && item.id) {
				linked.push(buildLinkedChecklistItemFromCompra(item));
			}
		});

		return linked;
	}

	function mergeLinkedItemsIntoChecklistDays(days, weekDays) {
		days = days || {};
		var merged = {};
		var weekDates = (weekDays || []).map(function (day) {
			return day.date;
		});

		Object.keys(days).forEach(function (date) {
			var day = days[date];
			merged[date] = {
				day_type: day && day.day_type ? day.day_type : '',
				day_type_manual: !!(day && day.day_type_manual),
				items: Array.isArray(day && day.items) ? day.items.slice() : []
			};
		});

		weekDates.forEach(function (date) {
			if (!merged[date]) {
				merged[date] = { day_type: '', day_type_manual: false, items: [] };
			}

			var existingIds = {};
			merged[date].items.forEach(function (item) {
				if (item && item.id) {
					existingIds[item.id] = true;
				}
			});

			getLinkedChecklistItemsForDate(date).forEach(function (item) {
				if (isNonWorkingDayType(resolveDayType(date, merged[date]))) {
					return;
				}

				if (!existingIds[item.id]) {
					merged[date].items.push(item);
					existingIds[item.id] = true;
				}
			});
		});

		return merged;
	}

	function findLinkedChecklistItem(date, id) {
		var meta = parseLinkedChecklistId(id);
		if (!meta) {
			return null;
		}

		var source = findListItem(meta.section, meta.sourceId);
		if (!source) {
			return null;
		}

		var sourceDate = meta.section === 'agenda' ? source.date : source.fecha_requerida;
		if (sourceDate !== date) {
			return null;
		}

		return meta.section === 'agenda'
			? buildLinkedChecklistItemFromAgenda(source)
			: buildLinkedChecklistItemFromCompra(source);
	}

	function shiftSelectedDateForWeekOffset(newOffset) {
		var currentWeek = buildWeekDays(checklistWeekOffset);
		var newWeek = buildWeekDays(newOffset);
		var selected = getSelectedChecklistDate();
		var idx = 0;

		for (var i = 0; i < currentWeek.length; i++) {
			if (currentWeek[i].date === selected) {
				idx = i;
				break;
			}
		}

		selectedChecklistDate = newWeek[idx] ? newWeek[idx].date : (newWeek[0] ? newWeek[0].date : selected);
	}

	function updateChecklistToolbar() {
		if (!root) {
			return;
		}

		var addBtn = root.querySelector('[data-user-panel-add-checklist]');
		if (!addBtn) {
			return;
		}

		if (isChecklistReadOnlyWeek()) {
			addBtn.setAttribute('hidden', 'hidden');
			addBtn.setAttribute('aria-hidden', 'true');
			return;
		}

		var selectedDate = getSelectedChecklistDate();
		var selectedDay = state && state.panel && state.panel.checklist_days
			? (state.panel.checklist_days[selectedDate] || {})
			: {};
		if (isNonWorkingDayType(resolveDayType(selectedDate, selectedDay))) {
			addBtn.setAttribute('hidden', 'hidden');
			addBtn.setAttribute('aria-hidden', 'true');
			return;
		}

		addBtn.removeAttribute('hidden');
		addBtn.setAttribute('aria-hidden', 'false');
	}

	function labelMap(map, key) {
		return map && map[key] ? map[key] : key;
	}

	function badgeClass(prefix, value) {
		return prefix + ' logistica-user-panel__badge--' + escapeHtml(value || 'default');
	}

	function isListSection(section) {
		return section === 'pendientes' || section === 'agenda' || section === 'compras' || section === 'proveedores';
	}

	function isAgendaComplete(item) {
		if (!item) {
			return false;
		}
		if (item.status) {
			return item.status === 'completado';
		}
		return !!item.done;
	}

	function isSectionItemComplete(section, item) {
		if (!item) {
			return false;
		}

		if (section === 'agenda') {
			return isAgendaComplete(item);
		}

		if (section === 'compras') {
			return item.status === 'recibido';
		}

		if (section === 'pendientes') {
			return item.status === 'terminado';
		}

		return false;
	}

	function isEditingItem(section, id) {
		return editingItems[section] === id;
	}

	function rowStatusClass(complete, editing) {
		var cls = 'logistica-user-panel__row';
		if (editing) {
			return cls + ' is-editing';
		}
		if (complete) {
			return cls + ' is-complete';
		}
		return cls + ' is-pending';
	}

	function orderListItemsForDisplay(section, items) {
		if (!Array.isArray(items) || !items.length) {
			return items || [];
		}

		items = items.filter(function (item) {
			if (isUnsavedNewItem(section, item.id)) {
				return false;
			}
			return true;
		});

		// Agenda / compras: completado o recibido al final; el resto conserva su orden.
		if (section === 'agenda' || section === 'compras') {
			items.sort(function (a, b) {
				var aDone = isSectionItemComplete(section, a) ? 1 : 0;
				var bDone = isSectionItemComplete(section, b) ? 1 : 0;
				return aDone - bDone;
			});
		}

		return items;
	}

	function isUnsavedNewItem(section, id) {
		return !!id && unsavedNewItems[section] === id;
	}

	function clearUnsavedNewItem(section, id) {
		if (isUnsavedNewItem(section, id)) {
			unsavedNewItems[section] = '';
		}
	}

	function isUnsavedNewChecklist(date, id) {
		return unsavedNewChecklistKey === checklistEditKey(date, id);
	}

	function clearUnsavedNewChecklist(date, id) {
		if (isUnsavedNewChecklist(date, id)) {
			unsavedNewChecklistKey = '';
		}
	}

	function discardOrphanedDrafts(section) {
		var draftId = unsavedNewItems[section];
		if (!draftId || editingItems[section] === draftId) {
			return;
		}

		removeItem(section, draftId, false);
		unsavedNewItems[section] = '';
	}

	function discardOrphanedChecklistDraft() {
		if (!unsavedNewChecklistKey || editingChecklistKey === unsavedNewChecklistKey) {
			return;
		}

		var meta = parseChecklistEditKey(unsavedNewChecklistKey);
		if (meta) {
			removeChecklistItem(meta.date, meta.id, false);
		}
		unsavedNewChecklistKey = '';
	}

	function parseChecklistEditKey(key) {
		if (!key) {
			return null;
		}

		var sep = key.indexOf(':');
		if (sep === -1) {
			return null;
		}

		return {
			date: key.slice(0, sep),
			id: key.slice(sep + 1)
		};
	}

	function orderChecklistItemsForDisplay(dayDate, items) {
		if (!Array.isArray(items) || !items.length) {
			return items || [];
		}

		items = items.filter(function (item) {
			if (isUnsavedNewChecklist(dayDate, item.id)) {
				return false;
			}
			return true;
		});

		// Completadas al final; pendientes primero.
		items.sort(function (a, b) {
			var aDone = a && a.done ? 1 : 0;
			var bDone = b && b.done ? 1 : 0;
			return aDone - bDone;
		});

		return items;
	}

	function reopenSectionItem(section, item) {
		// Conservado por compatibilidad: ya no se reabre/resetea el estado al editar.
		// El estado se actualiza solo desde el formulario o el botón Completado/Recibido.
		void section;
		void item;
	}

	function checklistEditKey(date, id) {
		return date + ':' + id;
	}

	function isEditingChecklist(date, id) {
		return editingChecklistKey === checklistEditKey(date, id);
	}

	function panelIconActionBtn(options) {
		var label = options.label || '';
		var tip = options.tip || label;
		var extraClass = options.extraClass || '';
		var dataAttr = options.dataAttr || '';
		var icon = options.icon || 'dashicons-admin-generic';

		return (
			'<button type="button" class="logistica-user-panel__btn logistica-user-panel__btn--icon-only ' + extraClass + '" ' +
				dataAttr + ' aria-label="' + escapeHtml(label) + '">' +
				'<span class="dashicons ' + escapeHtml(icon) + '" aria-hidden="true"></span>' +
				'<span class="logistica-user-panel__tip-bubble logistica-user-panel__tip-bubble--action" role="tooltip">' + escapeHtml(tip) + '</span>' +
			'</button>'
		);
	}

	function panelTipTrigger(tipText, label) {
		var aria = label ? ('Ayuda: ' + label) : 'Ayuda';

		return (
			'<button type="button" class="logistica-user-panel__tip-trigger" aria-label="' + escapeHtml(aria) + '">' +
				'<span class="dashicons dashicons-info-outline" aria-hidden="true"></span>' +
				'<span class="logistica-user-panel__tip-bubble" role="tooltip">' + escapeHtml(tipText) + '</span>' +
			'</button>'
		);
	}

	function panelFieldHead(label, tipText) {
		return (
			'<div class="logistica-user-panel__field-head">' +
				'<span class="logistica-user-panel__field-label">' + escapeHtml(label) + '</span>' +
				(tipText ? panelTipTrigger(tipText, label) : '') +
			'</div>'
		);
	}

	function panelField(label, controlHtml, extraClass, tipText) {
		return (
			'<div class="logistica-user-panel__field' + (extraClass ? ' ' + extraClass : '') + '">' +
				panelFieldHead(label, tipText) +
				controlHtml +
			'</div>'
		);
	}

	var PANEL_UPPERCASE_FIELDS = {
		title: true,
		producto_ofrecido: true,
		referencia: true,
		nombre: true,
		escala: true,
		unidad_medida: true,
		documento_numero: true
	};

	function normalizePanelUppercaseValue(value) {
		return typeof value === 'string' ? value.toUpperCase() : value;
	}

	function shouldPanelFieldUppercase(field) {
		if (!field) {
			return false;
		}

		if (field.classList.contains('logistica-field-uppercase')) {
			return true;
		}

		var key = field.getAttribute('data-field') || '';
		return !!PANEL_UPPERCASE_FIELDS[key];
	}

	function normalizePanelUppercaseField(field) {
		if (!field || typeof field.value !== 'string' || !shouldPanelFieldUppercase(field)) {
			return;
		}

		field.value = field.value.toUpperCase();
	}

	function panelFieldValueFromInput(field) {
		if (!field) {
			return '';
		}

		if (field.type === 'checkbox') {
			return field.checked;
		}

		var value = field.value;
		if (shouldPanelFieldUppercase(field)) {
			value = normalizePanelUppercaseValue(value);
			field.value = value;
		}

		return value;
	}

	function bindPanelUppercaseFields(container) {
		if (!container) {
			return;
		}

		container.querySelectorAll('[data-field]').forEach(function (field) {
			if (field.tagName === 'SELECT' || field.tagName === 'TEXTAREA') {
				return;
			}

			if (field.type === 'email' || field.type === 'date' || field.type === 'time' || field.type === 'number') {
				return;
			}

			if (!shouldPanelFieldUppercase(field)) {
				return;
			}

			if (field.dataset.panelUppercaseBound === '1') {
				normalizePanelUppercaseField(field);
				return;
			}

			field.dataset.panelUppercaseBound = '1';
			field.classList.add('logistica-field-uppercase');
			field.addEventListener('input', function () {
				normalizePanelUppercaseField(field);
			});
			field.addEventListener('blur', function () {
				normalizePanelUppercaseField(field);
			});
			normalizePanelUppercaseField(field);
		});
	}

	function panelViewEyeBtn(section, id, checkDate) {
		var checkAttr = checkDate ? (' data-user-panel-view-check-date="' + escapeHtml(checkDate) + '"') : '';
		return panelIconActionBtn({
			label: 'Ver',
			tip: 'Ver toda la información',
			extraClass: 'logistica-user-panel__btn--action-view logistica-user-panel__row-view-btn',
			dataAttr: 'data-panel-view data-user-panel-view-section="' + escapeHtml(section) + '" data-user-panel-view-id="' + escapeHtml(id) + '"' + checkAttr,
			icon: 'dashicons-visibility'
		});
	}

	function panelCardViewAction(section, id, checkDate) {
		var checkAttr = checkDate ? (' data-user-panel-view-check-date="' + escapeHtml(checkDate) + '"') : '';
		return panelIconActionBtn({
			label: 'Ver',
			tip: 'Ver toda la información',
			extraClass: 'logistica-user-panel__btn--action-view',
			dataAttr: 'data-panel-view data-user-panel-view-section="' + escapeHtml(section) + '" data-user-panel-view-id="' + escapeHtml(id) + '"' + checkAttr,
			icon: 'dashicons-visibility'
		});
	}

	/**
	 * Tarjeta unificada (estilo Avisos) para agenda, chequeo y compras.
	 *
	 * @param {Object} options Card options.
	 * @return {string}
	 */
	function renderPanelCard(options) {
		var kind = options.kind || 'general';
		var complete = !!options.complete;
		var urgent = !!options.urgent && !complete;
		var stateClass = complete ? ' is-complete' : (urgent ? ' is-pending is-urgent' : ' is-pending');
		var kindLabel = options.kindLabel || 'Registro';
		var statusLabel = options.statusLabel || (complete ? 'Completado' : 'Pendiente');
		var statusLive = !complete;
		var title = options.title || 'Sin título';
		var description = options.description || '';
		var timeLabel = options.timeLabel || '';
		var actionsHtml = options.actionsHtml || '';
		var attrs = options.attrs || '';
		var extraBadges = options.extraBadges || '';
		var viewHtml = options.viewHtml || '';

		return (
			'<article class="logistica-user-panel__row logistica-user-panel__row--card' + stateClass + ' is-' + escapeHtml(kind) + '" ' + attrs + '>' +
				'<div class="logistica-user-panel__row-accent" aria-hidden="true"></div>' +
				'<div class="logistica-user-panel__row-icon logistica-user-panel__row-icon--view">' +
					viewHtml +
				'</div>' +
				'<div class="logistica-user-panel__row-body">' +
					'<div class="logistica-user-panel__aviso-meta">' +
						'<span class="logistica-user-panel__aviso-kind">' + escapeHtml(kindLabel) + '</span>' +
						'<span class="logistica-user-panel__aviso-state' + (statusLive ? ' is-live' : '') + '">' + escapeHtml(statusLabel) + '</span>' +
						extraBadges +
					'</div>' +
					'<h3 class="logistica-user-panel__row-title">' + escapeHtml(title) + '</h3>' +
					(description ? '<p class="logistica-user-panel__row-desc">' + escapeHtml(description) + '</p>' : '') +
					(timeLabel
						? '<time class="logistica-user-panel__row-time">' +
							'<span class="dashicons dashicons-clock" aria-hidden="true"></span>' +
							escapeHtml(timeLabel) +
						'</time>'
						: '') +
				'</div>' +
				actionsHtml +
			'</article>'
		);
	}

	function panelRowTitleBlock(title, section, id, checkDate) {
		return (
			'<div class="logistica-user-panel__row-title-wrap">' +
				panelViewEyeBtn(section, id, checkDate) +
				'<strong class="logistica-user-panel__row-title">' + escapeHtml(title) + '</strong>' +
			'</div>'
		);
	}

	function panelViewDetailRow(label, value) {
		if (value === null || value === undefined || String(value).trim() === '') {
			return '';
		}

		return (
			'<div class="logistica-user-panel__view-detail">' +
				'<dt class="logistica-user-panel__view-detail-label">' + escapeHtml(label) + '</dt>' +
				'<dd class="logistica-user-panel__view-detail-value">' + escapeHtml(String(value)) + '</dd>' +
			'</div>'
		);
	}

	function panelViewDetailsHtml(rows) {
		var html = (rows || []).filter(Boolean).join('');
		if (!html) {
			return '<p class="logistica-user-panel__empty logistica-user-panel__empty--compact">Sin información adicional.</p>';
		}

		return '<dl class="logistica-user-panel__view-details">' + html + '</dl>';
	}

	function renderComprasViewModal(item) {
		ensureCompraGestionFields(item);
		var empresa = getProveedorNombre(item.proveedor_id);
		var totalSeconds = getCompraGestionTotalSeconds(item);
		var statusMap = getCompraStatusSecondsMap(item, true);
		var statusLines = Object.keys(statusMap).map(function (statusKey) {
			return labelMap(state.compra_statuses, statusKey) + ': ' + formatDurationSeconds(statusMap[statusKey]);
		}).join(' · ');

		var novedadesHtml = '';
		if (item.novedades && item.novedades.length) {
			novedadesHtml = (
				'<section class="logistica-user-panel__novedades logistica-user-panel__novedades--view">' +
					'<h3 class="logistica-user-panel__novedades-title">Historial de novedades</h3>' +
					'<ol class="logistica-user-panel__novedades-list">' +
						item.novedades.slice().reverse().map(function (nov) {
							return (
								'<li class="logistica-user-panel__novedad-item">' +
									'<div class="logistica-user-panel__novedad-meta">' +
										'<time>' + escapeHtml(formatColombiaDateTime(nov.at)) + '</time>' +
										(nov.status ? '<span class="logistica-user-panel__novedad-status">' + escapeHtml(labelMap(state.compra_statuses, nov.status)) + '</span>' : '') +
									'</div>' +
									'<p>' + escapeHtml(nov.texto) + '</p>' +
								'</li>'
							);
						}).join('') +
					'</ol>' +
				'</section>'
			);
		}

		return panelViewDetailsHtml([
			panelViewDetailRow('Producto', compraProductoLabel(item)),
			panelViewDetailRow('Referencia', item.referencia),
			panelViewDetailRow('Precio', item.precio),
			panelViewDetailRow('Cantidad', item.cantidad),
			panelViewDetailRow('Unidad de medida', item.unidad_medida),
			panelViewDetailRow('Empresa', empresa),
			panelViewDetailRow('Fecha requerida', item.fecha_requerida ? formatShortDate(item.fecha_requerida) : ''),
			panelViewDetailRow('Fecha solicitud', item.fecha_solicitud ? formatShortDate(item.fecha_solicitud) : ''),
			panelViewDetailRow('Estado', labelMap(state.compra_statuses, item.status)),
			panelViewDetailRow('Prioridad', labelMap(state.priorities, item.priority || 'media')),
			panelViewDetailRow('Escala', item.escala || item.quantity),
			panelViewDetailRow('Fecha documento', item.fecha ? formatShortDate(item.fecha) : ''),
			panelViewDetailRow('Nº documento', item.documento_numero),
			panelViewDetailRow('Fecha recibida', item.status === 'recibido' ? formatCompraReceivedDate(item) : ''),
			panelViewDetailRow('Inicio gestión', item.gestion_started_at ? formatColombiaDateTime(item.gestion_started_at) : ''),
			panelViewDetailRow('Tiempo total gestión', formatDurationSeconds(totalSeconds)),
			panelViewDetailRow('Tiempo por estado', statusLines),
			panelViewDetailRow('Actualizado', formatColombiaDateTime(item.updated_at))
		]) + novedadesHtml;
	}

	function renderAgendaViewModal(item) {
		ensureAgendaGestionFields(item);
		var complete = isSectionItemComplete('agenda', item);
		var totalSeconds = getGestionTotalSeconds(item);
		var statusMap = getStatusSecondsMap(item, true);
		var statusLabels = state.agenda_statuses || {};
		var statusLines = Object.keys(statusMap).map(function (statusKey) {
			return labelMap(statusLabels, statusKey) + ': ' + formatDurationSeconds(statusMap[statusKey]);
		}).join(' · ');

		var novedadesHtml = '';
		if (item.novedades && item.novedades.length) {
			novedadesHtml = (
				'<section class="logistica-user-panel__novedades logistica-user-panel__novedades--view">' +
					'<h3 class="logistica-user-panel__novedades-title">Historial de novedades</h3>' +
					'<ol class="logistica-user-panel__novedades-list">' +
						item.novedades.slice().reverse().map(function (nov) {
							return (
								'<li class="logistica-user-panel__novedad-item">' +
									'<div class="logistica-user-panel__novedad-meta">' +
										'<time>' + escapeHtml(formatColombiaDateTime(nov.at)) + '</time>' +
										(nov.status ? '<span class="logistica-user-panel__novedad-status">' + escapeHtml(labelMap(statusLabels, nov.status)) + '</span>' : '') +
									'</div>' +
									'<p>' + escapeHtml(nov.texto) + '</p>' +
								'</li>'
							);
						}).join('') +
					'</ol>' +
				'</section>'
			);
		}

		return panelViewDetailsHtml([
			panelViewDetailRow('Actividad', item.title),
			panelViewDetailRow('Cuándo', formatAgendaWhen(item)),
			panelViewDetailRow('Prioridad', labelMap(state.priorities, item.priority)),
			panelViewDetailRow('Estado', labelMap(statusLabels, item.status || (complete ? 'completado' : 'pendiente'))),
			panelViewDetailRow('Notas', item.notes),
			panelViewDetailRow('Inicio gestión', item.gestion_started_at ? formatColombiaDateTime(item.gestion_started_at) : ''),
			panelViewDetailRow('Tiempo total gestión', formatDurationSeconds(totalSeconds)),
			panelViewDetailRow('Tiempo por estado', statusLines),
			panelViewDetailRow('Actualizado', item.updated_at ? formatColombiaDateTime(item.updated_at) : '')
		]) + novedadesHtml;
	}

	function renderPendientesViewModal(item) {
		return panelViewDetailsHtml([
			panelViewDetailRow('Título', item.title),
			panelViewDetailRow('Estado', labelMap(state.pendiente_statuses, item.status)),
			panelViewDetailRow('Anotaciones', item.notes),
			panelViewDetailRow('Actualizado', formatColombiaDateTime(item.updated_at))
		]);
	}

	function renderProveedoresViewModal(item) {
		return panelViewDetailsHtml([
			panelViewDetailRow('Empresa', item.nombre),
			panelViewDetailRow('Contacto', item.contacto),
			panelViewDetailRow('Correo', item.email),
			panelViewDetailRow('Teléfono', item.telefono),
			panelViewDetailRow('Ofrece', item.descripcion),
			panelViewDetailRow('Actualizado', formatColombiaDateTime(item.updated_at))
		]) + renderProveedorHistorialCompras(item.id);
	}

	function renderChecklistViewModal(item, dayDate) {
		var recurrences = state.checklist_recurrences || {};
		var recurrence = item.recurrence || 'diario';
		var carried = (recurrence === 'diario') && item.carried_from && item.carried_from !== dayDate
			? ('Pendiente desde el ' + formatShortDate(item.carried_from))
			: '';

		return panelViewDetailsHtml([
			panelViewDetailRow('Actividad', item.title),
			panelViewDetailRow('Día', dayDate ? formatShortDate(dayDate) : ''),
			panelViewDetailRow('Duración', formatDuration(item.duration_minutes || 0)),
			panelViewDetailRow('Prioridad', labelMap(state.priorities, item.priority)),
			panelViewDetailRow('Recurrencia', labelMap(recurrences, recurrence)),
			panelViewDetailRow('Estado', item.done ? 'Completado' : 'Pendiente'),
			panelViewDetailRow('Origen', item.linked ? (item.link_label || 'Vinculado') : ''),
			panelViewDetailRow('Arrastre', carried),
			panelViewDetailRow('Actualizado', item.updated_at ? formatColombiaDateTime(item.updated_at) : '')
		]);
	}

	var modalSectionTitles = {
		agenda: { new: 'Nueva actividad', edit: 'Modificar actividad' },
		compras: { new: 'Nueva cotización', edit: 'Modificar cotización' },
		proveedores: { new: 'Nuevo proveedor', edit: 'Modificar proveedor' },
		checklist: { new: 'Nuevo chequeo', edit: 'Modificar chequeo' },
		pendientes: { new: 'Nuevo pendiente', edit: 'Modificar pendiente' }
	};

	function getModalEl() {
		return root ? root.querySelector('[data-user-panel-modal]') : null;
	}

	function isModalOpen() {
		var modal = getModalEl();
		return !!(modal && !modal.hidden);
	}

	function modalTitleFor(section, isNew) {
		var titles = modalSectionTitles[section];
		if (!titles) {
			return isNew ? 'Nuevo registro' : 'Modificar registro';
		}
		return isNew ? titles.new : titles.edit;
	}

	function closeEditModal() {
		var modal = getModalEl();
		if (!modal) {
			return;
		}

		modal.hidden = true;
		modal.classList.remove('logistica-user-panel__modal-dialog--wide');
		modal.removeAttribute('data-user-panel-modal-section');
		modal.removeAttribute('data-user-panel-modal-id');
		modal.removeAttribute('data-user-panel-modal-check-date');
		modal.removeAttribute('data-user-panel-modal-mode');

		var footer = modal.querySelector('.logistica-user-panel__modal-footer');
		if (footer) {
			footer.hidden = false;
		}

		var saveBtn = modal.querySelector('[data-user-panel-modal-save]');
		if (saveBtn) {
			saveBtn.textContent = 'Guardar';
		}

		var body = modal.querySelector('[data-user-panel-modal-body]');
		if (body) {
			body.innerHTML = '';
		}

		document.body.classList.remove('logistica-user-panel-modal-open');
		hideFloatingTip();
	}

	function ensureFloatingTipEl() {
		if (!floatingTipEl) {
			floatingTipEl = document.createElement('div');
			floatingTipEl.className = 'logistica-user-panel__tip-float';
			floatingTipEl.setAttribute('role', 'tooltip');
			floatingTipEl.hidden = true;
			document.body.appendChild(floatingTipEl);
		}

		return floatingTipEl;
	}

	function resolveFloatingTipTrigger(node) {
		if (!node || !node.closest) {
			return null;
		}

		var iconBtn = node.closest('.logistica-user-panel__btn--icon-only');
		if (iconBtn && iconBtn.querySelector('.logistica-user-panel__tip-bubble')) {
			return iconBtn;
		}

		if (!isModalOpen()) {
			return null;
		}

		var tipTrigger = node.closest('.logistica-user-panel__tip-trigger');
		if (tipTrigger && tipTrigger.closest('[data-user-panel-modal]')) {
			return tipTrigger;
		}

		return null;
	}

	function hideFloatingTip() {
		if (floatingTipEl) {
			floatingTipEl.hidden = true;
			floatingTipEl.textContent = '';
			floatingTipEl.style.left = '';
			floatingTipEl.style.top = '';
			floatingTipEl.classList.remove('is-below');
		}

		floatingTipTrigger = null;
	}

	function showFloatingTip(trigger) {
		if (!trigger) {
			return;
		}

		var bubble = trigger.querySelector('.logistica-user-panel__tip-bubble');
		if (!bubble || !bubble.textContent.trim()) {
			return;
		}

		var tip = ensureFloatingTipEl();
		if (!tip) {
			return;
		}

		floatingTipTrigger = trigger;
		tip.textContent = bubble.textContent.trim();
		tip.hidden = false;
		tip.classList.remove('is-below');
		tip.style.left = '-9999px';
		tip.style.top = '0';

		var rect = trigger.getBoundingClientRect();
		var tipRect = tip.getBoundingClientRect();
		var gap = 10;
		var pad = 12;
		var left = rect.left + (rect.width / 2) - (tipRect.width / 2);
		left = Math.max(pad, Math.min(left, window.innerWidth - tipRect.width - pad));

		var preferAbove = bubble.classList.contains('logistica-user-panel__tip-bubble--action');
		var top;

		if (preferAbove) {
			top = rect.top - tipRect.height - gap;
			if (top < pad) {
				top = rect.bottom + gap;
				tip.classList.add('is-below');
			}
		} else {
			top = rect.bottom + gap;
			if (top + tipRect.height > window.innerHeight - pad) {
				top = rect.top - tipRect.height - gap;
			} else {
				tip.classList.add('is-below');
			}
		}

		tip.style.left = Math.round(left) + 'px';
		tip.style.top = Math.round(top) + 'px';
	}

	function bindModalFloatingTips() {
		root.addEventListener('mouseover', function (event) {
			var trigger = resolveFloatingTipTrigger(event.target);
			if (trigger) {
				showFloatingTip(trigger);
			}
		});

		root.addEventListener('mouseout', function (event) {
			if (!floatingTipTrigger) {
				return;
			}

			var trigger = resolveFloatingTipTrigger(event.target);
			if (trigger !== floatingTipTrigger) {
				return;
			}

			var related = event.relatedTarget;
			if (related && trigger.contains(related)) {
				return;
			}

			hideFloatingTip();
		});

		root.addEventListener('focusin', function (event) {
			var trigger = resolveFloatingTipTrigger(event.target);
			if (trigger) {
				showFloatingTip(trigger);
			}
		});

		root.addEventListener('focusout', function (event) {
			if (!floatingTipTrigger) {
				return;
			}

			var related = event.relatedTarget;
			if (related && floatingTipTrigger.contains(related)) {
				return;
			}

			if (resolveFloatingTipTrigger(event.target) === floatingTipTrigger) {
				hideFloatingTip();
			}
		});

		root.addEventListener('scroll', function () {
			if (floatingTipTrigger) {
				hideFloatingTip();
			}
		}, true);

		window.addEventListener('scroll', function () {
			if (floatingTipTrigger) {
				hideFloatingTip();
			}
		}, true);
	}

	function openEditModal(options) {
		var modal = getModalEl();
		if (!modal || !options) {
			return;
		}

		var titleNode = modal.querySelector('[data-user-panel-modal-title]');
		var body = modal.querySelector('[data-user-panel-modal-body]');
		var dialog = modal.querySelector('.logistica-user-panel__modal-dialog');
		var footer = modal.querySelector('.logistica-user-panel__modal-footer');

		if (!titleNode || !body || !dialog) {
			return;
		}

		modal.removeAttribute('data-user-panel-modal-mode');
		if (footer) {
			footer.hidden = false;
		}

		titleNode.textContent = modalTitleFor(options.section, !!options.isNew);
		body.innerHTML = options.bodyHtml || '';
		dialog.classList.toggle('logistica-user-panel__modal-dialog--wide', !!options.wide);
		bindPanelUppercaseFields(body);

		modal.setAttribute('data-user-panel-modal-section', options.section || '');
		modal.setAttribute('data-user-panel-modal-id', options.id || '');
		if (options.checkDate) {
			modal.setAttribute('data-user-panel-modal-check-date', options.checkDate);
		} else {
			modal.removeAttribute('data-user-panel-modal-check-date');
		}

		modal.hidden = false;
		document.body.classList.add('logistica-user-panel-modal-open');

		var firstField = body.querySelector('input, select, textarea');
		if (firstField) {
			firstField.focus();
		}
	}

	function openViewModal(options) {
		var modal = getModalEl();
		if (!modal || !options) {
			return;
		}

		var titleNode = modal.querySelector('[data-user-panel-modal-title]');
		var body = modal.querySelector('[data-user-panel-modal-body]');
		var dialog = modal.querySelector('.logistica-user-panel__modal-dialog');
		var footer = modal.querySelector('.logistica-user-panel__modal-footer');

		if (!titleNode || !body || !dialog) {
			return;
		}

		modal.setAttribute('data-user-panel-modal-mode', 'view');
		modal.setAttribute('data-user-panel-modal-section', options.section || '');
		modal.setAttribute('data-user-panel-modal-id', options.id || '');
		if (options.checkDate) {
			modal.setAttribute('data-user-panel-modal-check-date', options.checkDate);
		} else {
			modal.removeAttribute('data-user-panel-modal-check-date');
		}

		if (footer) {
			footer.hidden = true;
		}

		titleNode.textContent = options.title || 'Detalle del registro';
		body.innerHTML = options.bodyHtml || '';
		dialog.classList.toggle('logistica-user-panel__modal-dialog--wide', !!options.wide);
		modal.hidden = false;
		document.body.classList.add('logistica-user-panel-modal-open');
	}

	function resolveChecklistViewSource(checkItem, id) {
		if (!checkItem && !id) {
			return null;
		}

		var linked = parseLinkedChecklistId(id);
		if (!linked && checkItem && checkItem.linked) {
			var sourceSection = checkItem.source_section || '';
			if (sourceSection === 'compra') {
				sourceSection = 'compras';
			}
			if ((sourceSection === 'compras' || sourceSection === 'agenda') && checkItem.source_id) {
				linked = { section: sourceSection, sourceId: checkItem.source_id };
			}
		}

		if (!linked) {
			return null;
		}

		var source = findListItem(linked.section, linked.sourceId);
		if (!source) {
			return null;
		}

		return { section: linked.section, item: source };
	}

	function openSectionViewModal(section, id, checkDate) {
		var title = 'Detalle del registro';
		var bodyHtml = '';
		var wide = section === 'compras' || section === 'proveedores' || section === 'agenda';
		var viewSection = section;
		var viewId = id;

		if (section === 'checklist') {
			var checkItem = findChecklistItem(checkDate, id);
			if (!checkItem) {
				return;
			}

			var sourceView = resolveChecklistViewSource(checkItem, id);
			if (sourceView) {
				viewSection = sourceView.section;
				viewId = sourceView.item.id;
				wide = true;
				if (sourceView.section === 'compras') {
					title = compraProductoLabel(sourceView.item);
					bodyHtml = renderComprasViewModal(sourceView.item);
				} else {
					title = sourceView.item.title || 'Actividad';
					bodyHtml = renderAgendaViewModal(sourceView.item);
				}
			} else {
				title = checkItem.title || 'Actividad';
				bodyHtml = renderChecklistViewModal(checkItem, checkDate);
			}
		} else {
			var item = findListItem(section, id);
			if (!item) {
				return;
			}

			if (section === 'compras') {
				title = compraProductoLabel(item);
				bodyHtml = renderComprasViewModal(item);
			} else if (section === 'agenda') {
				title = item.title || 'Actividad';
				bodyHtml = renderAgendaViewModal(item);
			} else if (section === 'pendientes') {
				title = item.title || 'Pendiente';
				bodyHtml = renderPendientesViewModal(item);
			} else if (section === 'proveedores') {
				title = item.nombre || 'Proveedor';
				bodyHtml = renderProveedoresViewModal(item);
			} else {
				return;
			}
		}

		openViewModal({
			section: viewSection,
			id: viewId,
			checkDate: checkDate || '',
			title: title,
			bodyHtml: bodyHtml,
			wide: wide
		});
	}

	function isViewModalOpen() {
		var modal = getModalEl();
		return !!(modal && !modal.hidden && modal.getAttribute('data-user-panel-modal-mode') === 'view');
	}

	function getModalContext() {
		var modal = getModalEl();
		if (!modal) {
			return null;
		}

		return {
			section: modal.getAttribute('data-user-panel-modal-section') || '',
			id: modal.getAttribute('data-user-panel-modal-id') || '',
			checkDate: modal.getAttribute('data-user-panel-modal-check-date') || ''
		};
	}

	function findEditFormArticle(section, id) {
		var body = root ? root.querySelector('[data-user-panel-modal-body]') : null;
		if (!body) {
			return null;
		}

		return body.querySelector('[data-user-panel-item="' + section + '"][data-id="' + id + '"]');
	}

	function agendaStatusOptionsHtml(selected) {
		var statuses = state.agenda_statuses || {};
		selected = selected || 'pendiente';
		return Object.keys(statuses).map(function (key) {
			return '<option value="' + escapeHtml(key) + '"' + (key === selected ? ' selected' : '') + '>' +
				escapeHtml(statuses[key]) + '</option>';
		}).join('');
	}

	function renderAgendaEditForm(item) {
		ensureAgendaGestionFields(item);
		var totalSeconds = getGestionTotalSeconds(item);
		var statusMap = getStatusSecondsMap(item, true);
		var statusLabels = state.agenda_statuses || {};
		var statusRows = Object.keys(statusMap).map(function (statusKey) {
			return (
				'<li><strong>' + escapeHtml(labelMap(statusLabels, statusKey)) + '</strong>: ' +
				escapeHtml(formatDurationSeconds(statusMap[statusKey])) + '</li>'
			);
		}).join('');

		return (
			'<div class="logistica-user-panel__row-edit">' +
				'<div class="logistica-user-panel__row-edit-grid logistica-user-panel__row-edit-grid--agenda">' +
					panelField('Actividad', '<input type="text" class="logistica-user-panel__input logistica-field-uppercase" data-field="title" value="' + escapeHtml(item.title) + '" placeholder="Actividad">') +
					panelField('Prioridad', '<select class="logistica-user-panel__select" data-field="priority">' +
						Object.keys(state.priorities).map(function (key) {
							return '<option value="' + escapeHtml(key) + '"' + (key === item.priority ? ' selected' : '') + '>' +
								escapeHtml(state.priorities[key]) + '</option>';
						}).join('') +
					'</select>') +
					panelField('Fecha requerida', '<input type="date" class="logistica-user-panel__input" data-field="date" value="' + escapeHtml(item.date) + '">') +
					panelField('Hora', '<input type="time" class="logistica-user-panel__input logistica-user-panel__time-input" data-field="time" value="' + escapeHtml(item.time) + '">') +
					panelField('Estado', '<select class="logistica-user-panel__select" data-field="status">' + agendaStatusOptionsHtml(item.status || 'pendiente') + '</select>') +
				'</div>' +
				panelField('Notas', '<textarea class="logistica-user-panel__textarea" rows="3" data-field="notes" placeholder="Notas">' + escapeHtml(item.notes) + '</textarea>',
					'logistica-user-panel__field--wide') +
				'<section class="logistica-user-panel__gestion-summary" data-agenda-gestion-summary>' +
					'<h3 class="logistica-user-panel__gestion-title">Tiempo de gestión</h3>' +
					'<p class="logistica-user-panel__gestion-total"><strong>Total:</strong> ' + escapeHtml(formatDurationSeconds(totalSeconds)) + '</p>' +
					(statusRows ? '<ul class="logistica-user-panel__gestion-status-list">' + statusRows + '</ul>' : '') +
				'</section>' +
				renderItemNovedadesEditor(item, 'agenda', statusLabels) +
			'</div>'
		);
	}

	function renderComprasEditForm(item) {
		ensureCompraGestionFields(item);
		var totalSeconds = getCompraGestionTotalSeconds(item);
		var statusMap = getCompraStatusSecondsMap(item, true);
		var statusRows = Object.keys(statusMap).map(function (statusKey) {
			return (
				'<li><strong>' + escapeHtml(labelMap(state.compra_statuses, statusKey)) + '</strong>: ' +
				escapeHtml(formatDurationSeconds(statusMap[statusKey])) + '</li>'
			);
		}).join('');

		return (
			'<div class="logistica-user-panel__row-edit">' +
				'<div class="logistica-user-panel__row-edit-grid logistica-user-panel__row-edit-grid--compras">' +
					panelField('Producto ofrecido', '<input type="text" class="logistica-user-panel__input logistica-field-uppercase" data-field="producto_ofrecido" value="' + escapeHtml(item.producto_ofrecido || item.item || '') + '" placeholder="Producto ofrecido">') +
					panelField('Referencia', '<input type="text" class="logistica-user-panel__input logistica-field-uppercase" data-field="referencia" value="' + escapeHtml(item.referencia || '') + '" placeholder="Referencia">') +
					panelField('Precio', '<input type="text" class="logistica-user-panel__input" data-field="precio" value="' + escapeHtml(item.precio || '') + '" placeholder="Precio">') +
					panelField('Cantidad', '<input type="text" class="logistica-user-panel__input" data-field="cantidad" value="' + escapeHtml(item.cantidad || '') + '" placeholder="Cantidad" inputmode="decimal">') +
					panelField(
						'Unidad de medida',
						'<input type="text" class="logistica-user-panel__input logistica-field-uppercase" data-field="unidad_medida" value="' + escapeHtml(item.unidad_medida || '') + '" placeholder="Und, kg, cajas…">'
					) +
					panelField('Fecha requerida', '<input type="date" class="logistica-user-panel__input" data-field="fecha_requerida" value="' + escapeHtml(item.fecha_requerida || '') + '">') +
					panelField('Fecha solicitud', '<input type="date" class="logistica-user-panel__input" data-field="fecha_solicitud" value="' + escapeHtml(item.fecha_solicitud || '') + '">') +
					panelField('Estado', '<select class="logistica-user-panel__select" data-field="status">' + compraStatusOptionsHtml(item.status) + '</select>') +
					panelField('Prioridad', '<select class="logistica-user-panel__select" data-field="priority">' +
						Object.keys(state.priorities).map(function (key) {
							return '<option value="' + escapeHtml(key) + '"' + (key === (item.priority || 'media') ? ' selected' : '') + '>' +
								escapeHtml(state.priorities[key]) + '</option>';
						}).join('') +
					'</select>') +
					panelField(
						'Escala',
						'<input type="text" class="logistica-user-panel__input logistica-field-uppercase" data-field="escala" value="' + escapeHtml(item.escala || item.quantity || '') + '" placeholder="Escala (opcional)">',
						'',
						'Notas de escala o volumen adicional (opcional). La cantidad y unidad van en sus campos propios.'
					) +
					panelField('Empresa', '<select class="logistica-user-panel__select" data-field="proveedor_id">' + proveedorOptionsHtml(item.proveedor_id || '') + '</select>') +
					panelField(
						'Fecha',
						'<input type="date" class="logistica-user-panel__input" data-field="fecha" value="' + escapeHtml(item.fecha || '') + '">',
						'',
						'Fecha del documento o registro de la cotización u orden (proforma, factura, OC, etc.).'
					) +
					panelField('Nº documento', '<input type="text" class="logistica-user-panel__input logistica-field-uppercase" data-field="documento_numero" value="' + escapeHtml(item.documento_numero || '') + '" placeholder="Nº proforma, factura o cotización">',
						'logistica-user-panel__field--wide') +
				'</div>' +
				'<section class="logistica-user-panel__gestion-summary" data-compra-gestion-summary>' +
					'<h3 class="logistica-user-panel__gestion-title">Tiempo de gestión</h3>' +
					'<p class="logistica-user-panel__gestion-total"><strong>Total:</strong> ' + escapeHtml(formatDurationSeconds(totalSeconds)) + '</p>' +
					(statusRows ? '<ul class="logistica-user-panel__gestion-status-list">' + statusRows + '</ul>' : '') +
				'</section>' +
				renderItemNovedadesEditor(item, 'compras', state.compra_statuses || {}) +
			'</div>'
		);
	}

	function renderCompraNovedadesEditor(item) {
		return renderItemNovedadesEditor(item, 'compras', state.compra_statuses || {});
	}

	function renderItemNovedadesEditor(item, section, statusLabels) {
		if (section === 'compras') {
			ensureCompraGestionFields(item);
		} else {
			ensureAgendaGestionFields(item);
		}
		var attrPrefix = section === 'agenda' ? 'agenda' : 'compra';
		var listHtml = (item.novedades || []).slice().reverse().map(function (nov) {
			return (
				'<li class="logistica-user-panel__novedad-item">' +
					'<div class="logistica-user-panel__novedad-meta">' +
						'<time>' + escapeHtml(formatColombiaDateTime(nov.at)) + '</time>' +
						(nov.status ? '<span class="logistica-user-panel__novedad-status">' + escapeHtml(labelMap(statusLabels, nov.status)) + '</span>' : '') +
					'</div>' +
					'<p>' + escapeHtml(nov.texto) + '</p>' +
					'<button type="button" class="logistica-user-panel__btn logistica-user-panel__btn--ghost logistica-user-panel__btn--sm" data-' + attrPrefix + '-novedad-remove="' + escapeHtml(nov.id) + '">Eliminar</button>' +
				'</li>'
			);
		}).join('');

		return (
			'<section class="logistica-user-panel__novedades" data-' + attrPrefix + '-novedades>' +
				'<h3 class="logistica-user-panel__novedades-title">Novedades de gestión</h3>' +
				'<div class="logistica-user-panel__novedad-form">' +
					panelField('Fecha y hora', '<input type="datetime-local" class="logistica-user-panel__input" data-' + attrPrefix + '-novedad-at value="">') +
					panelField('Novedad', '<textarea class="logistica-user-panel__textarea" rows="2" data-' + attrPrefix + '-novedad-texto placeholder="Describe el avance o contacto."></textarea>',
						'logistica-user-panel__field--wide') +
					'<label class="logistica-user-panel__novedad-notify">' +
						'<input type="checkbox" data-' + attrPrefix + '-novedad-notify checked> ' +
						'Crear aviso en la aplicación' +
					'</label>' +
					'<button type="button" class="logistica-user-panel__btn logistica-user-panel__btn--sm" data-' + attrPrefix + '-novedad-add>Agregar novedad</button>' +
				'</div>' +
				(listHtml
					? '<ol class="logistica-user-panel__novedades-list">' + listHtml + '</ol>'
					: '<p class="logistica-user-panel__empty logistica-user-panel__empty--compact">Sin novedades registradas.</p>') +
			'</section>'
		);
	}

	function renderProveedoresEditForm(item) {
		var historyHtml = item && item.id ? renderProveedorHistorialCompras(item.id) : '';

		return (
			'<div class="logistica-user-panel__row-edit">' +
				'<div class="logistica-user-panel__row-edit-grid logistica-user-panel__row-edit-grid--proveedores">' +
					panelField('Empresa', '<input type="text" class="logistica-user-panel__input logistica-field-uppercase" data-field="nombre" value="' + escapeHtml(item.nombre) + '" placeholder="Nombre de la empresa">') +
					panelField('Contacto', '<input type="text" class="logistica-user-panel__input" data-field="contacto" value="' + escapeHtml(item.contacto) + '" placeholder="Contacto">') +
					panelField('Correo', '<input type="email" class="logistica-user-panel__input" data-field="email" value="' + escapeHtml(item.email) + '" placeholder="Correo">') +
					panelField('Teléfono', '<input type="text" class="logistica-user-panel__input" data-field="telefono" value="' + escapeHtml(item.telefono) + '" placeholder="Teléfono">') +
				'</div>' +
				panelField('Descripción', '<textarea class="logistica-user-panel__textarea" rows="3" data-field="descripcion" placeholder="Descripción de lo que ofrece la empresa">' + escapeHtml(item.descripcion) + '</textarea>',
					'logistica-user-panel__field--wide') +
				historyHtml +
			'</div>'
		);
	}

	function renderChecklistEditForm(item) {
		var recurrence = item.recurrence || 'diario';
		var recurrences = state.checklist_recurrences || {};
		var doneValue = item.done ? '1' : '0';

		return (
			'<div class="logistica-user-panel__row-edit">' +
				panelField('Actividad', '<input type="text" class="logistica-user-panel__input logistica-field-uppercase" data-field="title" value="' + escapeHtml(item.title) + '" placeholder="Describe la actividad">',
					'logistica-user-panel__field--wide') +
				'<div class="logistica-user-panel__row-edit-grid logistica-user-panel__row-edit-grid--checklist">' +
					panelField('Duración (min)', '<input type="number" min="0" step="5" class="logistica-user-panel__input" data-field="duration_minutes" value="' + escapeHtml(String(item.duration_minutes || 0)) + '">') +
					panelField('Prioridad', '<select class="logistica-user-panel__select" data-field="priority">' +
						Object.keys(state.priorities).map(function (key) {
							return '<option value="' + escapeHtml(key) + '"' + (key === item.priority ? ' selected' : '') + '>' +
								escapeHtml(state.priorities[key]) + '</option>';
						}).join('') +
					'</select>') +
					panelField('Recurrencia', '<select class="logistica-user-panel__select" data-field="recurrence">' +
						Object.keys(recurrences).map(function (key) {
							return '<option value="' + escapeHtml(key) + '"' + (key === recurrence ? ' selected' : '') + '>' +
								escapeHtml(recurrences[key]) + '</option>';
						}).join('') +
					'</select>', '', 'Repetitivo: reaparece cada semana el mismo día. Diario: se arrastra día a día hasta completarla. Único: solo aparece una vez y no vuelve la semana siguiente.') +
					panelField('Estado', '<select class="logistica-user-panel__select" data-field="done">' +
						'<option value="0"' + (doneValue === '0' ? ' selected' : '') + '>Pendiente</option>' +
						'<option value="1"' + (doneValue === '1' ? ' selected' : '') + '>Completado</option>' +
					'</select>') +
				'</div>' +
			'</div>'
		);
	}

	function renderPendientesEditForm(item) {
		return (
			'<div class="logistica-user-panel__row-edit">' +
				'<div class="logistica-user-panel__row-edit-grid logistica-user-panel__row-edit-grid--pendientes">' +
					panelField('Título', '<input type="text" class="logistica-user-panel__input logistica-field-uppercase" data-field="title" value="' + escapeHtml(item.title) + '" placeholder="Título del pendiente">') +
					panelField('Estado', '<select class="logistica-user-panel__select" data-field="status">' +
						Object.keys(state.pendiente_statuses).map(function (key) {
							return '<option value="' + escapeHtml(key) + '"' + (key === item.status ? ' selected' : '') + '>' +
								escapeHtml(state.pendiente_statuses[key]) + '</option>';
						}).join('') +
					'</select>') +
				'</div>' +
				panelField('Anotaciones', '<textarea class="logistica-user-panel__textarea" rows="3" data-field="notes" placeholder="Anotaciones">' + escapeHtml(item.notes) + '</textarea>',
					'logistica-user-panel__field--wide') +
			'</div>'
		);
	}

	function buildModalFormArticle(section, id, innerHtml, checkDate) {
		var attrs = 'data-user-panel-item="' + escapeHtml(section) + '" data-id="' + escapeHtml(id) + '" class="logistica-user-panel__modal-form"';
		if (checkDate) {
			attrs += ' data-check-date="' + escapeHtml(checkDate) + '"';
		}
		return '<article ' + attrs + '>' + innerHtml + '</article>';
	}

	function openSectionEditModal(section, id, checkDate) {
		var isNew = false;
		var bodyHtml = '';
		var wide = section === 'compras' || section === 'agenda';

		if (section === 'checklist') {
			var checkItem = findChecklistItem(checkDate, id);
			if (!checkItem) {
				return;
			}
			isNew = isUnsavedNewChecklist(checkDate, id);
			bodyHtml = buildModalFormArticle('checklist', id, renderChecklistEditForm(checkItem), checkDate);
		} else {
			var item = findListItem(section, id);
			if (!item) {
				return;
			}
			isNew = isUnsavedNewItem(section, id);
			if (section === 'agenda') {
				bodyHtml = buildModalFormArticle(section, id, renderAgendaEditForm(item));
			} else if (section === 'compras') {
				bodyHtml = buildModalFormArticle(section, id, renderComprasEditForm(item));
			} else if (section === 'proveedores') {
				bodyHtml = buildModalFormArticle(section, id, renderProveedoresEditForm(item));
			} else if (section === 'pendientes') {
				bodyHtml = buildModalFormArticle(section, id, renderPendientesEditForm(item));
			}

			if (section === 'proveedores' && !isNew) {
				wide = true;
			}
		}

		openEditModal({
			section: section,
			id: id,
			checkDate: checkDate || '',
			isNew: isNew,
			wide: wide,
			bodyHtml: bodyHtml
		});

		if (section === 'compras' || section === 'agenda') {
			var atSel = section === 'agenda' ? '[data-agenda-novedad-at]' : '[data-compra-novedad-at]';
			var atInput = root.querySelector(atSel);
			if (atInput && !atInput.value) {
				atInput.value = datetimeLocalFromSql(nowSql());
			}
		}
	}

	function isAvisoResolveModalOpen() {
		var modal = getModalEl();
		return !!(modal && !modal.hidden && modal.getAttribute('data-user-panel-modal-mode') === 'aviso-resolve');
	}

	function handleModalSave() {
		if (isViewModalOpen()) {
			closeEditModal();
			return;
		}

		if (isAvisoResolveModalOpen()) {
			saveAvisoMarkReadModal();
			return;
		}

		var ctx = getModalContext();
		if (!ctx || !ctx.section || !ctx.id) {
			return;
		}

		if (ctx.section === 'checklist') {
			saveChecklistEdit(ctx.checkDate, ctx.id);
			return;
		}

		saveEdit(ctx.section, ctx.id);
	}

	function handleModalCancel() {
		if (isViewModalOpen() || isAvisoResolveModalOpen()) {
			closeEditModal();
			return;
		}

		var ctx = getModalContext();
		if (!ctx || !ctx.section || !ctx.id) {
			closeEditModal();
			return;
		}

		if (ctx.section === 'checklist') {
			cancelChecklistEdit(ctx.checkDate, ctx.id);
			return;
		}

		cancelEdit(ctx.section, ctx.id);
	}

	function checklistRowActionsHtml(item, readOnly, dayDate) {
		if (readOnly) {
			return '';
		}

		var completeHidden = !!item.done;
		var isLinked = !!item.linked;
		return (
			'<div class="logistica-user-panel__row-actions">' +
				panelIconActionBtn({
					label: isLinked ? 'Modificar origen' : 'Modificar',
					tip: isLinked
						? 'Abre el formulario completo de la actividad o compra vinculada (incluye estado).'
						: 'Abre el formulario para cambiar los datos del registro, incluido el estado.',
					extraClass: 'logistica-user-panel__btn--action-edit',
					dataAttr: 'data-panel-edit',
					icon: 'dashicons-edit'
				}) +
				(completeHidden ? '' :
					panelIconActionBtn({
						label: 'Completado',
						tip: isLinked
							? 'Marca la actividad o compra original como completada.'
							: 'Marca la actividad como completada.',
						extraClass: 'logistica-user-panel__btn--action-done',
						dataAttr: 'data-panel-complete',
						icon: 'dashicons-yes-alt'
					})) +
				(isLinked ? '' :
					panelIconActionBtn({
						label: 'Eliminar',
						tip: 'Elimina permanentemente este registro del panel.',
						extraClass: 'logistica-user-panel__btn--action-delete',
						dataAttr: 'data-panel-delete',
						icon: 'dashicons-trash'
					})) +
			'</div>'
		);
	}

	function findChecklistRow(date, id) {
		if (!root) {
			return null;
		}

		var modalBody = root.querySelector('[data-user-panel-modal-body]');
		if (modalBody) {
			var modalRow = modalBody.querySelector('[data-check-date="' + date + '"][data-id="' + id + '"]');
			if (modalRow) {
				return modalRow;
			}
		}

		var rows = root.querySelectorAll('[data-check-date="' + date + '"]');
		for (var i = 0; i < rows.length; i++) {
			if (rows[i].getAttribute('data-id') === id) {
				return rows[i];
			}
		}

		return null;
	}

	function startChecklistEdit(date, id) {
		var linked = parseLinkedChecklistId(id);
		if (linked) {
			startEdit(linked.section, linked.sourceId);
			return;
		}

		var key = checklistEditKey(date, id);
		if (editingChecklistKey && editingChecklistKey !== key) {
			var active = parseChecklistEditKey(editingChecklistKey);
			if (active) {
				cancelChecklistEdit(active.date, active.id);
			}
		}

		var item = findChecklistItem(date, id);
		if (!item) {
			return;
		}

		editChecklistSnapshots[key] = JSON.parse(JSON.stringify(item));
		editingChecklistKey = key;
		openSectionEditModal('checklist', id, date);
		renderChecklist();
	}

	function cancelChecklistEdit(date, id) {
		var key = checklistEditKey(date, id);
		if (isUnsavedNewChecklist(date, id)) {
			clearUnsavedNewChecklist(date, id);
			delete editChecklistSnapshots[key];
			editingChecklistKey = '';
			closeEditModal();
			removeChecklistItem(date, id, false);
			return;
		}

		if (editChecklistSnapshots[key]) {
			var day = state.panel.checklist_days[date];
			if (day && Array.isArray(day.items)) {
				for (var i = 0; i < day.items.length; i++) {
					if (day.items[i].id === id) {
						day.items[i] = editChecklistSnapshots[key];
						break;
					}
				}
			}
		}

		delete editChecklistSnapshots[key];
		editingChecklistKey = '';
		closeEditModal();
		renderChecklist();
	}

	function collectChecklistFields(article) {
		var date = article.getAttribute('data-check-date');
		var id = article.getAttribute('data-id');
		var item = findChecklistItem(date, id);
		if (!item) {
			return null;
		}

		article.querySelectorAll('[data-field]').forEach(function (field) {
			var key = field.getAttribute('data-field');
			if (key) {
				applyChecklistFieldChange(item, key, field);
			}
		});

		return item;
	}

	function saveChecklistEdit(date, id) {
		var article = findChecklistRow(date, id);
		if (!article) {
			return;
		}

		collectChecklistFields(article);
		clearUnsavedNewChecklist(date, id);
		delete editChecklistSnapshots[checklistEditKey(date, id)];
		editingChecklistKey = '';
		closeEditModal();
		renderChecklist();
		savePanelNow();
	}

	function markChecklistComplete(date, id) {
		var linked = parseLinkedChecklistId(id);
		if (linked) {
			var source = findListItem(linked.section, linked.sourceId);
			if (!source) {
				return;
			}

			if (linked.section === 'agenda') {
				var agendaPrev = source.status || (source.done ? 'completado' : 'pendiente');
				source.status = 'completado';
				source.done = true;
				recordStatusChange(source, agendaPrev, 'completado', nowSql());
				source.updated_at = nowSql();
			} else {
				var previousStatus = source.status || 'pendiente';
				source.status = 'recibido';
				applyCompraStatusSideEffects(source, previousStatus);
				source.updated_at = nowSql();
			}

			renderAll();
			savePanelNow();
			return;
		}

		var item = findChecklistItem(date, id);
		if (!item) {
			return;
		}

		item.done = true;
		clearUnsavedNewChecklist(date, id);
		delete editChecklistSnapshots[checklistEditKey(date, id)];
		editingChecklistKey = '';
		if (isModalOpen()) {
			var modalCtx = getModalContext();
			if (modalCtx && modalCtx.section === 'checklist' && modalCtx.id === id && modalCtx.checkDate === date) {
				closeEditModal();
			}
		}
		renderChecklist();
		savePanelNow();
	}

	function handleChecklistPanelAction(event, action) {
		if (isChecklistReadOnlyWeek()) {
			return false;
		}

		var checkRow = event.target.closest('[data-check-date]');
		if (!checkRow) {
			return false;
		}

		var date = checkRow.getAttribute('data-check-date');
		var id = checkRow.getAttribute('data-id');
		if (!date || !id) {
			return false;
		}

		if (action === 'edit') {
			startChecklistEdit(date, id);
		} else if (action === 'save') {
			saveChecklistEdit(date, id);
		} else if (action === 'cancel') {
			cancelChecklistEdit(date, id);
		} else if (action === 'complete') {
			markChecklistComplete(date, id);
		} else if (action === 'delete') {
			requestPanelDelete('checklist', id, date);
		}

		return true;
	}

	function panelRowActionsHtml(section, item) {
		var completeHidden = isSectionItemComplete(section, item);
		var isManageable = section === 'compras' || section === 'agenda';
		var showResolve = isManageable && !completeHidden;
		var showComplete = !isManageable && section !== 'proveedores' && !completeHidden;
		var resolveTip = section === 'compras'
			? 'Novedad, finalizar (recibido) o posponer el aviso.'
			: 'Novedad, finalizar (completado) o posponer el aviso.';
		var completeLabel = section === 'compras' ? 'Recibido' : 'Completado';
		var completeTip = section === 'compras'
			? 'Marca la cotización o compra como recibida.'
			: 'Marca el registro como completado.';

		return (
			'<div class="logistica-user-panel__row-actions">' +
				panelIconActionBtn({
					label: 'Modificar',
					tip: 'Abre el formulario para editar los datos.',
					extraClass: 'logistica-user-panel__btn--action-edit',
					dataAttr: 'data-panel-edit',
					icon: 'dashicons-edit'
				}) +
				(showResolve ?
					panelIconActionBtn({
						label: 'Resolver',
						tip: resolveTip,
						extraClass: 'logistica-user-panel__btn--action-done',
						dataAttr: 'data-panel-resolve',
						icon: 'dashicons-yes-alt'
					}) : '') +
				(showComplete ?
					panelIconActionBtn({
						label: completeLabel,
						tip: completeTip,
						extraClass: 'logistica-user-panel__btn--action-done',
						dataAttr: 'data-panel-complete',
						icon: 'dashicons-yes-alt'
					}) : '') +
				panelIconActionBtn({
					label: 'Eliminar',
					tip: 'Elimina permanentemente este registro.',
					extraClass: 'logistica-user-panel__btn--action-delete',
					dataAttr: 'data-panel-delete',
					icon: 'dashicons-trash'
				}) +
			'</div>'
		);
	}

	function formatAgendaWhen(item) {
		if (!item.date && !item.time) {
			return '—';
		}

		var datePart = item.date ? formatShortDate(item.date) : '—';
		if (!item.time) {
			return datePart;
		}

		return datePart + ' · ' + item.time;
	}

	function findRowArticle(section, id) {
		if (!root) {
			return null;
		}

		var rows = root.querySelectorAll('[data-user-panel-item="' + section + '"]');
		for (var i = 0; i < rows.length; i++) {
			if (rows[i].getAttribute('data-id') === id) {
				return rows[i];
			}
		}

		return null;
	}

	function savePanelNow() {
		clearTimeout(saveTimer);
		setSaveStatus('Guardando…', 'saving');
		savePanel();
	}

	function startEdit(section, id) {
		if (editingItems[section] && editingItems[section] !== id) {
			cancelEdit(section, editingItems[section]);
		}

		var item = findListItem(section, id);
		if (!item) {
			return;
		}

		editSnapshots[section + ':' + id] = JSON.parse(JSON.stringify(item));
		editingItems[section] = id;
		openSectionEditModal(section, id);
		renderAll();
	}

	function cancelEdit(section, id) {
		if (isUnsavedNewItem(section, id)) {
			clearUnsavedNewItem(section, id);
			delete editSnapshots[section + ':' + id];
			editingItems[section] = '';
			closeEditModal();
			removeItem(section, id, false);
			return;
		}

		var key = section + ':' + id;
		if (editSnapshots[key]) {
			var list = state.panel[section];
			if (Array.isArray(list)) {
				for (var i = 0; i < list.length; i++) {
					if (list[i].id === id) {
						list[i] = editSnapshots[key];
						break;
					}
				}
			}
		}

		delete editSnapshots[key];
		editingItems[section] = '';
		closeEditModal();
		renderAll();
	}

	function collectRowFields(article) {
		var section = article.getAttribute('data-user-panel-item');
		var id = article.getAttribute('data-id');
		var item = findListItem(section, id);
		if (!item) {
			return null;
		}

		var previousStatus = '';
		if (section === 'compras' || section === 'agenda') {
			previousStatus = item.status || (section === 'agenda' && item.done ? 'completado' : 'pendiente');
		}

		article.querySelectorAll('[data-field]').forEach(function (field) {
			var key = field.getAttribute('data-field');
			if (!key) {
				return;
			}

			if (field.type === 'checkbox') {
				item[key] = field.checked;
			} else {
				item[key] = panelFieldValueFromInput(field);
			}
		});

		if (section === 'agenda') {
			ensureAgendaGestionFields(item);
			item.done = isAgendaComplete(item);
			if (previousStatus && previousStatus !== item.status) {
				recordStatusChange(item, previousStatus, item.status, nowSql());
			}
		}

		if (section === 'compras') {
			applyCompraStatusSideEffects(item, previousStatus);
		}

		if (section === 'pendientes' || section === 'compras' || section === 'proveedores' || section === 'agenda') {
			item.updated_at = nowSql();
		}

		return item;
	}

	function saveEdit(section, id) {
		var article = findEditFormArticle(section, id);
		if (!article) {
			return;
		}

		collectRowFields(article);
		clearUnsavedNewItem(section, id);
		delete editSnapshots[section + ':' + id];
		editingItems[section] = '';
		closeEditModal();
		renderAll();
		savePanelNow();
	}

	function markSectionItemComplete(section, id) {
		var item = findListItem(section, id);
		if (!item) {
			return;
		}

		if (section === 'agenda') {
			var agendaPrevious = item.status || (item.done ? 'completado' : 'pendiente');
			item.status = 'completado';
			item.done = true;
			recordStatusChange(item, agendaPrevious, 'completado', nowSql());
			item.updated_at = nowSql();
		} else if (section === 'compras') {
			var compraPreviousStatus = item.status || 'pendiente';
			item.status = 'recibido';
			applyCompraStatusSideEffects(item, compraPreviousStatus);
			item.updated_at = nowSql();
		} else if (section === 'pendientes') {
			item.status = 'terminado';
			item.updated_at = nowSql();
		}

		clearUnsavedNewItem(section, id);
		delete editSnapshots[section + ':' + id];
		editingItems[section] = '';
		if (isModalOpen()) {
			var modalCtx = getModalContext();
			if (modalCtx && modalCtx.section === section && modalCtx.id === id) {
				closeEditModal();
			}
		}
		renderAll();
		savePanelNow();
	}

	function setPanelLoading(active, message, immediate) {
		if (!root) {
			return;
		}

		if (window.LogisticaTabLoading) {
			if (active) {
				window.LogisticaTabLoading.show(root, message, immediate);
			} else {
				window.LogisticaTabLoading.hide(root);
			}
			return;
		}

		var overlay = root.querySelector('[data-user-panel-loading]');
		if (!overlay) {
			return;
		}

		var msgNode = overlay.querySelector('[data-user-panel-loading-message]');
		clearTimeout(panelLoadingTimer);
		panelLoadingTimer = null;

		if (!active) {
			overlay.hidden = true;
			overlay.setAttribute('aria-busy', 'false');
			root.classList.remove('is-panel-loading');
			return;
		}

		if (msgNode && message) {
			msgNode.textContent = message;
		}

		function reveal() {
			overlay.hidden = false;
			overlay.setAttribute('aria-busy', 'true');
			root.classList.add('is-panel-loading');
		}

		if (immediate) {
			reveal();
			return;
		}

		panelLoadingTimer = setTimeout(reveal, 500);
	}

	function setSaveStatus(text, type) {
		var node = root ? root.querySelector('[data-user-panel-save-status]') : null;
		if (!node) {
			return;
		}

		clearTimeout(saveStatusClearTimer);
		saveStatusClearTimer = null;

		node.classList.toggle('is-error', type === 'error');
		node.classList.toggle('is-saving', type === 'saving');
		node.classList.toggle('is-saved', type === 'saved');

		if (type === 'saving') {
			node.innerHTML =
				'<span class="logistica-user-panel__save-status-inner">' +
					'<span class="logistica-user-panel__save-spinner" aria-hidden="true"></span>' +
					'<span>' + escapeHtml(text || 'Guardando…') + '</span>' +
				'</span>';
			return;
		}

		node.textContent = text || '';

		if (type === 'saved') {
			saveStatusClearTimer = setTimeout(function () {
				setSaveStatus('', '');
			}, 2800);
		}
	}

	function scheduleSave() {
		if (!state) {
			return;
		}

		clearTimeout(saveTimer);
		setSaveStatus('Guardando…', 'saving');
		saveTimer = setTimeout(savePanel, SAVE_DELAY);
	}

	function savePanel() {
		var cfg = config();

		if (!state || !cfg.ajaxUrl) {
			setPanelLoading(false);
			return;
		}

		if (window.__logisticaSessionDead) {
			setPanelLoading(false);
			setSaveStatus('Sesión expirada. Vuelve a iniciar sesión.', 'error');
			if (window.LogisticaSessionGuardApi && typeof window.LogisticaSessionGuardApi.markExpired === 'function') {
				window.LogisticaSessionGuardApi.markExpired();
			}
			return;
		}

		var requestId = ++panelSaveRequestId;

		setPanelLoading(true, 'Guardando tu información…');

		var body = new URLSearchParams();
		body.append('action', 'logistica_save_user_panel');
		body.append('nonce', getUserPanelNonce());
		body.append('payload', JSON.stringify(state.panel));

		fetch(cfg.ajaxUrl, {
			method: 'POST',
			credentials: 'same-origin',
			headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
			body: body.toString()
		})
			.then(function (response) {
				return response.json().then(function (result) {
					return { response: response, result: result };
				});
			})
			.then(function (payload) {
				var result = payload.result;

				if (requestId !== panelSaveRequestId) {
					return;
				}

				if (!result || !result.success) {
					throw new Error((result && result.data && result.data.message) || 'Error al guardar');
				}

				if (result.data && result.data.panel) {
					state.panel = result.data.panel;
				}

				applyClockContext(result.data);

				setSaveStatus('Guardado ' + formatColombiaTimeHms(), 'saved');
				renderAll();
				updateClockDisplay();
				flushPendingAvisoEmails();
			})
			.catch(function (error) {
				if (requestId !== panelSaveRequestId) {
					return;
				}

				setSaveStatus(error.message || 'Error al guardar', 'error');
			})
			.finally(function () {
				if (requestId !== panelSaveRequestId) {
					return;
				}

				setPanelLoading(false);
			});
	}

	function importProveedores(file) {
		var cfg = config();

		if (!file || !state || !cfg.ajaxUrl) {
			return;
		}

		setSaveStatus('Importando…', 'saving');
		setPanelLoading(true, 'Importando proveedores…', true);

		var body = new FormData();
		body.append('action', 'logistica_import_panel_proveedores');
		body.append('nonce', getUserPanelNonce());
		body.append('proveedores_file', file);

		fetch(cfg.ajaxUrl, {
			method: 'POST',
			credentials: 'same-origin',
			body: body
		})
			.then(function (response) {
				return response.json();
			})
			.then(function (result) {
				if (!result || !result.success) {
					throw new Error((result && result.data && result.data.message) || 'Error al importar');
				}

				if (result.data && result.data.panel) {
					state.panel = result.data.panel;
				}

				proveedoresPage = 1;
				applyClockContext(result.data);
				renderAll();
				setSaveStatus(result.data.message || 'Importación completada', 'saved');
			})
			.catch(function (error) {
				setSaveStatus(error.message || 'Error al importar', 'error');
			})
			.finally(function () {
				setPanelLoading(false);
			});
	}

	function importCompras(file) {
		var cfg = config();

		if (!file || !state || !cfg.ajaxUrl) {
			return;
		}

		setSaveStatus('Importando…', 'saving');
		setPanelLoading(true, 'Importando compras…', true);

		var body = new FormData();
		body.append('action', 'logistica_import_panel_compras');
		body.append('nonce', getUserPanelNonce());
		body.append('compras_file', file);

		fetch(cfg.ajaxUrl, {
			method: 'POST',
			credentials: 'same-origin',
			body: body
		})
			.then(function (response) {
				return response.json();
			})
			.then(function (result) {
				if (!result || !result.success) {
					throw new Error((result && result.data && result.data.message) || 'Error al importar');
				}

				if (result.data && result.data.panel) {
					state.panel = result.data.panel;
				}

				resetPanelListPage('compras');
				applyClockContext(result.data);
				renderAll();
				setSaveStatus(result.data.message || 'Importación completada', 'saved');
			})
			.catch(function (error) {
				setSaveStatus(error.message || 'Error al importar', 'error');
			})
			.finally(function () {
				setPanelLoading(false);
			});
	}

	function navigateToTabSlug(tabSlug, deepLink) {
		navigateToResumePoint({
			tab_slug: tabSlug || '',
			deep_link: deepLink || ''
		});
	}

	function getQuickLinkOptions() {
		if (state && Array.isArray(state.quick_link_options) && state.quick_link_options.length) {
			return state.quick_link_options;
		}

		var tabs = config().navTabs || {};
		var urls = config().navTabUrls || {};

		return Object.keys(tabs).filter(function (slug) {
			return QUICK_LINK_EXCLUDED_TABS.indexOf(slug) === -1;
		}).map(function (slug) {
			return {
				slug: slug,
				label: tabs[slug],
				url: urls[slug] || ''
			};
		});
	}

	function getQuickLinkMax() {
		var max = parseInt(state.max_quick_links, 10);
		return Number.isFinite(max) && max > 0 ? max : 6;
	}

	function getQuickLinkOption(slug) {
		return getQuickLinkOptions().find(function (option) {
			return option.slug === slug;
		}) || null;
	}

	function getQuickLinks() {
		if (!state || !state.panel) {
			return [];
		}

		return Array.isArray(state.panel.quick_links) ? state.panel.quick_links.slice() : [];
	}

	function setQuickLinksEditorOpen(open) {
		var editor = panelQuery('[data-user-panel-quick-links-editor]');
		var editBtn = panelQuery('[data-user-panel-quick-links-edit]');
		var actions = panelQuery('[data-user-panel-quick-links-editor-actions]');

		quickLinksEditing = !!open;

		if (editor) {
			editor.hidden = !open;
		}

		if (actions) {
			actions.hidden = !open;
		}

		if (editBtn) {
			editBtn.setAttribute('aria-expanded', open ? 'true' : 'false');
			editBtn.classList.toggle('is-active', open);
		}

		if (open) {
			quickLinksDraft = getQuickLinks();
			renderQuickLinksEditor();
		} else {
			renderQuickLinks();
		}
	}

	function renderQuickLinks() {
		var list = panelQuery('[data-user-panel-quick-links-list]');
		var hint = panelQuery('.logistica-user-panel__quick-links-hint');

		if (!list) {
			return;
		}

		var slugs = quickLinksEditing ? quickLinksDraft.slice() : getQuickLinks();
		var options = getQuickLinkOptions();

		if (!slugs.length) {
			list.innerHTML = '<p class="logistica-user-panel__empty logistica-user-panel__empty--compact">' +
				(quickLinksEditing ?
					'Selecciona secciones abajo y pulsa «Guardar accesos».' :
					'Sin accesos fijados. Pulsa «Personalizar» para elegir tus secciones.') +
			'</p>';
			if (hint) {
				hint.hidden = quickLinksEditing;
			}
			return;
		}

		if (hint) {
			hint.hidden = false;
		}

		list.innerHTML = slugs.map(function (slug) {
			var option = getQuickLinkOption(slug);
			var label = option ? option.label : (config().navTabs && config().navTabs[slug]) || slug;

			return (
				'<button type="button" class="logistica-user-panel__stat logistica-user-panel__stat--link" data-user-panel-quick-link="' + escapeHtml(slug) + '">' +
					'<span>' + escapeHtml(label) + '</span>' +
					'<span class="logistica-user-panel__stat-arrow dashicons dashicons-arrow-right-alt2" aria-hidden="true"></span>' +
				'</button>'
			);
		}).join('');

		if (!options.length && !slugs.length) {
			list.innerHTML = '<p class="logistica-user-panel__empty logistica-user-panel__empty--compact">No hay secciones disponibles para fijar.</p>';
		}
	}

	function renderQuickLinksEditor() {
		var wrap = panelQuery('[data-user-panel-quick-links-options]');
		var title = panelQuery('.logistica-user-panel__quick-links-editor-title');

		if (!wrap) {
			return;
		}

		var options = getQuickLinkOptions();
		var max = getQuickLinkMax();

		if (title) {
			title.textContent = 'Elige hasta ' + max + ' secciones';
		}

		if (!options.length) {
			wrap.innerHTML = '<p class="logistica-user-panel__empty logistica-user-panel__empty--compact">No hay secciones operativas disponibles.</p>';
			return;
		}

		wrap.innerHTML = options.map(function (option) {
			var active = quickLinksDraft.indexOf(option.slug) !== -1;

			return (
				'<button type="button" class="logistica-user-panel__quick-links-option' + (active ? ' is-active' : '') + '" data-quick-link-option="' + escapeHtml(option.slug) + '" aria-pressed="' + (active ? 'true' : 'false') + '">' +
					'<span class="logistica-user-panel__quick-links-check" aria-hidden="true">' +
						(active ? '<span class="dashicons dashicons-yes"></span>' : '') +
					'</span>' +
					'<span class="logistica-user-panel__quick-links-option-label">' + escapeHtml(option.label) + '</span>' +
				'</button>'
			);
		}).join('');
	}

	function toggleQuickLinkDraft(slug) {
		var max = getQuickLinkMax();
		var index = quickLinksDraft.indexOf(slug);

		if (index !== -1) {
			quickLinksDraft.splice(index, 1);
			renderQuickLinksEditor();
			renderQuickLinks();
			return;
		}

		if (quickLinksDraft.length >= max) {
			setSaveStatus('Máximo ' + max + ' accesos rápidos.', 'error');
			return;
		}

		quickLinksDraft.push(slug);
		renderQuickLinksEditor();
		renderQuickLinks();
	}

	function saveQuickLinks() {
		var cfg = config();

		if (!cfg.ajaxUrl) {
			return;
		}

		setSaveStatus('Guardando accesos…', 'saving');

		var body = new URLSearchParams();
		body.append('action', 'logistica_save_quick_links');
		body.append('nonce', getUserPanelNonce());
		body.append('slugs', JSON.stringify(quickLinksDraft));

		fetch(cfg.ajaxUrl, {
			method: 'POST',
			credentials: 'same-origin',
			headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
			body: body.toString()
		})
			.then(function (response) {
				return response.json();
			})
			.then(function (result) {
				if (!result || !result.success) {
					throw new Error((result && result.data && result.data.message) || 'Error al guardar accesos');
				}

				var saved = Array.isArray(result.data.quick_links) ? result.data.quick_links : [];

				if (quickLinksDraft.length && !saved.length) {
					throw new Error('No se pudieron guardar los accesos seleccionados. Recarga la página e intenta de nuevo.');
				}

				state.panel.quick_links = saved.length ? saved : quickLinksDraft.slice();
				setQuickLinksEditorOpen(false);
				renderQuickLinks();
				setSaveStatus(result.data.message || 'Accesos guardados.', 'saved');
			})
			.catch(function (error) {
				setSaveStatus(error.message || 'Error al guardar accesos', 'error');
			});
	}

	function renderUserCard() {
		var node = root.querySelector('[data-user-panel-user-card]');
		if (!node || !state.user) {
			return;
		}

		var user = state.user;
		var cfg = config();
		var profileLabel = state.profile_label || cfg.profile_label || 'Ver perfil';
		var profileTab = state.profile_tab || cfg.profile_tab || 'logistica-perfil';
		var profileHtml = profileLabel
			? '<button type="button" class="logistica-user-panel__logout logistica-user-panel__profile-btn" data-user-panel-open-profile data-profile-tab="' + escapeHtml(profileTab) + '">' +
				'<span class="dashicons dashicons-admin-users" aria-hidden="true"></span>' +
				escapeHtml(profileLabel) +
			'</button>'
			: '';

		node.innerHTML =
			'<div class="logistica-user-panel__avatar">' +
				(user.avatar_url ? '<img src="' + escapeHtml(user.avatar_url) + '" alt="" width="72" height="72" loading="lazy" decoding="async">' : '') +
			'</div>' +
			'<div class="logistica-user-panel__user-meta">' +
				'<strong>' + escapeHtml(user.display_name || '') + '</strong>' +
				'<span>' + escapeHtml(user.email || '') + '</span>' +
				(user.role ? '<span class="logistica-user-panel__role">' + escapeHtml(user.role) + '</span>' : '') +
			'</div>' +
			profileHtml +
			'<div class="logistica-user-panel__clock" data-user-panel-clock aria-live="polite"></div>';
		updateClockDisplay();
	}

	function renderPendientes() {
		var list = root.querySelector('[data-user-panel-list="pendientes"]');
		if (!list) {
			return;
		}

		var items = orderListItemsForDisplay('pendientes', state.panel.pendientes || []);
		if (!items.length) {
			list.innerHTML = '<p class="logistica-user-panel__empty">Sin pendientes registrados.</p>';
			return;
		}

		list.innerHTML = items.map(function (item) {
			var complete = isSectionItemComplete('pendientes', item);
			var rowClass = rowStatusClass(complete, false);

			var notesHtml = item.notes
				? '<p class="logistica-user-panel__row-notes">' + escapeHtml(item.notes) + '</p>'
				: '';

			return (
				'<article class="' + rowClass + '" data-user-panel-item="pendientes" data-id="' + escapeHtml(item.id) + '">' +
					'<div class="logistica-user-panel__row-body">' +
						'<div class="logistica-user-panel__row-head">' +
							panelRowTitleBlock(item.title || 'Sin título', 'pendientes', item.id) +
							'<div class="logistica-user-panel__row-badges">' +
								'<span class="' + badgeClass('logistica-user-panel__badge', item.status) + '">' +
									escapeHtml(labelMap(state.pendiente_statuses, item.status)) +
								'</span>' +
							'</div>' +
						'</div>' +
						notesHtml +
						'<span class="logistica-user-panel__updated">Actualizado: ' + escapeHtml(formatColombiaDateTime(item.updated_at)) + '</span>' +
					'</div>' +
					panelRowActionsHtml('pendientes', item) +
				'</article>'
			);
		}).join('');
	}

	function getResumeItems() {
		return (state.panel.resume_points || []).filter(function (item) {
			return item.auto && item.tab_slug;
		});
	}

	function getResumeItemById(pointId) {
		return (state.panel.resume_points || []).find(function (item) {
			return String(item.id) === String(pointId);
		}) || null;
	}

	function handleResumePointOpen(event) {
		if (event.target.closest('[data-resume-dismiss]')) {
			return false;
		}

		var trigger = event.target.closest('[data-resume-open], .logistica-user-panel__resume-card--linked');

		if (!trigger || !root.contains(trigger)) {
			return false;
		}

		var card = trigger.closest('[data-user-panel-item="resume_points"]') || trigger;
		var item = getResumeItemById(card.getAttribute('data-id') || '');

		if (!item) {
			return false;
		}

		event.preventDefault();
		navigateToResumePoint(item);
		return true;
	}

	function clampResumeOffset(total) {
		var maxOffset = Math.max(0, total - RESUME_VISIBLE);
		if (resumePointsOffset > maxOffset) {
			resumePointsOffset = maxOffset;
		}
		if (resumePointsOffset < 0) {
			resumePointsOffset = 0;
		}
	}

	function renderResumeItemHtml(item, tabLabels, tabUrls) {
		var tabSlug = item.tab_slug || '';
		var tabLabel = tabLabels[tabSlug] || tabSlug || 'Sección';
		var resumeUrl = buildResumeUrl(item, tabUrls);
		var contextHtml = item.context
			? '<p class="logistica-user-panel__resume-context">' + escapeHtml(item.context) + '</p>'
			: '';

		return (
			'<article class="logistica-user-panel__resume-card' + (resumeUrl ? ' logistica-user-panel__resume-card--linked' : '') + '" data-user-panel-item="resume_points" data-id="' + escapeHtml(item.id) + '"' +
				(resumeUrl ? ' data-resume-url="' + escapeHtml(resumeUrl) + '" tabindex="0" role="link"' : '') + '>' +
				'<div class="logistica-user-panel__resume-card-body">' +
					'<div class="logistica-user-panel__resume-head">' +
						'<strong class="logistica-user-panel__resume-title">' + escapeHtml(item.title || tabLabel) + '</strong>' +
						(item.auto ? '<span class="logistica-user-panel__resume-auto">Auto</span>' : '') +
					'</div>' +
					contextHtml +
					'<div class="logistica-user-panel__resume-meta">' +
						'<span class="logistica-user-panel__resume-section">' + escapeHtml(tabLabel) + '</span>' +
						'<span class="logistica-user-panel__resume-dot" aria-hidden="true">·</span>' +
						'<time class="logistica-user-panel__updated">' + escapeHtml(formatColombiaDateTime(item.updated_at)) + '</time>' +
					'</div>' +
				'</div>' +
				'<div class="logistica-user-panel__resume-actions">' +
					(resumeUrl ?
						'<a class="logistica-user-panel__resume-link" href="' + escapeHtml(resumeUrl) + '" data-resume-open>Retomar</a>' :
						'') +
					'<button type="button" class="logistica-user-panel__resume-dismiss" data-resume-dismiss="' + escapeHtml(item.id) + '">Quitar</button>' +
				'</div>' +
			'</article>'
		);
	}

	function renderResumePoints() {
		var list = root.querySelector('[data-user-panel-list="resume_points"]');
		if (!list) {
			return;
		}

		var items = getResumeItems();
		var cfg = config();
		var tabUrls = cfg.navTabUrls || {};
		var tabLabels = cfg.navTabs || {};
		var carousel = root.querySelector('[data-user-panel-resume-carousel]');
		var nav = carousel ? carousel.querySelector('[data-user-panel-resume-nav]') : null;

		clampResumeOffset(items.length);

		if (!items.length) {
			list.innerHTML = '<p class="logistica-user-panel__empty logistica-user-panel__empty--compact">Sin interrupciones recientes. Al salir de una sección se registrará aquí automáticamente.</p>';
			if (nav) {
				nav.hidden = true;
			}
			return;
		}

		var visible = items.slice(resumePointsOffset, resumePointsOffset + RESUME_VISIBLE);
		list.innerHTML = visible.map(function (item) {
			return renderResumeItemHtml(item, tabLabels, tabUrls);
		}).join('');

		if (nav) {
			var showNav = items.length > RESUME_VISIBLE;
			nav.hidden = !showNav;
			if (showNav) {
				var prevBtn = nav.querySelector('[data-user-panel-resume-prev]');
				var nextBtn = nav.querySelector('[data-user-panel-resume-next]');
				var indicator = nav.querySelector('[data-user-panel-resume-indicator]');
				var from = resumePointsOffset + 1;
				var to = Math.min(resumePointsOffset + RESUME_VISIBLE, items.length);

				if (prevBtn) {
					prevBtn.disabled = resumePointsOffset <= 0;
				}
				if (nextBtn) {
					nextBtn.disabled = resumePointsOffset + RESUME_VISIBLE >= items.length;
				}
				if (indicator) {
					indicator.textContent = from + '–' + to + ' de ' + items.length;
				}
			}
		}
	}

	function mergeResumePoints(points) {
		if (!state || !Array.isArray(points)) {
			return;
		}

		state.panel.resume_points = points;
		clampResumeOffset(getResumeItems().length);
		renderResumePoints();
	}

	function dismissResumePoint(pointId) {
		var cfg = config();
		if (!pointId || !cfg.ajaxUrl) {
			return;
		}

		var body = new URLSearchParams();
		body.append('action', 'logistica_dismiss_resume_point');
		body.append('nonce', getUserPanelNonce());
		body.append('point_id', pointId);

		fetch(cfg.ajaxUrl, {
			method: 'POST',
			credentials: 'same-origin',
			headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
			body: body.toString()
		})
			.then(function (response) {
				return response.json();
			})
			.then(function (result) {
				if (!result || !result.success || !result.data) {
					throw new Error((result && result.data && result.data.message) || 'No se pudo quitar el registro.');
				}

				mergeResumePoints(result.data.resume_points || []);
			})
			.catch(function (error) {
				window.alert(error.message || 'No se pudo quitar el registro.');
			});
	}

	function getProveedorNombre(id) {
		if (!id || !state || !Array.isArray(state.panel.proveedores)) {
			return '';
		}

		for (var i = 0; i < state.panel.proveedores.length; i++) {
			if (state.panel.proveedores[i].id === id) {
				return state.panel.proveedores[i].nombre || '';
			}
		}

		return '';
	}

	function applyCompraStatusSideEffects(item, previousStatus) {
		if (!item) {
			return;
		}

		ensureCompraGestionFields(item);

		var status = item.status || 'pendiente';
		var prev = previousStatus || '';

		if (prev && prev !== status) {
			recordCompraStatusChange(item, prev, status, nowSql());
		}

		if (status === 'recibido') {
			if (prev !== 'recibido' || !item.fecha_recibido) {
				item.fecha_recibido = nowSql();
			}
			return;
		}

		if (prev === 'recibido') {
			item.fecha_recibido = '';
		}
	}

	function getProveedorHistorialCompras(proveedorId) {
		if (!proveedorId || !state || !state.panel || !Array.isArray(state.panel.compras)) {
			return [];
		}

		return state.panel.compras
			.filter(function (compra) {
				return compra.proveedor_id === proveedorId;
			})
			.slice()
			.sort(function (a, b) {
				var dateA = String(a.fecha_recibido || a.updated_at || '');
				var dateB = String(b.fecha_recibido || b.updated_at || '');
				if (dateA !== dateB) {
					return dateB.localeCompare(dateA);
				}
				return String(b.updated_at || '').localeCompare(String(a.updated_at || ''));
			});
	}

	function formatCompraReceivedDate(compra) {
		var raw = compra.fecha_recibido || compra.updated_at || '';
		if (!raw) {
			return '-';
		}

		var datePart = String(raw).slice(0, 10);
		if (/^\d{4}-\d{2}-\d{2}$/.test(datePart)) {
			return formatShortDate(datePart);
		}

		return formatColombiaDateTime(raw);
	}

	function renderProveedorHistorialCompras(proveedorId) {
		var rows = getProveedorHistorialCompras(proveedorId);

		if (!rows.length) {
			return (
				'<section class="logistica-user-panel__proveedor-history">' +
					'<h3 class="logistica-user-panel__proveedor-history-title">Historial de compras y tiempos</h3>' +
					'<p class="logistica-user-panel__empty logistica-user-panel__empty--compact">Sin compras para este proveedor.</p>' +
				'</section>'
			);
		}

		var tableRows = rows.map(function (compra) {
			ensureCompraGestionFields(compra);
			return (
				'<tr>' +
					'<td>' + escapeHtml(compraProductoLabel(compra)) + '</td>' +
					'<td>' + escapeHtml(compra.referencia || '-') + '</td>' +
					'<td>' + escapeHtml(labelMap(state.compra_statuses, compra.status)) + '</td>' +
					'<td class="is-numeric">' + escapeHtml(formatDurationSeconds(getCompraGestionTotalSeconds(compra))) + '</td>' +
					'<td class="is-numeric">' + escapeHtml(String((compra.novedades || []).length)) + '</td>' +
					'<td class="is-date">' + escapeHtml(compra.status === 'recibido' ? formatCompraReceivedDate(compra) : '-') + '</td>' +
				'</tr>'
			);
		}).join('');

		return (
			'<section class="logistica-user-panel__proveedor-history">' +
				'<h3 class="logistica-user-panel__proveedor-history-title">Historial de compras y tiempos</h3>' +
				'<p class="logistica-user-panel__proveedor-history-meta">' + rows.length + ' compra' + (rows.length === 1 ? '' : 's') + ' con este proveedor</p>' +
				'<div class="logistica-user-panel__proveedor-history-scroll">' +
					'<table class="logistica-user-panel__proveedor-history-table">' +
						'<thead><tr>' +
							'<th>Producto</th>' +
							'<th>Referencia</th>' +
							'<th>Estado</th>' +
							'<th>Tiempo gestión</th>' +
							'<th>Novedades</th>' +
							'<th>Fecha recibida</th>' +
						'</tr></thead>' +
						'<tbody>' + tableRows + '</tbody>' +
					'</table>' +
				'</div>' +
			'</section>'
		);
	}

	function proveedorOptionsHtml(selectedId) {
		var options = '<option value="">— Empresa —</option>';
		var list = (state && state.panel && state.panel.proveedores) ? state.panel.proveedores : [];

		list.forEach(function (proveedor) {
			options += '<option value="' + escapeHtml(proveedor.id) + '"' +
				(proveedor.id === selectedId ? ' selected' : '') + '>' +
				escapeHtml(proveedor.nombre || 'Sin nombre') + '</option>';
		});

		return options;
	}

	function compraStatusOptionsHtml(selected) {
		return Object.keys(state.compra_statuses || {}).filter(function (key) {
			return key !== 'recibido';
		}).map(function (key) {
			return '<option value="' + escapeHtml(key) + '"' + (key === selected ? ' selected' : '') + '>' +
				escapeHtml(state.compra_statuses[key]) + '</option>';
		}).join('');
	}

	function compraProductoLabel(item) {
		return item.producto_ofrecido || item.item || 'Sin producto';
	}

	function panelListSelector(section, part) {
		return '[data-user-panel-' + section + '-' + part + ']';
	}

	function loadPanelListPageSize(section) {
		var cfg = panelListPagination[section];
		if (!cfg || !root) {
			return;
		}

		var select = root.querySelector(panelListSelector(section, 'page-size'));
		var stored = 0;

		try {
			stored = parseInt(localStorage.getItem(cfg.storageKey), 10);
		} catch (error) {
			stored = 0;
		}

		if (PANEL_LIST_PAGE_SIZES.indexOf(stored) !== -1) {
			cfg.pageSize = stored;
		}

		if (select) {
			select.value = String(cfg.pageSize);
		}
	}

	function resetPanelListPage(section) {
		if (panelListPagination[section]) {
			panelListPagination[section].page = 1;
		}
	}

	function paginatePanelListItems(section, items) {
		var cfg = panelListPagination[section];
		var total = items.length;
		var totalPages = Math.max(1, Math.ceil(total / cfg.pageSize));

		if (cfg.page > totalPages) {
			cfg.page = totalPages;
		}
		if (cfg.page < 1) {
			cfg.page = 1;
		}

		var startIndex = (cfg.page - 1) * cfg.pageSize;

		return {
			items: items.slice(startIndex, startIndex + cfg.pageSize),
			total: total,
			totalPages: totalPages,
			start: total ? startIndex + 1 : 0,
			end: total ? Math.min(cfg.page * cfg.pageSize, total) : 0
		};
	}

	function isPanelListFilterActive(section) {
		var filters = panelListFilters[section];
		if (!filters) {
			return false;
		}

		return !!(filters.status || filters.priority || filters.fecha_requerida);
	}

	function syncPanelListFilterControls(section) {
		if (!root || !panelListFilters[section]) {
			return;
		}

		var filters = panelListFilters[section];
		root.querySelectorAll('[data-user-panel-' + section + '-filter]').forEach(function (field) {
			var key = field.getAttribute('data-user-panel-' + section + '-filter');
			if (key && Object.prototype.hasOwnProperty.call(filters, key) && field.value !== filters[key]) {
				field.value = filters[key];
			}
		});
	}

	function clearPanelListFilters(section) {
		if (!panelListFilters[section]) {
			return;
		}

		panelListFilters[section].status = '';
		panelListFilters[section].priority = '';
		panelListFilters[section].fecha_requerida = '';
		syncPanelListFilterControls(section);
	}

	function filterAgendaItems(items) {
		var filters = panelListFilters.agenda;

		return items.filter(function (item) {
			var status = item.status || (item.done ? 'completado' : 'pendiente');
			if (filters.status && status !== filters.status) {
				return false;
			}
			if (filters.priority && (item.priority || 'media') !== filters.priority) {
				return false;
			}
			if (filters.fecha_requerida && item.date !== filters.fecha_requerida) {
				return false;
			}
			return true;
		});
	}

	function filterComprasItems(items) {
		var filters = panelListFilters.compras;

		return items.filter(function (item) {
			if (filters.status && (item.status || 'pendiente') !== filters.status) {
				return false;
			}
			if (filters.priority && (item.priority || 'media') !== filters.priority) {
				return false;
			}
			if (filters.fecha_requerida && (item.fecha_requerida || '') !== filters.fecha_requerida) {
				return false;
			}
			return true;
		});
	}

	function applyPanelListFilters(section, items) {
		if (section === 'agenda') {
			return filterAgendaItems(items);
		}
		if (section === 'compras') {
			return filterComprasItems(items);
		}
		return items;
	}

	function updatePanelListFilterToolbar(section, totalItems, visibleCount) {
		if (!root) {
			return;
		}

		var toolbar = root.querySelector('[data-user-panel-' + section + '-filters]');
		var countEl = root.querySelector('[data-user-panel-' + section + '-filter-count]');
		var clearBtn = root.querySelector('[data-user-panel-' + section + '-filter-clear]');
		var filterActive = isPanelListFilterActive(section);
		var countLabel = section === 'agenda'
			? (visibleCount === 1 ? 'actividad' : 'actividades')
			: (visibleCount === 1 ? 'registro' : 'registros');
		var totalLabel = section === 'agenda'
			? (totalItems === 1 ? 'actividad' : 'actividades')
			: (totalItems === 1 ? 'registro' : 'registros');

		if (toolbar) {
			toolbar.hidden = totalItems === 0;
		}

		if (countEl) {
			if (!totalItems) {
				countEl.textContent = '';
			} else if (filterActive && visibleCount !== totalItems) {
				countEl.textContent = visibleCount + ' de ' + totalItems + ' ' + countLabel;
			} else {
				countEl.textContent = totalItems + ' ' + totalLabel;
			}
		}

		if (clearBtn) {
			clearBtn.hidden = !filterActive;
		}
	}

	function bindPanelListFilters(section, renderFn) {
		var board = root ? root.querySelector('[data-user-panel-' + section + '-board]') : null;
		if (!board || board.dataset.panelListFiltersBound === '1') {
			return;
		}

		board.dataset.panelListFiltersBound = '1';

		board.addEventListener('change', function (event) {
			var field = event.target.closest('[data-user-panel-' + section + '-filter]');
			if (!field || !panelListFilters[section]) {
				return;
			}

			var key = field.getAttribute('data-user-panel-' + section + '-filter');
			if (!key || !Object.prototype.hasOwnProperty.call(panelListFilters[section], key)) {
				return;
			}

			panelListFilters[section][key] = String(field.value || '');
			resetPanelListPage(section);
			renderFn();
		});

		board.addEventListener('click', function (event) {
			if (!event.target.closest('[data-user-panel-' + section + '-filter-clear]')) {
				return;
			}

			clearPanelListFilters(section);
			resetPanelListPage(section);
			renderFn();
		});
	}

	function updatePanelListPaginationUi(section, visibleCount) {
		var cfg = panelListPagination[section];
		if (!cfg || !root) {
			return;
		}

		var pagination = root.querySelector(panelListSelector(section, 'pagination'));
		var pageInfo = root.querySelector(panelListSelector(section, 'page-info'));
		var pageLabel = root.querySelector(panelListSelector(section, 'page-label'));
		var prevBtn = root.querySelector(panelListSelector(section, 'page-prev'));
		var nextBtn = root.querySelector(panelListSelector(section, 'page-next'));
		var totalPages = Math.max(1, Math.ceil(visibleCount / cfg.pageSize));
		var start = visibleCount ? ((cfg.page - 1) * cfg.pageSize) + 1 : 0;
		var end = visibleCount ? Math.min(cfg.page * cfg.pageSize, visibleCount) : 0;

		if (pagination) {
			pagination.hidden = visibleCount <= cfg.pageSize;
		}

		if (pageLabel) {
			pageLabel.textContent = visibleCount > 0
				? ('Página ' + cfg.page + ' de ' + totalPages)
				: '';
		}

		if (pageInfo) {
			pageInfo.textContent = visibleCount > 0
				? ('Mostrando ' + start + '-' + end + ' de ' + visibleCount)
				: '';
		}

		if (prevBtn) {
			prevBtn.disabled = cfg.page <= 1 || visibleCount === 0;
		}

		if (nextBtn) {
			nextBtn.disabled = cfg.page >= totalPages || visibleCount === 0;
		}
	}

	function bindPanelListPagination(section, renderFn) {
		var board = root ? root.querySelector('[data-user-panel-' + section + '-board]') : null;
		if (!board || board.dataset.panelListBound === '1') {
			return;
		}

		board.dataset.panelListBound = '1';
		loadPanelListPageSize(section);

		board.addEventListener('change', function (event) {
			var pageSizeSelect = event.target.closest(panelListSelector(section, 'page-size'));
			if (!pageSizeSelect) {
				return;
			}

			var cfg = panelListPagination[section];
			cfg.pageSize = parseInt(pageSizeSelect.value, 10) || 3;
			cfg.page = 1;

			try {
				localStorage.setItem(cfg.storageKey, String(cfg.pageSize));
			} catch (error) {
				// Storage may be unavailable.
			}

			renderFn();
		});

		board.addEventListener('click', function (event) {
			var cfg = panelListPagination[section];

			if (event.target.closest(panelListSelector(section, 'page-prev'))) {
				if (cfg.page > 1) {
					cfg.page -= 1;
					renderFn();
				}
				return;
			}

			if (event.target.closest(panelListSelector(section, 'page-next'))) {
				cfg.page += 1;
				renderFn();
			}
		});
	}

	function proveedorSearchHaystack(item) {
		return [
			item.nombre,
			item.contacto,
			item.email,
			item.telefono,
			item.descripcion
		].map(function (value) {
			return String(value || '').trim().toLowerCase();
		}).join(' ');
	}

	function proveedorMatchesSearch(item, query) {
		if (!query) {
			return true;
		}

		return proveedorSearchHaystack(item).indexOf(query) !== -1;
	}

	function getProveedoresPageSizeSelect() {
		return root ? root.querySelector('[data-user-panel-proveedores-page-size]') : null;
	}

	function loadProveedoresPageSize() {
		var select = getProveedoresPageSizeSelect();
		var stored = 0;

		try {
			stored = parseInt(localStorage.getItem('logistica_panel_proveedores_page_size_v1'), 10);
		} catch (error) {
			stored = 0;
		}

		if (stored === 3 || stored === 5 || stored === 10 || stored === 25 || stored === 50) {
			proveedoresPageSize = stored;
		}

		if (select) {
			select.value = String(proveedoresPageSize);
		}
	}

	function updateProveedoresPaginationUi(totalItems, visibleCount) {
		var toolbar = root.querySelector('[data-user-panel-proveedores-toolbar]');
		var countEl = root.querySelector('[data-user-panel-proveedores-count]');
		var pagination = root.querySelector('[data-user-panel-proveedores-pagination]');
		var pageInfo = root.querySelector('[data-user-panel-proveedores-page-info]');
		var pageLabel = root.querySelector('[data-user-panel-proveedores-page-label]');
		var prevBtn = root.querySelector('[data-user-panel-proveedores-page-prev]');
		var nextBtn = root.querySelector('[data-user-panel-proveedores-page-next]');
		var totalPages = Math.max(1, Math.ceil(visibleCount / proveedoresPageSize));
		var start = visibleCount ? ((proveedoresPage - 1) * proveedoresPageSize) + 1 : 0;
		var end = visibleCount ? Math.min(proveedoresPage * proveedoresPageSize, visibleCount) : 0;
		var searchActive = !!proveedoresSearchQuery;

		if (toolbar) {
			toolbar.hidden = totalItems === 0;
		}

		if (countEl) {
			if (!totalItems) {
				countEl.textContent = '';
			} else if (searchActive && visibleCount !== totalItems) {
				countEl.textContent = visibleCount + ' de ' + totalItems + ' proveedores';
			} else {
				countEl.textContent = totalItems + (totalItems === 1 ? ' proveedor' : ' proveedores');
			}
		}

		if (pagination) {
			pagination.hidden = visibleCount <= proveedoresPageSize;
		}

		if (pageLabel) {
			pageLabel.textContent = visibleCount > 0
				? ('Página ' + proveedoresPage + ' de ' + totalPages)
				: '';
		}

		if (pageInfo) {
			pageInfo.textContent = visibleCount > 0
				? ('Mostrando ' + start + '-' + end + ' de ' + visibleCount)
				: '';
		}

		if (prevBtn) {
			prevBtn.disabled = proveedoresPage <= 1 || visibleCount === 0;
		}

		if (nextBtn) {
			nextBtn.disabled = proveedoresPage >= totalPages || visibleCount === 0;
		}
	}

	function bindProveedoresListControls() {
		var board = root ? root.querySelector('[data-user-panel-proveedores-board]') : null;
		if (!board || board.dataset.proveedoresControlsBound === '1') {
			return;
		}

		board.dataset.proveedoresControlsBound = '1';
		loadProveedoresPageSize();

		board.addEventListener('input', function (event) {
			var searchInput = event.target.closest('[data-user-panel-proveedores-search]');
			if (!searchInput) {
				return;
			}

			if (proveedoresSearchTimer) {
				window.clearTimeout(proveedoresSearchTimer);
			}

			proveedoresSearchTimer = window.setTimeout(function () {
				var nextQuery = String(searchInput.value || '').trim().toLowerCase();
				if (nextQuery === proveedoresSearchQuery) {
					return;
				}

				proveedoresSearchQuery = nextQuery;
				proveedoresPage = 1;
				renderProveedores();
			}, 220);
		});

		board.addEventListener('change', function (event) {
			var pageSizeSelect = event.target.closest('[data-user-panel-proveedores-page-size]');
			if (!pageSizeSelect) {
				return;
			}

			proveedoresPageSize = parseInt(pageSizeSelect.value, 10) || 3;
			proveedoresPage = 1;

			try {
				localStorage.setItem('logistica_panel_proveedores_page_size_v1', String(proveedoresPageSize));
			} catch (error) {
				// Storage may be unavailable.
			}

			renderProveedores();
		});

		board.addEventListener('click', function (event) {
			if (event.target.closest('[data-user-panel-proveedores-page-prev]')) {
				if (proveedoresPage > 1) {
					proveedoresPage -= 1;
					renderProveedores();
				}
				return;
			}

			if (event.target.closest('[data-user-panel-proveedores-page-next]')) {
				proveedoresPage += 1;
				renderProveedores();
			}
		});
	}

	function renderProveedorViewCard(item) {
		return (
			'<div class="logistica-user-panel__proveedor-card">' +
				'<div class="logistica-user-panel__proveedor-head">' +
					'<div class="logistica-user-panel__proveedor-head-text">' +
						'<div class="logistica-user-panel__row-title-wrap">' +
							panelViewEyeBtn('proveedores', item.id) +
							'<strong class="logistica-user-panel__proveedor-name">' + escapeHtml(item.nombre || 'Sin nombre') + '</strong>' +
						'</div>' +
					'</div>' +
				'</div>' +
			'</div>'
		);
	}

	function renderProveedores() {
		var list = root.querySelector('[data-user-panel-list="proveedores"]');
		if (!list) {
			return;
		}

		bindProveedoresListControls();

		if (!state.panel.proveedores) {
			state.panel.proveedores = [];
		}

		discardOrphanedDrafts('proveedores');

		var allItems = orderListItemsForDisplay('proveedores', state.panel.proveedores || []);
		var searchInput = root.querySelector('[data-user-panel-proveedores-search]');
		if (searchInput && String(searchInput.value || '').trim().toLowerCase() !== proveedoresSearchQuery) {
			searchInput.value = proveedoresSearchQuery;
		}

		if (!allItems.length) {
			proveedoresPage = 1;
			updateProveedoresPaginationUi(0, 0);
			list.innerHTML = '<p class="logistica-user-panel__empty">Sin proveedores registrados.</p>';
			return;
		}

		var filteredItems = allItems.filter(function (item) {
			return proveedorMatchesSearch(item, proveedoresSearchQuery);
		});

		var totalPages = Math.max(1, Math.ceil(filteredItems.length / proveedoresPageSize));
		if (proveedoresPage > totalPages) {
			proveedoresPage = totalPages;
		}
		if (proveedoresPage < 1) {
			proveedoresPage = 1;
		}

		if (!filteredItems.length) {
			updateProveedoresPaginationUi(allItems.length, 0);
			list.innerHTML = '<p class="logistica-user-panel__empty">Ningún proveedor coincide con la búsqueda.</p>';
			return;
		}

		var start = (proveedoresPage - 1) * proveedoresPageSize;
		var pageItems = filteredItems.slice(start, start + proveedoresPageSize);

		list.innerHTML = pageItems.map(function (item) {
			var rowClass = 'logistica-user-panel__row logistica-user-panel__row--proveedor';

			return (
				'<article class="' + rowClass + '" data-user-panel-item="proveedores" data-id="' + escapeHtml(item.id) + '">' +
					renderProveedorViewCard(item) +
					panelRowActionsHtml('proveedores', item) +
				'</article>'
			);
		}).join('');

		updateProveedoresPaginationUi(allItems.length, filteredItems.length);
	}

	function renderAgenda() {
		var list = root.querySelector('[data-user-panel-list="agenda"]');
		if (!list) {
			return;
		}

		bindPanelListPagination('agenda', renderAgenda);
		bindPanelListFilters('agenda', renderAgenda);
		discardOrphanedDrafts('agenda');

		var allItems = orderListItemsForDisplay('agenda', state.panel.agenda || []);

		if (!allItems.length) {
			updatePanelListFilterToolbar('agenda', 0, 0);
			resetPanelListPage('agenda');
			updatePanelListPaginationUi('agenda', 0);
			list.innerHTML = '<p class="logistica-user-panel__empty">Sin actividades en la agenda.</p>';
			return;
		}

		var items = applyPanelListFilters('agenda', allItems);
		updatePanelListFilterToolbar('agenda', allItems.length, items.length);

		if (!items.length) {
			resetPanelListPage('agenda');
			updatePanelListPaginationUi('agenda', 0);
			list.innerHTML = '<p class="logistica-user-panel__empty">Sin actividades con los filtros seleccionados.</p>';
			return;
		}

		var pageData = paginatePanelListItems('agenda', items);

		list.innerHTML = pageData.items.map(function (item) {
			var complete = isSectionItemComplete('agenda', item);
			var statusKey = item.status || (complete ? 'completado' : 'pendiente');
			var whenLabel = formatAgendaWhen(item);
			var overdue = !complete && item.date && state.today && item.date < state.today;
			var descParts = [];
			if (whenLabel && whenLabel !== '—') {
				descParts.push('Fecha requerida: ' + whenLabel);
			}
			if (item.notes) {
				descParts.push(item.notes);
			}
			var priorityBadge = item.priority
				? '<span class="logistica-user-panel__aviso-kind logistica-user-panel__aviso-kind--soft">' +
					escapeHtml(labelMap(state.priorities, item.priority)) +
				'</span>'
				: '';

			return renderPanelCard({
				kind: 'agenda',
				kindLabel: 'Agenda',
				complete: complete,
				urgent: overdue,
				statusLabel: labelMap(state.agenda_statuses, statusKey),
				title: item.title || 'Sin actividad',
				description: descParts.join(' · '),
				timeLabel: item.updated_at ? formatColombiaDateTime(item.updated_at) : '',
				extraBadges: priorityBadge,
				viewHtml: panelCardViewAction('agenda', item.id),
				attrs: 'data-user-panel-item="agenda" data-id="' + escapeHtml(item.id) + '"',
				actionsHtml: panelRowActionsHtml('agenda', item)
			});
		}).join('');

		updatePanelListPaginationUi('agenda', pageData.total);
	}

	function renderCompras() {
		var list = root.querySelector('[data-user-panel-list="compras"]');
		if (!list) {
			return;
		}

		bindPanelListPagination('compras', renderCompras);
		bindPanelListFilters('compras', renderCompras);
		discardOrphanedDrafts('compras');

		var allItems = orderListItemsForDisplay('compras', state.panel.compras || []);

		if (!allItems.length) {
			updatePanelListFilterToolbar('compras', 0, 0);
			resetPanelListPage('compras');
			updatePanelListPaginationUi('compras', 0);
			list.innerHTML = '<p class="logistica-user-panel__empty">Sin cotizaciones ni compras pendientes.</p>';
			return;
		}

		var items = applyPanelListFilters('compras', allItems);
		updatePanelListFilterToolbar('compras', allItems.length, items.length);

		if (!items.length) {
			resetPanelListPage('compras');
			updatePanelListPaginationUi('compras', 0);
			list.innerHTML = '<p class="logistica-user-panel__empty">Sin registros con los filtros seleccionados.</p>';
			return;
		}

		var pageData = paginatePanelListItems('compras', items);

		list.innerHTML = pageData.items.map(function (item) {
			var complete = isSectionItemComplete('compras', item);
			var producto = compraProductoLabel(item);
			var empresa = getProveedorNombre(item.proveedor_id);
			var overdue = !complete && item.fecha_requerida && state.today && item.fecha_requerida < state.today;
			var descParts = [];
			if (empresa) {
				descParts.push(empresa);
			}
			if (item.referencia) {
				descParts.push('Ref. ' + item.referencia);
			}
			if (item.fecha_requerida) {
				descParts.push('Requerida: ' + formatShortDate(item.fecha_requerida));
			}
			var priorityBadge = '<span class="logistica-user-panel__aviso-kind logistica-user-panel__aviso-kind--soft">' +
				escapeHtml(labelMap(state.priorities, item.priority || 'media')) +
			'</span>';

			return renderPanelCard({
				kind: 'compra',
				kindLabel: 'Compra',
				complete: complete,
				urgent: overdue,
				statusLabel: labelMap(state.compra_statuses, item.status),
				title: producto,
				description: descParts.join(' · '),
				timeLabel: item.updated_at ? formatColombiaDateTime(item.updated_at) : '',
				extraBadges: priorityBadge,
				viewHtml: panelCardViewAction('compras', item.id),
				attrs: 'data-user-panel-item="compras" data-id="' + escapeHtml(item.id) + '"',
				actionsHtml: panelRowActionsHtml('compras', item)
			});
		}).join('');

		updatePanelListPaginationUi('compras', pageData.total);
	}

	function daySummary(dayDate, dayData) {
		var items = getChecklistItemsForDisplay(dayDate, dayData);
		var total = 0;
		var done = 0;
		var pending = 0;
		var doneCount = 0;

		items.forEach(function (item) {
			total += parseInt(item.duration_minutes, 10) || 0;
			if (item.done) {
				done += parseInt(item.duration_minutes, 10) || 0;
				doneCount += 1;
			} else {
				pending += parseInt(item.duration_minutes, 10) || 0;
			}
		});

		var count = items.length;
		var countPct = count ? (doneCount / count) * 100 : null;
		var durationPct = total ? (done / total) * 100 : (count ? (doneCount ? 100 : 0) : null);

		return {
			total: total,
			done: done,
			pending: pending,
			count: count,
			doneCount: doneCount,
			countPct: countPct,
			durationPct: durationPct
		};
	}

	function weekSummary(weekDays, daysSource) {
		var totalCount = 0;
		var doneCount = 0;
		var totalMinutes = 0;
		var doneMinutes = 0;

		weekDays.forEach(function (day) {
			var summary = daySummary(day.date, daysSource[day.date] || { items: [] });
			totalCount += summary.count;
			doneCount += summary.doneCount;
			totalMinutes += summary.total;
			doneMinutes += summary.done;
		});

		return {
			totalCount: totalCount,
			doneCount: doneCount,
			totalMinutes: totalMinutes,
			doneMinutes: doneMinutes,
			countPct: totalCount ? (doneCount / totalCount) * 100 : null,
			durationPct: totalMinutes ? (doneMinutes / totalMinutes) * 100 : (totalCount ? (doneCount ? 100 : 0) : null)
		};
	}

	function formatShortDate(value) {
		if (!value) {
			return '';
		}

		var parts = String(value).split('-');
		if (parts.length !== 3) {
			return value;
		}

		return parts[2] + '/' + parts[1];
	}

	function getSelectedChecklistDate() {
		if (selectedChecklistDate) {
			return selectedChecklistDate;
		}

		return state && state.today ? state.today : '';
	}

	function getWeekDayMeta(date) {
		var weekDays = buildWeekDays(checklistWeekOffset);
		for (var i = 0; i < weekDays.length; i++) {
			if (weekDays[i].date === date) {
				return weekDays[i];
			}
		}

		return null;
	}

	function getCarriedReminderInfo(date) {
		var dayData = (state.panel.checklist_days || {})[date] || { items: [] };
		var carried = (dayData.items || []).filter(function (item) {
			return (item.recurrence || 'diario') === 'diario' &&
				item.carried_from &&
				item.carried_from !== date &&
				!item.done;
		});

		if (!carried.length) {
			return null;
		}

		var dates = {};
		carried.forEach(function (item) {
			dates[item.carried_from] = true;
		});

		return {
			count: carried.length,
			dates: Object.keys(dates).sort()
		};
	}

	function renderChecklistItem(dayDate, item, readOnly) {
		var isDone = !!item.done;
		var recurrence = item.recurrence || 'diario';
		var recurrences = state.checklist_recurrences || {};
		var descParts = [];
		if (item.duration_minutes) {
			descParts.push('Duración: ' + formatDuration(item.duration_minutes));
		}
		if (item.linked) {
			descParts.push(item.link_label || 'Vinculado');
		}
		if ((recurrence === 'diario') && item.carried_from && item.carried_from !== dayDate) {
			descParts.push('Pendiente desde el ' + formatShortDate(item.carried_from));
		}
		var extraBadges =
			'<span class="logistica-user-panel__aviso-kind logistica-user-panel__aviso-kind--soft">' +
				escapeHtml(labelMap(state.priorities, item.priority)) +
			'</span>' +
			'<span class="logistica-user-panel__aviso-kind logistica-user-panel__aviso-kind--soft">' +
				escapeHtml(labelMap(recurrences, recurrence)) +
			'</span>';

		return renderPanelCard({
			kind: 'chequeo',
			kindLabel: item.linked ? (item.link_label || 'Vinculado') : 'Chequeo',
			complete: isDone,
			urgent: !isDone && !!(item.carried_from && item.carried_from !== dayDate),
			statusLabel: isDone ? 'Completado' : 'Pendiente',
			title: item.title || 'Sin actividad',
			description: descParts.join(' · '),
			timeLabel: dayDate ? formatShortDate(dayDate) : '',
			extraBadges: extraBadges,
			viewHtml: panelCardViewAction('checklist', item.id, dayDate),
			attrs: 'data-check-date="' + escapeHtml(dayDate) + '" data-id="' + escapeHtml(item.id) + '"',
			actionsHtml: checklistRowActionsHtml(item, readOnly, dayDate)
		});
	}

	function renderChecklist() {
		var wrap = root.querySelector('[data-user-panel-checklist]');
		if (!wrap) {
			return;
		}

		discardOrphanedChecklistDraft();
		updateChecklistToolbar();

		var selectedDate = getSelectedChecklistDate();
		var weekDays = buildWeekDays(checklistWeekOffset);
		var days = getChecklistDaysForView();
		var dayData = days[selectedDate] || { day_type: '', items: [] };
		var summary = daySummary(selectedDate, dayData);
		var weekStats = weekSummary(weekDays, days);
		var dayMeta = getWeekDayMeta(selectedDate);
		var dayType = dayData.day_type || '';
		var isToday = selectedDate === state.today;
		var isHistory = isChecklistHistoryWeek();
		var isFuture = isChecklistFutureWeek();
		var isReadOnly = isChecklistReadOnlyWeek();
		var isDayTypeEditable = isChecklistDayTypeEditable();
		var reminder = isToday && !isReadOnly ? getCarriedReminderInfo(selectedDate) : null;
		var weekStartLabel = weekDays[0] ? weekDays[0].short : '';
		var weekEndLabel = weekDays[6] ? weekDays[6].short : '';
		var canPrevWeek = checklistWeekOffset > -MAX_CHECKLIST_WEEK_OFFSET;
		var canNextWeek = checklistWeekOffset < MAX_CHECKLIST_WEEK_OFFSET;

		var dayTabs = weekDays.map(function (day) {
			var dayDataForTab = days[day.date] || { day_type: '', items: [] };
			var tabDayType = resolveDayType(day.date, dayDataForTab);
			var tabIsOff = isNonWorkingDayType(tabDayType);
			var dayItems = getChecklistItemsForDisplay(day.date, dayDataForTab);
			var pendingCount = dayItems.filter(function (item) {
				return !item.done;
			}).length;
			var active = day.date === selectedDate ? ' is-active' : '';
			var dayName = day.label || day.weekday_label;
			var tabAriaLabel = dayName + ' ' + day.short +
				(day.is_today ? ', hoy' : '') +
				(tabIsOff ? ', ' + (labelMap(state.day_types, tabDayType) || 'no laborable') : '') +
				(pendingCount ? ', ' + pendingCount + ' pendiente' + (pendingCount === 1 ? '' : 's') : '');

			return (
				'<button type="button" class="logistica-user-panel__day-tab' + active + (day.is_today ? ' is-today-tab' : '') +
					(tabIsOff ? ' is-day-off is-' + escapeHtml(tabDayType) : '') + '" data-user-panel-checklist-day="' + escapeHtml(day.date) + '" aria-label="' + escapeHtml(tabAriaLabel) + '">' +
					'<strong class="logistica-user-panel__day-tab-label">' + escapeHtml(dayName) + '</strong>' +
					'<span class="logistica-user-panel__day-tab-initial" aria-hidden="true">' + escapeHtml(day.weekday_initial || '') + '</span>' +
					'<span class="logistica-user-panel__day-tab-date">' + escapeHtml(day.short) + '</span>' +
					(day.is_today ? '<span class="logistica-user-panel__day-tab-hoy"> · Hoy</span>' : '') +
					(pendingCount ? '<em class="logistica-user-panel__day-tab-badge">' + pendingCount + '</em>' : '') +
				'</button>'
			);
		}).join('');

		var dayTypeOptions = Object.keys(state.day_types).map(function (key) {
			return '<option value="' + escapeHtml(key) + '"' + (key === dayType ? ' selected' : '') + '>' +
				escapeHtml(state.day_types[key]) + '</option>';
		}).join('');

		var isNonWorkingDay = isNonWorkingDayType(dayType);
		var displayItems = getChecklistItemsForDisplay(selectedDate, dayData);
		var itemsHtml = '';

		if (isNonWorkingDay) {
			itemsHtml = renderNonWorkingDayView(dayType);
		} else {
			itemsHtml = orderChecklistItemsForDisplay(selectedDate, displayItems).map(function (item) {
				return renderChecklistItem(selectedDate, item, isReadOnly);
			}).join('');

			if (!itemsHtml) {
				itemsHtml = '<p class="logistica-user-panel__empty">' +
					(isHistory
						? 'Sin actividades registradas para este día en el historial.'
						: (isFuture
							? 'Sin actividades programadas para este día.'
							: 'Sin actividades para este día. Usa «Chequeo» para agregar una.')) +
					'</p>';
			}
		}

		var reminderHtml = '';
		if (reminder) {
			var datesLabel = reminder.dates.map(formatShortDate).join(', ');
			reminderHtml =
				'<div class="logistica-user-panel__checklist-reminder" role="status">' +
					'<strong>Actividades diarias pendientes de días anteriores</strong>' +
					'<p>Tienes ' + reminder.count + ' actividad' + (reminder.count === 1 ? '' : 'es') +
						' arrastrada' + (reminder.count === 1 ? '' : 's') + ' desde: ' + escapeHtml(datesLabel) + '.</p>' +
				'</div>';
		}

		var historyBanner = isHistory
			? '<div class="logistica-user-panel__checklist-history-banner" role="status">' +
				'<strong>Historial</strong>' +
				'<p>Semana del ' + escapeHtml(weekStartLabel) + ' al ' + escapeHtml(weekEndLabel) + '. Solo lectura.</p>' +
			'</div>'
			: (isFuture
				? '<div class="logistica-user-panel__checklist-history-banner logistica-user-panel__checklist-preview-banner" role="status">' +
					'<strong>Vista previa</strong>' +
					'<p>Semana del ' + escapeHtml(weekStartLabel) + ' al ' + escapeHtml(weekEndLabel) +
						'. Vista previa de actividades; puedes cambiar el tipo de día. El resto es solo lectura.</p>' +
				'</div>'
				: '');

		var dayTypeField = isDayTypeEditable
			? '<label class="logistica-user-panel__check-field logistica-user-panel__check-field--day-type">' +
				'<span class="logistica-user-panel__field-label">Tipo de día</span>' +
				'<select class="logistica-user-panel__select' + (isNonWorkingDay ? ' logistica-user-panel__select--day-off logistica-user-panel__select--' + escapeHtml(dayType) : '') + '" data-field="day_type">' + dayTypeOptions + '</select>' +
			'</label>'
			: '<div class="logistica-user-panel__check-field logistica-user-panel__check-field--day-type">' +
				'<span class="logistica-user-panel__field-label">Tipo de día</span>' +
				'<span class="logistica-user-panel__check-readonly' + (isNonWorkingDay ? ' logistica-user-panel__check-readonly--off logistica-user-panel__check-readonly--' + escapeHtml(dayType) : '') + '">' +
					escapeHtml(labelMap(state.day_types, dayType) || 'Laborable') +
				'</span>' +
			'</div>';

		var compliancePrimary = summary.count ? formatCompliancePercent(summary.countPct) : '—';
		var complianceDetail = summary.count
			? escapeHtml(String(summary.doneCount)) + '/' + escapeHtml(String(summary.count)) + ' actividades'
			: 'Sin actividades';

		var daySummaryHtml = isNonWorkingDay
			? ''
			: '<div class="logistica-user-panel__day-summary">' +
				'<span class="logistica-user-panel__day-summary-compliance">' +
					'Cumplimiento: <strong class="logistica-user-panel__compliance">' + compliancePrimary + '</strong> (' + complianceDetail + ')' +
				'</span>' +
				'<span>' + summary.count + ' actividades</span>' +
				'<span>Total: ' + formatDuration(summary.total) + '</span>' +
				'<span>Completado: ' + formatDuration(summary.done) +
					(summary.total ? ' (' + formatCompliancePercent(summary.durationPct) + ')' : '') +
				'</span>' +
				'<span>Pendiente: ' + formatDuration(summary.pending) + '</span>' +
			'</div>';

		var prevLabel = checklistWeekOffset === 1 ? 'Semana actual' : 'Semana anterior';
		var nextLabel = checklistWeekOffset === -1 ? 'Semana actual' : 'Semana siguiente';

		wrap.innerHTML =
			'<nav class="logistica-user-panel__checklist-week-nav" aria-label="Semana del checklist">' +
				'<button type="button" class="logistica-user-panel__page-btn logistica-user-panel__page-btn--week-prev"' +
					(canPrevWeek ? ' data-user-panel-checklist-week-prev' : ' disabled') +
					' aria-label="' + escapeHtml(prevLabel) + '">' +
					'<span class="dashicons dashicons-arrow-left-alt2" aria-hidden="true"></span>' +
					'<span class="logistica-user-panel__page-btn-label">' + escapeHtml(prevLabel) + '</span>' +
				'</button>' +
				'<div class="logistica-user-panel__checklist-week-meta">' +
					'<strong>' + escapeHtml(weekStartLabel) + ' – ' + escapeHtml(weekEndLabel) + '</strong>' +
					'<span>Cumplimiento semanal: <em class="logistica-user-panel__compliance">' + formatCompliancePercent(weekStats.countPct) + '</em>' +
						(weekStats.totalCount ? ' (' + escapeHtml(String(weekStats.doneCount)) + '/' + escapeHtml(String(weekStats.totalCount)) + ' actividades)' : '') +
					'</span>' +
				'</div>' +
				'<button type="button" class="logistica-user-panel__page-btn logistica-user-panel__page-btn--week-next"' +
					(canNextWeek ? ' data-user-panel-checklist-week-next' : ' disabled') +
					' aria-label="' + escapeHtml(nextLabel) + '">' +
					'<span class="logistica-user-panel__page-btn-label">' + escapeHtml(nextLabel) + '</span>' +
					'<span class="dashicons dashicons-arrow-right-alt2" aria-hidden="true"></span>' +
				'</button>' +
			'</nav>' +
			historyBanner +
			'<nav class="logistica-user-panel__day-tabs" aria-label="Días de la semana">' + dayTabs + '</nav>' +
			reminderHtml +
			'<article class="logistica-user-panel__day-detail' + (isToday ? ' is-today' : '') + (dayType ? ' is-' + escapeHtml(dayType) : '') + (isNonWorkingDay ? ' is-day-off' : '') + '" data-check-day="' + escapeHtml(selectedDate) + '">' +
				'<header class="logistica-user-panel__day-detail-head">' +
					dayTypeField +
				'</header>' +
				daySummaryHtml +
				'<div class="logistica-user-panel__list logistica-user-panel__day-items' + (isNonWorkingDay ? ' logistica-user-panel__day-items--off' : '') + '">' + itemsHtml + '</div>' +
			'</article>';
	}

	function renderAllPrimary() {
		renderUserCard();
		renderQuickLinks();
		renderResumePoints();
		renderAvisos();
		renderAgenda();
		renderChecklist();
	}

	function renderAllSecondary() {
		renderProveedores();
		renderCompras();
		renderInformeTiempos();
	}

	function datetimeLocalFromSql(sql) {
		var dt = parsePanelDateTime(sql || nowSql());
		if (!dt) {
			return '';
		}
		var parts = {};
		new Intl.DateTimeFormat('en-CA', {
			timeZone: 'America/Bogota',
			year: 'numeric',
			month: '2-digit',
			day: '2-digit',
			hour: '2-digit',
			minute: '2-digit',
			hour12: false
		}).formatToParts(dt).forEach(function (part) {
			if (part.type !== 'literal') {
				parts[part.type] = part.value;
			}
		});
		return parts.year + '-' + parts.month + '-' + parts.day + 'T' + parts.hour + ':' + parts.minute;
	}

	function sqlFromDatetimeLocal(value) {
		var text = String(value || '').trim();
		if (!text) {
			return nowSql();
		}
		var match = text.match(/^(\d{4}-\d{2}-\d{2})T(\d{2}):(\d{2})/);
		if (!match) {
			return nowSql();
		}
		return match[1] + ' ' + match[2] + ':' + match[3] + ':00';
	}

	function pushPanelAviso(aviso, sendEmail) {
		ensurePanelAvisos();
		var entry = {
			id: aviso.id || generateId('aviso'),
			title: aviso.title || 'Aviso',
			body: aviso.body || '',
			created_at: aviso.created_at || nowSql(),
			read: false,
			email_sent: false,
			source_type: aviso.source_type || '',
			source_id: aviso.source_id || '',
			dedupe_key: aviso.dedupe_key || ''
		};
		state.panel.avisos.unshift(entry);

		if (sendEmail) {
			pendingAvisoEmailIds.push(entry.id);
		}

		return entry;
	}

	function flushPendingAvisoEmails() {
		if (!pendingAvisoEmailIds.length) {
			return;
		}
		var ids = pendingAvisoEmailIds.slice();
		pendingAvisoEmailIds = [];
		ids.forEach(function (id) {
			sendAvisoEmail(id);
		});
	}

	function renderAvisos() {
		var wrap = root.querySelector('[data-user-panel-avisos]');
		var markAllBtn = root.querySelector('[data-user-panel-avisos-mark-all]');
		var deleteReadBtn = root.querySelector('[data-user-panel-avisos-delete-read]');
		var toggleBtn = root.querySelector('[data-user-panel-avisos-toggle-read]');
		var toggleLabel = root.querySelector('[data-user-panel-avisos-toggle-label]');
		var countBadge = root.querySelector('[data-user-panel-avisos-count]');
		if (!wrap) {
			return;
		}

		var avisos = ensurePanelAvisos();
		var unread = avisos.filter(function (a) { return !a.read; });
		var read = avisos.filter(function (a) { return !!a.read; });
		var readCount = read.length;
		// «Ver leídos» = solo leídos; por defecto = solo no leídos (nunca mezclar ambos).
		var visible = avisosShowRead ? read : unread;

		if (markAllBtn) {
			markAllBtn.hidden = unread.length === 0;
		}
		if (deleteReadBtn) {
			deleteReadBtn.hidden = readCount === 0;
		}
		if (toggleLabel) {
			toggleLabel.textContent = avisosShowRead ? 'Ocultar leídos' : 'Ver leídos';
		} else if (toggleBtn) {
			toggleBtn.textContent = avisosShowRead ? 'Ocultar leídos' : 'Ver leídos';
		}
		if (toggleBtn) {
			var toggleIcon = toggleBtn.querySelector('.dashicons');
			if (toggleIcon) {
				toggleIcon.className = 'dashicons ' + (avisosShowRead ? 'dashicons-hidden' : 'dashicons-visibility');
			}
		}
		if (countBadge) {
			if (unread.length) {
				countBadge.hidden = false;
				countBadge.textContent = String(unread.length);
			} else {
				countBadge.hidden = true;
				countBadge.textContent = '';
			}
		}

		if (!visible.length) {
			wrap.innerHTML =
				'<div class="logistica-user-panel__avisos-empty">' +
					'<span class="logistica-user-panel__avisos-empty-icon" aria-hidden="true"><span class="dashicons dashicons-yes-alt"></span></span>' +
					'<p class="logistica-user-panel__avisos-empty-title">' +
						(avisosShowRead ? 'Sin avisos guardados' : 'Todo al día') +
					'</p>' +
					'<p class="logistica-user-panel__avisos-empty-text">' +
						(avisosShowRead
							? 'No hay avisos archivados por ahora.'
							: 'No tienes pendientes urgentes. Usa «Ver leídos» para consultar los ocultos.') +
					'</p>' +
				'</div>';
			return;
		}

		wrap.innerHTML = '<div class="logistica-user-panel__avisos-list">' + visible.slice(0, 40).map(function (aviso, index) {
			var unreadClass = aviso.read ? ' is-read' : ' is-unread';
			var canOpen = !!(aviso.source_type && aviso.source_id);
			var sourceType = String(aviso.source_type || '');
			var kind = (sourceType === 'compras' || sourceType === 'compra') ? 'compra' : (sourceType === 'agenda' ? 'agenda' : 'general');
			var kindLabel = kind === 'compra' ? 'Compra' : (kind === 'agenda' ? 'Agenda' : 'Aviso');
			var delay = Math.min(index, 8) * 40;
			var viewIconHtml = canOpen
				? panelIconActionBtn({
					label: 'Ver',
					tip: 'Ver actividad o compra relacionada',
					extraClass: 'logistica-user-panel__btn--action-view',
					dataAttr: 'data-aviso-open-source="' + escapeHtml(aviso.id) + '"',
					icon: 'dashicons-visibility'
				})
				: '<span class="dashicons dashicons-flag" aria-hidden="true"></span>';

			return (
				'<article class="logistica-user-panel__aviso' + unreadClass + ' is-' + kind + '" data-aviso-id="' + escapeHtml(aviso.id) + '" style="--aviso-delay:' + delay + 'ms">' +
					'<div class="logistica-user-panel__aviso-accent" aria-hidden="true"></div>' +
					'<div class="logistica-user-panel__aviso-icon' + (canOpen ? ' logistica-user-panel__aviso-icon--view' : '') + '">' +
						viewIconHtml +
					'</div>' +
					'<div class="logistica-user-panel__aviso-body">' +
						'<div class="logistica-user-panel__aviso-meta">' +
							'<span class="logistica-user-panel__aviso-kind">' + escapeHtml(kindLabel) + '</span>' +
							(aviso.read ? '<span class="logistica-user-panel__aviso-state">Leído</span>' : '<span class="logistica-user-panel__aviso-state is-live">Pendiente</span>') +
						'</div>' +
						'<h3>' + escapeHtml(aviso.title || 'Aviso') + '</h3>' +
						'<p>' + escapeHtml(aviso.body || '') + '</p>' +
						'<time datetime="' + escapeHtml(aviso.created_at || '') + '">' +
							'<span class="dashicons dashicons-clock" aria-hidden="true"></span>' +
							escapeHtml(formatColombiaDateTime(aviso.created_at)) +
						'</time>' +
					'</div>' +
					'<div class="logistica-user-panel__aviso-actions">' +
						(aviso.read ? '' :
							panelIconActionBtn({
								label: 'Leído',
								tip: 'Resolver aviso: novedad y/o finalizar',
								extraClass: 'logistica-user-panel__btn--action-done',
								dataAttr: 'data-aviso-mark-read="' + escapeHtml(aviso.id) + '"',
								icon: 'dashicons-yes'
							})) +
						panelIconActionBtn({
							label: 'Eliminar',
							tip: 'Eliminar aviso permanentemente',
							extraClass: 'logistica-user-panel__btn--action-delete',
							dataAttr: 'data-aviso-delete="' + escapeHtml(aviso.id) + '"',
							icon: 'dashicons-trash'
						}) +
					'</div>' +
				'</article>'
			);
		}).join('') + '</div>';
	}

	function findAvisoById(avisoId) {
		var avisos = ensurePanelAvisos();
		for (var i = 0; i < avisos.length; i++) {
			if (String(avisos[i].id) === String(avisoId)) {
				return avisos[i];
			}
		}
		return null;
	}

	function resolveAvisoSourceSection(aviso) {
		if (!aviso || !aviso.source_type || !aviso.source_id) {
			return null;
		}
		var type = String(aviso.source_type || '');
		if (type === 'agenda') {
			return 'agenda';
		}
		if (type === 'compras' || type === 'compra') {
			return 'compras';
		}
		return null;
	}

	function avisoFinalizeStatusLabel(section) {
		return section === 'compras' ? 'recibido' : 'completado';
	}

	function avisoSourceItemLabel(section, item) {
		if (!item) {
			return 'Registro vinculado';
		}
		if (section === 'compras') {
			return compraProductoLabel(item);
		}
		return item.title || 'Actividad';
	}

	function panelTodayYmd() {
		if (state && state.today) {
			return String(state.today);
		}
		return String(nowSql() || '').slice(0, 10);
	}

	function panelDatePlusDays(ymd, days) {
		var match = String(ymd || '').match(/^(\d{4})-(\d{2})-(\d{2})/);
		if (!match) {
			return panelTodayYmd();
		}
		var dt = new Date(Date.UTC(parseInt(match[1], 10), parseInt(match[2], 10) - 1, parseInt(match[3], 10)));
		dt.setUTCDate(dt.getUTCDate() + (parseInt(days, 10) || 0));
		var y = dt.getUTCFullYear();
		var m = String(dt.getUTCMonth() + 1).padStart(2, '0');
		var d = String(dt.getUTCDate()).padStart(2, '0');
		return y + '-' + m + '-' + d;
	}

	function syncAvisoResolveNovedadFields() {
		var modal = getModalEl();
		if (!modal) {
			return;
		}
		var hasNov = modal.querySelector('[data-aviso-resolve-has-novedad]');
		var wrap = modal.querySelector('[data-aviso-resolve-novedad-wrap]');
		var texto = modal.querySelector('[data-aviso-resolve-novedad-texto]');
		var enabled = !!(hasNov && hasNov.checked);
		if (wrap) {
			wrap.hidden = !enabled;
		}
		if (texto) {
			texto.disabled = !enabled;
			if (enabled) {
				texto.focus();
			}
		}
	}

	function syncAvisoResolveFinalizeFields() {
		var modal = getModalEl();
		if (!modal) {
			return;
		}
		var finalize = modal.querySelector('[data-aviso-resolve-finalize]');
		var warn = modal.querySelector('[data-aviso-resolve-open-warn]');
		var snooze = modal.querySelector('[data-aviso-resolve-snooze]');
		var snoozeLabel = modal.querySelector('[data-aviso-resolve-snooze-wrap]');
		var isFinal = !!(finalize && finalize.checked);
		if (warn) {
			warn.hidden = isFinal;
		}
		if (snoozeLabel) {
			snoozeLabel.hidden = isFinal;
		}
		if (snooze) {
			snooze.disabled = isFinal;
			if (isFinal) {
				snooze.checked = false;
			}
		}
	}

	function findAvisoForSource(section, id) {
		if (!section || (!id && id !== 0)) {
			return null;
		}
		var avisos = ensurePanelAvisos();
		for (var i = 0; i < avisos.length; i++) {
			var aviso = avisos[i];
			if (resolveAvisoSourceSection(aviso) === section && String(aviso.source_id) === String(id)) {
				return aviso;
			}
		}
		return null;
	}

	function resolveSummaryForSource(section, item) {
		var statusMap = section === 'compras' ? state.compra_statuses : state.agenda_statuses;
		var estado = item && item.status ? item.status : 'pendiente';
		var parts = ['Estado actual: ' + (labelMap(statusMap || {}, estado) || estado)];
		var fecha = section === 'compras'
			? (item && item.fecha_requerida ? item.fecha_requerida : '')
			: (item && item.date ? item.date : '');
		if (fecha) {
			parts.push((section === 'compras' ? 'Fecha requerida: ' : 'Fecha: ') + fecha);
		}
		return parts.join(' · ');
	}

	/**
	 * Renderiza el modal de resolución (novedad + finalizar + posponer).
	 *
	 * cfg: { section, id, avisoId, headerTitle, headerBody, hasRelatedAviso }
	 */
	function renderResolveModal(cfg) {
		var modal = getModalEl();
		if (!modal) {
			return false;
		}

		var section = cfg.section;
		var hasRelatedAviso = !!cfg.hasRelatedAviso;
		var finalizeLabel = section === 'compras'
			? 'Finalizar compra (pasar a recibido)'
			: 'Finalizar actividad (pasar a completado)';
		var openWarnText;
		if (hasRelatedAviso) {
			openWarnText = section === 'compras'
				? 'Si no finalizas, la compra seguirá en gestión y el aviso podrá volver a aparecer cuando venza o sea hoy.'
				: 'Si no finalizas, la actividad seguirá pendiente y el aviso podrá volver a aparecer cuando venza o sea hoy.';
		} else {
			openWarnText = section === 'compras'
				? 'Si no finalizas, la compra seguirá en gestión.'
				: 'Si no finalizas, la actividad seguirá pendiente.';
		}

		var snoozeHtml = hasRelatedAviso
			? (
				'<label class="logistica-user-panel__aviso-resolve-check" data-aviso-resolve-snooze-wrap>' +
					'<input type="checkbox" data-aviso-resolve-snooze checked> ' +
					'Recordar mañana (posponer el aviso hasta mañana)' +
				'</label>'
			)
			: '';

		var bodyHtml =
			'<div class="logistica-user-panel__aviso-resolve" data-aviso-resolve-form' +
					' data-resolve-section="' + escapeHtml(section) + '"' +
					' data-resolve-id="' + escapeHtml(String(cfg.id)) + '"' +
					' data-aviso-id="' + escapeHtml(String(cfg.avisoId || '')) + '">' +
				'<div class="logistica-user-panel__aviso-resolve-summary">' +
					'<p class="logistica-user-panel__aviso-resolve-title"><strong>' + escapeHtml(cfg.headerTitle || 'Registro') + '</strong></p>' +
					(cfg.headerBody
						? '<p class="logistica-user-panel__aviso-resolve-body">' + escapeHtml(cfg.headerBody) + '</p>'
						: '') +
				'</div>' +
				'<label class="logistica-user-panel__aviso-resolve-check">' +
					'<input type="checkbox" data-aviso-resolve-has-novedad> ' +
					'¿Tiene alguna novedad?' +
				'</label>' +
				'<div class="logistica-user-panel__aviso-resolve-novedad" data-aviso-resolve-novedad-wrap hidden>' +
					panelField(
						'Cuál sería la novedad',
						'<textarea class="logistica-user-panel__textarea" rows="3" data-aviso-resolve-novedad-texto placeholder="Describe la novedad o avance."></textarea>',
						'',
						'Se agrega al historial de novedades del registro.'
					) +
				'</div>' +
				'<label class="logistica-user-panel__aviso-resolve-check">' +
					'<input type="checkbox" data-aviso-resolve-finalize> ' +
					escapeHtml(finalizeLabel) +
				'</label>' +
				'<p class="logistica-user-panel__field-hint">Al finalizar, el estado pasa a «' +
					escapeHtml(avisoFinalizeStatusLabel(section)) +
					'».' + (hasRelatedAviso ? ' El aviso se ocultará como leído.' : '') + '</p>' +
				'<div class="logistica-user-panel__aviso-resolve-warn" data-aviso-resolve-open-warn>' +
					'<p class="logistica-user-panel__aviso-resolve-warn-text">' + escapeHtml(openWarnText) + '</p>' +
					snoozeHtml +
				'</div>' +
			'</div>';

		var titleNode = modal.querySelector('[data-user-panel-modal-title]');
		var body = modal.querySelector('[data-user-panel-modal-body]');
		var dialog = modal.querySelector('.logistica-user-panel__modal-dialog');
		var footer = modal.querySelector('.logistica-user-panel__modal-footer');
		var saveBtn = modal.querySelector('[data-user-panel-modal-save]');

		if (!titleNode || !body || !dialog) {
			return false;
		}

		modal.setAttribute('data-user-panel-modal-mode', 'aviso-resolve');
		modal.setAttribute('data-user-panel-modal-section', section);
		modal.setAttribute('data-user-panel-modal-id', String(cfg.id));
		modal.removeAttribute('data-user-panel-modal-check-date');

		titleNode.textContent = section === 'compras' ? 'Resolver compra' : (section === 'agenda' ? 'Resolver actividad' : 'Resolver aviso');
		body.innerHTML = bodyHtml;
		dialog.classList.remove('logistica-user-panel__modal-dialog--wide');

		if (footer) {
			footer.hidden = false;
		}
		if (saveBtn) {
			saveBtn.textContent = 'Confirmar';
		}

		modal.hidden = false;
		document.body.classList.add('logistica-user-panel-modal-open');

		var hasNov = body.querySelector('[data-aviso-resolve-has-novedad]');
		if (hasNov) {
			hasNov.addEventListener('change', syncAvisoResolveNovedadFields);
		}
		var finalize = body.querySelector('[data-aviso-resolve-finalize]');
		if (finalize) {
			finalize.addEventListener('change', syncAvisoResolveFinalizeFields);
		}
		syncAvisoResolveNovedadFields();
		syncAvisoResolveFinalizeFields();
		return true;
	}

	function openAvisoMarkReadModal(avisoId) {
		var aviso = findAvisoById(avisoId);
		if (!aviso || aviso.read) {
			return;
		}

		var section = resolveAvisoSourceSection(aviso);
		var item = section ? findListItem(section, aviso.source_id) : null;

		if (!section || !item) {
			// Aviso sin origen gestionable: marcar leído directo.
			markAvisosRead([avisoId]);
			return;
		}

		renderResolveModal({
			section: section,
			id: aviso.source_id,
			avisoId: aviso.id,
			headerTitle: aviso.title || avisoSourceItemLabel(section, item),
			headerBody: aviso.body || resolveSummaryForSource(section, item),
			hasRelatedAviso: true
		});
	}

	function openSourceResolveModal(section, id) {
		if (section !== 'compras' && section !== 'agenda') {
			return;
		}
		var item = findListItem(section, id);
		if (!item) {
			return;
		}

		var relatedAviso = findAvisoForSource(section, id);

		renderResolveModal({
			section: section,
			id: id,
			avisoId: relatedAviso ? relatedAviso.id : '',
			headerTitle: avisoSourceItemLabel(section, item),
			headerBody: resolveSummaryForSource(section, item),
			hasRelatedAviso: !!relatedAviso
		});
	}

	function applyResolveToItem(section, item, options) {
		if (!section || !item) {
			return false;
		}

		var changed = false;
		var atSql = nowSql();

		if (section === 'compras') {
			ensureCompraGestionFields(item);
		} else {
			ensureAgendaGestionFields(item);
		}

		if (options.hasNovedad && options.novedadTexto) {
			item.novedades.push({
				id: generateId('nov'),
				at: atSql,
				texto: options.novedadTexto,
				status: item.status || 'pendiente'
			});
			changed = true;
		}

		if (options.finalize) {
			if (section === 'agenda') {
				var agendaPrev = item.status || (item.done ? 'completado' : 'pendiente');
				if (agendaPrev !== 'completado') {
					item.status = 'completado';
					item.done = true;
					recordStatusChange(item, agendaPrev, 'completado', atSql);
					changed = true;
				}
			} else if (section === 'compras') {
				var compraPrev = item.status || 'pendiente';
				if (compraPrev !== 'recibido') {
					item.status = 'recibido';
					applyCompraStatusSideEffects(item, compraPrev);
					changed = true;
				}
			}
		}

		if (changed) {
			item.updated_at = atSql;
		}

		return changed;
	}

	function saveAvisoMarkReadModal() {
		var modal = getModalEl();
		if (!modal) {
			return;
		}

		var form = modal.querySelector('[data-aviso-resolve-form]');
		var section = form ? (form.getAttribute('data-resolve-section') || '') : '';
		var sourceId = form ? (form.getAttribute('data-resolve-id') || '') : '';
		var avisoId = form ? (form.getAttribute('data-aviso-id') || '') : '';

		var item = section ? findListItem(section, sourceId) : null;
		var aviso = avisoId ? findAvisoById(avisoId) : findAvisoForSource(section, sourceId);

		if (!item && !aviso) {
			closeEditModal();
			return;
		}

		var hasNovInput = modal.querySelector('[data-aviso-resolve-has-novedad]');
		var textoInput = modal.querySelector('[data-aviso-resolve-novedad-texto]');
		var finalizeInput = modal.querySelector('[data-aviso-resolve-finalize]');
		var snoozeInput = modal.querySelector('[data-aviso-resolve-snooze]');
		var hasNovedad = !!(hasNovInput && hasNovInput.checked);
		var novedadTexto = textoInput ? String(textoInput.value || '').trim() : '';
		var finalize = !!(finalizeInput && finalizeInput.checked);
		var snooze = !!(!finalize && snoozeInput && snoozeInput.checked);

		if (hasNovedad && !novedadTexto) {
			window.alert('Indica cuál es la novedad, o desmarca «¿Tiene alguna novedad?».');
			if (textoInput) {
				textoInput.focus();
			}
			return;
		}

		var sourceChanged = false;
		if (item) {
			sourceChanged = applyResolveToItem(section, item, {
				hasNovedad: hasNovedad,
				novedadTexto: novedadTexto,
				finalize: finalize
			});
		}

		var avisoChanged = false;
		if (aviso) {
			aviso.read = true;
			if (finalize || !snooze) {
				aviso.snooze_until = '';
			} else {
				aviso.snooze_until = panelDatePlusDays(panelTodayYmd(), 1);
			}
			avisoChanged = true;
		}

		closeEditModal();

		if (sourceChanged || snooze || (avisoChanged && !aviso)) {
			// Persistir panel completo (novedad/estado/snooze + aviso leído).
			renderAll();
			savePanelNow();
			setResolveStatusMessage(section, finalize, snooze, !!aviso);
			return;
		}

		if (aviso) {
			// Solo aviso leído sin cambios en el origen: usar endpoint específico.
			markAvisosRead([aviso.id]);
		} else if (avisoChanged || sourceChanged) {
			renderAll();
			savePanelNow();
		}
		setResolveStatusMessage(section, finalize, snooze, !!aviso);
	}

	function setResolveStatusMessage(section, finalize, snooze, hadAviso) {
		var label = section === 'compras' ? 'La compra' : (section === 'agenda' ? 'La actividad' : 'El registro');
		if (finalize) {
			setSaveStatus(hadAviso ? 'Aviso resuelto y registro finalizado.' : (label + ' se finalizó.'), 'saved');
		} else if (snooze) {
			setSaveStatus('Aviso oculto hasta mañana. ' + label + ' sigue pendiente.', 'saved');
		} else {
			setSaveStatus(hadAviso ? ('Aviso marcado como leído. ' + label + ' sigue pendiente.') : (label + ' se actualizó y sigue pendiente.'), 'saved');
		}
	}

	function openAvisoSource(avisoId) {
		var aviso = findAvisoById(avisoId);
		if (!aviso || !aviso.source_type || !aviso.source_id) {
			return;
		}
		if (aviso.source_type === 'agenda' || aviso.source_type === 'compras' || aviso.source_type === 'compra') {
			var section = aviso.source_type === 'compra' ? 'compras' : aviso.source_type;
			openSectionViewModal(section, aviso.source_id);
			return;
		}
	}

	function deleteAviso(avisoId) {
		if (!window.confirm('¿Eliminar este aviso de forma permanente?')) {
			return;
		}
		var body = new FormData();
		body.append('action', 'logistica_delete_panel_avisos');
		body.append('nonce', getUserPanelNonce());
		body.append('aviso_ids', JSON.stringify([avisoId]));

		fetch(config().ajaxUrl, { method: 'POST', body: body, credentials: 'same-origin' })
			.then(function (res) { return res.json(); })
			.then(function (json) {
				if (json && json.success && json.data && json.data.panel) {
					state.panel = json.data.panel;
					renderAvisos();
				}
			});
	}

	function deleteReadAvisos() {
		var avisos = ensurePanelAvisos();
		var readCount = avisos.filter(function (a) { return !!a.read; }).length;
		if (!readCount) {
			return;
		}
		if (!window.confirm('¿Eliminar permanentemente los ' + readCount + ' avisos ya leídos?')) {
			return;
		}
		var body = new FormData();
		body.append('action', 'logistica_delete_panel_avisos');
		body.append('nonce', getUserPanelNonce());
		body.append('aviso_ids', 'read');

		fetch(config().ajaxUrl, { method: 'POST', body: body, credentials: 'same-origin' })
			.then(function (res) { return res.json(); })
			.then(function (json) {
				if (json && json.success && json.data && json.data.panel) {
					state.panel = json.data.panel;
					renderAvisos();
					setSaveStatus('Avisos leídos eliminados.', 'saved');
				}
			});
	}

	function syncInformeFilterControls() {
		if (!root) {
			return;
		}
		var statusSelect = root.querySelector('[data-user-panel-informe-filter="status"]');
		var provSelect = root.querySelector('[data-user-panel-informe-filter="proveedor_id"]');
		if (statusSelect) {
			var statuses = {};
			if (!informeFilters.tipo || informeFilters.tipo === 'compras') {
				Object.keys(state.compra_statuses || {}).forEach(function (k) { statuses[k] = state.compra_statuses[k]; });
			}
			if (!informeFilters.tipo || informeFilters.tipo === 'agenda') {
				Object.keys(state.agenda_statuses || {}).forEach(function (k) { statuses[k] = state.agenda_statuses[k]; });
			}
			var current = informeFilters.status;
			statusSelect.innerHTML = '<option value="">Todos</option>' + Object.keys(statuses).map(function (key) {
				return '<option value="' + escapeHtml(key) + '"' + (key === current ? ' selected' : '') + '>' +
					escapeHtml(statuses[key]) + '</option>';
			}).join('');
		}
		if (provSelect) {
			var currentProv = informeFilters.proveedor_id;
			var options = '<option value="">Todos</option>';
			(state.panel.proveedores || []).forEach(function (prov) {
				options += '<option value="' + escapeHtml(prov.id) + '"' + (prov.id === currentProv ? ' selected' : '') + '>' +
					escapeHtml(prov.nombre || 'Proveedor') + '</option>';
			});
			provSelect.innerHTML = options;
		}
		['tipo', 'fecha_desde', 'fecha_hasta'].forEach(function (key) {
			var el = root.querySelector('[data-user-panel-informe-filter="' + key + '"]');
			if (el) {
				el.value = informeFilters[key] || '';
			}
		});
		var clearBtn = root.querySelector('[data-user-panel-informe-filter-clear]');
		var active = !!(informeFilters.tipo || informeFilters.status || informeFilters.proveedor_id ||
			informeFilters.fecha_desde || informeFilters.fecha_hasta || informeFilters.solo_activos);
		if (clearBtn) {
			clearBtn.hidden = !active;
			clearBtn.textContent = isInformeDayView()
				? 'Ver acumulado total'
				: 'Limpiar filtros';
		}
	}

	function itemMatchesInformeFilters(row) {
		if (informeFilters.tipo && row.tipo !== informeFilters.tipo) {
			return false;
		}
		if (informeFilters.status && row.statusKey !== informeFilters.status) {
			return false;
		}
		if (informeFilters.solo_activos && !informeFilters.status && isGestionTerminalStatus(row.statusKey)) {
			return false;
		}
		if (informeFilters.proveedor_id && row.proveedorId !== informeFilters.proveedor_id) {
			return false;
		}

		// Vista del día: todos los registros activos (pendiente / en proceso / etc.).
		if (isInformeDayView()) {
			return !isGestionTerminalStatus(row.statusKey);
		}

		var refDate = row.refDate || '';
		if (informeFilters.fecha_desde && refDate && refDate < informeFilters.fecha_desde) {
			return false;
		}
		if (informeFilters.fecha_hasta && refDate && refDate > informeFilters.fecha_hasta) {
			return false;
		}
		if ((informeFilters.fecha_desde || informeFilters.fecha_hasta) && !refDate) {
			return false;
		}
		return true;
	}

	function renderInformeTiempos() {
		var wrap = root.querySelector('[data-user-panel-informe-tiempos]');
		if (!wrap) {
			return;
		}

		ensureInformeDefaultFilters();
		syncInformeFilterControls();

		var dayView = isInformeDayView();
		var rows = [];
		(state.panel.compras || []).forEach(function (compra) {
			ensureCompraGestionFields(compra);
			var statusMap = getInformeStatusSecondsMap(compra);
			rows.push({
				tipo: 'compras',
				tipoLabel: 'Compra',
				titulo: compraProductoLabel(compra),
				proveedor: getProveedorNombre(compra.proveedor_id) || '—',
				proveedorId: compra.proveedor_id || '',
				statusKey: compra.status || 'pendiente',
				status: labelMap(state.compra_statuses, compra.status),
				total: getInformeGestionTotalSeconds(compra),
				novedades: (compra.novedades || []).length,
				refDate: (compra.fecha_requerida || compra.gestion_started_at || compra.created_at || compra.fecha_solicitud || '').slice(0, 10),
				statusMap: statusMap
			});
		});
		(state.panel.agenda || []).forEach(function (item) {
			ensureAgendaGestionFields(item);
			var statusKey = item.status || (item.done ? 'completado' : 'pendiente');
			var statusMap = getInformeStatusSecondsMap(item);
			rows.push({
				tipo: 'agenda',
				tipoLabel: 'Agenda',
				titulo: item.title || 'Actividad',
				proveedor: '—',
				proveedorId: '',
				statusKey: statusKey,
				status: labelMap(state.agenda_statuses, statusKey),
				total: getInformeGestionTotalSeconds(item),
				novedades: (item.novedades || []).length,
				refDate: (item.date || item.gestion_started_at || item.created_at || '').slice(0, 10),
				statusMap: statusMap
			});
		});

		var filtered = rows.filter(itemMatchesInformeFilters);
		if (dayView) {
			filtered = filtered.filter(function (row) {
				return row.total > 0 || !isGestionTerminalStatus(row.statusKey);
			});
		}

		var countEl = root.querySelector('[data-user-panel-informe-filter-count]');
		if (countEl) {
			countEl.textContent = filtered.length + ' de ' + rows.length +
				(dayView ? ' · Día actual (activos)' : '');
		}

		if (!filtered.length) {
			wrap.innerHTML = '<p class="logistica-user-panel__empty">' +
				(dayView
					? 'No hay gestiones activas (pendiente, en proceso u otros estados abiertos) con tiempo en el día de hoy. Usa «Ver acumulado total» para el histórico.'
					: 'Sin registros para los filtros seleccionados.') +
			'</p>';
			return;
		}

		var byStatus = {};
		var byProveedor = {};
		filtered.forEach(function (row) {
			Object.keys(row.statusMap || {}).forEach(function (statusKey) {
				if (dayView && isGestionTerminalStatus(statusKey)) {
					return;
				}
				var seconds = row.statusMap[statusKey] || 0;
				if (dayView && seconds <= 0 && statusKey !== row.statusKey) {
					return;
				}
				byStatus[statusKey] = (byStatus[statusKey] || 0) + seconds;
			});
			if (dayView && row.statusKey && !isGestionTerminalStatus(row.statusKey)) {
				byStatus[row.statusKey] = byStatus[row.statusKey] || 0;
			}
			if (row.proveedorId) {
				if (!byProveedor[row.proveedorId]) {
					byProveedor[row.proveedorId] = { nombre: row.proveedor, total: 0, count: 0 };
				}
				byProveedor[row.proveedorId].total += row.total;
				byProveedor[row.proveedorId].count += 1;
			}
		});

		filtered.sort(function (a, b) { return b.total - a.total; });

		var statusLabels = {};
		Object.keys(state.compra_statuses || {}).forEach(function (k) { statusLabels[k] = state.compra_statuses[k]; });
		Object.keys(state.agenda_statuses || {}).forEach(function (k) { statusLabels[k] = state.agenda_statuses[k]; });
		var statusKeys = Object.keys(byStatus).filter(function (statusKey) {
			return !dayView || !isGestionTerminalStatus(statusKey);
		});
		var statusHtml = statusKeys.map(function (statusKey) {
			return (
				'<tr>' +
					'<td data-label="Estado">' + escapeHtml(labelMap(statusLabels, statusKey)) + '</td>' +
					'<td class="is-numeric" data-label="Tiempo">' + escapeHtml(formatDurationSeconds(byStatus[statusKey])) + '</td>' +
				'</tr>'
			);
		}).join('');

		var detailHtml = filtered.slice(0, 50).map(function (row) {
			return (
				'<tr>' +
					'<td data-label="Tipo">' + escapeHtml(row.tipoLabel) + '</td>' +
					'<td data-label="Detalle">' + escapeHtml(row.titulo) + '</td>' +
					'<td data-label="Proveedor">' + escapeHtml(row.proveedor) + '</td>' +
					'<td data-label="Estado">' + escapeHtml(row.status) + '</td>' +
					'<td class="is-numeric" data-label="Tiempo gestión">' + escapeHtml(formatDurationSeconds(row.total)) + '</td>' +
					'<td class="is-numeric" data-label="Novedades">' + escapeHtml(String(row.novedades)) + '</td>' +
				'</tr>'
			);
		}).join('');

		var provHtml = Object.keys(byProveedor).map(function (id) {
			var row = byProveedor[id];
			var avg = row.count ? Math.round(row.total / row.count) : 0;
			return (
				'<tr>' +
					'<td data-label="Proveedor">' + escapeHtml(row.nombre) + '</td>' +
					'<td class="is-numeric" data-label="Compras">' + escapeHtml(String(row.count)) + '</td>' +
					'<td class="is-numeric" data-label="Tiempo total">' + escapeHtml(formatDurationSeconds(row.total)) + '</td>' +
					'<td class="is-numeric" data-label="Promedio">' + escapeHtml(formatDurationSeconds(avg)) + '</td>' +
				'</tr>'
			);
		}).join('');

		var modeNote = dayView
			? '<p class="logistica-user-panel__informe-note">Vista del <strong>día actual</strong>: solo registros activos (pendiente, en proceso u otros abiertos) y tiempo contado desde las 00:00 de hoy. Usa filtros de fecha o «Ver acumulado total» para el histórico.</p>'
			: '';

		wrap.innerHTML =
			modeNote +
			'<div class="logistica-user-panel__informe-grid">' +
				'<section class="logistica-user-panel__informe-block">' +
					'<h3>Tiempo de gestión por estado' + (dayView ? ' (hoy)' : '') + '</h3>' +
					'<div class="logistica-user-panel__informe-scroll">' +
						'<table class="logistica-user-panel__informe-table">' +
							'<thead><tr><th>Estado</th><th>Tiempo</th></tr></thead>' +
							'<tbody>' + (statusHtml || '<tr><td colspan="2">Sin datos</td></tr>') + '</tbody>' +
						'</table>' +
					'</div>' +
				'</section>' +
				'<section class="logistica-user-panel__informe-block">' +
					'<h3>Historial por proveedor' + (dayView ? ' (hoy)' : '') + '</h3>' +
					'<div class="logistica-user-panel__informe-scroll">' +
						'<table class="logistica-user-panel__informe-table">' +
							'<thead><tr><th>Proveedor</th><th>Compras</th><th>Tiempo total</th><th>Promedio</th></tr></thead>' +
							'<tbody>' + (provHtml || '<tr><td colspan="4">Sin datos de proveedores</td></tr>') + '</tbody>' +
						'</table>' +
					'</div>' +
				'</section>' +
				'<section class="logistica-user-panel__informe-block logistica-user-panel__informe-block--wide">' +
					'<h3>Resumen por registro' + (dayView ? ' (activos hoy)' : '') + '</h3>' +
					'<div class="logistica-user-panel__informe-scroll">' +
						'<table class="logistica-user-panel__informe-table">' +
							'<thead><tr><th>Tipo</th><th>Detalle</th><th>Proveedor</th><th>Estado</th><th>Tiempo gestión</th><th>Novedades</th></tr></thead>' +
							'<tbody>' + detailHtml + '</tbody>' +
						'</table>' +
					'</div>' +
				'</section>' +
			'</div>';
	}

	function refreshCompraEditPanels(item) {
		var article = findEditFormArticle('compras', item.id);
		if (!article) {
			return;
		}
		var summary = article.querySelector('[data-compra-gestion-summary]');
		var novedades = article.querySelector('[data-compra-novedades]');
		if (summary || novedades) {
			var tmp = document.createElement('div');
			tmp.innerHTML = renderComprasEditForm(item);
			if (summary) {
				var nextSummary = tmp.querySelector('[data-compra-gestion-summary]');
				if (nextSummary) {
					summary.replaceWith(nextSummary);
				}
			}
			if (novedades) {
				var nextNov = tmp.querySelector('[data-compra-novedades]');
				if (nextNov) {
					novedades.replaceWith(nextNov);
				}
			}
		}
	}

	function addCompraNovedadFromModal(compraId) {
		var item = findListItem('compras', compraId);
		if (!item) {
			return;
		}
		ensureCompraGestionFields(item);

		var article = findEditFormArticle('compras', compraId);
		if (!article) {
			return;
		}

		var atField = article.querySelector('[data-compra-novedad-at]');
		var textoField = article.querySelector('[data-compra-novedad-texto]');
		var notifyField = article.querySelector('[data-compra-novedad-notify]');
		var texto = textoField ? String(textoField.value || '').trim() : '';
		if (!texto) {
			window.alert('Escribe la novedad antes de agregarla.');
			return;
		}

		var atSql = sqlFromDatetimeLocal(atField ? atField.value : '');
		var nov = {
			id: generateId('nov'),
			at: atSql,
			texto: texto,
			status: item.status || 'pendiente'
		};
		item.novedades.push(nov);
		item.updated_at = nowSql();

		if (notifyField && notifyField.checked) {
			pushPanelAviso({
				title: 'Novedad en compra: ' + compraProductoLabel(item),
				body: formatColombiaDateTime(atSql) + ' — ' + texto,
				source_type: 'compras',
				source_id: item.id,
				dedupe_key: 'nov_' + nov.id
			}, false);
		}

		if (atField) {
			atField.value = datetimeLocalFromSql(nowSql());
		}
		if (textoField) {
			textoField.value = '';
		}

		refreshCompraEditPanels(item);
		editSnapshots['compras:' + item.id] = JSON.parse(JSON.stringify(item));
		renderAvisos();
		renderInformeTiempos();
	}

	function refreshAgendaEditPanels(item) {
		var article = findEditFormArticle('agenda', item.id);
		if (!article) {
			return;
		}
		var summary = article.querySelector('[data-agenda-gestion-summary]');
		var novedades = article.querySelector('[data-agenda-novedades]');
		if (summary || novedades) {
			var tmp = document.createElement('div');
			tmp.innerHTML = renderAgendaEditForm(item);
			if (summary) {
				var nextSummary = tmp.querySelector('[data-agenda-gestion-summary]');
				if (nextSummary) {
					summary.replaceWith(nextSummary);
				}
			}
			if (novedades) {
				var nextNov = tmp.querySelector('[data-agenda-novedades]');
				if (nextNov) {
					novedades.replaceWith(nextNov);
				}
			}
		}
	}

	function addAgendaNovedadFromModal(agendaId) {
		var item = findListItem('agenda', agendaId);
		if (!item) {
			return;
		}
		ensureAgendaGestionFields(item);

		var article = findEditFormArticle('agenda', agendaId);
		if (!article) {
			return;
		}

		var atField = article.querySelector('[data-agenda-novedad-at]');
		var textoField = article.querySelector('[data-agenda-novedad-texto]');
		var notifyField = article.querySelector('[data-agenda-novedad-notify]');
		var texto = textoField ? String(textoField.value || '').trim() : '';
		if (!texto) {
			window.alert('Escribe la novedad antes de agregarla.');
			return;
		}

		var atSql = sqlFromDatetimeLocal(atField ? atField.value : '');
		var nov = {
			id: generateId('nov'),
			at: atSql,
			texto: texto,
			status: item.status || 'pendiente'
		};
		item.novedades.push(nov);
		item.updated_at = nowSql();

		if (notifyField && notifyField.checked) {
			pushPanelAviso({
				title: 'Novedad en agenda: ' + (item.title || 'Actividad'),
				body: formatColombiaDateTime(atSql) + ' — ' + texto,
				source_type: 'agenda',
				source_id: item.id,
				dedupe_key: 'nov_' + nov.id
			}, false);
		}

		if (atField) {
			atField.value = datetimeLocalFromSql(nowSql());
		}
		if (textoField) {
			textoField.value = '';
		}

		refreshAgendaEditPanels(item);
		editSnapshots['agenda:' + item.id] = JSON.parse(JSON.stringify(item));
		renderAvisos();
		renderInformeTiempos();
	}

	function removeAgendaNovedad(agendaId, novedadId) {
		var item = findListItem('agenda', agendaId);
		if (!item || !Array.isArray(item.novedades)) {
			return;
		}
		item.novedades = item.novedades.filter(function (nov) {
			return String(nov.id) !== String(novedadId);
		});
		item.updated_at = nowSql();
		refreshAgendaEditPanels(item);
		editSnapshots['agenda:' + item.id] = JSON.parse(JSON.stringify(item));
		renderInformeTiempos();
	}

	function removeCompraNovedad(compraId, novedadId) {
		var item = findListItem('compras', compraId);
		if (!item || !Array.isArray(item.novedades)) {
			return;
		}
		item.novedades = item.novedades.filter(function (nov) {
			return String(nov.id) !== String(novedadId);
		});
		item.updated_at = nowSql();
		refreshCompraEditPanels(item);
		editSnapshots['compras:' + item.id] = JSON.parse(JSON.stringify(item));
		renderInformeTiempos();
	}

	function markAvisosRead(ids, done) {
		var avisos = ensurePanelAvisos();
		if (ids === 'all') {
			avisos.forEach(function (aviso) {
				aviso.read = true;
			});
		} else if (Array.isArray(ids)) {
			var idSet = {};
			ids.forEach(function (id) {
				idSet[String(id)] = true;
			});
			avisos.forEach(function (aviso) {
				if (idSet[String(aviso.id)]) {
					aviso.read = true;
				}
			});
		}
		renderAvisos();

		var body = new FormData();
		body.append('action', 'logistica_mark_panel_avisos_read');
		body.append('nonce', getUserPanelNonce());
		body.append('aviso_ids', ids === 'all' ? 'all' : JSON.stringify(ids));

		fetch(config().ajaxUrl, { method: 'POST', body: body, credentials: 'same-origin' })
			.then(function (res) { return res.json(); })
			.then(function (json) {
				if (json && json.success && json.data && json.data.panel) {
					state.panel = json.data.panel;
					renderAvisos();
				}
				if (typeof done === 'function') {
					done(null, json);
				}
			})
			.catch(function (err) {
				if (typeof done === 'function') {
					done(err);
				}
			});
	}

	function sendAvisoEmail(avisoId) {
		var body = new FormData();
		body.append('action', 'logistica_send_panel_aviso_email');
		body.append('nonce', getUserPanelNonce());
		body.append('aviso_id', avisoId);

		fetch(config().ajaxUrl, { method: 'POST', body: body, credentials: 'same-origin' })
			.then(function (res) { return res.json(); })
			.then(function (json) {
				if (json && json.success && json.data && json.data.panel) {
					state.panel = json.data.panel;
					renderAvisos();
					setSaveStatus('Aviso enviado por correo.', 'saved');
				} else {
					var msg = json && json.data && json.data.message ? json.data.message : 'No se pudo enviar el correo.';
					setSaveStatus(msg, 'error');
				}
			})
			.catch(function () {
				setSaveStatus('No se pudo enviar el correo.', 'error');
			});
	}

	function scheduleSecondaryRender() {
		if (window.requestIdleCallback) {
			window.requestIdleCallback(function () {
				renderAllSecondary();
			}, { timeout: 150 });
			return;
		}

		window.requestAnimationFrame(function () {
			renderAllSecondary();
		});
	}

	function renderAll() {
		renderAllPrimary();
		renderAllSecondary();
	}

	function findListItem(section, id) {
		var list = state.panel[section];
		if (!Array.isArray(list)) {
			return null;
		}

		id = normalizePanelItemId(id);

		for (var i = 0; i < list.length; i++) {
			if (normalizePanelItemId(list[i].id) === id) {
				return list[i];
			}
		}

		return null;
	}

	function applyChecklistFieldChange(checkItem, checkKey, field) {
		if (checkKey === 'done') {
			checkItem.done = field.value === '1';
			return;
		}

		if (checkKey === 'duration_minutes') {
			checkItem.duration_minutes = parseInt(field.value, 10) || 0;
			return;
		}

		if (checkKey === 'recurrence') {
			checkItem.recurrence = field.value;
			if (checkItem.recurrence === 'repetitivo') {
				checkItem.series_id = checkItem.series_id || checkItem.id;
			} else {
				checkItem.series_id = '';
				checkItem.last_reset_week = '';
				if (checkItem.recurrence !== 'diario') {
					checkItem.carried_from = '';
				}
			}
			return;
		}

		if (checkKey) {
			checkItem[checkKey] = panelFieldValueFromInput(field);
		}
	}

	function findChecklistItem(date, id) {
		var linkedItem = findLinkedChecklistItem(date, id);
		if (linkedItem) {
			return linkedItem;
		}

		var day = state.panel.checklist_days[date];
		if (!day || !Array.isArray(day.items)) {
			return null;
		}

		for (var i = 0; i < day.items.length; i++) {
			if (normalizePanelItemId(day.items[i].id) === id) {
				return day.items[i];
			}
		}

		return null;
	}

	function addItem(section) {
		if (editingItems[section]) {
			if (isUnsavedNewItem(section, editingItems[section])) {
				openSectionEditModal(section, editingItems[section]);
				return;
			}
			cancelEdit(section, editingItems[section]);
		}

		var now = nowSql();
		var newId = '';

		if (section === 'pendientes') {
			newId = generateId('pend');
			state.panel.pendientes.unshift({
				id: newId,
				title: '',
				status: 'en_proceso',
				notes: '',
				updated_at: now,
				created_at: now
			});
		} else if (section === 'agenda') {
			newId = generateId('agenda');
			resetPanelListPage('agenda');
			state.panel.agenda.unshift({
				id: newId,
				title: '',
				date: state.today,
				time: '',
				notes: '',
				priority: 'media',
				status: 'pendiente',
				done: false,
				created_at: now,
				gestion_started_at: now,
				status_timeline: [{
					status: 'pendiente',
					started_at: now,
					ended_at: '',
					seconds: 0
				}],
				novedades: [],
				updated_at: now
			});
		} else if (section === 'compras') {
			newId = generateId('compra');
			resetPanelListPage('compras');
			state.panel.compras.unshift({
				id: newId,
				producto_ofrecido: '',
				referencia: '',
				precio: '',
				cantidad: '',
				unidad_medida: '',
				fecha_requerida: '',
				fecha_solicitud: state.today || '',
				status: 'pendiente',
				priority: 'media',
				escala: '',
				proveedor_id: '',
				fecha: state.today || '',
				documento_numero: '',
				fecha_recibido: '',
				created_at: now,
				gestion_started_at: now,
				status_timeline: [{
					status: 'pendiente',
					started_at: now,
					ended_at: '',
					seconds: 0
				}],
				novedades: [],
				updated_at: now
			});
		} else if (section === 'proveedores') {
			newId = generateId('prov');
			if (!Array.isArray(state.panel.proveedores)) {
				state.panel.proveedores = [];
			}
			proveedoresPage = 1;
			state.panel.proveedores.unshift({
				id: newId,
				nombre: '',
				email: '',
				telefono: '',
				contacto: '',
				descripcion: '',
				updated_at: now
			});
		} else {
			return;
		}

		editSnapshots[section + ':' + newId] = JSON.parse(JSON.stringify(findListItem(section, newId)));
		unsavedNewItems[section] = newId;
		editingItems[section] = newId;
		renderAll();
		openSectionEditModal(section, newId);
	}

	function addChecklistItem(date) {
		var targetDate = date || getSelectedChecklistDate() || state.today;
		var targetDay = (state.panel.checklist_days || {})[targetDate] || {};

		if (isNonWorkingDayType(resolveDayType(targetDate, targetDay))) {
			return;
		}

		if (editingChecklistKey) {
			var activeEdit = parseChecklistEditKey(editingChecklistKey);
			if (activeEdit && activeEdit.date === targetDate && isUnsavedNewChecklist(activeEdit.date, activeEdit.id)) {
				openSectionEditModal('checklist', activeEdit.id, targetDate);
				return;
			}
			if (activeEdit) {
				cancelChecklistEdit(activeEdit.date, activeEdit.id);
			}
		}

		if (!state.panel.checklist_days[targetDate]) {
			state.panel.checklist_days[targetDate] = { day_type: '', items: [] };
		}

		var newId = generateId('check');
		state.panel.checklist_days[targetDate].items.unshift({
			id: newId,
			series_id: newId,
			title: '',
			duration_minutes: 30,
			priority: 'media',
			recurrence: 'repetitivo',
			done: false,
			carried_from: '',
			last_reset_week: ''
		});

		selectedChecklistDate = targetDate;
		var key = checklistEditKey(targetDate, newId);
		editChecklistSnapshots[key] = JSON.parse(JSON.stringify(findChecklistItem(targetDate, newId)));
		unsavedNewChecklistKey = key;
		editingChecklistKey = key;
		renderChecklist();
		openSectionEditModal('checklist', newId, targetDate);
	}

	function confirmPanelDelete(message, detail) {
		var text = String(message || '¿Eliminar este registro?');

		if (detail) {
			text += '\n\n' + String(detail);
		}

		text += '\n\nEsta acción no se puede deshacer.';

		if (typeof window.confirm !== 'function') {
			return true;
		}

		return window.confirm(text);
	}

	function panelDeleteDetail(section, id, checkDate) {
		if (section === 'checklist') {
			var checkItem = findChecklistItem(checkDate, id);
			if (!checkItem) {
				return '';
			}

			if (checkItem.linked) {
				return checkItem.title || checkItem.link_label || '';
			}

			return checkItem.title || '';
		}

		var item = findListItem(section, id);
		if (!item) {
			return '';
		}

		if (section === 'compras') {
			return compraProductoLabel(item);
		}

		if (section === 'proveedores') {
			return item.nombre || '';
		}

		return item.title || '';
	}

	function confirmPanelDeleteAction(section, id, checkDate) {
		var detail = panelDeleteDetail(section, id, checkDate);
		var messages = {
			agenda: '¿Eliminar esta actividad de la agenda?',
			compras: '¿Eliminar esta cotización o compra?',
			proveedores: '¿Eliminar este proveedor?',
			pendientes: '¿Eliminar este pendiente?',
			checklist: '¿Eliminar esta actividad del chequeo diario?',
			resume_points: '¿Quitar este punto de retoma?'
		};

		if (section === 'checklist') {
			var checkItem = findChecklistItem(checkDate, id);
			if (checkItem && getChecklistSeriesId(checkItem)) {
				messages.checklist = '¿Eliminar esta actividad repetitiva del chequeo?';
				if (!detail) {
					detail = 'Se quitará de todos los días de la semana en que aparezca.';
				} else {
					detail += '\n\nSe quitará de todos los días de la semana en que aparezca.';
				}
			}
		}

		return confirmPanelDelete(messages[section] || '¿Eliminar este registro del panel?', detail);
	}

	function normalizePanelItemId(id) {
		return id == null ? '' : String(id);
	}

	function requestPanelDelete(section, id, checkDate) {
		section = String(section || '');
		id = normalizePanelItemId(id);
		checkDate = checkDate || '';

		if (!section || !id) {
			return;
		}

		if (!confirmPanelDeleteAction(section, id, checkDate)) {
			return;
		}

		if (section === 'checklist') {
			var linked = parseLinkedChecklistId(id);
			if (linked) {
				removeItem(linked.section, linked.sourceId);
				return;
			}

			removeChecklistItem(checkDate, id);
			return;
		}

		removeItem(section, id);
	}

	function removeItem(section, id, shouldSave) {
		id = normalizePanelItemId(id);

		if (shouldSave === undefined) {
			shouldSave = true;
		}

		var list = state.panel[section];
		if (!Array.isArray(list)) {
			return;
		}

		state.panel[section] = list.filter(function (item) {
			return normalizePanelItemId(item.id) !== id;
		});

		if (section === 'proveedores' && Array.isArray(state.panel.compras)) {
			state.panel.compras.forEach(function (compra) {
				if (compra.proveedor_id === id) {
					compra.proveedor_id = '';
				}
			});
		}

		if (editingItems[section] === id) {
			editingItems[section] = '';
		}

		if (isModalOpen()) {
			var modalCtx = getModalContext();
			if (modalCtx && modalCtx.section === section && modalCtx.id === id) {
				closeEditModal();
			}
		}

		clearUnsavedNewItem(section, id);
		delete editSnapshots[section + ':' + id];
		renderAll();

		if (shouldSave) {
			savePanelNow();
		}
	}

	function getChecklistSeriesId(item) {
		if (!item || item.linked) {
			return '';
		}

		if ((item.recurrence || 'diario') !== 'repetitivo') {
			return '';
		}

		return normalizePanelItemId(item.series_id || item.id);
	}

	function removeChecklistSeriesFromAllDays(seriesId) {
		seriesId = normalizePanelItemId(seriesId);
		if (!seriesId || !state.panel || !state.panel.checklist_days) {
			return;
		}

		Object.keys(state.panel.checklist_days).forEach(function (dayDate) {
			var day = state.panel.checklist_days[dayDate];
			if (!day || !Array.isArray(day.items)) {
				return;
			}

			day.items = day.items.filter(function (checkItem) {
				if ((checkItem.recurrence || 'diario') !== 'repetitivo') {
					return true;
				}

				return normalizePanelItemId(checkItem.series_id || checkItem.id) !== seriesId;
			});
		});
	}

	function removeChecklistItem(date, id, shouldSave) {
		id = normalizePanelItemId(id);

		if (shouldSave === undefined) {
			shouldSave = true;
		}

		var item = findChecklistItem(date, id);
		var seriesId = getChecklistSeriesId(item);

		if (seriesId) {
			removeChecklistSeriesFromAllDays(seriesId);
		} else {
			var day = state.panel.checklist_days[date];
			if (!day) {
				return;
			}

			day.items = (day.items || []).filter(function (checkItem) {
				return normalizePanelItemId(checkItem.id) !== id;
			});
		}

		if (editingChecklistKey === checklistEditKey(date, id)) {
			editingChecklistKey = '';
		}

		if (isModalOpen()) {
			var modalCtx = getModalContext();
			if (modalCtx && modalCtx.section === 'checklist' && modalCtx.id === id && modalCtx.checkDate === date) {
				closeEditModal();
			}
		}

		clearUnsavedNewChecklist(date, id);
		delete editChecklistSnapshots[checklistEditKey(date, id)];
		renderChecklist();

		if (shouldSave) {
			savePanelNow();
		}
	}

	function updateChecklistField(field) {
		var checkRow = field.closest('[data-check-date]');
		if (!checkRow) {
			return false;
		}

		var date = checkRow.getAttribute('data-check-date');
		var checkId = checkRow.getAttribute('data-id');
		if (editingChecklistKey !== checklistEditKey(date, checkId)) {
			return false;
		}

		var checkItem = findChecklistItem(date, checkId);
		if (!checkItem) {
			return false;
		}

		var checkKey = field.getAttribute('data-field');
		if (!checkKey) {
			return false;
		}

		applyChecklistFieldChange(checkItem, checkKey, field);
		return true;
	}

	function updateListItemField(field) {
		var article = field.closest('[data-user-panel-item]');
		if (!article) {
			return false;
		}

		var section = article.getAttribute('data-user-panel-item');
		var id = article.getAttribute('data-id');
		var item = findListItem(section, id);
		if (!item) {
			return false;
		}

		var key = field.getAttribute('data-field');
		if (!key) {
			return false;
		}

		var previousStatus = '';
		if (section === 'compras' && key === 'status') {
			previousStatus = item.status || 'pendiente';
		}
		if (section === 'agenda' && key === 'status') {
			previousStatus = item.status || (item.done ? 'completado' : 'pendiente');
		}

		if (isListSection(section) && editingItems[section] !== id) {
			return false;
		}

		if (field.type === 'checkbox') {
			item[key] = field.checked;
		} else {
			item[key] = field.value;
		}

		if (section === 'agenda' && key === 'status') {
			item.done = isAgendaComplete(item);
			recordStatusChange(item, previousStatus, item.status, nowSql());
			refreshAgendaEditPanels(item);
		}

		if (section === 'compras' && key === 'status') {
			applyCompraStatusSideEffects(item, previousStatus);
			refreshCompraEditPanels(item);
		}

		if (section === 'pendientes' || section === 'compras' || section === 'agenda') {
			item.updated_at = nowSql();
		}

		if (isListSection(section)) {
			return true;
		}

		scheduleSave();
		return true;
	}

	function bindEvents() {
		if (bound || !root) {
			return;
		}

		bound = true;
		bindModalFloatingTips();

		root.addEventListener('click', function (event) {
			if (event.target.closest('[data-user-panel-modal-save]')) {
				handleModalSave();
				return;
			}

			if (event.target.closest('[data-user-panel-modal-cancel]') || event.target.closest('[data-user-panel-modal-close]')) {
				handleModalCancel();
				return;
			}

			if (event.target.closest('[data-user-panel-avisos-mark-all]')) {
				markAvisosRead('all');
				return;
			}

			if (event.target.closest('[data-user-panel-avisos-delete-read]')) {
				deleteReadAvisos();
				return;
			}

			if (event.target.closest('[data-user-panel-avisos-toggle-read]')) {
				avisosShowRead = !avisosShowRead;
				renderAvisos();
				return;
			}

			var markReadBtn = event.target.closest('[data-aviso-mark-read]');
			if (markReadBtn) {
				openAvisoMarkReadModal(markReadBtn.getAttribute('data-aviso-mark-read'));
				return;
			}

			var openAvisoBtn = event.target.closest('[data-aviso-open-source]');
			if (openAvisoBtn) {
				openAvisoSource(openAvisoBtn.getAttribute('data-aviso-open-source'));
				return;
			}

			var deleteAvisoBtn = event.target.closest('[data-aviso-delete]');
			if (deleteAvisoBtn) {
				deleteAviso(deleteAvisoBtn.getAttribute('data-aviso-delete'));
				return;
			}

			var sendEmailBtn = event.target.closest('[data-aviso-send-email]');
			if (sendEmailBtn) {
				sendAvisoEmail(sendEmailBtn.getAttribute('data-aviso-send-email'));
				return;
			}

			var addNovedadBtn = event.target.closest('[data-compra-novedad-add]');
			if (addNovedadBtn) {
				var compraArticle = addNovedadBtn.closest('[data-user-panel-item="compras"]');
				if (compraArticle) {
					addCompraNovedadFromModal(compraArticle.getAttribute('data-id'));
				}
				return;
			}

			var removeNovedadBtn = event.target.closest('[data-compra-novedad-remove]');
			if (removeNovedadBtn) {
				var compraArticleRemove = removeNovedadBtn.closest('[data-user-panel-item="compras"]');
				if (compraArticleRemove) {
					removeCompraNovedad(
						compraArticleRemove.getAttribute('data-id'),
						removeNovedadBtn.getAttribute('data-compra-novedad-remove')
					);
				}
				return;
			}

			var addAgendaNovBtn = event.target.closest('[data-agenda-novedad-add]');
			if (addAgendaNovBtn) {
				var agendaArticle = addAgendaNovBtn.closest('[data-user-panel-item="agenda"]');
				if (agendaArticle) {
					addAgendaNovedadFromModal(agendaArticle.getAttribute('data-id'));
				}
				return;
			}

			var removeAgendaNovBtn = event.target.closest('[data-agenda-novedad-remove]');
			if (removeAgendaNovBtn) {
				var agendaArticleRemove = removeAgendaNovBtn.closest('[data-user-panel-item="agenda"]');
				if (agendaArticleRemove) {
					removeAgendaNovedad(
						agendaArticleRemove.getAttribute('data-id'),
						removeAgendaNovBtn.getAttribute('data-agenda-novedad-remove')
					);
				}
				return;
			}

			var informeClear = event.target.closest('[data-user-panel-informe-filter-clear]');
			if (informeClear) {
				informeFilters = {
					tipo: '',
					status: '',
					proveedor_id: '',
					fecha_desde: '',
					fecha_hasta: '',
					solo_activos: false
				};
				informeDefaultsReady = true;
				renderInformeTiempos();
				return;
			}

			var addBtn = event.target.closest('[data-user-panel-add]');
			if (addBtn) {
				addItem(addBtn.getAttribute('data-user-panel-add'));
				return;
			}

			if (event.target.closest('[data-user-panel-import-proveedores]')) {
				var importInput = root.querySelector('[data-user-panel-proveedores-file]');
				if (importInput) {
					importInput.click();
				}
				return;
			}

			if (event.target.closest('[data-user-panel-export-proveedores]')) {
				var exportUrl = buildProveedoresExportUrl();
				if (exportUrl) {
					event.preventDefault();
					window.location.href = exportUrl;
				}
				return;
			}

			if (event.target.closest('[data-user-panel-import-compras]')) {
				var comprasInput = root.querySelector('[data-user-panel-compras-file]');
				if (comprasInput) {
					comprasInput.click();
				}
				return;
			}

			if (event.target.closest('[data-user-panel-export-compras]')) {
				var comprasExportUrl = buildComprasExportUrl();
				if (comprasExportUrl) {
					event.preventDefault();
					window.location.href = comprasExportUrl;
				}
				return;
			}

			if (event.target.closest('[data-user-panel-add-checklist]')) {
				if (isChecklistReadOnlyWeek()) {
					return;
				}
				addChecklistItem(getSelectedChecklistDate());
				return;
			}

			if (event.target.closest('[data-user-panel-checklist-week-prev]')) {
				if (checklistWeekOffset <= -MAX_CHECKLIST_WEEK_OFFSET) {
					return;
				}
				if (isModalOpen()) {
					handleModalCancel();
				} else {
					editingChecklistKey = '';
				}
				checklistWeekOffset -= 1;
				shiftSelectedDateForWeekOffset(checklistWeekOffset);
				renderChecklist();
				return;
			}

			if (event.target.closest('[data-user-panel-checklist-week-next]')) {
				if (checklistWeekOffset >= MAX_CHECKLIST_WEEK_OFFSET) {
					return;
				}
				if (isModalOpen()) {
					handleModalCancel();
				} else {
					editingChecklistKey = '';
				}
				checklistWeekOffset += 1;
				shiftSelectedDateForWeekOffset(checklistWeekOffset);
				if (checklistWeekOffset === 0 && state.today) {
					selectedChecklistDate = state.today;
				}
				renderChecklist();
				return;
			}

			var dayTab = event.target.closest('[data-user-panel-checklist-day]');
			if (dayTab) {
				if (isModalOpen()) {
					handleModalCancel();
				} else {
					editingChecklistKey = '';
				}
				selectedChecklistDate = dayTab.getAttribute('data-user-panel-checklist-day') || state.today;
				renderChecklist();
				return;
			}

			if (event.target.closest('[data-panel-edit]') && handleChecklistPanelAction(event, 'edit')) {
				return;
			}

			var viewBtn = event.target.closest('[data-panel-view]');
			if (viewBtn) {
				var viewSection = viewBtn.getAttribute('data-user-panel-view-section');
				var viewId = viewBtn.getAttribute('data-user-panel-view-id');
				var viewCheckDate = viewBtn.getAttribute('data-user-panel-view-check-date') || '';
				if (viewSection && viewId) {
					openSectionViewModal(viewSection, viewId, viewCheckDate);
				}
				return;
			}

			if (event.target.closest('[data-panel-complete]') && handleChecklistPanelAction(event, 'complete')) {
				return;
			}

			if (event.target.closest('[data-panel-delete]')) {
				var checklistRow = event.target.closest('[data-check-date][data-id]');
				if (checklistRow && !checklistRow.closest('[data-user-panel-item]')) {
					if (handleChecklistPanelAction(event, 'delete')) {
						return;
					}
				}

				var deleteArticle = event.target.closest('[data-user-panel-item]');
				if (deleteArticle) {
					var deleteSection = deleteArticle.getAttribute('data-user-panel-item') || '';
					var deleteId = deleteArticle.getAttribute('data-id') || '';
					if (deleteSection === 'resume_points') {
						if (confirmPanelDeleteAction('resume_points', deleteId)) {
							dismissResumePoint(deleteId);
						}
					} else if (deleteSection) {
						requestPanelDelete(deleteSection, deleteId);
					}
				}
				return;
			}

			var editBtn = event.target.closest('[data-panel-edit]');
			if (editBtn) {
				var editArticle = editBtn.closest('[data-user-panel-item]');
				if (editArticle) {
					startEdit(editArticle.getAttribute('data-user-panel-item'), editArticle.getAttribute('data-id'));
				}
				return;
			}

			var resolveBtn = event.target.closest('[data-panel-resolve]');
			if (resolveBtn) {
				var resolveArticle = resolveBtn.closest('[data-user-panel-item]');
				if (resolveArticle) {
					openSourceResolveModal(
						resolveArticle.getAttribute('data-user-panel-item'),
						resolveArticle.getAttribute('data-id')
					);
				}
				return;
			}

			var completeBtn = event.target.closest('[data-panel-complete]');
			if (completeBtn) {
				var completeArticle = completeBtn.closest('[data-user-panel-item]');
				if (completeArticle) {
					markSectionItemComplete(
						completeArticle.getAttribute('data-user-panel-item'),
						completeArticle.getAttribute('data-id')
					);
				}
				return;
			}

			var removeBtn = event.target.closest('[data-user-panel-remove]');
			if (removeBtn) {
				var article = removeBtn.closest('[data-user-panel-item]');
				if (article) {
					requestPanelDelete(
						article.getAttribute('data-user-panel-item') || '',
						article.getAttribute('data-id') || ''
					);
				}
				return;
			}

			var dismissResumeBtn = event.target.closest('[data-resume-dismiss]');
			if (dismissResumeBtn) {
				var resumePointId = dismissResumeBtn.getAttribute('data-resume-dismiss') || '';
				if (confirmPanelDeleteAction('resume_points', resumePointId)) {
					dismissResumePoint(resumePointId);
				}
				return;
			}

			if (handleResumePointOpen(event)) {
				return;
			}

			var openProfileBtn = event.target.closest('[data-user-panel-open-profile]');
			if (openProfileBtn) {
				navigateToTabSlug(openProfileBtn.getAttribute('data-profile-tab') || config().profile_tab || 'logistica-perfil');
				return;
			}

			if (event.target.closest('[data-user-panel-quick-links-edit]')) {
				setQuickLinksEditorOpen(!quickLinksEditing);
				renderQuickLinks();
				return;
			}

			if (event.target.closest('[data-user-panel-quick-links-save]')) {
				saveQuickLinks();
				return;
			}

			if (event.target.closest('[data-user-panel-quick-links-cancel]')) {
				setQuickLinksEditorOpen(false);
				renderQuickLinks();
				return;
			}

			var quickLinkOption = event.target.closest('[data-quick-link-option]');
			if (quickLinkOption) {
				toggleQuickLinkDraft(quickLinkOption.getAttribute('data-quick-link-option') || '');
				return;
			}

			var quickLinkBtn = event.target.closest('[data-user-panel-quick-link]');
			if (quickLinkBtn) {
				navigateToTabSlug(quickLinkBtn.getAttribute('data-user-panel-quick-link') || '');
				return;
			}

			if (event.target.closest('[data-user-panel-resume-prev]')) {
				resumePointsOffset = Math.max(0, resumePointsOffset - RESUME_VISIBLE);
				renderResumePoints();
				return;
			}

			if (event.target.closest('[data-user-panel-resume-next]')) {
				var resumeTotal = getResumeItems().length;
				var maxOffset = Math.max(0, resumeTotal - RESUME_VISIBLE);
				resumePointsOffset = Math.min(maxOffset, resumePointsOffset + RESUME_VISIBLE);
				renderResumePoints();
				return;
			}
		});

		document.addEventListener('keydown', function (event) {
			if (event.key !== 'Escape' || !isModalOpen()) {
				return;
			}

			event.preventDefault();
			handleModalCancel();
		});

		root.addEventListener('keydown', function (event) {
			if (event.key !== 'Enter' && event.key !== ' ') {
				return;
			}

			var card = event.target.closest('.logistica-user-panel__resume-card--linked');

			if (!card || event.target.closest('[data-resume-dismiss], [data-resume-open]')) {
				return;
			}

			event.preventDefault();
			handleResumePointOpen(event);
		});

		root.addEventListener('input', function (event) {
			var field = event.target;
			if (updateListItemField(field)) {
				return;
			}

			if (updateChecklistField(field)) {
				return;
			}
		});

		root.addEventListener('change', function (event) {
			var informeFilter = event.target.closest('[data-user-panel-informe-filter]');
			if (informeFilter) {
				var filterKey = informeFilter.getAttribute('data-user-panel-informe-filter');
				if (filterKey && Object.prototype.hasOwnProperty.call(informeFilters, filterKey)) {
					informeFilters[filterKey] = informeFilter.value || '';
					informeFilters.solo_activos = false;
					if (filterKey === 'tipo') {
						informeFilters.status = '';
					}
					renderInformeTiempos();
				}
				return;
			}

			var proveedoresFile = event.target.closest('[data-user-panel-proveedores-file]');
			if (proveedoresFile && proveedoresFile.files && proveedoresFile.files[0]) {
				importProveedores(proveedoresFile.files[0]);
				proveedoresFile.value = '';
				return;
			}

			var comprasFile = event.target.closest('[data-user-panel-compras-file]');
			if (comprasFile && comprasFile.files && comprasFile.files[0]) {
				importCompras(comprasFile.files[0]);
				comprasFile.value = '';
				return;
			}

			var field = event.target;

			if (updateListItemField(field)) {
				return;
			}

			if (updateChecklistField(field)) {
				return;
			}

			var dayCard = field.closest('[data-check-day]');
			if (dayCard && field.matches('[data-field="day_type"]')) {
				if (!isChecklistDayTypeEditable()) {
					return;
				}

				var date = dayCard.getAttribute('data-check-day');
				if (!state.panel.checklist_days[date]) {
					state.panel.checklist_days[date] = { day_type: '', day_type_manual: false, items: [] };
				}
				state.panel.checklist_days[date].day_type = field.value;
				state.panel.checklist_days[date].day_type_manual = true;
				renderChecklist();
				scheduleSave();
			}
		});
	}

	function buildProveedoresExportUrl() {
		var cfg = config();
		var nonce = getUserPanelNonce();
		if (cfg.ajaxUrl && nonce) {
			var params = new URLSearchParams({
				action: 'logistica_export_panel_proveedores',
				nonce: nonce
			});
			return cfg.ajaxUrl + '?' + params.toString();
		}

		return (state && state.proveedores_export_url) || cfg.proveedores_export_url || '';
	}

	function syncProveedoresExportLink() {
		if (!root) {
			return;
		}

		var link = root.querySelector('[data-user-panel-export-proveedores]');
		var url = buildProveedoresExportUrl();

		if (!link || !url) {
			return;
		}

		link.href = url;
	}

	function buildComprasExportUrl() {
		var cfg = config();
		var nonce = getUserPanelNonce();
		if (cfg.ajaxUrl && nonce) {
			var params = new URLSearchParams({
				action: 'logistica_export_panel_compras',
				nonce: nonce
			});
			return cfg.ajaxUrl + '?' + params.toString();
		}

		return (state && state.compras_export_url) || cfg.compras_export_url || '';
	}

	function syncComprasExportLink() {
		if (!root) {
			return;
		}

		var link = root.querySelector('[data-user-panel-export-compras]');
		var url = buildComprasExportUrl();

		if (!link || !url) {
			return;
		}

		link.href = url;
	}

	function initUserPanel(container) {
		var host = container || document.querySelector('[data-user-panel]');
		if (!host) {
			return;
		}

		var panelRoot = host.matches && host.matches('[data-user-panel]')
			? host
			: host.querySelector('[data-user-panel]');

		if (!panelRoot) {
			return;
		}

		if (panelRoot.dataset.userPanelInit === '1') {
			root = panelRoot;
			return;
		}

		root = panelRoot;
		setPanelLoading(true, 'Cargando tareas y recordatorios…', true);

		var bootstrap = readBootstrap(host);
		if (!bootstrap) {
			setPanelLoading(false);
			return;
		}

		panelRoot.dataset.userPanelInit = '1';
		state = bootstrap;
		selectedChecklistDate = state.today || '';
		checklistWeekOffset = 0;
		if (state.panel && !state.panel.checklist_week_history) {
			state.panel.checklist_week_history = {};
		}
		clientBootMs = Date.now();
		syncProveedoresExportLink();
		syncComprasExportLink();

		if (pendingResumePoints) {
			state.panel.resume_points = pendingResumePoints;
			pendingResumePoints = null;
		}

		renderAllPrimary();
		bindEvents();
		startClock();
		setSaveStatus('', '');
		setPanelLoading(false);
		scheduleSecondaryRender();
	}

	window.initLogisticaUserPanel = initUserPanel;
	window.logisticaMergeResumePoints = mergeResumePoints;

	document.addEventListener('logistica:session-refreshed', function (event) {
		var nonces = event && event.detail ? event.detail.nonces : null;
		if (!nonces || !nonces.user_panel || !state) {
			return;
		}
		state.user_panel_nonce = nonces.user_panel;
	});

	if (document.readyState === 'loading') {
		document.addEventListener('DOMContentLoaded', function () {
			initUserPanel();
		});
	} else {
		initUserPanel();
	}
})();
