1<!DOCTYPE html> 2<html lang="en"> 3<head> 4<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%230D0D12'/%3E%3Cpath d='M16 4l3.09 6.26L26 11.27l-5 4.87L22.18 23 16 19.77 9.82 23 11 16.14 6 11.27l6.91-1.01L16 4z' fill='%2321CF7E'/%3E%3C/svg%3E"> 5<!-- Google Consent Mode default â runs first; CookieYes loads last per GCM docs -->
5<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==">window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('consent','default',{ad_storage:'denied',ad_user_data:'denied',ad_personalization:'denied',analytics_storage:'denied',functionality_storage:'granted',security_storage:'granted',wait_for_update:500});</script>
5 6<!-- Google tag (gtag.js) -->
vendor: 97 bytes, lines 6-7
6 7<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==" async src="https://www.googletagmanager.com/gtag/js?id=
7G-9XK9DCMS5N
vendor: 12 bytes, line 7
7"></script>
8<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==">
vendor: 118 bytes, line 8
8window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('js',new Date());gtag('config','
8G-9XK9DCMS5N
vendor: 3 bytes, line 8
8');
8</script>
8<!-- Start cookieyes banner -->
8<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==" id="cookieyes" type="text/javascript" src="https://cdn-cookieyes.com/client_data/7603e8a4c81a65b5baf2b18efc2a925b/script.js"></script>
8<!-- End cookieyes banner --> 9 10<meta charset="UTF-8"> 11<meta name="viewport" content="width=device-width, initial-scale=1.0"> 12<title>IndieHQ â Everything indie agencies need. One front door.</title> 13<!-- Indie HQ homepage · Homepage 26.0706.5 · see CHANGELOG.md --> 14<meta name="version" content="26.0708.3"> 15<meta name="description" content="IndieHQ is the home for everything Indie Agency News has built for independent agencies â events, shows, tools, community, and coaching, all in one place."> 16<style> 17 :root { 18 --ink: #0D0D12; /* near-black */ 19 --paper: #FAFAF8; /* warm off-white */ 20 --accent: #21CF7E; /* IAN electric green â the Indie@Cannes colorway */ 21 --accent-deep: #0C9B53; /* green that reads on light backgrounds */ 22 --grey: #56565E; 23 --line: #0D0D12; /* borders are ink â hard, editorial */ 24 --tint: #E9FAF0; /* light green hover tint */ 25 } 26 * { margin: 0; padding: 0; box-sizing: border-box; } 27 /* No orphans: balance headings, prettify body */ 28 h1, h2, h3, h4 { text-wrap: balance; } 29 p, li, blockquote, figcaption { text-wrap: pretty; } 30 html { scroll-behavior: smooth; } 31 body { 32 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, sans-serif; 33 background: var(--paper); 34 color: var(--ink); 35 line-height: 1.5; 36 -webkit-font-smoothing: antialiased; 37 } 38 a { color: inherit; text-decoration: none; } 39 .wrap { max-width: 1200px; margin: 0 auto; padding: 0 28px; } 40 41 /* ---------- Type ---------- */ 42 h1, h2, h3 { font-weight: 800; letter-spacing: -0.03em; line-height: 1.05; } 43 .kicker { 44 display: inline-block; 45 font-size: .78rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; 46 color: var(--accent-deep); margin-bottom: 16px; 47 } 48 .dark .kicker { color: var(--accent); } 49 50 /* ---------- Buttons ---------- */ 51 .btn { 52 display: inline-block; padding: 14px 28px; 53 font-weight: 700; font-size: .95rem; cursor: pointer; 54 border: 2px solid var(--ink); border-radius: 4px; 55 background: transparent; color: var(--ink); 56 transition: background .15s ease, color .15s ease, border-color .15s ease; 57 } 58 .btn:hover { background: var(--ink); color: var(--paper); } 59 .btn-solid { background: var(--ink); color: var(--paper); } 60 .btn-solid:hover { background: var(--accent); border-color: var(--accent); color: var(--ink); } 61 .btn-accent { background: var(--accent); border-color: var(--accent); color: var(--ink); } 62 .btn-accent:hover { background: var(--ink); border-color: var(--ink); color: var(--accent); } 63 .dark .btn { border-color: var(--paper); color: var(--paper); } 64 .dark .btn:hover { background: var(--paper); color: var(--ink); } 65 66 /* ---------- Header ---------- */ 67 header { 68 position: sticky; top: 0; z-index: 50; 69 background: var(--paper); 70 border-bottom: 2px solid var(--ink); 71 } 72 .header-inner { display: flex; align-items: center; gap: 36px; height: 72px; } 73 .wordmark { font-weight: 800; font-size: 1.3rem; letter-spacing: -.02em; white-space: nowrap; } 74 .wordmark .hq { color: var(--accent-deep); } 75 nav.main { display: flex; gap: 26px; font-size: .95rem; font-weight: 600; } 76 nav.main a { padding: 4px 0; border-bottom: 2px solid transparent; } 77 nav.main a:hover { border-bottom-color: var(--accent); } 78 .header-cta { margin-left: auto; display: flex; align-items: center; gap: 12px; } 79 .header-cta .btn { padding: 10px 20px; font-size: .88rem; } 80 .login-link { font-weight: 700; font-size: .92rem; margin-right: 4px; } 81 .login-link:hover { color: var(--accent-deep); } 82 /* mobile nav (hamburger) */ 83 .nav-toggle { display: none; background: none; border: 0; cursor: pointer; padding: 8px; margin-left: auto; } 84 .nav-toggle span { display: block; width: 24px; height: 2.5px; background: var(--ink); border-radius: 2px; margin: 5px 0; transition: .2s; } 85 .mob-only { display: none !important; } 86 @media (max-width: 960px) { 87 .nav-toggle { display: block; } 88 .header-cta { display: none; } 89 .header-inner { position: relative; gap: 16px; } 90 nav.main { display: none; position: absolute; top: 100%; left: 0; right: 0; background: var(--paper); border-bottom: 2px solid var(--ink); box-shadow: 0 14px 26px rgba(13,13,18,.10); flex-direction: column; gap: 0; padding: 6px 0; } 91 nav.main.open { display: flex; } 92 nav.main a { padding: 15px 22px; border-bottom: 1px solid rgba(13,13,18,.08); font-size: 1.05rem; } 93 nav.main a:last-child { border-bottom: 0; } 94 .mob-only { display: block !important; } 95 } 96 97 /* ---------- Hero (black, statement) ---------- */ 98 .hero { 99 background: var(--ink); color: var(--paper); 100 padding: 110px 0 100px; 101 } 102 .hero h1 { 103 font-size: clamp(2.8rem, 7vw, 5.2rem); 104 max-width: 15ch; 105 } 106 .hero h1 .accent { color: var(--accent); } 107 .hero .flag { width: 64px; height: 12px; background: var(--accent); margin-bottom: 36px; } 108 .hero p { margin-top: 28px; font-size: 1.2rem; max-width: 560px; color: #C9C9CF; } 109 .hero-cta { margin-top: 40px; display: flex; gap: 14px; flex-wrap: wrap; } 110 111 /* ---------- Sections ---------- */ 112 section { padding: 88px 0; } 113 .section-head { margin-bottom: 44px; max-width: 720px; } 114 .section-head h2 { font-size: clamp(1.9rem, 4vw, 2.9rem); } 115 .section-head p { margin-top: 14px; font-size: 1.08rem; color: var(--grey); } 116 .dark .section-head p { color: #C9C9CF; } 117 .see-all { 118 display: inline-block; margin-top: 18px; 119 font-weight: 700; border-bottom: 2px solid var(--accent); 120 padding-bottom: 2px; 121 } 122 .see-all:hover { color: var(--accent-deep); } 123 .dark .see-all:hover { color: var(--accent); } 124 125 /* ---------- Card grids (hard-edged, bordered) ---------- */ 126 .grid { display: grid; gap: 0; border: 2px solid var(--line); } 127 .grid-3 { grid-template-columns: repeat(3, 1fr); } 128 .grid-2 { grid-template-columns: repeat(2, 1fr); }
129 .grid-2 .cell:last-child { border-right: none; } 130 /* Events â horizontal rail: shows every upcoming event, swipe for more (nothing hidden in a 3-cap) */ 131 .evrail { display: flex; overflow-x: auto; border: 2px solid var(--line); 132 scroll-snap-type: x proximity; scrollbar-width: thin; scrollbar-color: var(--line) transparent; } 133 .evrail::-webkit-scrollbar { height: 8px; } 134 .evrail::-webkit-scrollbar-thumb { background: var(--line); } 135 .evrail::-webkit-scrollbar-track { background: transparent; } 136 .evrail .cell { flex: 0 0 300px; scroll-snap-align: start; } 137 @media (max-width: 600px) { .evrail .cell { flex: 0 0 82%; } } 138 .evfoot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 14px; } 139 .evfoot .see-all { margin: 0; } 140 .evnav { display: flex; gap: 8px; } 141 .evbtn { width: 42px; height: 42px; border: 2px solid var(--line); background: #fff; color: var(--ink); 142 font-size: 22px; line-height: 1; cursor: pointer; display: grid; place-items: center; 143 transition: background .12s, border-color .12s, opacity .12s; } 144 .evbtn:hover:not(:disabled) { background: var(--ink); color: var(--paper); border-color: var(--ink); } 145 .evbtn:disabled { opacity: .28; cursor: default; } 146 .cell .evby { font-size: .78rem; color: var(--grey); margin-top: 8px; letter-spacing: .01em; } 147 .cell .evby b { color: var(--ink); font-weight: 700; } 148 .cell-feature { display: block; padding: 34px 32px; border: 2px solid var(--line); border-top: none; cursor: pointer; transition: background .15s; } 149 .cell-feature .badge { position: static; } 150 .cell-feature h3 { font-size: 1.7rem; margin: 14px 0 10px; } 151 .cell-feature p { max-width: 620px; font-size: 1rem; } 152 .cell-feature .go { margin-top: 20px; display: inline-block; font-weight: 700; } 153 .feature-tag { font-size: .72rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--accent-deep); margin-left: 12px; } 154 .cell-feature:hover .go { color: var(--accent-deep); } 155 .cell { 156 padding: 32px 28px; border-right: 2px solid var(--line); 157 display: flex; flex-direction: column; position: relative; 158 background: var(--paper); 159 transition: background .15s ease; 160 } 161 .cell:last-child { border-right: none; } 162 .cell:hover { background: var(--tint); } 163 .cell h3 { font-size: 1.3rem; margin-bottom: 10px; } 164 .cell p { font-size: .95rem; color: var(--grey); flex: 1; } 165 .cell .go { margin-top: 22px; font-weight: 700; font-size: .92rem; } 166 .cell:hover .go { color: var(--accent-deep); } 167 .badge { 168 position: absolute; top: 0; right: 0; 169 font-size: .68rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; 170 padding: 6px 12px; background: var(--accent); color: var(--ink); 171 } 172 .event-date { font-weight: 800; font-size: .85rem; letter-spacing: .06em; text-transform: uppercase; color: var(--accent-deep); margin-bottom: 14px; } 173 /* ---- Summit feature (page-width, highlighted) ---- */ 174 .summit-feature { display:grid; grid-template-columns:1.4fr 1fr; gap:34px; align-items:center; 175 background:var(--ink); color:var(--paper); border:2px solid var(--ink); border-radius:6px; 176 padding:36px 40px; margin-bottom:26px; position:relative; overflow:hidden; } 177 .summit-feature::before { content:""; position:absolute; top:-40%; right:-8%; width:52%; height:180%; 178 background:radial-gradient(circle, rgba(33,222,115,.16) 0%, transparent 62%); pointer-events:none; } 179 .summit-feature > * { position:relative; z-index:1; } 180 .summit-kick { font-size:.72rem; font-weight:800; letter-spacing:.14em; text-transform:uppercase; color:var(--accent); margin-bottom:12px; } 181 .summit-feature h3 { font-size:clamp(1.7rem,3vw,2.5rem); line-height:1.0; letter-spacing:-.02em; } 182 .summit-where { margin-top:12px; font-size:1rem; color:#C9C9CF; } 183 .summit-where strong { color:var(--paper); } 184 .summit-tier { margin-top:16px; font-size:.95rem; color:#C9C9CF; } 185 .summit-tier b { color:var(--accent); font-weight:800; } 186 .summit-seats { margin-top:18px; max-width:420px; } 187 .summit-bar { height:9px; background:rgba(255,255,255,.15); border-radius:99px; overflow:hidden; margin-bottom:9px; } 188 .summit-bar > i { display:block; height:100%; background:var(--accent); border-radius:99px; } 189 .summit-seats .lab { font-size:.82rem; font-weight:700; color:#9A9AA4; } 190 .summit-seats .lab b { color:var(--paper); } 191 .summit-right { text-align:center; } 192 .countdown { display:flex; gap:9px; justify-content:center; margin-bottom:20px; } 193 .cd-box { background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.16); border-radius:8px; padding:12px 0; min-width:64px; flex:0 1 64px; } 194 .cd-box .n { font-size:1.9rem; font-weight:800; letter-spacing:-.03em; line-height:1; font-variant-numeric:tabular-nums; } 195 .cd-box .l { font-size:.6rem; font-weight:800; text-transform:uppercase; letter-spacing:.08em; color:#8C8C95; margin-top:6px; } 196 .summit-cta { display:inline-block; background:var(--accent); color:var(--ink); font-weight:800; padding:15px 28px; border-radius:4px; font-size:1rem; transition:background .15s; }
197 .summit-feature:hover .summit-cta { background:var(--paper); } 198 .summit-sub { display:block; margin-top:10px; font-size:.7rem; letter-spacing:.06em; text-transform:uppercase; color:#8C8C95; } 199 @media (max-width:760px){ .summit-feature { grid-template-columns:1fr; padding:28px 22px; gap:24px; } .summit-right { text-align:left; } .countdown { justify-content:flex-start; } .cd-box { flex:1 1 0; } } 200 .cell-img { height: 158px; background: #101018 center/cover no-repeat; margin: -32px -28px 22px; border-bottom: 2px solid var(--line); } 201 202 /* ---------- Live Tracker (prominent black band) ---------- */ 203 #tracker { 204 background: var(--ink); color: var(--paper); 205 border-top: 2px solid var(--ink); border-bottom: 2px solid var(--ink); 206 padding: 80px 0; 207 overflow: hidden; 208 } 209 .live-pill { 210 display: inline-flex; align-items: center; gap: 8px; 211 font-size: .75rem; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; 212 color: var(--ink); background: var(--accent); 213 padding: 6px 14px; margin-bottom: 18px; 214 } 215 .live-dot { 216 width: 8px; height: 8px; border-radius: 50%; background: var(--ink); 217 animation: blink 1.4s ease-in-out infinite; 218 } 219 @keyframes blink { 0%,100% { opacity: 1; } 50% { opacity: .25; } } 220 #tracker h2 { font-size: clamp(2rem, 4.5vw, 3.2rem); max-width: 18ch; } 221 #tracker .tracker-sub { margin-top: 14px; font-size: 1.1rem; color: #C9C9CF; max-width: 560px; } 222 .tracker-panel { margin-top: 30px; border: 2px solid var(--paper); border-radius: 10px; overflow: hidden; background: #fff; box-shadow: 0 24px 70px rgba(0,0,0,.38); } 223 .tracker-credit { margin-top: 16px; font-size: .82rem; letter-spacing: .02em; color: #8E8E98; font-weight: 600; } 224 .tracker-credit a { color: var(--accent); text-decoration: none; border-bottom: 1px solid rgba(33,222,115,.45); padding-bottom: 1px; } 225 .tracker-credit a:hover { color: #fff; border-bottom-color: #fff; } 226 .pixel-strip { display: flex; gap: 6px; margin: 40px 0 34px; } 227 .pixel-col { display: flex; flex-direction: column; gap: 6px; flex: 1; } 228 .px { 229 width: 100%; aspect-ratio: 1; background: var(--accent); 230 opacity: .15; 231 } 232 .px.on { opacity: 1; } 233 .ticker-window { border-top: 2px solid var(--paper); border-bottom: 2px solid var(--paper); padding: 18px 0; } 234 .ticker-track { 235 display: flex; gap: 64px; white-space: nowrap; width: max-content; 236 animation: ticker 40s linear infinite; 237 } 238 .ticker-window:hover .ticker-track { animation-play-state: paused; } 239 @keyframes ticker { from { transform: translateX(0); } to { transform: translateX(-50%); } } 240 .tick { font-weight: 700; font-size: 1.02rem; } 241 .tick .t-tag { color: var(--accent); font-size: .72rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; margin-right: 12px; } 242 #tracker .hero-cta { margin-top: 36px; } 243 244 /* ---------- News (editorial list) ---------- */ 245 #news { background: #F1F1EC; border-bottom: 2px solid var(--ink); } 246 #meet { background: var(--paper); border-bottom: 2px solid var(--ink); } 247 .news-list { border-top: 2px solid var(--ink); } 248 .news-item { 249 display: flex; gap: 28px; align-items: baseline; 250 padding: 26px 4px; border-bottom: 2px solid var(--ink); 251 transition: background .15s ease; 252 } 253 .news-item:hover { background: var(--tint); } 254 .news-item .tag { 255 flex: 0 0 130px; font-size: .72rem; font-weight: 800; 256 letter-spacing: .1em; text-transform: uppercase; color: var(--accent-deep); 257 } 258 .news-item h3 { font-size: clamp(1.05rem, 2.2vw, 1.45rem); font-weight: 700; letter-spacing: -.01em; } 259 .news-item .arrow { margin-left: auto; font-weight: 800; opacity: 0; transition: opacity .15s ease; } 260 .news-item:hover .arrow { opacity: 1; } 261 262 /* ---------- Member HQ (black band) ---------- */ 263 #members { background: var(--ink); color: var(--paper); } 264 #members .grid { border-color: var(--paper); } 265 #members .cell { background: var(--ink); border-color: var(--paper); } 266 #members .cell:hover { background: #14241A; } 267 #members .cell p { color: #C9C9CF; } 268 #members .cell-feature { background: #0F1A13; border-color: var(--paper); } 269 #members .cell-feature:hover { background: #14241A; } 270 #members .cell-feature p { color: #C9C9CF; } 271 #members .feature-tag { color: var(--accent); } 272 #members .mh-group { display:flex; align-items:center; gap:10px; margin:34px 0 14px; } 273 #members .mh-group:first-of-type { margin-top:26px; } 274 #members .mh-group .bar { width:4px; height:16px; background:var(--accent); flex:0 0 auto; } 275 #members .mh-group h3 { font-size:.82rem; font-weight:800; letter-spacing:.12em; text-transform:uppercase; color:var(--accent); margin:0; } 276 277 /* ---------- Front Desk (premium) ---------- */ 278 #front-desk .desk { 279 border: 2px solid var(--ink); padding: 56px 48px; 280 display: grid; grid-template-columns: 1fr 1fr; gap: 48px; align-items: center; 281 position: relative; 282 } 283 #front-desk h2 { font-size: clamp(1.9rem, 4vw, 2.9rem); } 284 #front-desk .desk-copy p { margin-top: 14px; font-size: 1.05rem; color: var(--grey); } 285 .desk-form { display: flex; flex-direction: column; gap: 12px; } 286 .desk-form input { 287 padding: 16px 18px; font-size: 1rem; font-family: inherit; 288 border: 2px solid var(--ink); border-radius: 4px; background: #fff; outline: none; 289 } 290 .desk-form input:focus { border-color: var(--accent-deep); } 291 .desk-note { font-size: .85rem; color: var(--grey); } 292 /* ---------- Feature bands (Partners / Commons) ---------- */ 293 .band { border: 2px solid var(--ink); padding: 48px 44px; display: grid; grid-template-columns: 1.6fr 1fr; gap: 40px; align-items: center; } 294 .band .kicker { margin-bottom: 12px; } 295 .band h2 { font-size: clamp(1.8rem, 4vw, 2.7rem); } 296 .band p { margin-top: 14px; font-size: 1.05rem; color: var(--grey); max-width: 640px; } 297 .band-cta { text-align: right; } 298 .partners-feature { background: var(--tint); } 299 #sister-cities { padding-top: 0; } 300 #sister-cities .band { background: var(--tint); border-top: 8px solid var(--accent); } 301 .band p.sc-runs { margin-top: 18px; font-size: .92rem; color: var(--ink); } 302 .sc-runs b { font-weight: 800; } 303 .sc-runs span, #sister-cities .nw { white-space: nowrap; } 304 .pchips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 20px; } 305 .pchips span { font-size: .8rem; font-weight: 700; border: 1.5px solid var(--ink); border-radius: 99px; padding: 6px 13px; background: #fff; } 306 @media (max-width: 760px) { .band { grid-template-columns: 1fr; gap: 24px; padding: 32px 26px; } .band-cta { text-align: left; } } 307 308 /* ---------- Footer (black) ---------- */ 309 footer { 310 background: var(--ink); color: var(--paper); 311 padding: 64px 0 72px; font-size: .92rem; 312 } 313 .footer-grid { display: flex; justify-content: space-between; gap: 40px; flex-wrap: wrap; } 314 .footer-brand { max-width: 320px; } 315 .footer-brand .wordmark { font-size: 1.4rem; } 316 .footer-brand .wordmark .hq { color: var(--accent); } 317 .footer-brand p { margin-top: 12px; color: #9A9AA4; } 318 .footer-links { display: flex; gap: 56px; flex-wrap: wrap; } 319 .footer-links h4 { font-size: .75rem; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; color: #9A9AA4; margin-bottom: 14px; } 320 .footer-links ul { list-style: none; display: flex; flex-direction: column; gap: 9px; } 321 .footer-links a:hover { color: var(--accent); } 322 .footer-legal { margin-top: 48px; padding-top: 24px; border-top: 1px solid #2A2A33; color: #9A9AA4; font-size: .82rem; } 323 324 /* ---------- Responsive ---------- */ 325 @media (max-width: 960px) { 326 .grid-3 { grid-template-columns: repeat(2, 1fr); }
327 .grid-3 .cell:nth-child(2n) { border-right: none; } 328 .grid-3 .cell:nth-child(-n+2) { border-bottom: 2px solid var(--line); } 329 #front-desk .desk { grid-template-columns: 1fr; padding: 36px 28px; } 330 .pixel-strip .pixel-col:nth-child(n+25) { display: none; } 331 } 332 @media (max-width: 600px) { 333 .grid-3 { grid-template-columns: 1fr; } 334 .grid-2 { grid-template-columns: 1fr; } 335 .cell { border-right: none !important; border-bottom: 2px solid var(--line); } 336 .grid .cell:last-child { border-bottom: none; } 337 .hero { padding: 72px 0 64px; } 338 .news-item { flex-direction: column; gap: 6px; } 339 .news-item .tag { flex: none; } 340 .pixel-strip .pixel-col:nth-child(n+15) { display: none; } 341 } 342{RULE} 343 /* mobile-stack guard */ 344 @media (max-width:600px){ .grid,.grid-2,.grid-3,.grid-4,.three,.cards,.stats,.nums,.board,.tiles,.topics,.solo{ grid-template-columns:1fr !important; } } 345 346 /* ---- Tighter, app-like spacing: tablet + mobile ---- */ 347 .scoreboard-feature { background: var(--tint); } 348 @media (max-width: 1024px){ section{ padding:60px 0; } #tracker{ padding:60px 0; } .section-head{ margin-bottom:32px; } .hero{ padding:88px 0 68px; } } 349 @media (max-width: 700px){ .wrap{ padding:0 20px; } section{ padding:42px 0; } #tracker{ padding:42px 0; } .section-head{ margin-bottom:20px; } .hero{ padding:60px 0 48px; } .hero p{ font-size:1.06rem; margin-top:18px; } .hero-cta{ margin-top:26px; } .band{ padding:26px 22px; } } 350 @media(max-width:600px){ .wordmark img, .ihq-logo{ height:40px !important; } } 351 /* QuickCoach two-column block stacks on phones */ 352 @media (max-width: 760px){ .qc-split{ grid-template-columns:1fr !important; gap:26px !important; } } 353 /* clearance for the fixed Holdco Watch ticker */ 354 body{ padding-bottom:80px; } 355 356 /* ===== Member-first landing: when signed in, lead with what you can do ===== */ 357 .member-hero{ display:none; } 358 html.ihq-member .hero{ display:none; } /* hide the prospect pitch for members */ 359 html.ihq-member .member-hero{ display:block; background:var(--ink,#0D0D12); color:#fff; padding:64px 0 56px; } 360 .member-hero .wrap{ max-width:1100px; margin:0 auto; padding:0 32px; } 361 .member-hero .mh-kicker{ font-size:.78rem; font-weight:800; letter-spacing:.16em; text-transform:uppercase; color:var(--accent,#21DE73); margin-bottom:12px; } 362 .member-hero h1{ font-size:clamp(2rem,4vw,3rem); line-height:1.03; letter-spacing:-.03em; margin:0; text-wrap:balance; } 363 .member-hero h1 .accent{ color:var(--accent,#21DE73); } 364 .member-hero .mh-sub{ color:#C8C8D0; font-size:1.1rem; margin:14px 0 26px; max-width:640px; text-wrap:pretty; } 365 .member-hero .mh-chips{ display:flex; flex-wrap:wrap; gap:10px; } 366 .member-hero .mh-chips a{ display:inline-flex; align-items:center; gap:7px; background:transparent; color:#fff; border:1.5px solid rgba(255,255,255,.32); border-radius:999px; padding:9px 16px; font-size:.95rem; font-weight:700; text-decoration:none; transition:background .12s ease,color .12s ease,border-color .12s ease; } 367 .member-hero .mh-chips a:hover{ background:var(--accent,#21DE73); color:var(--ink,#0D0D12); border-color:var(--accent,#21DE73); } 368 .member-hero .mh-chips a.primary{ background:var(--accent,#21DE73); color:var(--ink,#0D0D12); border-color:var(--accent,#21DE73); } 369 .member-hero .mh-chips a.primary:hover{ filter:brightness(1.05); } 370 html.ihq-member #members{ border-top:none; } 371 .member-hero .mh-news{ margin-top:30px; border-top:1px solid rgba(255,255,255,.18); padding-top:22px; } 372 .member-hero .mh-news-h{ font-size:.72rem; font-weight:800; letter-spacing:.14em; text-transform:uppercase; color:#9A9AA2; margin-bottom:14px; } 373 .member-hero .mh-news-list{ display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:12px; } 374 .member-hero .mh-news-item{ display:block; text-decoration:none; color:#fff; border:1px solid rgba(255,255,255,.16); border-radius:8px; padding:13px 15px; transition:border-color .12s ease,background .12s ease; } 375 .member-hero .mh-news-item:hover{ border-color:var(--accent,#21DE73); background:rgba(255,255,255,.05); } 376 .member-hero .mh-news-item .nt{ display:inline-block; font-size:.62rem; font-weight:800; letter-spacing:.1em; text-transform:uppercase; color:var(--accent,#21DE73); margin-bottom:6px; } 377 .member-hero .mh-news-item h4{ font-size:.98rem; font-weight:700; line-height:1.25; margin:0; letter-spacing:-.01em; text-wrap:pretty; } 378 /* Indie Stages spotlight â the big Member HQ feature */ 379 .stage-spotlight{ display:flex; gap:28px; flex-wrap:wrap; align-items:center; justify-content:space-between; background:#FAFAF8; color:#0D0D12; border:2px solid #21CF7E; border-radius:16px; padding:30px 32px; margin-bottom:22px; text-decoration:none;
379 transition:box-shadow .15s ease; } 380 .stage-spotlight:hover{ box-shadow:0 0 0 4px rgba(33,207,126,.28); } 381 .stage-spotlight .ss-left{ flex:1; min-width:280px; } 382 .stage-spotlight .ss-tag{ font-size:.7rem; font-weight:800; letter-spacing:.12em; text-transform:uppercase; color:#0C9B53; } 383 .stage-spotlight h3{ font-size:1.9rem; margin:10px 0 10px; letter-spacing:-.02em; line-height:1.05; } 384 .stage-spotlight p{ color:#333; margin:0 0 18px; max-width:54ch; font-size:1rem; } 385 .stage-spotlight .ss-cta{ display:inline-block; background:#0D0D12; color:#fff; font-weight:800; padding:12px 24px; border-radius:9px; font-size:.98rem; } 386 .stage-spotlight:hover .ss-cta{ background:#21CF7E; color:#0D0D12; } 387 .stage-spotlight .ss-right{ display:flex; flex-wrap:wrap; gap:8px; max-width:300px; } 388 .stage-spotlight .ss-chip{ border:1.5px solid #0D0D12; border-radius:20px; padding:6px 13px; font-size:.8rem; font-weight:700; } 389 @media(max-width:640px){ .stage-spotlight h3{ font-size:1.5rem; } .stage-spotlight .ss-right{ max-width:none; } } 390 @media(max-width:700px){ html.ihq-member .member-hero{ padding:40px 0 34px; } .member-hero .wrap{ padding:0 20px; } .member-hero .mh-sub{ font-size:1rem; } } 391</style> 392<!-- SEO --> 393<link rel="canonical" href="https://indiehq.com/"> 394<meta property="og:type" content="website"> 395<meta property="og:site_name" content="IndieHQ"> 396<meta property="og:title" content="IndieHQ â Everything indie agencies need. One front door."> 397<meta property="og:description" content="IndieHQ is the home for everything Indie Agency News has built for independent agencies â events, shows, tools, community, and coaching, all in one place."> 398<meta property="og:url" content="https://indiehq.com/"> 399<meta property="og:image" content="https://media.indiehq.com/IndieHQ%20Logos/indiehq_1200x630_vmheum.png"> 400<meta property="og:image:width" content="1200"> 401<meta property="og:image:height" content="630"> 402<meta name="twitter:card" content="summary_large_image"> 403<meta name="twitter:title" content="IndieHQ â Everything indie agencies need. One front door."> 404<meta name="twitter:description" content="IndieHQ is the home for everything Indie Agency News has built for independent agencies â events, shows, tools, community, and coaching, all in one place."> 405<meta name="twitter:image" content="https://media.indiehq.com/IndieHQ%20Logos/indiehq_1200x630_vmheum.png">
406<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==" type="application/ld+json">{"@context":"https://schema.org","@type":"Organization","name":"IndieHQ","legalName":"Indie Agency News","url":"https://indiehq.com","logo":"https://media.indiehq.com/IndieHQ%20Logos/PNG/Color/IHQ__Color_WhiteBackground_Horizontal_xsbzda.png?height=240","description":"IndieHQ is the home for the independent agency community â coaching, awards, community, research, and live events â from Indie Agency News.","sameAs":["https://indieagency.news"]}</script>
vendor: 1 bytes, line 406
406
407<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==" type="application/ld+json">{"@context":"https://schema.org","@type":"WebSite","name":"IndieHQ","url":"https://indiehq.com"}</script>
407 408</head> 409<body>
410<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ=="> 411 /* Member-first landing: flag the page BEFORE paint so the prospect hero never flashes. */ 412 (function(){ 413 try { 414 var p = JSON.parse(localStorage.getItem("ihq_session") || "null"); 415 if (p && (!p.exp || Date.now() < p.exp) && p.role !== "team") { 416 document.documentElement.className += " ihq-member"; 417 } 418 } catch (e) {} 419 })(); 420</script>
420 421 422<header> 423 <div class="wrap header-inner"> 424 <a class='wordmark' href='/' style='display:flex;align-items:center;'><img src="https://media.indiehq.com/IndieHQ%20Logos/PNG/Color/IHQ__Color_WhiteBackground_Horizontal_xsbzda.png?height=240" alt="Indie HQ" style="height:44px;width:189px;object-fit:cover;display:block;"></a> 425 <nav class="main"> 426 <a href="https://indieagency.news">News</a> 427 <a href="https://ihqevents.com/">Events</a> 428 <a href='/directory'>Directory</a> 429 <a href='/commons'>Community</a> 430 <a href='/top40'>Awards</a> 431 <a class="nav-enter" href="https://top40pa.juried.is" style="display:inline-flex;align-items:center;line-height:1;background:var(--accent);color:var(--ink);padding:6px 12px;border-radius:999px;font-weight:800;font-size:.82rem;white-space:nowrap;">Enter Top 40 →</a> 432 <a href="/partners">Partners</a> 433 <a href="/member-hq">Member HQ</a> 434 <a class='mob-only' href='/login'>Sign in</a> 435 <a class='mob-only' href='/join'>Become a member</a> 436 </nav> 437 <div class="header-cta"> 438 <a class='login-link' href='/login'>Sign in</a> 439 <a class='btn btn-accent' href='/join'>Become a member</a> 440 </div> 441 <button class="nav-toggle" aria-label="Open menu" aria-expanded="false"><span></span><span></span><span></span></button> 442 </div> 443</header> 444 445<!-- ===== Jury recruitment promo ribbon ===== --> 446<style> 447 .jury-ribbon{ background:var(--accent); color:var(--ink); border-bottom:2px solid var(--ink); } 448 .jury-ribbon-inner{ max-width:1200px; margin:0 auto; padding:10px 28px; display:flex; align-items:center; gap:14px; flex-wrap:wrap; } 449 .jury-ribbon-txt{ font-size:.95rem; } 450 .jury-ribbon-cta{ font-weight:800; text-decoration:underline; text-underline-offset:3px; white-space:nowrap; } 451 .jury-ribbon-x{ margin-left:auto; background:none; border:0; font-size:1.35rem; line-height:1; cursor:pointer; color:var(--ink); opacity:.65; } 452 .jury-ribbon-x:hover{ opacity:1; } 453</style> 454<div id="cfe-ribbon" class="jury-ribbon"> 455 <div class="jury-ribbon-inner"> 456 <img src="https://ihq-awards.b-cdn.net/Show%20Logos/IHQ__Top%2040%20Black.png" alt="Top 40" decoding="async" style="height:26px;width:auto;display:block;flex:0 0 auto;"> 457 <span class="jury-ribbon-txt"><strong>Top 40: People + Agencies 2026 — Call for Entries is open.</strong> <span id="cfe-price">Main deadline $179 through Sat., Oct. 17</span> · Members save 25%.</span> 458 <a class="jury-ribbon-cta" href="https://top40pa.juried.is">Enter now →</a> 459 <button type="button" class="jury-ribbon-x" aria-label="Dismiss" onclick="var b=document.getElementById('cfe-ribbon');if(b)b.style.display='none';try{localStorage.setItem('ihq_top40cfe_ribbon_v2','1');}catch(e){}">×</button> 460 </div> 461</div>
462<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ=="> 463/* Top 40 P+A ribbon â deadline copy advances by itself (matches top40.html pricing). 464 Main $179 through Sat Oct 17 -> Final $199 through Sat Oct 31 -> ribbon hides after entries close. */ 465(function(){ 466 var r=document.getElementById('cfe-ribbon'); if(!r) return; 467 try{ if(localStorage.getItem('ihq_top40cfe_ribbon_v2')==='1'){ r.style.display='none'; return; } }catch(e){} 468 var now=new Date(), pt=document.getElementById('cfe-price'); 469 if(now>=new Date('2026-11-01T00:00:00-07:00')){ r.style.display='none'; return; } 470 if(now>=new Date('2026-10-18T00:00:00-07:00') && pt){ pt.innerHTML='Final deadline $199 through Sat., Oct. 31'; } 471})(); 472</script>
472 473<style> 474 #nepal-ribbon{ background:#DC143C; color:#fff; border-bottom:2px solid #0D0D12; } 475 #nepal-ribbon .jury-ribbon-cta{ color:#fff; } 476 #nepal-ribbon .jury-ribbon-x{ color:#fff; } 477</style> 478<div id="nepal-ribbon" class="jury-ribbon"> 479 <div class="jury-ribbon-inner"> 480 <img src="https://ian-media.b-cdn.net/IndieHQ%20Site%20Images/nepal%20fav.png" alt="Nepal" decoding="async" style="height:22px;width:auto;display:block;flex:0 0 auto;"> 481 <span class="jury-ribbon-txt"><strong>Stand with Nepal.</strong> Our first forward is out — $1,030, 100% of what members gave, sent to Nepal's official relief fund.</span> 482 <a class='jury-ribbon-cta' href='/nepal-relief'>Add to it →</a> 483 <button type="button" class="jury-ribbon-x" aria-label="Dismiss" onclick="var b=document.getElementById('nepal-ribbon');if(b)b.style.display='none';try{localStorage.setItem('ihq_nepal_ribbon','1');}catch(e){}">×</button> 484 </div> 485</div>
486<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==">try{if(localStorage.getItem('ihq_nepal_ribbon')==='1'){var _nr=document.getElementById('nepal-ribbon');if(_nr)_nr.style.display='none';}}catch(e){}</script>
486 487 488<!-- ===== Is It IP? launch ribbon (powered by Toerek) ===== --> 489<style> 490 #isitip-ribbon{ background:var(--ink); color:#fff; border-bottom:2px solid #0D0D12; } 491 #isitip-ribbon .jury-ribbon-cta{ color:var(--accent); } 492 #isitip-ribbon .jury-ribbon-x{ color:#fff; } 493</style> 494<div id="isitip-ribbon" class="jury-ribbon"> 495 <div class="jury-ribbon-inner"> 496 <span class="jury-ribbon-txt"><strong>Is It IP?</strong> A free 2-minute gut-check on what your agency owns — powered by Toerek Law | Legal + Creative.</span> 497 <a class="jury-ribbon-cta" href="/is-it-ip">Take the quiz →</a> 498 <button type="button" class="jury-ribbon-x" aria-label="Dismiss" onclick="var b=document.getElementById('isitip-ribbon');if(b)b.style.display='none';try{localStorage.setItem('ihq_isitip_ribbon','1');}catch(e){}">×</button> 499 </div> 500</div>
501<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==">try{if(localStorage.getItem('ihq_isitip_ribbon')==='1'){var _ir=document.getElementById('isitip-ribbon');if(_ir)_ir.style.display='none';}}catch(e){}</script>
501 502 503<!-- ===== Member welcome band (signed-in members only; hoists the launchpad up top) ===== --> 504<div class="member-hero"> 505 <div class="wrap"> 506 <div class="mh-kicker">Welcome back</div> 507 <h1 id="mh-greeting">You’re in. <span class="accent">Here’s your HQ.</span></h1> 508 <p class="mh-sub">Everything you get as a member — QuickCoach, your community, all your tools — lives in one place now.</p> 509 <div class="mh-chips"> 510 <a class="primary" href="/member-hq">Go to your Member HQ →</a> 511 <a href='/how-to'>New here? Start with the guide →</a> 512 </div> 513 <div class="mh-news" id="mh-news" hidden> 514 <div class="mh-news-h">Fresh from the newsroom — the news never stops</div> 515 <div class="mh-news-list" id="mh-news-list"></div> 516 </div> 517 <div class="mh-optin" id="mh-optin" hidden style="margin-top:18px;padding:13px 16px;border:1px solid rgba(128,128,128,.32);border-radius:12px;display:flex;flex-wrap:wrap;gap:10px 16px;align-items:center;justify-content:space-between;"> 518 <span class="mh-optin-txt" style="font-weight:600;">Want the IndieHQ newsletter? The best of the indie world, straight to your inbox.</span> 519 <span style="display:flex;gap:12px;align-items:center;flex-wrap:wrap;"> 520 <button type="button" id="mh-optin-yes" class="primary" style="border:0;cursor:pointer;font:inherit;">Yes, sign me up</button> 521 <button type="button" id="mh-optin-no" style="background:none;border:0;color:inherit;opacity:.7;text-decoration:underline;text-underline-offset:3px;cursor:pointer;font:inherit;">No thanks</button> 522 </span> 523 </div> 524 </div> 525</div> 526 527<!-- ===== Hero â the statement ===== --> 528<div class="hero"> 529 <div class="wrap"> 530 <div class="flag"></div> 531 <div id="mkt-kicker" style="font-size:.72rem;font-weight:800;letter-spacing:.15em;text-transform:uppercase;color:#21CF7E;margin-bottom:12px;">The Global Home for Independent Agencies</div> 532 <h1 id="mkt-h1">Independence is beautiful. And it’s <span class="accent">better together.</span></h1> 533 <div class="hero-rot" style="display:flex;align-items:center;gap:14px;min-height:2rem;margin:16px 0 4px;flex-wrap:wrap;"> 534 <span id="mkt-rot" style="font-size:1.5rem;font-weight:800;color:#21CF7E;letter-spacing:-.02em;transition:opacity .3s;">Sharpen your website.</span> 535 <span id="mkt-rot-dots" style="display:flex;gap:6px;"></span> 536 </div> 537 <p id="mkt-sub">One roof for the work of running an indie: read the news, sharpen the craft, get seen, and grow across a global community of independent agencies.</p> 538 <div class="hero-cta" style="flex-direction:column;align-items:flex-start;gap:12px;"> 539 <a class='btn btn-accent' href='/join'>Join the community</a> 540 <a class="btn" href="/member-hq">Already a member? Head here →</a> 541 <a href='/check' style='color:#21CF7E;font-weight:700;font-size:.95rem;text-decoration:underline;text-underline-offset:3px;'>Not sure? Check whether your agency is already a member →</a> 542 </div> 543 </div> 544</div>
545<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ=="> 546(function(){ 547 var ROT=["Sharpen your website.","Polish an op-ed.","Strengthen an awards entry.","Tighten your pitch to the trades.","Share your work on Indie Agency News.","Get the research and intelligence to run smarter.","Lean on a global indie community.","Post a role, or find your next one."]; 548 var el=document.getElementById("mkt-rot"),dots=document.getElementById("mkt-rot-dots"),hero=document.querySelector(".hero"); 549 if(!el||!dots)return; 550 ROT.forEach(function(_,i){var d=document.createElement("span");d.style.cssText="width:7px;height:7px;border-radius:50%;display:block;transition:background .2s;background:"+(i===0?"#21CF7E":"#3a3a42");dots.appendChild(d);}); 551 var di=dots.children,idx=0,paused=false,reduce=window.matchMedia&&matchMedia("(prefers-reduced-motion: reduce)").matches; 552 if(hero){hero.addEventListener("mouseenter",function(){paused=true;});hero.addEventListener("mouseleave",function(){paused=false;});} 553 if(!reduce){setInterval(function(){if(paused)return;idx=(idx+1)%ROT.length;el.style.opacity="0";setTimeout(function(){el.textContent=ROT[idx];el.style.opacity="1";for(var k=0;k<di.length;k++){di[k].style.background=(k===idx?"#21CF7E":"#3a3a42");}},300);},2600);} 554})(); 555</script>
555 556 557 558 559<!-- ===== 360+ member agencies - auto-scrolling marquee (live from members-feed) ===== --> 560<style> 561 #agency-scroll{padding:52px 0 48px;text-align:center;} 562 #agency-scroll .amn{font-size:3rem;font-weight:900;color:#0C9B53;letter-spacing:-.03em;line-height:1;} 563 #agency-scroll h2{font-size:1.5rem;letter-spacing:-.02em;margin:6px 0 4px;} 564 #agency-scroll .amsub{color:#56565E;max-width:56ch;margin:0 auto;} 565 #agency-scroll .amlink{color:#0C9B53;font-weight:800;margin-top:8px;display:inline-block;text-decoration:none;} 566 .amarq{margin-top:16px;overflow:hidden;position:relative;-webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);} 567 .amarq .atrack{display:flex;gap:12px;width:max-content;} 568 .amarq .atrack.a{animation:amscroll 70s linear infinite;} 569 .amarq .atrack.b{animation:amscrollb 86s linear infinite;} 570 .amarq:hover .atrack{animation-play-state:paused;} 571 a.achip{white-space:nowrap;border:2px solid #0D0D12;border-radius:999px;padding:9px 18px;font-weight:700;font-size:1rem;background:#fff;color:#0D0D12;text-decoration:none;} 572 a.achip:hover{background:#0D0D12;color:#FAFAF8;} 573 @keyframes amscroll{from{transform:translateX(0);}to{transform:translateX(-50%);}} 574 @keyframes amscrollb{from{transform:translateX(-50%);}to{transform:translateX(0);}} 575 @media(prefers-reduced-motion:reduce){ .amarq .atrack{animation:none;} } 576</style> 577<section id="agency-scroll"> 578 <div class="wrap"> 579 <div class="amn">360+</div> 580 <h2>independent agencies call it home.</h2> 581 <p class="amsub">
581From two-person shops to household names — the largest community of indies anywhere.</p> 582 <input id="amsearch" type="search" placeholder="Find agencies you know" autocomplete="off" style="width:100%;max-width:460px;margin:16px auto 0;display:block;padding:12px 15px;border:2px solid #0D0D12;border-radius:10px;font-size:1rem;font-family:inherit;"> 583 <div id="amresultcount" style="font-size:.85rem;color:#56565E;margin-top:8px;min-height:1.1rem;"></div> 584 <a class='amlink' href='/directory'>Meet them all in the Directory →</a> 585 </div> 586 <div id="amhits" class="wrap" style="display:none;flex-wrap:wrap;gap:9px;justify-content:center;margin-top:8px;"></div> 587 <div id="ammarqwrap"> 588 <div class="amarq"><div class="atrack a" id="atrackA"></div></div> 589 <div class="amarq"><div class="atrack b" id="atrackB"></div></div> 590 </div> 591</section>
592<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ=="> 593(function(){ 594 var A=document.getElementById("atrackA"),B=document.getElementById("atrackB"); 595 if(!A||!B)return; 596 function esc(s){return String(s).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");} 597 var FALLBACK=["Cactus","Sukle","Karsh Hagan","Zeus Jones","Duncan Channon","Oberland","Orci","Big Communications","Fortnight Collective","Territorial","FUSE Create","Goodway Group","Moontide","Saylor","Delve","Response Media","fivebyfive","Chameleon Collective","Odd Notion","MNSTR","Glow","Harmonium Group","Flight PR","Where Eagles Dare"]; 598 function render(names){ 599 for(var i=names.length-1;i>0;i--){var j=Math.floor(Math.random()*(i+1));var t=names[i];names[i]=names[j];names[j]=t;} 600 var half=Math.ceil(names.length/2); 601 function fill(el,arr){el.innerHTML=arr.map(function(n){return '<a class="achip" href="directory.html">'+esc(n)+'</a>';}).join("")+arr.map(function(n){return '<a class="achip" href="directory.html">'+esc(n)+'</a>';}).join("");} 602 fill(A,names.slice(0,half));fill(B,names.slice(half)); 603 [A,B].forEach(function(el){ var w=el.scrollWidth/2; if(w>0){ el.style.animationDuration=Math.max(40,Math.round(w/50))+"s"; } }); 604 } 605 fetch("/.netlify/functions/members-feed").then(function(r){return r.json();}).then(function(d){ 606 var names=((d&&d.members)||[]).map(function(m){return m&&m.name;}).filter(Boolean); 607 render(names.length>=12?names:FALLBACK.slice()); 608 }).catch(function(){render(FALLBACK.slice());}); 609 var q=document.getElementById("amsearch"),hits=document.getElementById("amhits"),marq=document.getElementById("ammarqwrap"),rc=document.getElementById("amresultcount"); 610 if(q){q.addEventListener("input",function(){ 611 var v=q.value.trim().toLowerCase(); 612 if(!v){hits.style.display="none";if(marq)marq.style.display="block";rc.textContent="";return;} 613 if(marq)marq.style.display="none";hits.style.display="flex"; 614 var names=[]; try{ names=Array.prototype.slice.call(document.querySelectorAll("#atrackA .achip,#atrackB .achip")).map(function(a){return a.textContent;}); }catch(e){} 615 var uniq={},list=[]; names.forEach(function(n){var k=n.toLowerCase(); if(!uniq[k]){uniq[k]=1;list.push(n);}}); 616 var m=list.filter(function(n){return n.toLowerCase().indexOf(v)>-1;}); 617 hits.innerHTML=m.slice(0,60).map(function(n){return '<a class="achip" href="directory.html">'+String(n).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")+'</a>';}).join(""); 618 rc.textContent=m.length?(m.length+" agencies match \u201c"+q.value+"\u201d"):("No match yet for \u201c"+q.value+"\u201d \u2014 the full list is in the Directory."); 619 });} 620})(); 621</script>
621 622 623 624 625<!-- ===== Live Tracker â the prominent band ===== --> 626<section id="tracker" class="dark"> 627 <div class="wrap"> 628 <span class="live-pill"><span class="live-dot"></span> Live</span> 629 <h2 id="trk-h2">The indie world, as it happens.</h2> 630 <p class="tracker-sub" id="trk-sub">The Live Tracker is the real-time pulse of what independent agencies are doing, winning, and talking about â right now.</p> 631 <div class="tracker-panel"> 632 <iframe 633 id="trk-frame" 634 data-liveblog="O5W3tA2AZCE1Oh9cqOKG" 635 width="100%" 636 height="800" 637 title="Indie News Tracker Q3 2026 â Part 2" 638 src="https://embed.timepath.co/liveblog/O5W3tA2AZCE1Oh9cqOKG" 639 frameborder="0" 640 scrolling="yes" 641 allow="encrypted-media; clipboard-read; clipboard-write; fullscreen" 642 referrerpolicy="no-referrer-when-downgrade" 643 loading="lazy" 644 style="display:block;border:0;background:#fff;width:100%;" 645 ></iframe> 646 </div> 647 <p class="tracker-credit">Powered by <a href="https://timepath.co" target="_blank" rel="noopener">Timepath</a></p> 648
648<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==" type="text/javascript">(function () { 649 var FRAME_ORIGIN = "https://embed.timepath.co"; 650 var el = document.getElementById("trk-frame"); 651 if (!el) return; 652 var currentId = el.getAttribute("data-liveblog") || "O5W3tA2AZCE1Oh9cqOKG"; // mutable â the Site Content slot can swap it 653 var raf = null; 654 function setHeight(px) { if (raf) return; raf = requestAnimationFrame(function () { el.style.height = String(px) + "px"; raf = null; }); } 655 function onMessage(e) { 656 if (!e || e.origin !== FRAME_ORIGIN) return; 657 var d = e.data && typeof e.data === "object" ? e.data : null; 658 if (!d || d.liveblogId !== currentId) return; 659 if (typeof d.frameHeight === "number" && d.frameHeight > 0 && d.frameHeight < 100000) { setHeight(d.frameHeight); } 660 } 661 function handshake() { 662 try { el.contentWindow && el.contentWindow.postMessage({ parentUrl: window.location.href, liveblogId: currentId, v: "2.0" }, FRAME_ORIGIN); } catch (err) {} 663 } 664 window.addEventListener("message", onMessage); 665 el.addEventListener("load", handshake); // fires on first load AND whenever the src is swapped 666 // Let the content loader point the Tracker at a new liveblog with no redeploy. 667 window.__setTracker = function (id) { 668 id = String(id || "").trim(); 669 if (!id || id === currentId) return; 670 currentId = id; 671 el.src = FRAME_ORIGIN + "/liveblog/" + id; 672 }; 673 })();</script>
673 674 </div> 675</section> 676 677<!-- ===== Editable homepage content (Site Content slots) â team edits in the hub, no redeploy. 678 Every slot has a baked-in default above, so if this fetch is slow or fails the page is unchanged. ===== -->
679<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==" type="text/javascript">(function () { 680 var D = { 681 hero_headline: "Independence is beautiful. And it's", 682 hero_headline_accent: "better together.", 683 hero_subhead: "One roof for the work of running an indie: read the news, sharpen the craft, get seen, and grow across a global community of independent agencies.", 684 tracker_heading: "The indie world, as it happens.", 685 tracker_sub: "The Live Tracker is the real-time pulse of what independent agencies are doing, winning, and talking about â right now.", 686 tracker_liveblog_id: "O5W3tA2AZCE1Oh9cqOKG" 687 }; 688 function esc(s) { return String(s == null ? "" : s).replace(/[&<>"]/g, function (c) { return { "&": "&", "<": "<", ">": ">", '"': """ }[c]; }); } 689 function setText(id, v) { var el = document.getElementById(id); if (el && v != null) el.textContent = v; } 690 fetch("/.netlify/functions/home-content").then(function (r) { return r.json(); }).then(function (res) { 691 var c = (res && res.content) || {}; 692 function val(k) { return (c[k] != null && String(c[k]).trim() !== "") ? String(c[k]) : D[k]; } 693 var h1 = document.getElementById("mkt-h1"); 694 if (h1) h1.innerHTML = esc(val("hero_headline")) + ' <span class="accent">' + esc(val("hero_headline_accent")) + '</span>'; 695 setText("mkt-sub", val("hero_subhead")); 696 setText("trk-h2", val("tracker_heading")); 697 setText("trk-sub", val("tracker_sub")); 698 if (window.__setTracker) window.__setTracker(val("tracker_liveblog_id")); 699 }).catch(function () { /* keep baked-in defaults */ }); 700})();</script>
700 701 702<!-- ===== Events ===== --> 703<section id="events"> 704 <div class="wrap"> 705 <div class="section-head"> 706 <span class="kicker">Live programming</span> 707 <h2>Show up. It's the whole point.</h2> 708 <p>Summits, sessions, and shows â where the indie community actually gets together.</p> 709 </div> 710 711 <!-- Page-width highlighted feature: the flagship Summit --> 712 <a class="summit-feature" href="https://indie27.com/"> 713 <div class="summit-left"> 714 <div class="summit-kick">â The main event · 2027</div> 715 <h3>Indies Rising Global Summit</h3> 716 <p class="summit-where"><strong>Portland, OR</strong> · Tuesday, April 13, 2027 · Portland Center Stage at The Armory</p> 717 <p class="summit-tier">Current rate: <b>Turbo Early Bird â $599</b> (through Dec 31). <b>$99</b> saves your spot at today's tier.</p> 718 <div class="summit-seats"> 719 <div class="summit-bar"><i style="width:12.5%"></i></div> 720 <div class="lab"><b>50</b> of 400 seats reserved · <b>350 left</b></div> 721 </div> 722 </div> 723 <div class="summit-right"> 724 <div class="countdown" id="summitCountdown" data-date="2027-04-13T09:00:00-07:00"> 725 <div class="cd-box"><div class="n" data-cd="d">â</div><div class="l">Days</div></div> 726 <div class="cd-box"><div class="n" data-cd="h">â</div><div class="l">Hrs</div></div> 727 <div class="cd-box"><div class="n" data-cd="m">â</div><div class="l">Min</div></div> 728 <div class="cd-box"><div class="n" data-cd="s">â</div><div class="l">Sec</div></div> 729 </div> 730 <span class="summit-cta">Reserve your seat â $99 â</span> 731 <span class="summit-sub">Locks in today's tier price</span> 732 </div> 733 </a> 734 735 <div class="evrail" id="eventsGrid"> 736 <!-- Live from ihqevents.com via /.netlify/functions/events-feed â a horizontal rail of every 737 upcoming event. The cards below are a fallback shown only if the feed is unreachable. --> 738 <a class="cell" href="https://ihqevents.com/e/trivia-sf"> 739 <div class="cell-img" style="background-image:url('https://media.indiehq.com/Events:%20Trivia/trivia__sf_bhmfwb.png')"></div> 740 <span class="event-date">Thu · Jul 16</span> 741 <h3>IAN Trivia Battle</h3> 742 <p>Four departments. One winner.</p> 743 <span class="go">Register â</span> 744 </a> 745 <a class="cell" href="https://ihqevents.com/e/showoff-boulder"> 746 <div class="cell-img" style="background-image:url('https://media.indiehq.com/Events:%20Show%20Off/Boulder_Show_Off_byl4cp.png')"></div> 747 <span class="event-date">Wed · Aug 5</span> 748 <h3>IAN Show Off â Boulder</h3> 749 <p>Show off your work.</p> 750 <span class="go">Register â</span> 751 </a> 752 <a class="cell" href="https://ihqevents.com/e/showoff-dc"> 753 <div class="cell-img" style="background-image:url('https://media.indiehq.com/Events:%20Show%20Off/DC_Show_Off_qhfpmb.png')"></div> 754 <span class="event-date">Tue · Oct 13</span> 755 <h3>IAN Show Off â Washington DC</h3> 756 <p>Show off your work.</p> 757 <span class="go">Register â</span> 758 </a> 759 </div> 760 <div class="evfoot"> 761 <a class="see-all" href="https://ihqevents.com/">See all events</a> 762 <div class="evnav" id="evNav"> 763 <button type="button" class="evbtn" id="evPrev" aria-label="Scroll to previous events" disabled>‹</button> 764 <button type="button" class="evbtn" id="evNext" aria-label="Scroll to more events">›</button> 765 </div> 766 </div> 767 </div> 768</section> 769 770<!-- ===== Sister Cities (public · member benefit) â the one home-page entry point. 771 Reuses the .band pattern (same as Scoreboard / Partners). Destination: /sister-cities ===== --> 772<section id="sister-cities"> 773 <div class="wrap"> 774 <div class="band"> 775 <div> 776 <span class="kicker"><span class="nw">A member benefit</span> · <span class="nw">Since 2024</span></span> 777 <h2>Two markets. A few months. No agenda, just good company.</h2> 778 <p>One of our most-loved traditions is back for a new round. Fresh pairings, new friends, and a standing excuse to get to know the indies in another market. The friendships tend to outlast the round.</p> 779 <!-- Sister Cities stats. Hardcoded, current as of 2026-09-28. 780 Source: Airtable base appE6rDw2wQZxOUXA, table tblUdIGCzLO13EINq. 781 Refresh at each round changeover. Owner: Sister Cities project. --> 782 <p class="sc-runs"><span><b>Fall 2026</b></span> · <span><b>24</b> markets</span> · <span><b>12</b> pairings</span> · <span><b>357</b> agencies</span> · <span>Through <b>December 31, 2026</b></span></p> 783 </div> 784 <div class="band-cta"><a class='btn btn-accent' href='/sister-cities'>Find your market →</a></div> 785 </div> 786 </div> 787</section> 788 789<!-- ===== IAN Shows â upcoming, from the Shows table (shows-feed). Hidden until there are Booked shows. ===== --> 790<section id="ian-shows" hidden> 791 <div class="wrap"> 792 <div class="section-head">
793 <span class="kicker">On IAN TV</span> 794 <h2>Coming up on our stages</h2> 795 </div> 796 <div class="grid grid-3" id="shows-grid"></div> 797 <a class='see-all' hidden href='/indie-stages' id='shows-host-cta'>Want to host one? Get on our stages →</a> 798 </div> 799</section>
800<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ=="> 801(function(){ 802 function esc(s){return (s==null?"":String(s)).replace(/[&<>"]/g,function(c){return {"&":"&","<":"<",">":">","\"":"""}[c];});} 803 function fdate(s){ if(!s) return ""; var d=new Date(s+"T00:00"); return isNaN(d)?"":d.toLocaleDateString(undefined,{month:"short",day:"numeric"}); } 804 fetch("/.netlify/functions/shows-feed").then(function(r){return r.json();}).then(function(d){ 805 var shows=(d&&d.shows)||[]; 806 var up=shows.filter(function(s){return s.status==="Booked";}); 807 if(!up.length) return; // section stays hidden until a show is booked 808 up.sort(function(a,b){ return (a.airDate||"").localeCompare(b.airDate||""); }); 809 document.getElementById("shows-grid").innerHTML = up.slice(0,3).map(function(s){ 810 var meta=[s.format, fdate(s.airDate)].filter(Boolean).map(esc).join(" · "); 811 return '<div class="cell"><span class="event-date">'+esc(s.type||"Show")+(meta?' · '+meta:'')+'</span>'+ 812 '<h3>'+esc(s.title)+'</h3>'+(s.description?'<p>'+esc(String(s.description).slice(0,140))+'</p>':'')+'</div>'; 813 }).join(""); 814 if(up.some(function(s){return s.needsHost;})) document.getElementById("shows-host-cta").hidden=false; 815 document.getElementById("ian-shows").hidden=false; 816 }).catch(function(){}); 817})(); 818</script>
818 819 820<!-- ===== News (editorial list) ===== --> 821<section id="news"> 822 <div class="wrap"> 823 <div class="section-head"> 824 <span class="kicker">Indie Agency News</span> 825 <h2>The latest from the newsroom</h2> 826 </div> 827 <div class="news-list"> 828 <!-- Static fallback â the live feed (news-feed.js) replaces this with real headlines on load, 829 and serves last-known headlines from cache when indieagency.news is down. This graceful 830 row only shows in a true cold outage (feed unreachable AND nothing cached yet). --> 831 <div class="news-item" style="cursor:default"> 832 <span class="tag">Newsroom</span> 833 <h3>Fresh headlines are on their way â the newsroom is catching up. Check back in a moment.</h3> 834 </div> 835 </div> 836 <a class="see-all" href="https://indieagency.news" target="_blank" rel="noopener">Read all the news</a> 837 </div> 838</section> 839 840<!-- ===== Meet an Indie Agency (signature collection) ===== --> 841<section id="meet"> 842 <div class="wrap"> 843 <div class="section-head"> 844 <span class="kicker">Signature series</span> 845 <h2>Meet an Indie Agency</h2> 846 <p>The shops behind the work â who they are, how they think, and what makes them worth knowing.</p> 847 </div> 848 <div class="news-list"> 849 <!-- Static fallback â meet-an-indie-feed.js replaces this with real profiles on load, and 850 serves last-known profiles from cache when indieagency.news is down. This graceful row 851 only shows in a true cold outage (feed unreachable AND nothing cached yet). --> 852 <div class="news-item" style="cursor:default"> 853 <span class="tag">Meet an Indie Agency</span> 854 <h3>More agency profiles are loading â check back in a moment.</h3> 855 </div> 856 </div> 857 <a class="see-all" href="https://indieagency.news/meet-an-indie-agency/" target="_blank" rel="noopener">Meet more agencies</a> 858 </div> 859</section> 860 861<!-- ===== What you get (the 5 C's) â value pitch, right under the hero ===== --> 862<section id="members" class="dark"> 863 <div class="wrap"> 864 <div class="section-head"> 865 <span class="kicker">The featured member benefit</span> 866 <h2>QuickCoach — expert feedback on your work.</h2> 867 <p>The most powerful thing in your membership. Send us your website or an awards entry — or a pitch, an op-ed, a panel — and get back a real, scored expert review, with specific fixes, before it ever ships.</p> 868 </div> 869 870 <div class="qc-split" style="display:grid;grid-template-columns:1fr 1fr;gap:38px;align-items:center;margin:24px 0 6px;"> 871 <div> 872 <div style="font-size:.72rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:#21CF7E;">What you can run through it</div> 873 <ul style="list-style:none;margin:12px 0 0;padding:0;display:flex;flex-direction:column;gap:9px;font-size:1.02rem;"> 874 <li>→ Your website or messaging</li> 875 <li>→ An awards entry</li> 876 <li>→ A new-business pitch</li> 877 <li>→ An op-ed or byline</li> 878 <li>→ A conference panel or talk</li> 879 </ul> 880 <div style="margin-top:22px;display:flex;gap:14px 16px;flex-wrap:wrap;align-items:center;"> 881 <a class='btn btn-accent' href='/quickcoach-tour'>See how QuickCoach works →</a> 882 <a class='see-all' href='/join'>Become a member</a> 883 </div> 884 </div> 885 <div style="background:#FAFAF8;color:#0D0D12;border-radius:16px;padding:24px 22px;box-shadow:10px 12px 0 rgba(33,207,126,.9);"> 886 <div style="font-size:.72rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:#0C9B53;">How it works</div> 887 <div style="display:flex;gap:14px;align-items:flex-start;margin-top:16px;"> 888 <div style="flex:0 0 30px;height:30px;border-radius:999px;background:#EAF9F1;border:2px solid #21CF7E;color:#0C9B53;font-weight:900;display:flex;align-items:center;justify-content:center;">1</div> 889 <div><div style="font-weight:800;">Send us your work</div><div style="color:#56565E;font-size:.92rem;">A website, a pitch, an op-ed, an award entry — whatever you want sharper.</div></div> 890 </div> 891 <div style="display:flex;gap:14px;align-items:flex-start;margin-top:14px;"> 892 <div style="flex:0 0 30px;height:30px;border-radius:999px;background:#EAF9F1;border:2px solid #21CF7E;color:#0C9B53;font-weight:900;display:flex;align-items:center;justify-content:center;">2</div> 893 <div><div style="font-weight:800;">Scored, then checked by a human</div><div style="color:#56565E;font-size:.92rem;">Our model scores it against a real rubric — an expert makes sure it’s right.</div></div> 894 </div> 895 <div style="display:flex;gap:14px;align-items:flex-start;margin-top:14px;"> 896 <div style="flex:0 0 30px;height:30px;border-radius:999px;background:#EAF9F1;border:2px solid #21CF7E;color:#0C9B53;font-weight:900;display:flex;align-items:center;justify-content:center;">3</div> 897 <div><div style="font-weight:800;">You get specific fixes back</div><div style="color:#56565E;font-size:.92rem;">A clear page you can act on — specific, scored, ready to use.</div></div> 898 </div> 899 </div> 900 </div> 901 902 <!-- Member quote spotlight (one at a time, from the Airtable Testimonials table) --> 903 <div data-ihq-quotes data-use="Homepage" data-kind="spotlight" hidden style="margin-top:40px;"></div> 904 905 <!-- Front Desk strip â the "ask us anything" door, surfaced above the membership grid --> 906 <a class='fd-strip' href='/frontdesk' style='margin-top:40px;
906display:flex;align-items:center;gap:18px;flex-wrap:wrap;text-decoration:none;color:#FAFAF8;border:2px solid #21CF7E;border-radius:14px;padding:18px 22px;background:rgba(33,207,126,.08);'> 907 <span style="flex:0 0 auto;width:42px;height:42px;border-radius:999px;background:#21CF7E;color:#0D0D12;display:flex;align-items:center;justify-content:center;font-weight:900;font-size:1.25rem;" aria-hidden="true">?</span> 908 <span style="flex:1 1 280px;"> 909 <span style="display:block;font-weight:800;font-size:1.12rem;">Not sure where to start? Ask the Front Desk.</span> 910 <span style="display:block;color:rgba(250,250,248,.72);font-size:.95rem;margin-top:2px;">Anything at all. A real person on our team gets back to you.</span> 911 </span> 912 <span style="flex:0 0 auto;background:#21CF7E;color:#0D0D12;font-weight:800;padding:10px 18px;border-radius:8px;white-space:nowrap;">Ask the Front Desk →</span> 913 </a> 914 915 <div style="margin-top:32px;border-top:2px solid rgba(250,250,248,.2);padding-top:24px;"> 916 <span class="kicker">And everything else in your membership</span> 917 <div class="grid grid-3" style="margin-top:16px;"> 918 <a class="cell" href="https://indieagency.news" target="_blank" rel="noopener" style="text-decoration:none;color:inherit;"> 919 <span class="badge">Coverage</span> 920 <h3>Get your story told</h3> 921 <p>Daily coverage at Indie Agency News — a real spotlight for your news, work and wins.</p> 922 <span class="go">Read the coverage →</span> 923 </a> 924 <a class='cell' href='/commons' style='text-decoration:none;color:inherit;'> 925 <span class="badge">Community</span> 926 <h3>Find your people</h3> 927 <p>A mentor who’s been where you are, and peers who get it. Real, verified people.</p> 928 <span class="go">Into the Commons →</span> 929 </a> 930 <a class='cell' href='/top40' style='text-decoration:none;color:inherit;'> 931 <span class="badge">Celebration</span> 932 <h3>Recognition you deserve</h3> 933 <p>Awards and stages to show your agency’s unique brilliance.</p> 934 <span class="go">See the awards →</span> 935 </a> 936 <a class='cell' href='/preferred-partners' style='text-decoration:none;color:inherit;'> 937 <span class="badge">Connection</span> 938 <h3>The right intro, when you need it</h3> 939 <p>Vetted partner vendors, peer networks and mentors, and help when you need it.</p> 940 <span class="go">Meet the partners →</span> 941 </a> 942 <a class='cell' href='/indie-blueprint-home' style='text-decoration:none;color:inherit;'> 943 <span class="badge">Blueprint</span> 944 <h3>Research, intel and tools</h3> 945 <p>Indie Blueprints help you address the most critical and current issues agencies face.</p> 946 <span class="go">Open the Blueprints →</span> 947 </a> 948 <a class='cell' href='/perks' style='text-decoration:none;color:inherit;'> 949 <span class="badge">Value</span> 950 <h3>Member perks</h3> 951 <p>Real deals on the tools indie shops actually use, negotiated for the community.</p> 952 <span class="go">See the perks →</span> 953 </a> 954 </div> 955 </div> 956 957 <div style="margin-top:26px;display:flex;gap:14px 20px;flex-wrap:wrap;align-items:center;"> 958 <a class='btn btn-accent' href='/join'>Become a member</a> 959 <a class='see-all' href='/how-to'>See how it all works →</a> 960 </div> 961 </div> 962</section> 963 964<!-- ===== Cannes Indie Scoreboard (call-out · external) ===== --> 965<section id="scoreboard"> 966 <div class="wrap"> 967 <div class="band scoreboard-feature"> 968 <div> 969 <span class="kicker">Cannes Indie Scoreboard</span> 970 <h2>How did indies do at Cannes this year?</h2> 971 <p>Our annual scorecard tracks how independent agencies stacked up on the Croisette — the wins, the Lions, and the indies who punched above their weight.</p> 972 </div> 973 <div class="band-cta"><a class="btn btn-accent" href="https://indiescoreboard.com/" target="_blank" rel="noopener">See the scoreboard →</a></div> 974 </div> 975 </div> 976</section> 977 978<!-- ===== Preferred Partners (public · featured) ===== --> 979<section id="partners-band"> 980 <div class="wrap"> 981 <div class="band partners-feature"> 982 <div>
983 <span class="kicker">Preferred Partners</span> 984 <h2>The partners we vouch for.</h2> 985 <p>Vetted help for the work you don't do in-house — sorted by what you actually need, with the proof and a warm intro a click away.</p> 986 <div class="pchips"> 987 <span>Media</span><span>Data</span><span>Measurement</span><span>Performance</span><span>Finance</span><span>Legal</span><span>Social</span><span>Talent</span> 988 </div> 989 </div> 990 <div class="band-cta"><a class='btn btn-accent' href='/preferred-partners'>Meet the partners →</a></div> 991 </div> 992 </div> 993</section> 994 995<!-- ===== HOLDCO WATCH â live LED ticker ===== --> 996<link href="https://fonts.googleapis.com/css2?family=VT323&family=Share+Tech+Mono&display=swap" rel="stylesheet"> 997<style> 998 .hcw-wrap{position:fixed;left:0;right:0;bottom:0;z-index:9999} 999 .hcw-src{background:#000;border-top:1px solid #1a1a1a;color:#5a5a5a;font-size:11px; 1000 letter-spacing:.06em;text-align:center;padding:3px 12px;white-space:nowrap; 1001 font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif} 1002 .hcw{position:relative;height:46px; 1003 background:linear-gradient(180deg,#111 0%,#000 55%,#0a0a0a 100%); 1004 border-top:1px solid #2a2a2a;box-shadow:0 -8px 24px rgba(0,0,0,.55); 1005 display:flex;align-items:stretch;overflow:hidden; 1006 font-family:"VT323","Share Tech Mono",monospace} 1007 .hcw-cap{flex:0 0 auto;display:flex;align-items:center;gap:9px;padding:0 16px;background:#000; 1008 border-right:1px solid #222;color:#ffb02e;font-size:22px;letter-spacing:.06em; 1009 text-shadow:0 0 6px rgba(255,176,46,.55);white-space:nowrap;position:relative;z-index:5} 1010 .hcw-dot{width:9px;height:9px;border-radius:50%;background:#ff3b30; 1011 box-shadow:0 0 8px #ff3b30;animation:hcw-blink 1.6s steps(1) infinite} 1012 @keyframes hcw-blink{50%{opacity:.25}} 1013 .hcw-live{font-size:15px;letter-spacing:.15em;color:#4a4a4a} 1014 .hcw-live.on{color:#37e06b;text-shadow:0 0 6px rgba(55,224,107,.6)} 1015 .hcw-track{position:relative;flex:1 1 auto;overflow:hidden} 1016 .hcw-move{display:flex;width:max-content;height:100%;align-items:center; 1017 animation:hcw-scroll 70s linear infinite;will-change:transform} 1018 .hcw-track:hover .hcw-move{animation-play-state:paused} 1019 @keyframes hcw-scroll{from{transform:translateX(0)}to{transform:translateX(-50%)}} 1020 .hcw-cell{display:inline-flex;align-items:baseline;gap:8px;padding:0 26px;font-size:23px; 1021 line-height:1;white-space:nowrap} 1022 .hcw-sym{color:#ffb02e;text-shadow:0 0 5px rgba(255,176,46,.45)} 1023 .hcw-px{color:#f2f2f2;text-shadow:0 0 4px rgba(255,255,255,.25)} 1024 .hcw-chg,.hcw-yoy{font-size:20px} 1025 .hcw-up{color:#37e06b;text-shadow:0 0 6px rgba(55,224,107,.5)} 1026 .hcw-down{color:#ff3b30;text-shadow:0 0 6px rgba(255,59,48,.5)} 1027 .hcw-yoy .hcw-k{color:#7d7d7d;text-shadow:none} 1028 .hcw-sep{color:#8a6a2a;padding:0 2px;font-size:20px} 1029 .hcw::after{content:"";position:absolute;inset:0;pointer-events:none;z-index:3; 1030 background-image:radial-gradient(circle,rgba(0,0,0,.62) .9px,transparent 1.4px); 1031 background-size:3px 3px;mix-blend-mode:multiply} 1032 .hcw::before{content:"";position:absolute;inset:0;pointer-events:none;z-index:4; 1033 background:linear-gradient(180deg,rgba(255,255,255,.05),transparent 40%)} 1034 @media (prefers-reduced-motion:reduce){.hcw-move{animation-duration:200s}} 1035 @media (max-width:600px){.hcw-cap{font-size:18px;padding:0 10px}.hcw-cell{font-size:20px;padding:0 18px}} 1036</style> 1037<div class="hcw-wrap" aria-label="Live advertising holding company stock ticker"> 1038 <div class="hcw-src">Data: Yahoo Finance</div> 1039 <div class="hcw"> 1040 <div class="hcw-cap"><span class="hcw-dot"></span>HOLDCO WATCH<span class="hcw-live">LIVE</span></div> 1041 <div class="hcw-track"><div class="hcw-move" id="hcw-tape"></div></div> 1042 </div> 1043</div>
1044<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ=="> 1045(function(){ 1046 var HOLDCOS = [ 1047 { sym:"OMC", y:"OMC", px:83.45, cur:"USD", day:-0.4, yoy:14.8 }, 1048 { sym:"PUB", y:"PUB.PA", px:85.64, cur:"EUR", day: 0.6, yoy: 4.5 }, 1049 { sym:"WPP", y:"WPP", px:18.49, cur:"USD", day:-0.3, yoy:-48.2 }, 1050 { sym:"4324", y:"4324.T", px:3443, cur:"JPY", day: 2.6, yoy:-0.2 }, 1051 { sym:"HAVAS",y:"HAVAS.AS", px:17.15, cur:"EUR", day:-0.3, yoy: 3.6 }, 1052 { sym:"STGW", y:"STGW", px:7.93, cur:"USD", day: 0.8, yoy:55.0 }, 1053 { sym:"ACN", y:"ACN", px:135.23, cur:"USD", day:-1.1, yoy:-49.1 }, 1054 { sym:"IBM", y:"IBM", px:217.07, cur:"USD", day:-25.2, yoy:-21.6 } 1055 ]; 1056 var CUR = { USD:"$", EUR:"â¬", JPY:"Â¥", GBP:"£", GBp:"£" }; 1057 function fmtPrice(v,cur){ var s=CUR[cur]||""; return cur==="JPY" 1058 ? s+Math.round(v).toLocaleString("en-US") : s+Number(v).toFixed(2); } 1059 function skeleton(c){ return '<span class="hcw-cell" data-sym="'+c.sym+'">' 1060 +'<span class="hcw-sym">'+c.sym+'</span><span class="hcw-px"></span>' 1061 +'<span class="hcw-chg"></span><span class="hcw-yoy"></span>' 1062 +'<span class="hcw-sep">•</span></span>'; } 1063 var tape = HOLDCOS.map(skeleton).join(""); 1064 document.getElementById("hcw-tape").innerHTML = tape + tape; 1065 function paint(c){ 1066 var nodes = document.querySelectorAll('.hcw-cell[data-sym="'+c.sym+'"]'); 1067 for (var i=0;i<nodes.length;i++){ 1068 var el=nodes[i]; 1069 el.querySelector(".hcw-px").textContent = fmtPrice(c.px,c.cur); 1070 var chg=el.querySelector(".hcw-chg"); 1071 chg.textContent=(c.day>=0?"â²":"â¼")+Math.abs(c.day).toFixed(1)+"%"; 1072 chg.className="hcw-chg "+(c.day>=0?"hcw-up":"hcw-down"); 1073 var yoy=el.querySelector(".hcw-yoy"); 1074 yoy.innerHTML='<span class="hcw-k">1Y</span> '+(c.yoy>=0?"+":"")+c.yoy.toFixed(1)+"%"; 1075 yoy.className="hcw-yoy "+(c.yoy>=0?"hcw-up":"hcw-down"); 1076 } 1077 } 1078 HOLDCOS.forEach(paint); 1079 function getQuote(y){ 1080 var api="https://query1.finance.yahoo.com/v8/finance/chart/"+y+"?range=1y&interval=1d"; 1081 var proxies=[ 1082 function(u){return "https://api.allorigins.win/raw?url="+encodeURIComponent(u);}, 1083 function(u){return "https://corsproxy.io/?url="+encodeURIComponent(u);} 1084 ]; 1085 return (function tryNext(i){ 1086 if(i>=proxies.length) return Promise.resolve(null); 1087 return fetch(proxies[i](api),{cache:"no-store"}).then(function(r){ 1088 if(!r.ok) throw 0; return r.json(); 1089 }).then(function(j){ 1090 var res=j.chart.result[1], m=res.meta, price=m.regularMarketPrice; 1091 var prev=(m.chartPreviousClose!=null?m.chartPreviousClose:(m.previousClose!=null?m.previousClose:price)); 1092 var closes=(res.indicators.quote[1].close||[]).filter(function(x){return x!=null;}); 1093 var ago=closes.length?closes[1]:price; 1094 return { px:price, cur:m.currency||"USD", 1095 day:((price-prev)/prev)*100, yoy:((price-ago)/ago)*100 }; 1096 }).catch(function(){ return tryNext(i+1); }); 1097 })(0); 1098 } 1099 function refresh(){ 1100 var live=false; 1101 Promise.all(HOLDCOS.map(function(c){ 1102 return getQuote(c.y).then(function(q){ 1103 if(q){ c.px=q.px; c.cur=q.cur; c.day=q.day; c.yoy=q.yoy; paint(c); live=true; } 1104 }); 1105 })).then(function(){ if(live) document.querySelector(".hcw-live").classList.add("on"); }); 1106 } 1107 refresh(); 1108 setInterval(refresh, 60000); 1109})(); 1110</script>
1110 1111<!-- ===== end HOLDCO WATCH ===== --> 1112 1113<footer> 1114 <div class="wrap"> 1115 <div class="footer-grid"> 1116 <div class="footer-brand"> 1117 <div class="wordmark">Indie <span class="hq">HQ</span></div> 1118 <p>By Indie Agency News. The global home independent agencies deserve.</p> 1119 </div> 1120 <div class="footer-links"> 1121 <div> 1122 <h4>Go</h4> 1123 <ul> 1124 <li><a href='/directory'>Directory</a></li> 1125 <li><a href='/sister-cities'>Sister Cities</a></li> 1126 <li><a href="#tracker">Live Tracker</a></li> 1127 <li><a href="https://ihqevents.com/">Events</a></li> 1128 <li><a href="https://indieagency.news" target="_blank" rel="noopener">News</a></li> 1129 <li><a href='/preferred-partners'>Preferred Partners</a></li> 1130 <li><a href='/partners'>Sponsorship</a></li> 1131 <li><a href='/top40-winners'>Top 40 Awards</a></li> 1132 </ul> 1133 </div> 1134 <div> 1135 <h4>Belong</h4> 1136 <ul> 1137 <li><a href="#open">Community</a></li> 1138 <li><a href="/member-hq">Member HQ</a></li> 1139 <li><a href='/frontdesk'>Front Desk</a></li> 1140 <li><a href='/join'>Become a member</a></li> 1141 <li><a href='/login'>Sign in</a></li> 1142 </ul> 1143 </div> 1144 <div> 1145 <h4>Talk to us</h4> 1146 <ul> 1147 <li><a href='/frontdesk'>Front Desk (members)</a></li> 1148 <li><span class="ihq-mail" data-u="aloha" data-anon="sign in to reach us" data-anon-href="/login.html"></span></li> 1149 </ul> 1150 </div> 1151 </div> 1152 </div> 1153 <div class="footer-legal">© 2026 Creative Bohemian LLC. Indie Agency News and Indie HQ are brands of Creative Bohemian LLC. All rights reserved. · <a href='/privacy' style='color:var(--accent);font-weight:700;'>Privacy Policy</a> · <a href='/terms' style='color:var(--accent);font-weight:700;'>Terms of Service</a></div> 1154 </div> 1155</footer> 1156
1157<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ=="> 1158 // Pixel strip â the Indie@Cannes grid motif, gently flickering like a live signal 1159 (function () { 1160 var strip = document.getElementById('pixelStrip'); 1161 if (!strip) return; 1162 var cols = 36, rows = 3, pixels = []; 1163 for (var c = 0; c < cols; c++) { 1164 var col = document.createElement('div'); 1165 col.className = 'pixel-col'; 1166 for (var r = 0; r < rows; r++) { 1167 var px = document.createElement('div'); 1168 px.className = 'px' + (Math.random() > 0.35 ? ' on' : ''); 1169 col.appendChild(px); pixels.push(px); 1170 } 1171 strip.appendChild(col); 1172 } 1173 setInterval(function () { 1174 for (var i = 0; i < 6; i++) { 1175 var p = pixels[Math.floor(Math.random() * pixels.length)]; 1176 p.classList.toggle('on'); 1177 } 1178 }, 700); 1179 })(); 1180 1181 // Ticker â duplicate the track so the loop is seamless 1182 (function () { 1183 var track = document.getElementById('tickerTrack'); 1184 if (track) track.innerHTML += track.innerHTML; 1185 })(); 1186 1187 // Live events â pull the soonest few from ihqevents.com via the same-origin relay. 1188 // If the feed is unreachable, the baked-in fallback cards stay put. 1189 (function () { 1190 var grid = document.getElementById('eventsGrid'); 1191 if (!grid) return; 1192 function esc(s){ return (s==null?'':String(s)).replace(/[&<>"]/g,function(c){return{'&':'&','<':'<','>':'>','"':'"'}[c]; }); } 1193 function fmt(iso){ 1194 var d = new Date((iso||'') + 'T00:00:00'); 1195 if (isNaN(d)) return 'Date TBA'; 1196 var wk = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'][d.getDay()]; 1197 var mo = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'][d.getMonth()]; 1198 return wk + ' · ' + mo + ' ' + d.getDate(); 1199 } 1200 fetch('/.netlify/functions/events-feed').then(function(r){ return r.json(); }).then(function(d){ 1201 var evs = (d && d.events) || []; 1202 if (!evs.length) return; // keep the fallback cards 1203 var cards = evs.map(function(e){ 1204 var mem = e.memberEvent; 1205 var href = mem ? esc(e.registerUrl || 'https://ihqevents.com/') : ('https://ihqevents.com/e/' + esc(e.slug)); 1206 var ext = mem ? ' target="_blank" rel="noopener"' : ''; 1207 var dateLine = (mem ? 'Member Event · ' : '') + fmt(e._d); 1208 return '<a class="cell" href="' + href + '"' + ext + '>' + 1209 (e.banner ? '<div class="cell-img" style="background-image:url(\'' + esc(e.banner) + '\')"></div>' : '') + 1210 '<span class="event-date">' + esc(dateLine) + '</span>' + 1211 '<h3>' + esc(String(e.name || '').replace(/^IAN\s+/i, '')) + '</h3>' + 1212 '<p>' + esc(e.tagline || (e.type && e.market ? e.type + ' · ' + e.market : (mem ? 'Free · register' : ''))) + '</p>' + 1213 (e.sponsor ? '<div class="evby">Presented by <b>' + esc(e.sponsor) + '</b></div>' : '') + 1214 '<span class="go">Register â</span></a>'; 1215 }); 1216 grid.innerHTML = cards.join(''); 1217 }).catch(function(){ /* keep the fallback cards */ }); 1218 })(); 1219 1220 // Events rail â prev/next arrows scroll the row; the control hides when everything already fits. 1221 (function () { 1222 var rail = document.getElementById('eventsGrid'); 1223 var prev = document.getElementById('evPrev'), next = document.getElementById('evNext'), nav = document.getElementById('evNav'); 1224 if (!rail || !prev || !next || !nav) return; 1225 function step(){ return Math.max(300, Math.round(rail.clientWidth * 0.8)); } 1226 function update(){ 1227 var overflow = rail.scrollWidth - rail.clientWidth > 4; 1228 nav.style.display = overflow ? 'flex' : 'none'; 1229 var x = rail.scrollLeft; 1230 prev.disabled = x <= 2; 1231 next.disabled = x + rail.clientWidth >= rail.scrollWidth - 2; 1232 } 1233 prev.addEventListener('click', function(){ rail.scrollBy({ left: -step(), behavior: 'smooth' }); }); 1234 next.addEventListener('click', function(){ rail.scrollBy({ left: step(), behavior: 'smooth' }); }); 1235 rail.addEventListener('scroll', update, { passive: true }); 1236 window.addEventListener('resize', update); 1237 new MutationObserver(update).observe(rail, { childList: true });
1237 // re-check when the feed injects cards 1238 update(); 1239 })(); 1240 1241 // Newsroom â latest posts from indieagency.news via the same-origin relay. 1242 // Category-agnostic (newest first). If unreachable, the placeholder rows stay. 1243 (function () { 1244 var list = document.querySelector('#news .news-list'); 1245 if (!list) return; 1246 function esc(s){ return (s==null?'':String(s)).replace(/[&<>"]/g,function(c){return{'&':'&','<':'<','>':'>','"':'"'}[c]; }); } 1247 fetch('/.netlify/functions/news-feed').then(function(r){ return r.json(); }).then(function(d){ 1248 var items = (d && d.items) || []; 1249 if (!items.length) return; // keep the placeholder rows 1250 list.innerHTML = items.map(function(i){ 1251 return '<a class="news-item" href="' + esc(/^https?:\/\//i.test(i.url) ? i.url : '#') + '" target="_blank" rel="noopener">' + 1252 '<span class="tag">' + esc(i.category) + '</span>' + 1253 '<h3>' + esc(i.title) + '</h3>' + 1254 '<span class="arrow">→</span></a>'; 1255 }).join(''); 1256 }).catch(function(){ /* keep the placeholder rows */ }); 1257 })(); 1258 1259 // Meet an Indie Agency â latest profiles from indieagency.news (self-configuring category). 1260 (function () { 1261 var list = document.querySelector('#meet .news-list'); 1262 if (!list) return; 1263 function esc(s){ return (s==null?'':String(s)).replace(/[&<>"]/g,function(c){return{'&':'&','<':'<','>':'>','"':'"'}[c]; }); } 1264 fetch('/.netlify/functions/meet-an-indie-feed').then(function(r){ return r.json(); }).then(function(d){ 1265 var items = (d && d.items) || []; 1266 if (!items.length) return; // keep the placeholder rows 1267 list.innerHTML = items.slice(0,6).map(function(i){ 1268 return '<a class="news-item" href="' + esc(/^https?:\/\//i.test(i.url) ? i.url : '#') + '" target="_blank" rel="noopener">' + 1269 '<span class="tag">' + esc(i.category) + '</span>' + 1270 '<h3>' + esc(i.title) + '</h3>' + 1271 '<span class="arrow">→</span></a>'; 1272 }).join(''); 1273 }).catch(function(){ /* keep the placeholder rows */ }); 1274 })(); 1275 1276 // Summit countdown â April 13, 2027 (Portland). 1277 (function () { 1278 var el = document.getElementById('summitCountdown'); if (!el) return; 1279 var target = new Date(el.getAttribute('data-date')).getTime(); 1280 function pad(n){ return (n < 10 ? '0' : '') + n; } 1281 function set(k, v){ var n = el.querySelector('[data-cd="' + k + '"]'); if (n) n.textContent = v; } 1282 function tick() { 1283 var diff = target - Date.now(); if (diff < 0) diff = 0; 1284 set('d', Math.floor(diff / 86400000)); 1285 set('h', pad(Math.floor(diff % 86400000 / 3600000))); 1286 set('m', pad(Math.floor(diff % 3600000 / 60000))); 1287 set('s', pad(Math.floor(diff % 60000 / 1000))); 1288 } 1289 tick(); setInterval(tick, 1000); 1290 })(); 1291</script>
1291 1292 1293<!-- 1294 WIRING NOTES (for Pat): 1295 1. Outseta: swap every [data-outseta] link for the real Outseta embed/auth links once the account exists. 1296 Gated items [data-gated] check Outseta paid status (fail closed). FRONT DESK IS MEMBERS-ONLY (decision Jul 1). 1297 2. Live Tracker ticker + Events: content reads from Airtable via Make. Placeholders marked above. 1298 3. News list: WIRED â news-feed.js relays the latest 10 posts from indieagency.news (category-agnostic). 1299 4. Front Desk form: /front-desk page posts to the Make webhook (Airtable + R2), behind the Outseta gate. 1300 5. Deploy: drop this folder into a Netlify site; point indiehq.com at it. 1301--> 1302
1303<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==" src="feedback-widget.js" defer></script>
vendor: 1 bytes, line 1303
1303
1304<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==" src="ihq-tips.js" defer></script>
1304 1305<!-- Mobile hamburger is owned solely by mobile-nav.js (one handler sitewide). 1306 A second inline handler here caused a double-toggle that cancelled itself out. -->
1307<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==" src="mobile-nav.js" defer></script>
vendor: 1 bytes, line 1307
1307
1308<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==" src="nav-back.js" defer></script>
vendor: 1 bytes, line 1308
1308
1309<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==" src="signin-cue.js" defer></script>
vendor: 1 bytes, line 1309
1309
1310<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==" src="ihq-brand.js" defer></script>
1310 1311<!-- ===== IndieHQ first-run welcome ===== --> 1312<style> 1313.ihqwm-overlay{position:fixed;inset:0;background:rgba(13,13,18,.55);backdrop-filter:blur(3px);z-index:99999;display:flex;align-items:center;justify-content:center;padding:20px;} 1314.ihqwm-overlay[hidden]{display:none;} 1315.ihqwm-card{background:#FAFAF8;color:#0D0D12;max-width:520px;width:100%;border-radius:18px;padding:30px 28px 22px;box-shadow:0 24px 70px rgba(0,0,0,.35);position:relative;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Roboto,sans-serif;animation:ihqwm-in .22s ease-out;} 1316@keyframes ihqwm-in{from{opacity:0;transform:translateY(10px) scale(.98);}to{opacity:1;transform:none;}} 1317.ihqwm-x{position:absolute;top:12px;right:15px;border:0;background:none;font-size:26px;line-height:1;color:#56565E;cursor:pointer;} 1318.ihqwm-kicker{color:#0C9B53;font-weight:700;font-size:.72rem;letter-spacing:.12em;text-transform:uppercase;margin-bottom:8px;} 1319.ihqwm-title{font-size:1.6rem;margin:0 0 8px;line-height:1.15;} 1320.ihqwm-sub{color:#56565E;font-size:.98rem;line-height:1.5;margin:0 0 18px;} 1321.ihqwm-actions{display:flex;flex-direction:column;gap:10px;} 1322.ihqwm-act{display:block;text-decoration:none;color:#0D0D12;border:1px solid #0D0D12;border-radius:12px;padding:13px 15px;transition:background .15s,transform .15s;} 1323.ihqwm-act:hover{background:#E9FAF0;transform:translateY(-1px);} 1324.ihqwm-act-h{display:block;font-weight:700;font-size:1rem;} 1325.ihqwm-act-s{display:block;color:#56565E;font-size:.86rem;margin-top:2px;} 1326.ihqwm-skip{display:block;width:100%;margin-top:16px;border:0;background:none;color:#56565E;font-size:.9rem;cursor:pointer;text-decoration:underline;} 1327.ihqwm-launch{display:inline-flex;align-items:center;gap:6px;margin:2px 0 14px;background:#21CF7E;color:#08301c;border:0;border-radius:999px;padding:8px 15px;font-weight:700;font-size:.85rem;cursor:pointer;} 1328.ihqwm-launch:hover{filter:brightness(1.06);} 1329</style> 1330<div id="ihqwm" class="ihqwm-overlay" hidden role="dialog" aria-modal="true" aria-labelledby="ihqwm-title"> 1331 <div class="ihqwm-card"> 1332 <button class="ihqwm-x" id="ihqwm-x" aria-label="Close">×</button> 1333 <div class="ihqwm-kicker">Welcome in</div> 1334 <h3 id="ihqwm-title" class="ihqwm-title">Welcome to IndieHQ</h3> 1335 <p class="ihqwm-sub">You’re part of the independent agency community now. Here are three good first moves — or explore on your own.</p> 1336 <div class="ihqwm-actions"> 1337 <a class='ihqwm-act' data-ihqwm='go' href='/commons'><span class="ihqwm-act-h">Say hi in the Commons</span><span class="ihqwm-act-s">Meet your people — 360+ indie agencies.</span></a> 1338 <a class='ihqwm-act' data-ihqwm='go' href='/quickcoach'><span class="ihqwm-act-h">Run your first QuickCoach</span><span class="ihqwm-act-s">Fast, useful feedback before it goes out.</span></a> 1339 <a class='ihqwm-act' data-ihqwm='go' href='/frontdesk'><span class="ihqwm-act-h">Ask the Front Desk anything</span><span class="ihqwm-act-s">A real person, ready to help.</span></a> 1340 </div> 1341 <button class="ihqwm-skip" id="ihqwm-skip" type="button">I’ll explore on my own</button> 1342 </div> 1343</div>
1344<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ=="> 1345(function(){ 1346 var KEY="ihq_session", SEEN="ihq_welcomed"; 1347 function sess(){try{var p=JSON.parse(localStorage.getItem(KEY)||"null");if(!p)return null;if(p.exp&&Date.now()>p.exp)return null;return p;}catch(e){return null;}} 1348 var s=sess(), ov=document.getElementById("ihqwm"), launch=document.getElementById("ihqwm-launch"); 1349 if(!ov)return; 1350 function seen(){try{localStorage.setItem(SEEN,"1");}catch(e){}} 1351 function esc(e){if(e.key==="Escape")close();} 1352 function open(){ov.hidden=false;document.addEventListener("keydown",esc);} 1353 function close(){ov.hidden=true;seen();document.removeEventListener("keydown",esc);} 1354 if(s){ 1355 var fn=((s.name||"").trim().split(/\s+/)[1]||""); 1356 var t=document.getElementById("ihqwm-title"); 1357 if(t)t.textContent=fn?("Welcome in, "+fn+"!"):"Welcome to IndieHQ"; 1358 if(launch){launch.hidden=false;launch.addEventListener("click",open);} 1359 } 1360 var x=document.getElementById("ihqwm-x"), sk=document.getElementById("ihqwm-skip"); 1361 if(x)x.addEventListener("click",close); 1362 if(sk)sk.addEventListener("click",close); 1363 ov.addEventListener("click",function(e){if(e.target===ov)close();}); 1364 Array.prototype.forEach.call(ov.querySelectorAll('[data-ihqwm="go"]'),function(a){a.addEventListener("click",seen);}); 1365 /* Onboarding now lives on /member-hq (its own first-visit nudge), and members land 1366 there at sign-in â so the marketing homepage no longer auto-pops a welcome mat. */ 1367})(); 1368</script>
1368 1369
1370<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==" src="service-notice.js" defer></script>
vendor: 1 bytes, line 1370
1370
1371<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==" src="email-reveal.js" defer></script>
vendor: 1 bytes, line 1371
1371
1372<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ=="> 1373 /* Member-first landing: greet by name + hoist the Member HQ launchpad to the top. */ 1374 (function(){ 1375 try{ 1376 var p = JSON.parse(localStorage.getItem("ihq_session") || "null"); 1377 if(!p || (p.exp && Date.now() >= p.exp) || p.role === "team") return; 1378 var first = ((p.name || "").trim().split(/\s+/)[0] || "").replace(/[<>&"]/g, ""); 1379 var g = document.getElementById("mh-greeting"); 1380 if(g && first) g.innerHTML = "Welcome back, " + first + ". <span class=\"accent\">Hereâs your HQ.</span>"; 1381 var members = document.getElementById("members"); 1382 var band = document.querySelector(".member-hero"); 1383 if(members && band && band.parentNode){ band.insertAdjacentElement("afterend", members); } 1384 // Pull a few live headlines into the welcome â news stays front and center. 1385 var nwrap = document.getElementById("mh-news"), nlist = document.getElementById("mh-news-list"); 1386 if(nwrap && nlist){ 1387 var nesc = function(s){ return (s==null?"":String(s)).replace(/[&<>"]/g,function(c){return {"&":"&","<":"<",">":">","\"":"""}[c];}); }; 1388 fetch("/.netlify/functions/news-feed").then(function(r){ return r.json(); }).then(function(d){ 1389 var items = (d && d.items) || []; 1390 if(!items.length) return; 1391 nlist.innerHTML = items.slice(0,3).map(function(i){ 1392 return '<a class="mh-news-item" href="' + nesc(/^https?:\/\//i.test(i.url) ? i.url : '#') + '" target="_blank" rel="noopener">' + 1393 '<span class="nt">' + nesc(i.category) + '</span><h4>' + nesc(i.title) + '</h4></a>'; 1394 }).join(""); 1395 nwrap.hidden = false; 1396 }).catch(function(){}); 1397 } 1398 // Newsletter opt-in nudge â show only to signed-in members who aren't on the list yet. 1399 try{ 1400 if(!localStorage.getItem("ihq_nl_dismissed")){ 1401 var tok = p.session; 1402 fetch("/.netlify/functions/newsletter-status",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({session:tok})}) 1403 .then(function(r){return r.json();}).then(function(d){ 1404 if(!d || d.subscribed !== false) return; 1405 var box=document.getElementById("mh-optin"); if(!box) return; 1406 box.hidden=false; 1407 var yes=document.getElementById("mh-optin-yes"), no=document.getElementById("mh-optin-no"); 1408 if(yes) yes.addEventListener("click",function(){ 1409 yes.disabled=true; yes.textContent="Adding youâ¦"; 1410 fetch("/.netlify/functions/newsletter-status",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({session:tok,action:"subscribe"})}) 1411 .then(function(r){return r.json();}).then(function(){ 1412 box.innerHTML='<span class="mh-optin-txt" style="font-weight:600;">Youâre on the list. â Welcome aboard.</span>'; 1413 try{localStorage.setItem("ihq_nl_dismissed","1");}catch(e){} 1414 }).catch(function(){ yes.disabled=false; yes.textContent="Yes, sign me up"; }); 1415 }); 1416 if(no) no.addEventListener("click",function(){ box.hidden=true; try{localStorage.setItem("ihq_nl_dismissed","1");}catch(e){} }); 1417 }).catch(function(){}); 1418 } 1419 }catch(e){} 1420 }catch(e){} 1421 })(); 1422</script>
1422 1423 1424<!-- ===== Is It IP? homepage pop-up (public · one-time per browser · powered by Toerek) ===== --> 1425<style> 1426 #ipHome{position:fixed;inset:0;z-index:10000;background:rgba(13,13,18,.62);display:flex;align-items:center;justify-content:center;padding:20px;} 1427 #ipHome[hidden]{display:none;} 1428 #ipHome .ipbox{background:var(--paper);border:2px solid var(--ink);border-radius:16px;max-width:440px;width:100%;padding:26px;box-shadow:0 24px 60px rgba(0,0,0,.35);} 1429 #ipHome img.iplogo{height:32px;width:auto;display:block;margin-bottom:14px;} 1430 #ipHome h2{font-size:1.6rem;margin:0 0 8px;color:var(--ink);} 1431 #ipHome p{margin:0 0 18px;color:#3a3a42;font-size:1rem;line-height:1.5;} 1432 #ipHome .ipcta{display:flex;flex-wrap:wrap;gap:10px 14px;align-items:center;} 1433 #ipHome .ipgo{background:var(--accent);color:var(--ink);font-weight:800;padding:12px 22px;border-radius:999px;text-decoration:none;border:2px solid var(--accent);} 1434 #ipHome .iplater{background:none;border:0;color:var(--ink);opacity:.6;font-size:.95rem;cursor:pointer;text-decoration:underline;text-underline-offset:3px;} 1435 #ipHome .iplater:hover{opacity:1;} 1436</style> 1437<div id="ipHome" hidden role="dialog" aria-modal="true" aria-labelledby="ipHomeH"> 1438 <div class="ipbox"> 1439 <img class="iplogo" src="https://media.indiehq.com/IndieHQ%20Site%20Images/Preferred%20Partner/Toerek/Legal___Creative.png" alt="Toerek L
1439aw | Legal + Creative"> 1440 <h2 id="ipHomeH">Is it IP?</h2> 1441 <p>You made something and want to protect it — but half the time, the thing agencies try to own can’t be owned at all. Take the free 2-minute gut-check and get a plain read. Powered by Toerek Law | Legal + Creative.</p> 1442 <div class="ipcta"> 1443 <a class="ipgo" id="ipHomeGo" href="/is-it-ip">Take the gut-check →</a> 1444 <button type="button" class="iplater" id="ipHomeLater">Maybe later</button> 1445 </div> 1446 </div> 1447</div>
1448<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ=="> 1449 (function () { 1450 function run() { 1451 var force = /[?&]ip=1/.test(location.search); // /?ip=1 forces it (test/demo) 1452 var KEY = "ihq_isitip_home_v1", seen = false; 1453 try { seen = localStorage.getItem(KEY) === "1"; } catch (e) {} 1454 var ov = document.getElementById("ipHome"); if (!ov) return; 1455 function done() { try { if (!force) localStorage.setItem(KEY, "1"); } catch (e) {} ov.setAttribute("hidden", ""); } 1456 function open() { ov.removeAttribute("hidden"); } 1457 if (force) open(); 1458 else if (!seen) setTimeout(open, 1400); // gentle delay so it doesn't slam on load 1459 var go = document.getElementById("ipHomeGo"); if (go) go.addEventListener("click", done); 1460 var later = document.getElementById("ipHomeLater"); if (later) later.addEventListener("click", done); 1461 ov.addEventListener("click", function (e) { if (e.target === ov) done(); }); 1462 document.addEventListener("keydown", function (e) { if (e.key === "Escape" && !ov.hasAttribute("hidden")) done(); }); 1463 } 1464 if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", run); 1465 else run(); 1466 })(); 1467</script>
1467 1468<!-- ===== IndieHQ Radio â homepage mini player (appears only while a show is live) ===== --> 1469<style> 1470 #ianRadioBar{position:fixed;left:0;right:0;bottom:0;z-index:60;display:none;align-items:center;gap:12px; 1471 background:rgba(13,13,18,.97);backdrop-filter:blur(8px);border-top:2px solid var(--accent); 1472 padding:9px 14px calc(9px + env(safe-area-inset-bottom));color:#fff;} 1473 #ianRadioBar .rb-play{width:42px;height:42px;border-radius:50%;border:none;background:var(--accent);color:#0D0D12;flex:0 0 auto;display:flex;align-items:center;justify-content:center;cursor:pointer;} 1474 #ianRadioBar .rb-play svg{width:18px;height:18px;} 1475 #ianRadioBar .rb-meta{min-width:0;flex:1;} 1476 #ianRadioBar .rb-k{font-size:.62rem;letter-spacing:.14em;text-transform:uppercase;font-weight:800;color:var(--accent);display:flex;align-items:center;gap:6px;} 1477 #ianRadioBar .rb-dot{width:7px;height:7px;border-radius:50%;background:var(--accent);animation:rbpulse 1.4s ease-in-out infinite;} 1478 @keyframes rbpulse{0%,100%{opacity:1}50%{opacity:.35}} 1479 #ianRadioBar .rb-t{font-size:.9rem;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;} 1480 #ianRadioBar .rb-open{color:#fff;text-decoration:none;font-weight:700;font-size:.82rem;white-space:nowrap;opacity:.85;} 1481 #ianRadioBar .rb-x{background:none;border:0;color:#fff;opacity:.5;font-size:1.2rem;line-height:1;cursor:pointer;padding:4px;} 1482</style> 1483<div id="ianRadioBar"> 1484 <button class="rb-play" id="rbPlay" aria-label="Play IndieHQ Radio"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg></button> 1485 <div class="rb-meta"> 1486 <div class="rb-k"><span class="rb-dot"></span>Good Day Advertising · Live</div> 1487 <div class="rb-t" id="rbTitle">On air now</div> 1488 </div> 1489 <a class="rb-open" href="/radio">Open player →</a> 1490 <button class="rb-x" id="rbX" aria-label="Hide">×</button> 1491</div>
1492<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==" src="radio-config.js"></script>
vendor: 1 bytes, line 1492
1492
1493<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ=="> 1494(function(){ 1495 var CFG=window.IAN_RADIO||{}; var SID=(CFG.STATION_ID||"").trim(); 1496 if(!SID) return; // nothing shows until the station ID is set 1497 if(CFG.HOME_BAR!==true) return; // manual switch: homepage bar only when we flip HOME_BAR on for a real show (station is "online" during automation too) 1498 try{ if(sessionStorage.getItem("ian_radio_bar_off")==="1") return; }catch(e){} 1499 var STREAM="https://streams.radio.co/"+SID+"/listen", STATUS="/.netlify/functions/radio-status?s="+encodeURIComponent(SID); 1500 var bar=document.getElementById("ianRadioBar"), play=document.getElementById("rbPlay"), 1501 title=document.getElementById("rbTitle"), x=document.getElementById("rbX"); 1502 var audio=new Audio(); audio.preload="none"; 1503 var PLAY='<svg viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>'; 1504 var PAUSE='<svg viewBox="0 0 24 24" fill="currentColor"><path d="M6 5h4v14H6zM14 5h4v14h-4z"/></svg>'; 1505 play.addEventListener("click",function(){ 1506 if(audio.paused){ if(audio.src!==STREAM)audio.src=STREAM; audio.play().then(function(){play.innerHTML=PAUSE;}).catch(function(){}); } 1507 else { audio.pause(); play.innerHTML=PLAY; } 1508 }); 1509 x.addEventListener("click",function(){ audio.pause(); bar.style.display="none"; try{sessionStorage.setItem("ian_radio_bar_off","1");}catch(e){} }); 1510 function poll(){ 1511 fetch(STATUS).then(function(r){return r.json();}).then(function(d){ 1512 var online=d.status==="online"; 1513 if(d.streaming_hostname) STREAM="https://"+d.streaming_hostname+"/"+SID+"/listen"; // real stream host (streams.radio.co 403s) 1514 bar.style.display = online ? "flex" : "none"; // only while a show is live 1515 if(online){ title.textContent=(d.current_track&&d.current_track.title)||"On air now"; } 1516 }).catch(function(){}); 1517 } 1518 poll(); setInterval(poll,30000); 1519})(); 1520</script>
vendor: 1 bytes, line 1520
1520
1521<script nonce="4ZpV9mdUbRwVjmlyHiDdGQ==" src="/ihq-quotes.js" data-use="Homepage" defer></script>
1521 1522</body> 1523</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.