// Use bootstrap mixin for transition .transition-all() { .transition('all 0.3s ease-in-out'); } // Condition select if @color is a color // This mixin will do nothing if @color is not a color (like false or etc) .if_color (@color, @property, @value) when (iscolor(@color)) { @{property}: @value !important; } //Content .vc_grid { &.vc_row { padding-left: 0; padding-right: 0; margin-left: 0; margin-right: 0; } } .vc-row[data-vc-full-width] { .vc_grid.vc_row { overflow: hidden; } } @import "vc_grid_gap.less"; @import "../../params/vc_grid_item/vc_grid_item.less"; @import "vc_grid_style.less"; @import "vc_grid_loading.less"; // Import all other extensions @import "vc_grid_filter.less"; @import "vc_grid_carousel.less"; /** * API utilities - unified fetch wrapper and block-state loader * * Reads (from existing globals): * SFE.ManagerData.restUrl - REST base URL * SFE.ManagerData.nonce - WP nonce * SFE.ManagerData.postId - current post ID * SFE.ListBlockTracker * SFE.Context.activeEditor - live reference via getter * * Exposes: SFE.Api * { * apiCall, * hydrateEditorBlockStateOnOpen, * fetchBlockAttributes, * resolveMediaAttributes, * queueResolvedMediaAttributes, * ensureResolvedMediaAttributes * } */ (function() { 'use strict'; window.MWP = window.MWP || {}; window.MWP.SFE = window.MWP.SFE || {}; const SFE = window.MWP.SFE; SFE.ManagerData = SFE.ManagerData || {}; /** * Unified API call handler with consistent error handling */ async function apiCall(endpoint, data, button = null) { const restBase = (SFE.ManagerData.restUrl || '').replace(/\/$/, ''); const path = endpoint.startsWith('/') ? endpoint : '/' + endpoint; const originalText = button?.textContent; const wasDisabled = button?.disabled; if (button) { button.disabled = true; button.setAttribute('mwp-sfe-btn-loading', 'true'); } try { const response = await fetch(restBase + path, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': SFE.ManagerData.nonce }, body: JSON.stringify(data) }); const result = await response.json(); if (!response.ok) { const error = new Error(result?.error || `HTTP ${response.status}: ${response.statusText}`); error.payload = result; throw error; } // Check for error in response if (result.success === false || result.error) { const error = new Error(result.error || 'Operation failed'); error.payload = result; throw error; } return result; } catch (error) { // Reset button state on error if (button) { button.disabled = wasDisabled || false; button.removeAttribute('mwp-sfe-btn-loading'); if (originalText) button.textContent = originalText; } throw error; } } function resolveBlockStateOverride(editorState) { const publicApiBridge = SFE.PublicApiBridge || null; const editorUuid = String(editorState?.uuid || '').trim(); if ( publicApiBridge && editorUuid && publicApiBridge.stagedBlockStates instanceof Map && publicApiBridge.stagedBlockStates.has(editorUuid) ) { const stagedEntry = publicApiBridge.stagedBlockStates.get(editorUuid) || null; publicApiBridge.stagedBlockStates.delete(editorUuid); if (stagedEntry && stagedEntry.blockState) { return publicApiBridge.clonePlainData(stagedEntry.blockState); } } if (typeof SFE.ResolveBlockState === 'function') { try { const resolved = SFE.ResolveBlockState(editorState); if (resolved) return resolved; } catch (error) { console.warn('FrontEdit: block-state resolver hook failed', error); } } const batchManager = SFE.BatchEditManager || null; if ( editorState?.saveStrategy === 'batch' && batchManager && typeof batchManager.isSessionActive === 'function' && batchManager.isSessionActive() && typeof batchManager.getBlockStateForUuid === 'function' ) { return batchManager.getBlockStateForUuid(editorState.uuid); } return null; } function resolveMediaSourceFromAttributes(editorState, blockState) { const schemaRuntime = SFE.SchemaRuntime || null; if (!schemaRuntime || typeof schemaRuntime.resolveInitialMediaSource !== 'function') { return ''; } const resolved = schemaRuntime.resolveInitialMediaSource(editorState, blockState); if (typeof resolved === 'string' && resolved.trim()) { return resolved; } return ''; } function shouldInitListTracker(editorState, blockState) { const tagName = editorState?.element?.tagName || ''; const isListElement = tagName === 'OL' || tagName === 'UL'; if (!isListElement) return false; const schemaRuntime = SFE.SchemaRuntime || null; const hasSchemaListBinding = ( schemaRuntime && typeof schemaRuntime.hasListBinding === 'function' && schemaRuntime.hasListBinding(editorState) ); return hasSchemaListBinding || blockState?.blockName === 'core/list'; } /** * Resolve canonical attachment attributes for the current editor state. * * This lets schema-driven media saves preserve block-level intent such as an * existing `sizeSlug` on `core/image` while a new attachment is selected from * the frontend editor. * * @param {object} editorState Current editor state. * @param {object} [options] * @param {string} [options.expectedResolutionKey] Stable selection key that * must still match before the * resolved payload is applied. * @returns {Promise} Resolved media change patch, or null when no resolution is needed. */ async function resolveMediaAttributes(editorState, options = {}) { const rootElement = editorState?.element || null; const mediaChanges = rootElement?._mwpMediaChanges; if (!mediaChanges || typeof mediaChanges !== 'object') return null; const expectedResolutionKey = typeof options.expectedResolutionKey === 'string' ? options.expectedResolutionKey : ''; const attachmentId = mediaChanges.id ?? null; if (!attachmentId) return null; const blockAttrs = editorState?.blockState?.attrs; if (!blockAttrs || typeof blockAttrs !== 'object') return null; const sizeSlug = typeof blockAttrs.sizeSlug === 'string' ? blockAttrs.sizeSlug.trim() : ''; const response = await apiCall('/resolve-media-attributes', { post_id: SFE.ManagerData.postId, attachment_id: attachmentId, size_slug: sizeSlug }); if (!response || response.success === false || !response.url) { return null; } const nextChanges = { ...mediaChanges, url: response.url, resolvedUrl: response.url, resolvedWidth: Number.isFinite(response.width) ? response.width : null, resolvedHeight:Number.isFinite(response.height) ? response.height : null, }; if (rootElement) { const currentResolutionKey = buildMediaResolutionKey(rootElement._mwpMediaChanges); if (expectedResolutionKey && currentResolutionKey !== expectedResolutionKey) { return null; } rootElement._mwpMediaChanges = nextChanges; } return nextChanges; } /** * Build one stable identity key for the current pending media selection. * * Media replacement can change again before async attribute resolution * finishes. This key lets the shared save/runtime layer ignore late results * from an older selection instead of overwriting the current canonical media * state with stale data. * * @param {object|null} mediaChanges Current media change payload. * @returns {string} Stable resolution key, or an empty string when invalid. */ function buildMediaResolutionKey(mediaChanges) { if (!mediaChanges || typeof mediaChanges !== 'object') { return ''; } const attachmentId = mediaChanges.id ?? ''; const url = typeof mediaChanges.url === 'string' ? mediaChanges.url.trim() : ''; return `${attachmentId}::${url}`; } /** * Queue shared media resolution and cache the in-flight promise on the element. * * @param {object} editorState Current editor state. * @param {object} [options] * @param {HTMLElement|null} [options.mediaElement] * @param {function|null} [options.syncRootChanges] * @returns {Promise} */ function queueResolvedMediaAttributes(editorState, options = {}) { if (!editorState?.element) { return Promise.resolve(null); } const rootElement = editorState.element; const requestedChanges = ( rootElement._mwpMediaChanges && typeof rootElement._mwpMediaChanges === 'object' ) ? { ...rootElement._mwpMediaChanges } : null; const requestedResolutionKey = buildMediaResolutionKey(requestedChanges); const existingPromise = rootElement._mwpResolvedMediaPromise; if ( existingPromise && typeof existingPromise.then === 'function' && rootElement._mwpResolvedMediaKey === requestedResolutionKey ) { return existingPromise; } const mediaElement = options.mediaElement || null; const syncRootChanges = typeof options.syncRootChanges === 'function' ? options.syncRootChanges : null; const pending = Promise.resolve() .then(() => { const currentChanges = rootElement._mwpMediaChanges; if ( !currentChanges || buildMediaResolutionKey(currentChanges) !== requestedResolutionKey ) { return null; } return resolveMediaAttributes(editorState, { expectedResolutionKey: requestedResolutionKey }); }) .then((nextChanges) => { const currentChanges = rootElement._mwpMediaChanges; if ( !nextChanges || !currentChanges || buildMediaResolutionKey(currentChanges) !== requestedResolutionKey ) { return null; } if (nextChanges && mediaElement) { mediaElement._mwpMediaChanges = { ...nextChanges }; } if (syncRootChanges) { syncRootChanges(nextChanges); } return nextChanges; }); rootElement._mwpResolvedMediaKey = requestedResolutionKey; rootElement._mwpResolvedMediaPromise = pending.finally(() => { if (rootElement._mwpResolvedMediaPromise === pending) { delete rootElement._mwpResolvedMediaPromise; delete rootElement._mwpResolvedMediaKey; } }); return rootElement._mwpResolvedMediaPromise; } /** * Ensure resolved media attributes are settled before serialization/capture. * * @param {object} editorState Current editor state. * @returns {Promise} */ async function ensureResolvedMediaAttributes(editorState) { const pending = editorState?.element?._mwpResolvedMediaPromise; if (pending && typeof pending.then === 'function') { return pending; } const resolutionKey = buildMediaResolutionKey(editorState?.element?._mwpMediaChanges || null); return resolveMediaAttributes(editorState, { expectedResolutionKey: resolutionKey }); } /** * Shared editor-open hydration hook. * * Every editor entry path (text, mixed, media, container) should call this once * immediately after SFE.Context.activeEditor is assigned. It marks the editor as * having requested attrs and runs the shared block-state hydration pipeline. * * In free mode this results in per-block /get-block-state hydration on each open. * In batch mode this first calls ensureSession() so the full block tree is * loaded once, then resolves the active block from the batch cache. * * @param {object} editorState Current editor state. * @returns {void} */ function hydrateEditorBlockStateOnOpen(editorState) { if (!editorState || editorState._mwpBlockAttrsRequested) { return; } editorState._mwpBlockAttrsRequested = true; fetchBlockAttributes(editorState).catch((error) => { console.warn('FrontEdit: failed to hydrate editor block state on open', error); }); } /** * Fetch block attributes in background and update editorState * Disables primary button until loaded */ async function fetchBlockAttributes(editorState) { const postId = SFE.ManagerData.postId; const ListBlockTracker = SFE.ListBlockTracker; const { uuid, actionsContainer } = editorState; const batchManager = SFE.BatchEditManager || null; const getLivePrimaryButton = () => ( actionsContainer ? actionsContainer.querySelector('.mwp-sfe-btn-primary-inline') : null ); const initialPrimaryBtn = getLivePrimaryButton(); /** * Return the initial and current primary buttons (deduped) so loading state * can be removed even if the action bar swapped UIs during attr fetch. * * @return {HTMLElement[]} */ const getTrackedPrimaryButtons = () => { const buttons = []; if (initialPrimaryBtn) buttons.push(initialPrimaryBtn); const livePrimaryBtn = getLivePrimaryButton(); if (livePrimaryBtn && livePrimaryBtn !== initialPrimaryBtn) { buttons.push(livePrimaryBtn); } return buttons; }; /** * Remove loading attributes from tracked primary buttons and restore * disabled state based on button type. * * @param {string|null} originalBtnText Original text from the initial primary button. * @return {void} */ const clearPrimaryLoadingState = (originalBtnText = null) => { const tracked = getTrackedPrimaryButtons(); tracked.forEach((btn) => { if (!btn || !btn.hasAttribute('data-loading-attrs')) return; btn.removeAttribute('data-loading-attrs'); btn.removeAttribute('mwp-sfe-btn-loading'); if (btn === initialPrimaryBtn && originalBtnText !== null) { btn.textContent = originalBtnText; } if (btn.hasAttribute('data-url-gated')) { const editorWrap = btn.closest('.mwp-sfe-inline-media-editor'); const input = editorWrap ? editorWrap.querySelector('#mwp-sfe-media-upload') : null; const value = input && typeof input.value === 'string' ? input.value : ''; btn.disabled = !value.trim(); return; } btn.disabled = false; }); }; const disableSaveButton = (msg) => { const primaryBtn = getLivePrimaryButton() || initialPrimaryBtn; if (primaryBtn) { primaryBtn.removeAttribute('data-loading-attrs'); primaryBtn.removeAttribute('mwp-sfe-btn-loading'); primaryBtn.disabled = true; primaryBtn.textContent = 'Error'; primaryBtn.title = msg; primaryBtn.style.background = '#dc3232'; primaryBtn.style.borderColor = '#dc3232'; primaryBtn.style.cursor = 'not-allowed'; } }; const applyBlockState = (blockState, originalBtnText = null) => { if (SFE.Context.activeEditor !== editorState) return; editorState.originalAttributes = blockState.attrs || {}; editorState.blockName = blockState.blockName || ''; editorState.originalHTML = blockState.html || ''; if (editorState.isMediaEditor && !editorState._originalSrcResolved) { const srcFromAttrs = resolveMediaSourceFromAttributes(editorState, blockState); editorState.originalContent = srcFromAttrs; editorState.originalSrc = srcFromAttrs; editorState._originalSrcResolved = true; } editorState.blockState = blockState; const schemaRuntime = SFE.SchemaRuntime || null; if ( editorState._mwpSchemaRuntime && schemaRuntime && typeof schemaRuntime.refreshEditorState === 'function' ) { schemaRuntime.refreshEditorState(editorState, { blockState, attributeChanges: editorState.attributeChanges || null, }); if ( Array.isArray(editorState.editableComponents) && SFE.TextEditor && typeof SFE.TextEditor.refreshEditableComponents === 'function' ) { SFE.TextEditor.refreshEditableComponents(editorState); } } if (shouldInitListTracker(editorState, blockState)) { editorState.listTracker = ListBlockTracker.init(editorState.element, blockState); } clearPrimaryLoadingState(originalBtnText); if ( editorState?.saveStrategy === 'batch' && batchManager && typeof batchManager._captureEditorOpenBaseline === 'function' ) { batchManager._captureEditorOpenBaseline(editorState); } }; // If we're editing a draft, skip the server fetch entirely. // The draft element is already in the DOM with the correct content, // and its serialized block markup is stored in draftEditState.draftRawContent. // Fetching /get-block-state would return the published version, which has // different attributes (e.g. text alignment) and would silently revert them on save. const draftEditState = SFE.Context.draftEditState; if (draftEditState && draftEditState.draftRawContent && draftEditState.draftElement === editorState.element) { const rawContent = draftEditState.draftRawContent; let parsedBlock; try { [ parsedBlock ] = wp.blocks.parse( rawContent ); } catch (e) { disableSaveButton('Cannot save: Draft block data failed to parse'); return; } if (!parsedBlock) { disableSaveButton('Cannot save: Draft block data failed to parse'); return; } // Recursively map JS block format to PHP block format const mapToPhpBlock = (jsBlock) => { if (!jsBlock) return null; return { blockName: jsBlock.name || '', attrs: jsBlock.attributes || {}, innerHTML: jsBlock.originalContent || '', innerBlocks: (jsBlock.innerBlocks || []).map(mapToPhpBlock), innerContent: jsBlock.innerContent || [] }; }; editorState.blockState = mapToPhpBlock(parsedBlock); editorState.blockState.rawContent = rawContent; // Persist raw string editorState.originalAttributes = editorState.blockState.attrs; editorState.blockName = editorState.blockState.blockName; if (shouldInitListTracker(editorState, editorState.blockState)) { editorState.listTracker = ListBlockTracker.init(editorState.element, editorState.blockState); } clearPrimaryLoadingState(); return; } const resolvedBlockState = resolveBlockStateOverride(editorState); if (resolvedBlockState) { applyBlockState(resolvedBlockState); clearPrimaryLoadingState(); return; } const primaryBtn = initialPrimaryBtn; const originalText = primaryBtn ? primaryBtn.textContent : null; if (primaryBtn) { primaryBtn.disabled = true; primaryBtn.setAttribute('data-loading-attrs', 'true'); primaryBtn.setAttribute('mwp-sfe-btn-loading', 'true'); // Keep original text, let CSS handle the loading visual } if ( editorState?.saveStrategy === 'batch' && batchManager && typeof batchManager.isEnabled === 'function' && batchManager.isEnabled() && typeof batchManager.ensureSession === 'function' ) { try { await batchManager.ensureSession(); } catch (error) { console.warn('FrontEdit: batch session ensure failed, falling back to per-block fetch', error); } } const resolvedBlockStateAfterEnsure = resolveBlockStateOverride(editorState); if (resolvedBlockStateAfterEnsure) { applyBlockState(resolvedBlockStateAfterEnsure, originalText); clearPrimaryLoadingState(originalText); return; } if (primaryBtn) { try { const blockState = await apiCall('/get-block-state', { post_id: postId, element_uuid: uuid }); applyBlockState(blockState, originalText); } catch (error) { console.warn('Failed to fetch block state:', error); alert('Failed to load block data. Editing is disabled to prevent data loss. Please refresh the page.'); if (SFE.Context.activeEditor === editorState) { disableSaveButton('Cannot save: Block data failed to load'); } } } else { try { const blockState = await apiCall('/get-block-state', { post_id: postId, element_uuid: uuid }); applyBlockState(blockState); } catch (error) { console.warn('Failed to fetch block state:', error); editorState.originalAttributes = {}; editorState.blockName = ''; } } } SFE.Api = { apiCall, hydrateEditorBlockStateOnOpen, fetchBlockAttributes, resolveMediaAttributes, queueResolvedMediaAttributes, ensureResolvedMediaAttributes }; })(); Política de Privacidad – kibekis

Política de Privacidad

El Titular le informa sobre su Política de Privacidad respecto del tratamiento y protección de los datos de carácter personal de los usuarios que puedan ser recabados durante la navegación a través del Sitio Web: https://kibekis.es

En este sentido, el Titular garantiza el cumplimiento de la normativa vigente en materia de protección de datos personales, reflejada en la Ley Orgánica 3/2018, de 5 de diciembre, de Protección de Datos Personales y de Garantía de Derechos Digitales (LOPD GDD). Cumple también con el Reglamento (UE) 2016/679 del Parlamento Europeo y del Consejo de 27 de abril de 2016 relativo a la protección de las personas físicas (RGPD).

El uso de sitio Web implica la aceptación de esta Política de Privacidad así como las condiciones incluidas en el Aviso Legal.

Identidad del Responsable

  • Responsable:  Kibekis.
  • NIF: 05687975Y
  • Domicilio:  Paseo Juan Hernández Sarabia 1, piso 2-3, 28905, Getafe, Madrid - España.
  • Correo electrónico:  info@kibekis.com
  • Teléfono de contacto:  +34 911 42 48 37
  • Sitio Web:  https://kibekis.es

Principios aplicados en el tratamiento de datos

En el tratamiento de sus datos personales, el Titular aplicará los siguientes principios que se ajustan a las exigencias del nuevo reglamento europeo de protección de datos (RGPD):

  • Principio de licitud, lealtad y transparencia: El Titular siempre requerirá el consentimiento para el tratamiento de los datos personales que puede ser para uno o varios fines específicos sobre los que el Titular informará al Usuario previamente con absoluta transparencia.
  • Principio de minimización de datos: El Titular solicitará solo los datos estrictamente necesarios para el fin o los fines que los solicita.
  • Principio de limitación del plazo de conservación: El Titular mantendrá los datos personales recabados durante el tiempo estrictamente necesario para el fin o los fines del tratamiento. El Titular informará al Usuario del plazo de conservación correspondiente según la finalidad.
    En el caso de suscripciones, el Titular revisará periódicamente las listas y eliminará aquellos registros inactivos durante un tiempo considerable.
  • Principio de integridad y confidencialidad: Los datos personales recabados serán tratados de tal manera que su seguridad, confidencialidad e integridad está garantizada.
    El Titular toma las precauciones necesarias para evitar el acceso no autorizado o uso indebido de los datos de sus usuarios por parte de terceros.

Obtención de datos personales

Para navegar por el sitio Web no es necesario que facilite ningún dato personal.

Derechos

El Titular le informa que sobre sus datos personales tiene derecho a:

  • Solicitar el acceso a los datos almacenados.
  • Solicitar una rectificación o la supresión.
  • Solicitar la limitación de su tratamiento.
  • Oponerse al tratamiento.

No puede ejercitar el derecho a la portabilidad de los datos.

El ejercicio de estos derechos es personal y por tanto debe ser ejercido directamente por el interesado, solicitándolo directamente al Titular, lo que significa que cualquier cliente, suscriptor o colaborador que haya facilitado sus datos en algún momento, puede dirigirse al Titular y pedir información sobre los datos que tiene almacenados y cómo los ha obtenido, solicitar la rectificación de los mismos, oponerse al tratamiento, limitar su uso o solicitar la supresión de esos datos en los ficheros del Titular.

Para ejercitar sus derechos tiene que enviar su petición junto con una fotocopia del Documento Nacional de Identidad o equivalente a  la dirección de correo electrónico: info@kibekis.com

El ejercicio de estos derechos no incluye ningún dato que el Titular esté obligado a conservar con fines administrativos, legales o de seguridad.

Tiene derecho a la tutela judicial efectiva y a presentar una reclamación ante la autoridad de control, en este caso, la Agencia Española de Protección de Datos, si considera que el tratamiento de datos personales que le conciernen infringe el Reglamento.

Finalidad del tratamiento de datos personales

Cuando usted se conecta al Sitio Web para mandar un correo al Titular, se suscribe a su boletín está facilitando información de carácter personal de la que el responsable es el Titular. Esta información puede incluir datos de carácter personal como pueden ser su dirección IP, nombre y apellidos, dirección física, dirección de correo electrónico, número de teléfono, y otra información. Al facilitar esta información, da su consentimiento para que su información sea recopilada, utilizada, gestionada y almacenada por — Kibekis — sólo como se describe en las páginas:

Los datos personales y la finalidad del tratamiento por parte del Titular es diferente según el sistema de captura de información:

Existen otras finalidades por las que el Titular trata datos personales:

  • Para garantizar el cumplimiento de las condiciones recogidas en la página de Aviso Legal y de la ley aplicable. Esto puede incluir el desarrollo de herramientas y algoritmos que ayuden al Sitio Web a garantizar la confidencialidad de los datos personales que recoge.
  • Para apoyar y mejorar los servicios que ofrece este Sitio Web.
  • Para analizar la navegación de los usuarios. El Titular recoge otros datos no identificativos que se obtienen mediante el uso de cookies que se descargan en el ordenador del Usuario cuando navega por el Sitio Web cuyas características y finalidad están detalladas en la página de Política de Cookies.

Seguridad de los datos personales

Para proteger sus datos personales, el Titular toma todas las precauciones razonables y sigue las mejores prácticas de la industria para evitar su pérdida, mal uso, acceso indebido, divulgación, alteración o destrucción de los mismos.

Sus datos podrán ser incorporados a un fichero de lista de correo, del cual el Titular es responsable de su gestión y tratamiento. La seguridad de sus datos está garantizada, ya que el Titular toma todas las medidas de seguridad necesarias y le garantiza que los datos personales sólo se usarán para las finalidades dadas.

El Titular informa al Usuario de que sus datos personales no serán cedidos a terceras organizaciones, con la salvedad de que dicha cesión de datos esté amparada en una obligación legal o cuando la prestación de un servicio implique la necesidad de una relación contractual con un encargado de tratamiento. En este último caso, solo se llevará a cabo la cesión de datos al tercero cuando el Titular disponga del consentimiento expreso del Usuario.

Sin embargo, en algunos casos se pueden realizar colaboraciones con otros profesionales, en esos casos, se requerirá consentimiento al Usuario informando sobre la identidad del colaborador y la finalidad de la colaboración. Siempre se realizará con los más estrictos estándares de seguridad.

Contenido de otros sitios web

Las páginas de este sitio Web pueden incluir contenido incrustado (por ejemplo, vídeos, imágenes, artículos, etc.). El contenido incrustado de otras web se comporta exactamente de la misma manera que si hubiera visitado la otra web.

Estos sitios Web pueden recopilar datos sobre usted, utilizar cookies, incrustar un código de seguimiento adicional de terceros, y supervisar su interacción usando este código.

Política de Cookies

Para que este sitio Web funcione correctamente necesita utilizar cookies, que es una información que se almacena en su navegador web.

Puede consultar toda la información relativa a la política de recogida y tratamiento de las cookies en la página de Política de Cookies.

Legitimación para el tratamiento de datos

La base legal para el tratamiento de sus datos es:

  • El consentimiento del interesado.

Categorías de datos personales

Las categorías de datos personales que trata el Titular son:

  • Datos identificativos.
  • No se tratan categorías de datos especialmente protegidos.

Conservación de datos personales

Los datos personales proporcionados al Titular se conservarán hasta que solicite su supresión.

Navegación Web

Al navegar por el Sitio Web se pueden recoger datos no identificativos, que pueden incluir, la dirección IP, geolocalización, un registro de cómo se utilizan los servicios y sitios, hábitos de navegación y otros datos que no pueden ser utilizados para identificarle.

El sitio Web utiliza los siguientes servicios de análisis de terceros:

El Titular utiliza la información obtenida para obtener datos estadísticos, analizar tendencias, administrar el sitio, estudiar patrones de navegación y para recopilar información demográfica.

El Titular no se hace responsable del tratamiento de los datos personales que realicen las páginas web a las que pueda acceder a través de los distintos enlaces que contiene el Sitio Web.

Exactitud y veracidad de los datos personales

Usted se compromete a que los datos facilitados al Titular sean correctos, completos, exactos y vigentes, así como a mantenerlos debidamente actualizados.

Como Usuario del Sitio Web es el único responsable de la veracidad y corrección de los datos remitidos al Sitio Web exonerando al Titular de cualquier responsabilidad al respecto.

Aceptación y consentimiento

Como Usuario del Sitio Web declara haber sido informado de las condiciones sobre protección de datos de carácter personal, acepta y consiente el tratamiento de los mismos por parte del Titular en la forma y para las finalidades indicadas en esta Política de Privacidad.

Para contactar con el Titular, suscribirse a un boletín o realizar comentarios en este sitio Web tiene que aceptar la presente Política de Privacidad.

Cambios en la Política de Privacidad

El Titular se reserva el derecho a modificar la presente Política de Privacidad para adaptarla a novedades legislativas o jurisprudenciales, así como a prácticas de la industria.

Estas políticas estarán vigentes hasta que sean modificadas por otras debidamente publicadas.

Carrito de compras