Check server response of

Server response
NS records
Whois domain
Response headers
Request headers
Raw HTML code
301 Moved Permanently - on4.com
HTTP Status: 301
User-Agent: Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
Date: Mon, 05 May 2025 18:34:15 GMT
Content-Type: text/html
Content-Length: 167
Connection: keep-alive
Cache-Control: max-age=3600
Expires: Mon, 05 May 2025 19:34:15 GMT
Location: https://on4.com/
Report-To: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=pJAVRa%2FwfF2cxSIcbwOQZNfG4vBJGwxjdLO2ZEu6Hi4KgfLYmZjl8cQHtzyaRGB3Hj4RPmXYILrqIsvfxW9OgkMrI83IkKRrBh4CaxgjMcglgw%2BoTdN2Q1u7HUptMYNFkZsdUTBK"}],"group":"cf-nel","max_age":604800}
NEL: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
Server: cloudflare
CF-RAY: 93b254b6fe2bcd53-LHR
alt-svc: h3=":443"; ma=86400
server-timing: cfL4;desc="?proto=TCP&rtt=32246&min_rtt=32246&rtt_var=16123&sent=1&recv=3&lost=0&retrans=0&sent_bytes=0&recv_bytes=163&delivery_rate=0&cwnd=249&unsent_bytes=0&cid=0000000000000000&ts=0&x=0"

HTTP Code 301 Moved Permanently

301 status code means that the requested resource has been permanently moved to a new URL. All future requests should use the new address.

When is Code 301 used?

  • When changing a website domain
  • When modifying URL structures
  • When setting up redirects for SEO

What does Code 301 mean for the user?

The browser will automatically redirect the user to the new address, and search engines will update their indexes.

200 OK - https://on4.com/
HTTP Status: 200
User-Agent: Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
Date: Mon, 05 May 2025 18:34:15 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Server: cloudflare
Last-Modified: Tue, 08 Apr 2025 20:18:00 GMT
Vary: accept-encoding
X-Powered-By: PleskLin
Cf-Cache-Status: DYNAMIC
CF-RAY: 93b254b7db01694b-FRA
alt-svc: h3=":443"; ma=86400

HTTP Code 200 OK

200 status code is a standard successful HTTP server response. It means that the client’s request (e.g., from a browser) was successfully processed, and the server is delivering the requested data.

When is Code 200 used?

  • When loading a web page
  • When successfully receiving an API response
  • When processing a form or another HTTP request

What does Code 200 mean for the user?

The user receives content without errors, and the page or application functions properly. If Code 200 is accompanied by data, the browser or program processes and displays it to the user.

GET / HTTP/1.1
Host: on4.com
Accept: */*
User-Agent: Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Time Zone Converter</title>
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <!-- Include LZ-String for compressing/decompressing state -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lz-string/1.4.4/lz-string.min.js"></script>
  <style>
    /* Brutalist Minimal */
    :root {
      --accent: #d00; /* strong red accent */
      --bg: #fff;
      --text: #000;
      --grey: #ccc;
    }
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
      font-family: monospace;
      background: var(--bg);
      color: var(--text);
      padding: 1rem;
    }
    h1, h2, h3 { margin: 0.5rem 0; text-transform: uppercase; }
    /* Tabs */
    .tab-nav {
      display: flex; gap: 1rem; justify-content: center; margin-bottom: 1rem;
    }
    .tab-nav button {
      background: #eee; color: var(--text); border: 2px solid #000;
      padding: 0.5rem 1rem; font-weight: bold; text-transform: uppercase; cursor: pointer;
    }
    .tab-nav button.active {
      background: var(--accent); color: #fff; border-color: var(--accent);
    }
    .tab-content { display: none; max-width: 900px; margin: 0 auto; }
    .tab-content.active { display: block; }
    /* Card layout */
    .card {
      border: 2px solid var(--grey);
      padding: 1rem; margin-bottom: 1rem;
    }
    label { font-weight: bold; display: block; margin-bottom: 0.2rem; }
    input, select {
      border: 2px solid #000; font-family: inherit; padding: 0.3rem; width: 100%;
    }
    .row { display: flex; gap: 1rem; }
    .btn {
      border: 2px solid #000;
      background: #eee;
      padding: 0.4rem 0.8rem;
      font-weight: bold;
      text-transform: uppercase;
      cursor: pointer;
    }
    .btn.accent {
      background: var(--accent);
      color: #fff;
      border-color: var(--accent);
    }
    /* Dropdown styling */
    .dropdown {
      position: absolute;
      border: 2px solid #000;
      background: #fff;
      max-height: 150px;
      overflow-y: auto;
      display: none;
      z-index: 999999;
    }
    .dropdown.show { display: block; }
    .dropdown-item {
      padding: 0.3rem 0.5rem;
      cursor: pointer;
    }
    .dropdown-item:hover { background: #f88; }
    /* Overlaps container */
    .overlaps {
      display: none;
      border: 2px solid var(--accent);
      margin-top: 0.5rem;
      padding: 0.5rem;
    }
    /* Targets (Meeting Scheduler) */
    .target-item {
      display: flex;
      justify-content: space-between;
      align-items: center;
      border: 2px solid #000;
      padding: 0.3rem;
      margin-top: 0.3rem;
    }
    .time-display, .time-diff { margin-right: 0.3rem; }
    .remove-btn {
      background: none; border: none; color: var(--accent);
      cursor: pointer; font-weight: bold; margin-left: 0.3rem;
    }
    /* Time Slider tab */
    .clocks-container {
      display: grid;
      grid-template-columns: repeat(5, 1fr);
      gap: 0.5rem;
      width: 100%;
    }
    .clock-card {
      border: 2px solid #000;
      padding: 0.5rem;
      text-align: center;
      position: relative;
    }
    .digital-clock {
      background: #000; color: #0f0;
      padding: 0.3rem 0.6rem;
      display: inline-block;
      margin: 0.5rem 0;
      font-weight: bold;
    }
    .base-badge {
      color: var(--accent);
      font-size: 0.8rem;
      font-weight: bold;
    }
    .remove-clock {
      color: var(--accent);
      font-size: 0.8rem;
      cursor: pointer;
      font-weight: bold;
      margin-top: 0.3rem;
    }
    .make-base {
      color: var(--accent);
      font-size: 0.8rem;
      font-weight: bold;
      cursor: pointer;
      margin-top: 0.3rem;
    }
    /* Range slider */
    input[type="range"] {
      -webkit-appearance: none;
      height: 6px;
      cursor: pointer;
      background: transparent;
      outline: none;
    }
    input[type="range"]::-webkit-slider-runnable-track {
      height: 6px;
      background: var(--accent);
      border: 2px solid #000;
    }
    input[type="range"]::-moz-range-track {
      height: 6px; background: var(--accent); border: 2px solid #000;
    }
    input[type="range"]::-webkit-slider-thumb {
      -webkit-appearance: none;
      width: 16px; height: 16px;
      background: #fff; border: 2px solid #000;
      margin-top: -6px;
    }
    input[type="range"]::-moz-range-thumb {
      width: 16px; height: 16px;
      background: #fff; border: 2px solid #000;
    }
    /* Text link styling for small actions */
    .top5-link {
      font-size: 0.85rem;
      font-weight: normal;
      color: var(--accent);
      text-decoration: underline;
      margin-left: 1rem;
      cursor: pointer;
    }
  </style>
  <script async defer src="https://app.visitortracking.com/assets/js/tracer.js"></script>
  <script>
    function init_tracer() { 
      var tracer = new Tracer({  
        websiteId : "b5a0706a-c49f-4ec3-9935-30032808f78e",  
        async : true, 
        debug : false 
      }); 
    } 
  </script>
	<!-- Pixel Code - https://ore.io/ -->
<script defer src="https://ore.io/pixel/BPYqh0Lcoh39ApjK"></script>
<!-- END Pixel Code -->
</head>
<body>
  <!-- Tabs -->
  <div class="tab-nav">
    <button id="tabBtn1" class="active">Meeting Scheduler</button>
    <button id="tabBtn2">Time Slider</button>
  </div>

  <!-- TAB #1: Meeting Scheduler -->
  <div id="tab1" class="tab-content active">
    <h1>Meeting Scheduler</h1>
    <p style="margin-bottom:1rem;">
      Pick a <strong>Source City</strong> and set your desired date/time, then add
      multiple <strong>Target Cities</strong> to compare local times. You can also
      find <strong>8:00–18:00 overlaps</strong> that suit all.
    </p>

    <div class="card">
      <div class="row">
        <div style="position: relative; flex: 1;">
          <label>Source City</label>
          <input type="text" id="sourceCity">
          <div class="dropdown" id="srcDD"></div>
        </div>
        <button id="useLocBtn" class="btn accent" style="align-self: flex-end;">Current</button>
      </div>
      <div class="row" style="margin-top: 0.5rem;">
        <div style="flex: 1;">
          <label>Date</label>
          <input type="date" id="sourceDate">
        </div>
        <div style="flex: 1;">
          <label>Time (30min)</label>
          <select id="sourceTimeSelect"></select>
        </div>
      </div>
    </div>

    <div class="card">
      <div style="position: relative;">
        <label>Target City</label>
        <input type="text" id="targetCity">
        <div class="dropdown" id="tgtDD"></div>
      </div>
      <div id="tgtList"></div>
    </div>

    <div class="row" style="gap: 0.5rem;">
      <button id="icsBtn" class="btn">Local Cal</button>
      <button id="gCalBtn" class="btn">Google Cal</button>
	  <button id="overlapsBtn" class="btn">Overlaps</button>

      <!-- Deep Link button for Meeting Scheduler -->
      <button id="deepLinkBtnMeeting" class="btn">Share Link</button>
      <span id="resetLinkMeeting" class="top5-link">Clear</span>
    </div>

    <div class="overlaps" id="overlapsPanel">
      <h3>8:00–18:00 Overlaps</h3>
      <p>In <span id="sourceCityLabel">[source]</span> these hours also work for all targets:</p>
      <div id="overlapsRes"></div>
    </div>
  </div>

  <!-- TAB #2: Time Slider -->
  <div id="tab2" class="tab-content">
    <h1>Time Slider</h1>
    <p style="margin-bottom:1rem;">
      Choose a <strong>Base City</strong> to anchor the slider, then add more cities.
      Adjust the slider (in 30-min increments) to see each city's corresponding local time.
    </p>

    <div class="card">
      <div class="row" style="align-items: center;">
        <label>Base Time</label>
        <input type="range" id="slider" min="0" max="47" step="1" value="0" style="flex: 1;">
        <div id="sliderLabel" style="width: 50px; text-align: center;">00:00</div>
      </div>
    </div>

    <div class="card">
      <!-- Label with three text links: Add Top 5, Share Link, and Reset -->
      <div style="position: relative;">
        <label>
          Add City
          <span id="top5Link" class="top5-link">(Add Top 5)</span>
          <span id="deepLinkTextSlider" class="top5-link">(Share Link)</span>
          <span id="resetLinkSlider" class="top5-link">Clear</span>
        </label>
        <input type="text" id="sliderCity">
        <div class="dropdown" id="sliderDD"></div>
      </div>
    </div>

    <!-- Container for clocks -->
    <div class="clocks-container" id="clockList"></div>
  </div>

  <script>
    document.addEventListener('DOMContentLoaded', () => {
      // --- TAB SWITCHING ---
      const tabBtn1 = document.getElementById('tabBtn1'),
            tabBtn2 = document.getElementById('tabBtn2'),
            tab1 = document.getElementById('tab1'),
            tab2 = document.getElementById('tab2');

      tabBtn1.addEventListener('click', () => {
        tabBtn1.classList.add('active');
        tabBtn2.classList.remove('active');
        tab1.classList.add('active');
        tab2.classList.remove('active');
      });
      tabBtn2.addEventListener('click', () => {
        tabBtn2.classList.add('active');
        tabBtn1.classList.remove('active');
        tab2.classList.add('active');
        tab1.classList.remove('active');
      });

      // --- GLOBAL tzData ---
      window.tzData = [];
      fetch('tz.csv')
        .then(r => {
          if (!r.ok) throw new Error('tz.csv missing');
          return r.text();
        })
        .then(txt => {
          parseTZCSV(txt);
          return fetch('extraCities.json');
        })
        .then(r => {
          if (!r.ok) { console.warn('No extraCities'); return []; }
          return r.json();
        })
        .then(ex => {
          if (Array.isArray(ex)) mergeExtra(ex);
          initScheduler();
          initTimeSlider();
          applyDeepLink(); // restore state from URL parameters
        })
        .catch(err => {
          console.error(err);
          initScheduler();
          initTimeSlider();
          applyDeepLink();
        });

      // --- PARSE CSV ---
      function parseTZCSV(csv) {
        const lines = csv.trim().split(/\r?\n/);
        lines.shift(); // remove header
        lines.forEach(l => {
          const [rc, co, tz, ab] = l.split(',').map(x => x?.replace(/^"|"$/g, '').trim());
          if (!tz) return;
          const synonyms = [];
          const seg = rc.split('/');
          let city = seg[seg.length - 1]?.replace(/_/g, ' ') || tz;
          let rcLow = rc.toLowerCase();
          if (rcLow && !synonyms.includes(rcLow)) synonyms.push(rcLow);
          if (city && !synonyms.includes(city.toLowerCase())) synonyms.push(city.toLowerCase());
          if (co && !synonyms.includes(co.toLowerCase())) synonyms.push(co.toLowerCase());
          (ab || '').split('|').forEach(a => {
            const aa = a.trim().toLowerCase();
            if (aa && !synonyms.includes(aa)) synonyms.push(aa);
          });
          tzData.push({ tz, city, synonyms });
        });
      }
      // --- Merge extra cities ---
      function mergeExtra(eArr) {
        eArr.forEach(o => {
          let f = tzData.find(x => x.tz === o.tz);
          if (!f) {
            f = { tz: o.tz, city: o.city || o.tz, synonyms: [] };
            tzData.push(f);
          }
          const cLo = (o.city || '').toLowerCase();
          const coLo = (o.country || '').toLowerCase();
          if (cLo && !f.synonyms.includes(cLo)) f.synonyms.push(cLo);
          if (coLo && !f.synonyms.includes(coLo)) f.synonyms.push(coLo);
        });
      }

      // --- MEETING SCHEDULER ---
      function initScheduler() {
        const sCity = document.getElementById('sourceCity'),
              sDD = document.getElementById('srcDD'),
              locBtn = document.getElementById('useLocBtn'),
              sDate = document.getElementById('sourceDate'),
              sTime = document.getElementById('sourceTimeSelect'),
              tCity = document.getElementById('targetCity'),
              tDD = document.getElementById('tgtDD'),
              tList = document.getElementById('tgtList'),
              icsBtn = document.getElementById('icsBtn'),
              gCalBtn = document.getElementById('gCalBtn'),
              overlapsBtn = document.getElementById('overlapsBtn'),
              overlapsPanel = document.getElementById('overlapsPanel'),
              srcCityLabel = document.getElementById('sourceCityLabel'),
              resetLinkMeeting = document.getElementById('resetLinkMeeting');
        let sourceTZ = null, targets = [];

        // Fill time options if empty
        if (!sTime.options.length) {
          for (let h = 0; h < 24; h++) {
            for (let m = 0; m < 60; m += 30) {
              const val = `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;
              const opt = document.createElement('option');
              opt.value = val;
              opt.textContent = val;
              sTime.appendChild(opt);
            }
          }
        }

        sCity.addEventListener('input', () => 
          searchZone(sCity, sDD, (found) => {
            sourceTZ = found.tz;
            sCity.value = `${found.city} (${found.tz})`;
            updateAllTimes();
          })
        );
        tCity.addEventListener('input', () => 
          searchZone(tCity, tDD, (found) => {
            if (!targets.find(x => x.tz === found.tz)) {
              targets.push({ tz: found.tz, city: found.city });
              addTargetItem(found);
            }
            tCity.value = '';
            updateAllTimes();
          })
        );

        document.addEventListener('click', e => {
          if (!sDD.contains(e.target) && e.target !== sCity) sDD.style.display = 'none';
          if (!tDD.contains(e.target) && e.target !== tCity) tDD.style.display = 'none';
        });

        locBtn.addEventListener('click', () => {
          const sys = Intl.DateTimeFormat().resolvedOptions().timeZone;
          const f = tzData.find(x => x.tz === sys);
          if (f) {
            sourceTZ = sys;
            sCity.value = `${f.city} (${sys})`;
          } else {
            sourceTZ = sys;
            sCity.value = `(${sys})`;
          }
          updateAllTimes();
        });

        function addTargetItem(o) {
          const div = document.createElement('div');
          div.className = 'target-item';
          div.dataset.tz = o.tz;
          div.innerHTML = `
            <div>
              <strong>${o.city}</strong><br><small>${o.tz}</small>
            </div>
            <div>
              <span class="time-display"></span>
              <span class="time-diff"></span>
              <button class="remove-btn">x</button>
            </div>
          `;
          tList.appendChild(div);
          calcTime(div);
          div.querySelector('.remove-btn').addEventListener('click', () => {
            targets = targets.filter(x => x.tz !== o.tz);
            div.remove();
          });
        }
        function updateAllTimes() {
          document.querySelectorAll('.target-item').forEach(div => calcTime(div));
        }
        function calcTime(div) {
          if (!sourceTZ) {
            div.querySelector('.time-display').textContent = '';
            return;
          }
          const tz = div.dataset.tz;
          const utc = getSourceUTC();
          const str = fmtLocal(utc, tz);
          div.querySelector('.time-display').textContent = str;
          const diff = getOffset(utc, tz) - getOffset(utc, sourceTZ);
          if (diff === 0) {
            div.querySelector('.time-diff').textContent = 'same';
          } else {
            const hrs = Math.abs(Math.floor(diff / 60));
            div.querySelector('.time-diff').textContent = diff > 0 ? `${hrs}h ahead` : `${hrs}h behind`;
          }
        }
        function getSourceUTC() {
          const dV = sDate.value, tV = sTime.value;
          if (!dV || !tV) return new Date();
          const local = new Date(`${dV}T${tV}`);
          const off = getOffset(local, sourceTZ);
          const oh = Math.floor(Math.abs(off)/60),
                om = Math.abs(off)%60,
                sign = off >= 0 ? '+' : '-';
          return new Date(`${dV}T${tV}:00${sign}${String(oh).padStart(2, '0')}:${String(om).padStart(2, '0')}`);
        }

        icsBtn.addEventListener('click', () => {
          if (!sourceTZ) { alert('No source'); return; }
          const st = getSourceUTC(), en = new Date(st.getTime() + 3600000);
          const ics = buildICS(st, en, (sCity.value || 'Online'));
          downloadFile(ics, 'event.ics', 'text/calendar');
        });
        gCalBtn.addEventListener('click', () => {
          if (!sourceTZ) { alert('No source'); return; }
          const start = getSourceUTC(), end = new Date(start.getTime() + 3600000);
          const S = fmtGCal(start), E = fmtGCal(end),
                sum = 'My Event', loc = sCity.value || 'Online', details = 'Scheduled';
          const url = `https://calendar.google.com/calendar/render?action=TEMPLATE&text=${encodeURIComponent(sum)}&dates=${S}/${E}&details=${encodeURIComponent(details)}&location=${encodeURIComponent(loc)}`;
          window.open(url, '_blank');
        });

        overlapsBtn.addEventListener('click', () => {
          if (!sourceTZ) { alert('No source'); return; }
          if (!targets.length) { alert('No target'); return; }
          srcCityLabel.textContent = parseCity(sCity.value);
          const dayVal = sDate.value;
          const out = [];
          for (let h = 0; h < 24; h++) {
            for (let m = 0; m < 60; m += 30) {
              const hhmm = `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;
              const local = new Date(`${dayVal}T${hhmm}`);
              const so = getOffset(local, sourceTZ);
              const oh = Math.floor(Math.abs(so)/60),
                    om = Math.abs(so)%60,
                    sg = so >= 0 ? '+' : '-';
              const candidateUTC = new Date(`${dayVal}T${hhmm}:00${sg}${String(oh).padStart(2, '0')}:${String(om).padStart(2, '0')}`);
              const sr = fmtHour(candidateUTC, sourceTZ);
              if (sr < 8 || sr >= 18) continue;
              let allOk = true;
              for (let t of targets) {
                const h2 = fmtHour(candidateUTC, t.tz);
                if (h2 < 8 || h2 >= 18) { allOk = false; break; }
              }
              if (allOk) out.push(hhmm);
            }
          }
          document.getElementById('overlapsRes').innerHTML = out.length ? out.join('<br>') : 'No overlap found.';
          overlapsPanel.style.display = 'block';
        });

        // --- Meeting Scheduler: Share Link ---
        const deepLinkBtnMeeting = document.getElementById('deepLinkBtnMeeting');
        if (deepLinkBtnMeeting) {
          deepLinkBtnMeeting.addEventListener('click', () => {
            const url = getMeetingDeepLink();
            navigator.clipboard.writeText(url).then(() => {
              alert('Deep link copied to clipboard:\n' + url);
            }, () => {
              alert('Failed to copy deep link');
            });
          });
        }
        function getMeetingDeepLink() {
          const state = {
            tab: 'meeting',
            source: sCity.value,
            date: sDate.value,
            time: sTime.value,
            targets: []
          };
          const targetItems = document.querySelectorAll('#tgtList .target-item');
          targetItems.forEach(item => { if (item.dataset.tz) state.targets.push(item.dataset.tz); });
          const json = JSON.stringify(state);
          const compressed = LZString.compressToEncodedURIComponent(json);
          return window.location.origin + window.location.pathname + '?s=' + compressed;
        }
        // --- Meeting Scheduler: Reset ---
        resetLinkMeeting.addEventListener('click', () => {
          // Clear all fields and target list
          sourceTZ = null;
          sCity.value = '';
          sDate.value = '';
          sTime.selectedIndex = 0;
          tList.innerHTML = '';
          targets = [];
        });
        // Expose addTargetItem so deep linking can use it
        window.addTargetItem = addTargetItem;
      }

      // --- TIME SLIDER ---
      function initTimeSlider() {
        const slider = document.getElementById('slider'),
              sliderLabel = document.getElementById('sliderLabel'),
              sCity = document.getElementById('sliderCity'),
              dd = document.getElementById('sliderDD'),
              clockContainer = document.getElementById('clockList'),
              top5Link = document.getElementById('top5Link'),
              deepLinkTextSlider = document.getElementById('deepLinkTextSlider'),
              resetLinkSlider = document.getElementById('resetLinkSlider');
        let baseTZ = null, clockList = [];

        sliderLabel.textContent = val2HHMM(slider.value);
        slider.addEventListener('input', () => {
          sliderLabel.textContent = val2HHMM(slider.value);
          updateAllClocks();
        });

        // "Add Top 5" link
        const popularTZs = [
          "America/New_York",
          "America/Los_Angeles",
          "Europe/London",
          "Asia/Tokyo",
          "Australia/Sydney"
        ];
        top5Link.addEventListener('click', (e) => {
          e.preventDefault();
          popularTZs.forEach(tzName => {
            const f = tzData.find(x => x.tz === tzName);
            if (f) addClock(f);
          });
        });

        // --- Time Slider: Share Link ---
        deepLinkTextSlider.addEventListener('click', (e) => {
          e.preventDefault();
          const url = getSliderDeepLink();
          navigator.clipboard.writeText(url).then(() => {
            alert('Deep link copied to clipboard:\n' + url);
          }, () => {
            alert('Failed to copy deep link');
          });
        });

        // --- Time Slider: Reset ---
        resetLinkSlider.addEventListener('click', () => {
          // Reset slider and remove all clocks
          slider.value = 0;
          sliderLabel.textContent = val2HHMM(slider.value);
          clockContainer.innerHTML = '';
          clockList = [];
          baseTZ = null;
          sCity.value = '';
        });

        // Custom city search for slider
        sCity.addEventListener('input', () => {
          const q = sCity.value.trim().toLowerCase();
          dd.innerHTML = '';
          if (!q) { dd.style.display = 'none'; return; }
          let f = tzData.filter(o => o.city.toLowerCase().includes(q) || o.synonyms.some(x => x.includes(q)));
          if (!f.length) { dd.style.display = 'none'; return; }
          dd.innerHTML = f.slice(0, 10).map(o => `
            <div class="dropdown-item" data-tz="${o.tz}"><b>${o.city}</b><br><small>${o.tz}</small></div>
          `).join('');
          dd.style.display = 'block';
          dd.querySelectorAll('.dropdown-item').forEach(el => {
            el.addEventListener('click', () => {
              let z = tzData.find(xx => xx.tz === el.dataset.tz);
              if (z) addClock(z);
              dd.style.display = 'none';
              sCity.value = '';
            });
          });
        });
        document.addEventListener('click', e => {
          if (!dd.contains(e.target) && e.target !== sCity) dd.style.display = 'none';
        });

        function addClock(o) {
          if (clockList.find(x => x.tz === o.tz)) return;
          const div = document.createElement('div');
          div.className = 'clock-card';
          div.dataset.tz = o.tz;
          div.innerHTML = `
            <h3>${o.city}</h3>
            <div class="digital-clock">--:--</div>
            <div class="remove-clock">Remove</div>
            <span class="make-base">Make Base</span>
            <div class="base-badge" style="display:none;">(BASE)</div>
          `;
          clockContainer.appendChild(div);
          let cObj = { tz: o.tz, city: o.city, elm: div, isBase: false };
          clockList.push(cObj);
          if (!baseTZ) { setBase(o.tz); }
          div.querySelector('.remove-clock').addEventListener('click', () => {
            clockList = clockList.filter(x => x.tz !== o.tz);
            div.remove();
            if (o.tz === baseTZ) {
              if (clockList.length) setBase(clockList[0].tz); else baseTZ = null;
            }
          });
          div.querySelector('.make-base').addEventListener('click', () => {
            setBase(o.tz);
            updateAllClocks();
          });
          updateClock(cObj);
        }
        function setBase(tz) {
          baseTZ = tz;
          clockList.forEach(x => x.isBase = (x.tz === tz));
          updateBadges();
        }
        function updateBadges() {
          clockList.forEach(x => {
            let bb = x.elm.querySelector('.base-badge'),
                mk = x.elm.querySelector('.make-base');
            if (x.isBase) { bb.style.display = 'inline'; mk.style.display = 'none'; }
            else { bb.style.display = 'none'; mk.style.display = 'inline'; }
          });
        }
        function updateAllClocks() { clockList.forEach(c => updateClock(c)); }
        function updateClock(c) {
          if (!baseTZ) return;
          let utc = getBaseUTC();
          let local = toLocal(utc, c.tz);
          let hh = String(local.getHours()).padStart(2, '0'),
              mm = String(local.getMinutes()).padStart(2, '0');
          let baseLoc = toLocal(utc, baseTZ);
          let ddiff = dayNum(local) - dayNum(baseLoc);
          let dayL = ddiff === 0 ? '' : ddiff > 0 ? ` (+${ddiff}d)` : ` (${ddiff}d)`;
          c.elm.querySelector('.digital-clock').textContent = `${hh}:${mm}${dayL}`;
        }
        function getBaseUTC() {
          if (!baseTZ) return new Date();
          let val = +slider.value, tot = val * 30;
          let now = new Date(), y = now.getUTCFullYear(), m = now.getUTCMonth(), d = now.getUTCDate();
          let localMid = new Date(Date.UTC(y, m, d, 0, 0, 0)),
              off = getOffset(localMid, baseTZ);
          localMid.setUTCMinutes(localMid.getUTCMinutes() + off + tot);
          return localMid;
        }
        function val2HHMM(v) { let tot = +v * 30, h = Math.floor(tot / 60), mm = tot % 60; return `${String(h).padStart(2, '0')}:${String(mm).padStart(2, '0')}`; }
        function toLocal(utc, tz) { return new Date(utc.getTime() + getOffset(utc, tz) * 60000); }
        function dayNum(d) { let x = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate())); return Math.floor(x.getTime() / 86400000); }

        // --- Time Slider: Generate Short Deep Link ---
        function getSliderDeepLink() {
          const state = {
            tab: 'slider',
            slider: slider.value,
            base: null,
            clocks: []
          };
          // Determine the base timezone from clock cards:
          const clockCards = document.querySelectorAll('#clockList .clock-card');
          clockCards.forEach(card => {
            if (card.querySelector('.base-badge') && card.querySelector('.base-badge').style.display !== 'none') {
              state.base = card.dataset.tz;
            }
          });
          clockCards.forEach(card => { state.clocks.push(card.dataset.tz); });
          const json = JSON.stringify(state);
          const compressed = LZString.compressToEncodedURIComponent(json);
          return window.location.origin + window.location.pathname + '?s=' + compressed;
        }
        // Expose addClock for deep linking
        window.addClock = addClock;
      }

      // --- APPLY DEEP LINK ON PAGE LOAD ---
      function applyDeepLink() {
        const params = new URLSearchParams(window.location.search);
        if (params.has('s')) {
          // Use compressed state if available
          const compressed = params.get('s');
          const json = LZString.decompressFromEncodedURIComponent(compressed);
          if (json) {
            const state = JSON.parse(json);
            if (state.tab === 'meeting') {
              document.getElementById('tabBtn1').click();
              if (state.source) {
                document.getElementById('sourceCity').value = state.source;
                document.getElementById('sourceCity').dispatchEvent(new Event('input'));
              }
              if (state.date) document.getElementById('sourceDate').value = state.date;
              if (state.time) document.getElementById('sourceTimeSelect').value = state.time;
              if (state.targets && Array.isArray(state.targets)) {
                state.targets.forEach(tz => {
                  const found = tzData.find(x => x.tz === tz);
                  if (found && window.addTargetItem) {
                    window.addTargetItem(found);
                  }
                });
              }
            } else if (state.tab === 'slider') {
              document.getElementById('tabBtn2').click();
              if (state.slider) {
                const slider = document.getElementById('slider');
                slider.value = state.slider;
                slider.dispatchEvent(new Event('input'));
              }
              if (state.clocks && Array.isArray(state.clocks)) {
                state.clocks.forEach(tz => {
                  const found = tzData.find(x => x.tz === tz);
                  if (found && window.addClock) {
                    window.addClock(found);
                  }
                });
              }
              if (state.base) {
                const clockCards = document.querySelectorAll('#clockList .clock-card');
                clockCards.forEach(card => {
                  if (card.dataset.tz === state.base) {
                    card.querySelector('.make-base').click();
                  }
                });
              }
            }
          }
        } else if (params.get('tab')) {
          // Fallback: use uncompressed query parameters if available
          const tab = params.get('tab');
          if (tab === 'meeting') {
            document.getElementById('tabBtn1').click();
            const source = params.get('source'),
                  date = params.get('date'),
                  time = params.get('time');
            if (source) {
              document.getElementById('sourceCity').value = source;
              document.getElementById('sourceCity').dispatchEvent(new Event('input'));
            }
            if (date) document.getElementById('sourceDate').value = date;
            if (time) document.getElementById('sourceTimeSelect').value = time;
            const targets = params.get('targets');
            if (targets) {
              const targetArr = targets.split(',');
              targetArr.forEach(tz => {
                const found = tzData.find(x => x.tz === tz);
                if (found && window.addTargetItem) {
                  window.addTargetItem(found);
                }
              });
            }
          } else if (tab === 'slider') {
            document.getElementById('tabBtn2').click();
            const sliderVal = params.get('slider');
            if (sliderVal) {
              const slider = document.getElementById('slider');
              slider.value = sliderVal;
              slider.dispatchEvent(new Event('input'));
            }
            const clocks = params.get('clocks');
            if (clocks) {
              const clocksArr = clocks.split(',');
              clocksArr.forEach(tz => {
                const found = tzData.find(x => x.tz === tz);
                if (found && window.addClock) {
                  window.addClock(found);
                }
              });
            }
            const base = params.get('base');
            if (base) {
              const clockCards = document.querySelectorAll('#clockList .clock-card');
              clockCards.forEach(card => {
                if (card.dataset.tz === base) {
                  card.querySelector('.make-base').click();
                }
              });
            }
          }
        }
      }

      // --- HELPER FUNCTIONS ---
      function searchZone(inp, dd, cb) {
        const q = inp.value.trim().toLowerCase();
        dd.innerHTML = '';
        if (!q) { dd.style.display = 'none'; return; }
        const found = tzData.filter(o => o.city.toLowerCase().includes(q) || o.synonyms.some(s => s.includes(q)));
        if (!found.length) { dd.style.display = 'none'; return; }
        dd.innerHTML = found.slice(0, 10).map(x => `
          <div class="dropdown-item" data-tz="${x.tz}">
            <b>${x.city}</b><br><small>${x.tz}</small>
          </div>
        `).join('');
        dd.style.display = 'block';
        dd.querySelectorAll('.dropdown-item').forEach(el => {
          el.addEventListener('click', () => {
            const z = tzData.find(fz => fz.tz === el.dataset.tz);
            if (z) cb(z);
            dd.style.display = 'none';
          });
        });
      }
      function getOffset(d, tz) {
        const f = new Intl.DateTimeFormat('en', { timeZone: tz, timeZoneName: 'shortOffset' }).formatToParts(d);
        const nm = f.find(x => x.type === 'timeZoneName')?.value || '';
        const m = nm.match(/GMT([+-]\d+)(?::(\d+))?/);
        if (!m) return 0;
        const s = m[1].startsWith('-') ? -1 : 1,
              hrs = parseInt(m[1].replace(/\D/g, ''), 10),
              mn = m[2] ? parseInt(m[2], 10) : 0;
        return s * (hrs * 60 + mn);
      }
      function fmtLocal(u, tz) {
        const opt = { timeZone: tz, hour12: false, weekday: 'short', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' };
        return new Intl.DateTimeFormat('en-US', opt).format(u);
      }
      function fmtHour(u, tz) {
        const opt = { timeZone: tz, hour: '2-digit', hour12: false };
        return parseInt(new Intl.DateTimeFormat('en', opt).format(u), 10);
      }
      function parseCity(str) {
        const i = str.indexOf(' (');
        return i > 0 ? str.slice(0, i).trim() : str;
      }
      function buildICS(st, en, loc) {
        const f = d => {
          const y = d.getUTCFullYear(),
                mo = String(d.getUTCMonth() + 1).padStart(2, '0'),
                da = String(d.getUTCDate()).padStart(2, '0'),
                hh = String(d.getUTCHours()).padStart(2, '0'),
                mm = String(d.getUTCMinutes()).padStart(2, '0'),
                ss = String(d.getUTCSeconds()).padStart(2, '0');
          return `${y}${mo}${da}T${hh}${mm}${ss}Z`;
        };
        const s = f(st), e = f(en), ds = f(new Date());
        return `BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//BrutalistTZ//EN
BEGIN:VEVENT
UID:${Date.now()}
DTSTAMP:${ds}
DTSTART:${s}
DTEND:${e}
SUMMARY:My Event
LOCATION:${loc}
END:VEVENT
END:VCALENDAR`;
      }
      function downloadFile(content, name, type) {
        const b = new Blob([content], { type }),
              u = URL.createObjectURL(b);
        const a = document.createElement('a');
        a.href = u; a.download = name;
        document.body.appendChild(a);
        a.click();
        a.remove();
        URL.revokeObjectURL(u);
      }
      function fmtGCal(d) {
        const y = d.getUTCFullYear(),
              mo = String(d.getUTCMonth() + 1).padStart(2, '0'),
              da = String(d.getUTCDate()).padStart(2, '0'),
              hh = String(d.getUTCHours()).padStart(2, '0'),
              mm = String(d.getUTCMinutes()).padStart(2, '0'),
              ss = String(d.getUTCSeconds()).padStart(2, '0');
        return `${y}${mo}${da}T${hh}${mm}${ss}Z`;
      }
    });
  </script>
</body>
</html>
                               

Whois info of domain

Domain Name: ON4.COM
Registry Domain ID: 1362326_DOMAIN_COM-VRSN
Registrar WHOIS Server: whois.paimi.com
Registrar URL: http://register.paimi.com
Updated Date: 2025-05-03T13:04:54Z
Creation Date: 1998-06-03T04:00:00Z
Registry Expiry Date: 2026-06-02T04:00:00Z
Registrar: Zhuimi Inc
Registrar IANA ID: 776
Registrar Abuse Contact Email: [email protected]
Registrar Abuse Contact Phone: 7703370040
Domain Status: ok https://icann.org/epp#ok
Name Server: DELL.NS.CLOUDFLARE.COM
Name Server: RAZVAN.NS.CLOUDFLARE.COM
DNSSEC: unsigned
URL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/
>>> Last update of whois database: 2025-05-05T18:34:00Z <<<
For more information on Whois status codes, please visit https://icann.org/epp
NOTICE: The expiration date displayed in this record is the date the
TERMS OF USE: You are not authorized to access or query our Whois
by the following terms of use: You agree that you may use this Data only
to: (1) allow, enable, or otherwise support the transmission of mass