<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" /> <title>ITIEW Agent Panel</title> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Cinzel:wght@500;600&display=swap" media="print" onload="this.media='all'"> <noscript><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Cinzel:wght@500;600&display=swap"></noscript> <style> :root{ /* ✅ Default accent: PURE WHITE */ --itiew-accent: #ffffff; --accent: var(--itiew-accent); /* ✅ Derived accent vars (computed by JS; defaults here for first paint) */ --itiew-accent-text: rgba(255,255,255,0.98); --itiew-accent-subtext: rgba(255,255,255,0.92); --itiew-accent-border: rgba(255,255,255,0.28); --itiew-accent-glow: rgba(255,255,255,0.18); /* ✅ Global sleek glass background (NO BLUR) */ --itiew-glass-dark: rgba(0,0,0,0.72); --itiew-glass-medium: rgba(0,0,0,0.58); --itiew-glass-light: rgba(0,0,0,0.45); --itiew-glass-bg: var(--itiew-glass-light); --itiew-panel-bg: var(--itiew-glass-bg); --itiew-hero-bg: rgba(0,0,0,0.0); --itiew-panel-border: rgba(255,255,255,0.16); --itiew-text: #ffffff; --itiew-soft: rgba(255,255,255,0.78); /* Kept for compatibility (NOT USED) */ --itiew-blur: 0px; --itiew-radius: 16px; /* ========================= (0.1) PANEL SIZE OVERRIDES ========================= */ --itiew-panel-w: 100vw; --itiew-panel-max-w: 100vw; --itiew-panel-h: 100dvh; --itiew-panel-max-h: 100dvh; --itiew-panel-w-desktop: 37vw; --itiew-panel-max-w-desktop: 640px; /* ========================= (0.3) ICON CONTROLS (DO NOT MOVE) ========================= */ --itiew-icons-top: 3px; --itiew-icons-right: 5px; --itiew-icons-gap: 7px; --itiew-palette-btn-size: 22px; --itiew-palette-icon-size: 25px; --itiew-palette-offset-x: 0px; --itiew-palette-offset-y: 0px; --itiew-close-btn-size: 22px; --itiew-close-font-size: 21px; --itiew-close-offset-x: 0px; --itiew-close-offset-y: 1px; /* ========================= (0.8) COMPANY LOGO SIZE ========================= */ --itiew-company-logo-size: 75px; --itiew-company-logo-cap: 23vh; /* ========================= (1.0) HERO IMAGE CONTROLS (overridden via JS settings) ========================= */ --itiew-hero-container-w: 100%; --itiew-hero-container-h: auto; --itiew-hero-img-w: 100%; --itiew-hero-img-h: 100%; --itiew-hero-object-pos: 50% 12%; --itiew-hero-width: 100%; --itiew-hero-height: 85dvh; --itiew-hero-bleed: 1.02; --itiew-hero-origin: 50% 50%; --itiew-overlay-side: 10px; --itiew-overlay-bottom: 10px; /* legacy (not used for final positioning) */ --itiew-agent-meta-max-h: 24vh; --itiew-contact-max-h: 42vh; /* ========================= (0.7) CONTACT PILLS ========================= */ --itiew-pill-font: 10.8px; --itiew-pill-pad-y: 5px; --itiew-pill-pad-x: 10px; --itiew-pill-gap: 8px; /* ========================= (1.2) CONTACT BUTTON CONTROLS ========================= */ --itiew-bottom-pill-font: 11px; --itiew-bottom-pill-pad-y: 7px; --itiew-bottom-pill-pad-x: 16px; --itiew-toggle-left: 50%; --itiew-toggle-bottom: 12px; /* legacy (not used for final positioning) */ --itiew-toggle-translate-x: -50%; --itiew-toggle-translate-y: 0px; --itiew-toggle-width: min(340px, calc(100% - 24px)); --itiew-toggle-radius: 12px; /* ✅ Bottom button MUST stay visible above everything */ --itiew-toggle-z: 30; /* ✅ Dynamic measured contact pill height */ --itiew-pill-h: 44px; /* ✅ Overlay stacking when agent+company are shown together */ --itiew-stack-gap: 8px; /* configurable via JS settings */ --itiew-anno-top: 0px; --itiew-anno-side: 0px; --itiew-anno-w-mobile: 51vw; --itiew-anno-scale-user-mobile: 1; --itiew-anno-scale-user-desktop: 1; --itiew-fs-hint-offset-mobile: -50px; --itiew-fs-hint-offset-desktop: -107px; --itiew-fs-toast-offset-mobile: -65px; --itiew-fs-toast-offset-desktop: -119px; --itiew-fs-hint-bottom-mobile: calc(14px + var(--itiew-pill-h) + 50px + env(safe-area-inset-bottom, 0px) + var(--itiew-fs-hint-offset-mobile)); --itiew-fs-hint-bottom-desktop: calc(14px + var(--itiew-pill-h) + 50px + env(safe-area-inset-bottom, 0px) + var(--itiew-fs-hint-offset-desktop)); --itiew-fs-toast-bottom-mobile: calc(14px + var(--itiew-pill-h) + 50px + env(safe-area-inset-bottom, 0px) + var(--itiew-fs-toast-offset-mobile)); --itiew-fs-toast-bottom-desktop: calc(14px + var(--itiew-pill-h) + 50px + env(safe-area-inset-bottom, 0px) + var(--itiew-fs-toast-offset-desktop)); } html.itiew-dim-dark{ --itiew-glass-bg: var(--itiew-glass-dark); } html.itiew-dim-medium{ --itiew-glass-bg: var(--itiew-glass-medium); } html.itiew-dim-light{ --itiew-glass-bg: var(--itiew-glass-light); } html, body{ height: 100%; margin: 0; padding: 0; background: #000; } html.itiew-pagebg-on, body.itiew-pagebg-on{ background: transparent !important; } /* Standalone page background host (optional) */ #itiewPageBgHost{ position: fixed !important; inset: 0 !important; z-index: 2147483000 !important; overflow: hidden !important; display: none !important; pointer-events: none !important; background: #000 !important; } #itiewPageBgHost.itiew-open{ display:block !important; pointer-events: auto !important; } #itiewPageBgHost *{ pointer-events: auto !important; } #itiewPageBgHost::after{ content:""; position:absolute; inset:0; background: rgba(0,0,0,0.18); pointer-events:none; } #itiewPageBgHost iframe{ width: 100% !important; height: 100% !important; border: 0 !important; display:block !important; background: transparent !important; } #itiewPageBgHost img, #itiewPageBgHost video{ width: 100% !important; height: 100% !important; border: 0 !important; display:block !important; object-fit: cover !important; background: transparent !important; } *{ box-sizing: border-box; -webkit-tap-highlight-color: transparent; } #context_info{ position: fixed !important; top: 0 !important; right: 0 !important; left: auto !important; bottom: auto !important; margin: 0 !important; width: var(--itiew-panel-w) !important; max-width: var(--itiew-panel-max-w) !important; height: var(--itiew-panel-h) !important; max-height: var(--itiew-panel-max-h) !important; overflow: hidden !important; /* ✅ Global glass */ background: var(--itiew-hero-bg) !important; border: 0px solid var(--itiew-panel-border) !important; border-radius: var(--itiew-radius) !important; color: var(--itiew-text) !important; font-family: "Cinzel", serif !important; /* ✅ Remove padding so hero can reach absolute bottom/edges */ padding: 0 !important; z-index: 2147483647 !important; display: block !important; visibility: visible !important; opacity: 0 !important; transform: translateY(-10px) !important; pointer-events: none !important; transition: opacity .25s ease, transform .25s ease !important; /* ✅ Base bottom = 1px above bottom pill */ --itiew-overlay-base-bottom: calc(3px + env(safe-area-inset-bottom, 0px) + var(--itiew-pill-h) + 5px); /* ✅ Contact height offset (computed by JS) */ --itiew-contact-stack: 0px; } @media (min-width: 769px){ #context_info{ width: var(--itiew-panel-w-desktop) !important; max-width: var(--itiew-panel-max-w-desktop) !important; --itiew-hero-origin: 50% 0%; } } #context_info.itiew-open{ opacity: 1 !important; transform: translateY(0) !important; pointer-events: auto !important; } #context_info:fullscreen, #context_info:-webkit-full-screen{ background: var(--itiew-panel-bg) !important; } #context_info.itiew-open.itiew-bg-clickable{ pointer-events: none !important; } #context_info.itiew-open.itiew-bg-clickable .agent-meta, #context_info.itiew-open.itiew-bg-clickable .contact-area, #context_info.itiew-open.itiew-bg-clickable .contact-toggle, #context_info.itiew-open.itiew-bg-clickable .ci-top, #context_info.itiew-open.itiew-bg-clickable .hero-frame, #context_info.itiew-open.itiew-bg-clickable .hero-frame .agent-img, #context_info.itiew-open.itiew-bg-clickable .itiew-bg-host, #context_info.itiew-open.itiew-bg-clickable .itiew-bg-host *, #context_info.itiew-open.itiew-bg-clickable #itiewPaletteMenu, #context_info.itiew-open.itiew-bg-clickable #itiew_fsToast.itiew-open, #context_info.itiew-open.itiew-bg-clickable #itiewFsHint, #context_info.itiew-open.itiew-bg-clickable #itiewAdminOverlay.itiew-open{ pointer-events: auto !important; } /* ===== Layout ===== */ #context_info .ci-wrap{ position: relative !important; width: 100% !important; height: 100% !important; min-height: 100% !important; padding: 0 !important; margin: 0 !important; } /* ===== Top-right icons (LOCKED) ===== */ #context_info .ci-top{ position:absolute !important; top: var(--itiew-icons-top) !important; right: var(--itiew-icons-right) !important; display:flex !important; align-items:center !important; justify-content:flex-end !important; gap: var(--itiew-icons-gap) !important; z-index: 140 !important; pointer-events: auto !important; } #context_info .ci-palette, #context_info .ci-close{ background: transparent !important; border: 0 !important; padding: 0 !important; margin: 0 !important; color: #fff !important; cursor: pointer !important; display:flex !important; align-items:center !important; justify-content:center !important; user-select:none !important; filter: drop-shadow(0 2px 10px rgba(0,0,0,0.55)) !important; } #context_info .ci-palette:active, #context_info .ci-close:active{ transform: translateY(1px) !important; } #context_info .ci-palette{ width: var(--itiew-palette-btn-size) !important; height: var(--itiew-palette-btn-size) !important; position: relative !important; left: var(--itiew-palette-offset-x) !important; top: var(--itiew-palette-offset-y) !important; } #context_info .ci-palette::before{ content:""; width: var(--itiew-palette-icon-size); height: var(--itiew-palette-icon-size); display:block; background-repeat:no-repeat; background-position:center; background-size: var(--itiew-palette-icon-size) var(--itiew-palette-icon-size); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none'%3E%3Cpath d='M12 3c-5 0-9 3.9-9 8.7C3 16.1 6.6 20 11 20h2.2c1.1 0 2-.9 2-2 0-.5-.2-1-.5-1.3-.3-.4-.5-.8-.5-1.3 0-1.1.9-2 2-2h1.2c2 0 3.8-1.7 3.8-3.9C21.2 5.9 16.8 3 12 3Z' stroke='%23ffffff' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3Ccircle cx='8.2' cy='10.2' r='1.05' fill='%23ffffff'/%3E%3Ccircle cx='11.2' cy='7.8' r='1.05' fill='%23ffffff'/%3E%3Ccircle cx='14.8' cy='8.5' r='1.05' fill='%23ffffff'/%3E%3Ccircle cx='16.2' cy='11.6' r='1.05' fill='%23ffffff'/%3E%3C/svg%3E"); opacity: .98; } /* ===== Admin dashboard overlay (same glass style) ===== */ #itiewAdminOverlay{ position:absolute !important; left: var(--itiew-overlay-side) !important; right: var(--itiew-overlay-side) !important; bottom: var(--itiew-overlay-base-bottom) !important; top: auto !important; z-index: 200 !important; opacity: 0 !important; transform: translateY(18px) !important; pointer-events: none !important; transition: opacity .22s ease, transform .22s ease !important; } #itiewAdminOverlay.itiew-open{ opacity: 1 !important; transform: translateY(0) !important; pointer-events: auto !important; } #itiewAdminOverlay.itiew-peek{ opacity: 0 !important; transform: translateY(18px) !important; pointer-events: none !important; } #itiewAdminOverlay .itiew-admin-card{ border-radius: 14px !important; background: var(--itiew-panel-bg) !important; box-shadow: 0 14px 34px rgba(0,0,0,0.42), inset 0 1px 0 rgba(255,255,255,0.10) !important; padding: 14px 16px !important; display:flex !important; flex-direction:column !important; gap: 10px !important; max-height: calc(100dvh - 120px) !important; overflow: auto !important; width: min(640px, 100%) !important; margin: 0 auto !important; align-items: center !important; text-align: center !important; } #itiewAdminOverlay .itiew-admin-title{ text-align:center; font-size:13px; font-weight:700; letter-spacing:.16em; text-transform:uppercase; color: var(--itiew-accent); } #itiewAdminOverlay .itiew-admin-sub{ text-align:center; font-size:11px; letter-spacing:.10em; text-transform:uppercase; color: rgba(255,255,255,0.86); line-height:1.35; } #itiewAdminOverlay .itiew-admin-row{ display:flex; gap:8px; align-items:center; justify-content:center; flex-wrap:wrap; width: 100%; } #itiewAdminOverlay .itiew-admin-btn{ height:34px !important; padding:0 12px !important; border-radius:10px !important; background: var(--itiew-panel-bg) !important; border:1px solid var(--itiew-accent-border) !important; color: var(--itiew-accent) !important; font-size:11px !important; font-weight:700 !important; letter-spacing:.14em !important; text-transform:uppercase !important; cursor:pointer !important; user-select:none !important; -webkit-touch-callout: none !important; touch-action: manipulation !important; box-shadow: 0 10px 22px rgba(0,0,0,0.30), inset 0 1px 0 rgba(255,255,255,0.10) !important; } #itiewAdminOverlay .itiew-admin-btn[disabled]{ opacity:.55 !important; cursor:not-allowed !important; } #itiewAdminOverlay .itiew-admin-input, #itiewAdminOverlay select{ height:34px; padding:0 10px; border-radius:10px; background: rgba(0,0,0,0.22); border:1px solid var(--itiew-accent-border); color: rgba(255,255,255,0.92); outline:none; font-family: inherit; letter-spacing:.08em; text-transform: uppercase; font-size: 11px; min-width: 180px; text-align: center; } #itiewAdminOverlay .itiew-admin-seg{ display:flex; gap:8px; justify-content:center; flex-wrap:wrap; width: 100%; } #itiewAdminHintToast{ position:absolute !important; left:50% !important; bottom: calc(var(--itiew-overlay-base-bottom) + 12px) !important; transform: translateX(-50%) translateY(10px) !important; opacity:0 !important; pointer-events:none !important; z-index: 210 !important; width: min(640px, calc(100% - 24px)) !important; padding: 12px 12px !important; border-radius: 14px !important; background: var(--itiew-panel-bg) !important; border: 1px solid var(--itiew-accent-border) !important; color: var(--itiew-accent-text) !important; box-shadow: 0 18px 44px rgba(0,0,0,0.55) !important; text-align:center !important; transition: opacity .16s ease, transform .16s ease !important; font-size: 11px !important; font-weight: 600 !important; letter-spacing: .12em !important; text-transform: uppercase !important; line-height: 1.35 !important; } #itiewAdminHintToast.itiew-open{ opacity:1 !important; transform: translateX(-50%) translateY(0) !important; } #context_info .ci-close{ width: var(--itiew-close-btn-size) !important; height: var(--itiew-close-btn-size) !important; font-size: var(--itiew-close-font-size) !important; font-weight: 900 !important; line-height: 1 !important; position: relative !important; left: var(--itiew-close-offset-x) !important; top: var(--itiew-close-offset-y) !important; } /* Palette menu (NO BLUR, same glass) */ #itiewPaletteMenu{ position: fixed !important; width: 220px !important; background: var(--itiew-panel-bg) !important; border: 1px solid rgba(255,255,255,0.12) !important; border-radius: 14px !important; padding: 8px !important; display: none !important; z-index: 2147483647 !important; box-shadow: 0 18px 40px rgba(0,0,0,0.45) !important; } #itiewPaletteMenu.itiew-open{ display:block !important; } #itiewPaletteMenu .sw{ width: 100% !important; display:flex !important; align-items:center !important; gap: 10px !important; padding: 8px 10px !important; border-radius: 12px !important; cursor: pointer !important; border: 1px solid rgba(255,255,255,0.10) !important; background: var(--itiew-panel-bg) !important; color: #fff !important; font-size: 12px !important; letter-spacing: .06em !important; text-transform: uppercase !important; } #itiewPaletteMenu .sw:hover{ border-color: var(--itiew-accent-border) !important; } #itiewPaletteMenu .dot{ width: 14px !important; height: 14px !important; border-radius: 99px !important; background: var(--c) !important; box-shadow: 0 0 0 1px rgba(255,255,255,0.18) inset !important; flex: 0 0 auto !important; } /* ===== Admin gear (optional) ===== */ #context_info .ci-gear{ background: transparent !important; border: 0 !important; padding: 0 !important; margin: 0 !important; color: #fff !important; cursor: pointer !important; display:flex !important; align-items:center !important; justify-content:center !important; user-select:none !important; filter: drop-shadow(0 2px 10px rgba(0,0,0,0.55)) !important; width: var(--itiew-palette-btn-size) !important; height: var(--itiew-palette-btn-size) !important; position: relative !important; } #context_info .ci-gear:active{ transform: translateY(1px) !important; } #context_info .ci-gear::before{ content:""; width: var(--itiew-palette-icon-size); height: var(--itiew-palette-icon-size); display:block; background-repeat:no-repeat; background-position:center; background-size: var(--itiew-palette-icon-size) var(--itiew-palette-icon-size); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none'%3E%3Cpath d='M12 15.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7Z' stroke='%23ffffff' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M19.4 15a1.8 1.8 0 0 0 .36 1.98l.05.05a2.2 2.2 0 0 1-1.56 3.76h-.07a1.8 1.8 0 0 0-1.69 1.24 2.2 2.2 0 0 1-4.16 0 1.8 1.8 0 0 0-1.69-1.24h-.07A2.2 2.2 0 0 1 4.14 17l.05-.05A1.8 1.8 0 0 0 4.6 15a1.8 1.8 0 0 0-1.24-1.69h-.07a2.2 2.2 0 0 1 0-4.16h.07A1.8 1.8 0 0 0 4.6 7.46l-.05-.05A2.2 2.2 0 0 1 6.11 3.65h.07A1.8 1.8 0 0 0 7.87 2.4a2.2 2.2 0 0 1 4.16 0 1.8 1.8 0 0 0 1.69 1.24h.07A2.2 2.2 0 0 1 19.86 7.4l-.05.05A1.8 1.8 0 0 0 19.4 9a1.8 1.8 0 0 0 1.24 1.69h.07a2.2 2.2 0 0 1 0 4.16h-.07A1.8 1.8 0 0 0 19.4 15Z' stroke='%23ffffff' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); opacity: .98; } /* ===== Hero stage (full size, no background) ===== */ #context_info .ci-row{ position: absolute !important; inset: 0 !important; width: 100% !important; height: 100% !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; } /* ✅ Hero cropping frame (follows hero.width/height) */ #context_info .hero-frame{ position: absolute !important; left: 50% !important; bottom: 0 !important; transform: translateX(-50%) !important; width: var(--itiew-hero-width) !important; height: var(--itiew-hero-height) !important; overflow: hidden !important; border: 0 !important; background: transparent !important; border-radius: 0 !important; } @media (hover:hover) and (pointer:fine){ #context_info.itiew-fs-enabled .hero-frame::after{ content: var(--itiew-i18n-tap-to-fs, "TAP TO FULLSCREEN"); position:absolute; left:50%; bottom: var(--itiew-fs-hint-bottom-desktop) !important; transform:translateX(-50%) translateY(6px); opacity:0; padding: 8px 12px; border-radius: 12px; background: var(--itiew-panel-bg); border: 1px solid var(--itiew-accent-border); color: var(--itiew-accent-text); font-size: 11px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; white-space: nowrap; pointer-events:none; z-index: 5; box-shadow: 0 14px 34px rgba(0,0,0,0.42); transition: opacity .16s ease, transform .16s ease; } #context_info.itiew-fs-enabled .hero-frame:hover::after{ opacity:1; transform:translateX(-50%) translateY(0); } } @media (hover:none) and (pointer:coarse){ #context_info.itiew-fs-enabled .hero-frame::after{ content: var(--itiew-i18n-tap-to-fs, "TAP TO FULLSCREEN"); position:absolute; left:50%; bottom: var(--itiew-fs-hint-bottom-mobile) !important; transform:translateX(-50%); opacity:1; padding: 8px 12px; border-radius: 12px; background: var(--itiew-panel-bg); border: 1px solid var(--itiew-accent-border); color: var(--itiew-accent-text); font-size: 11px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; white-space: nowrap; pointer-events:none; z-index: 5; box-shadow: 0 14px 34px rgba(0,0,0,0.42); } } @media (hover:none) and (pointer:coarse){ #context_info.itiew-fs-enabled.itiew-contact-open:not(.itiew-in-fs)::after{ content: var(--itiew-i18n-tap-to-fs, "TAP TO FULLSCREEN"); position:absolute; left:50%; bottom: var(--itiew-fs-hint-bottom-mobile) !important; transform:translateX(-50%); opacity:1; padding: 8px 12px; border-radius: 12px; background: var(--itiew-panel-bg); border: 1px solid var(--itiew-accent-border); color: var(--itiew-accent-text); font-size: 11px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; white-space: nowrap; pointer-events:none; z-index: 150; box-shadow: 0 14px 34px rgba(0,0,0,0.42); } } #context_info.itiew-contact-open .hero-frame::after{ opacity:0 !important; } #context_info.itiew-in-fs .hero-frame::after{ opacity:0 !important; } /* ✅ Agent image inside frame (always fills; crops cleanly) */ #context_info .agent-img{ position: absolute !important; inset: 0 !important; width: 100% !important; height: 100% !important; max-height: none !important; object-fit: cover !important; object-position: var(--itiew-hero-object-pos) !important; transform: scale(var(--itiew-hero-bleed)) !important; transform-origin: var(--itiew-hero-origin, 50% 50%) !important; border: 0 !important; background: transparent !important; border-radius: 0 !important; cursor: pointer !important; display: block !important; user-select: none !important; } /* ✅ Shared overlay edges */ #context_info .agent-meta, #context_info .contact-area{ left: var(--itiew-overlay-side) !important; right: var(--itiew-overlay-side) !important; } /* ✅ Bottom anchoring + stacking when both boxes visible */ #context_info .contact-area{ bottom: var(--itiew-overlay-base-bottom) !important; } #context_info .agent-meta{ bottom: calc(var(--itiew-overlay-base-bottom) + var(--itiew-contact-stack)) !important; } /* Agent meta overlay (sleek glass, NO BORDER, NO BLUR) */ #context_info .agent-meta{ position: absolute !important; z-index: 60 !important; pointer-events: auto !important; display:flex !important; flex-direction:column !important; gap: 9px !important; align-items:center !important; padding: 14px 16px !important; border-radius: 14px !important; background: var(--itiew-panel-bg) !important; box-shadow: 0 14px 34px rgba(0,0,0,0.42), inset 0 1px 0 rgba(255,255,255,0.10) !important; max-height: none !important; overflow: visible !important; } /* ✅ Company open can optionally hide agent (controlled by JS class) */ #context_info.itiew-contact-open.itiew-hide-agent .agent-meta{ display: none !important; } /* ✅ Closed state: both hidden */ #context_info.itiew-all-closed .agent-meta, #context_info.itiew-all-closed .contact-area{ display: none !important; } /* ✅ Polished unified title style (agent + company must match) */ #context_info .agent-name{ font-size: clamp(18px, 3.2vw, 22px) !important; font-weight: 600 !important; letter-spacing: .10em !important; text-transform: uppercase !important; line-height: 1.14 !important; color: var(--itiew-accent) !important; text-shadow: 0 2px 14px rgba(0,0,0,0.65) !important; text-align:center !important; max-width: 100% !important; white-space: normal !important; display: block !important; overflow: visible !important; -webkit-line-clamp: unset !important; -webkit-box-orient: unset !important; word-break: break-word !important; } #context_info .agent-status{ font-size: clamp(12px, 2.8vw, 13px) !important; color: var(--itiew-accent-subtext) !important; display:flex !important; align-items:center !important; justify-content:center !important; gap: 8px !important; width: 100% !important; letter-spacing: .06em !important; text-transform: uppercase !important; text-shadow: 0 2px 10px rgba(0,0,0,0.55) !important; } #context_info .status-dot{ width: 8px !important; height: 8px !important; border-radius: 999px !important; background: #e05c5c !important; box-shadow: 0 0 10px rgba(224,92,92,.40) !important; flex: 0 0 auto !important; } #context_info .itiew-online .status-dot{ background: #23d16b !important; box-shadow: 0 0 12px rgba(35,209,107,.45) !important; } #context_info .hint{ font-size: 12px !important; color: rgba(255,255,255,0.86) !important; line-height: 1.35 !important; text-shadow: 0 2px 10px rgba(0,0,0,0.55) !important; text-align:center !important; letter-spacing: .07em !important; text-transform: uppercase !important; } #context_info .hint[data-i18n="reply_time"]{ color: var(--itiew-accent-subtext) !important; } /* Optional agent extra */ #context_info .agent-extra{ width: 100% !important; text-align: center !important; font-size: 11px !important; line-height: 1.35 !important; letter-spacing: .06em !important; color: rgba(255,255,255,0.88) !important; overflow: hidden !important; text-overflow: ellipsis !important; } /* Contact area overlay (NO BLUR, NO BORDER) */ #context_info .contact-area{ position: absolute !important; z-index: 70 !important; pointer-events: auto !important; display: none !important; padding: 14px 16px !important; border-radius: 14px !important; background: var(--itiew-panel-bg) !important; box-shadow: 0 14px 34px rgba(0,0,0,0.42), inset 0 1px 0 rgba(255,255,255,0.10) !important; max-height: var(--itiew-contact-max-h) !important; overflow: hidden !important; min-height: 0 !important; } #context_info.itiew-contact-open .contact-area{ display: flex !important; flex-direction: column !important; gap: 12px !important; } /* Company block */ #context_info .company{ display:flex !important; flex-direction: column !important; gap: 10px !important; align-items:center !important; flex: 0 0 auto !important; min-height: 0 !important; text-align: center !important; } /* ✅ Company name matches agent name (typography + visibility) */ #context_info .co-name{ font-size: clamp(18px, 3.2vw, 22px) !important; font-weight: 600 !important; letter-spacing: .10em !important; text-transform: uppercase !important; line-height: 1.14 !important; color: var(--itiew-accent) !important; text-shadow: 0 2px 14px rgba(0,0,0,0.65) !important; text-align:center !important; max-width: 100% !important; white-space: normal !important; display: -webkit-box !important; -webkit-line-clamp: 2 !important; -webkit-box-orient: vertical !important; overflow: hidden !important; } #context_info .co-logo{ width: auto !important; height: auto !important; max-height: min(var(--itiew-company-logo-size), var(--itiew-company-logo-cap)) !important; max-width: 100% !important; border-radius: 14px !important; object-fit: contain !important; border: 0 !important; background: transparent !important; display: block !important; } /* Custom content block (fills overlay; no scrollbars) */ #context_info .itiew-custom{ width: 100% !important; border-radius: 12px !important; overflow: hidden !important; min-height: 0 !important; flex: 1 1 auto !important; display: flex !important; align-items: stretch !important; justify-content: stretch !important; } #context_info .itiew-custom > iframe{ width: 100% !important; height: 100% !important; border: 0 !important; display: block !important; } #context_info .itiew-custom img, #context_info .itiew-custom video{ width: 100% !important; height: auto !important; max-height: 100% !important; object-fit: contain !important; display: block !important; } #context_info .itiew-custom a{ width: 100% !important; height: 100% !important; display: block !important; text-decoration: none !important; } #context_info .itiew-custom a > *{ width: 100% !important; height: 100% !important; max-width: 100% !important; max-height: 100% !important; display: block !important; } #context_info .itiew-custom .itiew-html{ width: 100% !important; height: 100% !important; max-width: 100% !important; color: rgba(255,255,255,0.92) !important; text-shadow: 0 2px 10px rgba(0,0,0,0.45) !important; transform-origin: top left; } #context_info.itiew-custom-only .contact-area{ padding: 0 !important; gap: 0 !important; } #context_info.itiew-custom-only #itiewCustomBlock{ border-radius: 14px !important; } /* ✅ Messenger pills: smaller, clean grid alignment, one row on mobile */ #context_info .btns{ display: grid !important; grid-template-columns: repeat(3, minmax(0, 1fr)) !important; gap: var(--itiew-pill-gap) !important; width: 100% !important; align-items: stretch !important; flex: 0 0 auto !important; min-height: 0 !important; } #context_info .btn{ display:inline-flex !important; align-items:center !important; justify-content:center !important; height: 34px !important; padding: 0 10px !important; border-radius: 10px !important; background: var(--itiew-panel-bg) !important; border: 1px solid var(--itiew-accent-border) !important; color: var(--itiew-accent) !important; text-decoration:none !important; font-size: clamp(9.5px, 2.6vw, var(--itiew-pill-font)) !important; font-weight: 600 !important; letter-spacing: .11em !important; text-transform: uppercase !important; min-width: 0 !important; overflow: hidden !important; text-overflow: ellipsis !important; white-space: nowrap !important; box-shadow: 0 10px 22px rgba(0,0,0,0.30), inset 0 1px 0 rgba(255,255,255,0.10) !important; transition: transform .16s ease, border-color .16s ease !important; user-select:none !important; } #context_info .btn:hover{ transform: translateY(-1px) !important; border-color: var(--itiew-accent-border) !important; box-shadow: 0 10px 22px rgba(0,0,0,0.30), inset 0 1px 0 rgba(255,255,255,0.10), 0 0 18px var(--itiew-accent-glow) !important; } /* ✅ Bottom contact button: absolute bottom (3px) ALWAYS visible */ #context_info .contact-toggle{ position:absolute !important; left: var(--itiew-toggle-left) !important; bottom: calc(3px + env(safe-area-inset-bottom, 0px)) !important; transform: translate(var(--itiew-toggle-translate-x), var(--itiew-toggle-translate-y)) !important; z-index: var(--itiew-toggle-z) !important; display:inline-flex !important; align-items:center !important; justify-content:center !important; padding: var(--itiew-bottom-pill-pad-y) var(--itiew-bottom-pill-pad-x) !important; border-radius: var(--itiew-toggle-radius) !important; background: var(--itiew-panel-bg) !important; border: 1px solid var(--itiew-accent-border) !important; color: var(--itiew-accent) !important; font-size: var(--itiew-bottom-pill-font) !important; font-weight: 600 !important; letter-spacing: .14em !important; text-transform: uppercase !important; box-shadow: 0 18px 40px rgba(0,0,0,0.42), inset 0 1px 0 rgba(255,255,255,0.10), 0 0 18px var(--itiew-accent-glow) !important; cursor:pointer !important; user-select:none !important; -webkit-touch-callout: none !important; touch-action: manipulation !important; width: var(--itiew-toggle-width) !important; pointer-events: auto !important; } #context_info .contact-toggle:hover{ border-color: var(--itiew-accent-border) !important; } /* Compact mode kept */ #context_info.itiew-compact{ --itiew-company-logo-cap: 9vh; --itiew-pill-font: 10.4px; --itiew-pill-pad-y: 4px; --itiew-pill-pad-x: 9px; --itiew-pill-gap: 6px; --itiew-bottom-pill-font: 10.6px; --itiew-bottom-pill-pad-y: 6px; --itiew-bottom-pill-pad-x: 14px; --itiew-agent-meta-max-h: 22vh; --itiew-contact-max-h: 38vh; } /* Fullscreen image overlay */ #itiew_fsOverlay{ position: fixed !important; inset: 0 !important; background: rgba(0,0,0,0.88) !important; display: none !important; align-items: center !important; justify-content: center !important; z-index: 2147483647 !important; padding: 14px !important; } #itiew_fsOverlay.itiew-open{ display:flex !important; } #itiew_fsOverlay img{ max-width: 100% !important; max-height: 100% !important; border-radius: 14px !important; border: 1px solid rgba(255,255,255,0.16) !important; } #itiew_fsClose{ position: fixed !important; top: 12px !important; right: 12px !important; width: 44px !important; height: 44px !important; border-radius: 14px !important; border: 1px solid rgba(255,255,255,0.18) !important; background: var(--itiew-panel-bg) !important; color:#fff !important; display:flex !important; align-items:center !important; justify-content:center !important; cursor:pointer !important; user-select:none !important; -webkit-touch-callout: none !important; touch-action: manipulation !important; } /* Fullscreen hint button */ #itiewFsHint{ position:absolute !important; left:50% !important; bottom: var(--itiew-fs-hint-bottom-mobile) !important; transform:translateX(-50%) !important; padding: 8px 12px !important; border-radius: 12px !important; background: var(--itiew-panel-bg) !important; border: 1px solid var(--itiew-accent-border) !important; color: var(--itiew-accent-text) !important; font-size: 11px !important; font-weight: 600 !important; letter-spacing: .14em !important; text-transform: uppercase !important; white-space: nowrap !important; z-index: 160 !important; box-shadow: 0 14px 34px rgba(0,0,0,0.42) !important; cursor: pointer !important; user-select: none !important; display: none !important; } #context_info.itiew-open.itiew-fs-enabled:not(.itiew-in-fs) #itiewFsHint{ display: block !important; } #context_info #itiew_fsToast.itiew-open ~ #itiewFsHint{ display: none !important; } #context_info.itiew-fs-toast-open .hero-frame::after, #context_info.itiew-fs-toast-open::after{ opacity: 0 !important; } @media (min-width: 769px){ #itiewFsHint{ bottom: var(--itiew-fs-hint-bottom-desktop) !important; } } @media (hover:hover) and (pointer:fine){ #context_info.itiew-open.itiew-fs-enabled:not(.itiew-in-fs) #itiewFsHint{ opacity:0 !important; transform:translateX(-50%) translateY(6px) !important; transition: opacity .16s ease, transform .16s ease !important; } #context_info.itiew-open.itiew-fs-enabled:not(.itiew-in-fs):hover #itiewFsHint{ opacity:1 !important; transform:translateX(-50%) translateY(0) !important; } } /* Fullscreen exit toast */ #itiew_fsToast{ position:absolute !important; left:50% !important; bottom: var(--itiew-fs-toast-bottom-mobile) !important; transform:translateX(-50%) translateY(10px) !important; opacity:0 !important; pointer-events:none !important; z-index:160 !important; width:min(640px, calc(100% - 24px)) !important; padding: 12px 12px !important; border-radius: 14px !important; background: var(--itiew-panel-bg) !important; border: 1px solid var(--itiew-accent-border) !important; color: var(--itiew-accent-text) !important; box-shadow: 0 18px 44px rgba(0,0,0,0.55) !important; text-align:center !important; transition: opacity .16s ease, transform .16s ease !important; } #itiew_fsToast.itiew-open{ opacity:1 !important; transform:translateX(-50%) translateY(0) !important; pointer-events:auto !important; } #itiew_fsToast .itiew-fst-msg{ font-size: 11px !important; font-weight: 600 !important; letter-spacing: .12em !important; text-transform: uppercase !important; line-height: 1.35 !important; } #itiew_fsToast .itiew-fst-actions{ margin-top: 10px !important; display:flex !important; gap: 8px !important; justify-content:center !important; } #itiew_fsToast .itiew-fst-btn{ height: 34px !important; padding: 0 12px !important; border-radius: 10px !important; background: var(--itiew-panel-bg) !important; border: 1px solid var(--itiew-accent-border) !important; color: var(--itiew-accent) !important; font-size: 11px !important; font-weight: 700 !important; letter-spacing: .14em !important; text-transform: uppercase !important; cursor:pointer !important; user-select:none !important; -webkit-touch-callout: none !important; touch-action: manipulation !important; } #itiew_fsToast .itiew-fst-btn:active{ transform: translateY(1px) !important; } @media (min-width: 769px){ #itiew_fsToast{ bottom: var(--itiew-fs-toast-bottom-desktop) !important; } } /* ===== LIMITLESS: custom background layer behind overlays ===== */ #context_info .itiew-bg-host{ position: absolute !important; inset: 0 !important; z-index: 0 !important; overflow: hidden !important; display: none !important; background: transparent !important; pointer-events: none !important; touch-action: auto !important; } #context_info .itiew-bg-host.itiew-open{ display: block !important; } #context_info .itiew-bg-host *{ pointer-events: none !important; touch-action: auto !important; } #context_info.itiew-bg-clickable .itiew-bg-host, #context_info.itiew-bg-clickable .itiew-bg-host *{ pointer-events: auto !important; } @media (max-width: 768px){ #context_info.itiew-bg-clickable .itiew-bg-host.itiew-open ~ .agent-meta{ pointer-events: none !important; } } /* Slight readability dim (does not block clicks) */ #context_info .itiew-bg-host::after{ content:""; position:absolute; inset:0; background: rgba(0,0,0,0.18); pointer-events:none; } /* Make background content fill panel */ #context_info .itiew-bg-host iframe{ width: 100% !important; height: 100% !important; border: 0 !important; display:block !important; background: transparent !important; } #context_info .itiew-bg-host img, #context_info .itiew-bg-host video{ width: 100% !important; height: 100% !important; border: 0 !important; display:block !important; object-fit: cover !important; background: transparent !important; } /* Ensure hero sits above bg if both visible */ #context_info .hero-frame{ z-index: 1 !important; } /* If bg is active and setting says hide hero, we do it by class */ #context_info.itiew-bg-active .hero-frame{ display:none !important; } /* ===== LIMITLESS: custom block inside agent card ===== */ #context_info .itiew-agentcustom{ width: 100% !important; border-radius: 12px !important; overflow: hidden !important; min-height: 0 !important; flex: 0 0 auto !important; display: flex !important; align-items: stretch !important; justify-content: stretch !important; } /* Annotation theme bridge (NO BLUR) */ html.itiew-anno-enabled .annotation{ --itiew-anno-scale-user: var(--itiew-anno-scale-user-mobile, 1) !important; box-sizing: border-box !important; font-family: "Cinzel", serif !important; line-height: 1.35 !important; padding: var(--itiew-anno-pad, 14px) !important; border-radius: var(--itiew-anno-radius, 16px) !important; max-width: calc(100vw - (var(--itiew-anno-side, 3px) * 2)) !important; overflow-wrap: anywhere !important; word-break: break-word !important; hyphens: auto !important; z-index: 2147483646 !important; } html.itiew-anno-enabled .annotation, html.itiew-anno-enabled .annotation *{ color: rgba(255,255,255,0.94) !important; text-shadow: 0 2px 10px rgba(0,0,0,0.55) !important; max-width: 100% !important; box-sizing: border-box !important; white-space: normal !important; } html.itiew-anno-enabled .annotation b, html.itiew-anno-enabled .annotation strong{ display:block !important; margin:0 !important; font-weight:600 !important; } html.itiew-anno-enabled .annotation em, html.itiew-anno-enabled .annotation i{ font-style: italic !important; } html.itiew-anno-enabled .annotation b:nth-of-type(1), html.itiew-anno-enabled .annotation strong:nth-of-type(1){ font-size: calc(clamp(16px, 3.2vw, 20px) * var(--itiew-anno-scale, 1) * var(--itiew-anno-scale-user, 1) * var(--itiew-anno-s1, 1)) !important; font-weight: var(--itiew-anno-fw1, 650) !important; letter-spacing: var(--itiew-anno-ls1, .08em) !important; text-transform: var(--itiew-anno-tx1, uppercase) !important; color: var(--itiew-accent) !important; } html.itiew-anno-enabled .annotation b:nth-of-type(2), html.itiew-anno-enabled .annotation strong:nth-of-type(2){ margin-top: var(--itiew-anno-gap, 10px) !important; font-size: calc(clamp(12px, 2.8vw, 15px) * var(--itiew-anno-scale, 1) * var(--itiew-anno-scale-user, 1) * var(--itiew-anno-s2, 1)) !important; font-weight: var(--itiew-anno-fw2, 600) !important; letter-spacing: var(--itiew-anno-ls2, .05em) !important; text-transform: var(--itiew-anno-tx2, uppercase) !important; color: var(--itiew-accent) !important; } html.itiew-anno-enabled .annotation b:nth-of-type(n+3), html.itiew-anno-enabled .annotation strong:nth-of-type(n+3){ margin-top: var(--itiew-anno-gap, 10px) !important; font-size: calc(clamp(13px, 3.4vw, 16px) * var(--itiew-anno-scale, 1) * var(--itiew-anno-scale-user, 1) * var(--itiew-anno-s3, 1)) !important; font-weight: var(--itiew-anno-fw3, 450) !important; letter-spacing: var(--itiew-anno-ls3, .02em) !important; text-transform: var(--itiew-anno-tx3, none) !important; color: rgba(255,255,255,0.92) !important; } html.itiew-anno-enabled .annotation b:nth-of-type(n+3) strong{ font-weight:700 !important; } html.itiew-anno-pack-p1{ --itiew-anno-s1:1; --itiew-anno-s2:1; --itiew-anno-s3:1; } html.itiew-anno-pack-p2{ --itiew-anno-s1:.92; --itiew-anno-s2:1.02; --itiew-anno-s3:1.22; --itiew-anno-ls1:.10em; } html.itiew-anno-pack-p3{ --itiew-anno-s1:1.06; --itiew-anno-s2:1.06; --itiew-anno-s3:1.12; --itiew-anno-fw1:720; --itiew-anno-fw2:650; --itiew-anno-ls1:.06em; } html.itiew-anno-pack-p4{ --itiew-anno-s1:.88; --itiew-anno-s2:.96; --itiew-anno-s3:1.18; --itiew-anno-tx1:none; --itiew-anno-ls1:.02em; --itiew-anno-tx2:none; --itiew-anno-ls2:.02em; } html.itiew-anno-pack-p5{ --itiew-anno-s1:.98; --itiew-anno-s2:1.10; --itiew-anno-s3:1.10; --itiew-anno-ls1:.14em; --itiew-anno-ls2:.10em; } html.itiew-anno-pack-p6{ --itiew-anno-s1:.94; --itiew-anno-s2:1.00; --itiew-anno-s3:1.32; --itiew-anno-ls1:.08em; } html.itiew-anno-size-s{ --itiew-anno-scale: .92; --itiew-anno-pad: 12px; --itiew-anno-gap: 8px; } html.itiew-anno-size-m{ --itiew-anno-scale: 1; --itiew-anno-pad: 14px; --itiew-anno-gap: 10px; } html.itiew-anno-size-l{ --itiew-anno-scale: 1.12;--itiew-anno-pad: 16px; --itiew-anno-gap: 12px; } html.itiew-anno-rtl .annotation{ direction: rtl !important; unicode-bidi: plaintext !important; } html.itiew-anno-align-a1 .annotation{ text-align:center !important; } html.itiew-anno-align-a1 .annotation b, html.itiew-anno-align-a1 .annotation strong{ text-align:center !important; } html.itiew-anno-align-a1 .annotation b:nth-of-type(n+3), html.itiew-anno-align-a1 .annotation strong:nth-of-type(n+3){ margin-left:auto !important; margin-right:auto !important; max-width: min(46ch, 100%) !important; } html.itiew-anno-align-a2 .annotation{ text-align:left !important; } html.itiew-anno-align-a2.itiew-anno-rtl .annotation{ text-align:right !important; } html.itiew-anno-align-a3 .annotation{ text-align:right !important; } html.itiew-anno-style-glass .annotation{ background: var(--itiew-panel-bg) !important; border: 1px solid var(--itiew-accent-border) !important; box-shadow: 0 18px 44px rgba(0,0,0,0.45), inset 0 1px 0 rgba(255,255,255,0.10) !important; } html.itiew-anno-style-plain .annotation{ background: transparent !important; border: 0 !important; box-shadow: none !important; padding: 0 !important; border-radius: 0 !important; } html.itiew-anno-style-banner .annotation{ position: relative !important; background: var(--itiew-panel-bg) !important; border: 1px solid var(--itiew-accent-border) !important; box-shadow: 0 18px 44px rgba(0,0,0,0.45), inset 0 1px 0 rgba(255,255,255,0.08) !important; padding-left: calc(var(--itiew-anno-pad, 14px) + 10px) !important; } html.itiew-anno-style-banner .annotation::before{ content:""; position:absolute; top:0; bottom:0; left:0; width: 4px; background: var(--itiew-accent); } html.itiew-anno-right.itiew-anno-style-banner .annotation, html.itiew-anno-align-a3.itiew-anno-style-banner .annotation, html.itiew-anno-rtl.itiew-anno-style-banner .annotation{ padding-left: var(--itiew-anno-pad, 14px) !important; padding-right: calc(var(--itiew-anno-pad, 14px) + 10px) !important; } html.itiew-anno-right.itiew-anno-style-banner .annotation::before, html.itiew-anno-align-a3.itiew-anno-style-banner .annotation::before, html.itiew-anno-rtl.itiew-anno-style-banner .annotation::before{ left:auto !important; right:0 !important; } html.itiew-anno-left .annotation, html.itiew-anno-right .annotation{ position: fixed !important; top: var(--itiew-anno-top, 3px) !important; bottom: auto !important; width: min(var(--itiew-anno-w-mobile, 51vw), var(--itiew-anno-max-w, 640px)) !important; } html.itiew-anno-left .annotation{ left: var(--itiew-anno-side, 3px) !important; right: auto !important; } html.itiew-anno-right .annotation{ right: var(--itiew-anno-side, 3px) !important; left: auto !important; } @media (min-width: 769px){ html.itiew-anno-enabled .annotation{ --itiew-anno-scale-user: var(--itiew-anno-scale-user-desktop, 1) !important; } html.itiew-anno-left .annotation, html.itiew-anno-right .annotation{ width: min(var(--itiew-anno-w-desktop, 33vw), var(--itiew-anno-max-w, 640px)) !important; } } html.itiew-anno-enabled .annotation mark{ background: rgba(0,0,0,0.38) !important; border: 1px solid var(--itiew-accent-border) !important; color: var(--itiew-accent) !important; padding: 2px 8px !important; border-radius: 999px !important; } html.itiew-anno-enabled .annotation u{ text-decoration-color: var(--itiew-accent) !important; text-decoration-thickness: 2px !important; text-underline-offset: 4px !important; } html.itiew-anno-enabled .annotation kbd{ font-family: inherit !important; font-size: .92em !important; padding: 2px 7px !important; border-radius: 10px !important; background: rgba(255,255,255,0.10) !important; border: 1px solid rgba(255,255,255,0.18) !important; color: rgba(255,255,255,0.92) !important; } </style> </head> <body> <div id="context_info" class="itiew-open" data-open-default="true"> <div class="ci-wrap"> <div class="ci-top"> <button class="ci-palette" id="itiewPaletteBtn" type="button" aria-label="Theme colors"></button> <button class="ci-gear" id="itiewGearBtn" type="button" aria-label="Admin"></button> <button class="ci-close" id="itiewCloseBtn" type="button" aria-label="Close">✕</button> </div> <div id="itiewPaletteMenu" aria-label="Theme palette"></div> <div class="ci-row"> <div class="itiew-bg-host" id="itiewBgHost" aria-hidden="true"></div> <div class="hero-frame" id="itiewHeroFrame" aria-label="Agent hero"> <img id="itiewAgentPhoto" class="agent-img" src="https://itiew.com/icons/agent-3.webp" alt="Agent photo" /> </div> <div class="agent-meta" id="itiewStatusBox"> <div class="agent-name" id="itiewAgentName">PATRICIA GRÖNWALL</div> <div class="hint" data-i18n="hint">Left click outside closes • Right click opens</div> <div class="agent-status" id="itiewStatusLine"> <span class="status-dot" aria-hidden="true"></span> <span id="itiewStatusText">Checking status…</span> </div> <div class="hint" data-i18n="reply_time">Usually replies in 45 minutes</div> <div class="itiew-custom itiew-agentcustom" id="itiewAgentCustom" hidden></div> <div class="agent-extra" id="itiewAgentExtra" hidden></div> </div> <div class="contact-area" id="itiewContactArea" aria-hidden="true"> <div class="company" id="itiewCompany" data-show="true"> <div class="co-name" id="itiewCompanyName">itiew.com</div> <img class="co-logo" id="itiewCompanyLogo" alt="Company logo"> </div> <div class="itiew-custom" id="itiewCustomBlock" hidden></div> <div class="btns" id="itiewButtons"> <a class="btn itiew-ext" id="itiewWA" href="#" rel="noopener noreferrer">WhatsApp</a> <a class="btn itiew-ext" id="itiewTG" href="https://t.me/itiewcom" rel="noopener noreferrer">Telegram</a> <a class="btn itiew-ext" id="itiewLINE" href="https://line.me/R/ti/p/itiew.com" rel="noopener noreferrer">LINE</a> </div> </div> </div> <button class="contact-toggle" id="itiewContactToggle" type="button" aria-expanded="false" data-open-text="" data-close-text=""> Open Agent Info </button> </div> </div> <div id="itiew_fsOverlay" role="dialog" aria-modal="true" aria-label="Image fullscreen"> <div id="itiew_fsClose">✕</div> <img id="itiew_fsImg" alt="Fullscreen image" /> </div> <script> (function(){ /* ========================================================== ✅ ITIEW — SIMPLIFIED + FULLY FLEXIBLE LOGIC ========================================================== ========================================================== */ const ITIEW_SETTINGS = { /* ========================= 0) BEHAVIOR ========================= */ behavior: { // Close panel by LEFT click outside? (default false as requested) leftClickOutsideClosesPanel: false, // Right click outside toggles panel open/close (default true) rightClickOutsideTogglesPanel: true, backgroundClickableBehindCard: true }, theme: { glassDim: "medium", defaultAccent: "#ffffff" }, /* Standalone main page background (behind the panel) */ pageBackground: { enabled: false, show: true, pool: "custom", active: "J", autoScaleDefault: "auto", allowScriptsDefault: false, sandboxIframesDefault: true, modes: { } }, /* ========================= ADMIN (OWNER ONLY) - Hidden from normal visitors - Open: long-press bottom button OR optional gear icon ========================= */ admin: { enabled: true, showGearIcon: false, longPressMs: 1200, password: "10987654321", sessionMinutes: 30 }, /* ========================= 1) PRESETS (FREE-FORM) ========================= These strings can be ANY order / ANY combination. Recognized tokens in this build: - agent => shows agent meta box - company => shows company block - contacts => shows messenger buttons - custom => shows custom module - closed => hides agent/company/custom/contacts (bottom button still visible) - none => panel starts closed (invisible) if used as defaultView */ defaultView: "agent+custom", // e.g. "agent+company+contacts", "custom+agent", "company+contacts+custom" closedOpensTo: "custom", // kept for compatibility menuFlow: { enabled: true, loop: true, sortByLetter: false, items: [ { id:"B1", enabled:true, key:"B", view:"custom", titleKey:"flow_title_B1", customOnly:true }, { id:"J1", enabled:true, key:"J", view:"custom", titleKey:"flow_title_J1", customOnly:true }, { id:"F1", enabled:true, key:"F", view:"custom", titleKey:"flow_title_F1", customOnly:true }, { id:"I1", enabled:true, key:"I", view:"custom", titleKey:"flow_title_I1", customOnly:true } ] }, /* ========================= 2) VISIBILITY TOGGLES ========================= */ visibility: { showPaletteButton: true, showCloseButton: false, showHeroImage: true, showAgentBox: true, showAgentName: true, showHintLine: false, showReplyTime: true, showStatusLine: true, showAgentExtra: true, showContactArea: true, showCompanyBlock: true, showCompanyName: true, showCompanyLogo: true, showCustomBlock: false, showMessengerButtons: true, showWhatsAppButton: true, showTelegramButton: true, showLineButton: true, showContactButton: true, enableFullscreen: true }, /* ========================= 3) HERO IMAGE CONTROL (OWN SETTINGS) ========================= */ heroVisibility: { mode: "hero", openOnLoad: true, keepBehindOverlays: true }, /* Fullscreen behavior for agent photo: "page" | "image" | "off" */ fullscreenMode: "page", /* ========================= 4) AGENT ========================= */ agent: { name: "PATRICIA GRÖNWALL", photoUrl: "https://itiew.com/icons/agent-3.webp", extraHtml: "", hero: { sizeMode: 3, sizeModes: { 1:{ height:"70dvh", bleed:1.00, objectPosition:"50% 0%" }, 2:{ height:"78dvh", bleed:1.01, objectPosition:"50% 3%" }, 3:{ height:"86dvh", bleed:1.02, objectPosition:"50% 8%" }, 4:{ height:"92dvh", bleed:1.02, objectPosition:"50% 10%" }, 5:{ height:"97dvh", bleed:1.02, objectPosition:"50% 12%" } }, width: "100%", height: "97dvh", bleed: 1.02, objectPosition: "50% 12%" } }, /* ========================= 5) COMPANY ========================= */ company: { name: "itiew.com", logoUrl: "https://itiew.com/icons/logo-2.png" }, /* ========================= 6) CUSTOM (A..N) — AS YOU PROVIDED ========================= */ custom: { enabled: true, active: "B", only: true, fullHeight: true, autoScaleDefault: "auto", // "auto" | true | false allowScriptsDefault: false, sandboxIframesDefault: false, modes: { A: { kind: "html", autoScale: "auto", allowScripts: false, html: ` <div style="padding:12px;text-align:center;letter-spacing:.08em;text-transform:uppercase;"> Paste any HTML here (Mode A) </div> ` }, B: { kind: "calendly", autoScale: true, url: "https://calendly.com/d0449298864/30min?hide_event_type_details=1&hide_gdpr_banner=1" }, C: { kind: "image", fit: "cover", src: "https://itiew.com/icons/agent-3.webp?auto=format&fit=crop&w=1200&q=170" }, D: { kind: "imageLink", fit: "cover", src: "https://images.unsplash.com/photo-1521737604893-d14cc237f11d?auto=format&fit=crop&w=1200&q=60", link: "https://itiew.com" }, E: { kind: "video", fit: "contain", src: "https://app.itiew.com/video.mp4", controls: true, autoplay: false, muted: true, loop: false }, F: { kind: "youtube", url: "https://youtu.be/M5339gFZOZo?si=wXW5fcBJ3ya_rSZ_" }, G: { kind: "vimeo", url: "https://vimeo.com/76979871" }, H: { kind: "iframe", sandbox: true, url: "https://itiew.com/test/stats-lates.html" }, I: { kind: "html", autoScale: false, allowScripts: true, scripts: [], html: ` <div style="padding:12px;text-align:center;"> Chatbot embed here (Mode I) </div> ` }, J: { kind: "matterport", url: "https://my.matterport.com/show?play=1&lang=en-US&m=wVRaQjxxS8h&ss=4&sr=-.11,.37" }, K: { kind: "pdf", url: "https://app.itiew.com/pdf.pdf" }, L: { kind: "fetch", as: "json", url: "https://api.github.com/repos/openai/openai-python" }, M: { kind: "map", url: "https://maps.itiew.com/viewer/index.php?code=68e6110cc7de5" }, N: { kind: "qr", size: 360, data: "https://itiew.com" } } }, /* ========================= 7) CONTACT BUTTONS ========================= */ contactButtons: { enabled: true, whatsapp: { enabled: true, label: "WhatsApp", url: "", number: "358449298864", messageTemplate: "" }, telegram: { enabled: true, label: "Telegram", url: "https://t.me/itiewcom" }, line: { enabled: true, label: "LINE", url: "https://line.me/R/ti/p/itiew.com" } }, /* ========================= 8) HOURS / STATUS ========================= */ weeklyHours: { 1: [{ start:"06:00", end:"18:00" }], 2: [{ start:"09:00", end:"18:00" }], 3: [{ start:"09:00", end:"18:00" }], 4: [{ start:"08:00", end:"23:00" }], 5: [{ start:"05:00", end:"23:00" }], 6: [{ start:"14:00", end:"05:00" }], 0: [{ start:"22:00", end:"09:00" }] }, /* ========================= 9) I18N (includes button labels) ========================= */ i18n: { mode: "B+C+D", defaultLang: "en", lang: "auto", en: { hint: "Right click outside toggles • Left click outside optional", reply_time: "Usually replies in 45 minutes", status_online: "Online now", status_offline: "Offline", status_closed_today: "Closed today", local_time: "local time", btn_hide_agent_open_menu: "Hide Agent • Open Menu", btn_open_menu: "Open Menu", btn_contact_agent: "Contact Agent", btn_agent_info: "Open Agent Info", custom_title_A: "Info", custom_title_B: "Book Meeting", custom_title_C: "Image", custom_title_D: "Link", custom_title_E: "Video", custom_title_F: "YouTube", custom_title_G: "Vimeo", custom_title_H: "Website", custom_title_I: "Chat", custom_title_J: "3D Tour", custom_title_K: "PDF", custom_title_L: "Data", custom_title_M: "Map", custom_title_N: "QR Code", flow_title_B1: "Book Meeting", flow_title_J1: "3D Tour", flow_title_F1: "YouTube", flow_title_I1: "Chat", loading: "Loading…", fetch_failed: "Fetch failed.", wa_msg: "Hello, I am interested in this listing.", tap_to_fullscreen: "TAP TO FULLSCREEN", fs_exit_msg: "Fullscreen is required for full functionality. Exit anyway?", fs_exit_stay: "Go Fullscreen", fs_exit_exit: "Exit" }, de: { hint: "Rechtsklick außerhalb toggelt • Linksklick optional", reply_time: "Antwortet meist in 45 Minuten", status_online: "Jetzt online", status_offline: "Offline", status_closed_today: "Heute geschlossen", local_time: "Ortszeit", btn_hide_agent_open_menu: "MAKLER AUSBLENDEN • MENÜ ÖFFNEN", btn_open_menu: "MENÜ ÖFFNEN", btn_contact_agent: "MAKLER KONTAKTIEREN", btn_agent_info: "AGENT INFO ÖFFNEN", custom_title_A: "INFO", custom_title_B: "TERMIN BUCHEN", custom_title_C: "BILD", custom_title_D: "LINK", custom_title_E: "VIDEO", custom_title_F: "YOUTUBE", custom_title_G: "VIMEO", custom_title_H: "WEBSEITE", custom_title_I: "CHAT", custom_title_J: "3D RUNDGANG", custom_title_K: "PDF", custom_title_L: "DATEN", custom_title_M: "KARTE", custom_title_N: "QR-CODE", flow_title_B1: "TERMIN BUCHEN", flow_title_J1: "3D RUNDGANG", flow_title_F1: "YOUTUBE", flow_title_I1: "CHAT", loading: "Lädt…", fetch_failed: "Abruf fehlgeschlagen.", wa_msg: "Hallo, ich interessiere mich für dieses Objekt.", tap_to_fullscreen: "TIPPE FÜR VOLLBILD", fs_exit_msg: "Dieses Erlebnis erfordert Vollbild. Trotzdem beenden?", fs_exit_stay: "ZUM VOLLBILD", fs_exit_exit: "BEENDEN" }, fr: { hint: "Clic droit à l'extérieur pour basculer • Clic gauche optionnel", reply_time: "Répond généralement en 45 minutes", status_online: "En ligne", status_offline: "Hors ligne", status_closed_today: "Fermé aujourd'hui", local_time: "heure locale", btn_hide_agent_open_menu: "Masquer l'agent • Ouvrir le menu", btn_open_menu: "Ouvrir le menu", btn_contact_agent: "Contacter l'agent", btn_agent_info: "Informations sur l'agent", custom_title_A: "Infos", custom_title_B: "Réserver", custom_title_C: "Image", custom_title_D: "Lien", custom_title_E: "Vidéo", custom_title_F: "YouTube", custom_title_G: "Vimeo", custom_title_H: "Site Web", custom_title_I: "Chat", custom_title_J: "Visite 3D", custom_title_K: "PDF", custom_title_L: "Données", custom_title_M: "Carte", custom_title_N: "QR Code", flow_title_B1: "Réserver", flow_title_J1: "Visite 3D", flow_title_F1: "YouTube", flow_title_I1: "Chat", loading: "Chargement…", fetch_failed: "Échec du chargement.", wa_msg: "Bonjour, je suis intéressé par cette propriété.", tap_to_fullscreen: "TOUCHEZ POUR LE PLEIN ÉCRAN", fs_exit_msg: "Le mode plein écran est requis. Quitter quand même ?", fs_exit_stay: "Plein écran", fs_exit_exit: "Quitter" }, fi: { hint: "Oikea klikkaus ulkopuolella togglaa • Vasen klikkaus valinnainen", reply_time: "Vastaa yleensä 45 minuutissa", status_online: "Online nyt", status_offline: "Offline", status_closed_today: "Suljettu tänään", local_time: "paikallista aikaa", btn_hide_agent_open_menu: "PIILOTA AGENTTI • AVAA VALIKKO", btn_open_menu: "AVAA VALIKKO", btn_contact_agent: "OTA YHTEYTTÄ", btn_agent_info: "YHTEYSTIEDOT", custom_title_A: "TIEDOT", custom_title_B: "VARAA AIKA", custom_title_C: "KUVA", custom_title_D: "LINKKI", custom_title_E: "VIDEO", custom_title_F: "YOUTUBE", custom_title_G: "VIMEO", custom_title_H: "SIVUSTO", custom_title_I: "CHAT", custom_title_J: "3D-ESITTELY", custom_title_K: "PDF", custom_title_L: "DATA", custom_title_M: "KARTTA", custom_title_N: "QR-KOODI", flow_title_B1: "VARAA AIKA", flow_title_J1: "3D-ESITTELY", flow_title_F1: "YOUTUBE", flow_title_I1: "KESKUSTELU", loading: "Ladataan…", fetch_failed: "Haku epäonnistui.", wa_msg: "Hei, olen kiinnostunut tästä kohteesta.", tap_to_fullscreen: "SIIRRY KOKONÄYTÖN NÄKYMÄÄN", fs_exit_msg: "Kokonäytön tila on tämän sivuston toiminnan kannalta välttämätön. Poistutaanko silti?", fs_exit_stay: "KOKONÄYTTÖÖN", fs_exit_exit: "POISTU" } }, /* ========================= 10) PALETTES ========================= */ palettes: [ { id:"platinum", name:"Platinum", accent:"#ffffff" }, { id:"dubai", name:"Dubai Gold", accent:"#d7b35a" }, { id:"monaco", name:"Monaco Emerald", accent:"#18b98a" }, { id:"soho", name:"Soho Sapphire", accent:"#2d7dff" }, { id:"amethyst", name:"Amethyst Royale", accent:"#7b4cff" }, { id:"ruby", name:"Ruby Reserve", accent:"#d4345a" }, { id:"onyx", name:"Onyx Aqua", accent:"#5de1ed" }, { id:"rose", name:"Rose Diamond", accent:"#f89cbd" }, { id:"champagne", name:"Champagne Pearl", accent:"#e8d2b8" }, { id:"copper", name:"Copper Royale", accent:"#e0a064" } ], /* ========================= 11) MANUAL OVERRIDES (OPTIONAL) ========================= Leave "" to use CSS defaults. Any CSS length: "42vh", "520px", "100%", etc. ========================= */ manual: { panel: { width:"", maxWidth:"", height:"", maxHeight:"" }, hero: { width:"", height:"" }, // usually controlled by agent.hero.* agentBox:{ maxHeight:"", width:"" }, contactBox:{ maxHeight:"", height:"", width:"" }, customBox:{ height:"", width:"" }, // Optional: per-preset overrides (applied after base manual overrides) defaultPresetOverrides: { panel: {}, hero:{}, agentBox:{}, contactBox:{}, customBox:{} }, menuPresetOverrides: { panel: {}, hero:{}, agentBox:{}, contactBox:{}, customBox:{} } }, /* ========================= 12) LIMITLESS (Agent Card ↔ Background sync) ========================= */ limitless: { enabled: false, /* "A" = agent-card changes, background stays fixed "B" = agent-card follows background/page URL recognition "C" = background follows agent-card content */ mode: "B", // "A" | "B" | "C" agentCard: { enabled: true, pool: "agent", active: "A", autoScaleDefault: "auto", allowScriptsDefault: false, sandboxIframesDefault: false, modes: { A: { kind: "html", autoScale: "auto", html: ` <div style="padding:12px;text-align:center;letter-spacing:.08em;text-transform:uppercase;"> Agent Card Custom Content (Bot) </div> ` } } }, /* Custom background behind overlays (renders into #itiewBgHost) */ background: { enabled: true, show: false, // TRUE shows bg layer, FALSE hides it hideHeroWhenActive: true, pool: "custom", // "custom" uses ITIEW_SETTINGS.custom.modes, "background" uses background.modes active: "C", // fallback key if nothing else sets bgKey autoScaleDefault: "auto", allowScriptsDefault: false, sandboxIframesDefault: true, modes: { } }, /* Recognition rules (unlimited) - Use ANY order, add as many as you want. - "when" can match: urlIncludes, urlRegex, customKey, customUrlIncludes, customKind, bgKey, bgUrlIncludes, bgKind, agentKey - "then" can set: agentKey, bgKey, agentOverride, bgOverride */ rules: [ { id:"example_room_link_to_agentcard", when:{ urlIncludes:"matterport" }, then:{ agentKey:"I" } }, { id:"example_bg_iframe_to_agentcard", when:{ bgKey:"H" }, then:{ agentKey:"I" } }, { id:"example_custom_key_to_bg", when:{ agentKey:"J" }, then:{ bgKey:"J" } } ], /* Watch page URL (for Mode B URL recognition) */ urlWatch: { enabled: true, pollMs: 500 } }, annotations: { enabled: true, position: "left", style: "banner", align: "a1", size: "s", pack: "p4", s1: 1.1, s2: 1.15, s3: 1.1, scaleMobile: 1, scaleDesktop: 0.88, scale: 1, rtl: false } }; /* ========================================================== Utilities ========================================================== */ function onReady(fn){ if(document.readyState === "loading") document.addEventListener("DOMContentLoaded", fn, { once:true }); else fn(); } function whenIdle(fn){ if("requestIdleCallback" in window) requestIdleCallback(fn, { timeout:1200 }); else setTimeout(fn, 20); } function qs(sel, root){ return (root || document).querySelector(sel); } function qsa(sel, root){ return Array.from((root || document).querySelectorAll(sel)); } function clamp(n, a, b){ return Math.max(a, Math.min(b, n)); } function parseHashParams(){ let h = window.location.hash || ""; h = h.replace(/^#/, ""); if(!h) return new URLSearchParams(""); if(h.includes("?")) h = h.split("?").pop(); if(h.startsWith("?")) h = h.slice(1); return new URLSearchParams(h); } function getAgentParam(){ const sp = new URLSearchParams(window.location.search || ""); const hp = parseHashParams(); const keys = ["agent","agent_open","agentcard","agent_card"]; for(const k of keys){ if(sp.has(k)) return { found:true, value: sp.get(k) }; if(hp.has(k)) return { found:true, value: hp.get(k) }; } return { found:false, value:null }; } function parseBoolLike(v){ if(v == null) return null; const s = String(v).trim(); if(!s) return null; if(/^(1|true|yes|open|on)$/i.test(s)) return true; if(/^(0|false|no|close|closed|off)$/i.test(s)) return false; return null; } function detectLang(S){ const I = (S && S.i18n) ? S.i18n : {}; const modeRaw = String(I.mode || "").trim(); if(!modeRaw && I.lang && I.lang !== "auto") return String(I.lang).trim().toLowerCase(); const parts = String(modeRaw || "B+C+D").toUpperCase().split(/[+,\s]+/).filter(Boolean); const A = parts.indexOf("A") !== -1; const B = parts.indexOf("B") !== -1; const C = parts.indexOf("C") !== -1; const D = parts.indexOf("D") !== -1; const hasDict = (k)=> !!(k && I[k] && typeof I[k] === "object"); const norm = (raw)=>{ const s = String(raw || "").trim(); if(!s) return ""; return s.replace(/_/g, "-").split("-")[0].toLowerCase(); }; const pick = (raw)=>{ const k = norm(raw); return hasDict(k) ? k : ""; }; if(A){ const defA = pick(I.defaultLang || (I.lang && I.lang !== "auto" ? I.lang : "") || "en"); return defA || pick("en") || "en"; } if(C){ const p = new URLSearchParams(window.location.search || ""); const fromPage = pick(p.get("lang") || document.documentElement.lang || ""); if(fromPage) return fromPage; } if(D){ const list = []; try{ const langs = (navigator && navigator.languages) ? navigator.languages : []; for(const v of langs) list.push(v); }catch(e){} try{ if(navigator && navigator.language) list.push(navigator.language); }catch(e){} try{ if(navigator && navigator.userLanguage) list.push(navigator.userLanguage); }catch(e){} for(const v of list){ const k = pick(v); if(k) return k; } } if(B){ const defB = pick(I.defaultLang || (I.lang && I.lang !== "auto" ? I.lang : "") || "en"); if(defB) return defB; } return pick("en") || "en"; } function hexToRgb(hex){ const h = String(hex||"").trim().replace("#",""); if(!/^[0-9a-fA-F]{6}$/.test(h)) return {r:255,g:255,b:255}; return { r:parseInt(h.slice(0,2),16), g:parseInt(h.slice(2,4),16), b:parseInt(h.slice(4,6),16) }; } function mix(a,b,t){ return { r:Math.round(a.r+(b.r-a.r)*t), g:Math.round(a.g+(b.g-a.g)*t), b:Math.round(a.b+(b.b-a.b)*t) }; } function rgba(c,a){ return `rgba(${c.r},${c.g},${c.b},${a})`; } function applyAccent(accentHex){ const base = hexToRgb(accentHex); const white = {r:255,g:255,b:255}; const text = mix(base, white, 0.72); const sub = mix(base, white, 0.58); const border = rgba(mix(base, white, 0.18), 0.34); const glow = rgba(base, 0.20); const root = document.documentElement.style; root.setProperty("--itiew-accent", accentHex); root.setProperty("--accent", accentHex); root.setProperty("--itiew-accent-text", rgba(text, 0.98)); root.setProperty("--itiew-accent-subtext", rgba(sub, 0.94)); root.setProperty("--itiew-accent-border", border); root.setProperty("--itiew-accent-glow", glow); } function resolveLenPx(val){ const s = String(val||"").trim(); if(!s) return 0; if(s.endsWith("px")) return parseFloat(s) || 0; const m = s.match(/^([0-9.]+)\s*(dvh|vh)$/i); if(m){ const n = parseFloat(m[1]) || 0; return (n/100) * (window.innerHeight || 0); } return parseFloat(s) || 0; } /* ========================================================== View parsing (FREE-FORM) ========================================================== */ function normalizeToken(t){ const s = String(t||"").trim().toLowerCase(); if(!s) return ""; if(s === "contact" || s === "contactbuttons" || s === "buttons") return "contacts"; return s; } function tokenizeView(str){ let s = String(str||"").trim().toLowerCase(); s = s.replace(/\s+/g, ""); s = s.replace(/&/g, "+"); if(!s) return new Set(); const parts = s.split("+").map(normalizeToken).filter(Boolean); return new Set(parts); } /* ========================================================== Script loader helpers (for Calendly + optional scripts) ========================================================== */ const __itiewLoadedScripts = new Set(); const __itiewLoadedCss = new Set(); function loadScriptOnce(src){ const u = String(src || "").trim(); if(!u) return Promise.resolve(false); if(__itiewLoadedScripts.has(u)) return Promise.resolve(true); const abs = (()=>{ try{ return new URL(u, document.baseURI).href; }catch(e){ return u; } })(); try{ const exists = Array.from(document.querySelectorAll("script[src]")).some(s=>{ const raw = s.getAttribute("src") || ""; if(raw === u) return true; try{ return new URL(raw, document.baseURI).href === abs; }catch(e){ return false; } }); if(exists){ __itiewLoadedScripts.add(u); return Promise.resolve(true); } }catch(e){} return new Promise((resolve)=>{ const s = document.createElement("script"); s.src = u; s.async = true; s.onload = ()=>{ __itiewLoadedScripts.add(u); resolve(true); }; s.onerror = ()=>resolve(false); (document.head || document.documentElement || document.body).appendChild(s); }); } function loadCssOnce(href){ const u = String(href || "").trim(); if(!u) return Promise.resolve(false); if(__itiewLoadedCss.has(u)) return Promise.resolve(true); const abs = (()=>{ try{ return new URL(u, document.baseURI).href; }catch(e){ return u; } })(); try{ const exists = Array.from(document.querySelectorAll('link[rel~="stylesheet"][href]')).some(l=>{ const raw = l.getAttribute("href") || ""; if(raw === u) return true; try{ return new URL(raw, document.baseURI).href === abs; }catch(e){ return false; } }); if(exists){ __itiewLoadedCss.add(u); return Promise.resolve(true); } }catch(e){} return new Promise((resolve)=>{ const l = document.createElement("link"); l.rel = "stylesheet"; l.href = u; l.onload = ()=>{ __itiewLoadedCss.add(u); resolve(true); }; l.onerror = ()=>resolve(false); (document.head || document.documentElement || document.body).appendChild(l); }); } async function loadScripts(list){ const arr = Array.isArray(list) ? list : []; for(const u of arr) await loadScriptOnce(u); } function sanitizeHtmlLite(html){ return String(html||"").replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, ""); } function injectHtml(target, html, opts){ const allowScripts = !!(opts && opts.allowScripts); const scriptsFirst = (opts && opts.scripts) ? opts.scripts : []; const t = document.createElement("template"); t.innerHTML = String(html || ""); const foundScripts = Array.from(t.content.querySelectorAll("script")); foundScripts.forEach(sc => sc.parentNode && sc.parentNode.removeChild(sc)); target.innerHTML = ""; target.appendChild(t.content); (async ()=>{ await loadScripts(scriptsFirst); if(!allowScripts) return; const externals = []; const inlines = []; foundScripts.forEach(sc=>{ const src = sc.getAttribute("src"); if(src) externals.push(src); else inlines.push(sc.textContent || ""); }); for(const u of externals) await loadScriptOnce(u); for(const code of inlines){ const s = document.createElement("script"); s.text = code; target.appendChild(s); } })(); } function parseYouTubeId(url){ const u = String(url||"").trim(); if(!u) return ""; const m1 = u.match(/[?&]v=([^&#]+)/i); if(m1 && m1[1]) return m1[1]; const m2 = u.match(/youtu\.be\/([^?&#/]+)/i); if(m2 && m2[1]) return m2[1]; const m3 = u.match(/youtube\.com\/embed\/([^?&#/]+)/i); if(m3 && m3[1]) return m3[1]; return ""; } function parseVimeoId(url){ const u = String(url||"").trim(); if(!u) return ""; const m1 = u.match(/vimeo\.com\/(\d+)/i); if(m1 && m1[1]) return m1[1]; const m2 = u.match(/player\.vimeo\.com\/video\/(\d+)/i); if(m2 && m2[1]) return m2[1]; return ""; } function buildIframe(url, sandbox){ const f = document.createElement("iframe"); f.src = String(url || ""); f.loading = "eager"; f.allow = "autoplay; fullscreen; picture-in-picture; xr-spatial-tracking; gyroscope; accelerometer; clipboard-write; encrypted-media"; f.setAttribute("allowfullscreen", ""); f.setAttribute("webkitallowfullscreen", ""); f.referrerPolicy = "no-referrer-when-downgrade"; f.style.width = "100%"; f.style.height = "100%"; f.style.border = "0"; f.style.touchAction = "auto"; if(sandbox){ f.setAttribute( "sandbox", "allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-top-navigation-by-user-activation allow-pointer-lock allow-presentation allow-orientation-lock" ); } return f; } function openInTop(url){ const u = String(url || "").trim(); if(!u) return; try{ const w = window.open(u, "_blank", "noopener,noreferrer"); if(w) return; }catch(e){} try{ const a = document.createElement("a"); a.href = u; a.target = "_blank"; a.rel = "noopener noreferrer"; a.style.display = "none"; (document.body || document.documentElement).appendChild(a); a.click(); a.remove(); return; }catch(e){} try{ window.location.href = u; }catch(e){} } /* ========================================================== Init ========================================================== */ onReady(()=>whenIdle(init)); function init(){ if(window.__ITIEW_AGENT_PANEL_INITED__) return; const panel = qs("#context_info"); if(!panel) return; window.__ITIEW_AGENT_PANEL_INITED__ = true; /* ---------- panel positioning guard ---------- */ function pinTopRight(){ panel.style.setProperty("position","fixed","important"); panel.style.setProperty("top","0px","important"); panel.style.setProperty("right","0px","important"); panel.style.setProperty("left","auto","important"); panel.style.setProperty("bottom","auto","important"); panel.style.setProperty("margin","0px","important"); panel.style.setProperty("z-index","2147483647","important"); } function ensureInBody(){ try{ if(document.body && !panel.isConnected) document.body.appendChild(panel); }catch(e){} pinTopRight(); } function forceShow(){ try{ if(panel.__itiewHideTO){ clearTimeout(panel.__itiewHideTO); panel.__itiewHideTO = 0; } panel.style.setProperty("display","block","important"); panel.style.setProperty("visibility","visible","important"); panel.style.setProperty("pointer-events", (ITIEW_SETTINGS.behavior && ITIEW_SETTINGS.behavior.backgroundClickableBehindCard) ? "none" : "auto", "important"); panel.removeAttribute("inert"); panel.setAttribute("aria-hidden","false"); panel.querySelectorAll("iframe").forEach(fr=>{ try{ fr.style.pointerEvents = "auto"; }catch(e){} }); }catch(e){} } function forceHide(){ try{ panel.setAttribute("aria-hidden","true"); panel.setAttribute("inert",""); panel.style.setProperty("pointer-events","none","important"); panel.querySelectorAll("iframe").forEach(fr=>{ try{ fr.style.pointerEvents = "none"; }catch(e){} }); try{ if(document.pointerLockElement) document.exitPointerLock(); }catch(e){} try{ const fsEl = document.fullscreenElement; if(fsEl && document.exitFullscreen && fsEl.id === "itiew_fsOverlay"){ document.exitFullscreen(); } }catch(e){} try{ if(document.activeElement && document.activeElement.blur) document.activeElement.blur(); }catch(e){} try{ document.querySelectorAll(".calendly-overlay, .calendly-popup, .calendly-badge-widget, .calendly-spinner").forEach(n=>n.remove()); }catch(e){} if(panel.__itiewHideTO){ clearTimeout(panel.__itiewHideTO); } panel.__itiewHideTO = setTimeout(()=>{ try{ if(!panel.classList.contains("itiew-open")){ panel.style.setProperty("display","none","important"); panel.style.setProperty("visibility","visible","important"); } }catch(e){} }, 260); }catch(e){} } ensureInBody(); /* ---------- open/close state ---------- */ let wantedOpen = false; let userClosed = false; let suppressCloseUntil = 0; const defaultTokens = tokenizeView(ITIEW_SETTINGS.defaultView); const defaultViewWantsNone = defaultTokens.has("none"); function computeInitialOpen(){ if(defaultViewWantsNone) return false; const ap = getAgentParam(); if(ap.found){ const b = parseBoolLike(ap.value); return (b === null) ? true : b; } return String(panel.getAttribute("data-open-default") || "true").toLowerCase() === "true"; } function openPanel(ms){ ensureInBody(); const wasOpen = panel.classList.contains("itiew-open"); panel.style.setProperty("display","block","important"); panel.classList.add("itiew-open"); forceShow(); suppressCloseUntil = Math.max(suppressCloseUntil, Date.now() + (typeof ms === "number" ? ms : 800)); if(!wasOpen && typeof panel.__itiewApplyPreset === "function"){ try{ panel.__itiewApplyPreset(); }catch(e){} } } function closePanel(){ ensureInBody(); panel.classList.remove("itiew-open"); forceHide(); } function setWantedOpen(v){ wantedOpen = !!v; if(wantedOpen){ userClosed = false; openPanel(1200); requestAnimationFrame(()=>{ if(wantedOpen && !userClosed) openPanel(1200); }); setTimeout(()=>{ if(wantedOpen && !userClosed) openPanel(1200); }, 180); setTimeout(()=>{ if(wantedOpen && !userClosed) openPanel(1200); }, 650); }else{ userClosed = true; closePanel(); } } setWantedOpen(computeInitialOpen()); function eventInsidePanel(e){ const path = (typeof e.composedPath === "function") ? e.composedPath() : null; if(path && path.length) return path.indexOf(panel) !== -1; return panel.contains(e.target); } function maybeCloseFromOutsideLeftClick(e){ if(!ITIEW_SETTINGS.behavior.leftClickOutsideClosesPanel) return; if(!panel.classList.contains("itiew-open")) return; if(Date.now() < suppressCloseUntil) return; if(e && e.isTrusted === false) return; if(eventInsidePanel(e)) return; userClosed = true; wantedOpen = false; closePanel(); } document.addEventListener("pointerdown", maybeCloseFromOutsideLeftClick, true); document.addEventListener("contextmenu", (e)=>{ if(!ITIEW_SETTINGS.behavior.rightClickOutsideTogglesPanel) return; if(eventInsidePanel(e)) return; e.preventDefault(); if(panel.classList.contains("itiew-open")){ userClosed = true; wantedOpen = false; closePanel(); }else{ userClosed = false; wantedOpen = true; openPanel(1200); requestAnimationFrame(()=>{ if(wantedOpen && !userClosed) openPanel(1200); }); setTimeout(()=>{ if(wantedOpen && !userClosed) openPanel(1200); }, 220); } }, { passive:false }); const closeBtn = qs("#itiewCloseBtn"); if(closeBtn){ closeBtn.addEventListener("click", (e)=>{ e.preventDefault(); e.stopPropagation(); userClosed = true; wantedOpen = false; closePanel(); }, true); } /* Keep panel alive if something tries to fight it */ let lock = 0; const panelObs = new MutationObserver(()=>{ if(lock) return; lock = requestAnimationFrame(()=>{ lock = 0; if(wantedOpen && !userClosed){ ensureInBody(); if(!panel.classList.contains("itiew-open")) openPanel(1200); else forceShow(); }else{ ensureInBody(); } }); }); try{ panelObs.observe(panel, { attributes:true, attributeFilter:["class","style"] }); }catch(e){} window.addEventListener("load", ()=>{ if(wantedOpen && !userClosed) openPanel(800); }, { once:true }); setTimeout(setupUI, 0); /* ========================================================== UI SETUP ========================================================== */ function setupUI(){ const S = ITIEW_SETTINGS; const lang = detectLang(S); const dict = (S.i18n && S.i18n[lang]) ? S.i18n[lang] : (S.i18n && S.i18n.en) ? S.i18n.en : {}; try{ panel.style.setProperty("--itiew-i18n-tap-to-fs", JSON.stringify((dict && dict.tap_to_fullscreen) ? dict.tap_to_fullscreen : "TAP TO FULLSCREEN")); }catch(e){} // Nodes const palBtn = qs("#itiewPaletteBtn", panel); const palMenu = qs("#itiewPaletteMenu", panel); const closeBtnEl = qs("#itiewCloseBtn", panel); const hintLine = qsa('[data-i18n="hint"]', panel)[0]; const replyLine = qsa('[data-i18n="reply_time"]', panel)[0]; const statusLine = qs("#itiewStatusLine", panel); const statusBox = qs("#itiewStatusBox", panel); const statusText = qs("#itiewStatusText", panel); const heroFrame = qs("#itiewHeroFrame", panel); const agentPhoto = qs("#itiewAgentPhoto", panel); const agentName = qs("#itiewAgentName", panel); const agentExtra = qs("#itiewAgentExtra", panel); const contactArea = qs("#itiewContactArea", panel); const companyBox = qs("#itiewCompany", panel); const coName = qs("#itiewCompanyName", panel); const coLogo = qs("#itiewCompanyLogo", panel); const bgHost = qs("#itiewBgHost", panel); const pageBgHost = (function(){ let el = document.getElementById("itiewPageBgHost"); if(el) return el; el = document.createElement("div"); el.id = "itiewPageBgHost"; try{ (document.body || document.documentElement).insertBefore(el, (document.body || document.documentElement).firstChild); }catch(e){ try{ (document.body || document.documentElement).appendChild(el); }catch(_e){} } return el; })(); panel.classList.toggle("itiew-bg-clickable", !!(S.behavior && S.behavior.backgroundClickableBehindCard)); const customBox = qs("#itiewCustomBlock", panel); const agentCustomBox = qs("#itiewAgentCustom", panel); const buttonsBox = qs("#itiewButtons", panel); const contactToggle = qs("#itiewContactToggle", panel); const waBtn = qs("#itiewWA", panel); const tgBtn = qs("#itiewTG", panel); const lineBtn = qs("#itiewLINE", panel); (function(){ const A = S.admin || {}; if(A.enabled === false) return; const LS = { adminUntil: "itiew_admin_until_v1", builder: "itiew_builder_cfg_v4" }; function lsGet(k){ try{ return localStorage.getItem(k); }catch(e){ return null; } } function lsSet(k,v){ try{ localStorage.setItem(k,v); }catch(e){} } function parseUntil(v){ if(v == null) return 0; if(typeof v === "number" && isFinite(v)) return Math.floor(v); const s = String(v).trim(); if(!s) return 0; if(/^\d+$/.test(s)) return parseInt(s,10) || 0; const t = Date.parse(s); return isFinite(t) ? t : 0; } function getAdminUntil(){ return parseUntil(lsGet(LS.adminUntil)) || 0; } function setAdminUntil(ts){ lsSet(LS.adminUntil, String(Math.floor(ts || 0))); } function isAuthed(){ return Date.now() < getAdminUntil(); } function defaultBuilderCfg(){ return { buildConfirmed: false, backgroundEnabled: !!(S.limitless && S.limitless.background && S.limitless.background.show), backgroundKey: String((S.limitless && S.limitless.background && S.limitless.background.active) || "C").toUpperCase(), hideHeroWhenBg: !!(S.limitless && S.limitless.background && S.limitless.background.hideHeroWhenActive), pageBgEnabled: !!(S.pageBackground && S.pageBackground.show), pageBgKey: String((S.pageBackground && S.pageBackground.active) || "C").toUpperCase(), customActive: String((S.custom && S.custom.active) || "B").toUpperCase(), menuKeys: ["B"] }; } function loadBuilderCfg(){ const base = defaultBuilderCfg(); const raw = lsGet(LS.builder); if(!raw) return base; try{ const j = JSON.parse(raw); return Object.assign({}, base, j || {}); }catch(e){ return base; } } function saveBuilderCfg(cfg){ lsSet(LS.builder, JSON.stringify(cfg)); } function applyBuilderCfg(cfg){ if(S.limitless && S.limitless.background){ S.limitless.background.show = !!cfg.backgroundEnabled; S.limitless.background.active = String(cfg.backgroundKey || S.limitless.background.active || "C").toUpperCase(); S.limitless.background.hideHeroWhenActive = !!cfg.hideHeroWhenBg; } if(S.pageBackground){ S.pageBackground.show = !!cfg.pageBgEnabled; S.pageBackground.active = String(cfg.pageBgKey || S.pageBackground.active || "C").toUpperCase(); } if(S.custom){ S.custom.active = String(cfg.customActive || S.custom.active || "B").toUpperCase(); } if(S.menuFlow && Array.isArray(S.menuFlow.items)){ const allow = new Set((cfg.menuKeys || []).map(x=>String(x||"").toUpperCase())); S.menuFlow.items.forEach(it=>{ const k = String(it.key||"").toUpperCase(); it.enabled = allow.has(k); }); } if(typeof panel.__itiewRebuildFlow === "function") panel.__itiewRebuildFlow(); if(typeof panel.__itiewApplyPreset === "function") panel.__itiewApplyPreset(); } const overlay = document.createElement("div"); overlay.id = "itiewAdminOverlay"; overlay.innerHTML = ` <div class="itiew-admin-card"> <div class="itiew-admin-row" style="justify-content:space-between;align-items:center;"> <div style="width:34px;"></div> <div class="itiew-admin-title">ADMIN</div> <button type="button" class="itiew-admin-btn" data-itiew-admin-close style="width:34px;padding:0;">✕</button> </div> <div class="itiew-admin-sub">OWNER ONLY • PASSWORD REQUIRED</div> <div id="itiewAdminLogin"> <div class="itiew-admin-row" style="justify-content:center;"> <input class="itiew-admin-input" id="itiewAdminPw" type="password" placeholder="PASSWORD"> <button type="button" class="itiew-admin-btn" data-itiew-admin-login>UNLOCK</button> </div> <div class="itiew-admin-sub" style="opacity:.9;margin-top:6px;"> TIP: HOLD THE BOTTOM BUTTON FOR ${Math.max(800, parseInt(A.longPressMs||3000,10)||3000)}MS </div> </div> <div id="itiewAdminMain" style="display:none;"> <div id="itiewTabBuild" style="display:block;"> <div class="itiew-admin-sub">STEP 1 • BACKGROUND</div> <div class="itiew-admin-row"> <button type="button" class="itiew-admin-btn" data-itiew-bg-toggle></button> <select id="itiewBgKey"></select> <button type="button" class="itiew-admin-btn" data-itiew-bg-hidehero></button> </div> <div class="itiew-admin-row"> <button type="button" class="itiew-admin-btn" data-itiew-pagebg-toggle></button> <select id="itiewPageBgKey"></select> </div> <div class="itiew-admin-sub">STEP 2 • DEFAULT CUSTOM</div> <div class="itiew-admin-row" style="justify-content:center;"> <select id="itiewCustomActive"></select> </div> <div class="itiew-admin-sub">STEP 3 • MENU ITEMS</div> <div id="itiewMenuKeys" class="itiew-admin-seg"></div> <div class="itiew-admin-sub">STEP 4 • CONFIRM BUILD</div> <div class="itiew-admin-row" style="justify-content:center;"> <button type="button" class="itiew-admin-btn" data-itiew-confirm></button> <button type="button" class="itiew-admin-btn" data-itiew-preview>PREVIEW</button> <button type="button" class="itiew-admin-btn" data-itiew-save>APPLY</button> </div> <div class="itiew-admin-sub" style="opacity:.92;"> NOTE: THIS IS LIGHTWEIGHT ON PURPOSE. IT ONLY USES EXISTING FUNCTIONS AND SETTINGS. </div> </div> </div> </div> `; panel.appendChild(overlay); const hintToast = (function(){ let t = panel.querySelector("#itiewAdminHintToast"); if(t) return t; t = document.createElement("div"); t.id = "itiewAdminHintToast"; panel.appendChild(t); return t; })(); let hintTO = 0; function showAdminHint(msg, ms){ if(!hintToast) return; hintToast.textContent = String(msg || ""); hintToast.classList.add("itiew-open"); if(hintTO) clearTimeout(hintTO); hintTO = setTimeout(()=>{ hintToast.classList.remove("itiew-open"); }, Math.max(800, parseInt(ms||1800,10)||1800)); } let previewTO = 0; function openAdmin(){ if(previewTO){ clearTimeout(previewTO); previewTO = 0; } overlay.classList.remove("itiew-peek"); overlay.classList.add("itiew-open"); panel.__itiewAdminOverlayOpen = true; const login = overlay.querySelector("#itiewAdminLogin"); const main = overlay.querySelector("#itiewAdminMain"); if(isAuthed()){ if(login) login.style.display = "none"; if(main) main.style.display = "block"; }else{ if(login) login.style.display = "block"; if(main) main.style.display = "none"; const pw = overlay.querySelector("#itiewAdminPw"); if(pw) setTimeout(()=>{ try{ pw.focus(); }catch(e){} }, 0); } refreshBuildUI(); } function closeAdmin(){ overlay.classList.remove("itiew-open"); overlay.classList.remove("itiew-peek"); if(previewTO){ clearTimeout(previewTO); previewTO = 0; } panel.__itiewAdminOverlayOpen = false; } const gearBtn = qs("#itiewGearBtn", panel); if(gearBtn){ setDispImp(gearBtn, A.showGearIcon === true); gearBtn.addEventListener("click", (e)=>{ e.preventDefault(); e.stopPropagation(); openAdmin(); }, true); } if(contactToggle){ const holdMs = Math.max(600, parseInt(A.longPressMs||1200,10)||1200); let holdTO = 0; const clearHold = ()=>{ if(holdTO){ clearTimeout(holdTO); holdTO = 0; } }; contactToggle.addEventListener("contextmenu", (e)=>{ e.preventDefault(); }, true); contactToggle.addEventListener("pointerdown", (e)=>{ if(e && e.button != null && e.button !== 0) return; e.preventDefault(); clearHold(); holdTO = setTimeout(()=>{ panel.__itiewHoldConsumed = true; openAdmin(); }, holdMs); }, true); ["pointerup","pointercancel","pointerleave","lostpointercapture"].forEach(ev=>{ contactToggle.addEventListener(ev, clearHold, true); }); } let cfg = loadBuilderCfg(); function listCustomKeys(){ const m = (S.custom && S.custom.modes) ? S.custom.modes : {}; return Object.keys(m).map(k=>String(k).toUpperCase()).sort(); } function refreshBuildUI(){ cfg = loadBuilderCfg(); const bgBtn = overlay.querySelector("[data-itiew-bg-toggle]"); if(bgBtn) bgBtn.textContent = cfg.backgroundEnabled ? "BACKGROUND: ON" : "BACKGROUND: OFF"; const hh = overlay.querySelector("[data-itiew-bg-hidehero]"); if(hh) hh.textContent = cfg.hideHeroWhenBg ? "HIDE HERO: ON" : "HIDE HERO: OFF"; const bgSel = overlay.querySelector("#itiewBgKey"); if(bgSel){ const keys = listCustomKeys(); bgSel.innerHTML = keys.map(k=>`<option value="${k}">${k}</option>`).join(""); bgSel.value = String(cfg.backgroundKey || "C").toUpperCase(); } const pbgBtn = overlay.querySelector("[data-itiew-pagebg-toggle]"); if(pbgBtn) pbgBtn.textContent = cfg.pageBgEnabled ? "PAGE BG: ON" : "PAGE BG: OFF"; const pbgSel = overlay.querySelector("#itiewPageBgKey"); if(pbgSel){ const keys = listCustomKeys(); pbgSel.innerHTML = keys.map(k=>`<option value="${k}">${k}</option>`).join(""); pbgSel.value = String(cfg.pageBgKey || "C").toUpperCase(); } const cSel = overlay.querySelector("#itiewCustomActive"); if(cSel){ const keys = listCustomKeys(); cSel.innerHTML = keys.map(k=>`<option value="${k}">${k}</option>`).join(""); cSel.value = String(cfg.customActive || "B").toUpperCase(); } const mk = overlay.querySelector("#itiewMenuKeys"); if(mk){ const items = (S.menuFlow && Array.isArray(S.menuFlow.items)) ? S.menuFlow.items : []; const uniq = Array.from(new Set(items.map(it=>String(it.key||"").toUpperCase()).filter(Boolean))); const allow = new Set((cfg.menuKeys||[]).map(x=>String(x).toUpperCase())); mk.innerHTML = uniq.map(k=>{ const on = allow.has(k); return `<button type="button" class="itiew-admin-btn" data-itiew-menukey="${k}">${k}: ${on?"ON":"OFF"}</button>`; }).join(""); } const cBtn = overlay.querySelector("[data-itiew-confirm]"); if(cBtn){ cBtn.textContent = cfg.buildConfirmed ? "BUILD: CONFIRMED" : "BUILD: NOT CONFIRMED"; cBtn.disabled = true; } } function applyAndSave(){ saveBuilderCfg(cfg); applyBuilderCfg(cfg); } function markDirtyAndApply(){ cfg.buildConfirmed = false; applyAndSave(); refreshBuildUI(); } function doApply(){ cfg.buildConfirmed = true; applyAndSave(); refreshBuildUI(); showAdminHint("NEW SETTINGS HAVE BEEN APPLIED", 1800); } function doPreview(){ showAdminHint("DIMMED FOR 5 SECONDS FOR PREVIEW", 2000); overlay.classList.add("itiew-peek"); if(previewTO) clearTimeout(previewTO); previewTO = setTimeout(()=>{ overlay.classList.remove("itiew-peek"); }, 5000); } overlay.addEventListener("click", (e)=>{ const b = e.target && e.target.closest ? e.target.closest("[data-itiew-admin-close],[data-itiew-admin-login],[data-itiew-bg-toggle],[data-itiew-bg-hidehero],[data-itiew-pagebg-toggle],[data-itiew-menukey],[data-itiew-preview],[data-itiew-save]") : null; if(!b) return; e.preventDefault(); e.stopPropagation(); if(b.hasAttribute("data-itiew-admin-close")){ closeAdmin(); return; } if(b.hasAttribute("data-itiew-admin-login")){ const pw = overlay.querySelector("#itiewAdminPw"); const val = String(pw && pw.value || "").trim(); const want = String(A.password || "").trim(); if(!want || val === want){ const mins = Math.max(1, parseInt(A.sessionMinutes||30,10)||30); setAdminUntil(Date.now() + mins*60*1000); const login = overlay.querySelector("#itiewAdminLogin"); const main = overlay.querySelector("#itiewAdminMain"); if(login) login.style.display = "none"; if(main) main.style.display = "block"; refreshBuildUI(); }else{ if(pw){ pw.value = ""; pw.placeholder = "WRONG PASSWORD"; } } return; } if(b.hasAttribute("data-itiew-bg-toggle")){ cfg.backgroundEnabled = !cfg.backgroundEnabled; markDirtyAndApply(); return; } if(b.hasAttribute("data-itiew-bg-hidehero")){ cfg.hideHeroWhenBg = !cfg.hideHeroWhenBg; markDirtyAndApply(); return; } if(b.hasAttribute("data-itiew-pagebg-toggle")){ cfg.pageBgEnabled = !cfg.pageBgEnabled; markDirtyAndApply(); return; } if(b.hasAttribute("data-itiew-menukey")){ const k = String(b.getAttribute("data-itiew-menukey")||"").toUpperCase(); const set = new Set((cfg.menuKeys||[]).map(x=>String(x).toUpperCase())); if(set.has(k)) set.delete(k); else set.add(k); cfg.menuKeys = Array.from(set); markDirtyAndApply(); return; } if(b.hasAttribute("data-itiew-preview")){ doPreview(); return; } if(b.hasAttribute("data-itiew-save")){ doApply(); return; } }, true); overlay.addEventListener("change", (e)=>{ const t = e.target; if(!t) return; if(t.id === "itiewBgKey"){ cfg.backgroundKey = String(t.value||"C").toUpperCase(); markDirtyAndApply(); } if(t.id === "itiewPageBgKey"){ cfg.pageBgKey = String(t.value||"C").toUpperCase(); markDirtyAndApply(); } if(t.id === "itiewCustomActive"){ cfg.customActive = String(t.value||"B").toUpperCase(); markDirtyAndApply(); } }, true); overlay.addEventListener("keydown", (e)=>{ if(e.key !== "Enter") return; const pw = overlay.querySelector("#itiewAdminPw"); if(pw && document.activeElement === pw){ const btn = overlay.querySelector("[data-itiew-admin-login]"); if(btn) btn.click(); } }, true); panel.__itiewAdminOverlayOpen = false; setDispImp(qs("#itiewGearBtn", panel), A.showGearIcon === true); cfg = loadBuilderCfg(); applyBuilderCfg(cfg); refreshBuildUI(); window.ITIEW_ADMIN = { open: openAdmin, close: closeAdmin, getCfg: ()=>loadBuilderCfg() }; })(); function setDispImp(el, show){ if(!el) return; if(show) el.style.removeProperty("display"); else el.style.setProperty("display", "none", "important"); } setDispImp(palBtn, S.visibility.showPaletteButton !== false); setDispImp(closeBtnEl, S.visibility.showCloseButton !== false); setDispImp(hintLine, S.visibility.showHintLine !== false); setDispImp(replyLine, S.visibility.showReplyTime !== false); setDispImp(statusLine, S.visibility.showStatusLine !== false); setDispImp(contactToggle, S.visibility.showContactButton !== false); // i18n static nodes qsa("[data-i18n]", panel).forEach(el=>{ const key = el.getAttribute("data-i18n"); if(dict && dict[key]) el.textContent = dict[key]; }); if(agentName){ agentName.textContent = S.agent.name || agentName.textContent; setDispImp(agentName, S.visibility.showAgentName !== false); } if(agentPhoto){ const u = String(S.agent.photoUrl || "").trim(); if(u) agentPhoto.src = u; } if(coName){ coName.textContent = S.company.name || coName.textContent; setDispImp(coName, S.visibility.showCompanyName !== false); } if(coLogo){ const u = String(S.company.logoUrl || "").trim(); if(u && S.visibility.showCompanyLogo !== false){ coLogo.src = u; setDispImp(coLogo, true); }else{ coLogo.removeAttribute("src"); setDispImp(coLogo, false); } } if(agentExtra){ if(S.visibility.showAgentExtra === false){ agentExtra.hidden = true; agentExtra.textContent = ""; }else{ const html = String(S.agent.extraHtml || "").trim(); if(html){ agentExtra.hidden = false; agentExtra.innerHTML = sanitizeHtmlLite(html); }else{ agentExtra.hidden = true; agentExtra.textContent = ""; } } } // Hero sizing vars try{ const H = (S.agent && S.agent.hero) ? S.agent.hero : {}; const m = parseInt(H.sizeMode, 10); const P = (H.sizeModes && H.sizeModes[m]) ? H.sizeModes[m] : null; document.documentElement.style.setProperty("--itiew-hero-width", String((P && P.width) || H.width || "100%")); document.documentElement.style.setProperty("--itiew-hero-height", String((P && P.height) || H.height || "85dvh")); document.documentElement.style.setProperty("--itiew-hero-bleed", String(((P && P.bleed)!=null ? P.bleed : (H.bleed!=null ? H.bleed : 1.02)))); document.documentElement.style.setProperty("--itiew-hero-object-pos", String((P && P.objectPosition) || H.objectPosition || "50% 12%")); }catch(e){} // Manual overrides (base) function applyManualBlock(over){ if(!over) return; try{ if(over.panel){ if(over.panel.width) panel.style.setProperty("--itiew-panel-w", over.panel.width); if(over.panel.maxWidth) panel.style.setProperty("--itiew-panel-max-w", over.panel.maxWidth); if(over.panel.height) panel.style.setProperty("--itiew-panel-h", over.panel.height); if(over.panel.maxHeight) panel.style.setProperty("--itiew-panel-max-h", over.panel.maxHeight); } if(over.hero){ if(over.hero.width) document.documentElement.style.setProperty("--itiew-hero-width", over.hero.width); if(over.hero.height) document.documentElement.style.setProperty("--itiew-hero-height", over.hero.height); } if(over.agentBox){ if(over.agentBox.maxHeight) panel.style.setProperty("--itiew-agent-meta-max-h", over.agentBox.maxHeight); if(over.agentBox.width && statusBox) statusBox.style.width = over.agentBox.width; } if(over.contactBox){ if(over.contactBox.maxHeight) panel.style.setProperty("--itiew-contact-max-h", over.contactBox.maxHeight); if(contactArea){ if(over.contactBox.height) contactArea.style.height = over.contactBox.height; if(over.contactBox.width) contactArea.style.width = over.contactBox.width; } } if(over.customBox && customBox){ if(over.customBox.height) customBox.style.height = over.customBox.height; if(over.customBox.width) customBox.style.width = over.customBox.width; } }catch(e){} } applyManualBlock(S.manual); // (preset overrides applied later when preset changes) // Palette system const palettes = Array.isArray(S.palettes) ? S.palettes : []; function applyPalette(p){ applyAccent(p.accent); try{ localStorage.setItem("itiewPalette", p.id); }catch(e){} } if(palMenu){ palMenu.innerHTML = palettes.map(p => `<div class="sw" data-id="${p.id}" style="--c:${p.accent}"> <span class="dot"></span><span>${p.name}</span> </div>` ).join(""); palMenu.addEventListener("click", (e)=>{ const sw = e.target.closest(".sw"); if(!sw) return; const id = sw.getAttribute("data-id"); const pal = palettes.find(x=>x.id===id); if(pal) applyPalette(pal); palMenu.classList.remove("itiew-open"); }); } if(palBtn && palMenu){ function positionMenu(){ const r = palBtn.getBoundingClientRect(); palMenu.style.top = (r.bottom + 8) + "px"; palMenu.style.left = "auto"; palMenu.style.right = (Math.max(8, (window.innerWidth - r.right))) + "px"; } palBtn.addEventListener("click", (e)=>{ e.preventDefault(); e.stopPropagation(); positionMenu(); palMenu.classList.toggle("itiew-open"); }); window.addEventListener("resize", ()=>{ if(palMenu.classList.contains("itiew-open")) positionMenu(); }); document.addEventListener("click", ()=> palMenu.classList.remove("itiew-open")); } try{ const T = S.theme || {}; const defAccent = String(T.defaultAccent || "").trim() || String(getComputedStyle(document.documentElement).getPropertyValue("--itiew-accent") || "").trim() || "#ffffff"; const lock = (S.visibility && S.visibility.showPaletteButton === false); const saved = lock ? "" : localStorage.getItem("itiewPalette"); const pal = palettes.find(x=>x.id===saved) || palettes.find(x=>String(x.accent||"").toLowerCase()===defAccent.toLowerCase()) || palettes[0] || { accent:defAccent }; applyAccent(pal.accent || defAccent); if(!lock && pal && pal.id) localStorage.setItem("itiewPalette", pal.id); }catch(e){ try{ applyAccent(String(((S.theme||{}).defaultAccent)||"").trim() || "#ffffff"); }catch(_e){ applyAccent("#ffffff"); } } (function(){ const T = S.theme || {}; const dim = String(T.glassDim || "light").trim().toLowerCase(); const root = document.documentElement; root.classList.toggle("itiew-dim-dark", dim === "dark"); root.classList.toggle("itiew-dim-medium", dim === "medium"); root.classList.toggle("itiew-dim-light", dim === "light"); })(); (function(){ const A = S.annotations || {}; const enabled = (A.enabled !== false); const pos = String(A.position || "custom").trim().toLowerCase(); const sty = String(A.style || "glass").trim().toLowerCase(); const align = String(A.align || "a1").trim().toLowerCase(); const size = String(A.size || "m").trim().toLowerCase(); const pack = String(A.pack || A.textMode || "p1").trim().toLowerCase(); const rtl = (A.rtl === true) || (String(A.dir || "").trim().toLowerCase() === "rtl"); const baseRaw = (typeof A.scale === "number") ? A.scale : parseFloat(String(A.scale || "1")); const mRaw = (typeof A.scaleMobile === "number") ? A.scaleMobile : parseFloat(String(A.scaleMobile || "")); const dRaw = (typeof A.scaleDesktop === "number") ? A.scaleDesktop : parseFloat(String(A.scaleDesktop || "")); const base = (isFinite(baseRaw) ? clamp(baseRaw, 0.75, 1.35) : 1); const scM = (isFinite(mRaw) ? clamp(mRaw, 0.75, 1.35) : base); const scD = (isFinite(dRaw) ? clamp(dRaw, 0.75, 1.35) : base); const root = document.documentElement; root.classList.toggle("itiew-anno-enabled", enabled); root.classList.toggle("itiew-anno-left", enabled && pos === "left"); root.classList.toggle("itiew-anno-right", enabled && pos === "right"); root.classList.toggle("itiew-anno-custom", enabled && pos === "custom"); root.classList.toggle("itiew-anno-style-glass", enabled && sty === "glass"); root.classList.toggle("itiew-anno-style-plain", enabled && sty === "plain"); root.classList.toggle("itiew-anno-style-banner", enabled && sty === "banner"); root.classList.toggle("itiew-anno-align-a1", enabled && align === "a1"); root.classList.toggle("itiew-anno-align-a2", enabled && align === "a2"); root.classList.toggle("itiew-anno-align-a3", enabled && align === "a3"); root.classList.toggle("itiew-anno-size-s", enabled && size === "s"); root.classList.toggle("itiew-anno-size-m", enabled && size === "m"); root.classList.toggle("itiew-anno-size-l", enabled && size === "l"); root.classList.toggle("itiew-anno-pack-p1", enabled && pack === "p1"); root.classList.toggle("itiew-anno-pack-p2", enabled && pack === "p2"); root.classList.toggle("itiew-anno-pack-p3", enabled && pack === "p3"); root.classList.toggle("itiew-anno-pack-p4", enabled && pack === "p4"); root.classList.toggle("itiew-anno-pack-p5", enabled && pack === "p5"); root.classList.toggle("itiew-anno-pack-p6", enabled && pack === "p6"); const s1 = parseFloat(String(A.s1 || "")); const s2 = parseFloat(String(A.s2 || "")); const s3 = parseFloat(String(A.s3 || "")); if(isFinite(s1)) root.style.setProperty("--itiew-anno-s1", String(clamp(s1, 0.7, 1.6))); if(isFinite(s2)) root.style.setProperty("--itiew-anno-s2", String(clamp(s2, 0.7, 1.6))); if(isFinite(s3)) root.style.setProperty("--itiew-anno-s3", String(clamp(s3, 0.7, 1.8))); root.classList.toggle("itiew-anno-rtl", enabled && rtl); root.style.setProperty("--itiew-anno-scale-user-mobile", String(scM)); root.style.setProperty("--itiew-anno-scale-user-desktop", String(scD)); })(); /* Measure bottom pill height -> keep overlays above it */ function syncOverlayBottom(){ if(!contactToggle) return; const h = Math.ceil(contactToggle.getBoundingClientRect().height || 44); panel.style.setProperty("--itiew-pill-h", h + "px"); } /* External links in top */ panel.addEventListener("click", (e)=>{ const a = e.target && e.target.closest ? e.target.closest("a.itiew-ext") : null; if(!a || !panel.contains(a)) return; const href = a.getAttribute("href"); if(!href || href === "#") return; e.preventDefault(); e.stopPropagation(); openInTop(a.href); }, true); /* Buttons */ function syncButtons(show){ if(!buttonsBox) return; const cfg = S.contactButtons || {}; const enabledAll = !!(cfg.enabled && show && S.visibility.showMessengerButtons !== false); if(!enabledAll){ setDispImp(buttonsBox, false); return; } let anyVisible = false; if(waBtn){ const w = cfg.whatsapp || {}; const showW = !!(w.enabled && S.visibility.showWhatsAppButton !== false); setDispImp(waBtn, showW); if(showW){ anyVisible = true; waBtn.textContent = String(w.label || "WhatsApp"); const pageUrl = window.location.href.split("#")[0]; const directUrl = String(w.url || "").trim(); if(directUrl){ waBtn.href = directUrl; }else{ const num = String(w.number || "").trim(); const tmpl = String(w.messageTemplate || "").trim(); const msgBase = tmpl ? tmpl.replace(/\{url\}/g, pageUrl) : ((dict.wa_msg || "Hello, I am interested in this listing.") + " " + pageUrl); waBtn.href = num ? ("https://wa.me/" + num + "?text=" + encodeURIComponent(msgBase)) : "#"; } } } if(tgBtn){ const t = cfg.telegram || {}; const showT = !!(t.enabled && S.visibility.showTelegramButton !== false); setDispImp(tgBtn, showT); if(showT){ anyVisible = true; tgBtn.textContent = String(t.label || "Telegram"); tgBtn.href = String(t.url || "#"); } } if(lineBtn){ const l = cfg.line || {}; const showL = !!(l.enabled && S.visibility.showLineButton !== false); setDispImp(lineBtn, showL); if(showL){ anyVisible = true; lineBtn.textContent = String(l.label || "LINE"); lineBtn.href = String(l.url || "#"); } } setDispImp(buttonsBox, anyVisible); } /* Status */ const WEEKLY_HOURS = S.weeklyHours || {}; function toMin(hhmm){ const m = String(hhmm||"").trim().match(/^(\d{1,2})[:.](\d{2})$/); if(!m) return null; const h = clamp(parseInt(m[1],10), 0, 23); const mm = clamp(parseInt(m[2],10), 0, 59); return h*60 + mm; } function fmtDot(hhmm){ const m = String(hhmm||"").trim().match(/^(\d{1,2})[:.](\d{2})$/); if(!m) return hhmm; return String(parseInt(m[1],10)).padStart(2,"0") + "." + m[2]; } function rangesText(ranges){ return ranges.map(r => `${fmtDot(r.start)}–${fmtDot(r.end)}`).join(", "); } function isWithinRange(nowMin, startMin, endMin){ if(startMin === endMin) return true; if(startMin < endMin) return (nowMin >= startMin && nowMin < endMin); return (nowMin >= startMin || nowMin < endMin); } function updateStatus(){ const d = new Date(); const dow = d.getDay(); const nowMin = d.getHours()*60 + d.getMinutes(); const ranges = WEEKLY_HOURS[dow] || []; let online = false; for(const r of ranges){ const s = toMin(r.start), e = toMin(r.end); if(s == null || e == null) continue; if(isWithinRange(nowMin, s, e)){ online = true; break; } } if(statusBox) statusBox.classList.toggle("itiew-online", online); if(statusText){ if(online){ statusText.textContent = dict.status_online || "Online now"; }else{ if(!ranges.length){ statusText.textContent = dict.status_closed_today || "Closed today"; }else{ statusText.textContent = (dict.status_offline || "Offline") + " • " + rangesText(ranges) + " " + (dict.local_time || "local time"); } } } requestAnimationFrame(syncOverlayBottom); } setTimeout(()=>{ updateStatus(); setInterval(updateStatus, 15000); }, 250); /* Fullscreen */ const fsOverlay = qs("#itiew_fsOverlay"); const fsImg = qs("#itiew_fsImg"); const fsClose = qs("#itiew_fsClose"); function normFsMode(m){ const s = String(m||"").trim().toLowerCase(); if(s === "page" || s === "image" || s === "off") return s; return "image"; } const fsMode = (S.visibility.enableFullscreen === false) ? "off" : normFsMode(S.fullscreenMode || "image"); panel.classList.toggle("itiew-fs-enabled", fsMode === "page"); const isToastMobile = ()=> !!(window.matchMedia && window.matchMedia("(max-width: 768px)").matches); const fsToast = (function(){ let el = qs("#itiew_fsToast"); if(el) return el; el = document.createElement("div"); el.id = "itiew_fsToast"; el.innerHTML = '<div class="itiew-fst-msg"></div><div class="itiew-fst-actions"><button type="button" class="itiew-fst-btn itiew-fst-stay"></button><button type="button" class="itiew-fst-btn itiew-fst-exit"></button></div>'; const msg = qs(".itiew-fst-msg", el); const stay = qs(".itiew-fst-stay", el); const exit = qs(".itiew-fst-exit", el); if(msg) msg.textContent = (dict.fs_exit_msg || "Fullscreen is required for this experience. Exit anyway?"); if(stay) stay.textContent = (dict.fs_exit_stay || "Go Fullscreen"); if(exit) exit.textContent = (dict.fs_exit_exit || "Exit"); panel.appendChild(el); return el; })(); const fsHint = (function(){ if(fsMode !== "page") return null; let el = qs("#itiewFsHint"); if(el) return el; el = document.createElement("button"); el.id = "itiewFsHint"; el.type = "button"; el.textContent = (dict.tap_to_fullscreen || "TAP TO FULLSCREEN"); el.setAttribute("aria-label", el.textContent); panel.appendChild(el); return el; })(); function showFsToast(){ if(!fsToast || fsMode !== "page") return; panel.classList.add("itiew-fs-toast-open"); fsToast.classList.add("itiew-open"); } function hideFsToast(){ if(!fsToast) return; fsToast.classList.remove("itiew-open"); panel.classList.remove("itiew-fs-toast-open"); } function openFS(src){ if(!fsOverlay || !fsImg) return; fsImg.src = src; fsOverlay.classList.add("itiew-open"); if(!isAnyFullscreen()){ const fn = fsOverlay.requestFullscreen || fsOverlay.webkitRequestFullscreen || fsOverlay.webkitRequestFullScreen || fsOverlay.msRequestFullscreen; if(fn){ const p = fn.call(fsOverlay); if(p && typeof p.catch === "function") p.catch(()=>{}); } } } function closeFS(){ if(!fsOverlay) return; fsOverlay.classList.remove("itiew-open"); const cur = document.fullscreenElement || document.webkitFullscreenElement || document.msFullscreenElement; const exit = document.exitFullscreen || document.webkitExitFullscreen || document.msExitFullscreen; if(cur === fsOverlay && exit){ const p = exit.call(document); if(p && typeof p.catch === "function") p.catch(()=>{}); } } function isAnyFullscreen(){ return !!(document.fullscreenElement || document.webkitFullscreenElement || document.msFullscreenElement); } function syncFsOffer(inFs){ inFs = (inFs === true || inFs === false) ? inFs : isAnyFullscreen(); panel.classList.toggle("itiew-in-fs", inFs); if(agentPhoto) agentPhoto.removeAttribute("title"); if(inFs) hideFsToast(); } function requestPageFullscreen(){ if(isAnyFullscreen()) return; const root = document.documentElement; const callFS = (el)=>{ if(!el) return null; const fn = el.requestFullscreen || el.webkitRequestFullscreen || el.webkitRequestFullScreen || el.msRequestFullscreen; if(!fn) return null; try{ return fn.call(el); }catch(e){ return null; } }; const p = callFS(root) || callFS(panel); if(p && typeof p.catch === "function") p.catch(()=>{}); if(!p && agentPhoto && agentPhoto.src) openFS(agentPhoto.src); } if(fsHint){ fsHint.addEventListener("click", (e)=>{ e.preventDefault(); e.stopPropagation(); requestPageFullscreen(); }, true); } if(fsToast){ fsToast.addEventListener("click", (e)=>{ const b = e.target && e.target.closest ? e.target.closest("button") : null; if(!b) return; e.preventDefault(); e.stopPropagation(); if(b.classList.contains("itiew-fst-stay")){ hideFsToast(); requestPageFullscreen(); }else{ hideFsToast(); } }, true); } if(agentPhoto){ if(fsMode === "off"){ agentPhoto.style.cursor = "default"; agentPhoto.removeAttribute("title"); }else{ agentPhoto.style.cursor = "pointer"; agentPhoto.addEventListener("click", (e)=>{ e.preventDefault(); e.stopPropagation(); if(fsMode === "page") requestPageFullscreen(); else openFS(agentPhoto.src); }); document.addEventListener("click", (e)=>{ if(!panel.classList.contains("itiew-open")) return; if(!panel.classList.contains("itiew-bg-clickable")) return; if(fsOverlay && fsOverlay.classList.contains("itiew-open")) return; if(!heroFrame || getComputedStyle(heroFrame).display === "none") return; if(!e || e.isTrusted === false) return; if(e.button != null && e.button !== 0) return; if(eventInsidePanel(e)) return; const r = agentPhoto.getBoundingClientRect(); const x = e.clientX, y = e.clientY; if(x < r.left || x > r.right || y < r.top || y > r.bottom) return; e.preventDefault(); e.stopPropagation(); if(e.stopImmediatePropagation) e.stopImmediatePropagation(); if(fsMode === "page") requestPageFullscreen(); else openFS(agentPhoto.src); }, true); } } if(fsClose) fsClose.addEventListener("click", closeFS); if(fsOverlay) fsOverlay.addEventListener("click", (e)=>{ if(e.target === fsOverlay) closeFS(); }); let wasFs = isAnyFullscreen(); const onFsChange = ()=>{ const inFs = isAnyFullscreen(); syncFsOffer(inFs); if(wasFs && !inFs) showFsToast(); if(!inFs && fsOverlay && fsOverlay.classList.contains("itiew-open")){ closeFS(); } wasFs = inFs; }; document.addEventListener("fullscreenchange", onFsChange); document.addEventListener("webkitfullscreenchange", onFsChange); document.addEventListener("msfullscreenchange", onFsChange); syncFsOffer(wasFs); /* ========================================================== /* ========================================================== CUSTOM RENDERER + LIMITLESS (Agent Card ↔ Background) ========================================================== */ function normKey(v){ return String(v||"").trim().toUpperCase(); } function clearBox(box, hard){ if(!box) return; const doHard = (hard !== false); try{ if(box.__itiewScaleRO){ box.__itiewScaleRO.disconnect(); } }catch(e){} box.__itiewScaleRO = null; try{ if(box.__itiewFetchAbort){ box.__itiewFetchAbort.abort(); } }catch(e){} box.__itiewFetchAbort = null; try{ box.querySelectorAll("iframe").forEach(fr=>{ try{ fr.style.pointerEvents = "none"; }catch(e){} try{ fr.src = "about:blank"; }catch(e){} }); box.querySelectorAll("video").forEach(v=>{ try{ v.pause(); }catch(e){} }); }catch(e){} if(doHard){ try{ document.querySelectorAll(".calendly-overlay, .calendly-popup, .calendly-badge-widget, .calendly-spinner").forEach(n=>n.remove()); }catch(e){} } if(doHard) box.hidden = true; box.innerHTML = ""; box.style.height = ""; box.style.maxHeight = ""; box.style.width = ""; box.style.alignItems = ""; box.style.justifyContent = ""; } function normBoolAuto(v, fallback){ if(v === true || v === false) return v; const s = String(v || "").trim().toLowerCase(); if(s === "auto") return "auto"; return (fallback === true || fallback === false || fallback === "auto") ? fallback : "auto"; } function setupAutoScale(container, content, scaleMode){ if(!container || !content) return; const tag = (content.tagName || "").toUpperCase(); if(tag === "IFRAME" || tag === "IMG" || tag === "VIDEO") return; const mode = normBoolAuto(scaleMode, "auto"); const applyScale = ()=>{ try{ content.style.transform = "scale(1)"; const cw = container.clientWidth || 1; const ch = container.clientHeight || 1; const w = Math.max(content.scrollWidth || 1, 1); const h = Math.max(content.scrollHeight || 1, 1); const sRaw = Math.min(cw / w, ch / h); const s = clamp(sRaw, 0.1, 3); if(mode === false){ content.style.transform = "scale(1)"; return; } if(mode === "auto" && Math.abs(s - 1) < 0.01){ content.style.transform = "scale(1)"; return; } content.style.transform = `scale(${s})`; }catch(e){} }; try{ if(container.__itiewScaleRO){ container.__itiewScaleRO.disconnect(); } }catch(e){} container.__itiewScaleRO = null; if("ResizeObserver" in window){ try{ const ro = new ResizeObserver(()=>applyScale()); ro.observe(container); ro.observe(content); container.__itiewScaleRO = ro; }catch(e){} } setTimeout(applyScale, 0); setTimeout(applyScale, 60); } function getPool(name){ const L = S.limitless || {}; if(name === "agent") return (L.agentCard && L.agentCard.modes) ? L.agentCard.modes : {}; if(name === "background") return (L.background && L.background.modes) ? L.background.modes : {}; return (S.custom && S.custom.modes) ? S.custom.modes : {}; } function resolveModeFrom(poolName, key, override){ const pool = getPool(poolName); const k = normKey(key); const base = (pool && pool[k]) ? pool[k] : null; if(!base) return null; return Object.assign({}, base, (override && typeof override === "object") ? override : null); } function guessUrl(mode){ if(!mode) return ""; if(mode.url) return String(mode.url); if(mode.src) return String(mode.src); if(mode.link) return String(mode.link); return ""; } async function renderInto(box, show, mode, defaults, role){ if(!box){ return; } if(!show){ clearBox(box); return; } if(!mode){ clearBox(box); return; } clearBox(box, false); box.hidden = false; box.style.alignItems = "stretch"; box.style.justifyContent = "stretch"; const kind = String(mode.kind || "html").trim().toLowerCase(); const fitRaw = String(mode.fit || (role === "bg" ? "cover" : "contain")).toLowerCase(); const fit = (fitRaw === "cover") ? "cover" : "contain"; const allowScripts = (mode.allowScripts === true || mode.allowScripts === false) ? mode.allowScripts : !!(defaults && defaults.allowScriptsDefault); const autoScale = (mode.autoScale === true || mode.autoScale === false || String(mode.autoScale).toLowerCase() === "auto") ? mode.autoScale : ((defaults && defaults.autoScaleDefault != null) ? defaults.autoScaleDefault : "auto"); const sandboxIframes = (mode.sandbox === true || mode.sandbox === false) ? mode.sandbox : ((kind === "matterport") ? false : !!(defaults && defaults.sandboxIframesDefault)); const scripts = Array.isArray(mode.scripts) ? mode.scripts : []; if(mode.width) box.style.width = String(mode.width); if(mode.height) box.style.height = String(mode.height); if(kind === "image"){ const img = document.createElement("img"); img.alt = "Custom image"; img.src = String(mode.src || ""); img.style.width = "100%"; img.style.height = (role === "bg" || fit === "cover") ? "100%" : "auto"; img.style.maxHeight = "100%"; img.style.objectFit = (role === "bg") ? "cover" : fit; img.style.display = "block"; box.appendChild(img); return; } if(kind === "imagelink"){ const a = document.createElement("a"); a.href = String(mode.link || "#"); a.rel = "noopener noreferrer"; a.className = "itiew-ext"; a.style.display = "block"; a.style.width = "100%"; a.style.height = (role === "bg" || fit === "cover") ? "100%" : "auto"; const img = document.createElement("img"); img.alt = "Custom linked image"; img.src = String(mode.src || ""); img.style.width = "100%"; img.style.height = (role === "bg" || fit === "cover") ? "100%" : "auto"; img.style.maxHeight = "100%"; img.style.objectFit = (role === "bg") ? "cover" : fit; img.style.display = "block"; a.appendChild(img); box.appendChild(a); return; } if(kind === "video"){ const v = document.createElement("video"); v.src = String(mode.src || ""); v.controls = (mode.controls !== false); v.autoplay = !!mode.autoplay; v.muted = (mode.muted !== false); v.loop = !!mode.loop; v.playsInline = true; v.style.width = "100%"; v.style.height = (role === "bg" || fit === "cover") ? "100%" : "auto"; v.style.maxHeight = "100%"; v.style.objectFit = (role === "bg") ? "cover" : fit; box.appendChild(v); return; } if(kind === "youtube"){ const id = parseYouTubeId(mode.url || mode.id || ""); const url = id ? (`https://www.youtube.com/embed/${id}`) : String(mode.url || ""); box.appendChild(buildIframe(url, sandboxIframes)); return; } if(kind === "vimeo"){ const id = parseVimeoId(mode.url || mode.id || ""); const url = id ? (`https://player.vimeo.com/video/${id}`) : String(mode.url || ""); box.appendChild(buildIframe(url, sandboxIframes)); return; } if(kind === "iframe" || kind === "pdf" || kind === "map" || kind === "matterport"){ box.appendChild(buildIframe(String(mode.url || ""), sandboxIframes)); return; } if(kind === "qr"){ const size = Math.max(120, parseInt(mode.size || 360, 10) || 360); const data = String(mode.data || ""); const img = document.createElement("img"); img.alt = "QR"; img.style.width = "100%"; img.style.height = "100%"; img.style.objectFit = (role === "bg") ? "cover" : "contain"; img.src = `https://api.qrserver.com/v1/create-qr-code/?size=${size}x${size}&data=${encodeURIComponent(data)}`; box.appendChild(img); return; } if(kind === "fetch"){ const pre = document.createElement("pre"); pre.style.margin = "0"; pre.style.whiteSpace = "pre-wrap"; pre.style.fontFamily = 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace'; pre.style.fontSize = "12px"; pre.textContent = dict.loading || "Loading…"; box.appendChild(pre); const url = String(mode.url || ""); const as = String(mode.as || "text").toLowerCase(); try{ if(box.__itiewFetchAbort){ box.__itiewFetchAbort.abort(); } }catch(e){} const ac = ("AbortController" in window) ? new AbortController() : null; box.__itiewFetchAbort = ac; fetch(url, ac ? { signal: ac.signal } : undefined).then(async (r)=>{ if(!r || r.ok === false){ const txt = r ? await r.text().catch(()=> "") : ""; throw new Error(txt || "fetch_failed"); } if(as === "json") return r.json(); return r.text(); }).then((data)=>{ if(ac && ac.signal && ac.signal.aborted) return; box.__itiewFetchAbort = null; if(as === "html"){ const wrap = document.createElement("div"); wrap.className = "itiew-html"; injectHtml(wrap, String(data || ""), { allowScripts: allowScripts, scripts: scripts }); box.innerHTML = ""; box.appendChild(wrap); setupAutoScale(box, wrap, autoScale); setTimeout(()=>{ try{ layoutContactArea(); updateOverlayStack(); }catch(e){} }, 0); return; } if(as === "json") pre.textContent = JSON.stringify(data, null, 2); else pre.textContent = String(data || ""); }).catch(()=>{ if(ac && ac.signal && ac.signal.aborted) return; box.__itiewFetchAbort = null; pre.textContent = dict.fetch_failed || "Fetch failed."; }); return; } if(kind === "calendly"){ const host = document.createElement("div"); host.style.width = "100%"; host.style.height = "100%"; host.textContent = dict.loading || "Loading…"; box.appendChild(host); const url = String(mode.url || ""); await loadCssOnce("https://assets.calendly.com/assets/external/widget.css"); await loadScriptOnce("https://assets.calendly.com/assets/external/widget.js"); host.textContent = ""; if(window.Calendly && typeof window.Calendly.initInlineWidget === "function"){ window.Calendly.initInlineWidget({ url: url, parentElement: host }); }else{ const d = document.createElement("div"); d.className = "calendly-inline-widget"; d.setAttribute("data-url", url); d.style.minWidth = "320px"; d.style.height = "100%"; host.appendChild(d); } setTimeout(()=>{ try{ layoutContactArea(); updateOverlayStack(); }catch(e){} }, 0); return; } const wrap = document.createElement("div"); wrap.className = "itiew-html"; injectHtml(wrap, String(mode.html || ""), { allowScripts: allowScripts, scripts: scripts }); box.appendChild(wrap); setupAutoScale(box, wrap, autoScale); } async function syncPageBg(){ const P = S.pageBackground || {}; if(P.enabled === false) return; if(!pageBgHost) return; const show = (P.show === true); const key = normKey(P.active || ""); const on = !!(show && key); try{ document.documentElement.classList.toggle("itiew-pagebg-on", on); if(document.body) document.body.classList.toggle("itiew-pagebg-on", on); }catch(e){} const last = syncPageBg.__last || { on:null, key:"" }; if(last.on === on && last.key === key) return; syncPageBg.__last = { on, key }; if(!on){ pageBgHost.classList.remove("itiew-open"); clearBox(pageBgHost); return; } pageBgHost.classList.add("itiew-open"); const pool = (String(P.pool || "custom").toLowerCase() === "background") ? "background" : "custom"; const mode = resolveModeFrom(pool, key, null); if(!mode){ pageBgHost.classList.remove("itiew-open"); clearBox(pageBgHost); return; } await renderInto(pageBgHost, true, mode, P, "bg"); } /* Contact-area custom block (existing) */ async function renderCustom(show){ if(!customBox) return; if(!show){ clearBox(customBox); return; } const C = S.custom || {}; if(!(C.enabled === true)) { clearBox(customBox); return; } const key = normKey(panel.__itiewCustomKeyOverride || C.active || "A"); const mode = resolveModeFrom("custom", key, panel.__itiewCustomModeOverride); await renderInto(customBox, true, mode, C, "custom"); } function getLimitlessMode(){ const p = new URLSearchParams(window.location.search || ""); const q = (p.get("limitless") || p.get("itiew_limitless") || "").trim().toUpperCase(); const s = (q || String((S.limitless && S.limitless.mode) || "A")).trim().toUpperCase(); return (s === "B" || s === "C") ? s : "A"; } function activeCustomInfo(){ const C = S.custom || {}; const k = normKey(panel.__itiewCustomKeyOverride || C.active || "A"); const m = resolveModeFrom("custom", k, panel.__itiewCustomModeOverride); return { key: k, mode: m, kind: m ? String(m.kind || "html").toLowerCase() : "", url: guessUrl(m) }; } function pickPoolForAgent(){ const L = S.limitless || {}; return (L.agentCard && L.agentCard.pool === "agent") ? "agent" : "custom"; } function pickPoolForBg(){ const L = S.limitless || {}; return (L.background && L.background.pool === "background") ? "background" : "custom"; } function ruleMatches(rule, ctx){ const w = (rule && rule.when) ? rule.when : {}; if(w.mode && String(w.mode).trim().toUpperCase() !== ctx.mode) return false; if(w.urlIncludes && !String(ctx.pageUrl || "").includes(String(w.urlIncludes))) return false; if(w.urlRegex){ try{ const re = new RegExp(String(w.urlRegex), "i"); if(!re.test(String(ctx.pageUrl || ""))) return false; }catch(e){ return false; } } if(w.customKey && normKey(w.customKey) !== ctx.customKey) return false; if(w.customKind && String(w.customKind).toLowerCase() !== String(ctx.customKind || "")) return false; if(w.customUrlIncludes && !String(ctx.customUrl || "").includes(String(w.customUrlIncludes))) return false; if(w.bgKey && normKey(w.bgKey) !== ctx.bgKey) return false; if(w.bgKind && String(w.bgKind).toLowerCase() !== String(ctx.bgKind || "")) return false; if(w.bgUrlIncludes && !String(ctx.bgUrl || "").includes(String(w.bgUrlIncludes))) return false; if(w.agentKey && normKey(w.agentKey) !== ctx.agentKey) return false; return true; } async function syncLimitless(reason){ const L = S.limitless || {}; if(!(L.enabled === true)) { if(bgHost){ bgHost.classList.remove("itiew-open"); clearBox(bgHost); bgHost.setAttribute("aria-hidden","true"); } if(agentCustomBox) clearBox(agentCustomBox); panel.classList.remove("itiew-bg-active"); return; } const modeSel = getLimitlessMode(); const cInfo = activeCustomInfo(); const aCfg = L.agentCard || {}; const bCfg = L.background || {}; const agentPool = pickPoolForAgent(); const bgPool = pickPoolForBg(); let agentKey = normKey(panel.__itiewAgentKeyOverride || aCfg.active || "A"); let agentOverride = panel.__itiewAgentModeOverride || null; let bgKey = normKey(panel.__itiewBgKeyOverride || bCfg.active || ""); let bgOverride = panel.__itiewBgModeOverride || null; if(modeSel === "A"){ if(!panel.__itiewAgentKeyOverride) agentKey = cInfo.key; } if(modeSel === "C"){ if(!panel.__itiewBgKeyOverride) bgKey = agentKey; } let bgMode0 = bgKey ? resolveModeFrom(bgPool, bgKey, bgOverride) : null; let agentMode0 = agentKey ? resolveModeFrom(agentPool, agentKey, agentOverride) : null; const ctx0 = { mode: modeSel, pageUrl: window.location.href, customKey: cInfo.key, customKind: cInfo.kind, customUrl: cInfo.url, bgKey: bgKey, bgKind: bgMode0 ? String(bgMode0.kind || "html").toLowerCase() : "", bgUrl: guessUrl(bgMode0), agentKey: agentKey }; const rules = Array.isArray(L.rules) ? L.rules : []; for(const r of rules){ if(ruleMatches(r, ctx0)){ const t = (r && r.then) ? r.then : {}; if(t.agentKey) agentKey = normKey(t.agentKey); if(t.bgKey) bgKey = normKey(t.bgKey); if(t.agentOverride && typeof t.agentOverride === "object"){ agentOverride = Object.assign({}, agentOverride || {}, t.agentOverride); } if(t.bgOverride && typeof t.bgOverride === "object"){ bgOverride = Object.assign({}, bgOverride || {}, t.bgOverride); } break; } } /* Mode B: agent follows bg/page recognition (so if nothing set agentKey, keep it stable) */ if(modeSel === "B"){ if(!panel.__itiewAgentKeyOverride && !agentKey) agentKey = normKey(aCfg.active || "A"); } const flags = panel.__itiewFlags || {}; const showAgentCardBlock = !!(aCfg.enabled === true && flags.showAgent && agentCustomBox); const agentMode = agentKey ? resolveModeFrom(agentPool, agentKey, agentOverride) : null; await renderInto(agentCustomBox, !!(showAgentCardBlock && !!agentMode), agentMode, aCfg, "agent"); const showBg = !!(bCfg.enabled === true && bCfg.show === true && bgHost && bgKey); const bgMode = bgKey ? resolveModeFrom(bgPool, bgKey, bgOverride) : null; if(bgHost){ if(showBg && bgMode){ bgHost.hidden = false; bgHost.classList.add("itiew-open"); bgHost.setAttribute("aria-hidden", "false"); await renderInto(bgHost, true, bgMode, bCfg, "bg"); }else{ bgHost.classList.remove("itiew-open"); clearBox(bgHost); bgHost.setAttribute("aria-hidden", "true"); } } panel.classList.toggle("itiew-bg-active", !!(showBg && (bCfg.hideHeroWhenActive === true))); } function setupLimitlessUrlWatch(){ const L = S.limitless || {}; if(!(L.urlWatch && L.urlWatch.enabled)) return; if(window.__ITIEW_LIMITLESS_URLWATCH__) return; window.__ITIEW_LIMITLESS_URLWATCH__ = true; const ev = "__itiew_urlchange"; const dispatch = ()=>{ try{ window.dispatchEvent(new Event(ev)); }catch(e){} }; const fire = ()=>{ syncLimitless("url").catch(()=>{}); }; window.addEventListener(ev, fire); window.addEventListener("hashchange", dispatch); window.addEventListener("popstate", dispatch); const p = history.pushState; const r = history.replaceState; if(typeof p === "function"){ history.pushState = function(){ const out = p.apply(this, arguments); dispatch(); return out; }; } if(typeof r === "function"){ history.replaceState = function(){ const out = r.apply(this, arguments); dispatch(); return out; }; } let last = window.location.href; const ms = Math.max(100, parseInt((L.urlWatch && L.urlWatch.pollMs) || 500, 10) || 500); setInterval(()=>{ const now = window.location.href; if(now !== last){ last = now; dispatch(); } }, ms); } /* ========================================================== LAYOUT: CONTACT AREA + STACKING ========================================================== */ function layoutContactArea(){ if(!contactArea) return; if(!panel.classList.contains("itiew-contact-open")){ panel.style.removeProperty("--itiew-contact-max-h"); contactArea.style.height = ""; contactArea.style.maxHeight = ""; if(customBox){ customBox.style.height = ""; customBox.style.maxHeight = ""; } return; } const manualMax = (S.manual && S.manual.contactBox && S.manual.contactBox.maxHeight) ? String(S.manual.contactBox.maxHeight) : ""; const manualH = (S.manual && S.manual.contactBox && S.manual.contactBox.height) ? String(S.manual.contactBox.height) : ""; const pillH = contactToggle ? Math.ceil(contactToggle.getBoundingClientRect().height || 44) : 44; const panelH = Math.ceil(panel.getBoundingClientRect().height || window.innerHeight || 0); const modeKey = String((panel.__itiewCustomKeyOverride || (S.custom && S.custom.active) || "A")).trim().toUpperCase(); const baseMode = (S.custom && S.custom.modes && S.custom.modes[modeKey]) ? S.custom.modes[modeKey] : null; const mode = baseMode ? Object.assign({}, baseMode, (panel.__itiewCustomModeOverride || null)) : null; const kind = mode ? String(mode.kind || "html").toLowerCase() : "html"; const as = (kind === "fetch") ? String((mode && mode.as) || "text").toLowerCase() : ""; const embedKinds = new Set(["iframe","youtube","vimeo","pdf","map","matterport","calendly"]); const isEmbed = embedKinds.has(kind) || (kind === "fetch" && as === "html"); const f = panel.__itiewFlags || {}; const customCfg = S.custom || {}; const wantsFull = !!(f.showCustom && customCfg.fullHeight && (customCfg.only || !f.showAgent) && isEmbed); const cssMax = getComputedStyle(panel).getPropertyValue("--itiew-contact-max-h"); const baseMaxPx = resolveLenPx(cssMax) || Math.round((window.innerHeight||0) * 0.42); let maxPx = baseMaxPx; if(wantsFull){ maxPx = Math.max(0, panelH - (pillH + 24)); } if(manualMax) maxPx = resolveLenPx(manualMax) || maxPx; panel.style.setProperty("--itiew-contact-max-h", maxPx + "px", "important"); contactArea.style.maxHeight = maxPx + "px"; contactArea.style.height = manualH ? manualH : ""; if(!customBox || customBox.hidden){ if(customBox){ customBox.style.height = ""; customBox.style.maxHeight = ""; } return; } const csCA = getComputedStyle(contactArea); const gap = Math.ceil(parseFloat(csCA.rowGap || csCA.gap) || 0); const pad = Math.ceil((parseFloat(csCA.paddingTop) || 0) + (parseFloat(csCA.paddingBottom) || 0)); const companyH = (companyBox && getComputedStyle(companyBox).display !== "none") ? Math.ceil(companyBox.getBoundingClientRect().height) : 0; const btnsH = (buttonsBox && getComputedStyle(buttonsBox).display !== "none") ? Math.ceil(buttonsBox.getBoundingClientRect().height) : 0; const available = Math.max(0, maxPx - pad - companyH - btnsH - (companyH?gap:0) - (btnsH?gap:0)); const modeHasHeight = !!(mode && mode.height) || !!(S.manual && S.manual.customBox && S.manual.customBox.height); if(!modeHasHeight){ if(isEmbed){ if(!manualH) contactArea.style.height = maxPx + "px"; customBox.style.height = available ? (available + "px") : "0px"; customBox.style.maxHeight = customBox.style.height; }else{ customBox.style.height = ""; customBox.style.maxHeight = ""; } } } function updateOverlayStack(){ const bothVisible = !!panel.__itiewBothVisible; if(!bothVisible || !contactArea || getComputedStyle(contactArea).display === "none"){ panel.style.setProperty("--itiew-contact-stack", "0px"); return; } const h = Math.ceil(contactArea.getBoundingClientRect().height || 0); const g = parseFloat(getComputedStyle(panel).getPropertyValue("--itiew-stack-gap")) || 0; panel.style.setProperty("--itiew-contact-stack", Math.max(0, h + g) + "px"); } /* ========================================================== PRESET ENGINE (HERO -> DEFAULT -> CUSTOM FLOW) ========================================================== */ panel.__itiewCustomKeyOverride = null; panel.__itiewCustomModeOverride = null; panel.__itiewCustomOnlyOverride = null; panel.__itiewAgentKeyOverride = null; panel.__itiewAgentModeOverride = null; panel.__itiewBgKeyOverride = null; panel.__itiewBgModeOverride = null; panel.__itiewActiveFlowItem = null; function normFlowKey(k){ return String(k||"").trim().toUpperCase(); } function buildFlowItems(){ const F = S.menuFlow || {}; if(F.enabled === false) return []; const raw = Array.isArray(F.items) ? F.items : []; const out = []; for(let i=0;i<raw.length;i++){ const it = raw[i] || {}; const key = normFlowKey(it.key || it.customKey || it.mode || ""); if(!key) continue; if(it.enabled === false) continue; if(!(S.custom && S.custom.modes && S.custom.modes[key])) continue; out.push({ id: String(it.id || (key + "_" + (i+1))), key, view: String(it.view || "custom"), titleKey: String(it.titleKey || ""), title: it.title || null, customOnly: (it.customOnly === true || it.customOnly === false) ? it.customOnly : null, modeOverride: (it.modeOverride && typeof it.modeOverride === "object") ? it.modeOverride : null, agentKey: normFlowKey(it.agentKey || it.agent || "") || null, agentOverride: (it.agentOverride && typeof it.agentOverride === "object") ? it.agentOverride : null, bgKey: normFlowKey(it.bgKey || it.backgroundKey || it.bg || "") || null, bgOverride: (it.bgOverride && typeof it.bgOverride === "object") ? it.bgOverride : null }); } if(F.sortByLetter === true){ out.sort((a,b)=> (a.key < b.key ? -1 : (a.key > b.key ? 1 : 0))); } return out; } let flowItems = buildFlowItems(); // Allows admin panel to reconfigure menu flow dynamically panel.__itiewRebuildFlow = function(){ flowItems = buildFlowItems(); try{ if(state.mode === "custom"){ if(!flowItems.length){ gotoHero(); }else{ state.flowIndex = clamp(state.flowIndex, 0, Math.max(0, flowItems.length - 1)); } } updateBottomButton(); }catch(e){} }; const hv0 = S.heroVisibility || {}; const hvMode0 = String(hv0.mode || "default").toLowerCase(); const heroOnLoad = (S.visibility.showHeroImage !== false) && (hvMode0 !== "never") && (hvMode0 === "always" || !!hv0.openOnLoad); const hasHeroStep = !!heroOnLoad; const hasDefaultStep = !defaultViewWantsNone; const state = { mode: (hasHeroStep ? "hero" : "default"), flowIndex: -1, useClosedOpensTo: false }; function heroShouldShowFor(mode, showAgent, contactOpen){ const hv = S.heroVisibility || {}; const m = String(hv.mode || "default").toLowerCase(); const keep = (hv.keepBehindOverlays !== false); if(m === "never") return false; if(!panel.classList.contains("itiew-open")) return false; if(m === "always") return true; if(m === "smart"){ if(mode === "custom") return false; if(!keep && contactOpen) return false; if(mode === "hero") return true; return !!showAgent; } if(mode === "hero") return true; if(mode === "default"){ if(!keep && contactOpen) return false; return !!hv.openOnLoad; } return false; } function getViewStringForState(){ if(state.mode === "default"){ if(state.useClosedOpensTo && S.closedOpensTo){ const raw = String(S.closedOpensTo || "").trim(); const k = normFlowKey(raw); if(k && k.length === 1 && S.custom && S.custom.modes && S.custom.modes[k]) return "custom"; return raw; } return String(S.defaultView || ""); } if(state.mode === "custom"){ const it = flowItems[state.flowIndex]; return it ? String(it.view || "custom") : "custom"; } return "closed"; } function applyFlowOverrides(){ if(state.mode === "custom"){ const it = flowItems[state.flowIndex] || null; panel.__itiewActiveFlowItem = it; panel.__itiewCustomKeyOverride = it ? it.key : null; panel.__itiewCustomModeOverride = it ? it.modeOverride : null; panel.__itiewCustomOnlyOverride = it ? it.customOnly : null; panel.__itiewAgentKeyOverride = it ? (it.agentKey || null) : null; panel.__itiewAgentModeOverride = it ? (it.agentOverride || null) : null; panel.__itiewBgKeyOverride = it ? (it.bgKey || null) : null; panel.__itiewBgModeOverride = it ? (it.bgOverride || null) : null; }else{ panel.__itiewActiveFlowItem = null; const raw = (state.mode === "default" && state.useClosedOpensTo) ? String(S.closedOpensTo || "").trim() : ""; const k = raw ? normFlowKey(raw) : ""; panel.__itiewCustomKeyOverride = (k && k.length === 1 && S.custom && S.custom.modes && S.custom.modes[k]) ? k : null; panel.__itiewCustomModeOverride = null; panel.__itiewCustomOnlyOverride = null; panel.__itiewAgentKeyOverride = null; panel.__itiewAgentModeOverride = null; panel.__itiewBgKeyOverride = null; panel.__itiewBgModeOverride = null; } } function resolveTitleFromItem(it){ if(!it) return (dict.btn_agent_info || "Agent Info"); if(it.titleKey && dict && dict[it.titleKey]) return dict[it.titleKey]; if(it.title && typeof it.title === "string") return it.title; if(it.title && typeof it.title === "object"){ const v = it.title[lang] || it.title.en || it.title.de || it.title.fi || it.title.fr; if(v) return String(v); } const k = "custom_title_" + String(it.key||"").toUpperCase(); if(dict && dict[k]) return dict[k]; return (dict.btn_open_menu || "Open Menu"); } function getNextButtonLabel(){ if(state.mode === "hero"){ return (dict.btn_agent_info || "Agent Info"); } if(state.mode === "default"){ if(flowItems.length) return resolveTitleFromItem(flowItems[0]); return (dict.btn_agent_info || "Agent Info"); } const nextIdx = state.flowIndex + 1; if(nextIdx >= 0 && nextIdx < flowItems.length){ return resolveTitleFromItem(flowItems[nextIdx]); } return (dict.btn_agent_info || "Agent Info"); } function updateBottomButton(){ if(!contactToggle) return; contactToggle.textContent = getNextButtonLabel(); } function gotoHero(){ state.mode = "hero"; state.flowIndex = -1; state.useClosedOpensTo = false; } function gotoDefault(useClosed){ state.mode = "default"; state.flowIndex = -1; state.useClosedOpensTo = !!useClosed; } function gotoCustom(i){ if(!flowItems.length){ gotoHero(); return; } state.mode = "custom"; state.flowIndex = clamp(i, 0, Math.max(0, flowItems.length - 1)); state.useClosedOpensTo = false; } function advanceFlow(){ const target = String(S.closedOpensTo || "").trim(); const isClosedView = (state.mode === "default") && tokenizeView(getViewStringForState()).has("closed"); if(isClosedView && target){ const t = tokenizeView(target); if(t.has("none")){ userClosed = true; wantedOpen = false; closePanel(); return; } if(t.has("closed")){ gotoHero(); return; } gotoDefault(true); return; } if(state.mode === "hero"){ if(hasDefaultStep) gotoDefault(); else if(flowItems.length) gotoCustom(0); else gotoHero(); return; } if(state.mode === "default"){ if(flowItems.length) gotoCustom(0); else if(hasHeroStep) gotoHero(); else gotoDefault(); return; } const next = state.flowIndex + 1; if(next < flowItems.length){ gotoCustom(next); }else{ if(hasHeroStep) gotoHero(); else gotoDefault(); } } function computeFlags(tokens){ const isNone = tokens.has("none"); const isClosed = tokens.has("closed"); const V = S.visibility || {}; const customCfg = S.custom || {}; const customEnabled = (customCfg.enabled === true); const showAgent = tokens.has("agent") && !isClosed && !isNone && (V.showAgentBox !== false); const showCompany = tokens.has("company") && !isClosed && !isNone && (V.showCompanyBlock !== false); const showContacts= tokens.has("contacts")&& !isClosed && !isNone && (V.showMessengerButtons !== false) && !!(S.contactButtons && S.contactButtons.enabled); const showCustom = tokens.has("custom") && !isClosed && !isNone && (V.showCustomBlock !== false) && customEnabled; const onlySetting = (panel.__itiewCustomOnlyOverride === true || panel.__itiewCustomOnlyOverride === false) ? panel.__itiewCustomOnlyOverride : !!customCfg.only; const customOnly = !!(onlySetting && showCustom); const finalShowCompany = customOnly ? false : showCompany; const finalShowContacts = customOnly ? false : showContacts; const showContactArea = !!( !isClosed && !isNone && (V.showContactArea !== false) && (finalShowCompany || finalShowContacts || showCustom) ); return { isNone, isClosed, showAgent, showCompany: finalShowCompany, showContacts: finalShowContacts, showCustom, showContactArea }; } function applyPresetManualOverrides(mode){ const over = (mode === "default") ? (S.manual && S.manual.defaultPresetOverrides) : (S.manual && S.manual.menuPresetOverrides); applyManualBlock(over); } function setDisp(el, show){ if(!el) return; if(show) el.style.removeProperty("display"); else el.style.setProperty("display", "none", "important"); } async function applyPreset(){ applyFlowOverrides(); if(state.mode === "hero"){ applyPresetManualOverrides("default"); const heroVisible = heroShouldShowFor("hero", false, false) && (S.visibility.showHeroImage !== false); setDisp(heroFrame, heroVisible); setDisp(statusBox, false); panel.classList.add("itiew-all-closed"); panel.classList.remove("itiew-contact-open"); panel.classList.remove("itiew-hide-agent"); panel.classList.remove("itiew-custom-only"); if(contactArea) contactArea.setAttribute("aria-hidden", "true"); setDisp(contactArea, false); await renderCustom(false); syncButtons(false); panel.__itiewBothVisible = false; panel.__itiewFlags = { isNone:false, isClosed:true, showAgent:false, showCompany:false, showContacts:false, showCustom:false, showContactArea:false }; syncLimitless("preset").catch(()=>{}); syncPageBg().catch(()=>{}); panel.style.setProperty("--itiew-contact-stack", "0px"); requestAnimationFrame(syncOverlayBottom); setTimeout(()=>{ layoutContactArea(); updateOverlayStack(); updateBottomButton(); }, 0); updateBottomButton(); return; } applyPresetManualOverrides(state.mode === "default" ? "default" : "menu"); const viewStr = getViewStringForState(); const tokens = tokenizeView(viewStr); if(tokens.has("none")){ userClosed = true; wantedOpen = false; closePanel(); return; } const flags = computeFlags(tokens); panel.__itiewFlags = flags; const heroVisible = heroShouldShowFor(state.mode, flags.showAgent, flags.showContactArea) && (S.visibility.showHeroImage !== false); setDisp(heroFrame, heroVisible); setDisp(statusBox, flags.showAgent); panel.classList.toggle("itiew-all-closed", flags.isClosed); panel.classList.toggle("itiew-contact-open", flags.showContactArea); panel.classList.toggle("itiew-hide-agent", (flags.showContactArea && !flags.showAgent && !flags.isClosed)); panel.classList.toggle("itiew-custom-only", !!(flags.showContactArea && flags.showCustom && !flags.showCompany && !flags.showContacts)); if(contactArea) contactArea.setAttribute("aria-hidden", String(!flags.showContactArea)); setDisp(contactArea, flags.showContactArea); const companyAllowedByAttr = companyBox ? (String(companyBox.getAttribute("data-show") || "true").toLowerCase() === "true") : true; const showCompanyBlock = !!( flags.showContactArea && flags.showCompany && companyAllowedByAttr && (S.visibility.showCompanyBlock !== false) ); setDisp(companyBox, showCompanyBlock); await renderCustom(!!(flags.showContactArea && flags.showCustom)); const showButtons = !!( flags.showContactArea && flags.showContacts && (S.visibility.showMessengerButtons !== false) && (S.contactButtons && S.contactButtons.enabled) ); syncButtons(showButtons); panel.__itiewBothVisible = !!(flags.showAgent && flags.showContactArea); requestAnimationFrame(syncOverlayBottom); setTimeout(()=>{ requestAnimationFrame(syncOverlayBottom); }, 40); setTimeout(()=>{ layoutContactArea(); updateOverlayStack(); updateBottomButton(); }, 0); setTimeout(()=>{ layoutContactArea(); updateOverlayStack(); updateBottomButton(); }, 80); syncLimitless("preset").catch(()=>{}); syncPageBg().catch(()=>{}); updateBottomButton(); } panel.__itiewApplyPreset = function(){ applyPreset().catch(()=>{}); }; if(contactToggle){ contactToggle.addEventListener("click", (e)=>{ e.preventDefault(); e.stopPropagation(); // If admin long-press consumed this interaction, do nothing. if(panel.__itiewHoldConsumed){ panel.__itiewHoldConsumed = false; return; } // If admin overlay is open, don't advance flow accidentally. if(panel.__itiewAdminOverlayOpen === true){ return; } advanceFlow(); applyPreset().catch(()=>{}); }, true); } if(hintLine && (S.visibility.showHintLine !== false)){ const base = (dict.hint || hintLine.textContent); if(S.behavior.leftClickOutsideClosesPanel){ hintLine.textContent = base; }else{ const parts = String(base).split("•"); const re = /(left click|linksklick|vasen klikkaus)/i; hintLine.textContent = (parts.find(p=>!re.test(p)) || parts[0] || "").trim(); } } // Initial apply applyPreset().catch(()=>{}); setupLimitlessUrlWatch(); syncLimitless("init").catch(()=>{}); // Resize handlers window.addEventListener("resize", ()=>{ requestAnimationFrame(syncOverlayBottom); setTimeout(()=>{ layoutContactArea(); updateOverlayStack(); }, 0); }); window.addEventListener("orientationchange", ()=>{ requestAnimationFrame(syncOverlayBottom); setTimeout(()=>{ layoutContactArea(); updateOverlayStack(); }, 0); }); if(document.fonts && document.fonts.ready){ document.fonts.ready.then(()=>{ requestAnimationFrame(syncOverlayBottom); setTimeout(()=>{ layoutContactArea(); updateOverlayStack(); }, 0); }).catch(()=>{}); } setTimeout(()=>requestAnimationFrame(syncOverlayBottom), 60); } } })(); </script> </body> </html>
Switching language to
Skip Video

Choose Your Language

initializing ...
Chat
    input locked





    -/-
    -/-
    1 here    1 total
      |  
     0 views


    LOADING VR EXPERIENCE ...
      Orbit - Left mouse
      Zoom - Middle mouse or mousewheel
      Pan - Right mouse or left mouse + ctrl/meta/shiftKey
        All
        Close
      Meeting 

      -

      Average Rating

      - comments





        Write a review