{"id":5083,"date":"2026-06-28T13:06:33","date_gmt":"2026-06-28T17:06:33","guid":{"rendered":"https:\/\/turisvina.cl\/?page_id=5083"},"modified":"2026-07-09T13:26:32","modified_gmt":"2026-07-09T17:26:32","slug":"cotizar-transfer","status":"publish","type":"page","link":"https:\/\/turisvina.cl\/en\/cotizar-transfer\/","title":{"rendered":"Cotizar transfer"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"5083\" class=\"elementor elementor-5083\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-d54d205 e-con-full e-flex e-con e-parent\" data-id=\"d54d205\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-dfcfafd elementor-widget elementor-widget-shortcode\" data-id=\"dfcfafd\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\"><script>window.tvCotizadorAjaxUrl=\"https:\\\/\\\/turisvina.cl\\\/wp-admin\\\/admin-ajax.php\";window.tvCotizadorPagoNonce=\"f5d0350b2f\";window.tvCotizadorWebpay=1;<\/script><!-- Google Maps API \u2014 Places + Directions -->\n<script src=\"https:\/\/maps.googleapis.com\/maps\/api\/js?key=AIzaSyBYBnUSjP0SzY_5kQ5_edN3c2y3Wch8mgs&libraries=places&language=es&region=CL\" async defer><\/script>\n\n<!-- =============================================================\n     COTIZADOR TURISVI\u00d1A \u2014 HTML + JS\n     Pegar en: Elementor > Widget \"HTML\" o \"C\u00f3digo\"\n     El CSS va en cotizador.css (CSS adicional de WordPress)\n     ============================================================= -->\n\n<div class=\"tv-cotizador\">\n\n  <!-- ============ HERO BANNER (full width) ============ -->\n  <header class=\"tv-hero\">\n    <div class=\"tv-hero-media\">\n      <img decoding=\"async\" src=\"https:\/\/turisvina.cl\/wp-content\/uploads\/2026\/06\/Turisvina-en-el-aeropuerto.png\" alt=\"Conductor de TurisVi\u00f1a recibiendo a un pasajero en el aeropuerto \u2014 transfer privado en Chile\" fetchpriority=\"high\">\n    <\/div>\n    <div class=\"tv-hero-inner\">\n      <span class=\"tv-hero-eyebrow\">Transporte privado en todo Chile<\/span>\n      <h1>Cotiza tu <span>traslado<\/span> al instante<\/h1>\n      <p class=\"tv-hero-sub\">\n        Sed\u00e1n ejecutivo, van, minib\u00fas y bus para aeropuerto, ciudad o cualquier destino del pa\u00eds.\n        Ingresa tu ruta y obt\u00e9n el precio en segundos \u2014 sin llamadas, sin esperas.\n      <\/p>\n      <div class=\"tv-hero-points\">\n        <span class=\"tv-hero-point\">\u2713 <b>Certificado<\/b> SERNATUR<\/span>\n        <span class=\"tv-hero-point\">\ud83d\udd50 Atenci\u00f3n <b>24\/7<\/b><\/span>\n        <span class=\"tv-hero-point\">\ud83d\udccd Cobertura <b>nacional<\/b><\/span>\n        <span class=\"tv-hero-point\">\ud83d\udcac Confirmas por <b>WhatsApp<\/b><\/span>\n      <\/div>\n    <\/div>\n  <\/header>\n\n  <!-- ============ TRUST BAR ============ -->\n  <div class=\"tv-trust\">\n    <div class=\"tv-trust-inner\">\n      <span class=\"tv-trust-label\">Nos avalan<\/span>\n      <div class=\"tv-trust-logos\">\n        <img decoding=\"async\" src=\"https:\/\/turisvina.cl\/wp-content\/uploads\/2026\/06\/logo-prochile-innovacion.png\" alt=\"ProChile\" loading=\"lazy\">\n        <img decoding=\"async\" src=\"https:\/\/turisvina.cl\/wp-content\/uploads\/2024\/03\/Group-154.webp\" alt=\"Pro PYME\" loading=\"lazy\">\n        <img decoding=\"async\" src=\"https:\/\/turisvina.cl\/wp-content\/uploads\/2025\/03\/c14.png\" alt=\"Ministerio Secretar\u00eda General de la Presidencia\" loading=\"lazy\">\n        <img decoding=\"async\" src=\"https:\/\/turisvina.cl\/wp-content\/uploads\/2025\/05\/CHILE-SELLO-MUJER-1-834x1024-1.png\" alt=\"Sello mujer\" loading=\"lazy\">\n\t\t  <img decoding=\"async\" src=\"https:\/\/turisvina.cl\/wp-content\/uploads\/2024\/03\/sernatur2.png\" alt=\"Sernatur\" loading=\"lazy\">\n      <\/div>\n      <span class=\"tv-trust-badge\">\n        <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M12 2l8 3v6c0 5-3.4 8.6-8 11-4.6-2.4-8-6-8-11V5l8-3z\" fill=\"#48c774\"><\/path><path d=\"M9 12l2 2 4-4\" stroke=\"#fff\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><\/path><\/svg>\n        Operador formal \u00b7 MTT\n      <\/span>\n    <\/div>\n  <\/div>\n\n  <div class=\"tv-wrap\">\n\n    <!-- STEPPER -->\n    <div class=\"tv-stepper\" id=\"tv-stepper\" role=\"navigation\" aria-label=\"Progreso de la cotizaci\u00f3n\">\n      <div class=\"tv-st active\" data-step=\"1\"><div class=\"tv-st-num\">1<\/div><div class=\"tv-st-label\">Servicio<\/div><\/div>\n      <div class=\"tv-st\" data-step=\"2\"><div class=\"tv-st-num\">2<\/div><div class=\"tv-st-label\">Pasajero<\/div><\/div>\n      <div class=\"tv-st\" data-step=\"3\"><div class=\"tv-st-num\">3<\/div><div class=\"tv-st-label\">Confirmaci\u00f3n<\/div><\/div>\n      <div class=\"tv-st\" data-step=\"4\"><div class=\"tv-st-num\">4<\/div><div class=\"tv-st-label\">Listo<\/div><\/div>\n    <\/div>\n\n    <!-- APP -->\n    <main id=\"tv-app\"><\/main>\n\n  <\/div>\n\n  <!-- FOOTER MINI -->\n  <div class=\"tv-foot\">\n    <div class=\"tv-foot-secure\">\n      <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M12 2l8 3v6c0 5-3.4 8.6-8 11-4.6-2.4-8-6-8-11V5l8-3z\" fill=\"#061f36\"><\/path><path d=\"M9 12l2 2 4-4\" stroke=\"#f9b733\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><\/path><\/svg>\n      Tus datos viajan seguros y no se comparten con terceros\n    <\/div>\n    <p>\n      \u00bfPrefieres hablar con una persona? Escr\u00edbenos: <a href=\"https:\/\/wa.me\/56323467715\" target=\"_blank\" rel=\"noopener\">+56 323467715<\/a> \u00b7 <a href=\"mailto:ventas@turisvina.cl\">ventas@turisvina.cl<\/a><br>\n      TurisVi\u00f1a \u00b7 Transporte ejecutivo, tur\u00edstico y de carga menor \u00b7 Operador certificado SERNATUR y Ministerio de Transportes.\n    <\/p>\n  <\/div>\n\n<\/div>\n\n<style>\n\/* =============================================================\n   COTIZADOR TURISVI\u00d1A \u2014 HOJA DE ESTILOS\n   Marca: Oswald + Montserrat \u00b7 navy #061f36 \u00b7 naranja #f36f21\n   Pegar en: WordPress > Apariencia > Personalizar > CSS adicional\n   (o en el widget HTML, antes del bloque del cotizador)\n   ============================================================= *\/\n\n\/* ---- TOKENS DE MARCA ---- *\/\n.tv-cotizador{\n  --navy:#061f36; --navy-2:#082b49; --ink:#080d2b;\n  --orange:#f36f21; --orange-d:#d85d12; --yellow:#f9b733; --green:#48c774;\n  --aqua:#55c9de; --text:#27313b; --muted:#6d7a86; --border:#e4edf3;\n  --sky:#eef6fb; --sky-2:#f5f9fc; --white:#fff;\n  --shadow:0 12px 28px rgba(6,31,54,.08);\n  --shadow-lg:0 18px 45px rgba(6,31,54,.13);\n  --shadow-orange:0 12px 26px rgba(243,111,33,.32);\n  --r-xl:26px; --r-lg:18px; --r-md:12px; --r-sm:8px;\n  --container:1200px;\n\n  font-family:'Montserrat',Arial,sans-serif;\n  color:var(--text);\n  background:var(--sky);\n}\n.tv-cotizador *{box-sizing:border-box;margin:0;padding:0}\n.tv-cotizador img{max-width:100%;display:block}\n\n\/* ============ HERO BANNER (full width) ============ *\/\n.tv-hero{\n  position:relative;width:100%;overflow:hidden;\n  border-radius:0 0 var(--r-xl) var(--r-xl);\n}\n.tv-hero-media{position:absolute;inset:0;z-index:0}\n.tv-hero-media img{width:100%;height:100%;object-fit:cover}\n.tv-hero-media::after{\n  content:\"\";position:absolute;inset:0;\n  background:linear-gradient(180deg,rgba(6,31,54,.55) 0%,rgba(6,31,54,.82) 100%);\n}\n.tv-hero-inner{\n  position:relative;z-index:1;\n  max-width:var(--container);margin:0 auto;\n  padding:64px 24px 56px;text-align:center;\n  display:flex;flex-direction:column;align-items:center;\n}\n.tv-hero-eyebrow{\n  font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.16em;\n  color:var(--yellow);margin-bottom:14px;\n  display:inline-flex;align-items:center;gap:9px;\n}\n.tv-hero-eyebrow::before{content:\"\";width:26px;height:2px;background:var(--yellow)}\n.tv-hero-eyebrow::after{content:\"\";width:26px;height:2px;background:var(--yellow)}\n.tv-hero h1{\n  font-family:'Oswald',Impact,sans-serif;font-weight:600;\n  font-size:clamp(30px,5.4vw,60px);text-transform:uppercase;\n  color:#fff;line-height:1.02;margin:0 0 16px;max-width:880px;letter-spacing:.005em;\n}\n.tv-hero h1 span{color:var(--orange)}\n.tv-hero-sub{\n  font-size:clamp(14px,1.6vw,17px);color:rgba(255,255,255,.9);\n  max-width:620px;margin:0 auto;line-height:1.6;\n}\n.tv-hero-points{\n  display:flex;flex-wrap:wrap;justify-content:center;gap:10px 18px;margin-top:26px;\n}\n.tv-hero-point{\n  display:inline-flex;align-items:center;gap:8px;\n  font-size:13px;font-weight:600;color:#fff;\n  background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.2);\n  padding:9px 16px;border-radius:999px;backdrop-filter:blur(4px);\n}\n.tv-hero-point b{color:var(--yellow);font-weight:800}\n\n\/* ============ TRUST BAR ============ *\/\n.tv-trust{background:var(--white);border-bottom:1px solid var(--border)}\n.tv-trust-inner{\n  max-width:var(--container);margin:0 auto;padding:18px 24px;\n  display:flex;align-items:center;justify-content:center;gap:14px 40px;flex-wrap:wrap;\n}\n.tv-trust-label{\n  font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.1em;\n  color:var(--muted);\n}\n.tv-trust-logos{display:flex;align-items:center;gap:30px;flex-wrap:wrap;justify-content:center}\n.tv-trust-logos img{height:42px;width:auto;object-fit:contain;opacity:.8;filter:grayscale(15%);transition:opacity .2s}\n.tv-trust-logos img:hover{opacity:1}\n.tv-trust-badge{\n  display:inline-flex;align-items:center;gap:7px;font-size:12px;font-weight:700;color:var(--navy);\n}\n.tv-trust-badge svg{flex-shrink:0}\n\n\/* ============ WRAP \/ STEPPER ============ *\/\n.tv-wrap{max-width:var(--container);margin:0 auto;padding:28px 24px 64px}\n\n.tv-stepper{\n  position:sticky;top:0;z-index:30;\n  display:flex;align-items:center;\n  background:var(--white);border-radius:var(--r-lg);\n  padding:16px 24px;box-shadow:var(--shadow);margin-bottom:14px;\n  border:1px solid var(--border);\n}\n.tv-st{display:flex;flex-direction:column;align-items:center;gap:6px;flex:1;position:relative}\n.tv-st:not(:last-child)::after{\n  content:'';position:absolute;top:15px;left:58%;width:84%;height:3px;\n  background:var(--border);border-radius:3px;transition:background .3s;\n}\n.tv-st.done:not(:last-child)::after{background:var(--orange)}\n.tv-st-num{\n  width:32px;height:32px;border-radius:50%;border:2px solid var(--border);\n  background:#fff;display:flex;align-items:center;justify-content:center;\n  font-size:13px;font-weight:800;color:var(--muted);\n  position:relative;z-index:1;transition:all .25s;\n  font-family:'Oswald',sans-serif;\n}\n.tv-st.active .tv-st-num{border-color:var(--orange);background:var(--orange);color:#fff;box-shadow:0 0 0 5px rgba(243,111,33,.16)}\n.tv-st.done .tv-st-num{border-color:var(--orange);background:var(--orange);color:#fff}\n.tv-st.done .tv-st-num::after{content:'\u2713';font-size:14px}\n.tv-st.done .tv-st-num{font-size:0}\n.tv-st-label{font-size:11px;font-weight:700;color:var(--muted);white-space:nowrap;text-transform:uppercase;letter-spacing:.04em}\n.tv-st.active .tv-st-label,.tv-st.done .tv-st-label{color:var(--navy)}\n\n\/* ============ MENSAJE DE PROCESO (friendly) ============ *\/\n.tv-step-msg{\n  display:flex;align-items:center;gap:14px;\n  background:linear-gradient(100deg,var(--navy),var(--navy-2));\n  color:#fff;border-radius:var(--r-lg);padding:16px 22px;margin-bottom:20px;\n  box-shadow:var(--shadow);\n}\n.tv-step-msg .ico{\n  width:42px;height:42px;border-radius:12px;background:rgba(249,183,51,.18);\n  display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;\n}\n.tv-step-msg .txt strong{\n  display:block;font-family:'Oswald',sans-serif;font-size:16px;text-transform:uppercase;\n  letter-spacing:.04em;color:#fff;margin-bottom:2px;\n}\n.tv-step-msg .txt span{font-size:13px;color:rgba(255,255,255,.82);line-height:1.5}\n\n\/* ============ TIPO DE SERVICIO ============ *\/\n.tv-tipo-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-bottom:22px}\n.tv-tipo-card{\n  position:relative;background:#fff;border:2px solid var(--border);border-radius:var(--r-lg);\n  cursor:pointer;text-align:left;overflow:hidden;transition:all .2s;box-shadow:var(--shadow);\n}\n.tv-tipo-card:hover{border-color:var(--orange);transform:translateY(-3px);box-shadow:var(--shadow-lg)}\n.tv-tipo-card.selected{border-color:var(--orange)}\n.tv-tipo-card.selected::after{\n  content:\"\u2713\";position:absolute;top:12px;right:12px;z-index:3;\n  width:30px;height:30px;border-radius:50%;background:var(--orange);color:#fff;\n  display:flex;align-items:center;justify-content:center;font-weight:800;font-size:15px;\n  box-shadow:0 4px 10px rgba(243,111,33,.4);\n}\n.tv-tipo-img{\n  width:100%;height:130px;object-fit:cover;display:block;margin:0;border-radius:0;\n}\n.tv-tipo-card .tv-tipo-name{\n  font-family:'Oswald',sans-serif;font-size:18px;text-transform:uppercase;\n  color:var(--navy);margin:14px 16px 3px;letter-spacing:.01em;\n}\n.tv-tipo-card .tv-tipo-sub{font-size:12.5px;color:var(--muted);line-height:1.4;margin:0 16px 16px}\n\n\/* ============ CARDS ============ *\/\n.tv-card{\n  background:#fff;border-radius:var(--r-lg);padding:26px;margin-bottom:18px;\n  box-shadow:var(--shadow);border:1px solid var(--border);\n}\n.tv-card-title{\n  font-family:'Oswald',sans-serif;font-size:16px;text-transform:uppercase;\n  letter-spacing:.06em;color:var(--navy);margin-bottom:18px;\n  display:flex;align-items:center;gap:10px;\n}\n.tv-card-title::after{content:'';flex:1;height:2px;background:var(--border);border-radius:2px}\n\n\/* ============ GRIDS ============ *\/\n.tv-g2{display:grid;grid-template-columns:1fr 1fr;gap:16px}\n.tv-g4{display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:16px}\n\n\/* ============ CAMPOS ============ *\/\n.tv-field{display:flex;flex-direction:column;gap:7px;position:relative}\n.tv-field label{font-size:11px;font-weight:800;color:var(--muted);text-transform:uppercase;letter-spacing:.06em}\n.tv-field input,.tv-field select{\n  height:50px;border:1.5px solid var(--border);border-radius:var(--r-md);\n  padding:0 15px;font-size:14.5px;font-family:'Montserrat',sans-serif;color:var(--text);\n  background:var(--sky-2);outline:none;transition:all .16s;width:100%;\n}\n.tv-field input:focus,.tv-field select:focus{\n  border-color:var(--orange);background:#fff;box-shadow:0 0 0 3px rgba(243,111,33,.12);\n}\n.tv-field input::placeholder{color:#aeb9c3}\n\/* Validaci\u00f3n visual: solo tras interacci\u00f3n del usuario *\/\n.tv-field input:user-invalid{border-color:#e2574c;background:#fef4f3}\n.tv-field input:user-valid:not(:placeholder-shown){border-color:var(--green);background:#f3fbf6}\n.tv-field input:user-valid:not(:placeholder-shown)+.tv-valid-check{opacity:1}\n.tv-valid-check{\n  position:absolute;right:14px;top:34px;color:var(--green);font-weight:800;font-size:15px;\n  opacity:0;transition:opacity .2s;pointer-events:none;\n}\n\n\/* ============ AUTOCOMPLETE ============ *\/\n.tv-ac-drop{\n  position:absolute;top:calc(100% + 6px);left:0;right:0;background:#fff;\n  border:2px solid var(--orange);border-radius:var(--r-md);box-shadow:var(--shadow-lg);\n  z-index:9999;max-height:260px;overflow-y:auto;display:none;\n}\n.tv-ac-drop.open{display:block}\n\n\/* Aeropuertos *\/\n.tv-aero-btn{display:flex;align-items:center;gap:11px;padding:11px 15px;cursor:pointer;border-bottom:1px solid var(--border);transition:background .12s}\n.tv-aero-btn:last-child{border-bottom:none}\n.tv-aero-btn:hover{background:#fff5ee}\n.tv-aero-cod{background:var(--orange);color:#fff;font-size:11px;font-weight:800;padding:4px 8px;border-radius:6px;flex-shrink:0;letter-spacing:.04em}\n.tv-aero-info{display:flex;flex-direction:column;gap:2px}\n.tv-aero-nombre{font-size:13px;font-weight:700;color:var(--text)}\n.tv-aero-ciudad{font-size:11px;color:var(--muted)}\n\n\/* ============ PARADAS ============ *\/\n.tv-parada-row{display:flex;align-items:flex-end;gap:10px;margin-top:14px}\n.tv-parada-row .tv-field{flex:1}\n.tv-btn-rm{\n  width:50px;height:50px;border:1.5px solid var(--border);border-radius:var(--r-md);\n  background:#fff;color:var(--muted);cursor:pointer;display:flex;align-items:center;\n  justify-content:center;font-size:16px;flex-shrink:0;transition:all .15s;\n}\n.tv-btn-rm:hover{background:#fee2e2;border-color:#fca5a5;color:#dc2626}\n.tv-btn-add{\n  display:flex;align-items:center;justify-content:center;gap:7px;\n  border:2px dashed #cdd8e1;border-radius:var(--r-md);padding:13px;font-size:12.5px;\n  font-weight:800;color:var(--orange);cursor:pointer;margin-top:14px;width:100%;\n  background:none;text-transform:uppercase;letter-spacing:.06em;transition:all .15s;\n  font-family:'Montserrat',sans-serif;\n}\n.tv-btn-add:hover{border-color:var(--orange);background:#fff5ee}\n\n\/* ============ TOGGLE ============ *\/\n.tv-toggle-row{display:flex;align-items:center;gap:14px;padding:6px 0}\n.tv-tgl{position:relative;width:50px;height:28px;flex-shrink:0}\n.tv-tgl input{opacity:0;width:0;height:0;position:absolute}\n.tv-tgl-slider{position:absolute;inset:0;background:#d4dde5;border-radius:28px;cursor:pointer;transition:background .2s}\n.tv-tgl-slider::before{content:'';position:absolute;width:22px;height:22px;left:3px;top:3px;background:#fff;border-radius:50%;transition:transform .2s;box-shadow:0 2px 5px rgba(0,0,0,.22)}\n.tv-tgl input:checked+.tv-tgl-slider{background:var(--orange)}\n.tv-tgl input:checked+.tv-tgl-slider::before{transform:translateX(22px)}\n.tv-tgl-label{font-size:15px;font-weight:700;color:var(--text)}\n.tv-tgl-badge{font-size:11px;background:#e8f8ee;color:#1f9a52;padding:4px 11px;border-radius:20px;font-weight:800}\n\n\/* ============ VUELTA ============ *\/\n.tv-puntos-row{display:flex;gap:10px;margin:12px 0 16px}\n.tv-btn-punto{\n  flex:1;padding:12px;border:1.5px solid var(--border);border-radius:var(--r-md);\n  background:#fff;font-size:12.5px;font-weight:800;cursor:pointer;color:var(--muted);\n  text-transform:uppercase;letter-spacing:.04em;transition:all .15s;font-family:'Montserrat',sans-serif;\n}\n.tv-btn-punto.selected{border-color:var(--orange);background:#fff5ee;color:var(--orange)}\n.tv-vuelta-card{background:#fdf6ef;border:1.5px solid #fbddc7;border-radius:var(--r-md);padding:20px;margin-top:8px}\n\n\/* ============ CONTADORES ============ *\/\n.tv-counter{display:flex;align-items:center;gap:14px}\n.tv-ctr-btn{\n  width:48px;height:48px;border:1.5px solid var(--border);border-radius:var(--r-md);\n  background:#fff;font-size:24px;cursor:pointer;display:flex;align-items:center;\n  justify-content:center;color:var(--navy);transition:all .15s;line-height:1;font-family:'Montserrat',sans-serif;\n}\n.tv-ctr-btn:hover{border-color:var(--orange);color:var(--orange);background:#fff5ee}\n.tv-ctr-val{font-size:26px;font-weight:800;min-width:42px;text-align:center;color:var(--navy);font-family:'Oswald',sans-serif}\n.tv-ctr-label{font-size:12.5px;color:var(--muted);font-weight:600}\n\n\/* ============ VEH\u00cdCULOS ============ *\/\n.tv-veh-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:16px}\n.tv-veh-card{\n  position:relative;background:#fff;border:2px solid var(--border);border-radius:var(--r-lg);\n  padding:18px 16px 16px;cursor:pointer;transition:all .2s;text-align:center;\n  box-shadow:var(--shadow);overflow:hidden;\n}\n.tv-veh-card:hover:not(.disabled){border-color:var(--orange);box-shadow:var(--shadow-lg);transform:translateY(-3px)}\n.tv-veh-card.selected{border-color:var(--orange);background:linear-gradient(160deg,#fff7f1,#fff)}\n.tv-veh-card.selected::before{\n  content:\"\u2713 Seleccionado\";position:absolute;top:0;right:0;\n  background:var(--orange);color:#fff;font-size:9.5px;font-weight:800;\n  padding:5px 11px;border-radius:0 0 0 12px;letter-spacing:.05em;text-transform:uppercase;z-index:2;\n}\n.tv-veh-card.disabled{opacity:.32;cursor:not-allowed;pointer-events:none;filter:grayscale(40%)}\n.tv-veh-rec{\n  position:absolute;top:10px;left:16px;right:auto;transform:none;background:var(--yellow);color:var(--navy);\n  font-size:9px;font-weight:900;padding:5px 8px;border-radius:999px;max-width:calc(100% - 32px);\n  letter-spacing:.04em;text-transform:uppercase;white-space:nowrap;z-index:3;\n  box-shadow:0 5px 14px rgba(6,31,54,.14);line-height:1;\n}\n.tv-veh-img{width:100%;height:96px;object-fit:contain;margin:18px 0 12px}\n.tv-veh-name{font-family:'Oswald',sans-serif;font-size:17px;text-transform:uppercase;color:var(--navy);margin-bottom:4px;line-height:1.05}\n.tv-veh-cap{font-size:12px;color:var(--muted);margin-bottom:10px;font-weight:600}\n.tv-veh-price{\n  font-size:22px;font-weight:800;color:var(--orange);font-family:'Oswald',sans-serif;\n  border-top:1.5px dashed var(--border);padding-top:10px;margin-top:2px;\n}\n.tv-veh-manual{\n  display:inline-flex;align-items:center;justify-content:center;margin-top:4px;padding:7px 11px;\n  border:1px solid #bfd2df;border-radius:999px;background:#f1f7fa;color:#35576c;\n  font-size:11px;font-weight:700;line-height:1.2;letter-spacing:.01em;\n}\n\n\/* ============ MAPA ============ *\/\n#tv-map-box{border-radius:var(--r-lg);overflow:hidden;border:2px solid var(--border);margin-bottom:18px;height:300px;display:none;box-shadow:var(--shadow)}\n#tv-map{width:100%;height:100%}\n.tv-dist-badge{\n  display:none;align-items:center;gap:9px;background:#fff;border:1.5px solid var(--border);\n  border-radius:var(--r-md);padding:13px 18px;margin-bottom:18px;font-size:14px;font-weight:700;\n  color:var(--navy);box-shadow:var(--shadow);\n}\n.tv-dist-badge span{color:var(--orange);font-family:'Oswald',sans-serif;font-size:16px}\n\n\/* ============ RESUMEN ============ *\/\n.tv-resumen{\n  background:linear-gradient(155deg,var(--navy),var(--ink));\n  border-radius:var(--r-lg);padding:26px;margin-bottom:18px;box-shadow:var(--shadow-lg);\n  position:relative;overflow:hidden;\n}\n.tv-resumen::before{\n  content:\"\";position:absolute;top:-40px;right:-40px;width:160px;height:160px;\n  background:radial-gradient(circle,rgba(243,111,33,.25),transparent 70%);\n}\n.tv-res-title{font-family:'Oswald',sans-serif;font-size:18px;text-transform:uppercase;color:var(--yellow);margin-bottom:16px;letter-spacing:.05em;position:relative}\n.tv-res-row{display:flex;justify-content:space-between;align-items:center;font-size:13.5px;color:rgba(255,255,255,.72);padding:8px 0;border-bottom:1px solid rgba(255,255,255,.08);position:relative}\n.tv-res-row:last-child{border-bottom:none}\n.tv-res-row .val{font-weight:700;color:#fff}\n.tv-res-row.total-row{font-size:15px;font-weight:800;padding-top:16px;border-top:2px solid rgba(255,255,255,.16);border-bottom:none;margin-top:6px;text-transform:uppercase;font-family:'Oswald',sans-serif;letter-spacing:.04em}\n.tv-res-row.total-row .val{color:var(--yellow);font-size:28px}\n.tv-res-row.desc-row .val{color:var(--green)}\n\n\/* ============ FORMULARIO \/ CONFIRMACI\u00d3N ============ *\/\n.tv-form-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px}\n.tv-conf-block{margin-bottom:16px}\n.tv-conf-label{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.08em;color:var(--muted);margin-bottom:4px}\n.tv-conf-val{font-size:14.5px;font-weight:700;color:var(--text)}\n\n\/* ============ \u00c9XITO ============ *\/\n.tv-success{text-align:center;padding:3rem 1rem}\n.tv-success-icon{font-size:68px;margin-bottom:18px}\n.tv-success-title{font-family:'Oswald',sans-serif;font-size:34px;text-transform:uppercase;color:var(--navy);margin-bottom:10px}\n.tv-success-sub{font-size:14.5px;color:var(--muted);line-height:1.8;margin-bottom:2rem;max-width:560px;margin-left:auto;margin-right:auto}\n\n\/* ============ BOTONES ============ *\/\n.tv-btn-primary{\n  width:100%;background:var(--orange);color:#fff;border:none;border-radius:999px;\n  padding:17px;font-size:14.5px;font-weight:800;font-family:'Montserrat',sans-serif;cursor:pointer;\n  display:flex;align-items:center;justify-content:center;gap:9px;transition:all .18s;\n  text-transform:uppercase;letter-spacing:.05em;box-shadow:var(--shadow-orange);min-height:54px;\n}\n.tv-btn-primary:hover{background:var(--orange-d);transform:translateY(-2px)}\n.tv-btn-primary:disabled{opacity:.4;cursor:not-allowed;box-shadow:none;transform:none;background:var(--muted)}\n.tv-btn-secondary{\n  width:100%;background:#fff;color:var(--navy);border:2px solid var(--border);border-radius:999px;\n  padding:15px;font-size:13.5px;font-weight:800;font-family:'Montserrat',sans-serif;cursor:pointer;\n  transition:all .15s;text-transform:uppercase;letter-spacing:.05em;min-height:54px;\n}\n.tv-btn-secondary:hover{border-color:var(--navy);background:var(--navy);color:#fff}\n.tv-btn-wa{\n  width:100%;background:#25D366;color:#fff;border:none;border-radius:999px;padding:16px;\n  font-size:14.5px;font-weight:800;font-family:'Montserrat',sans-serif;cursor:pointer;\n  display:flex;align-items:center;justify-content:center;gap:9px;text-transform:uppercase;\n  letter-spacing:.05em;min-height:54px;transition:all .18s;\n}\n.tv-btn-wa:hover{background:#1fb558;transform:translateY(-2px)}\n.tv-btn-row{display:flex;gap:12px;margin-top:14px}\n.tv-btn-row>*{margin:0}\n.tv-btn-row .tv-btn-secondary{flex:0 0 auto;width:auto;padding-left:28px;padding-right:28px}\n.tv-btn-row .tv-btn-primary{flex:1}\n.tv-tip{\n  font-size:12px;color:#8a6d2f;margin-top:10px;line-height:1.5;\n  background:#fdf3dc;border-radius:8px;padding:9px 13px;border-left:3px solid var(--yellow);\n}\n.tv-hint{\n  font-size:12.5px;color:var(--navy);margin-bottom:14px;padding:11px 15px;\n  background:var(--sky);border-radius:var(--r-sm);border-left:3px solid var(--aqua);line-height:1.5;\n  overflow-wrap:anywhere;\n}\n.tv-route-warning{\n  display:none;align-items:flex-start;gap:10px;margin:0 0 14px;padding:13px 15px;\n  background:#fff7ed;border:1.5px solid #fed7aa;border-left:4px solid var(--orange);\n  border-radius:var(--r-sm);color:#9a3412;font-size:13px;font-weight:700;line-height:1.45;\n}\n.tv-route-warning .ico{flex:0 0 auto}\n.tv-route-warning strong{color:#7c2d12}\n.tv-route-warning small{display:block;color:#9a3412;font-size:12px;font-weight:600;margin-top:2px}\n.tv-route-warning.show{display:flex}\n\n\/* ============ FOOTER MINI ============ *\/\n.tv-foot{\n  max-width:var(--container);margin:0 auto;padding:26px 24px 72px;text-align:center!important;\n  display:flex;flex-direction:column;align-items:center;justify-content:center;\n}\n.tv-foot p{font-size:12px;color:var(--muted);line-height:1.8;text-align:center!important;margin:0 auto;max-width:920px}\n.tv-foot a{color:var(--orange);font-weight:700;text-decoration:none}\n.tv-foot-secure{display:inline-flex;align-items:center;justify-content:center;gap:8px;font-size:12px;font-weight:700;color:var(--navy);margin:0 auto 10px;text-align:center}\n\n\/* ============ RESPONSIVE ============ *\/\n@media(max-width:920px){\n  .tv-g4{grid-template-columns:1fr 1fr}\n}\n@media(max-width:620px){\n  .tv-wrap{padding:20px 14px 48px}\n  .tv-tipo-grid{grid-template-columns:1fr}\n  .tv-g4,.tv-form-grid,.tv-g2{grid-template-columns:1fr}\n  .tv-veh-grid{grid-template-columns:1fr 1fr}\n  .tv-btn-row{flex-direction:column}\n  .tv-btn-row .tv-btn-secondary{width:100%}\n  .tv-st-label{font-size:0}\n  .tv-st-label::first-letter{font-size:11px}\n  .tv-stepper{padding:14px 12px}\n  .tv-hero-inner{padding:48px 18px 40px}\n  .tv-step-msg{padding:14px 16px}\n  .tv-step-msg .ico{width:38px;height:38px;font-size:19px}\n}\n<\/style>\n\n<script>\n(function(){\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/ DATOS\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nconst AEROPUERTOS=[\n  {n:'Aeropuerto Arturo Merino Ben\u00edtez',ciudad:'Santiago',region:'Regi\u00f3n Metropolitana',cod:'SCL',lat:-33.3930,lng:-70.7858},\n  {n:'Aeropuerto El Tepual',ciudad:'Puerto Montt',region:'Los Lagos',cod:'PMC',lat:-41.4389,lng:-73.0942},\n  {n:'Aeropuerto La Araucan\u00eda',ciudad:'Temuco',region:'La Araucan\u00eda',cod:'ZCO',lat:-38.9267,lng:-72.6511},\n  {n:'Aeropuerto Carriel Sur',ciudad:'Concepci\u00f3n',region:'Biob\u00edo',cod:'CCP',lat:-36.7727,lng:-73.0631},\n  {n:'Aeropuerto El Loa',ciudad:'Calama',region:'Antofagasta',cod:'CJC',lat:-22.4981,lng:-68.9036},\n  {n:'Aeropuerto Diego Aracena',ciudad:'Iquique',region:'Tarapac\u00e1',cod:'IQQ',lat:-20.5352,lng:-70.1814},\n  {n:'Aeropuerto Chacalluta',ciudad:'Arica',region:'Arica y Parinacota',cod:'ARI',lat:-18.3485,lng:-70.3388},\n  {n:'Aeropuerto La Florida',ciudad:'La Serena',region:'Coquimbo',cod:'LSC',lat:-29.9165,lng:-71.1995},\n  {n:'Aeropuerto El Libertador',ciudad:'Balmaceda',region:'Ays\u00e9n',cod:'BBA',lat:-45.9159,lng:-71.6897},\n  {n:'Aeropuerto Carlos Ib\u00e1\u00f1ez del Campo',ciudad:'Punta Arenas',region:'Magallanes',cod:'PUQ',lat:-53.0026,lng:-70.8546},\n  {n:'Aeropuerto Mataveri',ciudad:'Isla de Pascua',region:'Valpara\u00edso',cod:'IPC',lat:-27.1648,lng:-109.4219},\n  {n:'Aeropuerto Andr\u00e9s Sabella',ciudad:'Antofagasta',region:'Antofagasta',cod:'ANF',lat:-23.4444,lng:-70.4451},\n  {n:'Aeropuerto Chamonate',ciudad:'Copiap\u00f3',region:'Atacama',cod:'CPO',lat:-27.2611,lng:-70.7792},\n  {n:'Aeropuerto Pichoy',ciudad:'Valdivia',region:'Los R\u00edos',cod:'ZAL',lat:-39.6500,lng:-73.0861},\n  {n:'Aeropuerto Canal Bajo',ciudad:'Osorno',region:'Los Lagos',cod:'ZOS',lat:-40.6111,lng:-73.0611},\n  {n:'Aeropuerto Teniente Vidal',ciudad:'Coyhaique',region:'Ays\u00e9n',cod:'GXQ',lat:-45.5953,lng:-72.1075},\n  {n:'Aeropuerto Eulogio S\u00e1nchez (Tobalaba)',ciudad:'Santiago',region:'Regi\u00f3n Metropolitana',cod:'TLX',lat:-33.4561,lng:-70.5486},\n  {n:'Aeropuerto Julio Gallardo',ciudad:'Puerto Natales',region:'Magallanes',cod:'PNT',lat:-51.6717,lng:-72.5283},\n];\n\nconst VEHICULOS=[\n  {id:'sedan',nombre:'Sed\u00e1n ejecutivo',img:'https:\/\/turisvina.cl\/wp-content\/uploads\/2025\/03\/a02.png',cap:'3\u20134 pax',maxPax:4,kmMax:1100,base5:10000,espMax:15000},\n  {id:'suv',nombre:'SUV ejecutivo',img:'https:\/\/turisvina.cl\/wp-content\/uploads\/2025\/03\/a03.png',cap:'4\u20135 pax',maxPax:5,kmMax:1300,base5:12000,espMax:18000},\n  {id:'van8',nombre:'Van corta',img:'https:\/\/turisvina.cl\/wp-content\/uploads\/2026\/06\/VAN-CORTA.png',cap:'6\u20138 pax',maxPax:8,kmMax:1500,base5:15000,espMax:18000},\n  {id:'van16',nombre:'Van Sprinter',img:'https:\/\/turisvina.cl\/wp-content\/uploads\/2026\/06\/VAN-SPLINTER.png',cap:'12\u201316 pax',maxPax:16,kmMax:2000,base5:20000,espMax:30000},\n  {id:'mini',nombre:'Minib\u00fas',img:'https:\/\/turisvina.cl\/wp-content\/uploads\/2026\/06\/mini-bus.png',cap:'20\u201330 pax',maxPax:30,kmMax:0,base5:0,espMax:0,manual:true},\n  {id:'bus44',nombre:'Bus turismo',img:'https:\/\/turisvina.cl\/wp-content\/uploads\/2026\/06\/bus-de-44-pasajeros.png',cap:'39\u201345 pax',maxPax:45,kmMax:0,base5:0,espMax:0,manual:true},\n];\n\nconst LIMITE_TARIFA_BASE_KM=5;\nconst RECARGO_NOCTURNO=0.20;\nconst DESCUENTO_IDA_VUELTA=0.10;\n\nconst TIPOS=[\n  {id:'ciudad',img:'https:\/\/turisvina.cl\/wp-content\/uploads\/2026\/06\/vista-distritos-providencia-condes-frente-cordillera-andes-santiago-chile_1599530-1020.avif',name:'Por Chile',sub:'Cualquier direcci\u00f3n en Chile'},\n  {id:'al-aero',img:'https:\/\/turisvina.cl\/wp-content\/uploads\/2026\/06\/hacia-el-aeropeurto-1.png',name:'Hacia el aeropuerto',sub:'Te llevamos a tu vuelo'},\n  {id:'desde-aero',img:'https:\/\/turisvina.cl\/wp-content\/uploads\/2026\/06\/desde-el-aeropeurto.png',name:'Desde el aeropuerto',sub:'Te buscamos en tu llegada'},\n];\n\n\/\/ Mensajes amigables por paso\nconst STEP_MSG={\n  1:{ico:'\ud83d\ude8d',t:'Cu\u00e9ntanos tu viaje',s:'Elige el tipo de servicio, ingresa tu ruta y ver\u00e1s el precio de cada veh\u00edculo al instante.'},\n  2:{ico:'\ud83d\udc4b',t:'\u00bfA qui\u00e9n acompa\u00f1amos?',s:'Solo necesitamos tus datos de contacto para confirmar la reserva y enviarte la cotizaci\u00f3n.'},\n  3:{ico:'\ud83d\udd0d',t:'Revisemos que todo est\u00e9 perfecto',s:'Verifica tu ruta, fecha y datos antes de continuar. Puedes volver atr\u00e1s para editar lo que quieras.'},\n  4:{ico:'\ud83e\udd1d',t:'\u00daltimo paso: confirmemos juntos',s:'Elige c\u00f3mo prefieres cerrar tu reserva. Un ejecutivo confirma la tarifa final contigo.'},\n};\nfunction stepMsg(n){\n  const m=STEP_MSG[n];if(!m)return'';\n  return`<div class=\"tv-step-msg\"><div class=\"ico\">${m.ico}<\/div><div class=\"txt\"><strong>${m.t}<\/strong><span>${m.s}<\/span><\/div><\/div>`;\n}\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/ ESTADO\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nconst S={\n  step:1,tipo:null,\n  origen:'',origenLL:null,\n  destino:'',destinoLL:null,\n  paradas:[],paradasLL:[],\n  fechaIda:'',horaIda:'',\n  vuelta:false,vueltaMismos:true,\n  origenVuelta:'',origenVueltaLL:null,\n  destinoVuelta:'',destinoVueltaLL:null,\n  vueltaDistKm:null,\n  fechaVuelta:'',horaVuelta:'',\n  pax:1,espHoras:0,vehId:null,\n  distKm:null,\n  nombre:'',email:'',tel:'',rut:'',notas:'',ordenReserva:'',\n};\n\nlet mapInst=null;\nconst TV_WHATSAPP_NUM='56323467715';\n\nfunction fmt(n){return '$'+Math.round(n).toLocaleString('es-CL')}\nfunction today(){return new Date().toISOString().split('T')[0]}\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/ C\u00c1LCULO \u2014 tarifa m\u00e1xima\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nfunction calcular(){\n  const v=VEHICULOS.find(x=>x.id===S.vehId);\n  if(!v||!S.distKm) return null;\n  return calcularParaVehiculo(v);\n}\n\nfunction calcularParaVehiculo(v){\n  if(!v||!S.distKm) return null;\n  if(v.manual) return null;\n  const idaKm=S.distKm||0;\n  const vueltaKm=S.vuelta?(S.vueltaMismos?idaKm:(S.vueltaDistKm||0)):0;\n  const kmFact=idaKm;\n  const vueltaKmFact=vueltaKm;\n  const baseIda=kmFact<=LIMITE_TARIFA_BASE_KM?v.base5:0;\n  const baseVuelta=S.vuelta&&vueltaKmFact<=LIMITE_TARIFA_BASE_KM?v.base5:0;\n  const sub=kmFact*v.kmMax;\n  const esp=S.espHoras*v.espMax;\n  const nocheIda=horaNocturna(S.horaIda);\n  const nocheVuelta=S.vuelta&&horaNocturna(S.horaVuelta);\n  let total=sub+baseIda+esp;\n  const recargoNocheIda=nocheIda?total*RECARGO_NOCTURNO:0;\n  total+=recargoNocheIda;\n  const vueltaBaseKm=S.vuelta?vueltaKmFact*v.kmMax:0;\n  let vueltaT=S.vuelta?(vueltaBaseKm+baseVuelta+esp):0;\n  const recargoNocheVuelta=nocheVuelta?vueltaT*RECARGO_NOCTURNO:0;\n  vueltaT+=recargoNocheVuelta;\n  if(S.vuelta) total+=vueltaT;\n  let desc=0;\n  if(S.vuelta){desc=Math.round(total*DESCUENTO_IDA_VUELTA);total-=desc;}\n  return{km:idaKm,kmVuelta:vueltaKm,kmTotal:idaKm+vueltaKm,kmFact,vueltaKmFact,tarifaKm:v.kmMax,sub,baseIda,baseVuelta,esp,vueltaT,desc,total,v,nocheIda,nocheVuelta,recargoNocheIda,recargoNocheVuelta};\n}\n\nfunction horaNocturna(hora){\n  const m=\/^(\\d{2}):(\\d{2})$\/.exec(hora||'');\n  return !!m&&Number(m[1])>=0&&Number(m[1])<6;\n}\n\n\/\/ Descuento adicional del 5% por pagar de inmediato con Getnet.\n\/\/ (Se suma al descuento de ida y vuelta: se aplica SOBRE el total ya calculado.)\n\/\/ \u26a0\ufe0f R\u00e9plica en servidor: TV_Cotizador_Webpay::aplicar_descuento_pago().\nconst DESC_PAGO_INMEDIATO=0.05;\nfunction calcPagoInmediato(total){\n  const desc=Math.round(total*DESC_PAGO_INMEDIATO);\n  return{base:total,desc,total:total-desc};\n}\n\nfunction rutaMinimaOk(){\n  return !!S.distKm&&(!S.vuelta||S.vueltaMismos||!!S.vueltaDistKm);\n}\n\nfunction mensajeRutaMinima(){\n  return 'Debes calcular la distancia de todos los tramos para continuar.';\n}\n\nfunction avisoRutaMinimaHTML(){\n  return `<span class=\"ico\">\u26a0\ufe0f<\/span><span><strong>${mensajeRutaMinima()}<\/strong><small>Por eso el bot\u00f3n para continuar queda deshabilitado.<\/small><\/span>`;\n}\n\nfunction refreshRutaMinima(){\n  const mostrar=S.distKm&&!rutaMinimaOk();\n  document.querySelectorAll('[data-tv-ruta-min]').forEach(el=>{\n    el.classList.toggle('show',!!mostrar);\n    el.innerHTML=mostrar?avisoRutaMinimaHTML():'';\n  });\n}\n\nfunction resumenHTML(){\n  const c=calcular();\n  if(!c) return '';\n  return`<div class=\"tv-resumen\">\n    <div class=\"tv-res-title\">\ud83e\uddfe Tu cotizaci\u00f3n<\/div>\n    <div class=\"tv-res-row\"><span>Kil\u00f3metros considerados<\/span><span class=\"val\">${c.kmTotal} km<\/span><\/div>\n    <div class=\"tv-res-row\"><span>Subtotal traslado<\/span><span class=\"val\">${fmt(c.sub+c.baseIda)}<\/span><\/div>\n    ${c.esp>0?`<div class=\"tv-res-row\"><span>Espera ${S.espHoras} hr${S.espHoras>1?'s':''}<\/span><span class=\"val\">${fmt(c.esp)}<\/span><\/div>`:''}\n    ${c.recargoNocheIda?`<div class=\"tv-res-row\"><span>Recargo nocturno ida (20%)<\/span><span class=\"val\">${fmt(c.recargoNocheIda)}<\/span><\/div>`:''}\n    ${S.vuelta?`<div class=\"tv-res-row\"><span>Viaje de vuelta<\/span><span class=\"val\">${fmt(c.vueltaT-c.recargoNocheVuelta)}<\/span><\/div>`:''}\n    ${c.recargoNocheVuelta?`<div class=\"tv-res-row\"><span>Recargo nocturno incluido en vuelta (20%)<\/span><span class=\"val\">${fmt(c.recargoNocheVuelta)}<\/span><\/div>`:''}\n    ${S.vuelta?`<div class=\"tv-res-row desc-row\"><span>Descuento ida y vuelta (10%)<\/span><span class=\"val\">\u2212${fmt(c.desc)}<\/span><\/div>`:''}\n    <div class=\"tv-res-row total-row\"><span>Total estimado<\/span><span class=\"val\">${fmt(c.total)}<\/span><\/div>\n  <\/div>`;\n}\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/ GOOGLE PLACES AUTOCOMPLETE\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nfunction nomAC(inputId, dropId, onSelect){\n  const inp = document.getElementById(inputId);\n  if(!inp) return;\n  \/\/ Esperar a que Google Maps est\u00e9 listo\n  function init(){\n    const ac = new google.maps.places.Autocomplete(inp, {\n      componentRestrictions: { country: 'cl' },\n      fields: ['formatted_address','geometry','name'],\n      language: 'es',\n      types: ['geocode','establishment'],\n    });\n    ac.addListener('place_changed', () => {\n      const place = ac.getPlace();\n      if(!place.geometry) return;\n      const addr = place.formatted_address || place.name;\n      const ll = {\n        lat: place.geometry.location.lat(),\n        lng: place.geometry.location.lng(),\n      };\n      inp.value = addr;\n      onSelect(addr, ll);\n    });\n  }\n  if(window.google && window.google.maps && window.google.maps.places){\n    init();\n  } else {\n    \/\/ Si Google Maps a\u00fan no carg\u00f3, reintentar\n    const t = setInterval(()=>{\n      if(window.google && window.google.maps && window.google.maps.places){\n        clearInterval(t); init();\n      }\n    }, 200);\n  }\n}\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/ AEROPUERTOS \u2014 SELECTOR CON BOTONES\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nfunction norm(s){return s.toLowerCase().normalize('NFD').replace(\/[\\u0300-\\u036f]\/g,'')}\n\nfunction aeroAC(inputId, dropId, onSelect){\n  const inp = document.getElementById(inputId);\n  const drop = document.getElementById(dropId);\n  if(!inp || !drop) return;\n\n  function renderBotones(){\n    const q = inp.value.trim();\n    const lista = q\n      ? AEROPUERTOS.filter(a => norm(a.n+' '+a.ciudad+' '+a.cod).includes(norm(q)))\n      : AEROPUERTOS;\n    if(!lista.length){ drop.classList.remove('open'); return; }\n    drop.innerHTML = lista.map(a =>\n      `<div class=\"tv-aero-btn\" data-nombre=\"${a.n}\" data-cod=\"${a.cod}\" data-lat=\"${a.lat}\" data-lng=\"${a.lng}\">\n        <span class=\"tv-aero-cod\">${a.cod}<\/span>\n        <span class=\"tv-aero-info\">\n          <span class=\"tv-aero-nombre\">${a.n}<\/span>\n          <span class=\"tv-aero-ciudad\">${a.ciudad} \u00b7 ${a.region}<\/span>\n        <\/span>\n      <\/div>`).join('');\n    drop.classList.add('open');\n    drop.querySelectorAll('.tv-aero-btn').forEach(el => {\n      el.onclick = () => {\n        inp.value = el.dataset.nombre + ' (' + el.dataset.cod + ')';\n        drop.classList.remove('open');\n        const ll = { lat: parseFloat(el.dataset.lat), lng: parseFloat(el.dataset.lng) };\n        onSelect(inp.value, ll);\n        refreshBtn();\n      };\n    });\n  }\n\n  inp.addEventListener('focus', renderBotones);\n  inp.addEventListener('click', renderBotones);\n  inp.addEventListener('input', renderBotones);\n  document.addEventListener('click', e => {\n    if(!inp.contains(e.target) && !drop.contains(e.target))\n      drop.classList.remove('open');\n  });\n}\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/ GOOGLE MAPS + DIRECTIONS API\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nfunction initMapa(){\n  const box = document.getElementById('tv-map-box');\n  if(!box) return;\n  box.style.display = 'block';\n  const mapEl = document.getElementById('tv-map');\n  if(mapInst && mapEl && !mapEl._gmaps_init){\n    mapInst = null;\n  }\n  if(window.google && window.google.maps){\n    crearMapa();\n  } else {\n    const t = setInterval(()=>{\n      if(window.google && window.google.maps){ clearInterval(t); crearMapa(); }\n    }, 200);\n  }\n}\n\nfunction crearMapa(){\n  const el = document.getElementById('tv-map');\n  if(!el) return;\n  el._gmaps_init = true;\n  mapInst = new google.maps.Map(el, {\n    zoom: 9,\n    center: { lat: -33.45, lng: -70.67 },\n    mapTypeControl: false,\n    streetViewControl: false,\n    fullscreenControl: false,\n    styles: [{ featureType: 'poi', elementType: 'labels', stylers: [{ visibility: 'off' }] }],\n  });\n  if(window._dirRenderer) window._dirRenderer.setMap(null);\n  if(window._dirRendererVuelta) window._dirRendererVuelta.setMap(null);\n  window._dirRenderer = new google.maps.DirectionsRenderer({\n    map: mapInst,\n    suppressMarkers: false,\n    polylineOptions: { strokeColor: '#f36f21', strokeWeight: 5, strokeOpacity: 0.9 },\n  });\n  window._dirRendererVuelta = new google.maps.DirectionsRenderer({\n    map: mapInst,\n    suppressMarkers: false,\n    preserveViewport: true,\n    polylineOptions: { strokeColor: '#061f36', strokeWeight: 5, strokeOpacity: 0.78 },\n  });\n  if(S.origenLL && S.destinoLL) dibujarRuta();\n}\n\nfunction dibujarRuta(){\n  if(!S.origenLL || !S.destinoLL) return;\n  const badge = document.getElementById('tv-dist-badge');\n  if(badge){ badge.style.display='flex'; badge.innerHTML='\u23f3 Calculando ruta...'; }\n\n  function llObj(ll){return new google.maps.LatLng(ll.lat, ll.lng);}\n  function kmAprox(a,b){\n    const R=6371, dLat=(b.lat-a.lat)*Math.PI\/180, dLng=(b.lng-a.lng)*Math.PI\/180;\n    const x=Math.sin(dLat\/2)**2+Math.cos(a.lat*Math.PI\/180)*Math.cos(b.lat*Math.PI\/180)*Math.sin(dLng\/2)**2;\n    return Math.round(R*2*Math.atan2(Math.sqrt(x),Math.sqrt(1-x))*1.35);\n  }\n  function sumaLegs(result){\n    return result.routes[0].legs.reduce((sum,leg)=>sum+(leg.distance?.value||0),0);\n  }\n  function sumaDuracion(result){\n    const mins=Math.round(result.routes[0].legs.reduce((sum,leg)=>sum+(leg.duration?.value||0),0)\/60);\n    if(mins<60) return mins+' min';\n    return Math.floor(mins\/60)+' h '+String(mins%60).padStart(2,'0')+' min';\n  }\n  function fitResultados(resultados){\n    if(!mapInst || !resultados.length) return;\n    const bounds=new google.maps.LatLngBounds();\n    resultados.forEach(res=>{\n      (res.routes[0].overview_path||[]).forEach(p=>bounds.extend(p));\n    });\n    if(!bounds.isEmpty()) mapInst.fitBounds(bounds);\n  }\n  function pedirRuta(opts, renderer){\n    const svc = new google.maps.DirectionsService();\n    return new Promise(resolve=>{\n      svc.route({\n        origin: llObj(opts.origin),\n        destination: llObj(opts.destination),\n        waypoints: (opts.waypoints||[]).map(ll=>({location:llObj(ll),stopover:true})),\n        optimizeWaypoints: false,\n        travelMode: google.maps.TravelMode.DRIVING,\n        region: 'CL',\n      }, (result, status) => {\n        if(status === 'OK'){\n          renderer.setDirections(result);\n          resolve({ok:true,result,km:Math.round(sumaLegs(result)\/1000),duracion:sumaDuracion(result)});\n        } else {\n          renderer.set('directions', null);\n          const puntos=[opts.origin,...(opts.waypoints||[]),opts.destination];\n          const km=puntos.slice(1).reduce((sum,p,i)=>sum+kmAprox(puntos[i],p),0);\n          resolve({ok:false,result:null,km,duracion:''});\n        }\n      });\n    });\n  }\n  function calcRuta(){\n    if(!window._dirRenderer || !mapInst){ initMapa(); setTimeout(calcRuta,400); return; }\n    const waypoints=S.paradasLL.filter(Boolean);\n    pedirRuta({origin:S.origenLL,destination:S.destinoLL,waypoints},window._dirRenderer).then(ida=>{\n      S.distKm=ida.km;\n      let pendientes=[ida];\n      const calcularVuelta=S.vuelta&&!S.vueltaMismos&&S.origenVueltaLL&&S.destinoVueltaLL;\n      const listo=()=>{\n        const resultados=pendientes.filter(x=>x.result).map(x=>x.result);\n        if(resultados.length) fitResultados(resultados);\n        const total=S.distKm+(S.vuelta&&!S.vueltaMismos?(S.vueltaDistKm||0):0);\n        if(badge){\n          if(S.vuelta&&!S.vueltaMismos&&S.vueltaDistKm){\n            badge.innerHTML=`\ud83d\udccd Ida: <span>${S.distKm} km<\/span> &nbsp;\u00b7&nbsp; \ud83d\udd04 Regreso: <span>${S.vueltaDistKm} km<\/span> &nbsp;\u00b7&nbsp; Total: <span>${total} km<\/span>`;\n          } else {\n            badge.innerHTML=`\ud83d\udccd Ruta real: <span>${S.distKm} km<\/span> ${ida.duracion?`&nbsp;\u00b7&nbsp; <small style=\"color:#6d7a86;font-weight:500\">\u23f1 ${ida.duracion} aprox.<\/small>`:''}`;\n          }\n        }\n        actualizarVehiculos(); refreshResumen(); refreshBtn();\n      };\n      if(calcularVuelta){\n        pedirRuta({origin:S.origenVueltaLL,destination:S.destinoVueltaLL,waypoints:[]},window._dirRendererVuelta).then(vuelta=>{\n          S.vueltaDistKm=vuelta.km;\n          pendientes.push(vuelta);\n          listo();\n        });\n      } else {\n        S.vueltaDistKm=null;\n        if(window._dirRendererVuelta) window._dirRendererVuelta.set('directions', null);\n        listo();\n      }\n    });\n  }\n  calcRuta();\n}\n\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/ STEPPER\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nfunction updateStepper(){\n  document.querySelectorAll('.tv-st').forEach(el=>{\n    const n=+el.dataset.step;\n    el.className='tv-st'+(n===S.step?' active':'')+(n<S.step?' done':'');\n  });\n}\n\nfunction buildHoras(id,conDisp,val){\n  const s=document.getElementById(id);if(!s)return;\n  s.innerHTML='';\n  \/\/ Primera opci\u00f3n siempre vac\u00eda (placeholder)\n  const placeholder=document.createElement('option');\n  placeholder.value='';\n  placeholder.textContent='Seleccionar hora';\n  placeholder.disabled=true;\n  s.appendChild(placeholder);\n  for(let h=0;h<24;h++)for(let m=0;m<60;m+=30){\n    const hh=String(h).padStart(2,'0'),mm=String(m).padStart(2,'0');\n    const o=document.createElement('option');o.value=`${hh}:${mm}`;o.textContent=`${hh}:${mm}`;s.appendChild(o);\n  }\n  s.value=val||'';\n}\n\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/ ACTUALIZAR SOLO VEH\u00cdCULOS (sin re-render completo)\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nfunction actualizarVehiculos(){\n  const wrap=document.getElementById('tv-veh-wrap');\n  const titulo=document.getElementById('tv-veh-titulo');\n  if(!wrap) return;\n  const sug=VEHICULOS.find(v=>S.pax<=v.maxPax);\n  if(titulo) titulo.textContent='\ud83d\ude97 Elige tu veh\u00edculo'+(S.distKm?' \u2014 ruta de '+S.distKm+' km':'');\n  wrap.innerHTML=VEHICULOS.map(v=>{\n    const ok=S.pax<=v.maxPax;\n    const sel=S.vehId===v.id;\n    const rec=sug&&v.id===sug.id&&!S.vehId;\n    let precioHTML=v.manual&&S.distKm?'<div class=\"tv-veh-manual\">Solicitar cotizaci\u00f3n<\/div>':'';\n    if(S.distKm&&!v.manual){\n      const cVeh=calcularParaVehiculo(v);\n      precioHTML=cVeh?`<div class=\"tv-veh-price\">${fmt(cVeh.total)}<\/div>`:'';\n    }\n    return`<div class=\"tv-veh-card${sel?' selected':''}${!ok?' disabled':''}\" onclick=\"tvSelVeh('${v.id}')\">\n      ${rec?'<div class=\"tv-veh-rec\">\u2605 Sugerido<\/div>':''}\n      <img decoding=\"async\" class=\"tv-veh-img\" src=\"${v.img}\" alt=\"${v.nombre} para transporte privado \u2014 TurisVi\u00f1a\" onerror=\"this.style.display='none'\">\n      <div class=\"tv-veh-name\">${v.nombre}<\/div>\n      <div class=\"tv-veh-cap\">${v.cap}<\/div>\n      ${precioHTML}\n    <\/div>`;\n  }).join('');\n  refreshRutaMinima();\n}\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/ PASO 1\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nfunction renderStep1(){\n  const sug=VEHICULOS.find(v=>S.pax<=v.maxPax);\n  const origenEsAero=S.tipo==='desde-aero';\n  const destinoEsAero=S.tipo==='al-aero';\n\n  document.getElementById('tv-app').innerHTML=`\n  ${stepMsg(1)}\n  <div class=\"tv-card\">\n    <div class=\"tv-card-title\">\ud83e\udded \u00bfQu\u00e9 tipo de traslado necesitas?<\/div>\n    <div class=\"tv-tipo-grid\">\n      ${TIPOS.map(t=>`<div class=\"tv-tipo-card${S.tipo===t.id?' selected':''}\" onclick=\"tvSelTipo('${t.id}')\">\n        <img decoding=\"async\" class=\"tv-tipo-img\" src=\"${t.img}\" alt=\"${t.name} \u2014 transporte privado TurisVi\u00f1a\" onerror=\"this.style.display='none'\">\n        <div class=\"tv-tipo-name\">${t.name}<\/div>\n        <div class=\"tv-tipo-sub\">${t.sub}<\/div>\n      <\/div>`).join('')}\n    <\/div>\n  <\/div>\n\n  <div class=\"tv-card\">\n    <div class=\"tv-card-title\">\ud83d\udccb Datos del viaje<\/div>\n    <div class=\"tv-g4\" style=\"margin-bottom:16px;align-items:end\">\n      <div class=\"tv-field\" style=\"position:relative\">\n        <label>${origenEsAero?'\u2708\ufe0f Aeropuerto origen':'\ud83d\udccd Origen'}<\/label>\n        <input id=\"tv-inp-o\" type=\"text\" placeholder=\"${origenEsAero?'Selecciona aeropuerto...':'Calle, n\u00famero, ciudad...'}\" value=\"${S.origen}\" autocomplete=\"off\">\n        <div class=\"tv-ac-drop\" id=\"tv-drop-o\"><\/div>\n      <\/div>\n      <div class=\"tv-field\" style=\"position:relative\">\n        <label>${destinoEsAero?'\u2708\ufe0f Aeropuerto destino':'\ud83d\udccd Destino'}<\/label>\n        <input id=\"tv-inp-d\" type=\"text\" placeholder=\"${destinoEsAero?'Selecciona aeropuerto...':'Calle, n\u00famero, ciudad...'}\" value=\"${S.destino}\" autocomplete=\"off\">\n        <div class=\"tv-ac-drop\" id=\"tv-drop-d\"><\/div>\n      <\/div>\n      <div class=\"tv-field\">\n        <label>\ud83d\udcc5 Fecha de ida *<\/label>\n        <input id=\"tv-fecha\" type=\"date\" value=\"${S.fechaIda||today()}\" min=\"${today()}\" required>\n      <\/div>\n      <div class=\"tv-field\">\n        <label>\ud83d\udd50 Hora de salida *<\/label>\n        <select id=\"tv-hora\" required><\/select>\n      <\/div>\n    <\/div>\n    <div id=\"tv-paradas-wrap\"><\/div>\n    <button class=\"tv-btn-add\" onclick=\"tvAddParada()\">\uff0b A\u00f1adir parada en el camino<\/button>\n  <\/div>\n\n  <div class=\"tv-card\" style=\"padding:18px 26px\">\n    <div class=\"tv-toggle-row\">\n      <label class=\"tv-tgl\">\n        <input type=\"checkbox\" id=\"tv-tgl-vuelta\" ${S.vuelta?'checked':''} onchange=\"tvSetVuelta(this.checked)\">\n        <span class=\"tv-tgl-slider\"><\/span>\n      <\/label>\n      <span class=\"tv-tgl-label\">\u00bfNecesitas vuelta?<\/span>\n      <span class=\"tv-tgl-badge\">\u2605 10% de descuento<\/span>\n    <\/div>\n    <div id=\"tv-vuelta-sec\" style=\"display:${S.vuelta?'block':'none'}\">\n      <div class=\"tv-vuelta-card\">\n        <div class=\"tv-card-title\" style=\"margin-bottom:12px\">\ud83d\udd04 Datos del regreso<\/div>\n        <div style=\"font-size:12px;font-weight:700;color:#6d7a86;margin-bottom:8px;text-transform:uppercase;letter-spacing:.06em\">\u00bfLa vuelta es entre los mismos puntos?<\/div>\n        <div class=\"tv-puntos-row\">\n          <button class=\"tv-btn-punto${S.vueltaMismos?' selected':''}\" onclick=\"tvSetVueltaMismos(true)\">\u2713 Mismos puntos<\/button>\n          <button class=\"tv-btn-punto${!S.vueltaMismos?' selected':''}\" onclick=\"tvSetVueltaMismos(false)\">Otros puntos<\/button>\n        <\/div>\n        ${!S.vueltaMismos?`\n        <div class=\"tv-g2\" style=\"margin-bottom:14px\">\n          <div class=\"tv-field\" style=\"position:relative\">\n            <label>\ud83d\udccd Origen del regreso<\/label>\n            <input id=\"tv-inp-ov\" type=\"text\" placeholder=\"Direcci\u00f3n...\" value=\"${S.origenVuelta}\" autocomplete=\"off\">\n            <div class=\"tv-ac-drop\" id=\"tv-drop-ov\"><\/div>\n          <\/div>\n          <div class=\"tv-field\" style=\"position:relative\">\n            <label>\ud83d\udccd Destino del regreso<\/label>\n            <input id=\"tv-inp-dv\" type=\"text\" placeholder=\"Direcci\u00f3n...\" value=\"${S.destinoVuelta}\" autocomplete=\"off\">\n            <div class=\"tv-ac-drop\" id=\"tv-drop-dv\"><\/div>\n          <\/div>\n        <\/div>`:''}\n        <div class=\"tv-g2\">\n          <div class=\"tv-field\">\n            <label>\ud83d\udcc5 Fecha de vuelta *<\/label>\n            <input id=\"tv-fv\" type=\"date\" value=\"${S.fechaVuelta}\" min=\"${S.fechaIda||today()}\" required>\n          <\/div>\n          <div class=\"tv-field\">\n            <label>\ud83d\udd50 Hora de vuelta *<\/label>\n            <select id=\"tv-hv\" required><\/select>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <div class=\"tv-dist-badge\" id=\"tv-dist-badge\"><\/div>\n  <div id=\"tv-map-box\"><div id=\"tv-map\"><\/div><\/div>\n\n  <div class=\"tv-card\">\n    <div class=\"tv-card-title\">\ud83d\udc65 Pasajeros y espera<\/div>\n    <div style=\"display:flex;gap:3rem;flex-wrap:wrap\">\n      <div>\n        <div style=\"font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:#6d7a86;margin-bottom:10px\">Pasajeros<\/div>\n        <div class=\"tv-counter\">\n          <button class=\"tv-ctr-btn\" onclick=\"tvSetPax(-1)\">\u2212<\/button>\n          <span class=\"tv-ctr-val\" id=\"tv-pax-val\">${S.pax}<\/span>\n          <button class=\"tv-ctr-btn\" onclick=\"tvSetPax(1)\">+<\/button>\n          <span class=\"tv-ctr-label\">personas<\/span>\n        <\/div>\n      <\/div>\n      <div>\n        <div style=\"font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:#6d7a86;margin-bottom:10px\">Horas de espera en destino<\/div>\n        <div class=\"tv-counter\">\n          <button class=\"tv-ctr-btn\" onclick=\"tvSetEsp(-1)\">\u2212<\/button>\n          <span class=\"tv-ctr-val\" id=\"tv-esp-val\">${S.espHoras}<\/span>\n          <button class=\"tv-ctr-btn\" onclick=\"tvSetEsp(1)\">+<\/button>\n          <span class=\"tv-ctr-label\">horas<\/span>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <div class=\"tv-card\">\n    <div class=\"tv-card-title\" id=\"tv-veh-titulo\">\ud83d\ude97 Elige tu veh\u00edculo${S.distKm?` \u2014 ruta de ${S.distKm} km`:''}<\/div>\n    ${!S.distKm?'<div class=\"tv-hint\">\ud83d\udca1 Ingresa origen y destino y te mostramos el precio total estimado de cada veh\u00edculo, al instante.<\/div>':''}\n    <div class=\"tv-route-warning${S.distKm&&!rutaMinimaOk()?' show':''}\" data-tv-ruta-min>${S.distKm&&!rutaMinimaOk()?avisoRutaMinimaHTML():''}<\/div>\n    <div class=\"tv-veh-grid\" id=\"tv-veh-wrap\">\n      ${VEHICULOS.map(v=>{\n        const ok=S.pax<=v.maxPax;\n        const sel=S.vehId===v.id;\n        const rec=sug&&v.id===sug.id&&!S.vehId;\n        let precioHTML=v.manual&&S.distKm?'<div class=\"tv-veh-manual\">Solicitar cotizaci\u00f3n<\/div>':'';\n        if(S.distKm&&!v.manual){\n          const cVeh=calcularParaVehiculo(v);\n          precioHTML=cVeh?`<div class=\"tv-veh-price\">${fmt(cVeh.total)}<\/div>`:'';\n        }\n        return`<div class=\"tv-veh-card${sel?' selected':''}${!ok?' disabled':''}\" onclick=\"tvSelVeh('${v.id}')\">\n          ${rec?'<div class=\"tv-veh-rec\">\u2605 Sugerido<\/div>':''}\n          <img decoding=\"async\" class=\"tv-veh-img\" src=\"${v.img}\" alt=\"${v.nombre} para transporte privado \u2014 TurisVi\u00f1a\" onerror=\"this.style.display='none'\">\n          <div class=\"tv-veh-name\">${v.nombre}<\/div>\n          <div class=\"tv-veh-cap\">${v.cap}<\/div>\n          ${precioHTML}\n        <\/div>`;\n      }).join('')}\n    <\/div>\n  <\/div>\n\n  <div id=\"tv-resumen-wrap\">${S.vehId&&S.distKm&&rutaMinimaOk()?resumenHTML():''}<\/div>\n\n  <div class=\"tv-route-warning${S.distKm&&!rutaMinimaOk()?' show':''}\" data-tv-ruta-min>${S.distKm&&!rutaMinimaOk()?avisoRutaMinimaHTML():''}<\/div>\n  <button class=\"tv-btn-primary\" id=\"tv-btn-cont\" onclick=\"tvIrPaso2()\" ${!S.origen||!S.destino||!S.vehId||!rutaMinimaOk()?'disabled':''}>\n    Continuar \u2192 Datos del pasajero\n  <\/button>`;\n\n  buildHoras('tv-hora',false,S.horaIda);\n  buildHoras('tv-hv',true,S.horaVuelta);\n  document.getElementById('tv-fecha').onchange=e=>{S.fechaIda=e.target.value;};\n  document.getElementById('tv-hora').onchange=e=>{S.horaIda=e.target.value;actualizarVehiculos();refreshResumen();};\n  const fv=document.getElementById('tv-fv');if(fv)fv.onchange=e=>{S.fechaVuelta=e.target.value;};\n  const hv=document.getElementById('tv-hv');if(hv)hv.onchange=e=>{S.horaVuelta=e.target.value;actualizarVehiculos();refreshResumen();};\n\n  if(origenEsAero) aeroAC('tv-inp-o','tv-drop-o',(val,ll)=>{S.origen=val;S.origenLL=ll;onDirSelect();});\n  else nomAC('tv-inp-o','tv-drop-o',(val,ll)=>{S.origen=val;S.origenLL=ll;onDirSelect();});\n  if(destinoEsAero) aeroAC('tv-inp-d','tv-drop-d',(val,ll)=>{S.destino=val;S.destinoLL=ll;onDirSelect();});\n  else nomAC('tv-inp-d','tv-drop-d',(val,ll)=>{S.destino=val;S.destinoLL=ll;onDirSelect();});\n  const io=document.getElementById('tv-inp-o');if(io)io.addEventListener('input',e=>{S.origen=e.target.value;S.origenLL=null;S.distKm=null;});\n  const id=document.getElementById('tv-inp-d');if(id)id.addEventListener('input',e=>{S.destino=e.target.value;S.destinoLL=null;S.distKm=null;});\n  if(!S.vueltaMismos){\n    nomAC('tv-inp-ov','tv-drop-ov',(val,ll)=>{S.origenVuelta=val;S.origenVueltaLL=ll;onDirSelect();});\n    nomAC('tv-inp-dv','tv-drop-dv',(val,ll)=>{S.destinoVuelta=val;S.destinoVueltaLL=ll;onDirSelect();});\n    const iov=document.getElementById('tv-inp-ov');if(iov)iov.addEventListener('input',e=>{S.origenVuelta=e.target.value;S.origenVueltaLL=null;S.vueltaDistKm=null;});\n    const idv=document.getElementById('tv-inp-dv');if(idv)idv.addEventListener('input',e=>{S.destinoVuelta=e.target.value;S.destinoVueltaLL=null;S.vueltaDistKm=null;});\n  }\n  renderParadas();\n  if(S.origenLL&&S.destinoLL){initMapa();setTimeout(dibujarRuta,300);}\n}\n\nfunction onDirSelect(){\n  refreshBtn();\n  if(S.origenLL&&S.destinoLL){initMapa();setTimeout(dibujarRuta,500);}\n}\n\nfunction renderParadas(){\n  const wrap=document.getElementById('tv-paradas-wrap');if(!wrap)return;\n  wrap.innerHTML=S.paradas.map((p,i)=>`\n    <div class=\"tv-parada-row\">\n      <div class=\"tv-field\" style=\"position:relative;flex:1\">\n        <label>\ud83d\udccc Parada ${i+1}<\/label>\n        <input id=\"tv-par-${i}\" type=\"text\" placeholder=\"Direcci\u00f3n de parada...\" value=\"${p||''}\" autocomplete=\"off\">\n        <div class=\"tv-ac-drop\" id=\"tv-dpar-${i}\"><\/div>\n      <\/div>\n      <button class=\"tv-btn-rm\" onclick=\"tvRmParada(${i})\">\u2715<\/button>\n    <\/div>`).join('');\n  S.paradas.forEach((_,i)=>{\n    const inp=document.getElementById(`tv-par-${i}`);\n    if(inp) inp.addEventListener('input',e=>{S.paradas[i]=e.target.value;S.paradasLL[i]=null;});\n    nomAC(`tv-par-${i}`,`tv-dpar-${i}`,(val,ll)=>{S.paradas[i]=val;S.paradasLL[i]=ll;onDirSelect();});\n  });\n}\n\nfunction refreshResumen(){\n  const w=document.getElementById('tv-resumen-wrap');\n  if(w) w.innerHTML=S.vehId&&S.distKm&&rutaMinimaOk()?resumenHTML():'';\n}\nfunction refreshBtn(){\n  const b=document.getElementById('tv-btn-cont');\n  if(b) b.disabled=(!S.origen||!S.destino||!S.vehId||!rutaMinimaOk());\n  refreshRutaMinima();\n}\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/ PASO 2\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nfunction renderStep2(){\n  document.getElementById('tv-app').innerHTML=`\n  ${stepMsg(2)}\n  <div class=\"tv-card\">\n    <div class=\"tv-card-title\">\ud83d\udc64 Datos del pasajero<\/div>\n    <div class=\"tv-form-grid\">\n      <div class=\"tv-field\"><label>Nombre completo *<\/label><input id=\"tv-nom\" type=\"text\" placeholder=\"Juan P\u00e9rez\" value=\"${S.nombre}\" required><span class=\"tv-valid-check\">\u2713<\/span><\/div>\n      <div class=\"tv-field\"><label>RUT *<\/label><input id=\"tv-rut\" type=\"text\" placeholder=\"12.345.678-9\" value=\"${S.rut}\" required><span class=\"tv-valid-check\">\u2713<\/span><\/div>\n      <div class=\"tv-field\"><label>Correo electr\u00f3nico *<\/label><input id=\"tv-email\" type=\"email\" placeholder=\"correo@ejemplo.cl\" value=\"${S.email}\" required><span class=\"tv-valid-check\">\u2713<\/span><\/div>\n      <div class=\"tv-field\"><label>Tel\u00e9fono \/ WhatsApp *<\/label><input id=\"tv-tel\" type=\"tel\" placeholder=\"+56 9 XXXX XXXX\" value=\"${S.tel}\" required><span class=\"tv-valid-check\">\u2713<\/span><\/div>\n    <\/div>\n    <div class=\"tv-field\" style=\"margin-top:14px\">\n      <label>Notas adicionales<\/label>\n      <input id=\"tv-notas\" type=\"text\" placeholder=\"Equipaje especial, silla de beb\u00e9, instrucciones...\" value=\"${S.notas}\">\n    <\/div>\n    <div class=\"tv-tip\" style=\"margin-top:16px\">\ud83d\udd12 Usamos tus datos solo para coordinar este servicio. Te enviaremos una copia de la cotizaci\u00f3n a tu correo.<\/div>\n  <\/div>\n  <div class=\"tv-btn-row\">\n    <button class=\"tv-btn-secondary\" onclick=\"tvIrPaso(1)\">\u2190 Volver<\/button>\n    <button class=\"tv-btn-primary\" onclick=\"tvIrPaso3()\">Continuar \u2192 Confirmaci\u00f3n<\/button>\n  <\/div>`;\n}\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/ PASO 3\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nfunction renderStep3(){\n  const c=calcular();\n  const veh=VEHICULOS.find(v=>v.id===S.vehId);\n  const cotizacionManual=!!veh?.manual;\n  const tipoLabel=TIPOS.find(t=>t.id===S.tipo)?.name||'\u2014';\n  const webpayOn=!!(window.tvCotizadorWebpay&&+window.tvCotizadorWebpay);\n  const promo=webpayOn&&c&&!cotizacionManual?calcPagoInmediato(c.total):null;\n  document.getElementById('tv-app').innerHTML=`\n  ${stepMsg(3)}\n  <div class=\"tv-card\">\n    <div class=\"tv-card-title\">\ud83d\ude97 Resumen del servicio<\/div>\n    <div class=\"tv-g2\">\n      <div class=\"tv-conf-block\"><div class=\"tv-conf-label\">Tipo<\/div><div class=\"tv-conf-val\">${tipoLabel}<\/div><\/div>\n      <div class=\"tv-conf-block\"><div class=\"tv-conf-label\">Veh\u00edculo<\/div><div class=\"tv-conf-val\">${veh?.nombre} (${veh?.cap})<\/div><\/div>\n      <div class=\"tv-conf-block\"><div class=\"tv-conf-label\">Origen<\/div><div class=\"tv-conf-val\">\ud83d\udccd ${S.origen}<\/div><\/div>\n      <div class=\"tv-conf-block\"><div class=\"tv-conf-label\">Destino<\/div><div class=\"tv-conf-val\">\ud83d\udccd ${S.destino}<\/div><\/div>\n      <div class=\"tv-conf-block\"><div class=\"tv-conf-label\">Fecha y hora<\/div><div class=\"tv-conf-val\">\ud83d\udcc5 ${S.fechaIda} \u00b7 \ud83d\udd50 ${S.horaIda}<\/div><\/div>\n      <div class=\"tv-conf-block\"><div class=\"tv-conf-label\">Pasajeros<\/div><div class=\"tv-conf-val\">\ud83d\udc65 ${S.pax}<\/div><\/div>\n      ${S.espHoras>0?`<div class=\"tv-conf-block\"><div class=\"tv-conf-label\">Espera<\/div><div class=\"tv-conf-val\">\u23f3 ${S.espHoras} hora${S.espHoras>1?'s':''}<\/div><\/div>`:''}\n      ${S.paradas.filter(p=>p).length?`<div class=\"tv-conf-block\" style=\"grid-column:1\/-1\"><div class=\"tv-conf-label\">Paradas<\/div><div class=\"tv-conf-val\">${S.paradas.filter(p=>p).map((p,i)=>`\ud83d\udccc ${i+1}: ${p}`).join('<br>')}<\/div><\/div>`:''}\n      ${S.vuelta?`<div class=\"tv-conf-block\" style=\"grid-column:1\/-1\"><div class=\"tv-conf-label\">Regreso<\/div><div class=\"tv-conf-val\">\ud83d\udd04 ${S.vueltaMismos?S.destino+' \u2192 '+S.origen:S.origenVuelta+' \u2192 '+S.destinoVuelta} \u00b7 \ud83d\udcc5 ${S.fechaVuelta} \u00b7 \ud83d\udd50 ${S.horaVuelta}<\/div><\/div>`:''}\n    <\/div>\n  <\/div>\n  <div class=\"tv-card\">\n    <div class=\"tv-card-title\">\ud83d\udc64 Pasajero<\/div>\n    <div class=\"tv-g2\">\n      <div class=\"tv-conf-block\"><div class=\"tv-conf-label\">Nombre<\/div><div class=\"tv-conf-val\">${S.nombre}<\/div><\/div>\n      <div class=\"tv-conf-block\"><div class=\"tv-conf-label\">RUT<\/div><div class=\"tv-conf-val\">${S.rut||'\u2014'}<\/div><\/div>\n      <div class=\"tv-conf-block\"><div class=\"tv-conf-label\">Correo<\/div><div class=\"tv-conf-val\">${S.email}<\/div><\/div>\n      <div class=\"tv-conf-block\"><div class=\"tv-conf-label\">Tel\u00e9fono<\/div><div class=\"tv-conf-val\">${S.tel}<\/div><\/div>\n      ${S.notas?`<div class=\"tv-conf-block\" style=\"grid-column:1\/-1\"><div class=\"tv-conf-label\">Notas<\/div><div class=\"tv-conf-val\">${S.notas}<\/div><\/div>`:''}\n    <\/div>\n  <\/div>\n  ${c?resumenHTML():`<div style=\"background:#f1f7fa;border:1px solid #bfd2df;border-radius:12px;padding:12px 16px;font-size:13px;color:#35576c;margin-bottom:16px\">\u2139\ufe0f ${cotizacionManual?'Este veh\u00edculo requiere una cotizaci\u00f3n personalizada. Enviaremos tu solicitud para que un ejecutivo te contacte con el valor.':'TurisVi\u00f1a confirmar\u00e1 el precio al contactarte.'}<\/div>`}\n  ${promo?`\n  <div class=\"tv-card\" style=\"padding:0;overflow:hidden;border:2px solid #f36f21\">\n    <div style=\"background:#f36f21;padding:14px 22px;display:flex;align-items:center;gap:10px\">\n      <span style=\"font-size:22px\">\ud83c\udf81<\/span>\n      <div>\n        <div style=\"font-family:'Oswald',sans-serif;font-size:16px;font-weight:700;color:#fff;text-transform:uppercase;letter-spacing:.04em\">Paga ahora y obt\u00e9n un 5% de descuento<\/div>\n        <div style=\"font-size:12px;color:rgba(255,255,255,.92)\">Descuento adicional exclusivo por pagar en l\u00ednea con Getnet${S.vuelta?' \u2014 se suma a tu 10% de ida y vuelta':''}<\/div>\n      <\/div>\n    <\/div>\n    <div style=\"padding:18px 22px\">\n      <div style=\"display:flex;justify-content:space-between;font-size:14px;color:#53616d;padding:4px 0\">\n        <span>Total estimado<\/span><span style=\"text-decoration:line-through\">${fmt(promo.base)}<\/span>\n      <\/div>\n      <div style=\"display:flex;justify-content:space-between;font-size:14px;color:#1a7f37;font-weight:700;padding:4px 0\">\n        <span>Descuento pago inmediato (5%)<\/span><span>\u2212${fmt(promo.desc)}<\/span>\n      <\/div>\n      <div style=\"display:flex;justify-content:space-between;align-items:center;border-top:2px solid #e4edf3;margin-top:8px;padding-top:10px\">\n        <span style=\"font-family:'Oswald',sans-serif;font-size:15px;font-weight:700;color:#061f36;text-transform:uppercase;letter-spacing:.04em\">Total pagando ahora<\/span>\n        <span style=\"font-family:'Oswald',sans-serif;font-size:26px;font-weight:700;color:#f36f21\">${fmt(promo.total)}<\/span>\n      <\/div>\n      <div style=\"display:flex;flex-direction:column;gap:10px;margin-top:14px\">\n        <button class=\"tv-btn-primary\" id=\"tv-btn-webpay\" onclick=\"tvPagarWebpay()\" style=\"margin:0;width:100%\">\n          \ud83d\udcb3 Pagar ahora ${fmt(promo.total)} con Getnet\n        <\/button>\n        <div style=\"text-align:center;font-size:11px;color:#6d7a86\">Pago seguro procesado por Getnet \u2014 cr\u00e9dito, d\u00e9bito y prepago<\/div>\n        <button class=\"tv-btn-secondary\" id=\"tv-btn-reservar\" onclick=\"tvReservar()\" style=\"margin:0;width:100%\">\n          Reservar y coordinar el pago despu\u00e9s (${fmt(promo.base)})\n        <\/button>\n      <\/div>\n    <\/div>\n  <\/div>\n  <div class=\"tv-btn-row\">\n    <button class=\"tv-btn-secondary\" onclick=\"tvIrPaso(2)\">\u2190 Volver<\/button>\n  <\/div>`:`\n  <div class=\"tv-btn-row\">\n    <button class=\"tv-btn-secondary\" onclick=\"tvIrPaso(2)\">\u2190 Volver<\/button>\n    <button class=\"tv-btn-primary\" id=\"tv-btn-reservar\" onclick=\"tvReservar()\">Reservar ahora \u2192<\/button>\n  <\/div>`}`;\n}\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/ PASO 5\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nfunction renderStep5(){\n  const c=calcular();\n  const veh=VEHICULOS.find(v=>v.id===S.vehId);\n  const tipoLabel=TIPOS.find(t=>t.id===S.tipo)?.name||'\u2014';\n  document.getElementById('tv-app').innerHTML=`\n  <div class=\"tv-success\">\n    <div class=\"tv-success-icon\">\ud83c\udf89<\/div>\n    <div class=\"tv-success-title\">\u00a1Solicitud enviada!<\/div>\n    <div class=\"tv-success-sub\">\n      Hemos recibido tu cotizaci\u00f3n y enviado una copia a <strong>${S.email}<\/strong>.<br>\n      Un ejecutivo de TurisVi\u00f1a te contactar\u00e1 pronto para confirmar los detalles y coordinar el pago.\n    <\/div>\n    <!-- Resumen visual para el cliente -->\n    <div style=\"background:#f5f9fc;border:1.5px solid #e4edf3;border-radius:14px;padding:20px;max-width:480px;margin:0 auto 24px;text-align:left\">\n      <div style=\"font-family:'Oswald',sans-serif;font-size:13px;text-transform:uppercase;color:#061f36;letter-spacing:.06em;margin-bottom:12px\">Detalle de tu solicitud<\/div>\n      <div style=\"font-size:13px;color:#27313b;line-height:2\">\n        <b>\ud83d\udccb Servicio:<\/b> ${tipoLabel}<br>\n        <b>\ud83d\ude97 Veh\u00edculo:<\/b> ${veh?.nombre||'\u2014'} (${veh?.cap||''})<br>\n        <b>\ud83d\udccd Origen:<\/b> ${S.origen}<br>\n        <b>\ud83d\udccd Destino:<\/b> ${S.destino}<br>\n        <b>\ud83d\udc65 Pasajeros:<\/b> ${S.pax}<br>\n        <b>\ud83d\udcc5 Fecha:<\/b> ${S.fechaIda} \u00b7 <b>\ud83d\udd50<\/b> ${S.horaIda}<br>\n        ${S.espHoras>0?`<b>\u23f3 Espera:<\/b> ${S.espHoras} hora${S.espHoras>1?'s':''}<br>`:''}\n        ${S.vuelta?`<b>\ud83d\udd04 Vuelta:<\/b> ${S.vueltaMismos?S.destino+' \u2192 '+S.origen:S.origenVuelta+' \u2192 '+S.destinoVuelta}<br>`:''}\n        ${c?`<b style=\"color:#f36f21\">\ud83d\udcb0 Total estimado: ${fmt(c.total)}<\/b>`:'<b>\ud83d\udcb0 Precio:<\/b> A confirmar'}\n      <\/div>\n    <\/div>\n    <div style=\"font-size:12px;color:#6d7a86;margin-bottom:20px\">\n      \u00bfPreguntas? Escr\u00edbenos directamente:<br>\n      <strong style=\"color:#f36f21\">+56 323467715 \u00b7 ventas@turisvina.cl<\/strong>\n    <\/div>\n    <div style=\"max-width:320px;margin:0 auto;display:flex;flex-direction:column;gap:10px\">\n      <button class=\"tv-btn-wa\" onclick=\"tvEnviarWA()\">\ud83d\udcf1 Tambi\u00e9n enviar por WhatsApp<\/button>\n      <button class=\"tv-btn-secondary\" onclick=\"tvReiniciar()\">Nueva cotizaci\u00f3n<\/button>\n    <\/div>\n  <\/div>`;\n}\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/ NAVEGACI\u00d3N \u2014 expuestas globalmente\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nfunction tvIrPaso(n){S.step=n;updateStepper();tvRender();window.scrollTo(0,0);}\nfunction tvRender(){\n  if(S.step===1) renderStep1();\n  else if(S.step===2) renderStep2();\n  else if(S.step===3) renderStep3();\n  else renderStep5(); \/\/ paso 4 = finalizado (eliminamos pantalla intermedia)\n}\n\nwindow.tvSelTipo=id=>{S.tipo=id;S.origen='';S.destino='';S.origenLL=null;S.destinoLL=null;S.paradas=[];S.paradasLL=[];S.distKm=null;S.vueltaDistKm=null;mapInst=null;tvRender();};\nwindow.tvSetVuelta=v=>{\n  S.vuelta=v;\n  const s=document.getElementById('tv-vuelta-sec');\n  if(s) s.style.display=v?'block':'none';\n  if(!v) S.vueltaDistKm=null;\n  if(S.origenLL&&S.destinoLL) setTimeout(dibujarRuta,300);\n  actualizarVehiculos(); refreshResumen();\n  refreshBtn();\n};\nwindow.tvSetVueltaMismos=v=>{S.vueltaMismos=v;S.vueltaDistKm=null;renderStep1();};\nwindow.tvSetPax=d=>{\n  S.pax=Math.max(1,Math.min(45,S.pax+d));\n  S.vehId=null;\n  const el=document.getElementById('tv-pax-val');\n  if(el) el.textContent=S.pax;\n  \/\/ Solo actualizar grilla, sin re-renderizar todo\n  actualizarVehiculos();\n  refreshResumen();\n  refreshBtn();\n};\nwindow.tvSetEsp=d=>{\n  S.espHoras=Math.max(0,Math.min(12,S.espHoras+d));\n  const el=document.getElementById('tv-esp-val');\n  if(el) el.textContent=S.espHoras;\n  actualizarVehiculos();\n  refreshResumen();\n};\nwindow.tvSelVeh=id=>{\n  const veh=VEHICULOS.find(v=>v.id===id);\n  if(!veh||S.pax>veh.maxPax) return;\n  S.vehId=id;\n  \/\/ Solo actualizar grilla veh\u00edculos y resumen, sin tocar los inputs\n  actualizarVehiculos();\n  refreshResumen();\n  refreshBtn();\n};\nwindow.tvAddParada=()=>{S.paradas.push('');S.paradasLL.push(null);renderParadas();};\nwindow.tvRmParada=i=>{S.paradas.splice(i,1);S.paradasLL.splice(i,1);renderParadas();if(S.origenLL&&S.destinoLL)dibujarRuta();};\nwindow.tvIrPaso=tvIrPaso;\n\nwindow.tvIrPaso2=()=>{\n  S.origen=document.getElementById('tv-inp-o')?.value||S.origen;\n  S.destino=document.getElementById('tv-inp-d')?.value||S.destino;\n  S.origenVuelta=document.getElementById('tv-inp-ov')?.value||S.origenVuelta;\n  S.destinoVuelta=document.getElementById('tv-inp-dv')?.value||S.destinoVuelta;\n  S.fechaIda=document.getElementById('tv-fecha')?.value||S.fechaIda;\n  S.horaIda=document.getElementById('tv-hora')?.value||S.horaIda;\n  S.fechaVuelta=document.getElementById('tv-fv')?.value||S.fechaVuelta;\n  S.horaVuelta=document.getElementById('tv-hv')?.value||S.horaVuelta;\n  if(!S.origen||!S.destino||!S.vehId){alert('Completa origen, destino y selecciona un veh\u00edculo.');return;}\n  if(!S.fechaIda||!\/^\\d{4}-\\d{2}-\\d{2}$\/.test(S.fechaIda)){alert('Selecciona la fecha de ida.');return;}\n  if(!S.horaIda||!(\/^(?:[01]\\d|2[0-3]):[0-5]\\d$\/).test(S.horaIda)){alert('Selecciona la hora de salida.');return;}\n  if(S.vuelta&&(!S.fechaVuelta||!\/^\\d{4}-\\d{2}-\\d{2}$\/.test(S.fechaVuelta))){alert('Selecciona la fecha de vuelta.');return;}\n  if(S.vuelta&&(!S.horaVuelta||!(\/^(?:[01]\\d|2[0-3]):[0-5]\\d$\/).test(S.horaVuelta))){alert('Selecciona la hora de vuelta.');return;}\n  if(!rutaMinimaOk()){alert(mensajeRutaMinima());return;}\n  tvIrPaso(2);\n};\nwindow.tvIrPaso3=()=>{\n  S.nombre=document.getElementById('tv-nom')?.value||'';\n  S.email=document.getElementById('tv-email')?.value||'';\n  S.tel=document.getElementById('tv-tel')?.value||'';\n  S.rut=document.getElementById('tv-rut')?.value||'';\n  S.notas=document.getElementById('tv-notas')?.value||'';\n  if(!S.nombre||!S.rut||!S.email||!S.tel){alert('Completa nombre, RUT, correo y tel\u00e9fono.');return;}\n  if(!(\/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$\/).test(S.email)){alert('Ingresa un correo electr\u00f3nico v\u00e1lido.');return;}\n  tvIrPaso(3);\n};\n\nwindow.tvReservar=async()=>{\n  \/\/ Deshabilitar bot\u00f3n para evitar doble clic\n  const btn=document.getElementById('tv-btn-reservar');\n  if(btn){btn.disabled=true;btn.textContent='Enviando...';}\n  await tvEnviarCorreo(true); \/\/ true = llamado desde reservar\n};\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/ GETNET WEB CHECKOUT\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/ Resumen de texto del viaje (compartido entre correo y pago)\nfunction tvResumenTexto(total){\n  const veh=VEHICULOS.find(v=>v.id===S.vehId);\n  const tipoLabel=TIPOS.find(t=>t.id===S.tipo)?.name||'\u2014';\n  return`\nSOLICITUD DE COTIZACI\u00d3N \u2014 TURISVI\u00d1A\n=====================================\n\ud83d\udccb Tipo de servicio: ${tipoLabel}\n\ud83d\ude97 Veh\u00edculo: ${veh?.nombre||'\u2014'} (${veh?.cap||''})\n\ud83d\udccd Origen: ${S.origen}\n\ud83d\udccd Destino: ${S.destino}\n${S.paradas.filter(p=>p).map((p,i)=>`\ud83d\udccc Parada ${i+1}: ${p}`).join('\\n')}\n\ud83d\udc65 Pasajeros: ${S.pax}\n\ud83d\udcc5 Fecha: ${S.fechaIda} \u2014 \ud83d\udd50 Hora: ${S.horaIda}\n${S.espHoras>0?`\u23f3 Espera en destino: ${S.espHoras} hora${S.espHoras>1?'s':''}`:'' }\n${S.vuelta?`\ud83d\udd04 Vuelta: ${S.vueltaMismos?S.destino+' \u2192 '+S.origen:S.origenVuelta+' \u2192 '+S.destinoVuelta} | ${S.fechaVuelta} ${S.horaVuelta}`:''}\n=====================================\n\ud83d\udc64 Nombre: ${S.nombre}\n\ud83d\udce7 Correo: ${S.email}\n\ud83d\udcf1 Tel\u00e9fono: ${S.tel}\n\ud83e\udeaa RUT: ${S.rut||'No indicado'}\n${S.notas?`\ud83d\udcdd Notas: ${S.notas}`:''}\n=====================================\n\ud83d\udcb0 TOTAL ESTIMADO: ${total}\n`;\n}\n\nwindow.tvPagarWebpay=async()=>{\n  if(VEHICULOS.find(v=>v.id===S.vehId)?.manual){alert('El veh\u00edculo seleccionado se cotiza de forma personalizada y no admite pago en l\u00ednea.');return;}\n  const btn=document.getElementById('tv-btn-webpay');\n  if(btn){btn.disabled=true;btn.textContent='Conectando con Getnet...';}\n  const c=calcular();\n  if(!c){alert('No se pudo calcular el total. Vuelve al paso 1 y verifica origen, destino y veh\u00edculo.');if(btn){btn.disabled=false;}return;}\n  const promo=calcPagoInmediato(c.total);\n  const veh=VEHICULOS.find(v=>v.id===S.vehId);\n  const tipoLabel=TIPOS.find(t=>t.id===S.tipo)?.name||'\u2014';\n\n  \/\/ Paquete de datos: el texto del resumen (para correos) + los datos CRUDOS\n  \/\/ para que el SERVIDOR recalcule y valide el monto (incluido el 5% extra).\n  const datos={\n    nombre:S.nombre,\n    email:S.email,\n    telefono:S.tel,\n    rut:S.rut||'',\n    fecha_ida:S.fechaIda,\n    hora_ida:S.horaIda,\n    fecha_vuelta:S.fechaVuelta||'',\n    hora_vuelta:S.horaVuelta||'',\n    tipo:tipoLabel,\n    vehiculo:`${veh?.nombre||'\u2014'} (${veh?.cap||''})`,\n    mensaje:tvResumenTexto(fmt(promo.total)+' (incluye 5% dcto. pago inmediato)'),\n    \/\/ \u2500\u2500 datos crudos de c\u00e1lculo \u2500\u2500\n    veh_id:S.vehId,\n    dist_km:S.distKm,\n    vuelta_dist_km:S.vueltaDistKm||0,\n    espera_horas:S.espHoras,\n    vuelta:S.vuelta,\n    vuelta_mismos:S.vueltaMismos,\n    o_ll:S.origenLL,\n    d_ll:S.destinoLL,\n    paradas_ll:S.paradasLL.filter(Boolean),\n    ov_ll:S.origenVueltaLL,\n    dv_ll:S.destinoVueltaLL,\n    pagina:window.location.href.split('?')[0],\n  };\n\n  try{\n    const ajaxUrl=(window.tvCotizadorAjaxUrl)||new URL('\/wp-admin\/admin-ajax.php', window.location.origin).toString();\n    const payload=new FormData();\n    payload.append('action','tv_iniciar_pago');\n    payload.append('nonce',window.tvCotizadorPagoNonce||'');\n    payload.append('datos',JSON.stringify(datos));\n    payload.append('tv_hp','');\n\n    const r=await fetch(ajaxUrl,{method:'POST',body:payload,credentials:'same-origin'});\n    const data=await r.json();\n    if(data&&data.success&&data.data&&data.data.url&&data.data.token){\n      \/\/ Redirecci\u00f3n oficial a Getnet Web Checkout.\n      window.location.href=data.data.url;\n    } else {\n      console.warn('Getnet error:',data);\n      alert((data&&data.data&&data.data.message)||'No se pudo iniciar el pago. Intenta nuevamente o usa \"Reservar y coordinar el pago despu\u00e9s\".');\n      if(btn){btn.disabled=false;btn.textContent='\ud83d\udcb3 Reintentar pago con Getnet';}\n    }\n  }catch(e){\n    console.warn('Getnet error:',e);\n    alert('No se pudo conectar con Getnet. Revisa tu conexi\u00f3n e intenta nuevamente.');\n    if(btn){btn.disabled=false;btn.textContent='\ud83d\udcb3 Reintentar pago con Getnet';}\n  }\n};\n\n\/\/ Pantalla de resultado al volver desde Getnet (?tv_pago=...)\nfunction tvRenderResultadoPago(p){\n  const app=document.getElementById('tv-app');\n  if(!app) return false;\n  const orden=p.get('tv_orden')||'';\n  const monto=p.get('tv_monto')?'$'+(+p.get('tv_monto')).toLocaleString('es-CL'):'';\n  const auth=p.get('tv_auth')||'';\n  const res=p.get('tv_pago');\n\n  const M={\n    exito:{ico:'\u2705',t:'\u00a1Pago exitoso!',s:'Tu reserva qued\u00f3 confirmada y pagada con tu 5% de descuento por pago inmediato. Te enviamos el comprobante a tu correo y un ejecutivo te contactar\u00e1 para coordinar los detalles.',color:'#1a7f37'},\n    pendiente:{ico:'\u23f3',t:'Pago pendiente',s:'Getnet a\u00fan est\u00e1 procesando la transacci\u00f3n. Si el banco aprueba el pago, actualizaremos la reserva autom\u00e1ticamente y te enviaremos el comprobante.',color:'#9a6700'},\n    rechazado:{ico:'\u274c',t:'Pago rechazado',s:'Tu banco rechaz\u00f3 la transacci\u00f3n. No se realiz\u00f3 ning\u00fan cobro. Puedes intentar con otra tarjeta o coordinar el pago con nosotros por WhatsApp.',color:'#cf222e'},\n    anulado:{ico:'\u21a9\ufe0f',t:'Pago anulado',s:'Anulaste el pago antes de completarlo. No se realiz\u00f3 ning\u00fan cobro. Puedes cotizar nuevamente cuando quieras.',color:'#57606a'},\n    expirado:{ico:'\u23f0',t:'Sesi\u00f3n de pago expirada',s:'El formulario de pago expir\u00f3 por inactividad. No se realiz\u00f3 ning\u00fan cobro. Vuelve a cotizar para intentarlo de nuevo.',color:'#9a6700'},\n    error:{ico:'\u26a0\ufe0f',t:'Ocurri\u00f3 un problema con el pago',s:'No pudimos confirmar el estado de tu transacci\u00f3n. Si ves un cargo en tu tarjeta, cont\u00e1ctanos por WhatsApp indicando tu n\u00famero de orden.',color:'#cf222e'},\n  };\n  const m=M[res];\n  if(!m) return false;\n\n  \/\/ Ocultar stepper (no aplica en esta pantalla)\n  const st=document.getElementById('tv-stepper');\n  if(st) st.style.display='none';\n\n  app.innerHTML=`\n  <div class=\"tv-success\">\n    <div class=\"tv-success-icon\">${m.ico}<\/div>\n    <div class=\"tv-success-title\" style=\"color:${m.color}\">${m.t}<\/div>\n    <div class=\"tv-success-sub\">${m.s}<\/div>\n    ${orden?`\n    <div style=\"background:#f5f9fc;border:1.5px solid #e4edf3;border-radius:14px;padding:20px;max-width:420px;margin:0 auto 24px;text-align:left\">\n      <div style=\"font-family:'Oswald',sans-serif;font-size:13px;text-transform:uppercase;color:#061f36;letter-spacing:.06em;margin-bottom:12px\">Detalle<\/div>\n      <div style=\"font-size:13px;color:#27313b;line-height:2\">\n        <b>\ud83e\uddfe Orden:<\/b> ${orden}<br>\n        ${monto?`<b>\ud83d\udcb0 Monto:<\/b> ${monto}<br>`:''}\n        ${auth?`<b>\ud83d\udd10 C\u00f3digo de autorizaci\u00f3n:<\/b> ${auth}<br>`:''}\n      <\/div>\n    <\/div>`:''}\n    <div style=\"max-width:320px;margin:0 auto;display:flex;flex-direction:column;gap:10px\">\n      ${!['exito','pendiente'].includes(res)?`<button class=\"tv-btn-wa\" onclick=\"window.open('https:\/\/wa.me\/${TV_WHATSAPP_NUM}?text='+encodeURIComponent('Hola TurisVi\u00f1a! Tuve un problema con el pago de mi reserva'+('${orden}'?' (orden ${orden})':'')+'. \u00bfMe pueden ayudar?'),'_blank')\">\ud83d\udcf1 Contactar por WhatsApp<\/button>`:''}\n      <button class=\"tv-btn-secondary\" onclick=\"window.location.href=window.location.pathname\">Nueva cotizaci\u00f3n<\/button>\n    <\/div>\n  <\/div>`;\n  window.scrollTo(0,0);\n  return true;\n}\n\nwindow.tvEnviarCorreo=async(desdeReservar=false)=>{\n  const c=calcular();\n  const veh=VEHICULOS.find(v=>v.id===S.vehId);\n  const tipoLabel=TIPOS.find(t=>t.id===S.tipo)?.name||'\u2014';\n  const total=c?fmt(c.total):'A confirmar por TurisVi\u00f1a';\n\n  const resumen=tvResumenTexto(total);\n\n  \/\/ Mostrar cargando (siempre sobre el bot\u00f3n de reservar, no el de Getnet)\n  const btn=document.getElementById('tv-btn-reservar')||document.querySelector('.tv-btn-primary');\n  const btnTexto=btn?btn.textContent:'';\n  if(btn){btn.disabled=true;btn.textContent='Enviando...';}\n\n  try{\n    const ajaxUrl=(window.tvCotizadorAjaxUrl)||new URL('\/wp-admin\/admin-ajax.php', window.location.origin).toString();\n    const payload=new FormData();\n    payload.append('action','tv_enviar_cotizacion');\n    payload.append('nombre',S.nombre);\n    payload.append('email',S.email);\n    payload.append('telefono',S.tel);\n    payload.append('rut',S.rut||'');\n    payload.append('fecha_ida',S.fechaIda||'');\n    payload.append('hora_ida',S.horaIda||'');\n    payload.append('vuelta',S.vuelta?'1':'0');\n    payload.append('fecha_vuelta',S.fechaVuelta||'');\n    payload.append('hora_vuelta',S.horaVuelta||'');\n    payload.append('tipo',tipoLabel);\n    payload.append('vehiculo',`${veh?.nombre||'\u2014'} (${veh?.cap||''})`);\n    payload.append('total',total);\n    payload.append('mensaje',resumen);\n    payload.append('tv_hp','');\n\n    const r=await fetch(ajaxUrl,{\n      method:'POST',\n      body:payload,\n      credentials:'same-origin'\n    });\n    const data=await r.json();\n    if(data.success){\n      S.ordenReserva=data.data?.orden||S.ordenReserva||'';\n      tvIrPaso(4);\n    } else {\n      console.warn('Email error:',data);\n      alert(data.data?.message||'No pudimos enviar el correo. Por favor intenta nuevamente o env\u00eda la solicitud por WhatsApp.');\n      if(btn){btn.disabled=false;btn.textContent=btnTexto||'Reservar ahora \u2192';}\n    }\n  }catch(e){\n    console.warn('Email error:',e);\n    alert('No pudimos conectar con WordPress para enviar el correo. Por favor intenta nuevamente o env\u00eda la solicitud por WhatsApp.');\n    if(btn){btn.disabled=false;btn.textContent=btnTexto||'Reservar ahora \u2192';}\n  }\n};\n\nwindow.tvEnviarWA=()=>{\n  const c=calcular();\n  const veh=VEHICULOS.find(v=>v.id===S.vehId);\n  const lineas=[\n    'Hola TurisVi\u00f1a! Quiero cotizar un servicio:','',\n    S.ordenReserva?`\ud83e\uddfe Orden: ${S.ordenReserva}`:null,\n    `\ud83d\udccb Tipo: ${TIPOS.find(t=>t.id===S.tipo)?.name||'\u2014'}`,\n    `\ud83d\ude97 Veh\u00edculo: ${veh?.nombre||'\u2014'} (${veh?.cap||''})`,\n    `\ud83d\udccd Origen: ${S.origen}`,`\ud83d\udccd Destino: ${S.destino}`,\n    ...S.paradas.filter(p=>p).map((p,i)=>`\ud83d\udccc Parada ${i+1}: ${p}`),\n    `\ud83d\udc65 Pasajeros: ${S.pax}`,\n    `\ud83d\udcc5 Fecha: ${S.fechaIda} \u00b7 \ud83d\udd50 ${S.horaIda}`,\n    S.espHoras>0?`\u23f3 Espera: ${S.espHoras} hora${S.espHoras>1?'s':''}`:null,\n    S.vuelta?`\ud83d\udd04 Vuelta: ${S.vueltaMismos?S.destino+' \u2192 '+S.origen:S.origenVuelta+' \u2192 '+S.destinoVuelta} \u00b7 ${S.fechaVuelta} ${S.horaVuelta}`:null,\n    '','\ud83d\udc64 '+S.nombre,'\ud83d\udce7 '+S.email,'\ud83d\udcf1 '+S.tel,\n    S.notas?'\ud83d\udcdd '+S.notas:null,\n    '',c?`\ud83d\udcb0 Total estimado: ${fmt(c.total)}`:'\ud83d\udcb0 Precio: a confirmar',\n  ].filter(l=>l!==null);\n  window.open('https:\/\/wa.me\/'+TV_WHATSAPP_NUM+'?text='+encodeURIComponent(lineas.join('\\n')),'_blank');\n};\n\nwindow.tvReiniciar=()=>{\n  Object.assign(S,{step:1,tipo:null,origen:'',destino:'',origenLL:null,destinoLL:null,paradas:[],paradasLL:[],fechaIda:'',horaIda:'',vuelta:false,vueltaMismos:true,origenVuelta:'',origenVueltaLL:null,destinoVuelta:'',destinoVueltaLL:null,vueltaDistKm:null,fechaVuelta:'',horaVuelta:'',pax:1,espHoras:0,vehId:null,distKm:null,nombre:'',email:'',tel:'',rut:'',notas:'',ordenReserva:''});\n  mapInst=null;updateStepper();tvRender();\n};\n\n\/\/ ARRANQUE\n\/\/ Si venimos de vuelta desde Getnet (?tv_pago=...), mostrar el resultado\n\/\/ del pago en vez del formulario; si no, iniciar el cotizador normal.\nconst tvParams=new URLSearchParams(window.location.search);\nif(tvParams.get('tv_pago')){\n  if(!tvRenderResultadoPago(tvParams)) tvRender();\n} else {\n  tvRender();\n}\n})();\n<\/script>\n<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p class=\"tx-excerpt\"><\/p>","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-5083","page","type-page","status-publish","hentry"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Cotizar Transporte Privado | Transfer Aeropuerto o ciudad<\/title>\n<meta name=\"description\" content=\"Cotiza online tu traslado privado en Chile. Transfer aeropuerto SCL, transporte ejecutivo y van para grupos. Precio inmediato. Cobertura nacional 24\/7\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/turisvina.cl\/en\/cotizar-transfer\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Transfer Aeropuerto y Ciudad | Cotiza en Chile\" \/>\n<meta property=\"og:description\" content=\"Reserva o cotiza tu transfer al aeropuerto, ciudad o destino especial en Chile. Veh\u00edculos privados, servicio formal y atenci\u00f3n disponible 24\/7.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/turisvina.cl\/en\/cotizar-transfer\/\" \/>\n<meta property=\"og:site_name\" content=\"Turisvi\u00f1a\" \/>\n<meta property=\"article:modified_time\" content=\"2026-07-09T17:26:32+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/turisvina.cl\/wp-content\/uploads\/2026\/06\/desde-el-aeropeurto-1024x683.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"683\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/turisvina.cl\\\/cotizar-transfer\\\/\",\"url\":\"https:\\\/\\\/turisvina.cl\\\/cotizar-transfer\\\/\",\"name\":\"Cotizar Transporte Privado | Transfer Aeropuerto o ciudad\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/turisvina.cl\\\/#website\"},\"datePublished\":\"2026-06-28T17:06:33+00:00\",\"dateModified\":\"2026-07-09T17:26:32+00:00\",\"description\":\"Cotiza online tu traslado privado en Chile. Transfer aeropuerto SCL, transporte ejecutivo y van para grupos. Precio inmediato. Cobertura nacional 24\\\/7\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/turisvina.cl\\\/cotizar-transfer\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/turisvina.cl\\\/cotizar-transfer\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/turisvina.cl\\\/cotizar-transfer\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Portada\",\"item\":\"https:\\\/\\\/turisvina.cl\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Cotizar transfer\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/turisvina.cl\\\/#website\",\"url\":\"https:\\\/\\\/turisvina.cl\\\/\",\"name\":\"Turisvi\u00f1a\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/turisvina.cl\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/turisvina.cl\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/turisvina.cl\\\/#organization\",\"name\":\"Turisvi\u00f1a\",\"url\":\"https:\\\/\\\/turisvina.cl\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/turisvina.cl\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/turisvina.cl\\\/wp-content\\\/uploads\\\/2024\\\/03\\\/turisvinalogo.png\",\"contentUrl\":\"https:\\\/\\\/turisvina.cl\\\/wp-content\\\/uploads\\\/2024\\\/03\\\/turisvinalogo.png\",\"width\":766,\"height\":315,\"caption\":\"Turisvi\u00f1a\"},\"image\":{\"@id\":\"https:\\\/\\\/turisvina.cl\\\/#\\\/schema\\\/logo\\\/image\\\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Cotizar Transporte Privado | Transfer Aeropuerto o ciudad","description":"Cotiza online tu traslado privado en Chile. Transfer aeropuerto SCL, transporte ejecutivo y van para grupos. Precio inmediato. Cobertura nacional 24\/7","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/turisvina.cl\/en\/cotizar-transfer\/","og_locale":"en_US","og_type":"article","og_title":"Transfer Aeropuerto y Ciudad | Cotiza en Chile","og_description":"Reserva o cotiza tu transfer al aeropuerto, ciudad o destino especial en Chile. Veh\u00edculos privados, servicio formal y atenci\u00f3n disponible 24\/7.","og_url":"https:\/\/turisvina.cl\/en\/cotizar-transfer\/","og_site_name":"Turisvi\u00f1a","article_modified_time":"2026-07-09T17:26:32+00:00","og_image":[{"width":1024,"height":683,"url":"https:\/\/turisvina.cl\/wp-content\/uploads\/2026\/06\/desde-el-aeropeurto-1024x683.png","type":"image\/png"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/turisvina.cl\/cotizar-transfer\/","url":"https:\/\/turisvina.cl\/cotizar-transfer\/","name":"Cotizar Transporte Privado | Transfer Aeropuerto o ciudad","isPartOf":{"@id":"https:\/\/turisvina.cl\/#website"},"datePublished":"2026-06-28T17:06:33+00:00","dateModified":"2026-07-09T17:26:32+00:00","description":"Cotiza online tu traslado privado en Chile. Transfer aeropuerto SCL, transporte ejecutivo y van para grupos. Precio inmediato. Cobertura nacional 24\/7","breadcrumb":{"@id":"https:\/\/turisvina.cl\/cotizar-transfer\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/turisvina.cl\/cotizar-transfer\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/turisvina.cl\/cotizar-transfer\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Portada","item":"https:\/\/turisvina.cl\/"},{"@type":"ListItem","position":2,"name":"Cotizar transfer"}]},{"@type":"WebSite","@id":"https:\/\/turisvina.cl\/#website","url":"https:\/\/turisvina.cl\/","name":"Turisvi\u00f1a","description":"","publisher":{"@id":"https:\/\/turisvina.cl\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/turisvina.cl\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/turisvina.cl\/#organization","name":"Turisvi\u00f1a","url":"https:\/\/turisvina.cl\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/turisvina.cl\/#\/schema\/logo\/image\/","url":"https:\/\/turisvina.cl\/wp-content\/uploads\/2024\/03\/turisvinalogo.png","contentUrl":"https:\/\/turisvina.cl\/wp-content\/uploads\/2024\/03\/turisvinalogo.png","width":766,"height":315,"caption":"Turisvi\u00f1a"},"image":{"@id":"https:\/\/turisvina.cl\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/turisvina.cl\/en\/wp-json\/wp\/v2\/pages\/5083","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/turisvina.cl\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/turisvina.cl\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/turisvina.cl\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/turisvina.cl\/en\/wp-json\/wp\/v2\/comments?post=5083"}],"version-history":[{"count":64,"href":"https:\/\/turisvina.cl\/en\/wp-json\/wp\/v2\/pages\/5083\/revisions"}],"predecessor-version":[{"id":5417,"href":"https:\/\/turisvina.cl\/en\/wp-json\/wp\/v2\/pages\/5083\/revisions\/5417"}],"wp:attachment":[{"href":"https:\/\/turisvina.cl\/en\/wp-json\/wp\/v2\/media?parent=5083"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}