Quanto custa o fretamento

6 fatores para calcular o preço do aluguel de van, ônibus e micro ônibus​

6 fatores que influenciarão os custos do seu fretamento

Organizar o aluguel de van, ônibus e micro ônibus pode ser uma tarefa exaustiva quando você está tentando obter os valores exatos dos custos totais da sua viagem. No entanto, com apenas algumas informações, planejar os gasto da locação do seu transporte torna-se muito mais simnples.

E mesmo que raramente os orçamentos para uma mesma viagem sejam iguais, existem vários fatores que podem afetar o preço e são utilizados por qualquer empresa de fretamento.

Reunimos um guia para ajudar você a começar a planejar o orçamento da sua viagem. Você verá os diferentes fatores que podem afetar o preço, e também, nossas sugestões de como economizar ao máximo no seu aluguel de van, ônibus e micro ônibus.

1. A distância e duração da sua viagem

Ao cotar o preços do seu transporte, nossos atendentes examinarão primeiro por quanto tempo e qual a distância percorrida em sua viagem. Então, verifique se o local de partida, o destino e as datas já estão confirmadas ou ao menos previstas.
Os veículos são contratados por hora, dia ou quilometragem.
Por exemplo, se você estiver fazendo deslocamentos pela cidade do seu destino final, será cobrado por hora. Lembre-se de que a maioria das empresas de aluguel de ônibus exige um mínimo de 5 horas. Se você está planejando uma viagem que dura alguns dias, como em uma conferência ou festival, será cobrada uma taxa diária. Se você está planejando uma viagem de ida ou volta de e para uma cidade específica, a maioria das empresas de aluguel de ônibus cobra por km rodado.
Sabemos que os itinerários de viagem podem mudar de última hora, embora seja ideal manter-se conforme o que for previamente acordado, seu motorista pode estar disposto a fazer desvios não planejados. Mesmo se você já pagou sua viagem integralmente, poderá ser cobrado por quilometros adicionais fora do seu itinerário original.

2. A época do ano

As tarifas de aluguel de ônibus mudam com as estações do ano. Por exemplo, as contratações de ônibus são mais frequentes quando as escolas estão de recesso, causando alta demanda de viagens e excursões em família e uma diminuição de ônibus disponíveis.
Não importa quando sua viagem ocorrerá, é melhor reservar sua viagem com três a seis meses de antecedência para obter a melhor oferta.

3. A Sua localização inicial

As tarifas de aluguel de ônibus mudam com as estações do ano. Por exemplo, as contratações de ônibus são mais frequentes quando as escolas estão de recesso, causando alta demanda de viagens e excursões em família e uma diminuição de ônibus disponíveis.

4. Taxas ao longo do percurso

Algumas rotas enfrentarão estradas com pedágio, custos de estacionamento e outras taxas de transporte adicionais. A depender do pacote fechado, esses valores já estão inclusos; portanto, pergunte com antecedência se você precisará pagar por pontes de pedágio ou taxas de estacionamento. Você também pode precisar entrar em contato com os hotéis ou locais que planeja visitar para obter especificações sobre estacionamento de ônibus.

5. Turnos, hotéis e gratificações para o seu motorista

Os regulamentos da exigem que os motoristas operem seus veículos apenas por 9 horas por dia e façam uma pausa a cada 4,5 horas. Se sua viagem exigir mais de 9 horas consecutivas de condução, o serviço de aluguel de ônibus precisará fincluir um motorista adicional. Embora um segundo motorista aumente sua taxa, você viaja com mais segurança por ter motoristas descansados e mais atentos.
Nossos serviços de aluguel de ônibus oferecem a possibilidade de que você pague e reserve o hotel de seu motorista para viagens durante a noite. Certifique-se de fornecer ao seu motorista um quarto em um hotel limpo e seguro para garantir que eles estejam bem descansados durante a sua viagem. Pergunte ao seu hotel se eles oferecem quartos com desconto ou gratuitos para os motoristas ao fazer uma reserva de grupo.

6. O tipode de veículo escolhido para o seu fretamento

Você obtém o máximo de valor do seu aluguel de ônibus quando ocupa o máximo de assentos possível. Quanto mais passageiros você tiver preenchendo assentos em seu ônibus, van ou micro, menor será o custo por pessoa. Por exemplo, um grupo de 47 passageiros no total de um ônibus de tamanho padrão geralmente paga menos por pessoa do que um grupo de 38 passageiros .
Se o seu grupo tiver 35 passageiros ou menos, um microônibus pode ser a melhor opção para você. Os microônibus geralmente custam menos do que um aluguel de ônibus comum. No entanto, sem banheiros a bordo e menos compartimentos de armazenamento, os microônibus são melhores para viagens mais curtas. Se você não tiver certeza de qual ônibus é adequado para o seu grupo, ligue para nossos especialista.

cotação de serviços de transporte

agende uma visita, tire suas dúvidas ou simplesmente deixe suas informações para que retornemos o contato.

Seu caso é de itinerários especiais, regiões afastadas ou demandas específicas?

Estamos disponíveis  para atendimento por ligação 24h  todos os dias para responder às suas perguntas relacionadas ao fretamento e ajudá-lo a montar a frota ideal para o seu transporte.

Precisa de ajuda para decidir?

clique e ligue agora.
atendimento 24h

Veja outras páginas

frota de vans, ônibus e micro ônibus enfilereirados na garagem
Frota

Nossa Frota Mais de 50 ônibus, vans e

Ir para o conteúdo var GOOGLE_ATTRIBUTION_URL = 'https://maps.gstatic.com/mapfiles/api-3/images/powered-by-google-on-white3.png'; var BASE_LOCATION = { latitude: -16.2535991668701, longitude: -47.9500007629395 }; var googlePlacesLibraryPromise = null; var QUALIFICATION_FIELD_NAME = 'form_fields[qualificacao_origem]'; var FIELD_CONFIGURATIONS = [ { name: 'form_fields[Origem]', key: 'origem', label: 'Origem' }, { name: 'form_fields[Destino]', key: 'destino', label: 'Destino' }, { name: 'form_fields[endereco]', key: 'endereco', label: 'Localização do atendimento' } ]; var REGIONS_BY_STATE = { AC: 'Norte', AL: 'Nordeste', AM: 'Norte', AP: 'Norte', BA: 'Nordeste', CE: 'Nordeste', DF: 'Centro-Oeste', ES: 'Sudeste', GO: 'Centro-Oeste', MA: 'Nordeste', MG: 'Sudeste', MS: 'Centro-Oeste', MT: 'Centro-Oeste', PA: 'Norte', PB: 'Nordeste', PE: 'Nordeste', PI: 'Nordeste', PR: 'Sul', RJ: 'Sudeste', RN: 'Nordeste', RO: 'Norte', RR: 'Norte', RS: 'Sul', SC: 'Sul', SE: 'Nordeste', SP: 'Sudeste', TO: 'Norte' };function normalizeText(value) { var text = String(value || '').toLowerCase().trim();if (typeof text.normalize === 'function') { text = text.normalize('NFD').replace(/[\u0300-\u036f]/g, ''); }return text.replace(/[–—-]/g, ' ').replace(/\s+/g, ' '); }var SEARCHABLE_MUNICIPALITIES = MUNICIPALITIES.map(function (municipality) { var name = municipality[0]; var state = municipality[1]; var id = municipality[2]; var distanceKm = Number(municipality[3]); var value = name + ' — ' + state;return { id: id, name: name, state: state, distanceKm: distanceKm, region: REGIONS_BY_STATE[state] || '', source: 'IBGE', value: value, normalizedName: normalizeText(name), searchKey: normalizeText(name + ' ' + state) }; }); var MUNICIPALITY_BY_VALUE = {};SEARCHABLE_MUNICIPALITIES.forEach(function (municipality) { MUNICIPALITY_BY_VALUE[normalizeText(municipality.value)] = municipality; });function findMatches(query) { var normalizedQuery = normalizeText(query);if (normalizedQuery.length < MIN_QUERY_LENGTH) { return []; }var tokens = normalizedQuery.split(' ');return SEARCHABLE_MUNICIPALITIES.filter(function (municipality) { return tokens.every(function (token) { return municipality.searchKey.indexOf(token) !== -1; }); }) .sort(function (left, right) { var leftScore = left.normalizedName.indexOf(normalizedQuery) === 0 ? 0 : 1; var rightScore = right.normalizedName.indexOf(normalizedQuery) === 0 ? 0 : 1;if (leftScore !== rightScore) { return leftScore - rightScore; }return left.value.localeCompare(right.value, 'pt-BR'); }) .slice(0, MAX_SUGGESTIONS); }function ensureDatalist() { var datalist = document.getElementById(DATALIST_ID);if (datalist) { return datalist; }datalist = document.createElement('datalist'); datalist.id = DATALIST_ID; document.body.appendChild(datalist); return datalist; }function replaceSuggestions(datalist, matches) { while (datalist.firstChild) { datalist.removeChild(datalist.firstChild); }matches.forEach(function (municipality) { var option = document.createElement('option'); option.value = municipality.value; option.label = municipality.name + ', ' + municipality.state; datalist.appendChild(option); }); }function ensureHiddenField(form, name) { var field = form.querySelector('[name="' + name + '"]');if (field) { return field; }field = document.createElement('input'); field.type = 'hidden'; field.name = name; form.appendChild(field); return field; }function writeMetadata(form, configuration, location) { var prefix = 'form_fields[' + configuration.key; var values = { '_ibge_id]': location && location.id ? String(location.id) : '', '_cidade]': location && location.name ? location.name : '', '_uf]': location && location.state ? location.state : '', '_regiao]': location && location.region ? location.region : '', '_google_place_id]': location && location.googlePlaceId ? location.googlePlaceId : '', '_latitude]': location && Number.isFinite(location.latitude) ? String(location.latitude) : '', '_longitude]': location && Number.isFinite(location.longitude) ? String(location.longitude) : '', '_endereco_formatado]': location && location.formattedAddress ? location.formattedAddress : '', '_distancia_base_km]': location && Number.isFinite(location.distanceKm) ? String(Math.round(location.distanceKm)) : '', '_fonte]': location && location.source ? location.source : '' };Object.keys(values).forEach(function (suffix) { ensureHiddenField(form, prefix + suffix).value = values[suffix]; }); }function calculateDistanceKm(latitude, longitude) { var earthRadiusKm = 6371; var toRadians = Math.PI / 180; var latitudeDelta = (latitude - BASE_LOCATION.latitude) * toRadians; var longitudeDelta = (longitude - BASE_LOCATION.longitude) * toRadians; var startLatitude = BASE_LOCATION.latitude * toRadians; var endLatitude = latitude * toRadians; var haversine = Math.sin(latitudeDelta / 2) * Math.sin(latitudeDelta / 2) + Math.cos(startLatitude) * Math.cos(endLatitude) * Math.sin(longitudeDelta / 2) * Math.sin(longitudeDelta / 2);return earthRadiusKm * 2 * Math.atan2(Math.sqrt(haversine), Math.sqrt(1 - haversine)); }function isGoogleApiKeyConfigured() { return ( GOOGLE_PLACES_API_KEY && GOOGLE_PLACES_API_KEY.indexOf('__TRANSLELES_') !== 0 ); }function loadGooglePlacesLibrary() { if (googlePlacesLibraryPromise) { return googlePlacesLibraryPromise; }googlePlacesLibraryPromise = new Promise(function (resolve, reject) { function importPlacesLibrary(attempt) { if ( !window.google || !window.google.maps || typeof window.google.maps.importLibrary !== 'function' ) { if (attempt < 100) { window.setTimeout(function () { importPlacesLibrary(attempt + 1); }, 50); return; }reject(new Error('Google Maps não foi carregado.')); return; }window.google.maps.importLibrary('places').then(resolve).catch(reject); }if ( window.google && window.google.maps && typeof window.google.maps.importLibrary === 'function' ) { importPlacesLibrary(0); return; }var existingScript = document.getElementById(GOOGLE_SCRIPT_ID);if (existingScript) { importPlacesLibrary(0); existingScript.addEventListener('error', reject, { once: true }); return; }var script = document.createElement('script'); script.id = GOOGLE_SCRIPT_ID; script.async = true; script.defer = true; script.src = 'https://maps.googleapis.com/maps/api/js?key=' + encodeURIComponent(GOOGLE_PLACES_API_KEY) + '&loading=async&libraries=places&v=weekly&language=pt-BR®ion=BR'; script.addEventListener('load', function () { importPlacesLibrary(0); }, { once: true }); script.addEventListener('error', function () { reject(new Error('Não foi possível carregar o Google Places.')); }, { once: true }); document.head.appendChild(script); });return googlePlacesLibraryPromise; }function getAddressComponent(addressComponents, types) { var component = (addressComponents || []).find(function (item) { return types.some(function (type) { return Array.isArray(item.types) && item.types.indexOf(type) !== -1; }); });return component || null; }function placeToLocation(place, predictionText, placeId) { var addressComponents = place.addressComponents || []; var cityComponent = getAddressComponent(addressComponents, [ 'locality', 'administrative_area_level_2', 'sublocality' ]); var stateComponent = getAddressComponent(addressComponents, [ 'administrative_area_level_1' ]); var latitude = place.location && typeof place.location.lat === 'function' ? Number(place.location.lat()) : Number(place.location && place.location.lat); var longitude = place.location && typeof place.location.lng === 'function' ? Number(place.location.lng()) : Number(place.location && place.location.lng); var state = stateComponent ? String(stateComponent.shortText || stateComponent.longText || '') : '';return { googlePlaceId: place.id || placeId || '', name: cityComponent ? String(cityComponent.longText || '') : '', state: state, region: REGIONS_BY_STATE[state] || '', latitude: latitude, longitude: longitude, distanceKm: Number.isFinite(latitude) && Number.isFinite(longitude) ? calculateDistanceKm(latitude, longitude) : NaN, formattedAddress: place.formattedAddress || predictionText || '', source: 'Google Places' }; }function classifyOrigin(municipality, rawValue) { if (!municipality) { return { kind: 'manual', value: String(rawValue || '').trim() ? 'Local específico informado — confirmar cidade e distância manualmente' : 'Origem não classificada — realizar análise manual' }; }if (!Number.isFinite(municipality.distanceKm)) { return { kind: 'manual', value: 'Origem selecionada — confirmar distância manualmente' }; }if (municipality.distanceKm > 300) { return { kind: 'partner', value: 'Origem superior a 300 km — avaliar atendimento por parceiro', title: 'Origem a mais de 300 km da Transleles', message: 'Esta origem fica a mais de 300 km da nossa base, em Luziânia. O deslocamento pode elevar o custo ou inviabilizar o atendimento com frota própria. Envie sua solicitação: nossa equipe avaliará a rota e poderá buscar uma empresa parceira na sua região.' }; }if (municipality.distanceKm >= 250) { return { kind: 'review', value: 'Origem próxima ao limite de 300 km — realizar análise manual', title: 'Origem próxima ao limite de atendimento', message: 'A origem está próxima do limite de 300 km. Nossa equipe confirmará a rota e os custos antes de indicar a melhor forma de atendimento.' }; }return { kind: 'priority', value: 'Origem dentro da área prioritária de atendimento' }; }function ensureOriginNotice(form, input, formIndex) { var fieldGroup = input.closest('.elementor-field-group') || input.parentElement; var destinationInput; var destinationGroup; var wrapper; var row; var notice; var title; var message;if (!fieldGroup) { return null; }notice = form.querySelector('.transleles-origin-notice');if (notice) { return notice; }wrapper = fieldGroup.parentElement;if (!wrapper) { return null; }destinationInput = form.querySelector('[name="form_fields[Destino]"]'); destinationGroup = destinationInput ? destinationInput.closest('.elementor-field-group') : null; row = document.createElement('div'); notice = document.createElement('div'); title = document.createElement('strong'); message = document.createElement('span'); row.className = 'elementor-field-group elementor-column elementor-col-100 transleles-origin-notice-row'; row.hidden = true; notice.id = 'transleles-origin-notice-' + String(formIndex); notice.className = 'transleles-origin-notice'; notice.setAttribute('role', 'status'); notice.setAttribute('aria-live', 'polite'); notice.appendChild(title); notice.appendChild(message); notice.__translelesTitle = title; notice.__translelesMessage = message; notice.__translelesRow = row; row.appendChild(notice); wrapper.insertBefore( row, destinationGroup ? destinationGroup.nextElementSibling : fieldGroup.nextElementSibling ); return notice; }function writeOriginQualification(form, input, municipality, formIndex) { var qualification = classifyOrigin(municipality, input.value); var notice = ensureOriginNotice(form, input, formIndex); var noticeRow = notice ? notice.__translelesRow : null;ensureHiddenField(form, QUALIFICATION_FIELD_NAME).value = qualification.value;if (!notice || !noticeRow) { return; }if (qualification.kind !== 'partner' && qualification.kind !== 'review') { noticeRow.hidden = true; notice.removeAttribute('data-status'); return; }noticeRow.hidden = false; notice.setAttribute('data-status', qualification.kind); notice.__translelesTitle.textContent = qualification.title; notice.__translelesMessage.textContent = qualification.message; }function addHelperText(input, configuration, formIndex) { var fieldGroup = input.closest('.elementor-field-group') || input.parentElement;if (!fieldGroup || fieldGroup.querySelector('.transleles-region-help')) { return; }var helper = document.createElement('small'); var helperId = 'transleles-region-help-' + configuration.key + '-' + String(formIndex); var describedBy = input.getAttribute('aria-describedby') || '';helper.id = helperId; helper.className = 'transleles-region-help'; helper.textContent = 'Comece a digitar e selecione uma cidade, endereço ou local. Também aceitamos texto livre.'; fieldGroup.appendChild(helper); input.setAttribute( 'aria-describedby', (describedBy + ' ' + helperId).trim() ); }function createPlacesInterface(input, configuration, formIndex) { var fieldGroup = input.closest('.elementor-field-group') || input.parentElement; var shell = document.createElement('div'); var dropdown = document.createElement('div'); var results = document.createElement('div'); var attribution = document.createElement('div'); var attributionImage = document.createElement('img'); var listboxId = 'transleles-places-listbox-' + configuration.key + '-' + String(formIndex);shell.className = 'transleles-places-shell'; dropdown.id = listboxId; dropdown.className = 'transleles-places-dropdown'; dropdown.setAttribute('role', 'listbox'); dropdown.hidden = true; results.className = 'transleles-places-results'; attribution.className = 'transleles-places-attribution'; attributionImage.src = GOOGLE_ATTRIBUTION_URL; attributionImage.alt = 'Powered by Google'; attributionImage.width = 120; attributionImage.height = 15; attribution.appendChild(attributionImage); dropdown.appendChild(results); dropdown.appendChild(attribution);if (fieldGroup && input.parentElement) { input.parentElement.insertBefore(shell, input); shell.appendChild(input); shell.appendChild(dropdown); }input.removeAttribute('list'); input.setAttribute('autocomplete', 'off'); input.setAttribute('aria-autocomplete', 'list'); input.setAttribute('aria-controls', listboxId); input.setAttribute('aria-expanded', 'false');return { dropdown: dropdown, results: results, shell: shell, listboxId: listboxId }; }function enableGooglePlaces( form, input, configuration, formIndex, placesLibrary ) { if (input.__translelesGooglePlacesV1) { return; }input.__translelesGooglePlacesV1 = true;var autocompleteSuggestion = placesLibrary.AutocompleteSuggestion; var autocompleteSessionToken = placesLibrary.AutocompleteSessionToken;if (!autocompleteSuggestion || !autocompleteSessionToken) { return; }var interfaceElements = createPlacesInterface( input, configuration, formIndex ); var dropdown = interfaceElements.dropdown; var results = interfaceElements.results; var debounceTimer = null; var requestSequence = 0; var activeIndex = -1; var renderedPredictions = []; var sessionToken = null; var selectedValue = '';function closeDropdown() { dropdown.hidden = true; input.setAttribute('aria-expanded', 'false'); input.removeAttribute('aria-activedescendant'); activeIndex = -1; }function setActiveOption(nextIndex) { var options = results.querySelectorAll('[role="option"]');if (!options.length) { return; }activeIndex = Math.max(0, Math.min(nextIndex, options.length - 1));Array.prototype.forEach.call(options, function (option, optionIndex) { var isActive = optionIndex === activeIndex; option.setAttribute('aria-selected', isActive ? 'true' : 'false'); option.classList.toggle('is-active', isActive); });input.setAttribute('aria-activedescendant', options[activeIndex].id); options[activeIndex].scrollIntoView({ block: 'nearest' }); }function clearResults() { while (results.firstChild) { results.removeChild(results.firstChild); }renderedPredictions = []; closeDropdown(); }function applyGoogleLocation(location) { writeMetadata(form, configuration, location); input.removeAttribute('data-ibge-id'); input.setAttribute('data-location-source', 'google-places');if (location.googlePlaceId) { input.setAttribute('data-google-place-id', location.googlePlaceId); } else { input.removeAttribute('data-google-place-id'); }if (configuration.key === 'origem') { writeOriginQualification(form, input, location, formIndex); } }function selectPrediction(placePrediction) { var predictionText = placePrediction.text ? placePrediction.text.toString() : ''; var placeId = placePrediction.placeId || ''; var place = placePrediction.toPlace(); var selectionRequest = ++requestSequence;input.value = predictionText; selectedValue = predictionText; closeDropdown(); input.setAttribute('aria-busy', 'true');place .fetchFields({ fields: ['formattedAddress', 'location', 'addressComponents'] }) .then(function () { if (selectionRequest !== requestSequence) { return; }applyGoogleLocation( placeToLocation(place, predictionText, placeId) ); }) .catch(function () { if (selectionRequest !== requestSequence) { return; }applyGoogleLocation({ googlePlaceId: placeId, formattedAddress: predictionText, distanceKm: NaN, source: 'Google Places' }); }) .finally(function () { input.removeAttribute('aria-busy'); });sessionToken = null; }function renderPredictions(predictions) { clearResults(); renderedPredictions = predictions.slice(0, GOOGLE_MAX_SUGGESTIONS);renderedPredictions.forEach(function (placePrediction, predictionIndex) { var option = document.createElement('div'); var primary = document.createElement('span'); var secondary = document.createElement('span'); var primaryText = placePrediction.mainText ? placePrediction.mainText.toString() : placePrediction.text.toString(); var secondaryText = placePrediction.secondaryText ? placePrediction.secondaryText.toString() : '';option.id = interfaceElements.listboxId + '-option-' + String(predictionIndex); option.className = 'transleles-places-option'; option.setAttribute('role', 'option'); option.setAttribute('aria-selected', 'false'); primary.className = 'transleles-places-primary'; primary.textContent = primaryText; option.appendChild(primary);if (secondaryText && secondaryText !== primaryText) { secondary.className = 'transleles-places-secondary'; secondary.textContent = secondaryText; option.appendChild(secondary); }option.addEventListener('mousedown', function (event) { event.preventDefault(); selectPrediction(placePrediction); }); option.addEventListener('mouseenter', function () { setActiveOption(predictionIndex); }); results.appendChild(option); });if (!renderedPredictions.length) { return; }dropdown.hidden = false; input.setAttribute('aria-expanded', 'true'); }function requestPredictions() { var query = String(input.value || '').trim(); var normalizedValue = normalizeText(query); var municipality = MUNICIPALITY_BY_VALUE[normalizedValue] || null; var currentRequest = ++requestSequence;if (municipality || query.length < GOOGLE_MIN_QUERY_LENGTH) { clearResults(); return; }if (!sessionToken) { sessionToken = new autocompleteSessionToken(); }input.setAttribute('aria-busy', 'true'); autocompleteSuggestion .fetchAutocompleteSuggestions({ input: query, includedRegionCodes: ['br'], language: 'pt-BR', region: 'br', locationBias: { center: { lat: BASE_LOCATION.latitude, lng: BASE_LOCATION.longitude }, radius: 50000 }, sessionToken: sessionToken }) .then(function (response) { if (currentRequest !== requestSequence) { return; }renderPredictions( (response.suggestions || []) .map(function (suggestion) { return suggestion.placePrediction; }) .filter(Boolean) ); }) .catch(function () { if (currentRequest === requestSequence) { clearResults(); } }) .finally(function () { if (currentRequest === requestSequence) { input.removeAttribute('aria-busy'); } }); }input.addEventListener('input', function () { selectedValue = ''; input.removeAttribute('data-google-place-id'); window.clearTimeout(debounceTimer);if (String(input.value || '').trim().length < GOOGLE_MIN_QUERY_LENGTH) { requestSequence += 1; clearResults(); return; }debounceTimer = window.setTimeout(requestPredictions, GOOGLE_DEBOUNCE_MS); });input.addEventListener('keydown', function (event) { if (dropdown.hidden || !renderedPredictions.length) { return; }if (event.key === 'ArrowDown') { event.preventDefault(); setActiveOption(activeIndex + 1); } else if (event.key === 'ArrowUp') { event.preventDefault(); setActiveOption(activeIndex <= 0 ? renderedPredictions.length - 1 : activeIndex - 1); } else if (event.key === 'Enter' && activeIndex >= 0) { event.preventDefault(); selectPrediction(renderedPredictions[activeIndex]); } else if (event.key === 'Escape') { closeDropdown(); } });input.addEventListener('change', function () { if (selectedValue && input.value === selectedValue) { return; }closeDropdown(); });input.addEventListener('blur', function () { window.setTimeout(closeDropdown, 120); }); }function initializeField(form, input, configuration, formIndex) { if (!input || input.__translelesRegionSearchV1) { return; }input.__translelesRegionSearchV1 = true; input.setAttribute('list', DATALIST_ID); input.setAttribute('autocomplete', 'address-level2'); input.setAttribute('aria-autocomplete', 'list'); input.setAttribute('data-transleles-region-field', configuration.key); input.classList.add('transleles-region-field'); addHelperText(input, configuration, formIndex);function refreshSuggestions() { replaceSuggestions(ensureDatalist(), findMatches(input.value)); }function refreshMetadata() { var municipality = MUNICIPALITY_BY_VALUE[normalizeText(input.value)] || null; writeMetadata(form, configuration, municipality);if (configuration.key === 'origem') { writeOriginQualification(form, input, municipality, formIndex); }if (municipality) { input.setAttribute('data-ibge-id', String(municipality.id)); input.setAttribute('data-location-source', 'ibge'); } else { input.removeAttribute('data-ibge-id'); input.removeAttribute('data-location-source'); } }input.addEventListener('focus', refreshSuggestions); input.addEventListener('input', function () { refreshSuggestions(); refreshMetadata(); }); input.addEventListener('change', refreshMetadata);if (isGoogleApiKeyConfigured()) { loadGooglePlacesLibrary() .then(function (placesLibrary) { enableGooglePlaces( form, input, configuration, formIndex, placesLibrary ); }) .catch(function (error) { input.setAttribute('data-location-search-fallback', 'ibge'); input.setAttribute( 'data-location-search-error', String((error && error.message) || error || 'Erro desconhecido') .replace(GOOGLE_PLACES_API_KEY, '') .slice(0, 180) ); }); } }function initializeForms() { var forms = document.querySelectorAll(FORM_SELECTOR);Array.prototype.forEach.call(forms, function (form, formIndex) { FIELD_CONFIGURATIONS.forEach(function (configuration) { var input = form.querySelector('[name="' + configuration.name + '"]'); initializeField(form, input, configuration, formIndex); }); }); }function start() { if (!MUNICIPALITIES.length || !document.body) { return; }ensureDatalist(); initializeForms();new MutationObserver(initializeForms).observe(document.body, { childList: true, subtree: true }); }if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', start, { once: true }); } else { start(); } })(); latitude: -16.2535991668701, longitude: -47.9500007629395 }; var googlePlacesLibraryPromise = null; var QUALIFICATION_FIELD_NAME = 'form_fields[qualificacao_origem]'; var FIELD_CONFIGURATIONS = [ { name: 'form_fields[Origem]', key: 'origem', label: 'Origem' }, { name: 'form_fields[Destino]', key: 'destino', label: 'Destino' }, { name: 'form_fields[endereco]', key: 'endereco', label: 'Localização do atendimento' } ]; var REGIONS_BY_STATE = { AC: 'Norte', AL: 'Nordeste', AM: 'Norte', AP: 'Norte', BA: 'Nordeste', CE: 'Nordeste', DF: 'Centro-Oeste', ES: 'Sudeste', GO: 'Centro-Oeste', MA: 'Nordeste', MG: 'Sudeste', MS: 'Centro-Oeste', MT: 'Centro-Oeste', PA: 'Norte', PB: 'Nordeste', PE: 'Nordeste', PI: 'Nordeste', PR: 'Sul', RJ: 'Sudeste', RN: 'Nordeste', RO: 'Norte', RR: 'Norte', RS: 'Sul', SC: 'Sul', SE: 'Nordeste', SP: 'Sudeste', TO: 'Norte' };function normalizeText(value) { var text = String(value || '').toLowerCase().trim();if (typeof text.normalize === 'function') { text = text.normalize('NFD').replace(/[\u0300-\u036f]/g, ''); }return text.replace(/[–—-]/g, ' ').replace(/\s+/g, ' '); }var SEARCHABLE_MUNICIPALITIES = MUNICIPALITIES.map(function (municipality) { var name = municipality[0]; var state = municipality[1]; var id = municipality[2]; var distanceKm = Number(municipality[3]); var value = name + ' — ' + state;return { id: id, name: name, state: state, distanceKm: distanceKm, region: REGIONS_BY_STATE[state] || '', source: 'IBGE', value: value, normalizedName: normalizeText(name), searchKey: normalizeText(name + ' ' + state) }; }); var MUNICIPALITY_BY_VALUE = {};SEARCHABLE_MUNICIPALITIES.forEach(function (municipality) { MUNICIPALITY_BY_VALUE[normalizeText(municipality.value)] = municipality; });function findMatches(query) { var normalizedQuery = normalizeText(query);if (normalizedQuery.length < MIN_QUERY_LENGTH) { return []; }var tokens = normalizedQuery.split(' ');return SEARCHABLE_MUNICIPALITIES.filter(function (municipality) { return tokens.every(function (token) { return municipality.searchKey.indexOf(token) !== -1; }); }) .sort(function (left, right) { var leftScore = left.normalizedName.indexOf(normalizedQuery) === 0 ? 0 : 1; var rightScore = right.normalizedName.indexOf(normalizedQuery) === 0 ? 0 : 1;if (leftScore !== rightScore) { return leftScore - rightScore; }return left.value.localeCompare(right.value, 'pt-BR'); }) .slice(0, MAX_SUGGESTIONS); }function ensureDatalist() { var datalist = document.getElementById(DATALIST_ID);if (datalist) { return datalist; }datalist = document.createElement('datalist'); datalist.id = DATALIST_ID; document.body.appendChild(datalist); return datalist; }function replaceSuggestions(datalist, matches) { while (datalist.firstChild) { datalist.removeChild(datalist.firstChild); }matches.forEach(function (municipality) { var option = document.createElement('option'); option.value = municipality.value; option.label = municipality.name + ', ' + municipality.state; datalist.appendChild(option); }); }function ensureHiddenField(form, name) { var field = form.querySelector('[name="' + name + '"]');if (field) { return field; }field = document.createElement('input'); field.type = 'hidden'; field.name = name; form.appendChild(field); return field; }function writeMetadata(form, configuration, location) { var prefix = 'form_fields[' + configuration.key; var values = { '_ibge_id]': location && location.id ? String(location.id) : '', '_cidade]': location && location.name ? location.name : '', '_uf]': location && location.state ? location.state : '', '_regiao]': location && location.region ? location.region : '', '_google_place_id]': location && location.googlePlaceId ? location.googlePlaceId : '', '_latitude]': location && Number.isFinite(location.latitude) ? String(location.latitude) : '', '_longitude]': location && Number.isFinite(location.longitude) ? String(location.longitude) : '', '_endereco_formatado]': location && location.formattedAddress ? location.formattedAddress : '', '_distancia_base_km]': location && Number.isFinite(location.distanceKm) ? String(Math.round(location.distanceKm)) : '', '_fonte]': location && location.source ? location.source : '' };Object.keys(values).forEach(function (suffix) { ensureHiddenField(form, prefix + suffix).value = values[suffix]; }); }function calculateDistanceKm(latitude, longitude) { var earthRadiusKm = 6371; var toRadians = Math.PI / 180; var latitudeDelta = (latitude - BASE_LOCATION.latitude) * toRadians; var longitudeDelta = (longitude - BASE_LOCATION.longitude) * toRadians; var startLatitude = BASE_LOCATION.latitude * toRadians; var endLatitude = latitude * toRadians; var haversine = Math.sin(latitudeDelta / 2) * Math.sin(latitudeDelta / 2) + Math.cos(startLatitude) * Math.cos(endLatitude) * Math.sin(longitudeDelta / 2) * Math.sin(longitudeDelta / 2);return earthRadiusKm * 2 * Math.atan2(Math.sqrt(haversine), Math.sqrt(1 - haversine)); }function isGoogleApiKeyConfigured() { return ( GOOGLE_PLACES_API_KEY && GOOGLE_PLACES_API_KEY.indexOf('__TRANSLELES_') !== 0 ); }function loadGooglePlacesLibrary() { if (googlePlacesLibraryPromise) { return googlePlacesLibraryPromise; }googlePlacesLibraryPromise = new Promise(function (resolve, reject) { function importPlacesLibrary(attempt) { if ( !window.google || !window.google.maps || typeof window.google.maps.importLibrary !== 'function' ) { if (attempt < 100) { window.setTimeout(function () { importPlacesLibrary(attempt + 1); }, 50); return; }reject(new Error('Google Maps não foi carregado.')); return; }window.google.maps.importLibrary('places').then(resolve).catch(reject); }if ( window.google && window.google.maps && typeof window.google.maps.importLibrary === 'function' ) { importPlacesLibrary(0); return; }var existingScript = document.getElementById(GOOGLE_SCRIPT_ID);if (existingScript) { importPlacesLibrary(0); existingScript.addEventListener('error', reject, { once: true }); return; }var script = document.createElement('script'); script.id = GOOGLE_SCRIPT_ID; script.async = true; script.defer = true; script.src = 'https://maps.googleapis.com/maps/api/js?key=' + encodeURIComponent(GOOGLE_PLACES_API_KEY) + '&loading=async&libraries=places&v=weekly&language=pt-BR®ion=BR'; script.addEventListener('load', function () { importPlacesLibrary(0); }, { once: true }); script.addEventListener('error', function () { reject(new Error('Não foi possível carregar o Google Places.')); }, { once: true }); document.head.appendChild(script); });return googlePlacesLibraryPromise; }function getAddressComponent(addressComponents, types) { var component = (addressComponents || []).find(function (item) { return types.some(function (type) { return Array.isArray(item.types) && item.types.indexOf(type) !== -1; }); });return component || null; }function placeToLocation(place, predictionText, placeId) { var addressComponents = place.addressComponents || []; var cityComponent = getAddressComponent(addressComponents, [ 'locality', 'administrative_area_level_2', 'sublocality' ]); var stateComponent = getAddressComponent(addressComponents, [ 'administrative_area_level_1' ]); var latitude = place.location && typeof place.location.lat === 'function' ? Number(place.location.lat()) : Number(place.location && place.location.lat); var longitude = place.location && typeof place.location.lng === 'function' ? Number(place.location.lng()) : Number(place.location && place.location.lng); var state = stateComponent ? String(stateComponent.shortText || stateComponent.longText || '') : '';return { googlePlaceId: place.id || placeId || '', name: cityComponent ? String(cityComponent.longText || '') : '', state: state, region: REGIONS_BY_STATE[state] || '', latitude: latitude, longitude: longitude, distanceKm: Number.isFinite(latitude) && Number.isFinite(longitude) ? calculateDistanceKm(latitude, longitude) : NaN, formattedAddress: place.formattedAddress || predictionText || '', source: 'Google Places' }; }function classifyOrigin(municipality, rawValue) { if (!municipality) { return { kind: 'manual', value: String(rawValue || '').trim() ? 'Local específico informado — confirmar cidade e distância manualmente' : 'Origem não classificada — realizar análise manual' }; }if (!Number.isFinite(municipality.distanceKm)) { return { kind: 'manual', value: 'Origem selecionada — confirmar distância manualmente' }; }if (municipality.distanceKm > 300) { return { kind: 'partner', value: 'Origem superior a 300 km — avaliar atendimento por parceiro', title: 'Origem a mais de 300 km da Transleles', message: 'Esta origem fica a mais de 300 km da nossa base, em Luziânia. O deslocamento pode elevar o custo ou inviabilizar o atendimento com frota própria. Envie sua solicitação: nossa equipe avaliará a rota e poderá buscar uma empresa parceira na sua região.' }; }if (municipality.distanceKm >= 250) { return { kind: 'review', value: 'Origem próxima ao limite de 300 km — realizar análise manual', title: 'Origem próxima ao limite de atendimento', message: 'A origem está próxima do limite de 300 km. Nossa equipe confirmará a rota e os custos antes de indicar a melhor forma de atendimento.' }; }return { kind: 'priority', value: 'Origem dentro da área prioritária de atendimento' }; }function ensureOriginNotice(form, input, formIndex) { var fieldGroup = input.closest('.elementor-field-group') || input.parentElement; var destinationInput; var destinationGroup; var wrapper; var row; var notice; var title; var message;if (!fieldGroup) { return null; }notice = form.querySelector('.transleles-origin-notice');if (notice) { return notice; }wrapper = fieldGroup.parentElement;if (!wrapper) { return null; }destinationInput = form.querySelector('[name="form_fields[Destino]"]'); destinationGroup = destinationInput ? destinationInput.closest('.elementor-field-group') : null; row = document.createElement('div'); notice = document.createElement('div'); title = document.createElement('strong'); message = document.createElement('span'); row.className = 'elementor-field-group elementor-column elementor-col-100 transleles-origin-notice-row'; row.hidden = true; notice.id = 'transleles-origin-notice-' + String(formIndex); notice.className = 'transleles-origin-notice'; notice.setAttribute('role', 'status'); notice.setAttribute('aria-live', 'polite'); notice.appendChild(title); notice.appendChild(message); notice.__translelesTitle = title; notice.__translelesMessage = message; notice.__translelesRow = row; row.appendChild(notice); wrapper.insertBefore( row, destinationGroup ? destinationGroup.nextElementSibling : fieldGroup.nextElementSibling ); return notice; }function writeOriginQualification(form, input, municipality, formIndex) { var qualification = classifyOrigin(municipality, input.value); var notice = ensureOriginNotice(form, input, formIndex); var noticeRow = notice ? notice.__translelesRow : null;ensureHiddenField(form, QUALIFICATION_FIELD_NAME).value = qualification.value;if (!notice || !noticeRow) { return; }if (qualification.kind !== 'partner' && qualification.kind !== 'review') { noticeRow.hidden = true; notice.removeAttribute('data-status'); return; }noticeRow.hidden = false; notice.setAttribute('data-status', qualification.kind); notice.__translelesTitle.textContent = qualification.title; notice.__translelesMessage.textContent = qualification.message; }function addHelperText(input, configuration, formIndex) { var fieldGroup = input.closest('.elementor-field-group') || input.parentElement;if (!fieldGroup || fieldGroup.querySelector('.transleles-region-help')) { return; }var helper = document.createElement('small'); var helperId = 'transleles-region-help-' + configuration.key + '-' + String(formIndex); var describedBy = input.getAttribute('aria-describedby') || '';helper.id = helperId; helper.className = 'transleles-region-help'; helper.textContent = 'Comece a digitar e selecione uma cidade, endereço ou local. Também aceitamos texto livre.'; fieldGroup.appendChild(helper); input.setAttribute( 'aria-describedby', (describedBy + ' ' + helperId).trim() ); }function createPlacesInterface(input, configuration, formIndex) { var fieldGroup = input.closest('.elementor-field-group') || input.parentElement; var shell = document.createElement('div'); var dropdown = document.createElement('div'); var results = document.createElement('div'); var attribution = document.createElement('div'); var attributionImage = document.createElement('img'); var listboxId = 'transleles-places-listbox-' + configuration.key + '-' + String(formIndex);shell.className = 'transleles-places-shell'; dropdown.id = listboxId; dropdown.className = 'transleles-places-dropdown'; dropdown.setAttribute('role', 'listbox'); dropdown.hidden = true; results.className = 'transleles-places-results'; attribution.className = 'transleles-places-attribution'; attributionImage.src = GOOGLE_ATTRIBUTION_URL; attributionImage.alt = 'Powered by Google'; attributionImage.width = 120; attributionImage.height = 15; attribution.appendChild(attributionImage); dropdown.appendChild(results); dropdown.appendChild(attribution);if (fieldGroup && input.parentElement) { input.parentElement.insertBefore(shell, input); shell.appendChild(input); shell.appendChild(dropdown); }input.removeAttribute('list'); input.setAttribute('autocomplete', 'off'); input.setAttribute('aria-autocomplete', 'list'); input.setAttribute('aria-controls', listboxId); input.setAttribute('aria-expanded', 'false');return { dropdown: dropdown, results: results, shell: shell, listboxId: listboxId }; }function enableGooglePlaces( form, input, configuration, formIndex, placesLibrary ) { if (input.__translelesGooglePlacesV1) { return; }input.__translelesGooglePlacesV1 = true;var autocompleteSuggestion = placesLibrary.AutocompleteSuggestion; var autocompleteSessionToken = placesLibrary.AutocompleteSessionToken;if (!autocompleteSuggestion || !autocompleteSessionToken) { return; }var interfaceElements = createPlacesInterface( input, configuration, formIndex ); var dropdown = interfaceElements.dropdown; var results = interfaceElements.results; var debounceTimer = null; var requestSequence = 0; var activeIndex = -1; var renderedPredictions = []; var sessionToken = null; var selectedValue = '';function closeDropdown() { dropdown.hidden = true; input.setAttribute('aria-expanded', 'false'); input.removeAttribute('aria-activedescendant'); activeIndex = -1; }function setActiveOption(nextIndex) { var options = results.querySelectorAll('[role="option"]');if (!options.length) { return; }activeIndex = Math.max(0, Math.min(nextIndex, options.length - 1));Array.prototype.forEach.call(options, function (option, optionIndex) { var isActive = optionIndex === activeIndex; option.setAttribute('aria-selected', isActive ? 'true' : 'false'); option.classList.toggle('is-active', isActive); });input.setAttribute('aria-activedescendant', options[activeIndex].id); options[activeIndex].scrollIntoView({ block: 'nearest' }); }function clearResults() { while (results.firstChild) { results.removeChild(results.firstChild); }renderedPredictions = []; closeDropdown(); }function applyGoogleLocation(location) { writeMetadata(form, configuration, location); input.removeAttribute('data-ibge-id'); input.setAttribute('data-location-source', 'google-places');if (location.googlePlaceId) { input.setAttribute('data-google-place-id', location.googlePlaceId); } else { input.removeAttribute('data-google-place-id'); }if (configuration.key === 'origem') { writeOriginQualification(form, input, location, formIndex); } }function selectPrediction(placePrediction) { var predictionText = placePrediction.text ? placePrediction.text.toString() : ''; var placeId = placePrediction.placeId || ''; var place = placePrediction.toPlace(); var selectionRequest = ++requestSequence;input.value = predictionText; selectedValue = predictionText; closeDropdown(); input.setAttribute('aria-busy', 'true');place .fetchFields({ fields: ['formattedAddress', 'location', 'addressComponents'] }) .then(function () { if (selectionRequest !== requestSequence) { return; }applyGoogleLocation( placeToLocation(place, predictionText, placeId) ); }) .catch(function () { if (selectionRequest !== requestSequence) { return; }applyGoogleLocation({ googlePlaceId: placeId, formattedAddress: predictionText, distanceKm: NaN, source: 'Google Places' }); }) .finally(function () { input.removeAttribute('aria-busy'); });sessionToken = null; }function renderPredictions(predictions) { clearResults(); renderedPredictions = predictions.slice(0, GOOGLE_MAX_SUGGESTIONS);renderedPredictions.forEach(function (placePrediction, predictionIndex) { var option = document.createElement('div'); var primary = document.createElement('span'); var secondary = document.createElement('span'); var primaryText = placePrediction.mainText ? placePrediction.mainText.toString() : placePrediction.text.toString(); var secondaryText = placePrediction.secondaryText ? placePrediction.secondaryText.toString() : '';option.id = interfaceElements.listboxId + '-option-' + String(predictionIndex); option.className = 'transleles-places-option'; option.setAttribute('role', 'option'); option.setAttribute('aria-selected', 'false'); primary.className = 'transleles-places-primary'; primary.textContent = primaryText; option.appendChild(primary);if (secondaryText && secondaryText !== primaryText) { secondary.className = 'transleles-places-secondary'; secondary.textContent = secondaryText; option.appendChild(secondary); }option.addEventListener('mousedown', function (event) { event.preventDefault(); selectPrediction(placePrediction); }); option.addEventListener('mouseenter', function () { setActiveOption(predictionIndex); }); results.appendChild(option); });if (!renderedPredictions.length) { return; }dropdown.hidden = false; input.setAttribute('aria-expanded', 'true'); }function requestPredictions() { var query = String(input.value || '').trim(); var normalizedValue = normalizeText(query); var municipality = MUNICIPALITY_BY_VALUE[normalizedValue] || null; var currentRequest = ++requestSequence;if (municipality || query.length < GOOGLE_MIN_QUERY_LENGTH) { clearResults(); return; }if (!sessionToken) { sessionToken = new autocompleteSessionToken(); }input.setAttribute('aria-busy', 'true'); autocompleteSuggestion .fetchAutocompleteSuggestions({ input: query, includedRegionCodes: ['br'], language: 'pt-BR', region: 'br', locationBias: { center: { lat: BASE_LOCATION.latitude, lng: BASE_LOCATION.longitude }, radius: 50000 }, sessionToken: sessionToken }) .then(function (response) { if (currentRequest !== requestSequence) { return; }renderPredictions( (response.suggestions || []) .map(function (suggestion) { return suggestion.placePrediction; }) .filter(Boolean) ); }) .catch(function () { if (currentRequest === requestSequence) { clearResults(); } }) .finally(function () { if (currentRequest === requestSequence) { input.removeAttribute('aria-busy'); } }); }input.addEventListener('input', function () { selectedValue = ''; input.removeAttribute('data-google-place-id'); window.clearTimeout(debounceTimer);if (String(input.value || '').trim().length < GOOGLE_MIN_QUERY_LENGTH) { requestSequence += 1; clearResults(); return; }debounceTimer = window.setTimeout(requestPredictions, GOOGLE_DEBOUNCE_MS); });input.addEventListener('keydown', function (event) { if (dropdown.hidden || !renderedPredictions.length) { return; }if (event.key === 'ArrowDown') { event.preventDefault(); setActiveOption(activeIndex + 1); } else if (event.key === 'ArrowUp') { event.preventDefault(); setActiveOption(activeIndex <= 0 ? renderedPredictions.length - 1 : activeIndex - 1); } else if (event.key === 'Enter' && activeIndex >= 0) { event.preventDefault(); selectPrediction(renderedPredictions[activeIndex]); } else if (event.key === 'Escape') { closeDropdown(); } });input.addEventListener('change', function () { if (selectedValue && input.value === selectedValue) { return; }closeDropdown(); });input.addEventListener('blur', function () { window.setTimeout(closeDropdown, 120); }); }function initializeField(form, input, configuration, formIndex) { if (!input || input.__translelesRegionSearchV1) { return; }input.__translelesRegionSearchV1 = true; input.setAttribute('list', DATALIST_ID); input.setAttribute('autocomplete', 'address-level2'); input.setAttribute('aria-autocomplete', 'list'); input.setAttribute('data-transleles-region-field', configuration.key); input.classList.add('transleles-region-field'); addHelperText(input, configuration, formIndex);function refreshSuggestions() { replaceSuggestions(ensureDatalist(), findMatches(input.value)); }function refreshMetadata() { var municipality = MUNICIPALITY_BY_VALUE[normalizeText(input.value)] || null; writeMetadata(form, configuration, municipality);if (configuration.key === 'origem') { writeOriginQualification(form, input, municipality, formIndex); }if (municipality) { input.setAttribute('data-ibge-id', String(municipality.id)); input.setAttribute('data-location-source', 'ibge'); } else { input.removeAttribute('data-ibge-id'); input.removeAttribute('data-location-source'); } }input.addEventListener('focus', refreshSuggestions); input.addEventListener('input', function () { refreshSuggestions(); refreshMetadata(); }); input.addEventListener('change', refreshMetadata);if (isGoogleApiKeyConfigured()) { loadGooglePlacesLibrary() .then(function (placesLibrary) { enableGooglePlaces( form, input, configuration, formIndex, placesLibrary ); }) .catch(function (error) { input.setAttribute('data-location-search-fallback', 'ibge'); input.setAttribute( 'data-location-search-error', String((error && error.message) || error || 'Erro desconhecido') .replace(GOOGLE_PLACES_API_KEY, '') .slice(0, 180) ); }); } }function initializeForms() { var forms = document.querySelectorAll(FORM_SELECTOR);Array.prototype.forEach.call(forms, function (form, formIndex) { FIELD_CONFIGURATIONS.forEach(function (configuration) { var input = form.querySelector('[name="' + configuration.name + '"]'); initializeField(form, input, configuration, formIndex); }); }); }function start() { if (!MUNICIPALITIES.length || !document.body) { return; }ensureDatalist(); initializeForms();new MutationObserver(initializeForms).observe(document.body, { childList: true, subtree: true }); }if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', start, { once: true }); } else { start(); } })();