PageSourceSearch

https://launchpadrocks.com/

html launchpadrocks.com collected 2026-09-26 01:17:32 UTC 58,574 bytes, 1,363 lines download raw bytes

1
2<!doctype html>
3<html lang="en">
4    <head>
5        <meta charset="utf-8">
6        <meta name="viewport" content="width=device-width, initial-scale=1">
7        <title>Launchpad Rocks</title>
8        <link rel="icon" type="image/png" sizes="32x32" href="/assets/images/favicon-32.png">
9        <style>
10            :root {
11                --ink: #f8f7f6cf;
12                --paper: #100a00ff;
13                --paper-deep: #efe6d6;
14                --accent: #fbfaf9ff;
15                --muted: #6e655b;
16                --rule: #d6cabb;
17            }
18
19            * {
20                box-sizing: border-box;
21            }
22
23            html, body {
24                margin: 0;
25                color: var(--ink);
26                background: black;
27                font-family: arial, sans-serif;
28                min-height: 100vh;
29                overflow-x: hidden;
30            }
31
32            html.modal-open,
33            body.modal-open {
34                overflow: hidden;
35                overscroll-behavior: none;
36            }
37
38            .launch-shake {
39                animation: launch-shake 2400ms linear 1 both;
40            }
41
42            .launch-shake-violent {
43                animation: launch-shake-violent 120ms linear infinite;
44            }
45
46            @keyframes launch-shake {
47                0% { transform: translate(0, 0); }
48                5% { transform: translate(-6px, 4px); }
49                10% { transform: translate(5px, -6px); }
50                18% { transform: translate(-7px, 3px); }
51                26% { transform: translate(6px, -5px); }
52                34% { transform: translate(-4px, 3px); }
53                45% { transform: translate(4px, -3px); }
54                58% { transform: translate(-3px, 2px); }
55                72% { transform: translate(2px, -2px); }
56                86% { transform: translate(-1px, 1px); }
57                100% { transform: translate(0, 0); }
58            }
59
60            @keyframes launch-shake-violent {
61                0% { transform: translate(0, 0); }
62                20% { transform: translate(-10px, 6px); }
63                40% { transform: translate(8px, -9px); }
64                60% { transform: translate(-9px, 5px); }
65                80% { transform: translate(9px, -6px); }
66                100% { transform: translate(0, 0); }
67            }
68
69            .wrap {
70                margin: 0;
71                padding: 0 10px;
72            }
73
74            .rocket-link {
75                position: fixed;
76                top: 16px;
77                right: 16px;
78                width: 61px;
79                height: 61px;
80                z-index: 10;
81                opacity: 0.8;
82                transition: transform 140ms ease, opacity 140ms ease;
83            }
84
85            .rocket-link:hover {
86                transform: translateY(-2px) scale(1.05);
87                opacity: 1;
88            }
89
90            .rocket-link img {
91                display: block;
92                width: 100%;
93                height: 100%;
94                object-fit: contain;
95            }
96
97
98            h1 {
99                font-size: clamp(2.6rem, 4vw, 4rem);
100                letter-spacing: -0.02em;
101                margin: 0;
102                text-transform: uppercase;
103            }
104
105            .tagline {
106                font-size: 1.05rem;
107                line-height: 1.5;
108                max-width: 520px;
109                margin: 0;
110                color: var(--muted);
111            }
112
113            .event-row {
114                display: flex;
115                gap: 0;
116                align-items: flex-start;
117                text-decoration: none;
118                color: inherit;
119                padding: 3px 0;
120                cursor: pointer;
121                transform-origin: center;
122                transition: transform 500ms ease;
123                will-change: transform;
124            }
125
126            .event-row:hover {
127                color: var(--accent);
128            }
129
130            .event-date {
131                font-size: 0.90rem;
132                letter-spacing: 0.06em;
133                text-transform: uppercase;
134                color: var(--accent);
135                flex: 0 0 45px;
136            }
137
138            .event-title {
139                font-size: 2rem;
140                line-height: 1;
141                text-transform: uppercase;
142                font-family: monospace, sans-serif;
143                text-wrap: nowrap;
144                word-spacing: 5px;
145                overflow: hidden;
146            }
147
148            .event-title span {
149                display: inline-block;
150                padding-right: 32px;
151            }
152
153            .event-title.is-scrolling span {
154                animation: title-scroll var(--scroll-duration, 6s) linear infinite;
155            }
156
157            @keyframes title-scroll {
158                from { transform: translateX(0); }
159                to { transform: translateX(calc(-1 * var(--scroll-distance, 0px))); }
160            }
161
162            .modal {
163                position: fixed;
164                inset: 0;
165                /* background: rgba(0, 0, 0, 0.75); */
166                display: flex;
167                align-items: center;
168                justify-content: center;
169                padding: 24px;
170                opacity: 0;
171                pointer-events: none;
172                transition: opacity 160ms ease;
173                z-index: 20;
174            }
175
176            .modal.is-open {
177                opacity: 1;
178                pointer-events: auto;
179            }
180
181            .modal-shell {
182                background: #0c0a08;
183                color: var(--ink);
184                max-width: 900px;
185                width: 100%;
186                max-height: 85vh;
187                overflow: auto;
188                border: 1px solid rgba(255, 255, 255, 0.08);
189                box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
190                position: relative;
191                padding: 24px;
192            }
193
194            .modal-close {
195                position: absolute;
196                top: 0px;
197                right: 6px;
198                background: transparent;
199                border: none;
200                color: var(--ink);
201                font-size: 2.4rem;
202                cursor: pointer;
203                text-shadow: 2px 2px 2px rgba(0, 0, 0, .8);
204            }
205
206            .modal-body {
207                font-size: 1rem;
208                line-height: 1.5;
209            }
210
211            .modal-body a {
212                color: #ffb48a;
213            }
214
215            .modal-body .flyer {
216                width: 300px;
217                max-width: 300px;
218                margin: 0 auto 16px;
219            }
220
221            .modal-body .flyer img {
222                width: 100%;
223                height: auto;
224                display: block;
225            }
226
227            .modal-body .buy {
228                margin: 12px 0 6px;
229            }
230
231            .modal-body .buy a {
232                display: inline-block;
233                padding: 10px 18px;
234                background: #ff6a00;
235                color: #1b0d00;
236                font-weight: 700;
237                font-size: 1.05rem;
238                text-transform: uppercase;
239                letter-spacing: 0.12em;
240                border: 2px solid #1b0d00;
241                box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.45);
242                text-decoration: none;
243            }
244
245            .empty {
246                font-size: 1.1rem;
247                color: var(--muted);
248            }
249
250            .footer {
251                margin-top: 48px;
252                font-size: 1.6rem;
253                color: var(--muted);
254                position: relative;
255                padding: 20px;
256                transition: box-shadow 300ms ease, color 300ms ease;
257            }
258
259            .footer-nav {
260                margin: 0;
261                padding: 0;
262                list-style: none;
263                display: flex;
264                flex-wrap: wrap;
265                gap: 16px 24px;
266                text-transform: uppercase;
267                letter-spacing: 0.08em;
268                font-size: 1.4rem;
269            }
270
271            .footer-nav a {
272                color: inherit;
273                text-decoration: none;
274            }
275
276            .footer-nav a:hover {
277                color: var(--accent);
278            }
279
280            .footer-glow {
281                color: #ffb48a;
282                box-shadow:
283                    0 -20px 60px rgba(255, 120, 40, 0.35),
284                    0 -6px 18px rgba(255, 90, 20, 0.6);
285                animation: footer-glow 2400ms ease-out 1 both;
286            }
287            .address {
288                margin-top: 12px;
289            }
290
291            @keyframes footer-glow {
292                0% {
293                    box-shadow:
294                        0 -28px 80px rgba(255, 120, 40, 0.5),
295                        0 -8px 22px rgba(255, 90, 20, 0.7);
296                    opacity: 1;
297                }
298                70% {
299                    box-shadow:
300                        0 -12px 40px rgba(255, 120, 40, 0.3),
301                        0 -4px 14px rgba(255, 90, 20, 0.4);
302                    opacity: 0.9;
303                }
304                100% {
305                    box-shadow:
306                        0 -4px 10px rgba(255, 120, 40, 0.1),
307                        0 -2px 6px rgba(255, 90, 20, 0.15);
308                    opacity: 0.7;
309                }
310            }
311
312            @media (max-width: 640px) {
313                .event-row {
314                    padding: 1px 0;
315                }
316
317                .event-date {
318                    font-size: 0.75rem;
319                }
320
321                .event-title {
322                    font-size: 1.2rem;
323                }
324                .modal-shell {
325                    padding: 0px;
326                }
327
328                .modal-body .flyer {
329                    width: 100%;
330                    max-width: 100%;
331                }
332
333                .modal-body .header-event-box h1 {
334                    font-size: 1.35rem;
335                }
336
337                .modal-body .buy {
338                    text-align: center;
339                }
340                .modal-close {
341                    position: fixed;
342                    top: 31px;
343                    right: 5px;
344                }
345            }
346        </style>
347    </head>
348    <body>
349        <a class="rocket-link" href="#footer" aria-label="Jump to footer">
350            <img src="/assets/images/rocket_cropped.webp" alt="">
351        </a>
352        <main class="wrap">
353                            <section class="events">
354                    
355                        <div class="event-row" data-event-id="467088">
356                            <div class="event-date">
357                                Sep<br><span class="dom">25</span>
358                            </div>
359                            <div class="event-title">
360                                <span>&quot;9 2 5&quot; Dolly Parton Tribute Show </span>
361                            </div>
362                        </div>
363                    
364                        
365                        <div class="event-row" data-event-id="467087">
366                            <div class="event-date">
367                                Sep<br><span class="dom">26</span>
368                            </div>
369                            <div class="event-title">
370                                <span>Dead Payphones * Ditch Dog * Anti Gravity Love Machine * Suitor Scenario</span>
371                            </div>
372                        </div>
373                    
374                        
375                        <div class="event-row" data-event-id="461621">
376                            <div class="event-date">
377                                Sep<br><span class="dom">27</span>
378                            </div>
379                            <div class="event-title">
380                                <span>Silly Goose * Cheem * Frigga Five </span>
381                            </div>
382                        </div>
383                    
384                        
385                        <div class="event-row" data-event-id="462090">
386                            <div class="event-date">
387                                Sep<br><span class="dom">29</span>
388                            </div>
389                            <div class="event-title">
390                                <span>Unto Others * Wraith Knight * Coma Recovery</span>
391                            </div>
392                        </div>
393                    
394                        
395                        <div class="event-row" data-event-id="457889">
396                            <div class="event-date">
397                                Oct<br><span class="dom">01</span>
398                            </div>
399                            <div class="event-title">
400                                <span>Hot Water Music * Russian Girlfriends * Past Lives</span>
401                            </div>
402                        </div>
403                    
404                        
405                        <div class="event-row" data-event-id="466017">
406                            <div class="event-date">
407                                Oct<br><span class="dom">02</span>
408                            </div>
409                            <div class="event-title">
410                                <span>Night of the Living Cover Bands - All Nights</span>
411                            </div>
412                        </div>
413                    
414                        
415                        <div class="event-row" data-event-id="453230">
416                            <div class="event-date">
417                                Oct<br><span class="dom">02</span>
418                            </div>
419                            <div class="event-title">
420                                <span>Night Of The Living Cover Bands - Night 1 </span>
421                            </div>
422                        </div>
423                    
424                        
425                        <div class="event-row" data-event-id="453922">
426                            <div class="event-date">
427                                Oct<br><span class="dom">03</span>
428                            </div>
429                            <div class="event-title">
430                                <span>Night Of The Living Cover Bands - Night 2</span>
431                            </div>
432                        </div>
433                    
434                        
435                        <div class="event-row" data-event-id="466104">
436                            <div class="event-date">
437                                Oct<br><span class="dom">04</span>
438                            </div>
439                            <div class="event-title">
440                                <span>Bl&#039;ast * Luicidal * Sorry Guero </span>
441                            </div>
442                        </div>
443                    
444                        
445                        <div class="event-row" data-event-id="466110">
446                            <div class="event-date">
447                                Oct<br><span class="dom">05</span>
448                            </div>
449                            <div class="event-title">
450                                <span>Exhorder * No/Mas * Phantom * Intoxicated </span>
451                            </div>
452                        </div>
453                    
454                        
455                        <div class="event-row" data-event-id="463679">
456                            <div class="event-date">
457                                Oct<br><span class="dom">07</span>
458                            </div>
459                            <div class="event-title">
460                                <span>Combichrist * Ludovico Technique * Dead Animal Assembly Plant * DJ K.0ss</span>
461                            </div>
462                        </div>
463                    
464                        
465                        <div class="event-row" data-event-id="467195">
466                            <div class="event-date">
467                                Oct<br><span class="dom">08</span>
468                            </div>
469                            <div class="event-title">
470                                <span> Anti Gravity Love Machine * In Fair Condition * ShyGuy * Happy Accident</span>
471                            </div>
472                        </div>
473                    
474                        
475                        <div class="event-row" data-event-id="454145">
476                            <div class="event-date">
477                                Oct<br><span class="dom">09</span>
478                            </div>
479                            <div class="event-title">
480                                <span>Night Of The Living Cover Bands - Night 3</span>
481                            </div>
482                        </div>
483                    
484                        
485                        <div class="event-row" data-event-id="464905">
486                            <div class="event-date">
487                                Oct<br><span class="dom">10</span>
488                            </div>
489                            <div class="event-title">
490                                <span>Night Of The Living Cover Bands - Night 4</span>
491                            </div>
492                        </div>
493                    
494                        
495                        <div class="event-row" data-event-id="464639">
496                            <div class="event-date">
497                                Oct<br><span class="dom">12</span>
498                            </div>
499                            <div class="event-title">
500                                <span>Chinese Football - Occupy the Absence Tour </span>
501                            </div>
502                        </div>
503                    
504                        
505                        <div class="event-row" data-event-id="461057">
506                            <div class="event-date">
507                                Oct<br><span class="dom">13</span>
508                            </div>
509                            <div class="event-title">
510                                <span>Cryogeyser * Starling * Heaven&#039;s Night </span>
511                            </div>
512                        </div>
513                    
514                        
515                        <div class="event-row" data-event-id="461937">
516                            <div class="event-date">
517                                Oct<br><span class="dom">14</span>
518                            </div>
519                            <div class="event-title">
520                                <span>Blitzkid - Modern Hel Tour 2026</span>
521                            </div>
522                        </div>
523                    
524                        
525                        <div class="event-row" data-event-id="454659">
526                            <div class="event-date">
527                                Oct<br><span class="dom">16</span>
528                            </div>
529                            <div class="event-title">
530                                <span>Night Of The Living Cover Bands - Night 5</span>
531                            </div>
532                        </div>
533                    
534                        
535                        <div class="event-row" data-event-id="464972">
536                            <div class="event-date">
537                                Oct<br><span class="dom">17</span>
538                            </div>
539                            <div class="event-title">
540                                <span>Night Of The Living Cover Bands - Night 6</span>
541                            </div>
542                        </div>
543                    
544                        
545                        <div class="event-row" data-event-id="467020">
546                            <div class="event-date">
547                                Oct<br><span class="dom">18</span>
548                            </div>
549                            <div class="event-title">
550                                <span>Three Bad Jacks </span>
551                            </div>
552                        </div>
553                    
554                        
555                        <div class="event-row" data-event-id="458375">
556                            <div class="event-date">
557                                Oct<br><span class="dom">20</span>
558                            </div>
559                            <div class="event-title">
560                                <span>she&#039;s green * Witches Exist  * smush  </span>
561                            </div>
562                        </div>
563                    
564                        
565                        <div class="event-row" data-event-id="463245">
566                            <div class="event-date">
567                                Oct<br><span class="dom">21</span>
568                            </div>
569                            <div class="event-title">
570                                <span>Authority Zero * Counterpunch * Right On, Kid * Washpot  </span>
571                            </div>
572                        </div>
573                    
574                        
575                        <div class="event-row" data-event-id="454712">
576                            <div class="event-date">
577                                Oct<br><span class="dom">23</span>
578                            </div>
579                            <div class="event-title">
580                                <span>Night Of The Living Cover Bands - Night 7</span>
581                            </div>
582                        </div>
583                    
584                        
585                        <div class="event-row" data-event-id="454713">
586                            <div class="event-date">
587                                Oct<br><span class="dom">24</span>
588                            </div>
589                            <div class="event-title">
590                                <span>Night Of The Living Cover Bands - Night 8</span>
591                            </div>
592                        </div>
593                    
594                        
595                        <div class="event-row" data-event-id="464444">
596                            <div class="event-date">
597                                Oct<br><span class="dom">25</span>
598                            </div>
599                            <div class="event-title">
600                                <span>Token - I&#039;m Leaving Soon Tour </span>
601                            </div>
602                        </div>
603                    
604                        
605                        <div class="event-row" data-event-id="465315">
606                            <div class="event-date">
607                                Oct<br><span class="dom">26</span>
608                            </div>
609                            <div class="event-title">
610                                <span>Boundaries * Centennial </span>
611                            </div>
612                        </div>
613                    
614                        
615                        <div class="event-row" data-event-id="463660">
616                            <div class="event-date">
617                                Oct<br><span class="dom">27</span>
618                            </div>
619                            <div class="event-title">
620                                <span>Sex Mex - The Stockpile Tour </span>
621                            </div>
622                        </div>
623                    
624                        
625                        <div class="event-row" data-event-id="456304">
626                            <div class="event-date">
627                                Oct<br><span class="dom">28</span>
628                            </div>
629                            <div class="event-title">
630                                <span>REZN * Lowheaven * Nomestomper </span>
631                            </div>
632                        </div>
633                    
634                        
635                        <div class="event-row" data-event-id="457240">
636                            <div class="event-date">
637                                Oct<br><span class="dom">30</span>
638                            </div>
639                            <div class="event-title">
640                                <span>Launchpad presents Jim Henson&#039;s Labyrinth: In Concert 40 Anniversary at KiMo Theatre</span>
641                            </div>
642                        </div>
643                    
644                        
645                        <div class="event-row" data-event-id="454714">
646                            <div class="event-date">
647                                Oct<br><span class="dom">30</span>
648                            </div>
649                            <div class="event-title">
650                                <span>Night Of The Living Cover Bands - Night 9</span>
651                            </div>
652                        </div>
653                    
654                        
655                        <div class="event-row" data-event-id="454658">
656                            <div class="event-date">
657                                Oct<br><span class="dom">31</span>
658                            </div>
659                            <div class="event-title">
660                                <span>5th Annual HALLOWEEN DANCE PARTY at Launchpad!</span>
661                            </div>
662                        </div>
663                    
664                        
665                        <div class="event-row" data-event-id="465160">
666                            <div class="event-date">
667                                Nov<br><span class="dom">01</span>
668                            </div>
669                            <div class="event-title">
670                                <span>Night Of The Living Cover Bands - All Ages Encore </span>
671                            </div>
672                        </div>
673                    
674                        
675                        <div class="event-row" data-event-id="466628">
676                            <div class="event-date">
677                                Nov<br><span class="dom">03</span>
678                            </div>
679                            <div class="event-title">
680                                <span>Escape The Fate * Atlas//Below * Dakota Ave</span>
681                            </div>
682                        </div>
683                    
684                        
685                        <div class="event-row" data-event-id="465244">
686                            <div class="event-date">
687                                Nov<br><span class="dom">08</span>
688                            </div>
689                            <div class="event-title">
690                                <span>Ouija Macc * Darby O&#039;Trill * Mikey Rotten</span>
691                            </div>
692                        </div>
693                    
694                        
695                        <div class="event-row" data-event-id="465490">
696                            <div class="event-date">
697                                Nov<br><span class="dom">11</span>
698                            </div>
699                            <div class="event-title">
700                                <span>2Dead Boys</span>
701                            </div>
702                        </div>
703                    
704                        
705                        <div class="event-row" data-event-id="464319">
706                            <div class="event-date">
707                                Nov<br><span class="dom">13</span>
708                            </div>
709                            <div class="event-title">
710                                <span>Kaotic State * Deforme * Unseen Espiritu * Ritual Noise Abuse * Destroy To Recreate</span>
711                            </div>
712                        </div>
713                    
714                        
715                        <div class="event-row" data-event-id="463324">
716                            <div class="event-date">
717                                Nov<br><span class="dom">14</span>
718                            </div>
719                            <div class="event-title">
720                                <span>Violet Grohl - Be Sweet To Me Tour </span>
721                            </div>
722                        </div>
723                    
724                        
725                        <div class="event-row" data-event-id="462540">
726                            <div class="event-date">
727                                Nov<br><span class="dom">15</span>
728                            </div>
729                            <div class="event-title">
730                                <span>INOHA - This Might Be Useful Tour </span>
731                            </div>
732                        </div>
733                    
734                        
735                        <div class="event-row" data-event-id="464988">
736                            <div class="event-date">
737                                Nov<br><span class="dom">16</span>
738                            </div>
739                            <div class="event-title">
740                                <span>Locked Shut * Rust * Music Is The Enemy * Cerberus </span>
741                            </div>
742                        </div>
743                    
744                        
745                        <div class="event-row" data-event-id="464660">
746                            <div class="event-date">
747                                Nov<br><span class="dom">20</span>
748                            </div>
749                            <div class="event-title">
750                                <span>Forbidden - Chaos By Design US Tour 2026</span>
751                            </div>
752                        </div>
753                    
754                        
755                        <div class="event-row" data-event-id="461280">
756                            <div class="event-date">
757                                Nov<br><span class="dom">21</span>
758                            </div>
759                            <div class="event-title">
760                                <span>Holy Wave * Queen Serene * The Art Dept.</span>
761                            </div>
762                        </div>
763                    
764                        
765                        <div class="event-row" data-event-id="463353">
766                            <div class="event-date">
767                                Nov<br><span class="dom">24</span>
768                            </div>
769                            <div class="event-title">
770                                <span>Thoughts on Bowling * Softly * HummusVacuum * MooseCreek Park</span>
771                            </div>
772                        </div>
773                    
774                        
775                        <div class="event-row" data-event-id="466717">
776                            <div class="event-date">
777                                Dec<br><span class="dom">11</span>
778                            </div>
779                            <div class="event-title">
780                                <span>Guilt Trip * Gates To Hell</span>
781                            </div>
782                        </div>
783                    
784                        
785                        <div class="event-row" data-event-id="462876">
786                            <div class="event-date">
787                                Dec<br><span class="dom">15</span>
788                            </div>
789                            <div class="event-title">
790                                <span>Kingdom Of Giants * Deadlands * Holy Wars * Night Rider </span>
791                            </div>
792                        </div>
793                    
794                        
795                        <div class="event-row" data-event-id="462975">
796                            <div class="event-date">
797                                Dec<br><span class="dom">18</span>
798                            </div>
799                            <div class="event-title">
800                                <span>Save Ferris * Rocksteady Pickups * DJ Rootz Rocka </span>
801                            </div>
802                        </div>
803                    
804                        
805                        <div class="event-row" data-event-id="464317">
806                            <div class="event-date">
807                                Jan<br><span class="dom">19</span>
808                            </div>
809                            <div class="event-title">
810                                <span> Koffin Kats * The Last Gang * Starving Wolves </span>
811                            </div>
812                        </div>
813                    
814                        
815                        <div class="event-row" data-event-id="466284">
816                            <div class="event-date">
817                                Jan<br><span class="dom">23</span>
818                            </div>
819                            <div class="event-title">
820                                <span>Emo Night Karaoke </span>
821                            </div>
822                        </div>
823                    
824                        
825                        <div class="event-row" data-event-id="463904">
826                            <div class="event-date">
827                                Feb<br><span class="dom">03</span>
828                            </div>
829                            <div class="event-title">
830                                <span>Nervosa - North America Slave Machine Tour 2027</span>
831                            </div>
832                        </div>
833                    
834                                        </section>
835                        <style>
836    .footer .footer-item {
837        position: relative;
838    }
839
840    .footer-toggle {
841        background: none;
842        border: 0;
843        color: inherit;
844        font: inherit;
845        text-transform: inherit;
846        letter-spacing: inherit;
847        cursor: pointer;
848        padding: 0;
849    }
850
851    .footer-subnav {
852        list-style: none;
853        margin: 8px 0 0;
854        padding: 0;
855        display: none;
856        gap: 6px;
857        flex-direction: column;
858        font-size: 0.95rem;
859        text-transform: none;
860        letter-spacing: 0.02em;
861    }
862
863    .footer-subnav.is-open {
864        display: flex;
865    }
866
867    .footer-subnav a {
868        color: inherit;
869        text-decoration: none;
870    }
871
872    .footer-subnav a:hover {
873        color: var(--accent);
874    }
875
876    .footer-subnav .is-hidden {
877        display: none;
878    }
879</style>
880<footer class="footer" id="footer">
881            <ul class="footer-nav">
882                            <li class="footer-item">
883                                                                        <a href="/month">Calendar</a>
884                                                            </li>
885                            <li class="footer-item">
886                                                                        <a href="/shopping">Store</a>
887                                                            </li>
888                            <li class="footer-item">
889                                                                        <a href="/contact_page">Contact</a>
890                                                            </li>
891                            <li class="footer-item">
892                                            <button class="footer-toggle" type="button" aria-expanded="false">
893                            Media                        </button>
894                        <ul class="footer-subnav" aria-hidden="true">
895                                                            <li class="">
896                                                                            <a href="https://www.instagram.com/launchpadabq/?hl=en">Instagram Photos</a>
897                                                                    </li>
898                                                            <li class="">
899                                                                            <a href="https://www.facebook.com/launchpadrocks/">Facebook Photos</a>
900                                                                    </li>
901                                                            <li class="is-hidden">
902                                                                            <a href="/event_videos">Videos</a>
903                                                                    </li>
904                                                    </ul>
905                                    </li>
906                    </ul>
907        <div class="address">618 Central Ave SW, Albuquerque, NM 87102</div>
908    </footer>
909<script>
910    (() => {
911        const toggles = document.querySelectorAll('.footer-toggle');
912        toggles.forEach((toggle) => {
913            toggle.addEventListener('click', () => {
914                const subnav = toggle.parentElement ? toggle.parentElement.querySelector('.footer-subnav') : null;
915                if (!subnav) {
916                    return;
917                }
918                const isOpen = subnav.classList.toggle('is-open');
919                subnav.setAttribute('aria-hidden', isOpen ? 'false' : 'true');
920                toggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
921            });
922        });
923    })();
924</script>
924
925        </main>
926        <div class="modal" id="event-modal" aria-hidden="true">
927            <div class="modal-shell" role="dialog" aria-modal="true" aria-labelledby="modal-title">
928                <button class="modal-close" type="button" aria-label="Close">×</button>
929                <div class="modal-body" id="modal-body">Loading...</div>
930            </div>
931        </div>
932        
932<script>
933            (() => {
934                const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
935                if (prefersReduced) {
936                    return;
937                }
938
939                const easeInOut = (t) => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t);
940                const animateScroll = (from, to, duration, done) => {
941                    const start = performance.now();
942                    const tick = (now) => {
943                        const elapsed = now - start;
944                        const progress = Math.min(elapsed / duration, 1);
945                        const eased = easeInOut(progress);
946                        window.scrollTo(0, from + (to - from) * eased);
947                        if (progress < 1) {
948                            requestAnimationFrame(tick);
949                        } else if (done) {
950                            done();
951                        }
952                    };
953                    requestAnimationFrame(tick);
954                };
955
956                const getViewportHeight = () => {
957                    if (window.visualViewport && window.visualViewport.height) {
958                        return window.visualViewport.height;
959                    }
960                    return window.innerHeight;
961                };
962
963                const getScrollTarget = () => {
964                    const footer = document.querySelector('.footer');
965                    const footerBottom = footer
966                        ? footer.getBoundingClientRect().bottom + window.scrollY
967                        : 0;
968                    const doc = document.documentElement;
969                    const body = document.body;
970                    const docHeight = Math.max(
971                        doc.scrollHeight,
972                        body.scrollHeight,
973                        doc.offsetHeight,
974                        body.offsetHeight,
975                        doc.clientHeight
976                    );
977                    const viewportHeight = getViewportHeight();
978                    const maxScroll = Math.max(0, Math.min(footerBottom || docHeight, docHeight) - viewportHeight);
979
980                    console.log('Footer bottom:', footerBottom);
981                    console.log('Doc height:', docHeight);
982                    console.log('Viewport height:', viewportHeight);
983                    console.log('Max scroll:', maxScroll);
984
985                    return maxScroll;
986                };
987
988                const isHomePath = () => window.location.pathname === '/' || window.location.pathname === '';
989
990                const runLaunchScroll = () => {
991                    if (!isHomePath()) {
992                        return;
993                    }
994                    const maxScroll = getScrollTarget();
995                    if (maxScroll <= 0) {
996                        return;
997                    }
998                    window.scrollTo(0, 0);
999                    animateScroll(0, maxScroll, 300, () => {
1000                        setTimeout(() => {
1001                            const footer = document.querySelector('.footer');
1002                            if (footer) {
1003                                footer.classList.add('footer-glow');
1004                            }
1005                            document.body.classList.add('launch-shake-violent');
1006                            setTimeout(() => {
1007                                document.body.classList.remove('launch-shake-violent');
1008                                document.body.classList.add('launch-shake');
1009                                animateScroll(maxScroll, 0, 2160, () => {
1010                                    document.body.classList.remove('launch-shake');
1011                                    if (footer) {
1012                                        footer.classList.remove('footer-glow');
1013                                    }
1014                                });
1015                            }, 320);
1016                        }, 250);
1017                    });
1018                };
1019
1020                window.addEventListener('load', () => {
1021                    requestAnimationFrame(() => {
1022                        setTimeout(runLaunchScroll, 120);
1023                    });
1024                });
1025
1026                const rocketLink = document.querySelector('.rocket-link');
1027                if (rocketLink) {
1028                    rocketLink.addEventListener('click', (event) => {
1029                        event.preventDefault();
1030                        const target = getScrollTarget();
1031                        if (target <= 0) {
1032                            return;
1033                        }
1034                        animateScroll(window.scrollY, target, 500);
1035                    });
1036                }
1037
1038                const titleEls = document.querySelectorAll('.event-title');
1039                titleEls.forEach((titleEl) => {
1040                    const textEl = titleEl.querySelector('span');
1041                    if (!textEl) {
1042                        return;
1043                    }
1044                    const updateScroll = () => {
1045                        const overflow = textEl.scrollWidth - titleEl.clientWidth;
1046                        if (overflow > 4) {
1047                            const duration = Math.min(10, Math.max(4, overflow / 60));
1048                            titleEl.style.setProperty('--scroll-distance', `${overflow}px`);
1049                            titleEl.style.setProperty('--scroll-duration', `${duration}s`);
1050                            titleEl.classList.add('is-scrolling');
1051                        } else {
1052                            titleEl.classList.remove('is-scrolling');
1053                        }
1054                    };
1055                    titleEl.addEventListener('mouseenter', updateScroll);
1056                    titleEl.addEventListener('mouseleave', () => {
1057                        titleEl.classList.remove('is-scrolling');
1058                    });
1059                });
1060
1061                const modal = document.getElementById('event-modal');
1062                const modalBody = document.getElementById('modal-body');
1063                const modalClose = modal ? modal.querySelector('.modal-close') : null;
1064                const eventRows = Array.from(document.querySelectorAll('.event-row'));
1065                let frameActive = false;
1066                let activeEventId = null;
1067                const basePath = '/';
1068                const eventPathPrefix = '/event/';
1069                const eventsEndpoint = '/events.php';
1070
1071                if (modalBody) {
1072                    modalBody.addEventListener('click', (event) => {
1073                        const trigger = event.target.closest('.calendars > a');
1074                        if (!trigger) {
1075                            return;
1076                        }
1077                        event.preventDefault();
1078                        const container = trigger.closest('.calendars');
1079                        const options = container ? container.querySelector('#calendar-options') : null;
1080                        if (!options) {
1081                            return;
1082                        }
1083                        const isOpen = options.style.display === 'block';
1084                        options.style.display = isOpen ? 'none' : 'block';
1085                    });
1086
1087                    modalBody.addEventListener('click', (event) => {
1088                        const trigger = event.target.closest('.venuelink');
1089                        if (!trigger) {
1090                            return;
1091                        }
1092                        event.preventDefault();
1093                        const container = trigger.closest('.venue-details');
1094                        const details = container ? container.querySelector('#venue-more') : null;
1095                        if (!details) {
1096                            return;
1097                        }
1098                        const isOpen = details.style.display === 'block';
1099                        details.style.display = isOpen ? 'none' : 'block';
1100                    });
1101                }
1102
1103                const getEventIdFromPath = () => {
1104                    const path = window.location.pathname || '';
1105                    if (!path.startsWith(eventPathPrefix)) {
1106                        return null;
1107                    }
1108                    const id = path.slice(eventPathPrefix.length).split('/')[0];
1109                    return /^[0-9]+$/.test(id) ? id : null;
1110                };
1111
1112                const frameRows = () => {
1113                    const total = eventRows.length;
1114                    if (!total) {
1115                        return;
1116                    }
1117
1118                    const baseScale = 1;
1119                    const frameGap = 28;
1120                    const framePadding = 24;
1121                    const modalShell = modal ? modal.querySelector('.modal-shell') : null;
1122                    const modalRect = modalShell ? modalShell.getBoundingClientRect() : null;
1123                    const modalWidth = modalRect ? modalRect.width : 0;
1124                    const modalHeight = modalRect ? modalRect.height : 0;
1125                    const frameRect = {
1126                        left: framePadding,
1127                        right: window.innerWidth - framePadding,
1128                        top: framePadding,
1129                        bottom: window.innerHeight - framePadding,
1130                    };
1131                    console.log('Modal rect:', modalRect);
1132                    // console.log('Frame offset:', frameOffsetX, frameOffsetY);
1133                    console.log('Frame rect:', frameRect);
1134                    const groups = {
1135                        top: [],
1136                        right: [],
1137                        bottom: [],
1138                        left: [],
1139                    };
1140                    eventRows.forEach((row, index) => {
1141                        const slot = index % 4;
1142                        if (slot === 0) groups.top.push(row);
1143                        if (slot === 1) groups.right.push(row);
1144                        if (slot === 2) groups.bottom.push(row);
1145                        if (slot === 3) groups.left.push(row);
1146                    });
1147
1148                    const randomInRange = (min, max) => min + Math.random() * (max - min);
1149
1150                    const positionRow = (row, side) => {
1151                        const viewportHeight = getViewportHeight();
1152                        const rect = row.getBoundingClientRect();
1153                        const scale = baseScale;
1154                        let targetX = rect.left;
1155                        let targetY = rect.top;
1156                        let rotate = 0;
1157
1158                        if (side === 'top') {
1159                            targetX = randomInRange(frameRect.left, frameRect.right - rect.width * scale);
1160                            targetY = frameRect.top + frameGap - rect.height * scale;
1161                            // targetX = 0;
1162                            // targetY = 0;
1163                        }
1164
1165                        if (side === 'bottom') {
1166                            targetX = randomInRange(frameRect.left, frameRect.right - rect.width * scale);
1167                            targetY = frameRect.bottom - frameGap;
1168                        }
1169
1170                        if (side === 'left') {
1171                            targetX = frameRect.left - frameGap - rect.height * scale - (modalWidth * 0.5);
1172                            if (window.matchMedia('(max-width: 640px)').matches) {
1173                                targetX = frameRect.right * -0.5 + frameGap / 2
1174                            }                            
1175                            targetY = viewportHeight / 2;//randomInRange(frameRect.top, frameRect.bottom - rect.width * scale) + (modalHeight * 0.5); //frameRect.bottom - rect.width * scale) + (modalHeight)
1176                            rotate = -90;
1177                        }
1178
1179                        if (side === 'right') {
1180
1181                            // targetX = frameRect.right - (modalWidth * 1);
1182                            // if (window.matchMedia('(max-width: 640px)').matches) {
1183                            //     targetX = frameRect.right * 0.5
1184                            // }
1185                            // targetY = randomInRange(frameRect.top, frameRect.bottom - rect.width * scale + modalHeight * 1.5);
1186                            // rotate = 90;
1187                            rotate = 90;
1188                            targetX = frameRect.left + frameGap + (modalWidth * 0.5)
1189                            if (window.matchMedia('(max-width: 640px)').matches) {
1190                                targetX = frameRect.right * 0.5
1191                            }                           
1192                            targetY = viewportHeight / 2; //randomInRange(frameRect.top, frameRect.bottom - rect.width * scale) + (modalHeight * 0.5); //frameRect.bottom - rect.width * scale) + (modalHeight)
1193                        }
1194
1195                        // if (side === 'top') {
1196                        //     targetX = randomInRange(frameRect.left, frameRect.right - rect.width * scale);
1197                        //     targetY = frameRect.top + frameGap - rect.height * scale;
1198                        //     // targetX = 0;
1199                        //     // targetY = 0;
1200                        // }
1201
1202                        // if (side === 'bottom') {
1203                        //     targetX = randomInRange(frameRect.left, frameRect.right - rect.width * scale);
1204                        //     targetY = frameRect.bottom - frameGap;
1205                        // }
1206
1207                        // if (side === 'left') {
1208                        //     targetX = frameRect.left - frameGap;
1209                        //     targetY = randomInRange(frameRect.top, frameRect.bottom - rect.width * scale);
1210                        //     rotate = -90;
1211                        // }
1212
1213                        // if (side === 'right') {
1214                        //     targetX = frameRect.right + frameGap;
1215                        //     targetY = randomInRange(frameRect.top, frameRect.bottom - rect.width * scale);
1216                        //     rotate = 90;
1217                        // }
1218
1219                        const deltaX = targetX - rect.left;
1220                        const deltaY = targetY - rect.top;
1221                        row.style.transform = `translate(${deltaX}px, ${deltaY}px) rotate(${rotate}deg) scale(${scale})`;
1222                    };
1223
1224                    groups.top.forEach((row) => positionRow(row, 'top'));
1225                    groups.right.forEach((row) => positionRow(row, 'right'));
1226                    groups.bottom.forEach((row) => positionRow(row, 'bottom'));
1227                    groups.left.forEach((row) => positionRow(row, 'left'));
1228                };
1229
1230                const resetRows = () => {
1231                    eventRows.forEach((row) => {
1232                        row.style.transform = '';
1233                    });
1234                };
1235
1236                const repositionBuy = () => {
1237                    if (!modalBody) {
1238                        return;
1239                    }
1240                    const buy = modalBody.querySelector('.buy');
1241                    if (!buy) {
1242                        return;
1243                    }
1244                    const eventTop = modalBody.querySelector('.event-top');
1245                    const flyer = modalBody.querySelector('.flyer');
1246                    const headerBox = modalBody.querySelector('.header-event-box');
1247                    if (eventTop && flyer && headerBox) {
1248                        eventTop.insertBefore(buy, headerBox);
1249                        return;
1250                    }
1251                    const title = modalBody.querySelector('h1');
1252                    if (title && title.parentElement) {
1253                        title.parentElement.insertBefore(buy, title);
1254                    }
1255                };
1256
1257                const openModal = (html) => {
1258                    if (!modal || !modalBody) {
1259                        return;
1260                    }
1261                    modalBody.innerHTML = html;
1262                    repositionBuy();
1263                    modal.classList.add('is-open');
1264                    modal.setAttribute('aria-hidden', 'false');
1265                    document.body.classList.add('modal-open');
1266                    document.documentElement.classList.add('modal-open');
1267                    if (!frameActive) {
1268                        frameActive = true;
1269                        setTimeout(() => {
1270                            requestAnimationFrame(frameRows);    
1271                        }, 500);
1272                        
1273                    }
1274                };
1275                const closeModal = () => {
1276                    if (!modal) {
1277                        return;
1278                    }
1279                    modal.classList.remove('is-open');
1280                    modal.setAttribute('aria-hidden', 'true');
1281                    document.body.classList.remove('modal-open');
1282                    document.documentElement.classList.remove('modal-open');
1283                    if (activeEventId) {
1284                        history.pushState({ eventId: null }, '', basePath);
1285                        activeEventId = null;
1286                    }
1287                    if (frameActive) {
1288                        resetRows();
1289                        frameActive = false;
1290                    }
1291                };
1292                if (modal && modalClose) {
1293                    modal.addEventListener('click', (event) => {
1294                        if (event.target === modal) {
1295                            closeModal();
1296                        }
1297                    });
1298                    modalClose.addEventListener('click', closeModal);
1299                    document.addEventListener('keydown', (event) => {
1300                        if (event.key === 'Escape') {
1301                            closeModal();
1302                        }
1303                    });
1304                }
1305
1306                document.querySelectorAll('.event-row').forEach((row) => {
1307                    row.addEventListener('click', async () => {
1308                        const eventId = row.getAttribute('data-event-id');
1309                        if (!eventId) {
1310                            return;
1311                        }
1312                        activeEventId = eventId;
1313                        history.pushState({ eventId }, '', `${eventPathPrefix}${eventId}`);
1314                        openModal('Loading...');
1315                        try {
1316                            const response = await fetch(`${eventsEndpoint}?event_id=${encodeURIComponent(eventId)}`);
1317                            console.log('Fetch response:', response);
1318                            // if (!response.ok) {
1319                            //     throw new Error('Request failed');
1320                            // }
1321                            const html = await response.text();
1322                            openModal(html);
1323                        } catch (error) {
1324                            openModal('Unable to load event details right now.');
1325                        }
1326                    });
1327                });
1328
1329                window.addEventListener('popstate', (event) => {
1330                    const stateEventId = event.state && event.state.eventId ? String(event.state.eventId) : null;
1331                    const pathEventId = getEventIdFromPath();
1332                    const nextEventId = stateEventId || pathEventId;
1333                    if (!nextEventId) {
1334                        if (modal && modal.classList.contains('is-open')) {
1335                            closeModal();
1336                        }
1337                        return;
1338                    }
1339                    if (nextEventId === activeEventId && modal && modal.classList.contains('is-open')) {
1340                        return;
1341                    }
1342                    activeEventId = nextEventId;
1343                    openModal('Loading...');
1344                    fetch(`${eventsEndpoint}?event_id=${encodeURIComponent(nextEventId)}`)
1345                        .then((response) => response.text())
1346                        .then((html) => openModal(html))
1347                        .catch(() => openModal('Unable to load event details right now.'));
1348                });
1349
1350                const initialEventId = getEventIdFromPath();
1351                if (initialEventId) {
1352                    activeEventId = initialEventId;
1353                    history.replaceState({ eventId: initialEventId }, '', `${eventPathPrefix}${initialEventId}`);
1354                    openModal('Loading...');
1355                    fetch(`${eventsEndpoint}?event_id=${encodeURIComponent(initialEventId)}`)
1356                        .then((response) => response.text())
1357                        .then((html) => openModal(html))
1358                        .catch(() => openModal('Unable to load event details right now.'));
1359                }
1360            })();
1361        </script>
1361
1362    </body>
1363</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.