| 1 | <!doctype html> |
| 2 | <html lang="en"> |
| 3 | <head> |
| 4 | <meta charset="utf-8"> |
| 5 | <meta name="viewport" content="width=device-width, initial-scale=1"> |
| 6 | <title>Countdown to Cloudflare Connect 2026, San Francisco</title> |
| 7 | <meta name="description" content="Countdown to Cloudflare Connect 2026, San Francisco: October 19–21, 2026 at Moscone West."> |
| 8 | <style> |
| 9 | :root { |
| 10 | --bg: #0b0d12; |
| 11 | --card: #161a23; |
| 12 | --text: #f5f6f8; |
| 13 | --muted: #a3a9b6; |
| 14 | --accent: #f6821f; |
| 15 | } |
| 16 | * { box-sizing: border-box; } |
| 17 | html, body { margin: 0; height: 100%; } |
| 18 | body { |
| 19 | font-family: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; |
| 20 | background: radial-gradient(circle at 50% 0%, #2a1a0c 0%, var(--bg) 60%); |
| 21 | color: var(--text); |
| 22 | display: flex; |
| 23 | align-items: center; |
| 24 | justify-content: center; |
| 25 | padding: 1.5rem; |
| 26 | text-align: center; |
| 27 | } |
| 28 | main { width: 100%; max-width: 46rem; } |
| 29 | .eyebrow { |
| 30 | color: var(--accent); |
| 31 | font-weight: 600; |
| 32 | letter-spacing: .12em; |
| 33 | text-transform: uppercase; |
| 34 | font-size: .8rem; |
| 35 | margin: 0 0 .75rem; |
| 36 | } |
| 37 | h1 { |
| 38 | font-size: clamp(1.6rem, 6vw, 3rem); |
| 39 | line-height: 1.15; |
| 40 | margin: 0 0 .75rem; |
| 41 | } |
| 42 | .where { color: var(--muted); margin: 0 0 2rem; font-size: clamp(.95rem, 3vw, 1.1rem); } |
| 43 | .timer { |
| 44 | display: grid; |
| 45 | grid-template-columns: repeat(4, 1fr); |
| 46 | gap: clamp(.5rem, 2vw, 1rem); |
| 47 | margin: 0 0 2rem; |
| 48 | } |
| 49 | .unit { |
| 50 | background: var(--card); |
| 51 | border: 1px solid #262b37; |
| 52 | border-radius: 14px; |
| 53 | padding: clamp(.75rem, 3vw, 1.5rem) .25rem; |
| 54 | } |
| 55 | .num { |
| 56 | display: block; |
| 57 | font-size: clamp(1.8rem, 9vw, 3.75rem); |
| 58 | font-weight: 700; |
| 59 | font-variant-numeric: tabular-nums; |
| 60 | line-height: 1; |
| 61 | } |
| 62 | .label { |
| 63 | display: block; |
| 64 | margin-top: .5rem; |
| 65 | color: var(--muted); |
| 66 | font-size: clamp(.65rem, 2.5vw, .85rem); |
| 67 | text-transform: uppercase; |
| 68 | letter-spacing: .08em; |
| 69 | } |
| 70 | .started { |
| 71 | font-size: clamp(1.4rem, 5vw, 2.25rem); |
| 72 | font-weight: 700; |
| 73 | color: var(--accent); |
| 74 | margin: 0 0 2rem; |
| 75 | } |
| 76 | .target { color: var(--muted); font-size: .95rem; margin: 0; } |
| 77 | .target strong { color: var(--text); font-weight: 600; } |
| 78 | [hidden] { display: none !important; } |
| 79 | </style> |
| 80 | </head> |
| 81 | <body> |
| 82 | <main> |
| 83 | <p class="eyebrow">Countdown</p> |
| 84 | <h1>Cloudflare Connect 2026, San Francisco</h1> |
| 85 | <p class="where">October 19–21, 2026 · Moscone West, San Francisco</p> |
| 86 | |
| 87 | <div class="timer" id="timer" aria-live="polite"> |
| 88 | <div class="unit"><span class="num" id="days">--</span><span class="label">Days</span></div> |
| 89 | <div class="unit"><span class="num" id="hours">--</span><span class="label">Hours</span></div> |
| 90 | <div class="unit"><span class="num" id="minutes">--</span><span class="label">Minutes</span></div> |
| 91 | <div class="unit"><span class="num" id="seconds">--</span><span class="label">Seconds</span></div> |
| 92 | </div> |
| 93 | |
| 94 | <p class="started" id="started" hidden>Cloudflare Connect 2026 has started. See you at Moscone West!</p> |
| 95 | |
| 96 | <p class="target">Counting down to <strong>Monday, October 19, 2026, 12:00 AM PDT</strong> (San Francisco time).</p> |
| 97 | </main> |
| 98 | |
| 99 | <script> |
| 100 | // Event start: midnight Pacific Daylight Time (UTC-7) on October 19, 2026. |
| 101 | var EVENT_START = new Date("2026-10-19T00:00:00-07:00").getTime(); |
| 102 | |
| 103 | var els = { |
| 104 | timer: document.getElementById("timer"), |
| 105 | started: document.getElementById("started"), |
| 106 | days: document.getElementById("days"), |
| 107 | hours: document.getElementById("hours"), |
| 108 | minutes: document.getElementById("minutes"), |
| 109 | seconds: document.getElementById("seconds") |
| 110 | }; |
| 111 | |
| 112 | function pad(n) { return n < 10 ? "0" + n : String(n); } |
| 113 | |
| 114 | var handle; |
| 115 | function tick() { |
| 116 | var remaining = EVENT_START - Date.now(); |
| 117 | if (remaining <= 0) { |
| 118 | els.timer.hidden = true; |
| 119 | els.started.hidden = false; |
| 120 | if (handle) clearInterval(handle); |
| 121 | return; |
| 122 | } |
| 123 | var s = Math.floor(remaining / 1000); |
| 124 | els.days.textContent = Math.floor(s / 86400); |
| 125 | els.hours.textContent = pad(Math.floor(s % 86400 / 3600)); |
| 126 | els.minutes.textContent = pad(Math.floor(s % 3600 / 60)); |
| 127 | els.seconds.textContent = pad(s % 60); |
| 128 | } |
| 129 | |
| 130 | tick(); |
| 131 | handle = setInterval(tick, 1000); |
| 132 | </script> |
| 133 | </body> |
| 134 | </html> |