Demo-apartamento

Vista Mar Apartments β€” Demo

:root {
–primary: #0d6efd;
–primary-dark: #0a58ca;
–accent: #ffb703;
–text: #1f2937;
–muted: #6b7280;
–bg: #f7f8fa;
–card: #ffffff;
–border: #e5e7eb;
–radius: 14px;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: ‘Segoe UI’, system-ui, -apple-system, sans-serif;
background: var(–bg);
color: var(–text);
line-height: 1.55;
}
a { color: inherit; }
.demo-banner {
background: #fff3cd;
border-bottom: 1px solid #ffe69c;
color: #664d03;
text-align: center;
font-size: 14px;
font-weight: 600;
padding: 10px 16px;
}
header {
background: var(–card);
border-bottom: 1px solid var(–border);
position: sticky;
top: 0;
z-index: 50;
}
.nav-wrap {
max-width: 1080px;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: space-between;
padding: 14px 20px;
}
.logo {
font-weight: 800;
font-size: 20px;
color: var(–primary-dark);
}
.logo span { color: var(–accent); }
nav a {
text-decoration: none;
margin-left: 22px;
color: var(–text);
font-size: 14px;
font-weight: 600;
}
.container { max-width: 1080px; margin: 0 auto; padding: 0 20px; }

.property-switcher {
display: flex;
gap: 10px;
padding: 18px 0 0;
flex-wrap: wrap;
}
.property-switcher button {
border: 1px solid var(–border);
background: var(–card);
padding: 8px 16px;
border-radius: 999px;
font-size: 13px;
font-weight: 600;
cursor: pointer;
color: var(–muted);
}
.property-switcher button.active {
background: var(–primary);
border-color: var(–primary);
color: #fff;
}

.hero { padding: 18px 0 6px; }
.hero h1 { font-size: 30px; margin: 6px 0 4px; }
.hero .loc { color: var(–muted); font-size: 14px; margin-bottom: 14px; }
.hero .stats { display: flex; gap: 18px; flex-wrap: wrap; font-size: 14px; color: var(–muted); margin-bottom: 16px; }
.hero .stats b { color: var(–text); }

.gallery {
display: grid;
grid-template-columns: 2fr 1fr 1fr;
grid-template-rows: 1fr 1fr;
gap: 8px;
height: 380px;
border-radius: var(–radius);
overflow: hidden;
margin-bottom: 28px;
}
.gallery .ph {
display: flex;
align-items: center;
justify-content: center;
color: rgba(255,255,255,.92);
font-size: 13px;
font-weight: 600;
text-align: center;
position: relative;
}
.gallery .g1 { grid-row: 1 / 3; }
.ph-1 { background: linear-gradient(135deg,#4a90d9,#1c5fa8); }
.ph-2 { background: linear-gradient(135deg,#f4b860,#e18a2a); }
.ph-3 { background: linear-gradient(135deg,#7ec8a4,#3d8f6b); }
.ph-4 { background: linear-gradient(135deg,#c98bd0,#8a4a99); }
.ph-5 { background: linear-gradient(135deg,#e07a7a,#b53f3f); }

.layout { display: grid; grid-template-columns: 1.6fr 1fr; gap: 28px; align-items: start; margin-bottom: 40px; }
@media (max-width: 860px) { .layout { grid-template-columns: 1fr; } .gallery { grid-template-columns: 1fr 1fr; height: auto; } .gallery .ph { height: 140px; } .gallery .g1 { grid-column: 1/3; height: 200px; } }

.card { background: var(–card); border: 1px solid var(–border); border-radius: var(–radius); padding: 22px; margin-bottom: 20px; }
.card h2 { font-size: 18px; margin: 0 0 12px; }

.amenities { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px 18px; }
.amenities div { font-size: 14px; display: flex; align-items: center; gap: 8px; }

.reviews .review { border-top: 1px solid var(–border); padding: 14px 0; }
.reviews .review:first-child { border-top: none; padding-top: 0; }
.reviews .stars { color: var(–accent); font-size: 14px; margin-bottom: 4px; }
.reviews .who { font-size: 12px; color: var(–muted); margin-top: 4px; }

.booking-card { position: sticky; top: 84px; }
.price-line { font-size: 22px; font-weight: 800; margin-bottom: 2px; }
.price-line span { font-size: 13px; font-weight: 500; color: var(–muted); }

.cal-head { display: flex; align-items: center; justify-content: space-between; margin: 14px 0 8px; }
.cal-head button { border: 1px solid var(–border); background: #fff; border-radius: 8px; width: 30px; height: 30px; cursor: pointer; font-size: 14px; }
.cal-head .label { font-weight: 700; font-size: 14px; }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.cal-grid .dow { font-size: 11px; color: var(–muted); text-align: center; font-weight: 700; padding-bottom: 4px; }
.day {
border-radius: 8px;
text-align: center;
padding: 6px 0 5px;
font-size: 12px;
cursor: pointer;
border: 1px solid transparent;
background: #f2f4f7;
}
.day .num { font-weight: 700; font-size: 13px; }
.day .p { font-size: 9px; color: var(–muted); }
.day.blank { background: transparent; cursor: default; }
.day.past { background: transparent; color: #d1d5db; cursor: not-allowed; }
.day.past .p { display: none; }
.day.booked { background: #fde2e2; color: #b91c1c; cursor: not-allowed; text-decoration: line-through; }
.day.booked .p { display:none; }
.day:hover:not(.blank):not(.past):not(.booked) { border-color: var(–primary); }
.day.selected { background: var(–primary); color: #fff; }
.day.selected .p { color: #dbeafe; }
.day.in-range { background: #dbeafe; }

.summary { margin-top: 16px; border-top: 1px dashed var(–border); padding-top: 14px; font-size: 14px; }
.summary-row { display: flex; justify-content: space-between; margin-bottom: 6px; color: var(–muted); }
.summary-row.total { color: var(–text); font-weight: 800; font-size: 16px; border-top: 1px solid var(–border); padding-top: 8px; margin-top: 8px; }

.guests { display: flex; align-items: center; justify-content: space-between; margin: 14px 0; font-size: 14px; }
.stepper { display: flex; align-items: center; gap: 10px; }
.stepper button { width: 28px; height: 28px; border-radius: 50%; border: 1px solid var(–border); background: #fff; cursor: pointer; font-size: 15px; }

.cta {
width: 100%;
background: var(–primary);
color: #fff;
border: none;
padding: 13px;
border-radius: 10px;
font-weight: 700;
font-size: 15px;
cursor: pointer;
margin-top: 12px;
}
.cta:hover { background: var(–primary-dark); }
.hint { font-size: 12px; color: var(–muted); text-align: center; margin-top: 8px; }

.confirm-box {
display: none;
margin-top: 14px;
background: #eef9ee;
border: 1px solid #d5e8d4;
border-radius: 10px;
padding: 14px;
font-size: 13px;
color: #2f6b2f;
}

.rules ul { margin: 0; padding-left: 18px; font-size: 14px; }
.rules li { margin-bottom: 6px; }

footer { background: #14213d; color: #cbd5e1; padding: 30px 0; margin-top: 30px; font-size: 13px; }
footer .container { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 14px; }
footer a { color: #fff; text-decoration: none; }

🚧 DEMO VERSION β€” the final site will be built with your own photos, details and domain

Description

Amenities

Guest Reviews (sample)

β˜…β˜…β˜…β˜…β˜…
“Fantastic view, everything was spotlessly clean, and check-in took just a few minutes.”
β€” Eva N., August 2025

β˜…β˜…β˜…β˜…β˜…
“Perfect location, everything is within walking distance. We’ll definitely be back!”
β€” Tom H., July 2025

β˜…β˜…β˜…β˜…β˜†
“Very nice apartment, a bit noisy from the street side, but overall a great experience.”
β€” Peter K., June 2025

House Rules & Terms

  • Check-in: from 3:00 PM  β€’  Check-out: until 11:00 AM
  • No smoking
  • Pets by arrangement
  • Free cancellation up to 7 days before check-in
  • Registered short-term rental property with official license (license number available on request)

Number of guests

2

Select your check-in and check-out dates in the calendar

This is a demo β€” the real booking/payment flow will go live on the actual site
βœ… Thank you for your request! This is a demo interface β€” on the live site, the payment/confirmation process would start here, and both you and the guest would receive an email notification.

Β© Vista Mar Apartments β€” demo page, not a live system.
Contact: info@example.com  β€’  +34 000 000 000

(function(){

var properties = [
{
id: ‘p1’,
name: ‘Sea View Studio β€” Puerto de la Cruz’,
loc: ‘Puerto de la Cruz, Tenerife β€” 5 minute walk from the old town’,
stats: { guests: 2, bedrooms: 1, beds: 1, baths: 1, size: 38 },
desc: ‘A modern, fully renovated studio apartment just two streets from the seafront. The spacious balcony offers a panoramic ocean view, especially stunning at sunset. Ideal for couples or solo travelers who want to be close to the lively old town while still enjoying a peaceful place to unwind.’,
amenities: [‘πŸ“Ά Free Wi-Fi’, ‘🍳 Fully equipped kitchen’, ‘❄️ Air conditioning’, ‘🧺 Washing machine’, ‘πŸ“Ί Smart TV’, ‘πŸ…ΏοΈ Street parking’, ‘πŸŒ… Balcony / sea view’, ‘πŸ”‘ Self check-in’],
prices: [58,58,62,68,75,92,118,128,98,80,64,68],
booked: genBooked(6)
},
{
id: ‘p2’,
name: ‘Garden Apartment β€” Los Cristianos’,
loc: ‘Los Cristianos, Tenerife β€” 300 m from the beach’,
stats: { guests: 4, bedrooms: 2, beds: 2, baths: 1, size: 62 },
desc: ‘A family-friendly, two-bedroom apartment with a private garden terrace and access to a shared pool. Located in a quiet, green residential complex, just a few minutes\’ walk from the beach and restaurants. A perfect choice for families or groups of up to 4 friends.’,
amenities: [‘πŸ“Ά Free Wi-Fi’, ‘🍳 Fully equipped kitchen’, ‘❄️ Air conditioning’, ‘🏊 Shared pool’, ‘🧺 Washing machine’, ‘πŸ“Ί Smart TV’, ‘πŸ…ΏοΈ Free parking’, ‘🌿 Private garden terrace’],
prices: [70,70,75,82,90,105,135,148,112,92,76,80],
booked: genBooked(5)
}
];

function genBooked(n){
var set = {};
var today = new Date();
for (var i=0;i<n;i++){
var d = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 3 + Math.floor(Math.random()*40));
set[fmt(d)] = true;
}
return set;
}

function fmt(d){
return d.getFullYear() + '-' + String(d.getMonth()+1).padStart(2,'0') + '-' + String(d.getDate()).padStart(2,'0');
}

var monthNames = ['January','February','March','April','May','June','July','August','September','October','November','December'];
var dowNames = ['Mo','Tu','We','Th','Fr','Sa','Su'];

var state = {
propIndex: 0,
viewDate: new Date(new Date().getFullYear(), new Date().getMonth(), 1),
checkIn: null,
checkOut: null,
guests: 2
};

function currentProp(){ return properties[state.propIndex]; }

function renderSwitcher(){
var wrap = document.getElementById('propertySwitcher');
wrap.innerHTML = '';
properties.forEach(function(p, i){
var btn = document.createElement('button');
btn.textContent = (i+1) + '. ' + p.name.split(' β€” ')[0];
if (i === state.propIndex) btn.className = 'active';
btn.addEventListener('click', function(){
state.propIndex = i;
state.checkIn = null;
state.checkOut = null;
state.viewDate = new Date(new Date().getFullYear(), new Date().getMonth(), 1);
renderAll();
});
wrap.appendChild(btn);
});
}

function renderHero(){
var p = currentProp();
document.getElementById('propTitle').textContent = p.name;
document.getElementById('propLoc').textContent = 'πŸ“ ' + p.loc;
document.getElementById('propDesc').textContent = p.desc;
var s = p.stats;
document.getElementById('propStats').innerHTML =
'

πŸ‘₯ ‘ + s.guests + ‘ guests

‘ +

πŸ›οΈ ‘ + s.bedrooms + ‘ bedroom’ + (s.bedrooms === 1 ? ” : ‘s’) + ‘

‘ +

πŸ›Œ ‘ + s.beds + ‘ bed’ + (s.beds === 1 ? ” : ‘s’) + ‘

‘ +

🚿 ‘ + s.baths + ‘ bathroom’ + (s.baths === 1 ? ” : ‘s’) + ‘

‘ +

πŸ“ ‘ + s.size + ‘ mΒ²

‘;
document.getElementById(‘propAmenities’).innerHTML = p.amenities.map(function(a){ return ‘

‘ + a + ‘

‘; }).join(”);
var minPrice = Math.min.apply(null, p.prices);
document.getElementById(‘priceFromLabel’).innerHTML = ‘From ‘ + minPrice + ‘ € / night, depending on season‘;
}

function renderCalendar(){
var p = currentProp();
var y = state.viewDate.getFullYear();
var m = state.viewDate.getMonth();
document.getElementById(‘calLabel’).textContent = monthNames[m] + ‘ ‘ + y;

var grid = document.getElementById(‘calGrid’);
grid.innerHTML = ”;
dowNames.forEach(function(d){
var el = document.createElement(‘div’);
el.className = ‘dow’;
el.textContent = d;
grid.appendChild(el);
});

var firstDay = new Date(y, m, 1);
var startOffset = (firstDay.getDay() + 6) % 7; // Monday-first
var daysInMonth = new Date(y, m+1, 0).getDate();
var today = new Date(); today.setHours(0,0,0,0);

for (var i=0;i<startOffset;i++){
var blank = document.createElement('div');
blank.className = 'day blank';
grid.appendChild(blank);
}

for (var day=1; day<=daysInMonth; day++){
var dateObj = new Date(y, m, day);
var dateStr = fmt(dateObj);
var cell = document.createElement('div');
cell.className = 'day';

var isPast = dateObj state.checkIn && dateStr < state.checkOut) cell.className += ' in-range';

var price = p.prices[m];
cell.innerHTML = '

‘ + day + ‘
‘ + price + ‘€

‘;

if (!isPast && !isBooked){
cell.addEventListener(‘click’, function(ds){
return function(){ onDayClick(ds); };
}(dateStr));
}

grid.appendChild(cell);
}
}

function onDayClick(dateStr){
if (!state.checkIn || (state.checkIn && state.checkOut)){
state.checkIn = dateStr;
state.checkOut = null;
} else if (dateStr <= state.checkIn) {
state.checkIn = dateStr;
state.checkOut = null;
} else {
if (rangeHasBooked(state.checkIn, dateStr)){
alert('There is already a booked day within the selected period β€” please choose a different date range.');
state.checkIn = dateStr;
state.checkOut = null;
} else {
state.checkOut = dateStr;
}
}
renderCalendar();
renderSummary();
}

function rangeHasBooked(inStr, outStr){
var p = currentProp();
var cur = new Date(inStr);
var end = new Date(outStr);
while (fmt(cur) < outStr){
if (p.booked[fmt(cur)]) return true;
cur.setDate(cur.getDate()+1);
}
return false;
}

function computeTotal(inStr, outStr){
var p = currentProp();
var cur = new Date(inStr);
var end = new Date(outStr);
var total = 0, nights = 0, lines = {};
while (fmt(cur) < outStr){
var price = p.prices[cur.getMonth()];
total += price;
nights++;
var key = monthNames[cur.getMonth()];
lines[key] = (lines[key] || 0) + price;
cur.setDate(cur.getDate()+1);
}
return { total: total, nights: nights, lines: lines };
}

function renderSummary(){
var box = document.getElementById('summary');
var btn = document.getElementById('bookBtn');
document.getElementById('confirmBox').style.display = 'none';

if (!state.checkIn || !state.checkOut){
box.innerHTML = '

Select your check-in and check-out dates in the calendar

‘;
btn.disabled = true;
btn.textContent = ‘Select dates’;
return;
}

var r = computeTotal(state.checkIn, state.checkOut);
var html = ‘

Check-in‘ + state.checkIn.split(‘-‘).reverse().join(‘/’) + ‘

‘;
html += ‘

Check-out‘ + state.checkOut.split(‘-‘).reverse().join(‘/’) + ‘

‘;
html += ‘

Number of nights‘ + r.nights + ‘

‘;
Object.keys(r.lines).forEach(function(k){
html += ‘

‘ + k + ‘ (based on average rate)‘ + r.lines[k] + ‘ €

‘;
});
html += ‘

Total‘ + r.total + ‘ €

‘;
box.innerHTML = html;

btn.disabled = false;
btn.textContent = ‘Request booking β€” ‘ + r.total + ‘ €’;
}

function renderAll(){
renderSwitcher();
renderHero();
renderCalendar();
renderSummary();
}

document.getElementById(‘prevMonth’).addEventListener(‘click’, function(){
state.viewDate = new Date(state.viewDate.getFullYear(), state.viewDate.getMonth()-1, 1);
renderCalendar();
});
document.getElementById(‘nextMonth’).addEventListener(‘click’, function(){
state.viewDate = new Date(state.viewDate.getFullYear(), state.viewDate.getMonth()+1, 1);
renderCalendar();
});
document.getElementById(‘guestMinus’).addEventListener(‘click’, function(){
if (state.guests > 1){ state.guests–; document.getElementById(‘guestCount’).textContent = state.guests; }
});
document.getElementById(‘guestPlus’).addEventListener(‘click’, function(){
var max = currentProp().stats.guests;
if (state.guests < max){ state.guests++; document.getElementById('guestCount').textContent = state.guests; }
});
document.getElementById('bookBtn').addEventListener('click', function(){
document.getElementById('confirmBox').style.display = 'block';
});

renderAll();
})();