- Add public/catalog.html with featured hero, quick categories, property grid - Add conversion blocks: why-buy (6 cards), how-it-works (3 steps), CTA form, FAQ - Register /catalog and /catalog.html routes in src/server/index.ts - Update nav links in index.html and property.html to /catalog.html - Add i18n support (ES/RU) for all new sections - Deploy to Docker container
1529 lines
117 KiB
HTML
1529 lines
117 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="es">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta name="description" content="Catálogo completo de propiedades en Tenerife - Terrenos agrícolas y urbanos, casas y apartamentos.">
|
||
<meta name="keywords" content="terrenos Tenerife, casas Tenerife, apartamentos Canarias, invertir Tenerife, propiedades España">
|
||
<title>Catálogo de Propiedades | TenerifeProp</title>
|
||
<!-- Open Graph -->
|
||
<meta property="og:title" content="Catálogo de Propiedades | TenerifeProp">
|
||
<meta property="og:description" content="Encuentra tu terreno perfecto en Tenerife. Terrenos agrícolas, urbanos, casas y apartamentos.">
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:locale" content="es_ES">
|
||
<!-- Bootstrap 5 CSS -->
|
||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||
<!-- Bootstrap Icons -->
|
||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css" rel="stylesheet">
|
||
<!-- Google Fonts -->
|
||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800&family=Open+Sans:wght@400;500;600&display=swap" rel="stylesheet">
|
||
<!-- AOS Animation -->
|
||
<link href="https://cdn.jsdelivr.net/npm/aos@2.3.4/dist/aos.css" rel="stylesheet">
|
||
<!-- Leaflet CSS -->
|
||
<link href="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.min.css" rel="stylesheet">
|
||
|
||
<style>
|
||
:root {
|
||
--primary: #1a5f4a;
|
||
--primary-light: #2d8f6f;
|
||
--primary-dark: #0d4535;
|
||
--secondary: #d4a853;
|
||
--secondary-light: #e6c57a;
|
||
--accent: #e85d04;
|
||
--dark: #1a1a2e;
|
||
--light: #f8f9fa;
|
||
--gray: #6c757d;
|
||
--shadow: 0 10px 40px rgba(0,0,0,0.1);
|
||
--shadow-lg: 0 25px 50px rgba(0,0,0,0.15);
|
||
}
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
html { scroll-behavior: smooth; }
|
||
body {
|
||
font-family: 'Open Sans', sans-serif;
|
||
color: var(--dark);
|
||
background: var(--light);
|
||
overflow-x: hidden;
|
||
}
|
||
h1, h2, h3, h4, h5, h6 { font-family: 'Montserrat', sans-serif; font-weight: 700; }
|
||
|
||
.text-primary-custom { color: var(--primary) !important; }
|
||
.bg-primary-custom { background-color: var(--primary) !important; }
|
||
.btn-primary-custom {
|
||
background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%);
|
||
border: none; color: white; padding: 15px 40px; font-weight: 600;
|
||
border-radius: 50px; transition: all 0.4s ease; text-transform: uppercase;
|
||
letter-spacing: 1px; font-size: 0.9rem; text-decoration: none;
|
||
}
|
||
.btn-primary-custom:hover {
|
||
transform: translateY(-3px); box-shadow: 0 15px 35px rgba(26, 95, 74, 0.4); color: white;
|
||
}
|
||
.section-padding { padding: 100px 0; }
|
||
.section-title {
|
||
font-size: 2.8rem; margin-bottom: 1rem; position: relative; display: inline-block;
|
||
}
|
||
.section-title::after {
|
||
content: ''; position: absolute; bottom: -10px; left: 50%; transform: translateX(-50%);
|
||
width: 80px; height: 4px;
|
||
background: linear-gradient(90deg, var(--secondary), var(--accent));
|
||
border-radius: 2px;
|
||
}
|
||
.section-subtitle { font-size: 1.1rem; color: var(--gray); margin-bottom: 3rem; }
|
||
|
||
/* ============ NAVBAR ============ */
|
||
.navbar {
|
||
padding: 20px 0; transition: all 0.4s ease;
|
||
background: rgba(255,255,255,0.98); box-shadow: var(--shadow);
|
||
}
|
||
.navbar-brand {
|
||
font-family: 'Montserrat', sans-serif; font-weight: 800; font-size: 1.8rem;
|
||
color: var(--primary) !important;
|
||
}
|
||
.navbar-brand span { color: var(--secondary); }
|
||
.nav-link {
|
||
color: var(--dark) !important; font-weight: 500; padding: 10px 20px !important;
|
||
transition: all 0.3s ease; position: relative;
|
||
}
|
||
.nav-link:hover { color: var(--primary) !important; }
|
||
.nav-link::after {
|
||
content: ''; position: absolute; bottom: 5px; left: 20px;
|
||
width: 0; height: 2px; background: var(--secondary); transition: width 0.3s ease;
|
||
}
|
||
.nav-link:hover::after { width: calc(100% - 40px); }
|
||
|
||
.lang-switcher { display: flex; gap: 5px; margin-left: 20px; }
|
||
.lang-btn {
|
||
padding: 8px 16px; border: 2px solid var(--primary); border-radius: 25px;
|
||
background: transparent; color: var(--primary); font-weight: 600; font-size: 0.85rem;
|
||
cursor: pointer; transition: all 0.3s ease;
|
||
}
|
||
.lang-btn.active { background: var(--primary); color: white; }
|
||
.lang-btn:hover { transform: scale(1.05); }
|
||
.navbar-toggler { border: none; padding: 10px; }
|
||
.navbar-toggler:focus { box-shadow: none; }
|
||
|
||
/* ============ FEATURED HERO ============ */
|
||
.featured-hero { position: relative; min-height: 500px; display: flex; align-items: center; overflow: hidden; }
|
||
.featured-hero-bg {
|
||
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
|
||
background: url('https://images.unsplash.com/photo-1564013799919-ab600027ffc6?w=1920&q=80') center/cover no-repeat; opacity: 0.25;
|
||
}
|
||
.featured-hero .featured-card {
|
||
background: white; border-radius: 24px; overflow: hidden; box-shadow: var(--shadow-lg);
|
||
}
|
||
.featured-hero .featured-card-img {
|
||
position: relative; height: 220px; overflow: hidden;
|
||
}
|
||
.featured-hero .featured-card-img img { width: 100%; height: 100%; object-fit: cover; }
|
||
.featured-hero .featured-card-body { padding: 25px; }
|
||
.featured-hero .featured-card-title { font-size: 1.2rem; margin-bottom: 8px; color: var(--dark); }
|
||
.featured-hero .featured-card-location { color: var(--gray); font-size: 0.9rem; margin-bottom: 12px; }
|
||
.featured-hero .featured-card-meta { display: flex; gap: 15px; margin-bottom: 15px; }
|
||
.featured-hero .featured-card-meta span { font-size: 0.85rem; color: var(--gray); }
|
||
.featured-hero .featured-card-price { font-size: 1.6rem; font-weight: 800; color: var(--primary); }
|
||
.featured-hero .featured-card-btn {
|
||
background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%); color: white;
|
||
padding: 10px 24px; border-radius: 50px; font-weight: 600; font-size: 0.85rem;
|
||
text-decoration: none; text-transform: uppercase; transition: all 0.3s ease;
|
||
}
|
||
.featured-hero .featured-card-btn:hover { transform: translateY(-2px); box-shadow: 0 5px 15px rgba(26,95,74,0.3); color: white; }
|
||
|
||
/* ============ QUICK CATEGORIES ============ */
|
||
.quick-cat-link {
|
||
display: block; text-align: center; padding: 25px 15px; background: #f8f9fa;
|
||
border-radius: 20px; text-decoration: none; transition: all 0.3s ease; border: 2px solid transparent;
|
||
}
|
||
.quick-cat-link:hover {
|
||
border-color: var(--primary); transform: translateY(-5px); box-shadow: var(--shadow);
|
||
}
|
||
.quick-cat-icon {
|
||
width: 60px; height: 60px;
|
||
background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%);
|
||
border-radius: 50%; display: flex; align-items: center; justify-content: center;
|
||
margin: 0 auto 15px;
|
||
}
|
||
.quick-cat-icon i { font-size: 1.5rem; color: white; }
|
||
.quick-cat-title { font-size: 0.95rem; color: var(--dark); margin: 0; }
|
||
.quick-cat-count { color: var(--gray); font-size: 0.8rem; }
|
||
|
||
/* ============ CATALOG ============ */
|
||
.catalog {
|
||
background: linear-gradient(180deg, #f8f9fa 0%, #fff 100%);
|
||
}
|
||
.catalog > .container > .row { align-items: stretch; }
|
||
.catalog-tabs {
|
||
display: flex; justify-content: center; gap: 15px; margin-bottom: 50px; flex-wrap: wrap;
|
||
}
|
||
.catalog-tab {
|
||
padding: 12px 30px; border: 2px solid var(--primary); border-radius: 50px;
|
||
background: transparent; color: var(--primary); font-weight: 600; cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
}
|
||
.catalog-tab:hover, .catalog-tab.active { background: var(--primary); color: white; }
|
||
|
||
.filters-section {
|
||
background: white; border-radius: 20px; padding: 30px; box-shadow: var(--shadow);
|
||
position: sticky; top: 100px;
|
||
}
|
||
.filter-group { margin-bottom: 25px; }
|
||
.filter-group label {
|
||
font-weight: 600; color: var(--dark); margin-bottom: 10px; display: block;
|
||
}
|
||
.filter-group label i { color: var(--primary); margin-right: 8px; }
|
||
.form-control, .form-select {
|
||
border: 2px solid #e9ecef; border-radius: 12px; padding: 12px 18px; transition: all 0.3s ease;
|
||
}
|
||
.form-control:focus, .form-select:focus {
|
||
border-color: var(--primary); box-shadow: 0 0 0 0.2rem rgba(26,95,74,0.15);
|
||
}
|
||
.filter-checkbox {
|
||
display: flex; align-items: center; gap: 10px; padding: 10px 15px;
|
||
background: #f8f9fa; border-radius: 10px; cursor: pointer; transition: all 0.3s ease;
|
||
}
|
||
.filter-checkbox:hover { background: #e9ecef; }
|
||
.filter-checkbox input { width: 20px; height: 20px; accent-color: var(--primary); }
|
||
.filter-checkbox i { color: var(--primary); font-size: 1.2rem; }
|
||
|
||
.view-toggle { display: flex; gap: 10px; margin-bottom: 30px; }
|
||
.view-btn {
|
||
padding: 10px 20px; border: 2px solid #e9ecef; border-radius: 10px;
|
||
background: white; color: var(--gray); cursor: pointer; transition: all 0.3s ease;
|
||
}
|
||
.view-btn.active, .view-btn:hover { background: var(--primary); border-color: var(--primary); color: white; }
|
||
.view-btn i { font-size: 1.2rem; }
|
||
|
||
.property-card {
|
||
background: white; border-radius: 20px; overflow: hidden;
|
||
box-shadow: var(--shadow); transition: all 0.4s ease; margin-bottom: 30px;
|
||
}
|
||
.property-card:hover {
|
||
transform: translateY(-10px); box-shadow: var(--shadow-lg);
|
||
}
|
||
.property-image { position: relative; height: 250px; overflow: hidden; }
|
||
.property-image img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s ease; }
|
||
.property-card:hover .property-image img { transform: scale(1.1); }
|
||
.property-badges { position: absolute; top: 15px; left: 15px; display: flex; gap: 8px; }
|
||
.property-badge {
|
||
padding: 5px 15px; border-radius: 20px; font-size: 0.75rem;
|
||
font-weight: 600; text-transform: uppercase;
|
||
}
|
||
.badge-new { background: var(--accent); color: white; }
|
||
.badge-exclusive { background: var(--secondary); color: var(--dark); }
|
||
.badge-agricultural { background: var(--primary); color: white; }
|
||
.badge-urban { background: #4a90d9; color: white; }
|
||
.badge-house { background: #9b59b6; color: white; }
|
||
.badge-ruins { background: #e74c3c; color: white; }
|
||
.property-favorite {
|
||
position: absolute; top: 15px; right: 15px; width: 40px; height: 40px;
|
||
background: white; border-radius: 50%; display: flex; align-items: center; justify-content: center;
|
||
cursor: pointer; transition: all 0.3s ease; border: none;
|
||
}
|
||
.property-favorite:hover { transform: scale(1.1); }
|
||
.property-favorite i { color: var(--gray); font-size: 1.2rem; transition: all 0.3s ease; }
|
||
.property-favorite.active i, .property-favorite:hover i { color: #e74c3c; }
|
||
.property-content { padding: 25px; }
|
||
.property-type { color: var(--primary); font-size: 0.85rem; font-weight: 600; text-transform: uppercase; margin-bottom: 8px; }
|
||
.property-title { font-size: 1.2rem; margin-bottom: 10px; color: var(--dark); }
|
||
.property-location { color: var(--gray); font-size: 0.9rem; margin-bottom: 15px; }
|
||
.property-location i { margin-right: 5px; }
|
||
.property-features { display: flex; gap: 20px; padding-top: 15px; border-top: 1px solid #eee; margin-bottom: 15px; }
|
||
.property-feature { display: flex; align-items: center; gap: 5px; font-size: 0.85rem; color: var(--gray); }
|
||
.property-feature i { color: var(--primary); }
|
||
.property-utilities { display: flex; gap: 10px; margin-bottom: 15px; }
|
||
.utility-icon {
|
||
width: 35px; height: 35px; background: #f0f0f0; border-radius: 8px;
|
||
display: flex; align-items: center; justify-content: center; font-size: 0.9rem;
|
||
}
|
||
.utility-icon.has { background: rgba(26,95,74,0.1); color: var(--primary); }
|
||
.utility-icon.no { background: rgba(231,76,60,0.1); color: #e74c3c; }
|
||
.property-price { font-size: 1.5rem; font-weight: 700; color: var(--primary); }
|
||
.property-price span { font-size: 0.9rem; font-weight: 400; color: var(--gray); }
|
||
.property-actions { display: flex; gap: 10px; margin-top: 15px; }
|
||
.property-actions .btn { flex: 1; padding: 12px; border-radius: 10px; font-size: 0.85rem; font-weight: 600; }
|
||
|
||
.map-container { height: calc(100% - 30px); min-height: 500px; border-radius: 20px; overflow: hidden; box-shadow: var(--shadow); margin-bottom: 30px; }
|
||
#mapView { height: 100%; padding-bottom: 0; }
|
||
#map { height: 100%; width: 100%; }
|
||
.leaflet-popup-content-wrapper {
|
||
border-radius: 16px; overflow: hidden; box-shadow: 0 10px 40px rgba(0,0,0,0.15); border: none; padding: 0;
|
||
}
|
||
.leaflet-popup-content { margin: 0; min-width: 0; }
|
||
.leaflet-popup-tip { background: var(--primary); box-shadow: 0 3px 14px rgba(0,0,0,0.1); }
|
||
.leaflet-popup-close-button { color: white !important; font-size: 22px !important; top: 8px !important; right: 10px !important; z-index: 10; text-shadow: 0 1px 4px rgba(0,0,0,0.4); }
|
||
.map-popup { padding: 0; width: 280px; font-family: 'Open Sans', sans-serif; }
|
||
.map-popup-img { position: relative; width: 100%; height: 160px; overflow: hidden; }
|
||
.map-popup-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||
.map-popup-img .popup-badge {
|
||
position: absolute; top: 10px; left: 10px; padding: 4px 12px; border-radius: 50px;
|
||
font-family: 'Montserrat', sans-serif; font-size: 0.7rem; font-weight: 600;
|
||
text-transform: uppercase; letter-spacing: 0.5px;
|
||
}
|
||
.popup-badge-agricultural { background: var(--primary); color: white; }
|
||
.popup-badge-urban { background: var(--secondary); color: var(--dark); }
|
||
.popup-badge-house { background: var(--primary); color: white; }
|
||
.popup-badge-apartment { background: var(--secondary); color: var(--dark); }
|
||
.popup-badge-ruins { background: var(--dark); color: white; }
|
||
.map-popup-body { padding: 16px; background: white; }
|
||
.map-popup-title { font-family: 'Montserrat', sans-serif; font-size: 0.95rem; font-weight: 700; color: var(--dark); margin: 0 0 6px 0; line-height: 1.3; }
|
||
.map-popup-location { font-size: 0.8rem; color: var(--gray); margin: 0 0 12px 0; }
|
||
.map-popup-location i { color: var(--primary); margin-right: 4px; }
|
||
.map-popup-meta { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 12px; }
|
||
.map-popup-price { font-family: 'Montserrat', sans-serif; font-size: 1.1rem; font-weight: 700; color: var(--primary); }
|
||
.map-popup-area { font-size: 0.8rem; color: var(--gray); background: #f0f0f0; padding: 3px 10px; border-radius: 50px; }
|
||
.map-popup-link {
|
||
display: block; width: 100%; text-align: center; padding: 10px;
|
||
background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%); color: white;
|
||
font-family: 'Montserrat', sans-serif; font-weight: 600; font-size: 0.8rem;
|
||
text-transform: uppercase; letter-spacing: 1px; text-decoration: none; border-radius: 50px;
|
||
transition: all 0.3s ease;
|
||
}
|
||
.map-popup-link:hover { transform: translateY(-2px); box-shadow: 0 5px 15px rgba(26,95,74,0.35); color: white; }
|
||
.map-popup-link i { margin-right: 6px; }
|
||
|
||
/* ============ FOOTER ============ */
|
||
footer { background: var(--dark); color: white; padding: 80px 0 30px; }
|
||
.footer-brand { font-family: 'Montserrat', sans-serif; font-size: 2rem; font-weight: 800; margin-bottom: 20px; }
|
||
.footer-brand span { color: var(--secondary); }
|
||
.footer-about { color: rgba(255,255,255,0.7); line-height: 1.8; margin-bottom: 25px; }
|
||
.footer-title { font-size: 1.2rem; font-weight: 700; margin-bottom: 25px; color: white; }
|
||
.footer-links { list-style: none; padding: 0; }
|
||
.footer-links li { margin-bottom: 12px; }
|
||
.footer-links a { color: rgba(255,255,255,0.7); text-decoration: none; transition: all 0.3s ease; }
|
||
.footer-links a:hover { color: var(--secondary); padding-left: 10px; }
|
||
.footer-contact-item { display: flex; align-items: center; gap: 15px; margin-bottom: 15px; color: rgba(255,255,255,0.7); }
|
||
.footer-contact-item i { color: var(--secondary); font-size: 1.2rem; }
|
||
.footer-bottom { border-top: 1px solid rgba(255,255,255,0.1); margin-top: 50px; padding-top: 30px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 20px; }
|
||
.footer-bottom p { margin: 0; color: rgba(255,255,255,0.5); font-size: 0.9rem; }
|
||
.footer-legal { display: flex; gap: 25px; }
|
||
.footer-legal a { color: rgba(255,255,255,0.5); font-size: 0.9rem; text-decoration: none; transition: color 0.3s ease; }
|
||
.footer-legal a:hover { color: var(--secondary); }
|
||
|
||
/* ============ MODAL ============ */
|
||
.property-modal .modal-content { border: none; border-radius: 25px; overflow: hidden; box-shadow: 0 25px 50px rgba(0,0,0,0.15); }
|
||
.property-modal .modal-header { border: none; padding: 0; position: relative; }
|
||
.property-modal .btn-close { position: absolute; top: 15px; right: 15px; z-index: 10; background: rgba(255,255,255,0.9); border-radius: 50%; padding: 10px; box-shadow: 0 2px 8px rgba(0,0,0,0.15); opacity: 1; }
|
||
.modal-gallery { position: relative; height: 350px; }
|
||
.modal-gallery img { width: 100%; height: 100%; object-fit: cover; }
|
||
.modal-gallery::after { content: ''; position: absolute; bottom: 0; left: 0; right: 0; height: 80px; background: linear-gradient(to top, rgba(26,26,46,0.6), transparent); pointer-events: none; }
|
||
.gallery-arrow { position: absolute; top: 50%; transform: translateY(-50%); width: 40px; height: 40px; background: rgba(255,255,255,0.85); border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 5; border: none; color: var(--dark); font-size: 1.1rem; transition: all 0.3s ease; box-shadow: 0 2px 8px rgba(0,0,0,0.15); }
|
||
.gallery-arrow:hover { background: var(--secondary); color: white; transform: translateY(-50%) scale(1.1); }
|
||
.gallery-arrow.prev { left: 15px; }
|
||
.gallery-arrow.next { right: 15px; }
|
||
.gallery-controls { position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); display: flex; gap: 10px; z-index: 2; }
|
||
.gallery-dot { width: 12px; height: 12px; background: rgba(255,255,255,0.5); border-radius: 50%; cursor: pointer; transition: all 0.3s ease; }
|
||
.gallery-dot.active { background: var(--secondary); transform: scale(1.2); }
|
||
.modal-gallery-slider { position: relative; width: 100%; height: 100%; overflow: hidden; }
|
||
.modal-gallery-slider img { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 0.5s ease; }
|
||
.modal-gallery-slider img.active { opacity: 1; }
|
||
.modal-view-details {
|
||
background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%); border: none; color: white;
|
||
padding: 14px 30px; font-weight: 600; border-radius: 50px; transition: all 0.4s ease;
|
||
text-transform: uppercase; letter-spacing: 1px; font-size: 0.85rem; text-decoration: none;
|
||
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
|
||
}
|
||
.modal-view-details:hover { transform: translateY(-2px); box-shadow: 0 10px 30px rgba(26,95,74,0.4); color: white; }
|
||
.property-modal .modal-body { padding: 30px; }
|
||
.property-modal .property-type { display: inline-block; padding: 5px 16px; border-radius: 50px; font-family: 'Montserrat', sans-serif; font-weight: 600; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 12px; }
|
||
.modal-property-title { font-family: 'Montserrat', sans-serif; font-size: 1.6rem; font-weight: 700; color: var(--dark); margin-bottom: 8px; }
|
||
.modal-property-location { color: var(--gray); margin-bottom: 20px; font-size: 0.95rem; }
|
||
.modal-property-location i { color: var(--primary); margin-right: 4px; }
|
||
.modal-price { font-family: 'Montserrat', sans-serif; font-size: 1.8rem; font-weight: 700; color: var(--primary); margin-bottom: 25px; }
|
||
.modal-features { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 25px; }
|
||
.modal-feature { display: flex; align-items: center; gap: 12px; padding: 14px; background: rgba(26,95,74,0.05); border-radius: 12px; border: 1px solid rgba(26,95,74,0.1); transition: all 0.3s ease; }
|
||
.modal-feature:hover { background: rgba(26,95,74,0.1); transform: translateY(-1px); }
|
||
.modal-feature i { font-size: 1.3rem; color: var(--primary); }
|
||
.modal-feature strong { display: block; font-family: 'Montserrat', sans-serif; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.5px; color: var(--gray); }
|
||
.modal-feature p { margin: 0; font-family: 'Montserrat', sans-serif; font-weight: 600; color: var(--dark); }
|
||
.modal-utility { display: flex; align-items: center; gap: 12px; padding: 12px 18px; border-radius: 12px; margin-bottom: 8px; font-size: 0.9rem; transition: all 0.3s ease; }
|
||
.modal-utility.has { background: rgba(26,95,74,0.08); border: 1px solid rgba(26,95,74,0.15); }
|
||
.modal-utility.no { background: rgba(231,76,60,0.05); border: 1px solid rgba(231,76,60,0.1); }
|
||
.modal-utility i { font-size: 1.1rem; width: 24px; text-align: center; }
|
||
.modal-utility.has i { color: var(--primary); }
|
||
.modal-utility.no i { color: #c0392b; }
|
||
.property-modal .btn-primary-custom { border-radius: 50px; }
|
||
.property-modal .btn-outline-primary { border: 2px solid var(--primary); color: var(--primary); border-radius: 50px; padding: 13px 38px; font-weight: 600; text-decoration: none; transition: all 0.3s ease; }
|
||
.property-modal .btn-outline-primary:hover { background: var(--primary); color: white; transform: translateY(-2px); }
|
||
|
||
/* ============ WHATSAPP BUTTON ============ */
|
||
.whatsapp-float { position: fixed; bottom: 30px; right: 30px; z-index: 1000; }
|
||
.whatsapp-btn { width: 65px; height: 65px; background: #25D366; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: white; font-size: 2rem; box-shadow: 0 5px 25px rgba(37,211,102,0.4); transition: all 0.3s ease; text-decoration: none; }
|
||
.whatsapp-btn:hover { transform: scale(1.1); color: white; box-shadow: 0 10px 35px rgba(37,211,102,0.5); }
|
||
|
||
/* ============ RESPONSIVE ============ */
|
||
@media (max-width: 991px) { .section-title { font-size: 2rem; } .modal-features { grid-template-columns: 1fr; } }
|
||
@media (max-width: 767px) { .section-title { font-size: 1.8rem; } .footer-bottom { flex-direction: column; text-align: center; } }
|
||
|
||
/* Leaflet Custom Styles */
|
||
.leaflet-container { font-family: 'Open Sans', sans-serif; }
|
||
.custom-marker { background: var(--primary); border: 3px solid white; border-radius: 50%; box-shadow: 0 3px 10px rgba(0,0,0,0.3); }
|
||
|
||
/* ============ PAGINATION ============ */
|
||
.pagination { gap: 6px; }
|
||
.pagination .page-item .page-link {
|
||
border: 2px solid var(--primary); border-radius: 50px !important; color: var(--primary);
|
||
font-family: 'Montserrat', sans-serif; font-weight: 600; font-size: 0.9rem;
|
||
padding: 8px 18px; background: transparent; transition: all 0.3s ease;
|
||
line-height: 1.4; min-width: 44px; text-align: center;
|
||
}
|
||
.pagination .page-item .page-link:hover { background: var(--primary); color: white; transform: translateY(-2px); box-shadow: 0 5px 15px rgba(26,95,74,0.3); }
|
||
.pagination .page-item.active .page-link { background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%); border-color: var(--primary); color: white; box-shadow: 0 5px 15px rgba(26,95,74,0.35); }
|
||
.pagination .page-item.active .page-link:hover { transform: translateY(-2px); }
|
||
.pagination .page-item.disabled .page-link { border-color: #ced4da; color: #adb5bd; background: transparent; pointer-events: none; opacity: 0.6; }
|
||
.pagination .page-item .page-link:focus { box-shadow: 0 0 0 0.2rem rgba(26,95,74,0.25); }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<!-- ============ NAVBAR ============ -->
|
||
<nav class="navbar navbar-expand-lg fixed-top">
|
||
<div class="container">
|
||
<a class="navbar-brand" href="/">
|
||
Tenerife<span>Prop</span>
|
||
</a>
|
||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||
<span class="navbar-toggler-icon" style="background-image: url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%2826, 95, 74, 1%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\");"></span>
|
||
</button>
|
||
<div class="collapse navbar-collapse justify-content-end" id="navbarNav">
|
||
<ul class="navbar-nav align-items-center">
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="/" data-i18n="nav.home">Inicio</a>
|
||
</li>
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="/catalog.html" data-i18n="nav.catalog">Catálogo</a>
|
||
</li>
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="/#services" data-i18n="nav.services">Servicios</a>
|
||
</li>
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="/#testimonials" data-i18n="nav.testimonials">Testimonios</a>
|
||
</li>
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="/#contact" data-i18n="nav.contact">Contacto</a>
|
||
</li>
|
||
<li class="nav-item">
|
||
<div class="lang-switcher">
|
||
<button class="lang-btn active" data-lang="es">ES</button>
|
||
<button class="lang-btn" data-lang="ru">RU</button>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
|
||
<!-- ============ FEATURED HERO ============ -->
|
||
<section class="featured-hero" style="margin-top: 86px; background: linear-gradient(135deg, var(--primary-dark) 0%, var(--primary) 50%, var(--primary-light) 100%);">
|
||
<div class="featured-hero-bg"></div>
|
||
<div class="container" style="position: relative; z-index: 2;">
|
||
<div class="row align-items-center">
|
||
<div class="col-lg-6" data-aos="fade-right">
|
||
<span class="hero-badge" style="display: inline-block; background: rgba(212,168,83,0.2); border: 1px solid var(--secondary); color: var(--secondary); padding: 8px 20px; border-radius: 50px; font-size: 0.9rem; font-weight: 600; margin-bottom: 20px;">
|
||
<i class="bi bi-star-fill me-2"></i><span data-i18n="hero.badge">Propiedad destacada</span>
|
||
</span>
|
||
<h1 style="font-size: 3rem; font-weight: 800; color: white; line-height: 1.2; margin-bottom: 20px;" data-i18n="hero.title">Encuentra tu propiedad ideal en Tenerife</h1>
|
||
<p style="font-size: 1.15rem; color: rgba(255,255,255,0.85); margin-bottom: 30px; line-height: 1.7;" data-i18n="hero.subtitle">Más de 500 propiedades seleccionadas: terrenos agrícolas, urbanos, casas, apartamentos y ruinas con documentación verificada.</p>
|
||
<a href="#catalog" class="btn btn-secondary-custom" style="background: var(--secondary); color: var(--dark); border: none;">
|
||
<i class="bi bi-grid-3x3-gap me-2"></i><span data-i18n="hero.cta">Ver catálogo</span>
|
||
</a>
|
||
</div>
|
||
<div class="col-lg-5 offset-lg-1" data-aos="fade-left">
|
||
<div class="featured-card">
|
||
<div class="featured-card-img">
|
||
<img src="https://images.unsplash.com/photo-1564013799919-ab600027ffc6?w=800&q=80" alt="Destacado">
|
||
<span class="property-badge badge-new" style="position: absolute; top: 15px; left: 15px;">Exclusivo</span>
|
||
<span class="property-badge" style="position: absolute; top: 15px; right: 15px; background: var(--secondary); color: var(--dark);">Urbano</span>
|
||
</div>
|
||
<div class="featured-card-body">
|
||
<h4 class="featured-card-title">Terreno Urbano en Adeje</h4>
|
||
<p class="featured-card-location"><i class="bi bi-geo-alt me-1 text-primary-custom"></i>Adeje, Tenerife Sur</p>
|
||
<div class="featured-card-meta">
|
||
<span><i class="bi bi-rulers me-1 text-primary-custom"></i>2.500 m²</span>
|
||
<span><i class="bi bi-droplet me-1 text-primary-custom"></i>Agua</span>
|
||
<span><i class="bi bi-lightning me-1 text-primary-custom"></i>Luz</span>
|
||
</div>
|
||
<div class="d-flex justify-content-between align-items-center">
|
||
<span class="featured-card-price">385.000 €</span>
|
||
<a href="/property/terreno-urbano-adeje" class="featured-card-btn">Ver más</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ QUICK CATEGORIES ============ -->
|
||
<section style="background: white; padding: 50px 0;">
|
||
<div class="container">
|
||
<div class="row g-3 justify-content-center" data-aos="fade-up">
|
||
<div class="col-lg-2 col-md-4 col-6">
|
||
<a href="#catalog" onclick="document.querySelector('[data-filter=\'agricultural\']').click(); return false;" class="quick-cat-link">
|
||
<div class="quick-cat-icon"><i class="bi bi-tree"></i></div>
|
||
<h6 class="quick-cat-title" data-i18n="cat.agricultural">Agrícolas</h6>
|
||
<small class="quick-cat-count" data-i18n="cat.agriculturalCount">45 disponibles</small>
|
||
</a>
|
||
</div>
|
||
<div class="col-lg-2 col-md-4 col-6">
|
||
<a href="#catalog" onclick="document.querySelector('[data-filter=\'urban\']').click(); return false;" class="quick-cat-link">
|
||
<div class="quick-cat-icon"><i class="bi bi-building"></i></div>
|
||
<h6 class="quick-cat-title" data-i18n="cat.urban">Urbanos</h6>
|
||
<small class="quick-cat-count" data-i18n="cat.urbanCount">32 disponibles</small>
|
||
</a>
|
||
</div>
|
||
<div class="col-lg-2 col-md-4 col-6">
|
||
<a href="#catalog" onclick="document.querySelector('[data-filter=\'house\']').click(); return false;" class="quick-cat-link">
|
||
<div class="quick-cat-icon"><i class="bi bi-house-door"></i></div>
|
||
<h6 class="quick-cat-title" data-i18n="cat.houses">Casas</h6>
|
||
<small class="quick-cat-count" data-i18n="cat.housesCount">28 disponibles</small>
|
||
</a>
|
||
</div>
|
||
<div class="col-lg-2 col-md-4 col-6">
|
||
<a href="#catalog" onclick="document.querySelector('[data-filter=\'apartment\']').click(); return false;" class="quick-cat-link">
|
||
<div class="quick-cat-icon"><i class="bi bi-building"></i></div>
|
||
<h6 class="quick-cat-title" data-i18n="cat.apartments">Apartamentos</h6>
|
||
<small class="quick-cat-count" data-i18n="cat.apartmentsCount">56 disponibles</small>
|
||
</a>
|
||
</div>
|
||
<div class="col-lg-2 col-md-4 col-6">
|
||
<a href="#catalog" onclick="document.querySelector('[data-filter=\'ruins\']').click(); return false;" class="quick-cat-link">
|
||
<div class="quick-cat-icon"><i class="bi bi-bricks"></i></div>
|
||
<h6 class="quick-cat-title" data-i18n="cat.ruins">Ruinas</h6>
|
||
<small class="quick-cat-count" data-i18n="cat.ruinsCount">18 disponibles</small>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ CATALOG SECTION ============ -->
|
||
<section class="catalog section-padding" style="padding-top: 60px;" id="catalog">
|
||
<div class="container">
|
||
<div class="text-center mb-5" data-aos="fade-up">
|
||
<h2 class="section-title" data-i18n="catalog.title">Nuestro Catálogo</h2>
|
||
<p class="section-subtitle" data-i18n="catalog.subtitle">Descubre nuestra selección de propiedades en Tenerife</p>
|
||
</div>
|
||
|
||
<!-- Catalog Tabs -->
|
||
<div class="catalog-tabs" data-aos="fade-up">
|
||
<button class="catalog-tab active" data-filter="all" data-i18n="catalog.tab.all">Todos</button>
|
||
<button class="catalog-tab" data-filter="agricultural" data-i18n="catalog.tab.agricultural">Terrenos Agrícolas</button>
|
||
<button class="catalog-tab" data-filter="urban" data-i18n="catalog.tab.urban">Terrenos Urbanos</button>
|
||
<button class="catalog-tab" data-filter="house" data-i18n="catalog.tab.houses">Casas</button>
|
||
<button class="catalog-tab" data-filter="apartment" data-i18n="catalog.tab.apartments">Apartamentos</button>
|
||
<button class="catalog-tab" data-filter="ruins" data-i18n="catalog.tab.ruins">Ruinas</button>
|
||
</div>
|
||
|
||
<div class="row">
|
||
<!-- Filters Sidebar -->
|
||
<div class="col-lg-3" data-aos="fade-right">
|
||
<div class="filters-section">
|
||
<h5 class="mb-4"><i class="bi bi-funnel me-2"></i><span data-i18n="filters.title">Filtros</span></h5>
|
||
<div class="filter-group">
|
||
<label data-i18n="filters.price">Precio</label>
|
||
<div class="row g-2">
|
||
<div class="col-6"><input type="number" class="form-control" id="priceMin" placeholder="Min €" value="20000"></div>
|
||
<div class="col-6"><input type="number" class="form-control" id="priceMax" placeholder="Max €" value="2000000"></div>
|
||
</div>
|
||
</div>
|
||
<div class="filter-group">
|
||
<label data-i18n="filters.area">Superficie (m²)</label>
|
||
<div class="row g-2">
|
||
<div class="col-6"><input type="number" class="form-control" id="areaMin" placeholder="Min" value="500"></div>
|
||
<div class="col-6"><input type="number" class="form-control" id="areaMax" placeholder="Max" value="50000"></div>
|
||
</div>
|
||
</div>
|
||
<div class="filter-group">
|
||
<label data-i18n="filters.utilities">Comunicaciones</label>
|
||
<div class="d-flex flex-column gap-2">
|
||
<label class="filter-checkbox"><input type="checkbox" id="filterWater" checked><i class="bi bi-droplet-fill"></i><span data-i18n="filters.water">Agua</span></label>
|
||
<label class="filter-checkbox"><input type="checkbox" id="filterElectricity" checked><i class="bi bi-lightning-fill"></i><span data-i18n="filters.electricity">Electricidad</span></label>
|
||
<label class="filter-checkbox"><input type="checkbox" id="filterRoad"><i class="bi bi-signpost-split-fill"></i><span data-i18n="filters.road">Acceso rodado</span></label>
|
||
</div>
|
||
</div>
|
||
<div class="filter-group">
|
||
<label data-i18n="filters.features">Características</label>
|
||
<div class="d-flex flex-column gap-2">
|
||
<label class="filter-checkbox"><input type="checkbox" id="filterRuins"><i class="bi bi-house-dash-fill"></i><span data-i18n="filters.hasRuins">Con ruinas/edificación</span></label>
|
||
<label class="filter-checkbox"><input type="checkbox" id="filterLicense"><i class="bi bi-file-earmark-check-fill"></i><span data-i18n="filters.license">Licencia de obras</span></label>
|
||
<label class="filter-checkbox"><input type="checkbox" id="filterSeaView"><i class="bi bi-water"></i><span data-i18n="filters.seaView">Vista al mar</span></label>
|
||
</div>
|
||
</div>
|
||
<button class="btn btn-primary-custom w-100 mt-3" id="applyFilters"><i class="bi bi-check-lg me-2"></i><span data-i18n="filters.apply">Aplicar Filtros</span></button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Properties Grid -->
|
||
<div class="col-lg-9">
|
||
<div class="d-flex justify-content-end mb-3">
|
||
<div class="view-toggle">
|
||
<button class="view-btn active" data-view="grid"><i class="bi bi-grid-3x3-gap"></i></button>
|
||
<button class="view-btn" data-view="map"><i class="bi bi-map"></i></button>
|
||
</div>
|
||
</div>
|
||
<div id="gridView">
|
||
<div class="row" id="propertiesGrid"></div>
|
||
<nav aria-label="Catalog pagination" class="mt-4">
|
||
<ul class="pagination justify-content-center" id="paginationControls"></ul>
|
||
</nav>
|
||
</div>
|
||
<div id="mapView" style="display: none;">
|
||
<div class="map-container"><div id="map"></div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ WHY BUY ============ -->
|
||
<section class="section-padding" style="background: linear-gradient(180deg, #ffffff 0%, #f8f9fa 100%); padding: 80px 0;">
|
||
<div class="container">
|
||
<div class="text-center mb-5" data-aos="fade-up">
|
||
<span style="display: inline-block; background: var(--primary); color: white; padding: 6px 20px; border-radius: 50px; font-size: 0.8rem; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 15px;" data-i18n="why.label">Garantía de confianza</span>
|
||
<h2 class="section-title" data-i18n="why.title">¿Por qué comprar con nosotros?</h2>
|
||
<p class="section-subtitle" data-i18n="why.subtitle">Más de 12 años de experiencia en el mercado inmobiliario de Tenerife</p>
|
||
</div>
|
||
<div class="row g-4">
|
||
<div class="col-lg-4 col-md-6" data-aos="fade-up" data-aos-delay="0">
|
||
<div style="background: white; border-radius: 20px; padding: 40px 30px; text-align: center; box-shadow: var(--shadow); transition: all 0.3s ease; height: 100%; border: 2px solid transparent;"
|
||
onmouseover="this.style.borderColor='var(--primary)'; this.style.transform='translateY(-8px)'" onmouseout="this.style.borderColor='transparent'; this.style.transform=''">
|
||
<div style="width: 80px; height: 80px; background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%); border-radius: 20px; display: flex; align-items: center; justify-content: center; margin: 0 auto 25px;">
|
||
<i class="bi bi-file-earmark-check" style="font-size: 2rem; color: white;"></i>
|
||
</div>
|
||
<h4 style="font-size: 1.2rem; margin-bottom: 15px;" data-i18n="why.card1.title">Documentación verificada</h4>
|
||
<p style="color: var(--gray); font-size: 0.95rem; line-height: 1.7; margin: 0;" data-i18n="why.card1.text">Todas nuestras propiedades pasan una rigurosa verificación legal. Trabajamos directamente con abogados y notarios para garantizar la seguridad de tu compra.</p>
|
||
</div>
|
||
</div>
|
||
<div class="col-lg-4 col-md-6" data-aos="fade-up" data-aos-delay="100">
|
||
<div style="background: white; border-radius: 20px; padding: 40px 30px; text-align: center; box-shadow: var(--shadow); transition: all 0.3s ease; height: 100%; border: 2px solid transparent;"
|
||
onmouseover="this.style.borderColor='var(--primary)'; this.style.transform='translateY(-8px)'" onmouseout="this.style.borderColor='transparent'; this.style.transform=''">
|
||
<div style="width: 80px; height: 80px; background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%); border-radius: 20px; display: flex; align-items: center; justify-content: center; margin: 0 auto 25px;">
|
||
<i class="bi bi-globe" style="font-size: 2rem; color: white;"></i>
|
||
</div>
|
||
<h4 style="font-size: 1.2rem; margin-bottom: 15px;" data-i18n="why.card2.title">Especialistas en extranjeros</h4>
|
||
<p style="color: var(--gray); font-size: 0.95rem; line-height: 1.7; margin: 0;" data-i18n="why.card2.text">Hablamos español, ruso e inglés. Te acompañamos en todo el proceso: desde la búsqueda hasta la obtención de la residencia en España.</p>
|
||
</div>
|
||
</div>
|
||
<div class="col-lg-4 col-md-6" data-aos="fade-up" data-aos-delay="200">
|
||
<div style="background: white; border-radius: 20px; padding: 40px 30px; text-align: center; box-shadow: var(--shadow); transition: all 0.3s ease; height: 100%; border: 2px solid transparent;"
|
||
onmouseover="this.style.borderColor='var(--primary)'; this.style.transform='translateY(-8px)'" onmouseout="this.style.borderColor='transparent'; this.style.transform=''">
|
||
<div style="width: 80px; height: 80px; background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%); border-radius: 20px; display: flex; align-items: center; justify-content: center; margin: 0 auto 25px;">
|
||
<i class="bi bi-shield-check" style="font-size: 2rem; color: white;"></i>
|
||
</div>
|
||
<h4 style="font-size: 1.2rem; margin-bottom: 15px;" data-i18n="why.card3.title">Sin sorpresas</h4>
|
||
<p style="color: var(--gray); font-size: 0.95rem; line-height: 1.7; margin: 0;" data-i18n="why.card3.text">Fotos reales, medidas exactas y descripciones detalladas. Ofrecemos visitas virtuales de 360° y tours in-situ antes de cualquier decisión.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="row mt-4 g-4 justify-content-center">
|
||
<div class="col-lg-4 col-md-6" data-aos="fade-up" data-aos-delay="300">
|
||
<div style="background: white; border-radius: 20px; padding: 40px 30px; text-align: center; box-shadow: var(--shadow); transition: all 0.3s ease; height: 100%; border: 2px solid transparent;"
|
||
onmouseover="this.style.borderColor='var(--primary)'; this.style.transform='translateY(-8px)'" onmouseout="this.style.borderColor='transparent'; this.style.transform=''">
|
||
<div style="width: 80px; height: 80px; background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%); border-radius: 20px; display: flex; align-items: center; justify-content: center; margin: 0 auto 25px;">
|
||
<i class="bi bi-hand-thumbs-up" style="font-size: 2rem; color: white;"></i>
|
||
</div>
|
||
<h4 style="font-size: 1.2rem; margin-bottom: 15px;" data-i18n="why.card4.title">Precio justo</h4>
|
||
<p style="color: var(--gray); font-size: 0.95rem; line-height: 1.7; margin: 0;" data-i18n="why.card4.text">Analizamos el mercado diariamente para ofrecerte propiedades al mejor precio. Sin comisiones ocultas ni costes inesperados.</p>
|
||
</div>
|
||
</div>
|
||
<div class="col-lg-4 col-md-6" data-aos="fade-up" data-aos-delay="400">
|
||
<div style="background: white; border-radius: 20px; padding: 40px 30px; text-align: center; box-shadow: var(--shadow); transition: all 0.3s ease; height: 100%; border: 2px solid transparent;"
|
||
onmouseover="this.style.borderColor='var(--primary)'; this.style.transform='translateY(-8px)'" onmouseout="this.style.borderColor='transparent'; this.style.transform=''">
|
||
<div style="width: 80px; height: 80px; background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%); border-radius: 20px; display: flex; align-items: center; justify-content: center; margin: 0 auto 25px;">
|
||
<i class="bi bi-headset" style="font-size: 2rem; color: white;"></i>
|
||
</div>
|
||
<h4 style="font-size: 1.2rem; margin-bottom: 15px;" data-i18n="why.card5.title">Acompañamiento total</h4>
|
||
<p style="color: var(--gray); font-size: 0.95rem; line-height: 1.7; margin: 0;" data-i18n="why.card5.text">Te ayudamos con financiación, trámites de NIE, contratos y post-venta. Estarás acompañado en cada paso del proceso de compra.</p>
|
||
</div>
|
||
</div>
|
||
<div class="col-lg-4 col-md-6" data-aos="fade-up" data-aos-delay="500">
|
||
<div style="background: white; border-radius: 20px; padding: 40px 30px; text-align: center; box-shadow: var(--shadow); transition: all 0.3s ease; height: 100%; border: 2px solid transparent;"
|
||
onmouseover="this.style.borderColor='var(--primary)'; this.style.transform='translateY(-8px)'" onmouseout="this.style.borderColor='transparent'; this.style.transform=''">
|
||
<div style="width: 80px; height: 80px; background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%); border-radius: 20px; display: flex; align-items: center; justify-content: center; margin: 0 auto 25px;">
|
||
<i class="bi bi-map" style="font-size: 2rem; color: white;"></i>
|
||
</div>
|
||
<h4 style="font-size: 1.2rem; margin-bottom: 15px;" data-i18n="why.card6.title">Conocemos cada zona</h4>
|
||
<p style="color: var(--gray); font-size: 0.95rem; line-height: 1.7; margin: 0;" data-i18n="why.card6.text">Expertos locales con más de 15 años viviendo en Tenerife. Te asesoramos sobre microclimas, urbanismo y zonas con mejor inversión.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="text-center mt-5" data-aos="fade-up">
|
||
<div style="display: inline-flex; align-items: center; gap: 30px; background: white; padding: 30px 50px; border-radius: 20px; box-shadow: var(--shadow);">
|
||
<div><span style="font-size: 2rem; font-weight: 800; color: var(--primary); display: block;">500+</span><small style="color: var(--gray);" data-i18n="why.stats.props">Propiedades vendidas</small></div>
|
||
<div style="width: 1px; height: 50px; background: #eee;"></div>
|
||
<div><span style="font-size: 2rem; font-weight: 800; color: var(--primary); display: block;">98%</span><small style="color: var(--gray);" data-i18n="why.stats.satisfied">Clientes satisfechos</small></div>
|
||
<div style="width: 1px; height: 50px; background: #eee;"></div>
|
||
<div><span style="font-size: 2rem; font-weight: 800; color: var(--primary); display: block;">12+</span><small style="color: var(--gray);" data-i18n="why.stats.years">Años de experiencia</small></div>
|
||
<div style="width: 1px; height: 50px; background: #eee;"></div>
|
||
<div><span style="font-size: 2rem; font-weight: 800; color: var(--primary); display: block;">24h</span><small style="color: var(--gray);" data-i18n="why.stats.response">Respuesta garantizada</small></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ HOW IT WORKS ============ -->
|
||
<section style="background: white; padding: 80px 0;">
|
||
<div class="container">
|
||
<div class="text-center mb-5" data-aos="fade-up">
|
||
<span style="display: inline-block; background: var(--primary); color: white; padding: 6px 20px; border-radius: 50px; font-size: 0.8rem; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 15px;" data-i18n="how.label">Proceso simple</span>
|
||
<h2 class="section-title" data-i18n="how.title">¿Cómo funciona?</h2>
|
||
<p class="section-subtitle" data-i18n="how.subtitle">Comprar una propiedad en Tenerife es más fácil de lo que piensas</p>
|
||
</div>
|
||
<div class="row g-4 align-items-center">
|
||
<div class="col-lg-4" data-aos="fade-up" data-aos-delay="0">
|
||
<div style="text-align: center; padding: 40px 20px;">
|
||
<div style="width: 90px; height: 90px; background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%); border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 25px; box-shadow: 0 10px 30px rgba(26,95,74,0.3);">
|
||
<i class="bi bi-search" style="font-size: 2.2rem; color: white;"></i>
|
||
</div>
|
||
<span style="display: inline-block; background: var(--secondary); color: var(--dark); padding: 4px 14px; border-radius: 50px; font-size: 0.75rem; font-weight: 700; margin-bottom: 15px;"><span data-i18n="how.step1.badge">Paso 01</span></span>
|
||
<h4 style="font-size: 1.3rem; margin-bottom: 12px;" data-i18n="how.step1.title">Filtra y encuentra</h4>
|
||
<p style="color: var(--gray); font-size: 0.95rem; line-height: 1.7; margin: 0;" data-i18n="how.step1.text">Usa nuestros filtros para descubrir propiedades que se adapten a tu presupuesto, ubicación y necesidades. Explora fotos, mapas y características.</p>
|
||
</div>
|
||
</div>
|
||
<div class="col-lg-4" data-aos="fade-up" data-aos-delay="150">
|
||
<div style="text-align: center; padding: 40px 20px;">
|
||
<div style="width: 90px; height: 90px; background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%); border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 25px; box-shadow: 0 10px 30px rgba(26,95,74,0.3);">
|
||
<i class="bi bi-camera-video" style="font-size: 2.2rem; color: white;"></i>
|
||
</div>
|
||
<span style="display: inline-block; background: var(--secondary); color: var(--dark); padding: 4px 14px; border-radius: 50px; font-size: 0.75rem; font-weight: 700; margin-bottom: 15px;"><span data-i18n="how.step2.badge">Paso 02</span></span>
|
||
<h4 style="font-size: 1.3rem; margin-bottom: 12px;" data-i18n="how.step2.title">Visita presencial o virtual</h4>
|
||
<p style="color: var(--gray); font-size: 0.95rem; line-height: 1.7; margin: 0;" data-i18n="how.step2.text">Agenda una visita guiada en persona o desde donde estés. Te mostramos cada detalle, respondemos preguntas y damos información sobre la zona.</p>
|
||
</div>
|
||
</div>
|
||
<div class="col-lg-4" data-aos="fade-up" data-aos-delay="300">
|
||
<div style="text-align: center; padding: 40px 20px;">
|
||
<div style="width: 90px; height: 90px; background: linear-gradient(135deg, var(--primary) 0%, var(--primary-light) 100%); border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 25px; box-shadow: 0 10px 30px rgba(26,95,74,0.3);">
|
||
<i class="bi bi-key" style="font-size: 2.2rem; color: white;"></i>
|
||
</div>
|
||
<span style="display: inline-block; background: var(--secondary); color: var(--dark); padding: 4px 14px; border-radius: 50px; font-size: 0.75rem; font-weight: 700; margin-bottom: 15px;"><span data-i18n="how.step3.badge">Paso 03</span></span>
|
||
<h4 style="font-size: 1.3rem; margin-bottom: 12px;" data-i18n="how.step3.title">Compra con seguridad</h4>
|
||
<p style="color: var(--gray); font-size: 0.95rem; line-height: 1.7; margin: 0;" data-i18n="how.step3.text">Te ayudamos con toda la documentación: NIE, contratos, registro y financiación. Recibes acompañamiento legal hasta que la propiedad sea tuya.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="text-center mt-5" data-aos="fade-up">
|
||
<a href="https://wa.me/34600123456" target="_blank" class="btn btn-primary-custom" data-i18n="how.cta">
|
||
<i class="bi bi-whatsapp me-2"></i>Quiero agendar una visita
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ CTA HELP ============ -->
|
||
<section style="background: linear-gradient(135deg, var(--primary-dark) 0%, var(--primary) 50%, var(--primary-light) 100%); padding: 80px 0; position: relative; overflow: hidden;">
|
||
<div style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: url('https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?w=1920&q=80') center/cover no-repeat; opacity: 0.1;"></div>
|
||
<div class="container" style="position: relative; z-index: 2;">
|
||
<div class="row align-items-center">
|
||
<div class="col-lg-7" data-aos="fade-right">
|
||
<h2 style="font-size: 2.5rem; font-weight: 800; color: white; margin-bottom: 20px;" data-i18n="cta.title">¿Necesitas ayuda para encontrar lo ideal?</h2>
|
||
<p style="font-size: 1.1rem; color: rgba(255,255,255,0.85); margin-bottom: 25px; line-height: 1.7;" data-i18n="cta.subtitle">Nuestros asesores te escuchan y buscan propiedades a tu medida. Sin compromiso. Te contactamos en menos de 24 horas.</p>
|
||
<ul style="list-style: none; padding: 0; margin: 0;">
|
||
<li style="color: rgba(255,255,255,0.9); margin-bottom: 10px;"><i class="bi bi-check-circle-fill me-2" style="color: var(--secondary);"></i><span data-i18n="cta.benefit1">Asesoramiento personalizado gratuito</span></li>
|
||
<li style="color: rgba(255,255,255,0.9); margin-bottom: 10px;"><i class="bi bi-check-circle-fill me-2" style="color: var(--secondary);"></i><span data-i18n="cta.benefit2">Selección de propiedades a tu medida</span></li>
|
||
<li style="color: rgba(255,255,255,0.9); margin-bottom: 10px;"><i class="bi bi-check-circle-fill me-2" style="color: var(--secondary);"></i><span data-i18n="cta.benefit3">Resolución de dudas sobre trámites</span></li>
|
||
</ul>
|
||
</div>
|
||
<div class="col-lg-5" data-aos="fade-left">
|
||
<div style="background: white; border-radius: 24px; padding: 40px; box-shadow: var(--shadow-lg);">
|
||
<h4 style="margin-bottom: 20px; color: var(--dark);" data-i18n="cta.form.title">Solicitar asesoramiento</h4>
|
||
<form id="ctaForm" onsubmit="event.preventDefault(); alert('Gracias. Te contactamos pronto.');">
|
||
<input type="text" class="form-control" placeholder="Tu nombre" required style="margin-bottom: 15px;" data-i18n="cta.form.name" data-i18n-attr="placeholder">
|
||
<input type="email" class="form-control" placeholder="Email" required style="margin-bottom: 15px;" data-i18n="cta.form.email" data-i18n-attr="placeholder">
|
||
<input type="tel" class="form-control" placeholder="Teléfono / WhatsApp" style="margin-bottom: 15px;" data-i18n="cta.form.phone" data-i18n-attr="placeholder">
|
||
<select class="form-select" style="margin-bottom: 20px;">
|
||
<option data-i18n="cta.form.select.default">¿Qué buscas?</option>
|
||
<option data-i18n="cta.form.select.agricultural">Terreno agrícola</option>
|
||
<option data-i18n="cta.form.select.urban">Terreno urbano</option>
|
||
<option data-i18n="cta.form.select.house">Casa o villa</option>
|
||
<option data-i18n="cta.form.select.apartment">Apartamento</option>
|
||
<option data-i18n="cta.form.select.unknown">No lo tengo claro</option>
|
||
</select>
|
||
<button type="submit" class="btn btn-primary-custom w-100" style="font-size: 1rem;">
|
||
<i class="bi bi-send me-2"></i><span data-i18n="cta.form.submit">Enviar solicitud</span>
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ FAQ BUYING ============ -->
|
||
<section style="background: #f8f9fa; padding: 80px 0;">
|
||
<div class="container">
|
||
<div class="text-center mb-5" data-aos="fade-up">
|
||
<span style="display: inline-block; background: var(--primary); color: white; padding: 6px 20px; border-radius: 50px; font-size: 0.8rem; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 15px;" data-i18n="faq.label">Dudas frecuentes</span>
|
||
<h2 class="section-title" data-i18n="faq.title">Preguntas sobre la compra</h2>
|
||
<p class="section-subtitle" data-i18n="faq.subtitle">Resolvemos las dudas más comunes de nuestros compradores</p>
|
||
</div>
|
||
<div class="row justify-content-center">
|
||
<div class="col-lg-8">
|
||
<div class="accordion" id="faqAccordion" data-aos="fade-up">
|
||
<div class="accordion-item" style="border: none; margin-bottom: 15px; border-radius: 15px !important; overflow: hidden; box-shadow: 0 5px 20px rgba(0,0,0,0.05);">
|
||
<h2 class="accordion-header">
|
||
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#faq1" data-i18n="faq.q1">¿Puedo comprar siendo extranjero?</button>
|
||
</h2>
|
||
<div id="faq1" class="accordion-collapse collapse show" data-bs-parent="#faqAccordion">
|
||
<div class="accordion-body" data-i18n="faq.a1">Sí. Cualquier persona puede comprar propiedad en España. Solo necesitas obtener el NIE (Número de Identificación de Extranjero), lo cual gestionamos nosotros en 1–2 semanas.</div>
|
||
</div>
|
||
</div>
|
||
<div class="accordion-item" style="border: none; margin-bottom: 15px; border-radius: 15px !important; overflow: hidden; box-shadow: 0 5px 20px rgba(0,0,0,0.05);">
|
||
<h2 class="accordion-header">
|
||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#faq2" data-i18n="faq.q2">¿Qué impuestos debo pagar?</button>
|
||
</h2>
|
||
<div id="faq2" class="accordion-collapse collapse" data-bs-parent="#faqAccordion">
|
||
<div class="accordion-body" data-i18n="faq.a2">Principalmente el ITP (Impuesto de Transmisiones Patrimoniales), notaría y registro. Te preparamos un desglose claro antes de firmar nada: sin sorpresas.</div>
|
||
</div>
|
||
</div>
|
||
<div class="accordion-item" style="border: none; margin-bottom: 15px; border-radius: 15px !important; overflow: hidden; box-shadow: 0 5px 20px rgba(0,0,0,0.05);">
|
||
<h2 class="accordion-header">
|
||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#faq3" data-i18n="faq.q3">¿La propiedad tiene agua y luz?</button>
|
||
</h2>
|
||
<div id="faq3" class="accordion-collapse collapse" data-bs-parent="#faqAccordion">
|
||
<div class="accordion-body" data-i18n="faq.a3">Cada ficha indica claramente qué servicios disponibles tiene (agua, electricidad, acceso rodado). Te ayudamos a conectar los que falten o a valorar el coste de hacerlo.</div>
|
||
</div>
|
||
</div>
|
||
<div class="accordion-item" style="border: none; margin-bottom: 15px; border-radius: 15px !important; overflow: hidden; box-shadow: 0 5px 20px rgba(0,0,0,0.05);">
|
||
<h2 class="accordion-header">
|
||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#faq4" data-i18n="faq.q4">¿Cómo es el clima en cada zona?</button>
|
||
</h2>
|
||
<div id="faq4" class="accordion-collapse collapse" data-bs-parent="#faqAccordion">
|
||
<div class="accordion-body" data-i18n="faq.a4">Tenerife tiene múltiples microclimas. El sur (Adeje, Arona) es más soleado y cálido, mientras que el norte (La Orotava, Puerto de la Cruz) es más verde y húmedo. Asesoramos según tus preferencias.</div>
|
||
</div>
|
||
</div>
|
||
<div class="accordion-item" style="border: none; margin-bottom: 15px; border-radius: 15px !important; overflow: hidden; box-shadow: 0 5px 20px rgba(0,0,0,0.05);">
|
||
<h2 class="accordion-header">
|
||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#faq5" data-i18n="faq.q5">¿Cuánto tarda el proceso de compra?</button>
|
||
</h2>
|
||
<div id="faq5" class="accordion-collapse collapse" data-bs-parent="#faqAccordion">
|
||
<div class="accordion-body" data-i18n="faq.a5">Desde la reserva hasta la escritura suelen ser 4–6 semanas. Si el NIE ya está tramitado y la financiación lista, puede acortarse a 2–3 semanas.</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ============ FOOTER ============ -->
|
||
<footer>
|
||
<div class="container">
|
||
<div class="row g-4">
|
||
<div class="col-lg-4">
|
||
<div class="footer-brand">Tenerife<span>Prop</span></div>
|
||
<p class="footer-about" data-i18n="footer.about">Su socio de confianza en la compra de propiedades en Tenerife. Más de 12 años ayudando a clientes de todo el mundo a encontrar su hogar en el paraíso.</p>
|
||
<div class="social-links">
|
||
<a href="#" class="social-link"><i class="bi bi-facebook"></i></a>
|
||
<a href="#" class="social-link"><i class="bi bi-instagram"></i></a>
|
||
<a href="#" class="social-link"><i class="bi bi-youtube"></i></a>
|
||
<a href="#" class="social-link"><i class="bi bi-telegram"></i></a>
|
||
</div>
|
||
</div>
|
||
<div class="col-lg-2 col-md-4">
|
||
<h5 class="footer-title" data-i18n="footer.navigation">Navegación</h5>
|
||
<ul class="footer-links">
|
||
<li><a href="/" data-i18n="nav.home">Inicio</a></li>
|
||
<li><a href="/catalog.html" data-i18n="nav.catalog">Catálogo</a></li>
|
||
<li><a href="/#services" data-i18n="nav.services">Servicios</a></li>
|
||
<li><a href="/#testimonials" data-i18n="nav.testimonials">Testimonios</a></li>
|
||
<li><a href="/#contact" data-i18n="nav.contact">Contacto</a></li>
|
||
</ul>
|
||
</div>
|
||
<div class="col-lg-3 col-md-4">
|
||
<h5 class="footer-title" data-i18n="footer.properties">Propiedades</h5>
|
||
<ul class="footer-links">
|
||
<li><a href="/catalog.html?type=agricultural" data-i18n="footer.terrain">Terrenos agrícolas</a></li>
|
||
<li><a href="/catalog.html?type=urban" data-i18n="footer.urban">Terrenos urbanos</a></li>
|
||
<li><a href="/catalog.html?type=house" data-i18n="footer.houses">Casas y villas</a></li>
|
||
<li><a href="/catalog.html?type=apartment" data-i18n="footer.apartments">Apartamentos</a></li>
|
||
<li><a href="/catalog.html?type=ruins" data-i18n="footer.ruins">Ruinas</a></li>
|
||
</ul>
|
||
</div>
|
||
<div class="col-lg-3 col-md-4">
|
||
<h5 class="footer-title" data-i18n="footer.contact">Contacto</h5>
|
||
<div class="footer-contact-item"><i class="bi bi-geo-alt"></i><span>Adeje, Tenerife, España</span></div>
|
||
<div class="footer-contact-item"><i class="bi bi-telephone"></i><span>+34 922 123 456</span></div>
|
||
<div class="footer-contact-item"><i class="bi bi-envelope"></i><span>info@tenerifeprop.com</span></div>
|
||
<div class="footer-contact-item"><i class="bi bi-whatsapp"></i><span>+34 600 123 456</span></div>
|
||
</div>
|
||
</div>
|
||
<div class="footer-bottom">
|
||
<p>© 2024 TenerifeProp. <span data-i18n="footer.rights">Todos los derechos reservados.</span></p>
|
||
<div class="footer-legal">
|
||
<a href="#" data-i18n="footer.privacy">Política de Privacidad</a>
|
||
<a href="#" data-i18n="footer.terms">Términos de Uso</a>
|
||
<a href="#" data-i18n="footer.cookies">Cookies</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
|
||
<!-- ============ PROPERTY MODAL ============ -->
|
||
<div class="modal fade property-modal" id="propertyModal" tabindex="-1">
|
||
<div class="modal-dialog modal-lg modal-dialog-centered">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<div class="modal-gallery">
|
||
<div class="modal-gallery-slider" id="modalGallerySlider"></div>
|
||
<button class="gallery-arrow prev" id="galleryPrev"><i class="bi bi-chevron-left"></i></button>
|
||
<button class="gallery-arrow next" id="galleryNext"><i class="bi bi-chevron-right"></i></button>
|
||
<div class="gallery-controls" id="galleryDots"></div>
|
||
</div>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<span class="property-type" id="modalType"></span>
|
||
<h3 class="modal-property-title" id="modalTitle"></h3>
|
||
<p class="modal-property-location" id="modalLocation"></p>
|
||
<div class="modal-price" id="modalPrice"></div>
|
||
<div class="modal-features" id="modalFeatures"></div>
|
||
<h5 class="mb-3"><i class="bi bi-tools me-2"></i><span data-i18n="modal.utilities">Comunicaciones</span></h5>
|
||
<div class="modal-utilities" id="modalUtilities"></div>
|
||
<div class="d-flex gap-2 mt-4 flex-wrap">
|
||
<a href="#" class="modal-view-details flex-fill" id="modalViewDetails" data-i18n="modal.details"><i class="bi bi-eye me-2"></i>Ver Detalles</a>
|
||
<a href="#" class="btn btn-primary-custom flex-fill" id="modalSchedule" data-i18n="modal.schedule"><i class="bi bi-calendar-check me-2"></i>Agendar Visita</a>
|
||
<a href="#" class="btn btn-whatsapp flex-fill" id="modalWhatsapp" target="_blank"><i class="bi bi-whatsapp me-1"></i>WhatsApp</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ============ WHATSAPP FLOAT ============ -->
|
||
<div class="whatsapp-float">
|
||
<a href="https://wa.me/34600123456" class="whatsapp-btn" target="_blank" title="WhatsApp"><i class="bi bi-whatsapp"></i></a>
|
||
</div>
|
||
|
||
<!-- Scripts -->
|
||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/aos@2.3.4/dist/aos.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.min.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/leaflet.markercluster@1.5.3/dist/leaflet.markercluster.min.js"></script>
|
||
<script src="/js/navigation.js"></script>
|
||
|
||
<script>
|
||
const translations = {
|
||
es: {
|
||
brand: 'Tenerife<span>Prop</span>',
|
||
nav: { home: 'Inicio', catalog: 'Catálogo', services: 'Servicios', testimonials: 'Testimonios', contact: 'Contacto' },
|
||
hero: {
|
||
badge: 'Propiedad destacada', title: 'Encuentra tu propiedad ideal en Tenerife',
|
||
subtitle: 'Más de 500 propiedades seleccionadas: terrenos agrícolas, urbanos, casas, apartamentos y ruinas con documentación verificada.',
|
||
cta: 'Ver catálogo'
|
||
},
|
||
cat: {
|
||
agricultural: 'Agrícolas', agriculturalCount: '45 disponibles',
|
||
urban: 'Urbanos', urbanCount: '32 disponibles',
|
||
houses: 'Casas', housesCount: '28 disponibles',
|
||
apartments: 'Apartamentos', apartmentsCount: '56 disponibles',
|
||
ruins: 'Ruinas', ruinsCount: '18 disponibles'
|
||
},
|
||
catalog: {
|
||
title: 'Nuestro Catálogo', subtitle: 'Descubre nuestra selección de propiedades en Tenerife',
|
||
tab: { all: 'Todos', agricultural: 'Terrenos Agrícolas', urban: 'Terrenos Urbanos', houses: 'Casas', apartments: 'Apartamentos', ruins: 'Ruinas' }
|
||
},
|
||
filters: {
|
||
title: 'Filtros', price: 'Precio', area: 'Superficie (m²)', utilities: 'Comunicaciones',
|
||
water: 'Agua', electricity: 'Electricidad', road: 'Acceso rodado', features: 'Características',
|
||
hasRuins: 'Con ruinas/edificación', license: 'Licencia de obras', seaView: 'Vista al mar', apply: 'Aplicar Filtros'
|
||
},
|
||
property: { area: 'm²', details: 'Ver Detalles', favorite: 'Añadir a favoritos' },
|
||
footer: {
|
||
about: 'Su socio de confianza en la compra de propiedades en Tenerife. Más de 12 años ayudando a clientes de todo el mundo a encontrar su hogar en el paraíso.',
|
||
navigation: 'Navegación', properties: 'Propiedades', contact: 'Contacto',
|
||
terrain: 'Terrenos agrícolas', urban: 'Terrenos urbanos', houses: 'Casas y villas', apartments: 'Apartamentos', ruins: 'Ruinas',
|
||
rights: 'Todos los derechos reservados.', privacy: 'Política de Privacidad', terms: 'Términos de Uso', cookies: 'Cookies'
|
||
},
|
||
modal: {
|
||
utilities: 'Comunicaciones', schedule: '<i class="bi bi-calendar-check me-2"></i>Agendar Visita',
|
||
details: '<i class="bi bi-eye me-2"></i>Ver Detalles', area: 'Superficie', rooms: 'Habitaciones', bathrooms: 'Baños', parking: 'Plazas de garaje',
|
||
seaView: 'Vista al mar', hasWater: 'Agua disponible', noWater: 'Agua no disponible', hasElectricity: 'Electricidad disponible',
|
||
noElectricity: 'Electricidad no disponible', hasRoad: 'Acceso rodado', noRoad: 'Sin acceso rodado',
|
||
withRuins: 'Con ruinas/edificación', hasLicense: 'Licencia de obras', noLicense: 'Sin licencia'
|
||
},
|
||
why: {
|
||
label: 'Garantía de confianza', title: '¿Por qué comprar con nosotros?', subtitle: 'Más de 12 años de experiencia en el mercado inmobiliario de Tenerife',
|
||
card1: { title: 'Documentación verificada', text: 'Todas nuestras propiedades pasan una rigurosa verificación legal. Trabajamos directamente con abogados y notarios para garantizar la seguridad de tu compra.' },
|
||
card2: { title: 'Especialistas en extranjeros', text: 'Hablamos español, ruso e inglés. Te acompañamos en todo el proceso: desde la búsqueda hasta la obtención de la residencia en España.' },
|
||
card3: { title: 'Sin sorpresas', text: 'Fotos reales, medidas exactas y descripciones detalladas. Ofrecemos visitas virtuales de 360° y tours in-situ antes de cualquier decisión.' },
|
||
card4: { title: 'Precio justo', text: 'Analizamos el mercado diariamente para ofrecerte propiedades al mejor precio. Sin comisiones ocultas ni costes inesperados.' },
|
||
card5: { title: 'Acompañamiento total', text: 'Te ayudamos con financiación, trámites de NIE, contratos y post-venta. Estarás acompañado en cada paso del proceso de compra.' },
|
||
card6: { title: 'Conocemos cada zona', text: 'Expertos locales con más de 15 años viviendo en Tenerife. Te asesoramos sobre microclimas, urbanismo y zonas con mejor inversión.' },
|
||
stats: { props: 'Propiedades vendidas', satisfied: 'Clientes satisfechos', years: 'Años de experiencia', response: 'Respuesta garantizada' }
|
||
},
|
||
how: {
|
||
label: 'Proceso simple', title: '¿Cómo funciona?', subtitle: 'Comprar una propiedad en Tenerife es más fácil de lo que piensas',
|
||
step1: { badge: 'Paso 01', title: 'Filtra y encuentra', text: 'Usa nuestros filtros para descubrir propiedades que se adapten a tu presupuesto, ubicación y necesidades. Explora fotos, mapas y características.' },
|
||
step2: { badge: 'Paso 02', title: 'Visita presencial o virtual', text: 'Agenda una visita guiada en persona o desde donde estés. Te mostramos cada detalle, respondemos preguntas y damos información sobre la zona.' },
|
||
step3: { badge: 'Paso 03', title: 'Compra con seguridad', text: 'Te ayudamos con toda la documentación: NIE, contratos, registro y financiación. Recibes acompañamiento legal hasta que la propiedad sea tuya.' },
|
||
cta: '<i class="bi bi-whatsapp me-2"></i>Quiero agendar una visita'
|
||
},
|
||
cta: {
|
||
title: '¿Necesitas ayuda para encontrar lo ideal?', subtitle: 'Nuestros asesores te escuchan y buscan propiedades a tu medida. Sin compromiso. Te contactamos en menos de 24 horas.',
|
||
benefit1: 'Asesoramiento personalizado gratuito', benefit2: 'Selección de propiedades a tu medida', benefit3: 'Resolución de dudas sobre trámites',
|
||
form: {
|
||
title: 'Solicitar asesoramiento', name: 'Tu nombre', email: 'Email', phone: 'Teléfono / WhatsApp',
|
||
select: { default: '¿Qué buscas?', agricultural: 'Terreno agrícola', urban: 'Terreno urbano', house: 'Casa o villa', apartment: 'Apartamento', unknown: 'No lo tengo claro' },
|
||
submit: '<i class="bi bi-send me-2"></i>Enviar solicitud'
|
||
}
|
||
},
|
||
faq: {
|
||
label: 'Dudas frecuentes', title: 'Preguntas sobre la compra', subtitle: 'Resolvemos las dudas más comunes de nuestros compradores',
|
||
q1: '¿Puedo comprar siendo extranjero?', a1: 'Sí. Cualquier persona puede comprar propiedad en España. Solo necesitas obtener el NIE (Número de Identificación de Extranjero), lo cual gestionamos nosotros en 1–2 semanas.',
|
||
q2: '¿Qué impuestos debo pagar?', a2: 'Principalmente el ITP (Impuesto de Transmisiones Patrimoniales), notaría y registro. Te preparamos un desglose claro antes de firmar nada: sin sorpresas.',
|
||
q3: '¿La propiedad tiene agua y luz?', a3: 'Cada ficha indica claramente qué servicios disponibles tiene (agua, electricidad, acceso rodado). Te ayudamos a conectar los que falten o a valorar el coste de hacerlo.',
|
||
q4: '¿Cómo es el clima en cada zona?', a4: 'Tenerife tiene múltiples microclimas. El sur (Adeje, Arona) es más soleado y cálido, mientras que el norte (La Orotava, Puerto de la Cruz) es más verde y húmedo. Asesoramos según tus preferencias.',
|
||
q5: '¿Cuánto tarda el proceso de compra?', a5: 'Desde la reserva hasta la escritura suelen ser 4–6 semanas. Si el NIE ya está tramitado y la financiación lista, puede acortarse a 2–3 semanas.'
|
||
},
|
||
form: { success: '¡Formulario enviado con éxito!', error: 'Error al enviar el formulario.' },
|
||
utility: { water: 'Agua', electricity: 'Electricidad', road: 'Acceso', yes: 'Sí', no: 'No' }
|
||
},
|
||
ru: {
|
||
brand: 'Tenerife<span>Prop</span>',
|
||
nav: { home: 'Главная', catalog: 'Каталог', services: 'Услуги', testimonials: 'Отзывы', contact: 'Контакты' },
|
||
hero: {
|
||
badge: 'Избранный объект', title: 'Найдите идеальную недвижимость на Тенерифе',
|
||
subtitle: 'Более 500 тщательно отобранных объектов: сельхоз- и городские участки, дома, апартаменты и руины с проверенной документацией.',
|
||
cta: 'Смотреть каталог'
|
||
},
|
||
cat: {
|
||
agricultural: 'Сельхоз', agriculturalCount: '45 доступно',
|
||
urban: 'Городские', urbanCount: '32 доступно',
|
||
houses: 'Дома', housesCount: '28 доступно',
|
||
apartments: 'Апартаменты', apartmentsCount: '56 доступно',
|
||
ruins: 'Руины', ruinsCount: '18 доступно'
|
||
},
|
||
catalog: {
|
||
title: 'Наш каталог', subtitle: 'Откройте для себя нашу подборку объектов на Тенерифе',
|
||
tab: { all: 'Все', agricultural: 'Сельхозучастки', urban: 'Городские участки', houses: 'Дома', apartments: 'Апартаменты', ruins: 'Руины' }
|
||
},
|
||
filters: {
|
||
title: 'Фильтры', price: 'Цена', area: 'Площадь (м²)', utilities: 'Коммуникации',
|
||
water: 'Вода', electricity: 'Электричество', road: 'Подъезд', features: 'Характеристики',
|
||
hasRuins: 'С руинами/постройками', license: 'Разрешение на стройку', seaView: 'Вид на море', apply: 'Применить фильтры'
|
||
},
|
||
property: { area: 'м²', details: 'Подробнее', favorite: 'В избранное' },
|
||
footer: {
|
||
about: 'Ваш надёжный партнёр в покупке недвижимости на Тенерифе. Более 12 лет помогаем клиентам со всего мира найти свой дом в раю.',
|
||
navigation: 'Навигация', properties: 'Объекты', contact: 'Контакты',
|
||
terrain: 'Сельхозучастки', urban: 'Городские участки', houses: 'Дома и виллы', apartments: 'Апартаменты', ruins: 'Руины',
|
||
rights: 'Все права защищены.', privacy: 'Политика конфиденциальности', terms: 'Условия использования', cookies: 'Файлы cookies'
|
||
},
|
||
modal: {
|
||
utilities: 'Коммуникации', schedule: 'Записаться на просмотр',
|
||
details: 'Смотреть объект', area: 'Площадь', rooms: 'Комнаты', bathrooms: 'Ванные', parking: 'Парковка',
|
||
seaView: 'Вид на море', hasWater: 'Вода подключена', noWater: 'Вода не подключена', hasElectricity: 'Электричество подключено',
|
||
noElectricity: 'Электричество не подключено', hasRoad: 'Подъезд', noRoad: 'Без подъезда',
|
||
withRuins: 'С руинами/постройками', hasLicense: 'Разрешение на строительство', noLicense: 'Без разрешения'
|
||
},
|
||
form: { success: 'Форма успешно отправлена!', error: 'Ошибка отправки формы.' },
|
||
why: {
|
||
label: 'Гарантия доверия', title: 'Почему покупать с нами?', subtitle: 'Более 12 лет опыта на рынке недвижимости Тенерифе',
|
||
card1: { title: 'Проверенная документация', text: 'Все наши объекты проходят строгую юридическую проверку. Мы работаем напрямую с адвокатами и нотариусами для гарантии безопасности вашей покупки.' },
|
||
card2: { title: 'Специалисты по работе с иностранцами', text: 'Мы говорим на испанском, русском и английском. Сопровождаем на всех этапах: от поиска до получения вида на жительство в Испании.' },
|
||
card3: { title: 'Без сюрпризов', text: 'Реальные фото, точные размеры и подробные описания. Предлагаем виртуальные туры 360° и выездные осмотры перед любым решением.' },
|
||
card4: { title: 'Справедливая цена', text: 'Анализируем рынок ежедневно, чтобы предлагать объекты по лучшей цене. Никаких скрытых комиссий и неожиданных расходов.' },
|
||
card5: { title: 'Полное сопровождение', text: 'Помогаем с финансированием, оформлением NIE, договорами и послепродажным обслуживанием. Вы будете сопровождены на каждом шагу покупки.' },
|
||
card6: { title: 'Знаем каждый район', text: 'Местные эксперты с более чем 15-летним стажем жизни на Тенерифе. Проконсультируем по микроклиматам, градостроительству и зонам с лучшими инвестициями.' },
|
||
stats: { props: 'Объектов продано', satisfied: 'Довольных клиентов', years: 'Лет опыта', response: 'Гарантия ответа' }
|
||
},
|
||
how: {
|
||
label: 'Простой процесс', title: 'Как это работает?', subtitle: 'Купить недвижимость на Тенерифе проще, чем вы думаете',
|
||
step1: { badge: 'Шаг 01', title: 'Найдите объект', text: 'Используйте наши фильтры, чтобы найти объекты по бюджету, местоположению и потребностям. Изучайте фото, карты и характеристики.' },
|
||
step2: { badge: 'Шаг 02', title: 'Осмотр: лично или онлайн', text: 'Запишитесь на экскурсию лично или удалённо. Покажем каждую деталь, ответим на вопросы и расскажем о районе.' },
|
||
step3: { badge: 'Шаг 03', title: 'Безопасная покупка', text: 'Помогаем со всей документацией: NIE, договоры, регистрация и финансирование. Юридическое сопровождение до оформления объекта на вас.' },
|
||
cta: '<i class="bi bi-whatsapp me-2"></i>Хочу записаться на просмотр'
|
||
},
|
||
cta: {
|
||
title: 'Нужна помощь в поиске идеального варианта?', subtitle: 'Наши консультанты выслушают вас и подберут объекты по вашим критериям. Без обязательств. Свяжемся с вами менее чем за 24 часа.',
|
||
benefit1: 'Бесплатная персональная консультация', benefit2: 'Подбор объектов по вашим критериям', benefit3: 'Ответы на вопросы по оформлению',
|
||
form: {
|
||
title: 'Запросить консультацию', name: 'Ваше имя', email: 'Email', phone: 'Телефон / WhatsApp',
|
||
select: { default: 'Что ищете?', agricultural: 'Сельхоз участок', urban: 'Городской участок', house: 'Дом или вилла', apartment: 'Апартаменты', unknown: 'Пока не определился' },
|
||
submit: '<i class="bi bi-send me-2"></i>Отправить запрос'
|
||
}
|
||
},
|
||
faq: {
|
||
label: 'Частые вопросы', title: 'Вопросы о покупке', subtitle: 'Отвечаем на самые распространённые вопросы наших покупателей',
|
||
q1: 'Могу ли я купить, будучи иностранцем?', a1: 'Да. Любой человек может купить недвижимость в Испании. Нужно только получить NIE (идентификационный номер иностранца), что мы оформляем за 1–2 недели.',
|
||
q2: 'Какие налоги нужно платить?', a2: 'В основном ITP (налог на передачу имущества), нотариус и регистрация. Подготовим прозрачный расчёт до подписания: без сюрпризов.',
|
||
q3: 'Есть ли вода и электричество?', a3: 'Каждая карточка чётко указывает доступные коммуникации (вода, электричество, подъезд). Поможем подключить отсутствующие или оценить стоимость.',
|
||
q4: 'Какой климат в разных районах?', a4: 'На Тенерифе множество микроклиматов. Юг (Адехе, Ароно) более солнечный и тёплый, а север (Ла-Оротава, Пуэрто-де-ла-Крус) — более зелёный и влажный. Проконсультируем по вашим предпочтениям.',
|
||
q5: 'Сколько длится процесс покупки?', a5: 'От бронирования до подписания обычно 4–6 недель. Если NIE уже оформлен и финансирование готово, можно сократить до 2–3 недель.'
|
||
},
|
||
utility: { water: 'Вода', electricity: 'Электричество', road: 'Подъезд', yes: 'Есть', no: 'Нет' }
|
||
}
|
||
};
|
||
|
||
let currentLang = 'es';
|
||
|
||
function escapeHtml(text) {
|
||
if (text == null) return '';
|
||
const div = document.createElement('div');
|
||
div.textContent = String(text);
|
||
return div.innerHTML;
|
||
}
|
||
|
||
// Properties Data
|
||
let properties = [];
|
||
let currentFilter = 'all';
|
||
let currentPage = 1;
|
||
const ITEMS_PER_PAGE = 12;
|
||
|
||
$(document).ready(function() {
|
||
AOS.init({ duration: 800, once: true, offset: 100 });
|
||
initMap();
|
||
loadProperties();
|
||
|
||
// Language switcher
|
||
$('.lang-btn').click(function() {
|
||
const lang = $(this).data('lang');
|
||
switchLanguage(lang);
|
||
});
|
||
|
||
// Catalog tabs
|
||
$('.catalog-tab').click(function() {
|
||
$('.catalog-tab').removeClass('active');
|
||
$(this).addClass('active');
|
||
const filter = $(this).data('filter');
|
||
filterProperties(filter);
|
||
});
|
||
|
||
// View toggle
|
||
$('.view-btn').click(function() {
|
||
$('.view-btn').removeClass('active');
|
||
$(this).addClass('active');
|
||
const view = $(this).data('view');
|
||
toggleView(view);
|
||
});
|
||
|
||
// Apply filters
|
||
$('#applyFilters').click(function() {
|
||
applyFilters();
|
||
});
|
||
});
|
||
|
||
function switchLanguage(lang) {
|
||
currentLang = lang;
|
||
$('html').attr('lang', lang);
|
||
$('.lang-btn').removeClass('active');
|
||
$(`.lang-btn[data-lang="${lang}"]`).addClass('active');
|
||
$('[data-i18n]').each(function() {
|
||
const key = $(this).data('i18n');
|
||
const value = getNestedValue(translations[lang], key);
|
||
if (!value) return;
|
||
const attr = $(this).data('i18n-attr');
|
||
if (attr) { $(this).attr(attr, value); }
|
||
else if ($(this).is('input:not([type="checkbox"]), textarea')) { $(this).attr('placeholder', value); }
|
||
else if ($(this).is('option')) { $(this).text(value); }
|
||
else { $(this).html(value); }
|
||
});
|
||
properties = [];
|
||
loadProperties();
|
||
}
|
||
|
||
function getNestedValue(obj, path) {
|
||
return path.split('.').reduce((acc, part) => acc && acc[part], obj);
|
||
}
|
||
|
||
// Map
|
||
let map;
|
||
let markersLayer;
|
||
function initMap() {
|
||
map = L.map('map').setView([28.2916, -16.6291], 10);
|
||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>', maxZoom: 18
|
||
}).addTo(map);
|
||
markersLayer = L.markerClusterGroup();
|
||
map.addLayer(markersLayer);
|
||
addMarkersToMap();
|
||
}
|
||
|
||
function addMarkersToMap() {
|
||
markersLayer.clearLayers();
|
||
properties.forEach(property => {
|
||
if (!property.lat || !property.lng) return;
|
||
const marker = L.marker([property.lat, property.lng]);
|
||
const popupBadgeClass = property.type === 'agricultural' ? 'popup-badge-agricultural' :
|
||
property.type === 'urban' ? 'popup-badge-urban' :
|
||
property.type === 'house' ? 'popup-badge-house' :
|
||
property.type === 'apartment' ? 'popup-badge-apartment' : 'popup-badge-ruins';
|
||
const typeLabel = getTypeLabel(property.type);
|
||
const title = escapeHtml(property.title || '');
|
||
const mainImage = getMainImage(property);
|
||
const location = escapeHtml(getLocationText(property));
|
||
const slug = property.slug || property.id;
|
||
const viewText = currentLang === 'es' ? 'Ver propiedad' : 'Смотреть объект';
|
||
marker.bindPopup(`
|
||
<div class="map-popup">
|
||
<div class="map-popup-img"><img src="${mainImage}" alt="${title}"><span class="popup-badge ${popupBadgeClass}">${typeLabel}</span></div>
|
||
<div class="map-popup-body">
|
||
<div class="map-popup-title">${title}</div>
|
||
<div class="map-popup-location"><i class="bi bi-geo-alt-fill"></i>${location}</div>
|
||
<div class="map-popup-meta"><span class="map-popup-price">${formatPrice(property.price)} €</span><span class="map-popup-area">${(property.area || 0).toLocaleString()} m²</span></div>
|
||
<a href="/property/${slug}" class="map-popup-link" onclick="event.stopPropagation();"><i class="bi bi-eye-fill"></i>${viewText}</a>
|
||
</div>
|
||
</div>
|
||
`);
|
||
markersLayer.addLayer(marker);
|
||
});
|
||
}
|
||
|
||
// Properties functions
|
||
function parseImages(prop) {
|
||
if (!prop.images) return [];
|
||
try { return JSON.parse(prop.images); } catch (e) { return []; }
|
||
}
|
||
function getMainImage(prop) {
|
||
const imgs = parseImages(prop);
|
||
if (imgs.length > 0) { if (typeof imgs[0] === 'object' && imgs[0].url) return imgs[0].url; if (typeof imgs[0] === 'string') return imgs[0]; }
|
||
return 'https://images.unsplash.com/photo-1564013799919-ab600027ffc6?w=800&q=80';
|
||
}
|
||
function getLocationText(prop) {
|
||
const city = prop.city || '';
|
||
const zone = prop.zone || prop.province || '';
|
||
if (city && zone) return city + ', ' + zone;
|
||
return city || zone || '';
|
||
}
|
||
|
||
async function loadProperties(filter, page) {
|
||
filter = filter || currentFilter;
|
||
page = page || 1;
|
||
currentPage = page;
|
||
const container = $('#propertiesGrid');
|
||
container.empty();
|
||
$('#paginationControls').empty();
|
||
|
||
if (properties.length === 0) {
|
||
container.html('<div class="col-12 text-center py-5"><div class="spinner-border text-primary" role="status"></div><p class="mt-2 text-muted">Cargando propiedades...</p></div>');
|
||
try {
|
||
const res = await fetch('/api/properties?lang=' + currentLang + '&limit=50');
|
||
const data = await res.json();
|
||
if (data.success && data.data) { properties = data.data; }
|
||
else { properties = []; }
|
||
} catch (e) {
|
||
console.error('Failed to load properties from API:', e);
|
||
container.html('<div class="col-12 text-center py-5"><i class="bi bi-exclamation-circle" style="font-size:2rem;color:var(--danger)"></i><p class="mt-2 text-muted">Error cargando propiedades</p></div>');
|
||
return;
|
||
}
|
||
}
|
||
|
||
let filteredProperties = properties;
|
||
if (filter !== 'all') { filteredProperties = properties.filter(p => p.type === filter); }
|
||
|
||
if (filteredProperties.length === 0) {
|
||
container.html(`<div class="col-12 text-center py-5"><i class="bi bi-search" style="font-size:3rem;color:var(--gray)"></i><h4 class="mt-3">${currentLang === 'es' ? 'No se encontraron propiedades' : 'Объекты не найдены'}</h4><p class="text-muted">${currentLang === 'es' ? 'Intenta ajustar los filtros' : 'Попробуйте изменить фильтры'}</p></div>`);
|
||
return;
|
||
}
|
||
|
||
const totalPages = Math.ceil(filteredProperties.length / ITEMS_PER_PAGE);
|
||
if (currentPage > totalPages) currentPage = totalPages;
|
||
const startIdx = (currentPage - 1) * ITEMS_PER_PAGE;
|
||
const pageProperties = filteredProperties.slice(startIdx, startIdx + ITEMS_PER_PAGE);
|
||
|
||
container.empty();
|
||
pageProperties.forEach((property, index) => {
|
||
const badgeClass = property.is_featured ? 'badge-new' :
|
||
property.is_exclusive ? 'badge-exclusive' :
|
||
property.type === 'agricultural' ? 'badge-agricultural' :
|
||
property.type === 'urban' ? 'badge-urban' :
|
||
property.type === 'house' ? 'badge-house' :
|
||
property.type === 'apartment' ? 'badge-apartment' : 'badge-ruins';
|
||
const typeLabel = getTypeLabel(property.type);
|
||
const location = getLocationText(property);
|
||
const title = escapeHtml(property.title || '');
|
||
const mainImage = getMainImage(property);
|
||
const priceFormatted = formatPrice(property.price);
|
||
const areaFormatted = (property.area || 0).toLocaleString();
|
||
const slug = property.slug || property.id;
|
||
|
||
const card = `
|
||
<div class="col-lg-4 col-md-6" data-aos="fade-up" data-aos-delay="${index % 3 * 100}">
|
||
<div class="property-card">
|
||
<div class="property-image">
|
||
<a href="#" onclick="openPropertyModal(${property.id}); return false;" class="property-card-link"><img src="${mainImage}" alt="${title}" loading="lazy"></a>
|
||
<div class="property-badges">
|
||
<span class="property-badge ${badgeClass}">${typeLabel}</span>
|
||
${property.is_featured ? '<span class="property-badge badge-exclusive">Destacado</span>' : ''}
|
||
${property.is_exclusive ? '<span class="property-badge" style="background:var(--secondary);color:var(--dark)">Exclusivo</span>' : ''}
|
||
</div>
|
||
<button class="property-favorite" onclick="toggleFavorite('${property.id}')" title="${currentLang === 'es' ? 'Añadir a favoritos' : 'В избранное'}"><i class="bi bi-heart"></i></button>
|
||
</div>
|
||
<div class="property-content">
|
||
<div class="property-type">${typeLabel}</div>
|
||
<a href="#" onclick="openPropertyModal(${property.id}); return false;" class="property-title">${title}</a>
|
||
<p class="property-location"><i class="bi bi-geo-alt"></i>${escapeHtml(location)}</p>
|
||
<div class="property-features">
|
||
<div class="property-feature"><i class="bi bi-rulers"></i><span>${areaFormatted} m²</span></div>
|
||
${property.bedrooms ? `<div class="property-feature"><i class="bi bi-door-open"></i><span>${property.bedrooms} ${currentLang === 'es' ? 'hab.' : 'комн.'}</span></div>` : ''}
|
||
${property.bathrooms ? `<div class="property-feature"><i class="bi bi-droplet"></i><span>${property.bathrooms} ${currentLang === 'es' ? 'baños' : 'ванн'}</span></div>` : ''}
|
||
</div>
|
||
<div class="property-utilities">${getUtilityIcons(property)}</div>
|
||
<div class="property-price">${priceFormatted} €<span>${property.area ? Math.round(property.price / property.area) : 0} €/m²</span></div>
|
||
<div class="property-actions">
|
||
<a href="/property/${slug}" class="btn btn-primary-custom"><i class="bi bi-eye me-2"></i>${currentLang === 'es' ? 'Ver' : 'Смотреть'}</a>
|
||
<a href="https://wa.me/34600123456?text=${encodeURIComponent((currentLang === 'es' ? 'Hola, me interesa esta propiedad: ' : 'Здравствуйте, интересует объект: ') + title)}" target="_blank" class="btn btn-whatsapp"><i class="bi bi-whatsapp"></i></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>`;
|
||
container.append(card);
|
||
});
|
||
|
||
renderPagination(totalPages);
|
||
AOS.refresh();
|
||
if (map && markersLayer) { addMarkersToMap(); }
|
||
}
|
||
|
||
function renderPagination(totalPages) {
|
||
const pag = $('#paginationControls');
|
||
pag.empty();
|
||
if (totalPages <= 1) return;
|
||
const prevText = currentLang === 'es' ? 'Anterior' : 'Назад';
|
||
const nextText = currentLang === 'es' ? 'Siguiente' : 'Далее';
|
||
pag.append(`<li class="page-item ${currentPage === 1 ? 'disabled' : ''}"><a class="page-link" href="#" onclick="goToPage(${currentPage - 1}); return false;">« ${prevText}</a></li>`);
|
||
for (let i = 1; i <= totalPages; i++) {
|
||
if (totalPages > 7 && i > 2 && i < totalPages - 1 && Math.abs(i - currentPage) > 1) {
|
||
if (i === 3 || i === totalPages - 2) pag.append('<li class="page-item disabled"><span class="page-link">...</span></li>');
|
||
continue;
|
||
}
|
||
pag.append(`<li class="page-item ${i === currentPage ? 'active' : ''}"><a class="page-link" href="#" onclick="goToPage(${i}); return false;">${i}</a></li>`);
|
||
}
|
||
pag.append(`<li class="page-item ${currentPage === totalPages ? 'disabled' : ''}"><a class="page-link" href="#" onclick="goToPage(${currentPage + 1}); return false;">${nextText} »</a></li>`);
|
||
}
|
||
|
||
function goToPage(page) {
|
||
loadProperties(currentFilter, page);
|
||
$('html, body').animate({ scrollTop: $('#catalog').offset().top - 80 }, 400);
|
||
}
|
||
|
||
function getTypeLabel(type) {
|
||
const labels = {
|
||
agricultural: currentLang === 'es' ? 'Agrícola' : 'Сельхоз',
|
||
urban: currentLang === 'es' ? 'Urbano' : 'Городской',
|
||
house: currentLang === 'es' ? 'Casa' : 'Дом',
|
||
apartment: currentLang === 'es' ? 'Apartamento' : 'Апартаменты',
|
||
ruins: currentLang === 'es' ? 'Ruinas' : 'Руины'
|
||
};
|
||
return labels[type] || type;
|
||
}
|
||
|
||
function getUtilityIcons(property) {
|
||
let icons = '';
|
||
const hasWater = property.water === 'available' || property.water === true;
|
||
const hasElec = property.electricity === 'available' || property.electricity === true;
|
||
const hasRoad = property.road === 'asphalt' || property.road === true;
|
||
const hasSeaView = property.views_sea === 1 || property.seaView === true;
|
||
icons += `<span class="utility-icon ${hasWater ? 'has' : 'no'}" title="${currentLang === 'es' ? 'Agua' : 'Вода'}"><i class="bi bi-droplet-fill"></i></span>`;
|
||
icons += `<span class="utility-icon ${hasElec ? 'has' : 'no'}" title="${currentLang === 'es' ? 'Electricidad' : 'Электричество'}"><i class="bi bi-lightning-fill"></i></span>`;
|
||
icons += `<span class="utility-icon ${hasRoad ? 'has' : 'no'}" title="${currentLang === 'es' ? 'Acceso' : 'Подъезд'}"><i class="bi bi-car-front-fill"></i></span>`;
|
||
if (hasSeaView) { icons += `<span class="utility-icon has" title="${currentLang === 'es' ? 'Vista al mar' : 'Вид на море'}"><i class="bi bi-water"></i></span>`; }
|
||
return icons;
|
||
}
|
||
|
||
function formatPrice(price) { return price.toLocaleString('de-DE'); }
|
||
|
||
function filterProperties(filter) {
|
||
currentFilter = filter; currentPage = 1;
|
||
loadProperties(filter, 1);
|
||
if (map) { map.setView([28.2916, -16.6291], 10); }
|
||
}
|
||
|
||
function toggleView(view) {
|
||
if (view === 'grid') { $('#gridView').show(); $('#mapView').hide(); }
|
||
else { $('#gridView').hide(); $('#mapView').show(); setTimeout(() => { map.invalidateSize(); }, 100); }
|
||
}
|
||
|
||
function applyFilters() {
|
||
const priceMin = parseInt($('#priceMin').val()) || 0;
|
||
const priceMax = parseInt($('#priceMax').val()) || Infinity;
|
||
const areaMin = parseInt($('#areaMin').val()) || 0;
|
||
const areaMax = parseInt($('#areaMax').val()) || Infinity;
|
||
const water = $('#filterWater').is(':checked');
|
||
const electricity = $('#filterElectricity').is(':checked');
|
||
const road = $('#filterRoad').is(':checked');
|
||
const ruins = $('#filterRuins').is(':checked');
|
||
const license = $('#filterLicense').is(':checked');
|
||
const seaView = $('#filterSeaView').is(':checked');
|
||
|
||
const container = $('#propertiesGrid');
|
||
container.empty();
|
||
|
||
let filteredProperties = properties.filter(p => {
|
||
if (p.price < priceMin || p.price > priceMax) return false;
|
||
if ((p.area || 0) < areaMin || (p.area || 0) > areaMax) return false;
|
||
if (water && p.water !== 'available') return false;
|
||
if (electricity && p.electricity !== 'available') return false;
|
||
if (road && p.road !== 'asphalt') return false;
|
||
if (ruins && !p.has_ruins) return false;
|
||
if (license && !p.has_license) return false;
|
||
if (seaView && !p.views_sea) return false;
|
||
if (currentFilter !== 'all' && p.type !== currentFilter) return false;
|
||
return true;
|
||
});
|
||
|
||
if (filteredProperties.length === 0) {
|
||
container.html(`<div class="col-12 text-center py-5"><i class="bi bi-search" style="font-size:3rem;color:var(--gray)"></i><h4 class="mt-3">${currentLang === 'es' ? 'No se encontraron propiedades con estos filtros' : 'По данным фильтрам объекты не найдены'}</h4></div>`);
|
||
return;
|
||
}
|
||
|
||
filteredProperties.forEach((property, index) => {
|
||
const badgeClass = property.is_featured ? 'badge-new' :
|
||
property.is_exclusive ? 'badge-exclusive' :
|
||
property.type === 'agricultural' ? 'badge-agricultural' :
|
||
property.type === 'urban' ? 'badge-urban' :
|
||
property.type === 'house' ? 'badge-house' :
|
||
property.type === 'apartment' ? 'badge-apartment' : 'badge-ruins';
|
||
const typeLabel = getTypeLabel(property.type);
|
||
const location = getLocationText(property);
|
||
const title = escapeHtml(property.title || '');
|
||
const mainImage = getMainImage(property);
|
||
const priceFormatted = formatPrice(property.price);
|
||
const areaFormatted = (property.area || 0).toLocaleString();
|
||
const slug = property.slug || property.id;
|
||
|
||
const card = `
|
||
<div class="col-lg-4 col-md-6" data-aos="fade-up" data-aos-delay="${index % 3 * 100}">
|
||
<div class="property-card">
|
||
<div class="property-image">
|
||
<a href="#" onclick="openPropertyModal(${property.id}); return false;" class="property-card-link"><img src="${mainImage}" alt="${title}" loading="lazy"></a>
|
||
<div class="property-badges">
|
||
<span class="property-badge ${badgeClass}">${typeLabel}</span>
|
||
${property.is_featured ? '<span class="property-badge badge-exclusive">Destacado</span>' : ''}
|
||
${property.is_exclusive ? '<span class="property-badge" style="background:var(--secondary);color:var(--dark)">Exclusivo</span>' : ''}
|
||
</div>
|
||
<button class="property-favorite" onclick="toggleFavorite('${property.id}')" title="${currentLang === 'es' ? 'Añadir a favoritos' : 'В избранное'}"><i class="bi bi-heart"></i></button>
|
||
</div>
|
||
<div class="property-content">
|
||
<div class="property-type">${typeLabel}</div>
|
||
<a href="#" onclick="openPropertyModal(${property.id}); return false;" class="property-title">${title}</a>
|
||
<p class="property-location"><i class="bi bi-geo-alt"></i>${escapeHtml(location)}</p>
|
||
<div class="property-features">
|
||
<div class="property-feature"><i class="bi bi-rulers"></i><span>${areaFormatted} m²</span></div>
|
||
${property.bedrooms ? `<div class="property-feature"><i class="bi bi-door-open"></i><span>${property.bedrooms} ${currentLang === 'es' ? 'hab.' : 'комн.'}</span></div>` : ''}
|
||
${property.bathrooms ? `<div class="property-feature"><i class="bi bi-droplet"></i><span>${property.bathrooms} ${currentLang === 'es' ? 'baños' : 'ванн'}</span></div>` : ''}
|
||
</div>
|
||
<div class="property-utilities">${getUtilityIcons(property)}</div>
|
||
<div class="property-price">${priceFormatted} €<span>${property.area ? Math.round(property.price / property.area) : 0} €/m²</span></div>
|
||
<div class="property-actions">
|
||
<a href="/property/${slug}" class="btn btn-primary-custom"><i class="bi bi-eye me-2"></i>${currentLang === 'es' ? 'Ver' : 'Смотреть'}</a>
|
||
<a href="https://wa.me/34600123456?text=${encodeURIComponent((currentLang === 'es' ? 'Hola, me interesa esta propiedad: ' : 'Здравствуйте, интересует объект: ') + title)}" target="_blank" class="btn btn-whatsapp"><i class="bi bi-whatsapp"></i></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>`;
|
||
container.append(card);
|
||
});
|
||
|
||
AOS.refresh();
|
||
addMarkersToMap();
|
||
}
|
||
|
||
// Modal
|
||
let modalGalleryImages = [];
|
||
let modalGalleryIndex = 0;
|
||
let modalGalleryInterval = null;
|
||
|
||
function setGalleryImage(index) {
|
||
if (index < 0) index = modalGalleryImages.length - 1;
|
||
if (index >= modalGalleryImages.length) index = 0;
|
||
modalGalleryIndex = index;
|
||
const slider = document.getElementById('modalGallerySlider');
|
||
if (!slider) return;
|
||
const imgs = slider.querySelectorAll('img');
|
||
imgs.forEach((img, i) => { img.classList.toggle('active', i === index); });
|
||
const dots = document.getElementById('galleryDots');
|
||
if (dots) {
|
||
dots.querySelectorAll('.gallery-dot').forEach((dot, i) => { dot.classList.toggle('active', i === index); });
|
||
}
|
||
}
|
||
|
||
function startGalleryAutoplay() {
|
||
stopGalleryAutoplay();
|
||
if (modalGalleryImages.length > 1) {
|
||
modalGalleryInterval = setInterval(() => { setGalleryImage(modalGalleryIndex + 1); }, 4000);
|
||
}
|
||
}
|
||
function stopGalleryAutoplay() {
|
||
if (modalGalleryInterval) { clearInterval(modalGalleryInterval); modalGalleryInterval = null; }
|
||
}
|
||
|
||
function openPropertyModal(id) {
|
||
const property = properties.find(p => p.id === id);
|
||
if (!property) return;
|
||
stopGalleryAutoplay();
|
||
const modal = $('#propertyModal');
|
||
const badgeClass = property.type === 'agricultural' ? 'badge-agricultural' :
|
||
property.type === 'urban' ? 'badge-urban' :
|
||
property.type === 'house' ? 'badge-house' :
|
||
property.type === 'apartment' ? 'badge-apartment' : 'badge-ruins';
|
||
const title = escapeHtml(property.title || '');
|
||
const location = escapeHtml(getLocationText(property));
|
||
const slug = property.slug || property.id;
|
||
|
||
const allImages = parseImages(property);
|
||
const imageUrls = allImages.map(img => typeof img === 'string' ? img : (img.url || '')).filter(u => u.length > 0);
|
||
if (imageUrls.length === 0) { imageUrls.push('https://images.unsplash.com/photo-1564013799919-ab600027ffc6?w=800&q=80'); }
|
||
modalGalleryImages = imageUrls; modalGalleryIndex = 0;
|
||
|
||
const slider = document.getElementById('modalGallerySlider');
|
||
slider.innerHTML = imageUrls.map((url, i) => `<img src="${url}" alt="${title}" class="${i === 0 ? 'active' : ''}">`).join('');
|
||
const dotsContainer = document.getElementById('galleryDots');
|
||
dotsContainer.innerHTML = imageUrls.map((_, i) => `<span class="gallery-dot${i === 0 ? ' active' : ''}" onclick="setGalleryImage(${i})"></span>`).join('');
|
||
const arrows = document.querySelectorAll('.gallery-arrow');
|
||
arrows.forEach(a => { a.style.display = imageUrls.length > 1 ? 'flex' : 'none'; });
|
||
document.getElementById('galleryDots').style.display = imageUrls.length > 1 ? 'flex' : 'none';
|
||
startGalleryAutoplay();
|
||
|
||
$('#modalType').attr('class', `property-type ${badgeClass}`).text(getTypeLabel(property.type));
|
||
$('#modalTitle').text(title);
|
||
$('#modalLocation').html(`<i class="bi bi-geo-alt"></i> ${location}`);
|
||
$('#modalPrice').text(`${formatPrice(property.price)} €`);
|
||
|
||
let featuresHtml = `
|
||
<div class="modal-feature"><i class="bi bi-rulers"></i><div><strong>${currentLang === 'es' ? 'Superficie' : 'Площадь'}</strong><p>${(property.area || 0).toLocaleString()} m²</p></div></div>`;
|
||
if (property.bedrooms) { featuresHtml += `<div class="modal-feature"><i class="bi bi-door-open"></i><div><strong>${currentLang === 'es' ? 'Habitaciones' : 'Комнаты'}</strong><p>${property.bedrooms}</p></div></div>`; }
|
||
if (property.bathrooms) { featuresHtml += `<div class="modal-feature"><i class="bi bi-droplet"></i><div><strong>${currentLang === 'es' ? 'Baños' : 'Ванные'}</strong><p>${property.bathrooms}</p></div></div>`; }
|
||
if (property.parking_spaces) { featuresHtml += `<div class="modal-feature"><i class="bi bi-car-front"></i><div><strong>${currentLang === 'es' ? 'Garaje' : 'Гараж'}</strong><p>${property.parking_spaces} ${currentLang === 'es' ? 'plazas' : 'мест'}</p></div></div>`; }
|
||
$('#modalFeatures').html(featuresHtml);
|
||
|
||
const hasWater = property.water === 'available';
|
||
const hasElec = property.electricity === 'available';
|
||
const hasRoad = property.road === 'asphalt';
|
||
const hasRuins = property.has_ruins === 1;
|
||
const hasLicense = property.has_license === 1;
|
||
const hasSeaView = property.views_sea === 1;
|
||
let utilitiesHtml = '';
|
||
utilitiesHtml += `<div class="modal-utility ${hasWater ? 'has' : 'no'}"><i class="bi bi-droplet-fill"></i>${hasWater ? (currentLang === 'es' ? 'Agua disponible' : 'Вода подключена') : (currentLang === 'es' ? 'Agua no disponible' : 'Вода не подключена')}</div>`;
|
||
utilitiesHtml += `<div class="modal-utility ${hasElec ? 'has' : 'no'}"><i class="bi bi-lightning-fill"></i>${hasElec ? (currentLang === 'es' ? 'Electricidad disponible' : 'Электричество подключено') : (currentLang === 'es' ? 'Electricidad no disponible' : 'Электричество не подключено')}</div>`;
|
||
utilitiesHtml += `<div class="modal-utility ${hasRoad ? 'has' : 'no'}"><i class="bi bi-car-front-fill"></i>${hasRoad ? (currentLang === 'es' ? 'Acceso rodado' : 'Подъезд') : (currentLang === 'es' ? 'Sin acceso rodado' : 'Без подъезда')}</div>`;
|
||
if (hasRuins) { utilitiesHtml += `<div class="modal-utility has"><i class="bi bi-house-dash-fill"></i>${currentLang === 'es' ? 'Con ruinas/edificación' : 'С руинами/постройками'}</div>`; }
|
||
if (hasLicense) { utilitiesHtml += `<div class="modal-utility has"><i class="bi bi-file-earmark-check-fill"></i>${currentLang === 'es' ? 'Licencia de obras' : 'Разрешение на стройку'}</div>`; }
|
||
if (hasSeaView) { utilitiesHtml += `<div class="modal-utility has"><i class="bi bi-water"></i>${currentLang === 'es' ? 'Vista al mar' : 'Вид на море'}</div>`; }
|
||
$('#modalUtilities').html(utilitiesHtml);
|
||
|
||
const whatsappText = encodeURIComponent(`${currentLang === 'es' ? 'Hola, me interesa esta propiedad: ' : 'Здравствуйте, интересует объект: '} ${title} - ${formatPrice(property.price)}€`);
|
||
$('#modalWhatsapp').attr('href', `https://wa.me/34600123456?text=${whatsappText}`);
|
||
const scheduleText = encodeURIComponent(`${currentLang === 'es' ? 'Hola, quiero agendar una visita para la propiedad: ' : 'Здравствуйте, хочу записаться на просмотр объекта: '} ${title} - ${formatPrice(property.price)}€`);
|
||
$('#modalSchedule').attr('href', `https://wa.me/34600123456?text=${scheduleText}`);
|
||
$('#modalViewDetails').attr('href', `/property/${slug}`);
|
||
modal.modal('show');
|
||
}
|
||
|
||
document.getElementById('galleryPrev').addEventListener('click', function() {
|
||
stopGalleryAutoplay(); setGalleryImage(modalGalleryIndex - 1); startGalleryAutoplay();
|
||
});
|
||
document.getElementById('galleryNext').addEventListener('click', function() {
|
||
stopGalleryAutoplay(); setGalleryImage(modalGalleryIndex + 1); startGalleryAutoplay();
|
||
});
|
||
document.getElementById('propertyModal').addEventListener('hidden.bs.modal', function() {
|
||
stopGalleryAutoplay();
|
||
});
|
||
|
||
function toggleFavorite(id) {
|
||
const btn = $(`.property-favorite`).eq(id - 1);
|
||
btn.toggleClass('active');
|
||
if (btn.hasClass('active')) { btn.find('i').removeClass('bi-heart').addClass('bi-heart-fill'); }
|
||
else { btn.find('i').removeClass('bi-heart-fill').addClass('bi-heart'); }
|
||
}
|
||
</script>
|
||
</body>
|
||
</html> |