PageSourceSearch

https://www.stmartinathletics.com/calendar

html stmartinathletics.com collected 2026-10-04 02:44:25 UTC 152,765 bytes, 2,787 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en">
3<head>
4<style>
5    .gam-sport-banner-ad iframe,
6    .gam-sport-banner-ad-2 iframe
7    {
8        width: 100%;
9        height: auto;
10    }
11
12    .prog-mobile-banners #gam-banner-ad,
13    .prog-mobile-banners #gam-banner-ad-2
14    {
15        min-height: 100px;
16        display: flex;
17        align-items: center;
18        justify-content: center;
19    }
20
21    /* Desktop presenting sponsor: cap at native 300x75. */
22    .gam-presenting-sponsor-2,
23    .gam_ps {
24        max-width: 300px;
25        max-height: 75px;
26        margin: 0 auto;
27        overflow: hidden;
28    }
29
30    .gam-presenting-sponsor-2 iframe,
31    .gam_ps iframe {
32        width: 100%;
33        height: 100%;
34    }
35
36    /* Layout 19 desktop presenting sponsor.
37       The slot is defined as a fixed 300x75 (defineSlot below), so give the iframe its
38       full 300x75 viewport and paint it at 2/3 (200x50) with a transform — same pattern
39       as the mobile slot. The old width:200px!important squeezed the iframe VIEWPORT to
40       200 while the creative document inside stayed 300 wide, clipping the right third
41       of every creative ("Piedmont" -> "Piedm"). The container rules reserve the flex
42       slot so the priority nav measures correctly before the ad loads; GAM tracking is
43       unaffected (the creative loads at native size, it just paints smaller). */
44    .presenting-sponsor-desktop-19 {
45        width: 212px;
46        min-width: 212px;
47        overflow: hidden;
48    }
49    .presenting-sponsor-desktop-19 .gam-presenting-sponsor-2 {
50        width: 200px;
51        height: 50px;
52        max-width: 200px;
53        max-height: 50px;
54        overflow: hidden;
55        position: relative;
56    }
57    .presenting-sponsor-desktop-19 .gam-presenting-sponsor-2 iframe {
58        width: 300px !important;
59        /* beat the generic img/iframe max-width:100% (would cap the viewport at the
60           200px container and clip the creative's right third) */
61        max-width: none !important;
62        height: 75px !important;
63        transform: scale(0.6667);
64        transform-origin: top left;
65        border: 0;
66    }
67
68    /* AB-6152: Bootstrap-3 header menus (Style 4/8/9/15/17) render the desktop
69       sponsor inside .presenting-sponsor-mobile-menu, whose template LESS floats
70       #gam-presenting-sponsor-2 off-screen (margin:0 -200px auto; width:250px) — so
71       it's hidden until you scroll and can run off the side / drop below the nav.
72       This GAM <style> loads BEFORE template main.css, so a class rule can't beat the
73       LESS on source order; we beat it on SPECIFICITY by including the slot id
74       (.class #id = 1,1,0 > the LESS .a .b .c = 0,3,0). Pin the slot to the same
75       200x50 right-aligned, clipped box template 19 uses so it stays in the viewport,
76       in both the rest and .fixedbar states. Scoped to .presenting-sponsor-mobile-menu,
77       so template 19 (.presenting-sponsor-desktop-19) is untouched. */
78    /* DIV wrapper = Style 15 family (the wrap is a div after the menu ul).
79       Absolute + translateY instead of float:right — the float top-aligned the
80       50px slot in the ~76px menu bar, so it rode visibly higher than the nav
81       links ("doesn't line up"). The nearest positioned ancestor is the header
82       .container (position:relative), which spans the bar's full height, so
83       top:50% centers the sponsor on the same line as the links in both the
84       resting and .fixedbar states. */
85    div.presenting-sponsor-mobile-menu #gam-presenting-sponsor-2 {
86        position: absolute;
87        right: 15px;
88        top: 50%;
89        transform: translateY(-50%);
90        float: none;
91        width: 200px;
92        max-width: 200px;
93        height: 50px;
94        max-height: 50px;
95        margin: 0;
96        overflow: hidden;
97    }
98    /* AB-6152 follow-up (template 5 / Style 15 family): the absolute rule above only
99       holds if an ancestor of the slot is positioned, so right:15px/top:50% anchor to
100       the header .container. Template 5's main.less sets `.custom-nav .navbar
101       { position: inherit }`, which makes the navbar STATIC and removes BS3's default
102       position:relative — so in the resting (unscrolled) state NO ancestor is
103       positioned and the slot anchors to the viewport, dropping the sponsor on top of
104       the nav links. (Scrolled, the position:fixed .fixedbar became the containing
105       block and it looked fine — hence the intermittent behavior.) Re-establish the
106       containing block AB-6152 assumes, for both states. Scoped to .custom-nav so only
107       the Style 15 header family is affected; a no-op for the li-variant (Style 8/9),
108       whose slot is position:relative (in-flow), not absolute. */
109    .custom-nav #nav-container {
110        position: relative;
111    }
112    /* AB-6152 follow-up #2 (Style-15 family, all-dropdown navs): when the greedy collapser
113       in topmenu2.js runs out of movable items — every remaining item is a .dropdown, which
114       it won't nest into MORE — but the nav still reaches the presenting sponsor, it tags the
115       header .nav-compact (then .nav-compact-2 if one tier isn't enough). That tightens the
116       nav just enough to clear the ad. Applied ONLY in that jammed case and cleared on resize,
117       so sparse navs keep their full padding and text size (and the larger-text preference).
118       Tier 1 trims horizontal padding only — text size is untouched; tier 2 is the last resort
119       and only then nudges letter-spacing. Loaded before template main.css, so we win on
120       specificity (id + 2 classes) + !important, same as the rules above. */
121    .custom-nav.nav-compact #nav-links > li > a {
122        padding-left: 9px !important;
123        padding-right: 9px !important;
124    }
125    .custom-nav.nav-compact.nav-compact-2 #nav-links > li > a {
126        padding-left: 5px !important;
127        padding-right: 5px !important;
128        letter-spacing: -0.2px;
129    }
130    /* LI wrapper = Style 8/9 (the sponsor is an inline li in the greedy #nav-links).
131       Keep it in flow — the nav JS reserves its width; absolute would collapse the li. */
132    li.presenting-sponsor-mobile-menu #gam-presenting-sponsor-2 {
133        float: right;
134        width: 200px;
135        max-width: 200px;
136        height: 50px;
137        max-height: 50px;
138        margin: 0;
139        overflow: hidden;
140        position: relative;
141    }
142    .presenting-sponsor-mobile-menu #gam-presenting-sponsor-2 iframe {
143        /* Full 300x75 viewport scaled to 200x50 — a 200px viewport clips the right
144           third of the 300-wide creative document (same bug as the t19 rule above). */
145        width: 300px !important;
146        max-width: none !important;
147        height: 75px !important;
148        transform: scale(0.6667);
149        transform-origin: top left;
150        border: 0;
151    }
152
153    /* Mobile presenting sponsor: GAM serves a 300x75 creative, so visually
154       scale the whole iframe down to fit the header next to the logo + nav
155       + hamburger. The iframe still loads at native 300x75 so impressions,
156       click tracking, and viewability reporting fire correctly — it just
157       paints smaller. (Pattern ported from the State Association sites.) */
158    #gam-presenting-sponsor-mobile {
159        width: 200px;
160        height: 50px;
161        overflow: hidden;
162        position: relative;
163        margin: 0;
164    }
165    #gam-presenting-sponsor-mobile iframe {
166        width: 300px !important;
167        max-width: none !important;
168        height: 75px !important;
169        transform: scale(0.6667);
170        transform-origin: top left;
171        border: 0;
172    }
173    @media (max-width: 380px) {
174        #gam-presenting-sponsor-mobile {
175            width: 160px;
176            height: 40px;
177        }
178        #gam-presenting-sponsor-mobile iframe {
179            transform: scale(0.5333);
180        }
181    }
182
183    /* Template 19 mobile: the sponsor has its own full-width row below the nav,
184       so don't clamp it to the inline box the other templates use.
185       Class+id specificity beats the bare #id rules above, including the 380px breakpoint. */
186    .presenting-sponsor-mobile-19 #gam-presenting-sponsor-mobile {
187        width: auto;
188        max-width: 100%;
189        height: 64px;
190    }
191
192    /* ===== PRESENTING SPONSOR FOLLOWS EACH TEMPLATE'S NATIVE NAV =====
193       No universal breakpoint. The desktop slot (.gam-presenting-sponsor-2) shows while
194       the header is in desktop mode and the mobile slot (#gam-presenting-sponsor-mobile)
195       shows once it collapses — exactly the Bootstrap visibility classes each header
196       already carries (BS3: hidden-sm hidden-xs / hidden-md hidden-lg; BS4/5: d-none
197       d-md-block / d-block d-md-none). The JS below fills whichever slot the CSS shows,
198       so per-template breakpoints are honored automatically. For the greedy "MORE" nav
199       (Style 8/9/15) the desktop sponsor is an inline <li>; nudgeGreedyNav() re-runs
200       AdjustNav() after the GAM creative paints so the nav reserves the ad's real width
201       and pushes overflow links into MORE instead of wrapping the sponsor below the nav.
202       (An earlier "force mobile sponsor at <=992 everywhere" rule lived here; it was
203       reverted because it misplaced the mobile slot on desktop-nav templates.) */
204
205</style>
206
207
208
209    
209<script async src="https://securepubads.g.doubleclick.net/tag/js/gpt.js"></script>
209
210    
210<script>
211        window.googletag = window.googletag || { cmd: [] };
212
213        function isMobile() {
214            return window.innerWidth <= 768;
215        }
216
217        // The greedy "MORE" nav (topmenu.js, Header Style 8/9/15) lays out BEFORE the GAM
218        // presenting-sponsor iframe paints, so it never reserves the ad's width and the
219        // sponsor wraps to a line below the nav. Re-running AdjustNav() once the creative is
220        // sized makes the nav recount the sponsor <li> and tuck overflow links into MORE,
221        // keeping the sponsor inline. No-op on templates without the greedy nav (AdjustNav
222        // is undefined there), so it's safe to call unconditionally.
223        function nudgeGreedyNav() {
224            if (typeof AdjustNav === 'function') {
225                try { AdjustNav(); } catch (e) { /* greedy nav not present on this template */ }
226            }
227        }
228
229        googletag.cmd.push(function () {
230            var isMobileDevice = isMobile();
231            var REFRESH_KEY = 'refresh';
232            var REFRESH_VALUE = 'true';
233
234            // NEW: programmatic flag + refresh timing
235            var useProgrammaticAds = false;
236            // 30s is Google's minimum refresh interval for any slot AdX can fill do not lower
237            var REFRESH_MS = 30000;
238
239            // NEW: add a body class only when programmatic + mobile (for stable layout)
240            if (useProgrammaticAds && isMobileDevice) {
241                document.body.classList.add('prog-mobile-banners');
242            }
243
244            // ------- PRESENTING SPONSOR-------
245            // Define BOTH slots unconditionally. Defining a slot does NOT request an ad
246            // (only display()/refresh() does), and the responsive-fill block below
247            // displays exactly ONE at a time — so this adds no load-time impressions.
248            // The old isMobileDevice (innerWidth<=768) branch defined only one slot for
249            // the page's life; combined with CSS that switches the sponsor container at
250            // 992px, that stranded 769-991px on a visible-but-empty slot (the tablet dead
251            // zone). We now align the fill to the 992 CSS boundary (see below).
252            var sponsorSlotsById = {};
253            sponsorSlotsById['gam-presenting-sponsor-mobile'] = googletag.defineSlot('/22870419559/headerwebmobile', [[300, 75]], 'gam-presenting-sponsor-mobile')
254                .setTargeting(REFRESH_KEY, REFRESH_VALUE)
255                .addService(googletag.pubads());
256            sponsorSlotsById['gam-presenting-sponsor-2'] = googletag.defineSlot('/22870419559/headerwebdesktop', [[300, 75]], 'gam-presenting-sponsor-2')
257                .setTargeting(REFRESH_KEY, REFRESH_VALUE)
258                .addService(googletag.pubads());
259
260            // Build base arrays of allowed sizes
261            var desktopTabletProgrammatic = [[640, 100], [728, 90]];
262            var mobileProgrammatic = [[320, 50]];              // << mobile = 320x50 ONLY
263            var desktopTabletDefault = [[640, 100]];
264            var mobileDefault = [[640, 100]];
265
266            var allProgrammaticSizes = [[640, 100], [728, 90], [320, 50]];
267            var allDefaultSizes = [[640, 100]];
268
269            var bannerMapping = googletag.sizeMapping()
270                .addSize([1024, 0], useProgrammaticAds ? desktopTabletProgrammatic : desktopTabletDefault) // desktop
271                .addSize([768, 0], useProgrammaticAds ? desktopTabletProgrammatic : desktopTabletDefault) // tablet
272                .addSize([0, 0], useProgrammaticAds ? mobileProgrammatic : mobileDefault)        // phones
273                .build();
274
275            googletag.defineSlot(
276                '/22870419559/bannerweb',
277                useProgrammaticAds ? allProgrammaticSizes : allDefaultSizes,
278                'gam-banner-ad'
279            )
280                .defineSizeMapping(bannerMapping)
281                .setTargeting(REFRESH_KEY, REFRESH_VALUE)
282                .addService(googletag.pubads());
283
284            googletag.defineSlot(
285                '/22870419559/bannerweb',
286                useProgrammaticAds ? allProgrammaticSizes : allDefaultSizes,
287                'gam-banner-ad-2'
288            )
289                .defineSizeMapping(bannerMapping)
290                .setTargeting(REFRESH_KEY, REFRESH_VALUE)
291                .addService(googletag.pubads());
292
293            googletag.defineSlot('/22870419559/agent', [[300, 75]], 'gam-agent-ad')
294                .setTargeting(REFRESH_KEY, REFRESH_VALUE)
295                .addService(googletag.pubads());
296
297            googletag.pubads().setTargeting('siteid', '958');
298            googletag.pubads().setTargeting('isschoolpay', '0');
299
300            googletag.pubads().addEventListener('impressionViewable', function (event) {
301                var slot = event.slot;
302                if (slot.getTargeting(REFRESH_KEY).indexOf(REFRESH_VALUE) > -1) {
303                    setTimeout(function () {
304                        googletag.pubads().refresh([slot]);
305                    }, REFRESH_MS);
306                }
307            });
308
309            googletag.enableServices();
310
311            // ------- PRESENTING SPONSOR: responsive fill (AB-6152 follow-up) -------
312            // The desktop/mobile split is owned entirely by each header's NATIVE Bootstrap
313            // visibility classes (no universal @media here anymore). We fill whichever slot
314            // the CSS currently shows, and re-fill on resize so a breakpoint cross is never
315            // stranded on an empty slot. Only ONE slot is displayed at a time, so load-time
316            // impression volume is unchanged — the filled slot is always the VISIBLE (and
317            // viewable) one. For the greedy "MORE" nav the desktop sponsor is an inline <li>;
318            // nudgeGreedyNav() (called after the creative paints) re-runs AdjustNav so the nav
319            // reserves the ad's width and keeps it inline instead of wrapping it below.
320            (function () {
321                var sponsorDisplayed = { 'gam-presenting-sponsor-2': false, 'gam-presenting-sponsor-mobile': false };
322                // Is the element actually rendered (not display:none on it or any ancestor)?
323                function isShown(el) { return !!(el && (el.offsetParent !== null || el.getClientRects().length)); }
324                // Fill whichever slot the CSS currently shows. The desktop/mobile split is owned
325                // entirely by the header CSS (the @media block above sets <=992 -> mobile on the
326                // standard menus; layout 19 keeps its reserved desktop slot, etc.), so the JS just
327                // follows it — no width is hard-coded here, and template-specific breakpoints
328                // (e.g. 19's reserved slot) are honored automatically. Fall back to a 993 width
329                // split only if neither container has been laid out yet.
330                function activeSponsorId() {
331                    var d = document.getElementById('gam-presenting-sponsor-2');
332                    var m = document.getElementById('gam-presenting-sponsor-mobile');
333                    if (isShown(d)) return 'gam-presenting-sponsor-2';
334                    if (isShown(m)) return 'gam-presenting-sponsor-mobile';
335                    if (!d && !m) return null;
336                    return window.innerWidth >= 993 ? 'gam-presenting-sponsor-2' : 'gam-presenting-sponsor-mobile';
337                }
338                function fillActiveSponsor() {
339                    var id = activeSponsorId();
340                    if (!id || !document.getElementById(id)) return;   // this template doesn't render that slot
341                    var slot = sponsorSlotsById[id];
342                    if (!slot) return;
343                    if (!sponsorDisplayed[id]) {
344                        googletag.display(id);
345                        sponsorDisplayed[id] = true;
346                    } else {
347                        googletag.pubads().refresh([slot]);     // already shown once -> re-serve on return
348                    }
349                }
350                function whenReady(fn) {
351                    if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', fn);
352                    else fn();
353                }
354                whenReady(fillActiveSponsor);
355                // Re-fill the now-visible slot after a resize crosses any template's CSS breakpoint.
356                var resizeTimer;
357                window.addEventListener('resize', function () {
358                    clearTimeout(resizeTimer);
359                    resizeTimer = setTimeout(fillActiveSponsor, 200);
360                });
361            })();
362
363            // Add event listeners for responsive image handling
364            document.addEventListener('DOMContentLoaded', function () {
365                handleResponsiveImages();
366
367                // Add debounced resize handler
368                var resizeTimeout = null;
369                window.addEventListener('resize', function () {
370                    if (resizeTimeout) {
371                        clearTimeout(resizeTimeout);
372                    }
373
374                    resizeTimeout = setTimeout(function () {
375                        handleResponsiveImages();
376                    }, 250);
377                });
378            });
379
380            // Add slotRenderEnded event to handle styling right after ads render
381            googletag.pubads().addEventListener('slotRenderEnded', function (event) {
382                // Give a small delay to ensure content is available
383                setTimeout(function () {
384                    var id = event.slot.getSlotElementId();
385                    var container = document.getElementById(id);
386                    if (container) {
387                        var iframes = container.querySelectorAll('iframe[id^="google_ads_iframe"]');
388                        iframes.forEach(applyResponsiveStyles);
389                    }
390                    if (id === 'gam-presenting-sponsor-2') {
391                        // Belt-and-suspenders for the greedy nav: re-run after the creative has
392                        // settled, covering the cross-origin safe-frame path where
393                        // fitPresentingSponsor (and thus its inline nudge) can't measure the ad.
394                        setTimeout(nudgeGreedyNav, 250);
395                    }
396                }, 50);
397            });
398
399            // Function to handle responsive images
400            function handleResponsiveImages() {
401                ['gam-banner-ad', 'gam-banner-ad-2', 'gam-sport-banner-ad', 'gam-sport-banner-ad-2', 'gam-presenting-sponsor-2', 'gam-presenting-sponsor-mobile'].forEach(adId => {
402                    var adContainer = document.querySelector(`#${adId}`);
403                    if (adContainer) {
404                        observeIframeInsertion(adContainer);
405                        var iframes = adContainer.querySelectorAll('iframe[id^="google_ads_iframe"]');
406                        iframes.forEach(applyResponsiveStyles);
407                    }
408                });
409            }
410
411            // Function to observe iframe insertion - from original code
412            function observeIframeInsertion(container) {
413                var observer = new MutationObserver(function (mutations) {
414                    mutations.forEach(function (mutation) {
415                        if (mutation.addedNodes) {
416                            mutation.addedNodes.forEach(function (node) {
417                                if (node.tagName === 'IFRAME' && node.id.startsWith('google_ads_iframe')) {
418                                    applyResponsiveStyles(node);
419                                    observeIframeChanges(node);
420                                }
421                            });
422                        }
423                    });
424                });
425
426                observer.observe(container, {
427                    childList: true,
428                    subtree: true
429                });
430            }
431
432            function applyResponsiveStyles(iframe) {
433                if (!iframe) return;
434
435                // Presenting sponsor (desktop AND mobile, ALL templates): one proportional
436                // fit — scale the creative to its reserved nav slot, no crop. (Previously this
437                // was template-19-only; every other template clipped via the default box.)
438                if (iframe.closest('.gam-presenting-sponsor-2') || iframe.closest('#gam-presenting-sponsor-mobile')) {
439                    fitPresentingSponsor(iframe);
440                    return;
441                }
442
443                // Banner / sport-banner ads — unchanged.
444                if (
445                    iframe.closest('.gam-banner-ad') ||
446                    iframe.closest('.gam-banner-ad-2') ||
447                    iframe.closest('.gam-sport-banner-ad') ||
448                    iframe.closest('.gam-sport-banner-ad-2')
449                ) {
450                    var isTemplate19 = !!document.querySelector('.sticky-header-19');
451                    var isTemplate19Banner = isTemplate19 && iframe.closest('.gam-banner-ad');
452
453                    if (isMobile() && !isTemplate19Banner) {
454                        iframe.style.width = '100%';
455                        iframe.style.height = 'auto';
456                        try {
457                            var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
458                            // Template 19's top banner sits at the very top of the sticky
459                            // header with nothing overlapping it; the 20% push-down other
460                            // templates use just renders as dead white space above the ad.
461                            iframeDoc.querySelectorAll('img').forEach(function (img) {
462                                img.style.maxWidth = '100%';
463                                img.style.height = 'auto';
464                                img.style.marginTop = iframe.closest('.gam-banner-ad') ? '20%' : '0';
465                            });
466                        } catch (e) {
467                            console.error('Could not access iframe content:', e);
468                        }
469                    }
470
471                    // Template 19's top banner ad: pin the iframe to the creative's true
472                    // rendered height on EVERY device, not just mobile (AB-6411 — the
473                    // sticky ad row is a fixed 122px box on desktop; see main.less/
474                    // CSSStyle19). Set inline with !important so it wins regardless of
475                    // CSS state — GAM ad sizing lives here in JS, not in template CSS,
476                    // which is easy to defeat via selector specificity drift (this exact
477                    // element had multiple overlapping height:auto rules quietly taking
478                    // turns winning).
479                    if (isTemplate19Banner) {
480                        try {
481                            var iframeDoc19 = iframe.contentDocument || iframe.contentWindow.document;
482                            if (iframeDoc19.documentElement) { iframeDoc19.documentElement.style.margin = '0'; iframeDoc19.documentElement.style.padding = '0'; }
483                            if (iframeDoc19.body) { iframeDoc19.body.style.margin = '0'; iframeDoc19.body.style.padding = '0'; }
484                            var bannerImg = iframeDoc19.querySelector('img');
485                            var fitBannerHeight = function () {
486                                if (!bannerImg.naturalWidth) return;
487                                var w = iframe.getBoundingClientRect().width;
488                                var h = Math.round(w * bannerImg.naturalHeight / bannerImg.naturalWidth);
489                                if (h > 0) iframe.style.setProperty('height', h + 'px', 'important');
490                            };
491                            if (bannerImg) {
492                                bannerImg.style.maxWidth = '100%';
493                                bannerImg.style.height = 'auto';
494                                bannerImg.style.display = 'block';
495                                bannerImg.style.marginTop = '0';
496                                if (bannerImg.complete && bannerImg.naturalWidth) { fitBannerHeight(); }
497                                else { bannerImg.addEventListener('load', fitBannerHeight); }
498                            }
499                        } catch (e) {
500                            console.error('Could not access iframe content:', e);
501                        }
502                    }
503                }
504            }
505
506            // Scale the presenting sponsor to fit its reserved nav slot from the creative's
507            // TRUE dimensions, preserving aspect ratio (never crop). Generalized from the old
508            // template-19-only version so EVERY template gets the same treatment. Per the
509            // business-rules GAM section, sizing lives here in JS — CSS can't reach the creative
510            // inside the friendly iframe. The iframe still loads the native creative so GAM
511            // impression/click/viewability tracking fires correctly; we only change how it paints.
512            function fitPresentingSponsor(iframe) {
513                var container = iframe.closest('.gam-presenting-sponsor-2, #gam-presenting-sponsor-mobile');
514                if (!container) return;
515                var isMobileSlot = container.id === 'gam-presenting-sponsor-mobile';
516
517                // Target box = the slot each template reserves in its nav. Read it from the
518                // rendered container; fall back / sanity-cap so an unbounded (e.g. max-width:none)
519                // or not-yet-sized container can't blow the ad out across the nav.
520                var boxW = container.clientWidth;
521                var boxH = container.clientHeight;
522                if (!boxW || boxW < 40 || boxW > 400) boxW = isMobileSlot ? Math.max(200, window.innerWidth - 24) : 240;
523                if (!boxH || boxH < 20 || boxH > 120) boxH = isMobileSlot ? 64 : 72;
524
525                function apply(nativeW, nativeH) {
526                    if (!nativeW || !nativeH) return;
527                    // Fit WITHIN the box on both dimensions, preserving aspect ratio — no crop.
528                    var scale = Math.min(boxW / nativeW, boxH / nativeH);
529                    iframe.style.setProperty('width', nativeW + 'px', 'important');
530                    iframe.style.setProperty('height', nativeH + 'px', 'important');
531                    iframe.style.setProperty('transform', 'scale(' + scale + ')', 'important');
532                    iframe.style.transformOrigin = 'top left';
533                    // display:block so the iframe ignores inherited line-height (e.g. 85px on
534                    // template 14's .upper-side) and its own vertical-align:bottom, which push an
535                    // inline iframe DOWN inside the slot and let overflow:hidden clip the bottom.
536                    iframe.style.setProperty('display', 'block', 'important');
537                    // Collapse the container to the painted size so there's no gap or overflow.
538                    container.style.width = Math.round(nativeW * scale) + 'px';
539                    container.style.height = Math.round(nativeH * scale) + 'px';
540                    container.style.overflow = 'hidden';
541                    // Desktop sponsor sits inline in the greedy nav — now that it has a real
542                    // width, let the nav reserve it (pushes overflow links into MORE).
543                    if (!isMobileSlot) nudgeGreedyNav();
544                }
545
546                try {
547                    var doc = iframe.contentDocument || iframe.contentWindow.document;
548                    var img = doc && doc.querySelector('img');
549                    if (img) {
550                        // GAM's friendly iframe ships an 8px <body> margin that nudges the creative
551                        // down/right (then overflow:hidden crops it). Zero margins + block-level the
552                        // image to kill the inline baseline gap, then measure true dimensions.
553                        if (doc.documentElement) { doc.documentElement.style.margin = '0'; doc.documentElement.style.padding = '0'; }
554                        if (doc.body) { doc.body.style.margin = '0'; doc.body.style.padding = '0'; }
555                        img.style.display = 'block';
556                        img.style.maxWidth = 'none';
557                        img.style.width = 'auto';
558                        img.style.height = 'auto';
559                        if (img.complete && img.naturalWidth) {
560                            apply(img.naturalWidth, img.naturalHeight);
561                        } else {
562                            img.addEventListener('load', function () {
563                                apply(img.naturalWidth, img.naturalHeight);
564                            });
565                        }
566                    }
567                } catch (e) {
568                    // Cross-origin (safe-frame) creative — can't measure it; leave the CSS default.
569                    console.error('Could not size presenting sponsor:', e);
570                }
571            }
572
573            function observeIframeChanges(iframe) {
574                iframe.addEventListener('load', function () {
575                    applyResponsiveStyles(iframe);
576                });
577
578                var observer = new MutationObserver(function (mutations) {
579                    mutations.forEach(function (mutation) {
580                        if (mutation.type === 'childList' || (mutation.type === 'attributes' && mutation.attributeName === 'src')) {
581                            applyResponsiveStyles(iframe);
582                        }
583                    });
584                });
585
586                observer.observe(iframe, {
587                    childList: true,
588                    subtree: true,
589                    attributes: true,
590                    attributeFilter: ['src']
591                });
592            }
593        });
594    </script>
594
595
596    <!-- End GPT Tag -->
597        <!-- Google tag (gtag.js) -->
vendor: 73 bytes, lines 597-598
597
598        <script async src="https://www.googletagmanager.com/gtag/js?id=
598G-KWN6WNQ89R
vendor: 21 bytes, lines 598-599
598"></script>
599        
599<script>
600            
vendor: 171 bytes, lines 600-604
600window.dataLayer = window.dataLayer || [];
601            function gtag() { dataLayer.push(arguments); }
602            gtag('js', new Date());
603
604            gtag('config', '
604G-KWN6WNQ89R
vendor: 13 bytes, lines 604-605
604');
605        
605</script>
605
606    
607
608    <meta charset="utf-8" />
609    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=2.0, user-scalable=yes" />
610    <title>St. Martin High School Yellow jackets Athletics Calendar | St. Martin High School (Ocean Springs, MS)</title>
611    <meta name="description" content="Stay up-to-date with the St. Martin Yellow jackets athletics calendar. View upcoming sports events, game dates, and important school activities." />
612    <meta name="keywords" content="st. martin high school, yellow jackets, athletics calendar, school sports calendar, st. martin high school yellow jackets calendar, high school sports events, st. martin high school sports schedule" />
613    <meta property="og:image" content="https://5starassets.blob.core.windows.net/athleticsites/958/91/images/9f55438e-5510-4fa8-adc9-5828b9add3d6.png">
614    <link rel="canonical" href="https://www.stmartinathletics.com/calendar" />
615<meta name="robots" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1" />
616    
616<script type="application/ld+json">{"@context":"https://schema.org","@type":"SportsOrganization","name":"St. Martin High School","url":"https://www.stmartinathletics.com","logo":"https://5starassets.blob.core.windows.net/athleticsites/958/91/images/9f55438e-5510-4fa8-adc9-5828b9add3d6.png","description":"Stay up-to-date with the St. Martin Yellow jackets athletics calendar. View upcoming sports events, game dates, and important school activities.","alternateName":"St. Martin High School Yellow jackets","address":{"@type":"PostalAddress","addressLocality":"Ocean Springs","addressRegion":"MS"}}</script>
616
617    
617<script type="application/ld+json">{"@context":"https://schema.org","@type":"WebSite","name":"St. Martin High School","url":"https://www.stmartinathletics.com","potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://www.stmartinathletics.com/search?keyword={search_term_string}"},"query-input":"required name=search_term_string"}}</script>
617
618
619    
620    
621        
621<script src="https://unpkg.com/focus-visible/dist/focus-visible.min.js"></script>
621
622        <!-- latest CDN compiled and minified CSS for lity (simple lightbox) -->
623        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/lity/2.3.1/lity.min.css" integrity="sha256-0SZxASYAglrmIuTx+ZYHE3hzTnCZWB7XLu+iA8AG0Z0=" crossorigin="anonymous" />
624        <!-- latest CDN compiled and minified CSS for bootstrap 3 -->
625        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
626        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
627        <!-- latest CDN compiled and minified CSS for slick slider -->
628        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick.min.css" integrity="sha256-UK1EiopXIL+KVhfbFa8xrmAWPeBjMVdvYMYkTAEv/HI=" crossorigin="anonymous" />
629        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick-theme.min.css" integrity="sha256-4hqlsNP9KM6+2eA8VUT0kk4RsMRTeS7QGHIM+MZ5sLY=" crossorigin="anonymous" />
630        <!-- latest CDN compiled and minified CSS for font awesome -->
631        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" integrity="sha256-NuCn4IvuZXdBaFKJOAcsU2Q3ZpwbdFisd5dux4jkQ5w=" crossorigin="anonymous" />
632        <!-- locally stored compiled and minified CSS for yamm -->
633        <link rel="stylesheet" href="/lib/yamm3/yamm/yamm.min.css" />
634        <link rel="stylesheet" href="/lib/datatables/media/css/dataTables.bootstrap.min.css" />
635        <link rel="stylesheet" href="/less/templates/1/main.min.css?v=2.3" />
636        <link rel="icon" type="image/png" href="https://5starassets.blob.core.windows.net/athleticsites/958/91/images/9f55438e-5510-4fa8-adc9-5828b9add3d6.png">
637        <link href="/lib/sweetalert/dist/sweetalert.css" rel="stylesheet" />
638        <link rel="stylesheet" href="/less/Components/AIAgent.min.css" />
639
640    
641    
642            <style>
643        h1{color: #01058a;}
644        body{background: url(https://5starassets.blob.core.windows.net/athleticsites/958/91/images/2aa8152d-18d3-4100-aaed-93abfda2bedf.jpg);}
645        .cd-main-content{background-image:url(https://5starassets.blob.core.windows.net/athleticsites/958/91/images/);}
646        @media (max-width: 500px){
647            #calendar-link{background-color: #01058a;}
648        }
649        #calendar-link > span{color:#01058a;}
650        .header-topper:before{background:#01058a;}
651        .header-topper .row:before {background:#01058a;}
652        .bg-primary{background-color: #01058a;}
653        .bg-secondary{background-color: #f4d214;}
654        .bg-gradient-primary-dark{background-image: linear-gradient(180deg,#000,#01058a);}
655        .text-primary{color: #01058a !important;}
656        .text-secondary{color: #f4d214 !important;}
657        .text-primary-font{color: #ffffff;}
658        .right-angle-primary{border-color: rgba(255,255,255,0) #01058a transparent #01058a;}
659        .left-angle-secondary{border-color: #fff #f4d214 transparent transparent;}
660        .border-all-thin-primary{border: solid 1px #01058a;}
661        .border-all-xl-primary{border: 20px solid #01058a;}
662        .border-all-sm-secondary{border: 2px solid #f4d214;}
663        .border-right-xl-primary{border-right: 20px solid #01058a;}
664        .border-right-xl-secondary{border-right: 20px solid #f4d214;}
665        .border-top-sm-secondary{border-top: 2px solid #f4d214 !important;}
666        .border-bottom-sm-secondary{border-bottom: 2px solid #f4d214 !important;}
667        .pins span:before,.pins span:after{border-top: 4px solid #01058a; border-bottom: 4px solid #f4d214;}
668        .angle-primary-secondary{border-color: #01058a #f4d214 #01058a #f4d214;}
669        .team-menu .navbar-nav>li.active {background-color: #f4d214; color: #01058a;}
670        .team-menu .navbar-nav>li.active:after {border-top-color: #f4d214;}
671        .team-menu-container{background-image:url(https://5starassets.blob.core.windows.net/athleticsites/958/91/images/dc5b8a2e-30f8-4d5b-971d-d53135bebe32.png);}
672        .news-header-container{background-image:url(https://5starassets.blob.core.windows.net/athleticsites/958/91/images/dc5b8a2e-30f8-4d5b-971d-d53135bebe32.png);}
673        .arrow_box {border-bottom: 4px solid #f4d214;}
674        .arrow_box:before {border-top-color: #f4d214;}
675    .ticker-19-badge-today, .ticker-19-badge-upcoming, .ticker-19-badge-final { background-color: #01058a; }
676    .ticker-19-calendar-link { background-color: #01058a; color: #fff !important; min-width: 80px !important; padding: 0 20px !important; border: none !important; border-right: 3px solid rgba(255,255,255,0.3) !important; font-size: 1rem !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 1px !important; gap: 4px !important; }
677    .ticker-19-calendar-link:hover { filter: brightness(1.15); }
678    .ticker-19-calendar-link i { font-size: 1.3rem !important; }
679    .ticker-19-calendar-link span { color: #fff !important; font-size: 0.7rem !important; font-weight: 700 !important; letter-spacing: 1px !important; }
680    </style>
681    
682
683    
684    <link href="/lib/fullcalendar/dist/fullcalendar.css" rel="stylesheet" />
685    <style>
686        .composite-calendar-view { padding: 20px 0 24px; }
687
688        /* ===== CARD ===== */
689        .cal-card {
690            background: #fff;
691            border: 1px solid #e5e7eb;
692            border-radius: 10px;
693            box-shadow: 0 2px 8px rgba(0,0,0,0.06);
694            margin-bottom: 24px;
695            overflow: hidden;
696        }
697
698        /* ===== HEADER ===== */
699        .cal-header {
700            display: flex;
701            align-items: center;
702            justify-content: space-between;
703            flex-wrap: wrap;
704            gap: 12px;
705            padding: 18px 24px;
706            border-bottom: 1px solid #e5e7eb;
707            background: #fafafa;
708        }
709        .cal-title {
710            font-size: 1.6rem;
711            font-weight: 800;
712            text-transform: uppercase;
713            letter-spacing: 1.5px;
714            color: #1a1a1a;
715            margin: 0;
716            white-space: nowrap;
717        }
718        .cal-header-controls {
719            display: flex;
720            align-items: center;
721            gap: 8px;
722            flex-wrap: wrap;
723        }
724        .cal-select {
725            font-size: 1.2rem;
726            font-weight: 600;
727            height: 44px;
728            padding: 8px 14px;
729            border-radius: 6px;
730            border: 1px solid #d1d5db;
731            color: #1a1a1a;
732            background: #fff;
733            cursor: pointer;
734            min-width: 160px;
735        }
736        .cal-select:focus { border-color: #888; outline: none; }
737        .cal-select option { color: #1a1a1a; font-size: 1.2rem; }
738
739        /* ===== CALENDAR AREA ===== */
740        #calendar { padding: 20px 24px 24px; }
741
742        /* ===== FULLCALENDAR OVERRIDES ===== */
743        .fc-toolbar {
744            margin-bottom: 16px !important;
745            display: flex !important;
746            align-items: center !important;
747            justify-content: space-between !important;
748            flex-wrap: wrap;
749            gap: 8px;
750        }
751        .fc-toolbar .fc-left { order: 1; display: flex; align-items: center; gap: 4px; }
752        .fc-toolbar .fc-center { order: 2; }
753        .fc-toolbar .fc-right { order: 3; display: flex; align-items: center; gap: 0; }
754        .fc-toolbar .fc-center h2 {
755            font-size: 1.8rem;
756            font-weight: 800;
757            text-transform: uppercase;
758            letter-spacing: 1px;
759            color: #1a1a1a;
760            margin: 0;
761        }
762        .fc-button {
763            font-size: 1.1rem !important;
764            font-weight: 700 !important;
765            text-transform: uppercase;
766            letter-spacing: 0.3px;
767            padding: 7px 14px !important;
768            border: 1px solid #d1d5db !important;
769            background: #fff !important;
770            color: #1a1a1a !important;
771            box-shadow: none !important;
772            line-height: 1.2 !important;
773            height: auto !important;
774            margin: 0 !important;
775        }
776        .fc-button:first-child { border-radius: 6px 0 0 6px !important; }
777        .fc-button:last-child { border-radius: 0 6px 6px 0 !important; }
778        .fc-button:only-child { border-radius: 6px !important; }
779        .fc-button + .fc-button { margin-left: -1px !important; }
780        .fc-button:hover { background: #f5f5f5 !important; }
781        .fc-button.fc-state-active, .fc-state-active {
782            background: #1a1a1a !important;
783            color: #fff !important;
784            border-color: #1a1a1a !important;
785            z-index: 1;
786        }
787        .fc-prev-button, .fc-next-button { padding: 7px 10px !important; }
788        .fc-today-button { border-radius: 6px !important; margin-left: 6px !important; }
789
790        /* Day headers */
791        .fc-day-header {
792            font-size: 1.1rem;
793            font-weight: 800;
794            text-transform: uppercase;
795            letter-spacing: 1px;
796            color: #1a1a1a;
797            padding: 12px 0 !important;
798            border-color: #e5e7eb !important;
799        }
800        .fc-day-number { font-size: 1.3rem; font-weight: 700; color: #1a1a1a; padding: 8px 10px !important; }
801        .fc-unthemed td.fc-today { background: rgba(0,0,0,0.02) !important; }
802        .fc-unthemed th, .fc-unthemed td { border-color: #f0f0f0 !important; }
803
804        /* Events in grid */
805        .fc-title { white-space: normal !important; }
806        .fc-day-grid-event {
807            border: none !important;
808            border-radius: 3px !important;
809            padding: 3px 6px !important;
810            font-size: 1rem !important;
811            font-weight: 600 !important;
812            margin-bottom: 2px !important;
813            line-height: 1.3;
814            background: #f3f4f6 !important;
815            color: #1a1a1a !important;
816            border-left: 3px solid #aaa !important;
817        }
818        .fc-day-grid-event:hover { background: #e8e9eb !important; }
819        .fc-more { font-size: 0.9rem; font-weight: 700; color: #888; }
820
821        /* List view */
822        .fc-list-heading td {
823            font-size: 1.25rem !important;
824            font-weight: 800 !important;
825            text-transform: uppercase;
826            letter-spacing: 0.5px;
827            background: #f9fafb !important;
828            color: #000 !important;
829            padding: 14px 16px !important;
830        }
831        .fc-list-item td {
832            font-size: 1.2rem !important;
833            font-weight: 600 !important;
834            padding: 12px 16px !important;
835            border-color: #f0f0f0 !important;
836            color: #000 !important;
837        }
838        .fc-list-item-title a { color: #000 !important; font-weight: 600 !important; }
839        .fc-list-item-time,
840        .fc-list-item-marker {
841            font-size: 1.4rem !important;
842            font-weight: 700 !important;
843            color: #000 !important;
844        }
845        .fc-list-item:hover td { background: #fafafa !important; }
846
847        /* Import messages */
848        .import-message {
849            margin: 0 24px 16px;
850            padding: 12px 16px;
851            border-radius: 6px;
852            border: 1px solid #bce8f1;
853            background: #d9edf7;
854            color: #31708f;
855        }
856        .import-message .close { float: right; font-size: 18px; font-weight: bold; opacity: .3; cursor: pointer; }
857        .import-message .close:hover { opacity: .6; }
858        .ics-url-box {
859            margin: 8px 0; padding: 8px; background: #f9f9f9;
860            border: 1px solid #ddd; border-radius: 4px;
861            font-family: monospace; font-size: 0.85rem; word-break: break-all; cursor: pointer;
862        }
863        .ics-url-box:hover { background: #f0f0f0; }
864
865        /* ===== MOBILE ===== */
866        @media (max-width: 768px) {
867            .cal-header { flex-direction: column; align-items: stretch; padding: 14px 16px; }
868            .cal-title { font-size: 1.1rem; }
869            .cal-header-controls { flex-direction: column; }
870            .cal-select { width: 100%; min-width: 100%; }
871            #calendar { padding: 12px; }
872            .fc-toolbar { flex-direction: column !important; gap: 8px !important; }
873            .fc-toolbar .fc-left, .fc-toolbar .fc-right, .fc-toolbar .fc-center { justify-content: center; width: 100%; }
874            .fc-toolbar .fc-center h2 { font-size: 1.1rem; text-align: center; }
875        }
876
877        /* Subscribe-to-Schedule trigger + modal (parallel to SA template-4 modal). */
878        .sch-cal-sub-btn {
879            display: inline-flex;
880            align-items: center;
881            gap: 8px;
882            padding: 8px 16px;
883            background: #c8102e;
884            color: #fff;
885            border: none;
886            border-radius: 6px;
887            font-weight: 700;
888            font-size: 1.15rem;
889            letter-spacing: 0.04em;
890            text-transform: uppercase;
891            cursor: pointer;
892            transition: background 0.18s ease, transform 0.12s ease;
893        }
894        .sch-cal-sub-btn i { color: #fff; font-size: 1rem; }
895        .sch-cal-sub-btn:hover,
896        .sch-cal-sub-btn:focus { background: #a40e26; color: #fff; transform: translateY(-1px); outline: none; }
897
898        body.sch-cal-sub-locked { overflow: hidden; }
899        .sch-cal-sub-overlay {
900            position: fixed;
901            inset: 0;
902            /* Above the school site's fixed/sticky nav (which sits at z-index
903               1030-1050 depending on layout). 9999 keeps the modal above any
904               sticky toolbar / chat widget without going into max-int territory. */
905            z-index: 9999;
906            background: rgba(0, 0, 0, 0.55);
907            backdrop-filter: blur(2px);
908            -webkit-backdrop-filter: blur(2px);
909            display: flex;
910            align-items: center;
911            justify-content: center;
912            padding: 20px;
913        }
914        .sch-cal-sub-overlay[hidden] { display: none; }
915        .sch-cal-sub-modal {
916            position: relative;
917            background: #fff;
918            color: #0a0a0a;
919            border-radius: 8px;
920            width: 100%;
921            max-width: 660px;
922            max-height: calc(100vh - 40px);
923            overflow-y: auto;
924            box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
925            padding: 32px 32px 24px;
926            animation: schCalSubIn 0.18s ease;
927            border-top: 4px solid #c8102e;
928        }
929        @keyframes schCalSubIn {
930            from { transform: translateY(12px); opacity: 0; }
931            to { transform: translateY(0); opacity: 1; }
932        }
933        .sch-cal-sub-header {
934            display: flex; align-items: center; gap: 14px;
935            padding-bottom: 14px;
936            margin-bottom: 18px;
937            position: relative;
938        }
939        .sch-cal-sub-header::after {
940            content: '';
941            position: absolute;
942            left: 0; bottom: 0;
943            width: 64px; height: 3px;
944            background: #c8102e;
945        }
946        .sch-cal-sub-logo {
947            width: 44px; height: 44px; flex-shrink: 0;
948            background: #c8102e;
949            color: #fff;
950            display: inline-flex; align-items: center; justify-content: center;
951            transform: rotate(-3deg);
952        }
953        .sch-cal-sub-logo i { color: #fff; font-size: 1.15rem; transform: rotate(3deg); }
954        .sch-cal-sub-title {
955            margin: 0; flex: 1;
956            font-weight: 800;
957            font-size: 1.9rem;
958            color: #0a0a0a;
959            letter-spacing: 0.02em;
960            text-transform: uppercase;
961            line-height: 1.05;
962        }
963        .sch-cal-sub-close {
964            background: transparent; border: 0;
965            width: 36px; height: 36px;
966            border-radius: 50%;
967            cursor: pointer;
968            color: #4a4a4a;
969            display: inline-flex; align-items: center; justify-content: center;
970            transition: background 0.15s ease;
971        }
972        .sch-cal-sub-close i { font-size: 1rem; color: inherit; }
973        .sch-cal-sub-close:hover { background: #f3f3f3; color: #0a0a0a; }
974
975        .sch-cal-sub-lede { margin: 0 0 18px; color: #444; font-size: 1.1rem; line-height: 1.5; }
976
977        /* "You are subscribing to X" — the one line that tells a parent whether
978           they are getting one team or the whole school. */
979        .sch-cal-sub-scope {
980            margin: 0 0 16px;
981            padding: 12px 16px;
982            background: #f3f5f7;
983            border-left: 4px solid #c8102e;
984            color: #111;
985            font-size: 1.15rem;
986            line-height: 1.45;
987        }
988        .sch-cal-sub-scope-label {
989            display: block;
990            margin-bottom: 2px;
991            font-size: 0.82rem;
992            font-weight: 700;
993            letter-spacing: 0.09em;
994            text-transform: uppercase;
995            color: #4a4a4a;
996        }
997        .sch-cal-sub-scope strong { font-weight: 800; }
998        .sch-cal-sub-scope-hint {
999            display: block;
1000            margin-top: 4px;
1001            font-size: 0.98rem;
1002            color: #3d3d3d;
1003        }
1004
1005        .sch-cal-sub-grid {
1006            display: grid;
1007            grid-template-columns: repeat(3, 1fr);
1008            gap: 10px;
1009            margin-bottom: 18px;
1010        }
1011        .sch-cal-sub-tile {
1012            display: flex; flex-direction: column;
1013            align-items: center; justify-content: center;
1014            gap: 10px;
1015            min-height: 104px;
1016            background: #fafaf7;
1017            border: 2px solid #ececec;
1018            border-radius: 4px;
1019            padding: 16px 10px;
1020            text-align: center;
1021            color: #0a0a0a;
1022            text-decoration: none;
1023            font-size: 1rem;
1024            font-weight: 700;
1025            letter-spacing: 0.06em;
1026            text-transform: uppercase;
1027            transition: border-color 0.18s ease, background 0.18s ease, transform 0.12s ease;
1028            cursor: pointer;
1029        }
1030        .sch-cal-sub-tile i {
1031            font-size: 1.8rem;
1032            color: #0a0a0a;
1033            background: #fff;
1034            width: 44px; height: 44px;
1035            line-height: 44px;
1036            display: inline-flex; align-items: center; justify-content: center;
1037            border: 1px solid #ececec;
1038        }
1039        .sch-cal-sub-tile:hover,
1040        .sch-cal-sub-tile:focus,
1041        .sch-cal-sub-tile.is-active {
1042            border-color: #c8102e;
1043            background: #fff;
1044            color: #0a0a0a;
1045            text-decoration: none;
1046            outline: none;
1047            transform: translateY(-2px);
1048        }
1049        .sch-cal-sub-tile.is-active i { border-color: #c8102e; }
1050        .sch-cal-sub-tile[data-sch-subscribe-provider="google"] i { color: #4285F4; }
1051        .sch-cal-sub-tile[data-sch-subscribe-provider="apple"] i { color: #0a0a0a; }
1052        .sch-cal-sub-tile[data-sch-subscribe-provider="outlook365"] i,
1053        .sch-cal-sub-tile[data-sch-subscribe-provider="outlook"] i { color: #0078D4; }
1054        .sch-cal-sub-tile[data-sch-subscribe-provider="yahoo"] i { color: #6001D2; }
1055        .sch-cal-sub-tile[data-sch-subscribe-provider="android"] i { color: #3DDC84; }
1056        .sch-cal-sub-tile[data-sch-subscribe-provider="rss"] i { color: #F26522; }
1057        .sch-cal-sub-tile[data-sch-subscribe-provider="excel"] i { color: #207245; }
1058
1059        .sch-cal-sub-url-row {
1060            display: flex; align-items: center; gap: 8px;
1061            background: #f7f7f7;
1062            border: 1px solid #e3e3e3;
1063            border-radius: 8px;
1064            padding: 8px 10px;
1065            margin-bottom: 18px;
1066        }
1067        .sch-cal-sub-url-row label {
1068            font-size: 0.8rem; letter-spacing: 0.1em;
1069            text-transform: uppercase; color: #666;
1070            flex-shrink: 0; margin: 0;
1071        }
1072        .sch-cal-sub-url-row input {
1073            flex: 1; min-width: 0;
1074            border: 0; background: transparent;
1075            font-size: 1rem; color: #222;
1076            padding: 4px 2px;
1077        }
1078        .sch-cal-sub-url-row input:focus { outline: none; }
1079        .sch-cal-sub-copy {
1080            background: #fff;
1081            border: 1px solid #d9d9d9;
1082            border-radius: 6px;
1083            padding: 6px 12px;
1084            font-size: 0.9rem; letter-spacing: 0.06em;
1085            text-transform: uppercase;
1086            cursor: pointer;
1087            color: #0a0a0a;
1088            transition: background 0.15s ease;
1089        }
1090        .sch-cal-sub-copy:hover { background: #f3f3f3; }
1091        .sch-cal-sub-footer {
1092            border-top: 1px solid #ececec;
1093            padding-top: 18px;
1094            display: flex;
1095            align-items: center;
1096            justify-content: flex-start;
1097        }
1098        .sch-cal-sub-primary {
1099            display: inline-flex; align-items: center; gap: 10px;
1100            background: #c8102e; color: #fff;
1101            border: 0; padding: 14px 30px;
1102            border-radius: 0;
1103            font-weight: 700;
1104            font-size: 1.15rem;
1105            letter-spacing: 0.12em;
1106            text-transform: uppercase;
1107            cursor: pointer;
1108            box-shadow: 6px 6px 0 #0a0a0a;
1109            transition: transform 0.15s ease, box-shadow 0.15s ease;
1110        }
1111        .sch-cal-sub-primary:hover,
1112        .sch-cal-sub-primary:focus {
1113            transform: translate(-2px, -2px);
1114            box-shadow: 8px 8px 0 #0a0a0a;
1115            color: #fff;
1116            outline: none;
1117        }
1118
1119        @media (max-width: 600px) {
1120            .sch-cal-sub-modal { padding: 22px 18px 18px; }
1121            .sch-cal-sub-grid { grid-template-columns: repeat(2, 1fr); }
1122            .sch-cal-sub-title { font-size: 1.45rem; }
1123            .sch-cal-sub-btn { width: 100%; justify-content: center; }
1124        }
1125        /* Keyboard focus visibility (WCAG 2.4.7) */
1126        .cal-select:focus-visible,
1127        .sch-cal-sub-btn:focus-visible,
1128        .sch-cal-sub-url-row input:focus-visible,
1129        .sch-cal-sub-tile:focus-visible,
1130        .sch-cal-sub-primary:focus-visible,
1131        #calendar a:focus-visible {
1132            outline: 2px solid #005fcc;
1133            outline-offset: 2px;
1134        }
1135    </style>
1136
1137    
1138</head>
1139<body viewport="fixed">
1140    <a href="#main-content" class="skip-link">Skip to main content</a>
1141    
1142        <div class="ticker-19-section" aria-label="Game Schedule">
1143        <div class="ticker-19-bar">
1144            <!-- Composite calendar link — LEFT side like OU -->
1145                <a href="/calendar" class="ticker-19-calendar-link" aria-label="View full schedule">
1146                    <i class="fa fa-calendar" aria-hidden="true"></i>
1147                    <span>Composite</span>
1148                </a>
1149
1150            <!-- Tabs -->
1151            <div class="ticker-19-tabs" role="tablist">
1152                <button class="ticker-19-tab active" id="ticker19-ev-btn" role="tab" aria-controls="ticker19-events" aria-selected="true" tabindex="0">Events</button>
1153                <button class="ticker-19-tab" id="ticker19-res-btn" role="tab" aria-controls="ticker19-results" aria-selected="false" tabindex="0">Results</button>
1154            </div>
1155
1156            <!-- Events Panel -->
1157            <div class="ticker-19-panel active" id="ticker19-events" role="tabpanel" aria-labelledby="ticker19-ev-btn">
1158                <div class="ticker-19-scroll-container">
1159                    <button class="ticker-19-arrow ticker-19-arrow-left" aria-label="Previous games"><i class="fa fa-chevron-left" aria-hidden="true"></i></button>
1160                    <div class="ticker-19-track events-slider-19">
1161                                <div class="ticker-19-card" tabindex="0" role="button" aria-expanded="false" aria-label="Football vs Gulfport — Oct. 9">
1162                                    <div class="ticker-19-card-top">
1163                                        <span class="ticker-19-date"><span class="ticker-19-badge ticker-19-badge-today" style="background-color:#01058a;">Oct. 9</span> &middot; TBA</span>
1164                                    </div>
1165                                    <div class="ticker-19-sport">Football - Varsity</div>
1166                                    <div class="ticker-19-opponent">
1167                                            <img src="https://5starassets.blob.core.windows.net/mascots/generics/1.png" class="ticker-19-opp-logo" alt="Gulfport" loading="lazy" />
1168                                        <span class="ticker-19-opp-name">vs Gulfport</span>
1169                                    </div>
1170                                </div>
1171                                <div class="ticker-19-card" tabindex="0" role="button" aria-expanded="false" aria-label="Football at D&#x27;iberville — Oct. 16">
1172                                    <div class="ticker-19-card-top">
1173                                        <span class="ticker-19-date"><span class="ticker-19-badge ticker-19-badge-today" style="background-color:#01058a;">Oct. 16</span> &middot; TBA</span>
1174                                    </div>
1175                                    <div class="ticker-19-sport">Football - Varsity</div>
1176                                    <div class="ticker-19-opponent">
1177                                            <img src="https://5starassets.blob.core.windows.net/mascots/generics/1.png" class="ticker-19-opp-logo" alt="D&#x27;iberville" loading="lazy" />
1178                                        <span class="ticker-19-opp-name">at D&#x27;iberville</span>
1179                                    </div>
1180                                </div>
1181                                <div class="ticker-19-card" tabindex="0" role="button" aria-expanded="false" aria-label="Football vs Harrison Central — Oct. 23">
1182                                    <div class="ticker-19-card-top">
1183                                        <span class="ticker-19-date"><span class="ticker-19-badge ticker-19-badge-today" style="background-color:#01058a;">Oct. 23</span> &middot; TBA</span>
1184                                    </div>
1185                                    <div class="ticker-19-sport">Football - Varsity</div>
1186                                    <div class="ticker-19-opponent">
1187                                            <img src="https://5starassets.blob.core.windows.net/mascots/generics/1.png" class="ticker-19-opp-logo" alt="Harrison Central" loading="lazy" />
1188                                        <span class="ticker-19-opp-name">vs Harrison Central</span>
1189                                    </div>
1190                                </div>
1191                                <div class="ticker-19-card" tabindex="0" role="button" aria-expanded="false" aria-label="Soccer vs Resurrection Catholic — Oct. 26">
1192                                    <div class="ticker-19-card-top">
1193                                        <span class="ticker-19-date"><span class="ticker-19-badge ticker-19-badge-today" style="background-color:#01058a;">Oct. 26</span> &middot; 5:30 PM</span>
1194                                    </div>
1195                                    <div class="ticker-19-sport">Girls Soccer - Varsity</div>
1196                                    <div class="ticker-19-opponent">
1197                                            <img src="https://5starassets.blob.core.windows.net/mascots/generics/4.png" class="ticker-19-opp-logo" alt="Resurrection Catholic" loading="lazy" />
1198                                        <span class="ticker-19-opp-name">vs Resurrection Catholic</span>
1199                                    </div>
1200                                </div>
1201                                <div class="ticker-19-card" tabindex="0" role="button" aria-expanded="false" aria-label="Soccer vs Resurrection Catholic — Oct. 26">
1202                                    <div class="ticker-19-card-top">
1203                                        <span class="ticker-19-date"><span class="ticker-19-badge ticker-19-badge-today" style="background-color:#01058a;">Oct. 26</span> &middot; 7:00 PM</span>
1204                                    </div>
1205                                    <div class="ticker-19-sport">Girls Soccer - Varsity</div>
1206                                    <div class="ticker-19-opponent">
1207                                            <img src="https://5starassets.blob.core.windows.net/mascots/generics/4.png" class="ticker-19-opp-logo" alt="Resurrection Catholic" loading="lazy" />
1208                                        <span class="ticker-19-opp-name">vs Resurrection Catholic</span>
1209                                    </div>
1210                                </div>
1211                                <div class="ticker-19-card" tabindex="0" role="button" aria-expanded="false" aria-label="Soccer vs Sumrall — Oct. 29">
1212                                    <div class="ticker-19-card-top">
1213                                        <span class="ticker-19-date"><span class="ticker-19-badge ticker-19-badge-today" style="background-color:#01058a;">Oct. 29</span> &middot; 5:30 PM</span>
1214                                    </div>
1215                                    <div class="ticker-19-sport">Girls Soccer - Varsity</div>
1216                                    <div class="ticker-19-opponent">
1217                                            <img src="https://5starassets.blob.core.windows.net/mascots/generics/4.png" class="ticker-19-opp-logo" alt="Sumrall" loading="lazy" />
1218                                        <span class="ticker-19-opp-name">vs Sumrall</span>
1219                                    </div>
1220                                </div>
1221                                <div class="ticker-19-card" tabindex="0" role="button" aria-expanded="false" aria-label="Soccer vs Sumrall — Oct. 29">
1222                                    <div class="ticker-19-card-top">
1223                                        <span class="ticker-19-date"><span class="ticker-19-badge ticker-19-badge-today" style="background-color:#01058a;">Oct. 29</span> &middot; 7:00 PM</span>
1224                                    </div>
1225                                    <div class="ticker-19-sport">Girls Soccer - Varsity</div>
1226                                    <div class="ticker-19-opponent">
1227                                            <img src="https://5starassets.blob.core.windows.net/mascots/generics/4.png" class="ticker-19-opp-logo" alt="Sumrall" loading="lazy" />
1228                                        <span class="ticker-19-opp-name">vs Sumrall</span>
1229                                    </div>
1230                                </div>
1231                                <div class="ticker-19-card" tabindex="0" role="button" aria-expanded="false" aria-label="Basketball at Pass Christian — Oct. 31">
1232                                    <div class="ticker-19-card-top">
1233                                        <span class="ticker-19-date"><span class="ticker-19-badge ticker-19-badge-today" style="background-color:#01058a;">Oct. 31</span> &middot; 12:05 PM</span>
1234                                    </div>
1235                                    <div class="ticker-19-sport">Girls Basketball - Varsity</div>
1236                                    <div class="ticker-19-opponent">
1237                                            <img src="https://5starassets.blob.core.windows.net/mascots/generics/2.png" class="ticker-19-opp-logo" alt="Pass Christian" loading="lazy" />
1238                                        <span class="ticker-19-opp-name">at Pass Christian</span>
1239                                    </div>
1240                                </div>
1241                                <div class="ticker-19-card" tabindex="0" role="button" aria-expanded="false" aria-label="Basketball at Long Beach — Oct. 31">
1242                                    <div class="ticker-19-card-top">
1243                                        <span class="ticker-19-date"><span class="ticker-19-badge ticker-19-badge-today" style="background-color:#01058a;">Oct. 31</span> &middot; 1:45 PM</span>
1244                                    </div>
1245                                    <div class="ticker-19-sport">Girls Basketball - Varsity</div>
1246                                    <div class="ticker-19-opponent">
1247                                            <img src="https://5starassets.blob.core.windows.net/mascots/generics/2.png" class="ticker-19-opp-logo" alt="Long Beach" loading="lazy" />
1248                                        <span class="ticker-19-opp-name">at Long Beach</span>
1249                                    </div>
1250                                </div>
1251                                <div class="ticker-19-card" tabindex="0" role="button" aria-expanded="false" aria-label="Basketball vs Ocean Springs — Nov. 2">
1252                                    <div class="ticker-19-card-top">
1253                                        <span class="ticker-19-date"><span class="ticker-19-badge ticker-19-badge-today" style="background-color:#01058a;">Nov. 2</span> &middot; 6:30 PM</span>
1254                                    </div>
1255                                    <div class="ticker-19-sport">Boys Basketball - Freshman</div>
1256                                    <div class="ticker-19-opponent">
1257                                            <img src="https://5starassets.blob.core.windows.net/mascots/generics/2.png" class="ticker-19-opp-logo" alt="Ocean Springs" loading="lazy" />
1258                                        <span class="ticker-19-opp-name">vs Ocean Springs</span>
1259                                    </div>
1260                                </div>
1261                    </div>
1262                    <button class="ticker-19-arrow ticker-19-arrow-right" aria-label="Next games"><i class="fa fa-chevron-right" aria-hidden="true"></i></button>
1263                </div>
1264            </div>
1265
1266            <!-- Results Panel -->
1267            <div class="ticker-19-panel" id="ticker19-results" role="tabpanel" aria-labelledby="ticker19-res-btn" hidden>
1268                <div class="ticker-19-scroll-container">
1269                    <button class="ticker-19-arrow ticker-19-arrow-left" aria-label="Previous results"><i class="fa fa-chevron-left" aria-hidden="true"></i></button>
1270                    <div class="ticker-19-track results-slider-19">
1271                            <div class="ticker-19-empty">No recent results</div>
1272                    </div>
1273                    <button class="ticker-19-arrow ticker-19-arrow-right" aria-label="Next results"><i class="fa fa-chevron-right" aria-hidden="true"></i></button>
1274                </div>
1275            </div>
1276        </div>
1277    </div>
1278    
1278<script>
1279        (function loadTicker() {
1280            if (typeof jQuery !== 'undefined') {
1281                var s = document.createElement('script');
1282                s.src = '/js/UpcomingEventsStyle19.js';
1283                document.body.appendChild(s);
1284            } else {
1285                setTimeout(loadTicker, 50);
1286            }
1287        })();
1288    </script>
1288
1289
1290<!-- Mobile: collapsible mini schedule (future events only) -->
1291    <div class="mobile-mini-sched" id="mobileMinSched" aria-label="Upcoming events" hidden>
1292            <div class="mms-filter">
1293                <select id="mmsSportFilter" class="mms-sport-select" aria-label="Filter by sport">
1294                    <option value="">All Sports</option>
1295                        <option value="Baseball">Baseball</option>
1296                        <option value="Basketball">Basketball</option>
1297                        <option value="Football">Football</option>
1298                        <option value="Soccer">Soccer</option>
1299                        <option value="Softball">Softball</option>
1300                        <option value="Volleyball">Volleyball</option>
1301                </select>
1302            </div>
1303        <div class="mms-events" id="mmsEvents" aria-live="polite">
1304                <div class="mms-event" data-sport="Football">
1305                    <div class="mms-date">
1306                        <span class="mms-month">OCT</span>
1307                        <span class="mms-day">9</span>
1308                    </div>
1309                    <div class="mms-info">
1310                        <span class="mms-sport">Football - Varsity</span>
1311                        <span class="mms-matchup">
1312                                <img src="https://5starassets.blob.core.windows.net/mascots/generics/1.png" class="mms-logo" alt="" loading="lazy" />
1313                            vs Gulfport
1314                        </span>
1315                    </div>
1316                    <div class="mms-right">
1317                        <span class="mms-time">TBA</span>
1318                    </div>
1319                </div>
1320                <div class="mms-event" data-sport="Football">
1321                    <div class="mms-date">
1322                        <span class="mms-month">OCT</span>
1323                        <span class="mms-day">16</span>
1324                    </div>
1325                    <div class="mms-info">
1326                        <span class="mms-sport">Football - Varsity</span>
1327                        <span class="mms-matchup">
1328                                <img src="https://5starassets.blob.core.windows.net/mascots/generics/1.png" class="mms-logo" alt="" loading="lazy" />
1329                            at D&#x27;iberville
1330                        </span>
1331                    </div>
1332                    <div class="mms-right">
1333                        <span class="mms-time">TBA</span>
1334                    </div>
1335                </div>
1336                <div class="mms-event" data-sport="Football">
1337                    <div class="mms-date">
1338                        <span class="mms-month">OCT</span>
1339                        <span class="mms-day">23</span>
1340                    </div>
1341                    <div class="mms-info">
1342                        <span class="mms-sport">Football - Varsity</span>
1343                        <span class="mms-matchup">
1344                                <img src="https://5starassets.blob.core.windows.net/mascots/generics/1.png" class="mms-logo" alt="" loading="lazy" />
1345                            vs Harrison Central
1346                        </span>
1347                    </div>
1348                    <div class="mms-right">
1349                        <span class="mms-time">TBA</span>
1350                    </div>
1351                </div>
1352                <div class="mms-event" data-sport="Soccer">
1353                    <div class="mms-date">
1354                        <span class="mms-month">OCT</span>
1355                        <span class="mms-day">26</span>
1356                    </div>
1357                    <div class="mms-info">
1358                        <span class="mms-sport">Girls Soccer - Varsity</span>
1359                        <span class="mms-matchup">
1360                                <img src="https://5starassets.blob.core.windows.net/mascots/generics/4.png" class="mms-logo" alt="" loading="lazy" />
1361                            vs Resurrection Catholic
1362                        </span>
1363                    </div>
1364                    <div class="mms-right">
1365                        <span class="mms-time">5:30 PM</span>
1366                    </div>
1367                </div>
1368                <div class="mms-event" data-sport="Soccer">
1369                    <div class="mms-date">
1370                        <span class="mms-month">OCT</span>
1371                        <span class="mms-day">26</span>
1372                    </div>
1373                    <div class="mms-info">
1374                        <span class="mms-sport">Girls Soccer - Varsity</span>
1375                        <span class="mms-matchup">
1376                                <img src="https://5starassets.blob.core.windows.net/mascots/generics/4.png" class="mms-logo" alt="" loading="lazy" />
1377                            vs Resurrection Catholic
1378                        </span>
1379                    </div>
1380                    <div class="mms-right">
1381                        <span class="mms-time">7:00 PM</span>
1382                    </div>
1383                </div>
1384                <div class="mms-event" data-sport="Soccer">
1385                    <div class="mms-date">
1386                        <span class="mms-month">OCT</span>
1387                        <span class="mms-day">29</span>
1388                    </div>
1389                    <div class="mms-info">
1390                        <span class="mms-sport">Girls Soccer - Varsity</span>
1391                        <span class="mms-matchup">
1392                                <img src="https://5starassets.blob.core.windows.net/mascots/generics/4.png" class="mms-logo" alt="" loading="lazy" />
1393                            vs Sumrall
1394                        </span>
1395                    </div>
1396                    <div class="mms-right">
1397                        <span class="mms-time">5:30 PM</span>
1398                    </div>
1399                </div>
1400                <div class="mms-event" data-sport="Soccer">
1401                    <div class="mms-date">
1402                        <span class="mms-month">OCT</span>
1403                        <span class="mms-day">29</span>
1404                    </div>
1405                    <div class="mms-info">
1406                        <span class="mms-sport">Girls Soccer - Varsity</span>
1407                        <span class="mms-matchup">
1408                                <img src="https://5starassets.blob.core.windows.net/mascots/generics/4.png" class="mms-logo" alt="" loading="lazy" />
1409                            vs Sumrall
1410                        </span>
1411                    </div>
1412                    <div class="mms-right">
1413                        <span class="mms-time">7:00 PM</span>
1414                    </div>
1415                </div>
1416                <div class="mms-event" data-sport="Basketball">
1417                    <div class="mms-date">
1418                        <span class="mms-month">OCT</span>
1419                        <span class="mms-day">31</span>
1420                    </div>
1421                    <div class="mms-info">
1422                        <span class="mms-sport">Girls Basketball - Varsity</span>
1423                        <span class="mms-matchup">
1424                                <img src="https://5starassets.blob.core.windows.net/mascots/generics/2.png" class="mms-logo" alt="" loading="lazy" />
1425                            at Pass Christian
1426                        </span>
1427                    </div>
1428                    <div class="mms-right">
1429                        <span class="mms-time">12:05 PM</span>
1430                    </div>
1431                </div>
1432                <div class="mms-event" data-sport="Basketball">
1433                    <div class="mms-date">
1434                        <span class="mms-month">OCT</span>
1435                        <span class="mms-day">31</span>
1436                    </div>
1437                    <div class="mms-info">
1438                        <span class="mms-sport">Girls Basketball - Varsity</span>
1439                        <span class="mms-matchup">
1440                                <img src="https://5starassets.blob.core.windows.net/mascots/generics/2.png" class="mms-logo" alt="" loading="lazy" />
1441                            at Long Beach
1442                        </span>
1443                    </div>
1444                    <div class="mms-right">
1445                        <span class="mms-time">1:45 PM</span>
1446                    </div>
1447                </div>
1448                <div class="mms-event" data-sport="Basketball">
1449                    <div class="mms-date">
1450                        <span class="mms-month">NOV</span>
1451                        <span class="mms-day">2</span>
1452                    </div>
1453                    <div class="mms-info">
1454                        <span class="mms-sport">Boys Basketball - Freshman</span>
1455                        <span class="mms-matchup">
1456                                <img src="https://5starassets.blob.core.windows.net/mascots/generics/2.png" class="mms-logo" alt="" loading="lazy" />
1457                            vs Ocean Springs
1458                        </span>
1459                    </div>
1460                    <div class="mms-right">
1461                        <span class="mms-time">6:30 PM</span>
1462                    </div>
1463                </div>
1464        </div>
1465        <a href="/calendar" class="mms-full-link"><i class="fa fa-calendar" aria-hidden="true"></i> Full Schedule</a>
1466    </div>
1467
1468<style>
1469    /* Game footnote (Homecoming, Senior Night, ...) under the matchup */
1470    .ticker-19-footnote {
1471        font-size: 0.7rem;
1472        font-style: italic;
1473        font-weight: 600;
1474        color: #444;
1475        text-align: center;
1476        white-space: nowrap;
1477        overflow: hidden;
1478        text-overflow: ellipsis;
1479        max-width: 190px;
1480        margin: 1px auto 0;
1481    }
1482
1483    /* Auto-scroll card text that overflows its max-width (JS flags with .t19-marq) */
1484    .ticker-19-sport.t19-marq, .ticker-19-opp-name.t19-marq { text-overflow: clip; }
1485    .t19-marq .t19-marq-inner {
1486        display: inline-block;
1487        white-space: nowrap;
1488        animation: t19-marq-slide var(--t19-marq-dur, 6s) ease-in-out infinite alternate;
1489    }
1490    .ticker-19-card:hover .t19-marq .t19-marq-inner,
1491    .ticker-19-card:focus-within .t19-marq .t19-marq-inner { animation-play-state: paused; }
1492    @keyframes t19-marq-slide {
1493        0%, 20% { transform: translateX(0); }
1494        80%, 100% { transform: translateX(var(--t19-marq-shift, 0px)); }
1495    }
1496    @media (prefers-reduced-motion: reduce) {
1497        .ticker-19-sport.t19-marq, .ticker-19-opp-name.t19-marq { text-overflow: ellipsis; }
1498        .t19-marq .t19-marq-inner { animation: none; }
1499    }
1500
1501    .mobile-cal-bar { display: none; }
1502    .mobile-mini-sched { display: none; }
1503    @media (max-width: 991px) {
1504        .ticker-19-section { display: none !important; }
1505
1506        /* Calendar bar: toggle + full schedule link */
1507        .mobile-cal-bar {
1508            display: flex !important;
1509            align-items: center;
1510            justify-content: center;
1511            padding: 0;
1512            margin: 0;
1513        }
1514        .mcb-toggle {
1515            flex: 1;
1516            display: flex;
1517            align-items: center;
1518            justify-content: center;
1519            gap: 8px;
1520            color: #fff;
1521            background: transparent;
1522            border: none;
1523            font-size: 1.1rem;
1524            font-weight: 700;
1525            text-transform: uppercase;
1526            letter-spacing: 0.4px;
1527            padding: 8px 14px;
1528            cursor: pointer;
1529        }
1530        .mcb-caret {
1531            transition: transform 0.2s;
1532            font-size: 0.95rem;
1533        }
1534        .mcb-toggle[aria-expanded="true"] .mcb-caret {
1535            transform: rotate(180deg);
1536        }
1537        .mcb-full {
1538            display: flex;
1539            align-items: center;
1540            justify-content: center;
1541            padding: 8px 16px;
1542            color: rgba(255,255,255,0.9);
1543            text-decoration: none;
1544            border-left: 1px solid rgba(255,255,255,0.15);
1545            font-size: 1.05rem;
1546        }
1547        .mcb-full:hover { color: #fff; text-decoration: none; }
1548
1549        /* Mini schedule (collapsed by default) */
1550        .mobile-mini-sched {
1551            background: #fff;
1552            border-bottom: 1px solid #e5e7eb;
1553            overflow: hidden;
1554            max-height: 0;
1555            transition: max-height 0.3s ease;
1556        }
1557        .mobile-mini-sched.mms-open {
1558            display: block;
1559            max-height: 1200px;
1560        }
1561        .mms-event {
1562            display: flex;
1563            align-items: center;
1564            gap: 14px;
1565            padding: 14px 16px;
1566            border-bottom: 1px solid #f0f0f0;
1567        }
1568        .mms-event:last-child { border-bottom: none; }
1569        .mms-date {
1570            display: flex;
1571            flex-direction: column;
1572            align-items: center;
1573            min-width: 56px;
1574            flex-shrink: 0;
1575        }
1576        .mms-month {
1577            font-size: 1rem;
1578            font-weight: 700;
1579            text-transform: uppercase;
1580            color: #444;
1581            line-height: 1;
1582        }
1583        .mms-day {
1584            font-size: 1.85rem;
1585            font-weight: 800;
1586            color: #000;
1587            line-height: 1.2;
1588        }
1589        .mms-info {
1590            flex: 1;
1591            min-width: 0;
1592        }
1593        .mms-sport {
1594            display: block;
1595            font-size: 1.05rem;
1596            font-weight: 700;
1597            text-transform: uppercase;
1598            color: #444;
1599            letter-spacing: 0.3px;
1600        }
1601        .mms-matchup {
1602            display: flex;
1603            align-items: center;
1604            gap: 8px;
1605            font-size: 1.2rem;
1606            font-weight: 700;
1607            color: #000;
1608            white-space: nowrap;
1609            overflow: hidden;
1610            text-overflow: ellipsis;
1611        }
1612        .mms-logo {
1613            width: 32px;
1614            height: 32px;
1615            object-fit: contain;
1616            border-radius: 50%;
1617            flex-shrink: 0;
1618        }
1619        .mms-right {
1620            flex-shrink: 0;
1621            text-align: right;
1622        }
1623        .mms-time {
1624            font-size: 1.15rem;
1625            font-weight: 600;
1626            color: #000;
1627        }
1628        .mms-filter {
1629            padding: 12px 16px;
1630            border-bottom: 1px solid #e5e7eb;
1631        }
1632        .mms-sport-select {
1633            width: 100%;
1634            padding: 12px 14px;
1635            font-size: 1.2rem;
1636            font-weight: 600;
1637            border: 1px solid #d1d5db;
1638            border-radius: 4px;
1639            background: #fff;
1640            color: #000;
1641            -webkit-appearance: menulist;
1642        }
1643        .mms-sport-select option {
1644            color: #000;
1645            background: #fff;
1646            font-size: 1.2rem;
1647        }
1648        .mms-full-link {
1649            display: flex;
1650            align-items: center;
1651            justify-content: center;
1652            gap: 10px;
1653            padding: 16px;
1654            font-size: 1.2rem;
1655            font-weight: 700;
1656            text-transform: uppercase;
1657            letter-spacing: 0.5px;
1658            color: #000;
1659            text-decoration: none;
1660            border-top: 1px solid #e5e7eb;
1661        }
1662        .mms-full-link:hover { color: #1a1a1a; text-decoration: none; }
1663    }
1664</style>
1665<script>
1666document.addEventListener('DOMContentLoaded', function () {
1667    var btn = document.getElementById('mcbToggle');
1668    var sched = document.getElementById('mobileMinSched');
1669    var calBar = document.querySelector('.mobile-cal-bar');
1670    if (!btn || !sched || !calBar) return;
1671
1672    // Move the schedule right after the calendar bar so it expands downward
1673    calBar.parentNode.insertBefore(sched, calBar.nextSibling);
1674
1675    // Toggle expand/collapse
1676    btn.addEventListener('click', function () {
1677        var open = sched.classList.toggle('mms-open');
1678        sched.hidden = !open;
1679        btn.setAttribute('aria-expanded', open ? 'true' : 'false');
1680    });
1681
1682    // Sport filter: fetch filtered events from server
1683    var filter = document.getElementById('mmsSportFilter');
1684    var eventsContainer = document.getElementById('mmsEvents');
1685    if (filter && eventsContainer) {
1686        filter.addEventListener('change', function () {
1687            var sport = this.value;
1688            eventsContainer.style.opacity = '0.5';
1689            fetch('/api/mobile-events?sport=' + encodeURIComponent(sport))
1690                .then(function (r) { return r.json(); })
1691                .then(function (events) {
1692                    var html = '';
1693                    events.forEach(function (g) {
1694                        html += '<div class="mms-event" data-sport="' + (g.sport || '') + '">'
1695                            + '<div class="mms-date"><span class="mms-month">' + g.month + '</span><span class="mms-day">' + g.day + '</span></div>'
1696                            + '<div class="mms-info"><span class="mms-sport">' + g.sportLabel + '</span>'
1697                            + '<span class="mms-matchup">'
1698                            + (g.opponentLogo ? '<img src="' + g.opponentLogo + '" class="mms-logo" alt="" loading="lazy" />' : '')
1699                            + g.matchup + '</span></div>'
1700                            + '<div class="mms-right"><span class="mms-time">' + g.time + '</span></div></div>';
1701                    });
1702                    eventsContainer.innerHTML = html || '<div style="padding:18px;text-align:center;color:#555;font-size:1rem;font-weight:500;">No upcoming events</div>';
1703                    eventsContainer.style.opacity = '1';
1704                })
1705                .catch(function () { eventsContainer.style.opacity = '1'; });
1706        });
1707    }
1708});
1709</script>
1709
1710
1711    
1712    <input type="hidden" value="958" id="schoolId" />
1713    <input type="hidden" value="false" id="customAppSchool" />
1714    <input type="hidden" value="8/31/2023 12:00:00 AM" id="adServingDateBegins" />
1715    <header>
1716        
1717
1718
1719            <div class="row">
1720                <div class="col-md-12 no-print">
1721                    
1722                </div>
1723            </div>
1724
1725        <div class="header-topper">
1726            <div class="row">
1727                <h1 class="site-title text-primary no-print"><small style="color: black;">&nbsp;&nbsp;&nbsp;<i>THE OFFICIAL SITE OF </i></small><br /><i>St. Martin High School Athletics</i></h1>
1728            </div>
1729        </div>
1730        <div class="row">
1731            <div class="col-md-12">
1732                <div class="main-menu-container bg-primary" id="fixedscroll">
1733                    <div class="fixed-menu-container">
1734                        <div class="header-social-media">
1735                            <div class="feed-wrapper">
1736            <a href="https://www.facebook.com/StMartinHighSchoolActivities/" target="_blank" rel="noopener" aria-label="Visit our Facebook page">
1737                <i class="fa fa-facebook text-primary-font" aria-hidden="true"></i>
1738                <span class="sr-only">Facebook</span>
1739            </a>
1740            <a href="https://twitter.com/stmartinsports" target="_blank" rel="noopener" aria-label="Visit our X page">
1741                <i class="fa fa-twitter text-primary-font" aria-hidden="true"></i>
1742                <span class="sr-only">X</span>
1743            </a>
1744</div>
1745
1746                        </div>
1747                        <div id="center">
1748                            <div class="header-gfx border-right-xl-secondary no-print">
1749                                <a href="/"><img src="https://5starassets.blob.core.windows.net/athleticsites/958/91/images/de26b5b7-cdcc-4648-a984-f85a7312c181.png" aria-label="St. Martin" alt="St. Martin Logo" /><span class="mk-blank">-</span></a>
1750                            </div>
1751                            <div class="primary-line border-right-xl-primary"></div>
1752                        </div>
1753                        <div class="">
1754                            
1755                                <nav class="custom-nav" role="navigation" aria-label="Main Navigation" data-sponsor-model="true">
1756    <div class="navbar yamm navbar-static-top">
1757        <div class="container" id="nav-container">
1758            <div class="navbar-header">
1759                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
1760                    <span class="sr-only">Toggle navigation</span>
1761                    <span class="icon-bar bg-secondary"></span>
1762                    <span class="icon-bar bg-secondary"></span>
1763                    <span class="icon-bar bg-secondary"></span>
1764                </button>
1765                <a class="navbar-brand" href="/" aria-label="Return to St. Martin Home Page">
1766                    <img src="https://5starassets.blob.core.windows.net/athleticsites/958/91/images/fa90332f-b0c3-47a7-a8f8-cf50bd689d14.png" class="img-responsive tag" aria-label="St. Martin Logo" alt="St. Martin Logo" />
1767                </a>
1768                    <div class="presenting-sponsor hidden-md hidden-lg">
1769                        <div class="adzone adzone-0 presenting-sponsor">
1770                                <div class="ad-placement">
1771    <div id='gam-presenting-sponsor-mobile' class="gam_ps"></div>
1772    </div>
1773
1774                        </div>
1775                    </div>
1776                </div>
1777            <div id="navbar" class="navbar-collapse collapse" aria-expanded="false">
1778                <ul class="nav navbar-nav" id="nav-links" role="menubar">
1779                  
1780                            <li class="dropdown yamm-fw" role="presentation">
1781                                <a href="#" data-toggle="dropdown" class="dropdown-toggle text-primary-font" role="menuitem" aria-haspopup="true" aria-expanded="false" tabindex="0">SPORTS</a>
1782                                    <ul id="dropdown1" class="dropdown-menu two-columns" role="menu">
1783                                            <li role="menuitem">
1784                                                <div class="sport-link-nfo">
1785                                                    <div class="row">
1786                                                        <div class="col-xs-12 col-sm-6">
1787                                                            <div class="link">
1788                                                                <a class="text-primary" href="/sport/baseball/boys/" role="menuitem" tabindex="0" aria-label="Baseball go to Main Team Page">BASEBALL</a>
1789                                                            </div>
1790                                                        </div>
1791                                                        <div class="hidden-xs col-sm-6">
1792                                                            <div class="nfo">
1793                                                                <a class="text-primary" href="/sport/baseball/boys/?tab=schedule" role="menuitem" aria-label="Baseball - Schedules" tabindex="0">Schedules</a><span> /</span>
1794                                                                <a class="text-primary" href="/sport/baseball/boys/?tab=roster" role="menuitem" aria-label="Baseball - Rosters" tabindex="0">Rosters</a><span> /</span>
1795                                                                <a class="text-primary" href="/sport/baseball/boys/?tab=news" role="menuitem" aria-label="Baseball - News" tabindex="0">News</a>
1796                                                            </div>
1797                                                        </div>
1798                                                    </div>
1799                                                </div>
1800                                            </li>
1801                                            <li role="menuitem">
1802                                                <div class="sport-link-nfo">
1803                                                    <div class="row">
1804                                                        <div class="col-xs-12 col-sm-6">
1805                                                            <div class="link">
1806                                                                <a class="text-primary" href="/sport/basketball/boys/" role="menuitem" tabindex="0" aria-label="Basketball(Boys) go to Main Team Page">BASKETBALL(BOYS)</a>
1807                                                            </div>
1808                                                        </div>
1809                                                        <div class="hidden-xs col-sm-6">
1810                                                            <div class="nfo">
1811                                                                <a class="text-primary" href="/sport/basketball/boys/?tab=schedule" role="menuitem" aria-label="Basketball(Boys) - Schedules" tabindex="0">Schedules</a><span> /</span>
1812                                                                <a class="text-primary" href="/sport/basketball/boys/?tab=roster" role="menuitem" aria-label="Basketball(Boys) - Rosters" tabindex="0">Rosters</a><span> /</span>
1813                                                                <a class="text-primary" href="/sport/basketball/boys/?tab=news" role="menuitem" aria-label="Basketball(Boys) - News" tabindex="0">News</a>
1814                                                            </div>
1815                                                        </div>
1816                                                    </div>
1817                                                </div>
1818                                            </li>
1819                                            <li role="menuitem">
1820                                                <div class="sport-link-nfo">
1821                                                    <div class="row">
1822                                                        <div class="col-xs-12 col-sm-6">
1823                                                            <div class="link">
1824                                                                <a class="text-primary" href="/sport/basketball/girls/" role="menuitem" tabindex="0" aria-label="Basketball(Girls) go to Main Team Page">BASKETBALL(GIRLS)</a>
1825                                                            </div>
1826                                                        </div>
1827                                                        <div class="hidden-xs col-sm-6">
1828                                                            <div class="nfo">
1829                                                                <a class="text-primary" href="/sport/basketball/girls/?tab=schedule" role="menuitem" aria-label="Basketball(Girls) - Schedules" tabindex="0">Schedules</a><span> /</span>
1830                                                                <a class="text-primary" href="/sport/basketball/girls/?tab=roster" role="menuitem" aria-label="Basketball(Girls) - Rosters" tabindex="0">Rosters</a><span> /</span>
1831                                                                <a class="text-primary" href="/sport/basketball/girls/?tab=news" role="menuitem" aria-label="Basketball(Girls) - News" tabindex="0">News</a>
1832                                                            </div>
1833                                                        </div>
1834                                                    </div>
1835                                                </div>
1836                                            </li>
1837                                            <li role="menuitem">
1838                                                <div class="sport-link-nfo">
1839                                                    <div class="row">
1840                                                        <div class="col-xs-12 col-sm-6">
1841                                                            <div class="link">
1842                                                                <a class="text-primary" href="/sport/football/boys/" role="menuitem" tabindex="0" aria-label="Football go to Main Team Page">FOOTBALL</a>
1843                                                            </div>
1844                                                        </div>
1845                                                        <div class="hidden-xs col-sm-6">
1846                                                            <div class="nfo">
1847                                                                <a class="text-primary" href="/sport/football/boys/?tab=schedule" role="menuitem" aria-label="Football - Schedules" tabindex="0">Schedules</a><span> /</span>
1848                                                                <a class="text-primary" href="/sport/football/boys/?tab=roster" role="menuitem" aria-label="Football - Rosters" tabindex="0">Rosters</a><span> /</span>
1849                                                                <a class="text-primary" href="/sport/football/boys/?tab=news" role="menuitem" aria-label="Football - News" tabindex="0">News</a>
1850                                                            </div>
1851                                                        </div>
1852                                                    </div>
1853                                                </div>
1854                                            </li>
1855                                            <li role="menuitem">
1856                                                <div class="sport-link-nfo">
1857                                                    <div class="row">
1858                                                        <div class="col-xs-12 col-sm-6">
1859                                                            <div class="link">
1860                                                                <a class="text-primary" href="/sport/soccer/boys/" role="menuitem" tabindex="0" aria-label="Soccer(Boys) go to Main Team Page">SOCCER(BOYS)</a>
1861                                                            </div>
1862                                                        </div>
1863                                                        <div class="hidden-xs col-sm-6">
1864                                                            <div class="nfo">
1865                                                                <a class="text-primary" href="/sport/soccer/boys/?tab=schedule" role="menuitem" aria-label="Soccer(Boys) - Schedules" tabindex="0">Schedules</a><span> /</span>
1866                                                                <a class="text-primary" href="/sport/soccer/boys/?tab=roster" role="menuitem" aria-label="Soccer(Boys) - Rosters" tabindex="0">Rosters</a><span> /</span>
1867                                                                <a class="text-primary" href="/sport/soccer/boys/?tab=news" role="menuitem" aria-label="Soccer(Boys) - News" tabindex="0">News</a>
1868                                                            </div>
1869                                                        </div>
1870                                                    </div>
1871                                                </div>
1872                                            </li>
1873                                            <li role="menuitem">
1874                                                <div class="sport-link-nfo">
1875                                                    <div class="row">
1876                                                        <div class="col-xs-12 col-sm-6">
1877                                                            <div class="link">
1878                                                                <a class="text-primary" href="/sport/soccer/girls/" role="menuitem" tabindex="0" aria-label="Soccer(Girls) go to Main Team Page">SOCCER(GIRLS)</a>
1879                                                            </div>
1880                                                        </div>
1881                                                        <div class="hidden-xs col-sm-6">
1882                                                            <div class="nfo">
1883                                                                <a class="text-primary" href="/sport/soccer/girls/?tab=schedule" role="menuitem" aria-label="Soccer(Girls) - Schedules" tabindex="0">Schedules</a><span> /</span>
1884                                                                <a class="text-primary" href="/sport/soccer/girls/?tab=roster" role="menuitem" aria-label="Soccer(Girls) - Rosters" tabindex="0">Rosters</a><span> /</span>
1885                                                                <a class="text-primary" href="/sport/soccer/girls/?tab=news" role="menuitem" aria-label="Soccer(Girls) - News" tabindex="0">News</a>
1886                                                            </div>
1887                                                        </div>
1888                                                    </div>
1889                                                </div>
1890                                            </li>
1891                                            <li role="menuitem">
1892                                                <div class="sport-link-nfo">
1893                                                    <div class="row">
1894                                                        <div class="col-xs-12 col-sm-6">
1895                                                            <div class="link">
1896                                                                <a class="text-primary" href="/sport/softball/girls/" role="menuitem" tabindex="0" aria-label="Softball(Girls) go to Main Team Page">SOFTBALL(GIRLS)</a>
1897                                                            </div>
1898                                                        </div>
1899                                                        <div class="hidden-xs col-sm-6">
1900                                                            <div class="nfo">
1901                                                                <a class="text-primary" href="/sport/softball/girls/?tab=schedule" role="menuitem" aria-label="Softball(Girls) - Schedules"
1901 tabindex="0">Schedules</a><span> /</span>
1902                                                                <a class="text-primary" href="/sport/softball/girls/?tab=roster" role="menuitem" aria-label="Softball(Girls) - Rosters" tabindex="0">Rosters</a><span> /</span>
1903                                                                <a class="text-primary" href="/sport/softball/girls/?tab=news" role="menuitem" aria-label="Softball(Girls) - News" tabindex="0">News</a>
1904                                                            </div>
1905                                                        </div>
1906                                                    </div>
1907                                                </div>
1908                                            </li>
1909                                            <li role="menuitem">
1910                                                <div class="sport-link-nfo">
1911                                                    <div class="row">
1912                                                        <div class="col-xs-12 col-sm-6">
1913                                                            <div class="link">
1914                                                                <a class="text-primary" href="/sport/volleyball/girls/" role="menuitem" tabindex="0" aria-label="Volleyball go to Main Team Page">VOLLEYBALL</a>
1915                                                            </div>
1916                                                        </div>
1917                                                        <div class="hidden-xs col-sm-6">
1918                                                            <div class="nfo">
1919                                                                <a class="text-primary" href="/sport/volleyball/girls/?tab=schedule" role="menuitem" aria-label="Volleyball - Schedules" tabindex="0">Schedules</a><span> /</span>
1920                                                                <a class="text-primary" href="/sport/volleyball/girls/?tab=roster" role="menuitem" aria-label="Volleyball - Rosters" tabindex="0">Rosters</a><span> /</span>
1921                                                                <a class="text-primary" href="/sport/volleyball/girls/?tab=news" role="menuitem" aria-label="Volleyball - News" tabindex="0">News</a>
1922                                                            </div>
1923                                                        </div>
1924                                                    </div>
1925                                                </div>
1926                                            </li>
1927                                    </ul>
1928                            </li>
1929                            <li role="presentation">
1930                                    <a class="slanted-btn text-primary-font" href="#" role="menuitem" tabindex="0"><span>INSIDE ATHLETICS</span></a>
1931                            </li>
1932                            <li role="presentation">
1933                                    <a class="slanted-btn text-primary-font" href="/photos" role="menuitem" tabindex="0"><span>PHOTOS</span></a>
1934                            </li>
1935                            <li role="presentation">
1936                                    <a class="slanted-btn text-primary-font" href="/news" role="menuitem" tabindex="0"><span>NEWS</span></a>
1937                            </li>
1938                    <li id="more" class="hidden" role="presentation">
1939                        <a class="dropdown-toggle text-primary-font" data-toggle="dropdown" aria-haspopup="true" href="#" role="menuitem" aria-expanded="false" tabindex="0">
1940                            More <span class="caret"></span>
1941                        </a>
1942                        <ul class="dropdown-menu dropdown-menu-right" role="menu"></ul>
1943                    </li>
1944                </ul>
1945
1946                    <div class="presenting-sponsor-mobile-menu hidden-sm hidden-xs">
1947                        <div class="adzone adzone-0 presenting-sponsor">
1948                                <div class="ad-placement">
1949    <div id='gam-presenting-sponsor-2' class="gam-presenting-sponsor-2"></div>
1950    </div>
1951
1952                        </div>
1953                    </div>
1954            </div>
1955        </div>
1956    </div>
1957    <div class="mobile-cal-bar bg-primary"><button type="button" class="mcb-toggle" id="mcbToggle" aria-expanded="false"><i class="fa fa-calendar"></i> Calendar <i class="fa fa-caret-down mcb-caret"></i></button><a href="/calendar" class="mcb-full"><i class="fa fa-arrow-right"></i></a></div>
1958</nav>
1959
1960<!--Centerville-->
1961
1962                            
1963                        </div>
1964                        <div class="clearfix"></div>
1965                    </div>
1966                </div>
1967            </div>
1968        </div>
1969        
1970    </header>
1971    <div class="banner-ad-container-sticky-footer">
1972        <div class="banner-ad">
1973            <div class="banner">
1974    <div class="row">
1975        <div class="col-md-12 col-sm-12">            
1976            <div class="ad-placement">
1977                <div id='gam-banner-ad' class="gam-banner-ad">
1978                    
1978<script>
1979                        googletag.cmd.push(function () { googletag.display('gam-banner-ad'); });
1980                    </script>
1980
1981                </div>
1982            </div>
1983        </div>
1984    </div>
1985</div>
1986
1987        </div>
1988    </div>
1989    <div class="cd-main-content">
1990        <div class="row">
1991                <div class="col-md-3">
1992                    <div class="vertical-menu">
1993                        
1994                            
1995<nav class="cd-side-nav" role="navigation">
1996    <div class="row">
1997    <div class="feeder-container">
1998    </div>
1999</div>
2000
2001    <ul>
2002                <li class="cd-label text-secondary border-top-sm-secondary border-bottom-sm-secondary">
2003              
2004                        ATHLETICS
2005                 
2006                </li>
2007                        <li class="has-children bg-primary schedules">
2008                            <a href="#" aria-label="SCHEDULES link" aria-expanded="false" aria-haspopup="true">schedules</a>
2009                            <ul class="large-submenu bg-primary">
2010                                <li>
2011                                    <div class="row">
2012                                            <div class="col-md-6">
2013                                                <div>
2014                                                    <span class="sidebar-subnav-header" aria-label="boys">
2015                                                        <strong>boys</strong>
2016                                                    </span>
2017                                                </div>
2018                                                    <div><a href="/sport/baseball/boys" aria-label="Baseball">baseball</a></div>
2019                                                    <div><a href="/sport/basketball/boys" aria-label="Basketball">basketball</a></div>
2020                                                    <div><a href="/sport/football/boys" aria-label="Football">football</a></div>
2021                                                    <div><a href="/sport/soccer/boys" aria-label="Soccer">soccer</a></div>
2022                                            </div>
2023                                            <div class="col-md-6">
2024                                                <div>
2025                                                    <span class="sidebar-subnav-header" aria-label="girls">
2026                                                        <strong>girls</strong>
2027                                                    </span>
2028                                                </div>
2029                                                    <div><a href="/sport/basketball/girls" aria-label="Basketball">basketball</a></div>
2030                                                    <div><a href="/sport/soccer/girls" aria-label="Soccer">soccer</a></div>
2031                                                    <div><a href="/sport/softball/girls" aria-label="Softball">softball</a></div>
2032                                                    <div><a href="/sport/volleyball/girls" aria-label="Volleyball">volleyball</a></div>
2033                                            </div>
2034                                    </div>
2035                                </li>
2036                            </ul>
2037                        </li>
2038                        <li class="bg-primary">
2039                                <a href="/news" aria-label="NEWS">news</a>
2040                        </li>
2041                        <li class="has-children bg-primary rosters">
2042                            <a href="#" aria-label="ROSTERS link" aria-expanded="false" aria-haspopup="true">rosters</a>
2043                            <ul class="large-submenu bg-primary">
2044                                <li>
2045                                    <div class="row">
2046                                            <div class="col-md-6">
2047                                                <div>
2048                                                    <span class="sidebar-subnav-header" aria-label="boys">
2049                                                        <strong>boys</strong>
2050                                                    </span>
2051                                                </div>
2052                                                    <div><a href="/sport/baseball/boys?tab=roster" aria-label="Baseball">baseball</a></div>
2053                                                    <div><a href="/sport/basketball/boys?tab=roster" aria-label="Basketball">basketball</a></div>
2054                                                    <div><a href="/sport/football/boys?tab=roster" aria-label="Football">football</a></div>
2055                                                    <div><a href="/sport/soccer/boys?tab=roster" aria-label="Soccer">soccer</a></div>
2056                                            </div>
2057                                            <div class="col-md-6">
2058                                                <div>
2059                                                    <span class="sidebar-subnav-header" aria-label="girls">
2060                                                        <strong>girls</strong>
2061                                                    </span>
2062                                                </div>
2063                                                    <div><a href="/sport/basketball/girls?tab=roster" aria-label="Basketball">basketball</a></div>
2064                                                    <div><a href="/sport/soccer/girls?tab=roster" aria-label="Soccer">soccer</a></div>
2065                                                    <div><a href="/sport/softball/girls?tab=roster" aria-label="Softball">softball</a></div>
2066                                                    <div><a href="/sport/volleyball/girls?tab=roster" aria-label="Volleyball">volleyball</a></div>
2067                                            </div>
2068                                    </div>
2069                                </li>
2070                            </ul>
2071                        </li>
2072                        <li class="has-children bg-primary coaches-and-staff">
2073                            <a href="#" aria-label="COACHES AND STAFF link" aria-expanded="false" aria-haspopup="true">coaches and staff</a>
2074                            <ul class="large-submenu bg-primary">
2075                                <li>
2076                                    <div class="row">
2077                                            <div class="col-md-6">
2078                                                <div>
2079                                                    <span class="sidebar-subnav-header" aria-label="boys">
2080                                                        <strong>boys</strong>
2081                                                    </span>
2082                                                </div>
2083                                                    <div><a href="/sport/baseball/boys?tab=staff" aria-label="Baseball">baseball</a></div>
2084                                                    <div><a href="/sport/basketball/boys?tab=staff" aria-label="Basketball">basketball</a></div>
2085                                                    <div><a href="/sport/football/boys?tab=staff" aria-label="Football">football</a></div>
2086                                                    <div><a href="/sport/soccer/boys?tab=staff" aria-label="Soccer">soccer</a></div>
2087                                            </div>
2088                                            <div class="col-md-6">
2089                                                <div>
2090                                                    <span class="sidebar-subnav-header" aria-label="girls">
2091                                                        <strong>girls</strong>
2092                                                    </span>
2093                                                </div>
2094                                                    <div><a href="/sport/basketball/girls?tab=staff" aria-label="Basketball">basketball</a></div>
2095                                                    <div><a href="/sport/soccer/girls?tab=staff" aria-label="Soccer">soccer</a></div>
2096                                                    <div><a href="/sport/softball/girls?tab=staff" aria-label="Softball">softball</a></div>
2097                                                    <div><a href="/sport/volleyball/girls?tab=staff" aria-label="Volleyball">volleyball</a></div>
2098                                            </div>
2099                                    </div>
2100                                </li>
2101                            </ul>
2102                        </li>
2103                <li class="cd-label text-secondary border-top-sm-secondary border-bottom-sm-secondary">
2104              
2105                        RESOURCES
2106                 
2107                </li>
2108                        <li class="bg-primary">
2109                                <a href="/links" aria-label="LINKS">links</a>
2110                        </li>
2111                        <li class="bg-primary">
2112                                <a href="/documents" aria-label="FORMS">forms</a>
2113                        </li>
2114    </ul>
2115</nav>
2116                        
2117                    </div>
2118                </div>
2119                <div class="col-md-9">
2120                    <div class="content-wrapper" id="main-content" role="main">
2121                        
2122<div class="composite-calendar-view">
2123    <div class="container">
2124        <div class="cal-card">
2125            <div class="cal-header">
2126                <h1 class="cal-title">Composite Schedule</h1>
2127                <div class="cal-header-controls">
2128                    <select class="cal-select" id="sportFilter" aria-label="Filter by sport">
2129                        <option value="">All Sports</option>
2130                                <option value="Baseball">Baseball</option>
2131                                <option value="Basketball">Basketball</option>
2132                                <option value="Football">Football</option>
2133                                <option value="Soccer">Soccer</option>
2134                                <option value="Softball">Softball</option>
2135                                <option value="Volleyball">Volleyball</option>
2136                    </select>
2137                    <select class="cal-select" id="schoolTeams" aria-label="Filter by team">
2138                        <option value="0">All Teams</option>
2139                            <option value="9608" data-sport="Soccer">Boys Varsity Soccer</option>
2140                            <option value="9611" data-sport="Basketball">Boys Varsity Basketball</option>
2141                            <option value="9614" data-sport="Baseball">Boys Varsity Baseball</option>
2142                            <option value="9615" data-sport="Football">Boys Varsity Football</option>
2143                            <option value="9898" data-sport="Soccer">Boys JV Soccer</option>
2144                            <option value="9899" data-sport="Basketball">Boys JV Basketball</option>
2145                            <option value="66070" data-sport="Basketball">Boys Freshman Basketball</option>
2146                            <option value="9610" data-sport="Soccer">Girls Varsity Soccer</option>
2147                            <option value="9613" data-sport="Volleyball">Girls Varsity Volleyball</option>
2148                            <option value="9616" data-sport="Basketball">Girls Varsity Basketball</option>
2149                            <option value="9895" data-sport="Softball">Girls JV Softball</option>
2150                            <option value="9896" data-sport="Soccer">Girls JV Soccer</option>
2151                    </select>
2152                    <button type="button" class="sch-cal-sub-btn" data-sch-subscribe-open
2153                            aria-haspopup="dialog" aria-controls="sch-cal-sub-modal">
2154                        <i class="fa fa-calendar-plus-o" aria-hidden="true"></i>
2155                        <span>Subscribe to Calendar</span>
2156                    </button>
2157                </div>
2158            </div>
2159            <div id="importMessages" role="status"></div>
2160            <div id="calendar"></div>
2161        </div>
2162    </div>
2163</div>
2164
2165<div class="sch-cal-sub-overlay" data-sch-subscribe-overlay
2166     data-school-id="958"
2167     data-school-name="St. Martin High School"
2168     data-api-base="https://mmboltapi.azurewebsites.net/api/v2/events" hidden>
2169    <div class="sch-cal-sub-modal" role="dialog" aria-modal="true"
2170         aria-labelledby="sch-cal-sub-title" aria-describedby="sch-cal-sub-scope"
2171         id="sch-cal-sub-modal">
2172        <header class="sch-cal-sub-header">
2173            <div class="sch-cal-sub-logo" aria-hidden="true">
2174                <i class="fa fa-calendar-plus-o"></i>
2175            </div>
2176            <h2 id="sch-cal-sub-title" class="sch-cal-sub-title">Subscribe to the Calendar</h2>
2177            <button type="button" class="sch-cal-sub-close"
2178                    data-sch-subscribe-close aria-label="Close subscribe dialog">
2179                <i class="fa fa-times" aria-hidden="true"></i>
2180            </button>
2181        </header>
2182
2183        <p id="sch-cal-sub-scope" class="sch-cal-sub-scope">
2184            <span class="sch-cal-sub-scope-label">You are subscribing to</span>
2185            <strong data-sch-subscribe-scope-target>the full calendar, every sport and every team</strong>
2186            <span class="sch-cal-sub-scope-hint" data-sch-subscribe-scope-hint></span>
2187        </p>
2188
2189        <p class="sch-cal-sub-lede">Pick the calendar app you use and your schedule stays in
2190            sync automatically as games are added or changed. The Excel and Download .ics
2191            options give you a one-time copy that won&rsquo;t update on its own.</p>
2192
2193        <div class="sch-cal-sub-grid" role="list">
2194            <a href="https://calendar.google.com/calendar/r?cid=webcal%3A%2F%2Fmmboltapi.azurewebsites.net%2Fapi%2Fv2%2Fevents%2Fcalendar%2F958%2F0%2Fcalendar.ics" data-sch-subscribe-provider="google"
2195               data-ics-url="https://mmboltapi.azurewebsites.net/api/v2/events/calendar/958/0/calendar.ics"
2196               target="_blank" rel="noopener" class="sch-cal-sub-tile" role="listitem">
2197                <i class="fa fa-google" aria-hidden="true"></i>
2198                <span>Google</span>
2199            </a>
2200            <a href="webcal://mmboltapi.azurewebsites.net/api/v2/events/calendar/958/0/calendar.ics" data-sch-subscribe-provider="apple"
2201               class="sch-cal-sub-tile" role="listitem">
2202                <i class="fa fa-apple" aria-hidden="true"></i>
2203                <span>Apple</span>
2204            </a>
2205            <a href="https://outlook.office.com/calendar/0/addfromweb?url=https%3A%2F%2Fmmboltapi.azurewebsites.net%2Fapi%2Fv2%2Fevents%2Fcalendar%2F958%2F0%2Fcalendar.ics&amp;name=St.%20Martin%20High%20School%20Schedule" data-sch-subscribe-provider="outlook365"
2206               target="_blank" rel="noopener" class="sch-cal-sub-tile" role="listitem">
2207                <i class="fa fa-windows" aria-hidden="true"></i>
2208                <span>Microsoft 365</span>
2209            </a>
2210            <a href="https://outlook.live.com/calendar/0/addfromweb?url=https%3A%2F%2Fmmboltapi.azurewebsites.net%2Fapi%2Fv2%2Fevents%2Fcalendar%2F958%2F0%2Fcalendar.ics&amp;name=St.%20Martin%20High%20School%20Schedule" data-sch-subscribe-provider="outlook"
2211               target="_blank" rel="noopener" class="sch-cal-sub-tile" role="listitem">
2212                <i class="fa fa-envelope" aria-hidden="true"></i>
2213                <span>Outlook.com</span>
2214            </a>
2215            <a href="https://calendar.google.com/calendar/r?cid=webcal%3A%2F%2Fmmboltapi.azurewebsites.net%2Fapi%2Fv2%2Fevents%2Fcalendar%2F958%2F0%2Fcalendar.ics" data-sch-subscribe-provider="android"
2216               data-ics-url="https://mmboltapi.azurewebsites.net/api/v2/events/calendar/958/0/calendar.ics"
2217               target="_blank" rel="noopener" class="sch-cal-sub-tile" role="listitem">
2218                <i class="fa fa-android" aria-hidden="true"></i>
2219                <span>Android</span>
2220            </a>
2221            <a href="/Calendar/Schedule.csv" data-sch-subscribe-provider="excel"
2222               class="sch-cal-sub-tile" role="listitem">
2223                <i class="fa fa-file-excel-o" aria-hidden="true"></i>
2224                <span>Excel</span>
2225            </a>
2226            <a href="https://mmboltapi.azurewebsites.net/api/v2/events/downloadcalendar/958/0" data-sch-subscribe-provider="other"
2227               class="sch-cal-sub-tile" role="listitem">
2228                <i class="fa fa-download" aria-hidden="true"></i>
2229                <span>Download .ics</span>
2230            </a>
2231        </div>
2232
2233        <div class="sch-cal-sub-url-row">
2234            <label for="sch-cal-sub-url">Feed URL</label>
2235            <input id="sch-cal-sub-url" type="text" readonly value="https://mmboltapi.azurewebsites.net/api/v2/events/calendar/958/0/calendar.ics" />
2236            <button type="button" class="sch-cal-sub-copy" data-sch-subscribe-copy>
2237                <i class="fa fa-copy" aria-hidden="true"></i> Copy
2238            </button>
2239        </div>
2240
2241        <footer class="sch-cal-sub-footer">
2242            <button type="button" class="sch-cal-sub-primary"
2243                    data-sch-subscribe-primary>Subscribe Now</button>
2244        </footer>
2245    </div>
2246</div>
2247
2248
2249
2250                    </div>
2251                </div>
2252        </div>
2253        
2254        <footer>
2255            
2256                
2257            
2258            
2259                <div class="footer bg-primary">
2260    <div class="footer-contain">
2261        <div id="footer-gradient" class="angle-primary-secondary bg-primary"></div>
2262        <div id="footer-gradient-bottom" class="bg-primary">
2263            <div class="row">
2264                <div class="col-md-12">
2265                    <div id="address">
2266                        <p>
2267                                ATHLETIC OFFICE - (228) 872-0256<br />
2268                            10700 YELLOW JACKET BLVD.<br />
2269                            Ocean Springs, MS 39564<br />
2270                        </p>
2271                        <br />
2272                        <p>Thank you to all of our <a style="color: #fff; text-decoration: underline; padding: 3px;" href="/sponsor/SponsorsPage">Sponsors!</a></p>
2273                    </div>
2274                </div>
2275            </div>
2276            <!-- app promotion -->
2277            <div class="footer-items">
2278                <div class="row">
2279                    <div class="col-md-12">
2280                        <div id="app-downloads">
2281                            <div id="badges">
2282                                <div class="row">
2283                                    <div class="col-sm-12">
2284                                            <a href="https://itunes.apple.com/us/app/niaaa/id963291250?mt=8" target="_blank"><img class="img-responsive download" src="/images/dl-apple.png" aria-label="Apple App Store Badge" alt="Apple App Store Badge" /></a>
2285                                            <img class="img-responsive app-icon" src="/images/niaaa-icon.png" aria-label="Mascot Media App Icon Logo" alt="Mascot Media App Icon Logo" />
2286
2287                                            <a href="https://play.google.com/store/apps/details?id=com.sidelineaccess.niaaa&hl=en" target="_blank"><img class="img-responsive download" src="/images/dl-google.png" aria-label="Google Play Store Badge" alt="Google Play Store Badge" /></a>
2288                                    </div>
2289                                </div>
2290                            </div>
2291                        </div>
2292                    </div>
2293                </div>
2294            </div>
2295        </div>
2296    </div>
2297    <div class="feeder-schools-footer bg-primary">
2298    </div>
2299</div>
2300                <div class="footer bg-primary">
2301    <div class="widget padded-box">
2302        <div class="footer-items">
2303            <div class="row">
2304                <div class="col-md-12">
2305                    
2306                </div>
2307            </div>
2308        </div>
2309    </div>
2310</div>
2311            
2312        </footer>
2313    </div>
2314    <div class="privacy-terms">
2315        <a href="http://www.mascotmedia.net/privacy-policy/" target="_blank" rel="noopener noreferrer">PRIVACY POLICY</a> <span class="sr-only">(opens in a new tab)</span> |
2316
2317
2318        <span>&copy; 2026 MASCOT MEDIA, LLC</span>
2319    </div>
2320    <div class="ad-space">
2321    </div>
2322    
2323        
2323<script src="/lib/jquery/dist/jquery.min.js"></script>
2323
2324        
2324<script src="/js/lity.js"></script>
2324
2325        
2325<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
2325
2326        
2326<script type="text/javascript" src="/js/scrollfixed.min.js"></script>
2326
2327        
2327<script src="/js/topmenu2.min.js?v=1.1"></script>
2327
2328        
2328<script src="/js/sidenav.min.js"></script>
2328
2329        
2329<script src="/js/latestheadlines.min.js"></script>
2329
2330        
2330<script src="/lib/datatables/media/js/jquery.dataTables.min.js"></script>
2330
2331        
2331<script src="/lib/datatables/media/js/dataTables.bootstrap.min.js"></script>
2331
2332        
2332<script src="/lib/datatables-responsive/js/dataTables.responsive.min.js"></script>
2332
2333        
2333<script src="/lib/jquery.menu-aim/jquery.menu-aim.min.js"></script>
2333
2334        
2334<script src="https://cdn.jsdelivr.net/jquery.slick/1.3.15/slick.min.js"></script>
2334
2335        
2335<script src="/js/StagingButtons.min.js"></script>
2335
2336        
2336<script src="/lib/sweetalert/dist/sweetalert.min.js"></script>
2336
2337        
2337<script src="/lib/slick-carousel/slick/slick.min.js"></script>
2337
2338        
2338<script src="/js/PlatinumSponsorStyle2.min.js"></script>
2338
2339        
2339<script src="/js/CommitmentsStyle1.min.js"></script>
2339
2340
2341    
2342
2343    
2344    
2344<script src="/lib/moment/moment.js"></script>
2344
2345    
2345<script src="/lib/fullcalendar/dist/fullcalendar.js"></script>
2345
2346
2347    
2347<script type="text/javascript">
2348        $(document).ready(function () {
2349            setTimeout(function () {
2350                $('#calendar').fullCalendar({
2351                    eventRender: function (event, element) {
2352                        // Keyboard + SR access for month-grid events (WCAG 2.1.1)
2353                        element.attr('tabindex', '0');
2354                        element.attr('aria-label', (event.title || '') + (event.start ? ', ' + event.start.format('MMMM D') : ''));
2355                        element.on('keydown', function (e) {
2356                            if (e.key === 'Enter' || e.keyCode === 13) { $(this).trigger('click'); }
2357                        });
2358                    },
2359                    header: {
2360                        left: 'prev,next today',
2361                        center: 'title',
2362                        right: 'month,listMonth'
2363                    },
2364                    events: {
2365                        url: '/CalendarEvents/',
2366                        type: 'GET',
2367                        data: {
2368                            schoolTeamId: '0'
2369                        },
2370                        color: '#e6e7e8',
2371                        textColor: 'black'
2372                    },
2373                    contentHeight: "auto",
2374                    themeSystem: 'bootstrap3',
2375                    eventLimit: 4,
2376                    windowResize: function (view) {
2377                        if ($(window).width() < 991) {
2378                            $('#calendar').fullCalendar('changeView', 'listMonth');
2379                        }
2380                    }
2381                });
2382            }, 500);
2383
2384            // Enhanced import handler with Google Calendar smart fallback
2385            $(document).on('change', '#importCal', function () {
2386                var selectedOption = $(this).find('option:selected');
2387                var importUrl = $(this).val();
2388
2389                if (importUrl == "") {
2390                    return false;
2391                }
2392
2393                if (selectedOption.attr('id') === 'googleCalImport') {
2394                    handleGoogleCalendarImport(selectedOption);
2395                } else {
2396                    window.open(importUrl, '_blank');
2397                }
2398
2399                $(this).val('');
2400            });
2401
2402            // Picking a sport narrows the Team dropdown to that sport's teams
2403            // instead of wiping the selection: "Soccer" then leaves Boys
2404            // Varsity, Girls JV and so on to choose from.
2405            $(document).on('change', '#sportFilter', function () {
2406                var sport = $(this).val();
2407                applyCalendarFilters(sport, filterTeamsBySport(sport));
2408            });
2409
2410            $(document).on('change', '#schoolTeams', function () {
2411                applyCalendarFilters($('#sportFilter').val(), $(this).val());
2412            });
2413
2414            // Initialize calendar links
2415            ConfigureCalendarLinks(958, '0');
2416        });
2417
2418        function handleGoogleCalendarImport(optionElement) {
2419            var importUrl = optionElement.val();
2420            var icsUrl = optionElement.data('ics-url');
2421
2422            // Show the fallback panel immediately so it is waiting on this tab
2423            // when the user comes back from Google Calendar (whether the import
2424            // succeeded or showed "Unable to add calendar").
2425            showImportFallback(icsUrl);
2426
2427            // Try the one-click cid import.
2428            window.open(importUrl, '_blank');
2429        }
2430
2431        function showImportFallback(icsUrl) {
2432            if ($('.import-fallback').length) { return; }
2433            var safeUrl = String(icsUrl).replace(/'/g, "\\'");
2434            var html = '<div class="import-message import-fallback alert alert-warning">' +
2435                '<button type="button" class="close" onclick="$(this).parent().remove();">&times;</button>' +
2436                '<strong>Calendar did not import?</strong> ' +
2437                '<button class="btn btn-sm btn-primary" onclick="copyUrlAndOpenSettings(\'' + safeUrl + '\')">Open Google Calendar</button> ' +
2438                'to add it manually (URL will be copied to your clipboard).' +
2439                '</div>';
2440            $('#importMessages').prepend(html);
2441        }
2442
2443        function showImportMessage(message, type) {
2444            var alertClass = type === 'error' ? 'alert-danger' : 'alert-info';
2445            var messageHtml = '<div class="import-message alert ' + alertClass + '">' +
2446                '<button type="button" class="close" onclick="$(this).parent().remove();">&times;</button>' +
2447                message +
2448                '</div>';
2449
2450            $('.import-message').remove(); // Remove existing messages
2451            $('#importMessages').prepend(messageHtml);
2452        }
2453
2454        function copyUrlAndOpenSettings(icsUrl) {
2455            var openSettings = function () {
2456                window.open('https://calendar.google.com/calendar/u/0/r/settings/addbyurl', '_blank');
2457            };
2458            if (navigator.clipboard && navigator.clipboard.writeText) {
2459                navigator.clipboard.writeText(icsUrl).then(openSettings, openSettings);
2460            } else {
2461                openSettings();
2462            }
2463        }
2464
2465        function showManualInstructions(icsUrl) {
2466            var instructionsHtml = '<div class="import-message alert alert-info">' +
2467                '<button type="button" class="close" onclick="$(this).parent().remove();">&times;</button>' +
2468                '<strong>Manual Import Instructions:</strong><br>' +
2469                '1. <button class="btn btn-sm btn-success" onclick="copyUrlToClipboard(\'' + icsUrl + '\', this)">Copy Calendar URL</button><br><br>' +
2470                '2. <a href="https://calendar.google.com/calendar/u/0/r/settings/addbyurl" target="_blank" class="btn btn-sm btn-primary">Open Google Calendar Settings</a><br><br>' +
2471                '3. Paste the URL in the "URL of calendar" field<br>' +
2472                '4. Click "Add calendar"' +
2473                '</div>';
2474
2475            $('.import-message').remove();
2476            $('#importMessages').prepend(instructionsHtml);
2477        }
2478
2479        function copyUrlToClipboard(url, buttonElement) {
2480            if (navigator.clipboard) {
2481                navigator.clipboard.writeText(url).then(function () {
2482                    $(buttonElement).text('Copied!').removeClass('btn-success').addClass('btn-secondary');
2483                    setTimeout(function () {
2484                        $(buttonElement).text('Copy Calendar URL').removeClass('btn-secondary').addClass('btn-success');
2485                    }, 2000);
2486                }).catch(function () {
2487                    // Fallback: show the URL for manual copying
2488                    showUrlForManualCopy(url, buttonElement);
2489                });
2490            } else {
2491                // Fallback: show the URL for manual copying
2492                showUrlForManualCopy(url, buttonElement);
2493            }
2494        }
2495
2496        function showUrlForManualCopy(url, buttonElement) {
2497            var urlBox = '<div class="ics-url-box" onclick="selectText(this)" style="margin-top: 10px;">' + url + '</div>';
2498            $(buttonElement).after(urlBox);
2499            $(buttonElement).text('Click URL below to copy').removeClass('btn-success').addClass('btn-warning');
2500        }
2501
2502        function selectText(element) {
2503            var range = document.createRange();
2504            range.selectNodeContents(element);
2505            var selection = window.getSelection();
2506            selection.removeAllRanges();
2507            selection.addRange(range);
2508
2509            try {
2510                document.execCommand('copy');
2511                $(element).css('background-color', '#d4edda').after('<span style="color: green; font-size: 12px;"> Copied!</span>');
2512                setTimeout(function () {
2513                    $(element).css('background-color', '#f9f9f9').next('span').remove();
2514                }, 2000);
2515            } catch (err) {
2516                console.log('Copy failed:', err);
2517            }
2518        }
2519
2520        function guid() {
2521            function s4() {
2522                return Math.floor((1 + Math.random()) * 0x10000)
2523                    .toString(16)
2524                    .substring(1);
2525            }
2526            return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
2527                s4() + '-' + s4() + s4() + s4();
2528        }
2529
2530        var schoolTeamOptions = null;
2531
2532        // Snapshot of every team option, taken before the first narrowing so a
2533        // later sport change rebuilds from the full list rather than from
2534        // whatever survived the previous one.
2535        function teamOptionSnapshot() {
2536            if (!schoolTeamOptions) {
2537                schoolTeamOptions = $('#schoolTeams option').map(function () {
2538                    return { value: this.value, text: this.text, sport: this.getAttribute('data-sport') || '' };
2539                }).get();
2540            }
2541            return schoolTeamOptions;
2542        }
2543
2544        // Rebuilds the Team dropdown for the selected sport and returns the team
2545        // id that survived: the previous pick if it belongs to this sport,
2546        // otherwise All Teams.
2547        function filterTeamsBySport(sport) {
2548            var select = document.getElementById('schoolTeams');
2549            if (!select) { return '0'; }
2550
2551            var previous = select.value;
2552            var wanted = (sport || '').toLowerCase();
2553            var options = teamOptionSnapshot().filter(function (o) {
2554                return o.value === '0' || !wanted || o.sport.toLowerCase() === wanted;
2555            });
2556
2557            select.innerHTML = '';
2558            options.forEach(function (o) {
2559                var option = document.createElement('option');
2560                option.value = o.value;
2561                option.text = o.text; // .text, not innerHTML: school-entered data
2562                if (o.sport) { option.setAttribute('data-sport', o.sport); }
2563                select.appendChild(option);
2564            });
2565
2566            select.value = options.some(function (o) { return o.value === previous; }) ? previous : '0';
2567            return select.value;
2568        }
2569
2570        // Single path for both dropdowns, so the month grid and the subscribe
2571        // links can never disagree about what is being shown.
2572        function applyCalendarFilters(sport, schoolTeamId) {
2573            var teamId = String(schoolTeamId || '0');
2574            var source = {
2575                url: '/CalendarEvents/', type: 'GET',
2576                data: { schoolTeamId: teamId },
2577                color: '#e6e7e8', textColor: 'black'
2578            };
2579            // A team belongs to exactly one sport, so the sport filter only has
2580            // work to do while the feed is still school-wide.
2581            if (sport && teamId === '0') {
2582                source.success = function (events) {
2583                    return events.filter(function (e) {
2584                        return e.title && e.title.toLowerCase().indexOf(sport.toLowerCase()) > -1;
2585                    });
2586                };
2587            }
2588
2589            $('#calendar').fullCalendar('removeEventSources');
2590            $('#calendar').fullCalendar('addEventSource', source);
2591            ConfigureCalendarLinks(958, teamId);
2592        }
2593
2594        // Points every tile in the subscribe modal at the currently selected
2595        // team. The feed URL carries the team id (0 = the school's whole
2596        // calendar), so choosing "Boys Varsity Soccer" produces a Boys Varsity
2597        // Soccer subscription rather than every game the school plays.
2598        //
2599        // Deliberately no cache-buster on the .ics URL: Google keys a
2600        // subscription off the exact URL, so a per-load guid would let one
2601        // parent stack up a duplicate calendar on every visit.
2602        function ConfigureCalendarLinks(schoolId, schoolTeamId) {
2603            var overlay = document.querySelector('[data-sch-subscribe-overlay]');
2604            if (!overlay) { return; }
2605
2606            var teamId = String(schoolTeamId || '0');
2607            var apiBase = overlay.getAttribute('data-api-base');
2608            var schoolName = overlay.getAttribute('data-school-name') || 'School';
2609            var teamLabel = teamId !== '0'
2610                ? $('#schoolTeams option:selected').text().replace(/\s+/g, ' ').trim()
2611                : '';
2612
2613            var icsHttps = apiBase + '/calendar/' + schoolId + '/' + teamId + '/calendar.ics';
2614            var icsWebcal = icsHttps.replace(/^https:/i, 'webcal:');
2615            var encodedIcs = encodeURIComponent(icsHttps);
2616            var googleUrl = 'https://calendar.google.com/calendar/r?cid=' + encodeURIComponent(icsWebcal);
2617            var calName = encodeURIComponent(teamLabel ? schoolName + ' ' + teamLabel : schoolName + ' Schedule');
2618
2619            setSubscribeTile(overlay, 'google', googleUrl, icsHttps);
2620            setSubscribeTile(overlay, 'android', googleUrl, icsHttps);
2621            setSubscribeTile(overlay, 'apple', icsWebcal);
2622            setSubscribeTile(overlay, 'outlook365', 'https://outlook.office.com/calendar/0/addfromweb?url=' + encodedIcs + '&name=' + calName);
2623            setSubscribeTile(overlay, 'outlook', 'https://outlook.live.com/calendar/0/addfromweb?url=' + encodedIcs + '&name=' + calName);
2624            setSubscribeTile(overlay, 'excel', '/Calendar/Schedule.csv?schoolTeamId=' + encodeURIComponent(teamId));
2625            setSubscribeTile(overlay, 'other', apiBase + '/downloadcalendar/' + schoolId + '/' + teamId);
2626
2627            var urlInput = overlay.querySelector('#sch-cal-sub-url');
2628            if (urlInput) { urlInput.value = icsHttps; }
2629
2630            // textContent, not innerHTML: the team label is school-entered data.
2631            var scopeTarget = overlay.querySelector('[data-sch-subscribe-scope-target]');
2632            var scopeHint = overlay.querySelector('[data-sch-subscribe-scope-hint]');
2633            if (scopeTarget) {
2634                scopeTarget.textContent = teamLabel || 'the full calendar, every sport and every team';
2635            }
2636            if (scopeHint) {
2637                if (teamLabel) {
2638                    scopeHint.textContent = 'Only this team. Set the Team dropdown back to All Teams for the whole calendar.';
2639                } else if ($('#sportFilter').val()) {
2640                    scopeHint.textContent = 'A sport on its own cannot be subscribed to. Pick a team in the Team dropdown to get just that team.';
2641                } else {
2642                    scopeHint.textContent = 'Pick a team in the Team dropdown first to subscribe to one team instead.';
2643                }
2644            }
2645        }
2646
2647        function setSubscribeTile(overlay, provider, href, icsUrl) {
2648            var tile = overlay.querySelector('[data-sch-subscribe-provider="' + provider + '"]');
2649            if (!tile) { return; }
2650            tile.setAttribute('href', href);
2651            if (icsUrl) { tile.setAttribute('data-ics-url', icsUrl); }
2652        }
2653
2654        // --- Subscribe-to-Schedule modal -----------------------------
2655        (function () {
2656            var overlay = document.querySelector('[data-sch-subscribe-overlay]');
2657            var openBtn = document.querySelector('[data-sch-subscribe-open]');
2658            if (!overlay || !openBtn) return;
2659            var closeBtn = overlay.querySelector('[data-sch-subscribe-close]');
2660            var urlInput = overlay.querySelector('#sch-cal-sub-url');
2661            var copyBtn = overlay.querySelector('[data-sch-subscribe-copy]');
2662            var primary = overlay.querySelector('[data-sch-subscribe-primary]');
2663            var tiles = overlay.querySelectorAll('[data-sch-subscribe-provider]');
2664            var selected = tiles.length ? tiles[0] : null;
2665
2666            function setSelected(tile) {
2667                selected = tile;
2668                tiles.forEach(function (t) {
2669                    t.classList.toggle('is-active', t === tile);
2670                });
2671            }
2672            function openModal() {
2673                // Rebuild from the live dropdown rather than trusting the last
2674                // change event: browsers restore <select> state on a soft
2675                // reload without firing change, which would otherwise leave the
2676                // tiles pointing at whatever team was picked before the reload.
2677                var teamSelect = document.getElementById('schoolTeams');
2678                ConfigureCalendarLinks(overlay.getAttribute('data-school-id'), teamSelect ? teamSelect.value : '0');
2679                overlay.hidden = false;
2680                document.body.classList.add('sch-cal-sub-locked');
2681                if (selected) setSelected(selected);
2682                setTimeout(function () { primary && primary.focus(); }, 30);
2683            }
2684            function closeModal() {
2685                overlay.hidden = true;
2686                document.body.classList.remove('sch-cal-sub-locked');
2687                openBtn.focus();
2688            }
2689
2690            openBtn.addEventListener('click', openModal);
2691            closeBtn && closeBtn.addEventListener('click', closeModal);
2692            overlay.addEventListener('click', function (e) {
2693                if (e.target === overlay) closeModal();
2694            });
2695            document.addEventListener('keydown', function (e) {
2696                if (!overlay.hidden && e.key === 'Escape') closeModal();
2697            });
2698
2699            tiles.forEach(function (tile) {
2700                tile.addEventListener('click', function (e) {
2701                    setSelected(tile);
2702                    var href = tile.getAttribute('href');
2703                    if (!href || href === '#') {
2704                        e.preventDefault();
2705                        return;
2706                    }
2707                    // Google and Android both route through Google's add-by-URL
2708                    // flow, so show the fallback banner for either before opening.
2709                    var provider = tile.getAttribute('data-sch-subscribe-provider');
2710                    if (provider === 'google' || provider === 'android') {
2711                        var icsUrl = tile.getAttribute('data-ics-url');
2712                        if (icsUrl && typeof showImportFallback === 'function') {
2713                            showImportFallback(icsUrl);
2714                        }
2715                    }
2716                });
2717            });
2718
2719            primary && primary.addEventListener('click', function () {
2720                if (selected) selected.click();
2721            });
2722
2723            copyBtn && copyBtn.addEventListener('click', function () {
2724                urlInput.select();
2725                try { document.execCommand('copy'); } catch (_) { }
2726                if (navigator.clipboard) {
2727                    navigator.clipboard.writeText(urlInput.value).catch(function () { });
2728                }
2729                var orig = copyBtn.innerHTML;
2730                copyBtn.innerHTML = '<i class="fa fa-check" aria-hidden="true"></i> Copied';
2731                setTimeout(function () { copyBtn.innerHTML = orig; }, 1600);
2732            });
2733        })();
2734    </script>
2734
2735
2736
2737    
2738
2739    
2740
2741    
2741<script type="text/javascript">
2742        $.extend(true, $.fn.dataTable.defaults, {
2743            language: {
2744                "processing": "<i class='fa fa-refresh fa-spin fa-2x'></i><br />Loading..."
2745            }
2746        });
2747
2748        $('.dropdown-button').dropdown({
2749            inDuration: 300,
2750            outDuration: 225,
2751            //alignment: "center",
2752            hover: false, // Activate on hover
2753        });
2754    </script>
2754
2755    
2755<script type='text/javascript'>
2756        var url = '';
2757        var regex = /([\d]{10,})/g;
2758        var meta = document.createElement('meta');
2759            meta.setAttribute('name', 'apple-itunes-app');
2760            meta.setAttribute('content', 'app-id=' + url.match(regex));
2761        document.getElementsByTagName('head')[0].appendChild(meta);
2762    </script>
2762
2763
2764    <!-- Quantcast Tag -->
2765    
2765<script type="text/javascript">
2766        window._qevents = window._qevents || [];
2767        (function () {
2768            var elem = document.createElement('script');
2769            elem.src = (document.location.protocol == "https:" ? "https://secure" : "http://edge") + ".quantserve.com/quant.js";
2770            elem.async = true;
2771            elem.type = "text/javascript";
2772            var scpt = document.getElementsByTagName('script')[0];
2773            scpt.parentNode.insertBefore(elem, scpt);
2774        })();
2775        window._qevents.push({
2776            qacct: "p-L8Vz-DsnmdfCj",
2777            uid: "__INSERT_EMAIL_HERE__"
2778        });
2779    </script>
2779
2780    <noscript>
2781        <div style="display:none;">
2782            <img src="//pixel.quantserve.com/pixel/p-L8Vz-DsnmdfCj.gif" border="0" height="1" width="1" alt="Quantcast" />
2783        </div>
2784    </noscript>
2785    <!-- End Quantcast tag -->
2786</body>
2787</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.