@wral/hsot-data 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,66 +1,179 @@
1
- import { LitElement as ee, html as l, css as y, nothing as p, svg as q } from "lit";
2
- const te = 50;
3
- function se(a = {}) {
1
+ import { LitElement as te, html as i, css as b, nothing as p, svg as X } from "lit";
2
+ const ie = 50;
3
+ function ne(a = {}) {
4
4
  const e = Object.entries(a).filter(([, s]) => s != null && s !== "");
5
5
  if (!e.length) return "";
6
6
  const t = new URLSearchParams();
7
7
  return e.forEach(([s, r]) => t.set(s, String(r))), `?${t.toString()}`;
8
8
  }
9
- function ae({ baseUrl: a, token: e = "", fetchFn: t } = {}) {
9
+ function le({ baseUrl: a, token: e = "", fetchFn: t } = {}) {
10
10
  if (!a) throw new Error("createClient requires a baseUrl");
11
- const s = a.replace(/\/+$/, ""), r = t || ((...i) => fetch(...i));
12
- async function o(i) {
13
- const m = { Accept: "application/json" };
14
- e && (m.Authorization = `Bearer ${e}`);
15
- const d = await r(`${s}${i}`, { headers: m });
16
- if (!d.ok) {
17
- const c = new Error(`api-hsot ${d.status} on ${i}`);
18
- throw c.status = d.status, c;
11
+ const s = a.replace(/\/+$/, ""), r = t || ((...n) => fetch(...n));
12
+ async function o(n) {
13
+ const h = { Accept: "application/json" };
14
+ e && (h.Authorization = `Bearer ${e}`);
15
+ const l = await r(`${s}${n}`, { headers: h });
16
+ if (!l.ok) {
17
+ const d = new Error(`api-hsot ${l.status} on ${n}`);
18
+ throw d.status = l.status, d;
19
19
  }
20
- return d.json();
21
- }
22
- async function n(i, m = {}) {
23
- const d = [];
24
- let c = null;
25
- for (let h = 0; h < te; h += 1) {
26
- const f = se(c ? { ...m, cursor: c } : m), u = await o(`${i}${f}`);
27
- if (d.push(...u.items || []), c = u.nextCursor || null, !c) break;
20
+ return l.json();
21
+ }
22
+ async function c(n, h = {}) {
23
+ const l = [];
24
+ let d = null;
25
+ for (let m = 0; m < ie; m += 1) {
26
+ const f = ne(d ? { ...h, cursor: d } : h), g = await o(`${n}${f}`);
27
+ if (l.push(...g.items || []), d = g.nextCursor || null, !d) break;
28
28
  }
29
- return { items: d, total: d.length, nextCursor: null };
29
+ return { items: l, total: l.length, nextCursor: null };
30
30
  }
31
31
  return {
32
- listSchools: (i) => n("/schools", i),
33
- getSchool: (i) => o(`/schools/${i}`),
34
- listTeams: (i) => n("/teams", i),
35
- getTeam: (i) => o(`/teams/${i}`),
36
- listConferences: (i) => n("/conferences", i),
37
- listPlayers: (i) => n("/players", i),
38
- listRosters: (i) => n("/rosters", i),
39
- listGames: (i) => n("/games", i),
40
- getGame: (i) => o(`/games/${i}`),
41
- listTournaments: (i) => n("/tournaments", i),
42
- listSeedings: (i, m) => n(`/tournaments/${i}/seedings`, m),
43
- listRankings: (i) => n("/rankings", i),
32
+ listSchools: (n) => c("/schools", n),
33
+ getSchool: (n) => o(`/schools/${n}`),
34
+ listTeams: (n) => c("/teams", n),
35
+ getTeam: (n) => o(`/teams/${n}`),
36
+ listConferences: (n) => c("/conferences", n),
37
+ listPlayers: (n) => c("/players", n),
38
+ listRosters: (n) => c("/rosters", n),
39
+ listGames: (n) => c("/games", n),
40
+ getGame: (n) => o(`/games/${n}`),
41
+ listTournaments: (n) => c("/tournaments", n),
42
+ listSeedings: (n, h) => c(`/tournaments/${n}/seedings`, h),
43
+ listRankings: (n) => c("/rankings", n),
44
44
  listSports: () => o("/sports")
45
45
  };
46
46
  }
47
- class b extends ee {
47
+ const U = {
48
+ game: "/{sport}/game/{id}/",
49
+ school: "/school/{id}/",
50
+ section: "/{sport}/{view}/"
51
+ };
52
+ function u(a, e) {
53
+ return String(a).replace(/\{(\w+)\}/g, (t, s) => e[s] !== void 0 && e[s] !== null ? String(e[s]) : t);
54
+ }
55
+ function D(a) {
56
+ return {
57
+ game: a.getAttribute("game-href") || U.game,
58
+ school: a.getAttribute("school-href") || U.school,
59
+ section: a.getAttribute("section-href") || U.section
60
+ };
61
+ }
62
+ const T = (a) => a ? a.charAt(0).toUpperCase() + a.slice(1) : "";
63
+ function $(a, e) {
64
+ if (!a) return "TBD";
65
+ const [t, s, r] = String(a).split("-").map(Number);
66
+ return !t || !s || !r ? "TBD" : new Date(t, s - 1, r).toLocaleDateString("en-US", e || { weekday: "short", month: "short", day: "numeric" });
67
+ }
68
+ function L(a) {
69
+ if (!a) return "";
70
+ const [e, t] = String(a).split(":").map(Number);
71
+ if (Number.isNaN(e)) return "";
72
+ const s = e >= 12 ? "PM" : "AM";
73
+ return `${(e + 11) % 12 + 1}:${String(t || 0).padStart(2, "0")} ${s}`;
74
+ }
75
+ function ce(a) {
76
+ return a ? `${Math.floor(a / 12)}-${a % 12}` : "·";
77
+ }
78
+ function N(a = /* @__PURE__ */ new Date()) {
79
+ const e = a.getFullYear();
80
+ return a.getMonth() >= 6 ? `${e}-${e + 1}` : `${e - 1}-${e}`;
81
+ }
82
+ function j(a = /* @__PURE__ */ new Date()) {
83
+ const e = (t) => String(t).padStart(2, "0");
84
+ return `${a.getFullYear()}-${e(a.getMonth() + 1)}-${e(a.getDate())}`;
85
+ }
86
+ function de(a, e = j()) {
87
+ const t = [...new Set((a || []).filter(Boolean))].sort();
88
+ if (!t.length || t.includes(e)) return e;
89
+ const s = t.filter((r) => r < e);
90
+ return s.length ? s[s.length - 1] : t[0];
91
+ }
92
+ function G(a) {
93
+ return a ? (a.abbr || a.name || "?").slice(0, 4).toUpperCase() : "?";
94
+ }
95
+ function E(a) {
96
+ if (!a || !/^#[0-9a-fA-F]{6}$/.test(a)) return "#FFFFFF";
97
+ const e = parseInt(a.slice(1), 16), t = e >> 16 & 255, s = e >> 8 & 255, r = e & 255;
98
+ return 0.299 * t + 0.587 * s + 0.114 * r > 150 ? "#0F1B33" : "#FFFFFF";
99
+ }
100
+ const he = (a) => {
101
+ const e = ["th", "st", "nd", "rd"], t = a % 100;
102
+ return a + (e[(t - 20) % 10] || e[t] || e[0]);
103
+ };
104
+ function me(a) {
105
+ if (a.state === "live") return { kind: "live", label: `Live · ${a.period || ""}`.replace(/ · $/, "") };
106
+ if (a.state === "final") {
107
+ const e = [];
108
+ return a.finish === "overtime" && e.push("OT"), a.finish === "shootout" && e.push("PK-SO"), a.forfeit && a.forfeit !== "none" && e.push("Forfeit"), { kind: "final", label: `Final${e.length ? ` · ${e.join(" · ")}` : ""}` };
109
+ }
110
+ return a.state === "postponed" ? { kind: "warn", label: "Postponed" } : a.state === "canceled" ? { kind: "warn", label: "Canceled" } : { kind: "sched", label: `${$(a.date, { month: "short", day: "numeric" })} · ${L(a.time)}`.replace(/ · $/, "") };
111
+ }
112
+ const pe = /* @__PURE__ */ new Set(["game", "story", "page", "forum", "video", "gallery"]);
113
+ function x(a) {
114
+ let e = String(a || "").replace(/^[a-z][a-z0-9+.-]*:\/\/[^/#?]*/i, "");
115
+ const t = e.indexOf("#");
116
+ let s = "";
117
+ t !== -1 && (s = e.slice(t).split("?")[0], e = e.slice(0, t));
118
+ let r = e.split("?")[0] + s;
119
+ return r = r.replace(/([^:])\/{2,}/g, "$1/").replace(/^\/{2,}/, "/"), r = r.replace(/^\/(?=#)/, ""), r.length > 1 && (r = r.replace(/\/+$/, "")), r.toLowerCase();
120
+ }
121
+ function se() {
122
+ const a = globalThis.location;
123
+ if (!a) return "";
124
+ const e = (a.hash || "").startsWith("#/") ? a.hash : "";
125
+ return x((a.pathname || "") + e);
126
+ }
127
+ function fe(a, e, t) {
128
+ if (!t) return null;
129
+ const s = x(a);
130
+ if (!s) return null;
131
+ const r = x(u(e.game, { sport: t, id: "" })), o = x(u(e.school, { id: "" }));
132
+ if (s === r || s.startsWith(`${r}/`) || s === o || s.startsWith(`${o}/`)) return null;
133
+ const c = x(u(e.section, { sport: t, view: "" }));
134
+ if (s === c) return "";
135
+ if (!s.startsWith(`${c}/`)) return null;
136
+ const n = s.slice(c.length + 1), h = n.split("/");
137
+ return h.length > 2 || h.some((l) => !/^[a-z][a-z-]*$/.test(l)) || pe.has(h[0]) ? null : n;
138
+ }
139
+ function ue(a, e, t) {
140
+ const s = (c) => u(t.section, { sport: a, view: c }).replace(/([^:])\/{2,}/g, "$1/"), o = new Set((e || []).map((c) => c && c.gender).filter((c) => c === "boys" || c === "girls")).size === 2 ? [
141
+ { label: "Boys Standings", href: s("boys/standings") },
142
+ { label: "Girls Standings", href: s("girls/standings") }
143
+ ] : [{ label: "Standings", href: s("standings") }];
144
+ return [
145
+ { label: `${T(a)} Home`, href: s("") },
146
+ { label: "Scores/Schedule", href: s("scores") },
147
+ { label: "Playoff Brackets", href: s("brackets") },
148
+ ...o,
149
+ { label: "Polls & Rankings", href: s("rankings") }
150
+ ];
151
+ }
152
+ function ge(a, e = se()) {
153
+ const t = x(e);
154
+ for (const s of a.querySelectorAll(':scope > a[slot="nav"]'))
155
+ t && x(s.getAttribute("href")) === t ? s.setAttribute("aria-current", "page") : s.removeAttribute("aria-current");
156
+ }
157
+ class y extends te {
48
158
  static properties = {
49
159
  api: { type: String },
50
160
  refreshInterval: { type: Number, attribute: "refresh-interval" },
161
+ promoHref: { type: String, attribute: "promo-href" },
162
+ promoImage: { type: String, attribute: "promo-image" },
163
+ promoAlt: { type: String, attribute: "promo-alt" },
51
164
  data: { state: !0 },
52
165
  loading: { state: !0 },
53
166
  error: { state: !0 }
54
167
  };
55
168
  constructor() {
56
- super(), this.api = "", this.refreshInterval = 0, this.data = null, this.loading = !1, this.error = "", this._client = null, this._refreshId = null;
169
+ super(), this.api = "", this.refreshInterval = 0, this.promoHref = "", this.promoImage = "", this.promoAlt = "", this.data = null, this.loading = !1, this.error = "", this._client = null, this._refreshId = null;
57
170
  }
58
171
  /** Injected client wins; otherwise build a fetch client from the api attribute. */
59
172
  set client(e) {
60
173
  this._client = e, this.isConnected && this.load();
61
174
  }
62
175
  get client() {
63
- return this._client ? this._client : this.api ? ae({ baseUrl: this.api }) : null;
176
+ return this._client ? this._client : this.api ? le({ baseUrl: this.api }) : null;
64
177
  }
65
178
  connectedCallback() {
66
179
  super.connectedCallback(), this._setupInterval();
@@ -72,7 +185,7 @@ class b extends ee {
72
185
  this.load();
73
186
  }
74
187
  updated(e) {
75
- e.has("api") && e.get("api") !== void 0 && e.get("api") !== this.api && this.load(), e.has("refreshInterval") && this._setupInterval();
188
+ e.has("api") && e.get("api") !== void 0 && e.get("api") !== this.api && this.load(), e.has("refreshInterval") && this._setupInterval(), ge(this);
76
189
  }
77
190
  async load() {
78
191
  const e = this.client;
@@ -101,13 +214,13 @@ class b extends ee {
101
214
  this._refreshId && (clearInterval(this._refreshId), this._refreshId = null);
102
215
  }
103
216
  render() {
104
- return this.error === "not-configured" ? l`<div class="error">This component needs an <code>api</code> attribute (the api-hsot public read-surface base URL) or an injected client.</div>` : this.error ? l`<div class="error">Unable to load right now. <button class="chip" @click=${() => this.load()}>Retry</button></div>` : this.data ? this.renderView() : l`<div class="loading" role="status">Loading…</div>`;
217
+ return this.error === "not-configured" ? i`<div class="error">This component needs an <code>api</code> attribute (the api-hsot public read-surface base URL) or an injected client.</div>` : this.error ? i`<div class="error">Unable to load right now. <button class="chip" @click=${() => this.load()}>Retry</button></div>` : this.data ? this.renderView() : i`<div class="loading" role="status">Loading…</div>`;
105
218
  }
106
219
  renderView() {
107
- return l``;
220
+ return i``;
108
221
  }
109
222
  }
110
- const g = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), re = y`
223
+ const v = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), ve = b`
111
224
  :host {
112
225
  --hsot-red: var(--color-red, #D1232A);
113
226
  --hsot-red-deep: var(--color-red-dark, #951C21);
@@ -125,6 +238,10 @@ const g = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), re = y`
125
238
  --hsot-win: var(--color-green-dark, #66A208);
126
239
  --hsot-loss: var(--color-red, #D1232A);
127
240
  --hsot-tie: var(--color-gray-4, #7C7C7C);
241
+ --hsot-section-bg: var(--color-section-header, #1A1A1A);
242
+ --hsot-section-text: var(--color-section-header-text, #FFFFFF);
243
+ --hsot-section-divider: var(--color-section-header-divider, rgba(255, 255, 255, 0.2));
244
+ --hsot-section-red: #B90100;
128
245
  --hsot-heading-font: var(--heading-font-family, 'IBM Plex Sans Condensed', 'Helvetica Neue', Helvetica, sans-serif);
129
246
  --hsot-body-font: var(--body-font-family, Roboto, 'Helvetica Neue', Helvetica, sans-serif);
130
247
  --hsot-radius-xs: var(--radius-xs, 0.15rem);
@@ -141,7 +258,7 @@ const g = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), re = y`
141
258
  outline-offset: 1px;
142
259
  }
143
260
  .mut { color: var(--hsot-gray-5); }
144
- `, oe = y`
261
+ `, be = b`
145
262
  .band { background: var(--hsot-white); color: var(--hsot-black); }
146
263
  .band .inner { max-width: 1366px; margin: 0 auto; padding: 1.1rem 1.25rem 0; }
147
264
  .band h1, .band h2.bandtitle {
@@ -160,9 +277,59 @@ const g = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), re = y`
160
277
  }
161
278
  .band nav.tabs a.on { border-bottom-color: var(--hsot-red); }
162
279
  .band nav.tabs span.off { color: var(--hsot-gray-4); cursor: not-allowed; }
163
- @media (max-width: 720px) { .band h1, .band h2.bandtitle { font-size: 1.8rem; } }
164
- `, ie = y`
280
+ /* Section-front treatment, matching the site's hsot-section-header: dark
281
+ band, red baseline, sub-nav row of section links. The section tokens
282
+ inherit from the page when it defines the --color-section-header set. */
283
+ .band.section {
284
+ background: var(--hsot-section-bg); color: var(--hsot-section-text);
285
+ border-bottom: 3px solid var(--hsot-section-red);
286
+ }
287
+ .band.section .inner { padding: 1.25rem; }
288
+ .band.section h1, .band.section h2.bandtitle {
289
+ color: inherit; font-size: 2.875rem; font-weight: 700; line-height: 1;
290
+ }
291
+ .band.section .sub { color: #CFCFCF; margin: 0.4rem 0 0; }
292
+ nav.sectionnav { border-top: 1px solid var(--hsot-section-divider); }
293
+ .sectionnav .navrow {
294
+ display: flex; gap: 1rem; max-width: 1366px; margin: 0 auto;
295
+ padding: 0 1.25rem; overflow-x: auto; box-sizing: border-box;
296
+ }
297
+ .sectionnav a, .sectionnav ::slotted(a) {
298
+ font-family: var(--hsot-heading-font); font-weight: 500; font-size: 0.875rem;
299
+ line-height: 1.5rem; text-transform: uppercase; text-decoration: none;
300
+ white-space: nowrap; padding: 0.5rem; color: #CFCFCF;
301
+ border-bottom: 2px solid transparent; transition: color 0.15s, border-color 0.15s;
302
+ }
303
+ .sectionnav a:hover, .sectionnav a:focus-visible, .sectionnav a[aria-current="page"],
304
+ .sectionnav ::slotted(a:hover), .sectionnav ::slotted(a:focus-visible), .sectionnav ::slotted(a[aria-current="page"]) {
305
+ color: var(--hsot-section-text); border-bottom-color: var(--hsot-section-red);
306
+ }
307
+ @media (max-width: 720px) {
308
+ .band h1, .band h2.bandtitle, .band.section h1, .band.section h2.bandtitle { font-size: 1.8rem; }
309
+ }
310
+ `, $e = b`
165
311
  .view { max-width: 1366px; margin: 0 auto; padding: 1.25rem; box-sizing: border-box; }
312
+ /* Optional right rail (slot="rail" light-DOM children): a divided 300px
313
+ column on desktop, stacked under the view content on smaller screens. */
314
+ .viewmain, .viewrail { min-width: 0; }
315
+ .view.withrail .viewrail {
316
+ margin-top: 2rem; padding-top: 2rem;
317
+ border-top: 1px solid var(--hsot-gray-2, #E5E3E1);
318
+ }
319
+ @media (min-width: 1200px) {
320
+ .view.withrail {
321
+ /* 332px = 300px rail content + the 2rem divider padding. */
322
+ display: grid; grid-template-columns: minmax(0, 1fr) 332px;
323
+ gap: 2rem; align-items: stretch;
324
+ }
325
+ .view.withrail .viewrail {
326
+ margin-top: 0; padding-top: 0; border-top: none;
327
+ padding-left: 2rem;
328
+ border-left: 1px solid var(--hsot-gray-2, #E5E3E1);
329
+ }
330
+ }
331
+ .promo { text-align: center; margin: 0 0 1.1rem; }
332
+ .promo img { max-width: 100%; height: auto; display: inline-block; }
166
333
  .toolbar { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; margin: 0 0 1.1rem; }
167
334
  .toolbar .spacer { flex: 1; }
168
335
  .asof { font-size: 0.8125rem; color: var(--hsot-gray-5); }
@@ -204,7 +371,7 @@ const g = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), re = y`
204
371
  .error { padding: 1.2rem 1rem; color: var(--hsot-red-deep); font-size: 0.9rem; }
205
372
  .note { font-size: 0.8125rem; color: var(--hsot-gray-5); margin: 0.6rem 0 0; }
206
373
  .loading { padding: 1.2rem; color: var(--hsot-gray-5); font-family: var(--hsot-heading-font); }
207
- `, ne = y`
374
+ `, ye = b`
208
375
  .pill {
209
376
  display: inline-block; font-family: var(--hsot-heading-font); font-weight: 700;
210
377
  font-size: 0.6875rem; text-transform: uppercase; letter-spacing: 0.04em;
@@ -219,7 +386,7 @@ const g = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), re = y`
219
386
  .pill.champ { background: var(--hsot-straw); color: #6b5900; }
220
387
  @keyframes hsot-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
221
388
  @media (prefers-reduced-motion: reduce) { .pill.live { animation: none; } }
222
- `, le = y`
389
+ `, we = b`
223
390
  .tablewrap { overflow-x: auto; }
224
391
  table.data { font-family: var(--hsot-heading-font); font-size: 14px; border-collapse: collapse; width: 100%; }
225
392
  table.data th {
@@ -237,7 +404,7 @@ const g = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), re = y`
237
404
  table.data tbody tr.rowlink:hover { background: var(--hsot-gray-1); }
238
405
  table.data td.teamcell a { color: inherit; text-decoration: none; font-weight: 500; }
239
406
  table.data td.teamcell a:hover { text-decoration: underline; }
240
- `, ce = y`
407
+ `, xe = b`
241
408
  .swatch {
242
409
  display: inline-flex; align-items: center; justify-content: center;
243
410
  width: 26px; height: 26px; border-radius: 50%;
@@ -261,7 +428,7 @@ const g = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), re = y`
261
428
  .dot.W { background: var(--hsot-win); }
262
429
  .dot.L { background: var(--hsot-loss); }
263
430
  .dot.T { background: var(--hsot-tie); }
264
- `, de = y`
431
+ `, ke = b`
265
432
  ul.gamelist { list-style: none; margin: 0; padding: 0; }
266
433
  .gamelist li {
267
434
  display: flex; align-items: center; gap: 0.7rem; padding: 0.55rem 1rem;
@@ -278,136 +445,77 @@ const g = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), re = y`
278
445
  .gamelist .opp a:hover { text-decoration: underline; }
279
446
  .gamelist .where { color: var(--hsot-gray-5); font-size: 0.78rem; }
280
447
  .gamelist a.box { font-size: 0.78rem; }
281
- `, S = [re, oe, ie, ne, le, ce, de];
282
- function j(a) {
448
+ `, F = [ve, be, $e, ye, we, xe, ke];
449
+ function q(a) {
283
450
  return a.state !== "final" ? null : a.forfeit && a.forfeit !== "none" ? a.forfeit : a.homeScore > a.awayScore ? "home" : a.awayScore > a.homeScore ? "away" : a.tiebreakWinner && a.tiebreakWinner !== "none" ? a.tiebreakWinner : "tie";
284
451
  }
285
- function D(a, e) {
286
- const t = {}, s = (o) => (t[o] = t[o] || { w: 0, l: 0, t: 0, cw: 0, cl: 0, ct: 0, pf: 0, pa: 0, results: [] }, t[o]), r = a.filter((o) => o.state === "final" && o.gameType !== "scrimmage" && (!e || o.date <= e)).sort((o, n) => String(o.date).localeCompare(String(n.date)));
452
+ function z(a, e) {
453
+ const t = {}, s = (o) => (t[o] = t[o] || { w: 0, l: 0, t: 0, cw: 0, cl: 0, ct: 0, pf: 0, pa: 0, results: [] }, t[o]), r = a.filter((o) => o.state === "final" && o.gameType !== "scrimmage" && (!e || o.date <= e)).sort((o, c) => String(o.date).localeCompare(String(c.date)));
287
454
  for (const o of r) {
288
- const n = j(o), i = o.gameType === "conference";
289
- for (const m of ["home", "away"]) {
290
- const d = m === "home" ? o.homeTeamId : o.awayTeamId;
291
- if (!d) continue;
292
- const c = s(d), h = m === "home" ? o.homeScore : o.awayScore, f = m === "home" ? o.awayScore : o.homeScore;
293
- c.pf += h, c.pa += f;
294
- let u = "T";
295
- n === "tie" ? (c.t += 1, i && (c.ct += 1)) : n === m ? (c.w += 1, i && (c.cw += 1), u = "W") : (c.l += 1, i && (c.cl += 1), u = "L"), c.results.push({ gameId: o.id, date: o.date, mark: u, my: h, their: f, opp: m === "home" ? o.awayTeamId : o.homeTeamId, conf: i });
455
+ const c = q(o), n = o.gameType === "conference";
456
+ for (const h of ["home", "away"]) {
457
+ const l = h === "home" ? o.homeTeamId : o.awayTeamId;
458
+ if (!l) continue;
459
+ const d = s(l), m = h === "home" ? o.homeScore : o.awayScore, f = h === "home" ? o.awayScore : o.homeScore;
460
+ d.pf += m, d.pa += f;
461
+ let g = "T";
462
+ c === "tie" ? (d.t += 1, n && (d.ct += 1)) : c === h ? (d.w += 1, n && (d.cw += 1), g = "W") : (d.l += 1, n && (d.cl += 1), g = "L"), d.results.push({ gameId: o.id, date: o.date, mark: g, my: m, their: f, opp: h === "home" ? o.awayTeamId : o.homeTeamId, conf: n });
296
463
  }
297
464
  }
298
465
  return t;
299
466
  }
300
- function _(a) {
467
+ function O(a) {
301
468
  if (!a || !a.length) return "";
302
469
  const e = a[a.length - 1].mark;
303
470
  let t = 0;
304
471
  for (let s = a.length - 1; s >= 0 && a[s].mark === e; s -= 1) t += 1;
305
472
  return e + t;
306
473
  }
307
- const V = (a, e, t) => {
474
+ const Z = (a, e, t) => {
308
475
  const s = a + e + t;
309
476
  return s ? (a + t / 2) / s : 0;
310
- }, Y = (a) => a.toFixed(3).replace("0.", ".");
477
+ }, J = (a) => a.toFixed(3).replace("0.", ".");
311
478
  function w(a, e = !1) {
312
479
  if (!a) return "0-0";
313
480
  const t = e ? a.cw : a.w, s = e ? a.cl : a.l, r = e ? a.ct : a.t;
314
481
  return `${t}-${s}${r ? `-${r}` : ""}`;
315
482
  }
316
- function K(a, e) {
483
+ function ae(a, e) {
317
484
  return a.map((t) => {
318
485
  const s = e[t.id] || { w: 0, l: 0, t: 0, cw: 0, cl: 0, ct: 0, pf: 0, pa: 0, results: [] };
319
- return { team: t, rec: s, confPct: V(s.cw, s.cl, s.ct), overallPct: V(s.w, s.l, s.t) };
486
+ return { team: t, rec: s, confPct: Z(s.cw, s.cl, s.ct), overallPct: Z(s.w, s.l, s.t) };
320
487
  }).sort((t, s) => s.confPct - t.confPct || s.overallPct - t.overallPct || s.rec.pf - s.rec.pa - (t.rec.pf - t.rec.pa));
321
488
  }
322
- function H(a, e) {
489
+ function W(a, e) {
323
490
  return a.filter((t) => (t.homeTeamId === e || t.awayTeamId === e) && (t.state === "scheduled" || t.state === "live") && t.gameType !== "scrimmage").sort((t, s) => String(t.date).localeCompare(String(s.date)))[0] || null;
324
491
  }
325
- function Q(a, e) {
492
+ function ee(a, e) {
326
493
  const t = a[e];
327
494
  return t && t.results.length ? t.results[t.results.length - 1] : null;
328
495
  }
329
- const N = {
330
- game: "/{sport}/game/{id}/",
331
- school: "/school/{id}/",
332
- section: "/{sport}/{view}/"
333
- };
334
- function v(a, e) {
335
- return String(a).replace(/\{(\w+)\}/g, (t, s) => e[s] !== void 0 && e[s] !== null ? String(e[s]) : t);
336
- }
337
- function C(a) {
338
- return {
339
- game: a.getAttribute("game-href") || N.game,
340
- school: a.getAttribute("school-href") || N.school,
341
- section: a.getAttribute("section-href") || N.section
342
- };
343
- }
344
- const R = (a) => a ? a.charAt(0).toUpperCase() + a.slice(1) : "";
345
- function $(a, e) {
346
- if (!a) return "TBD";
347
- const [t, s, r] = String(a).split("-").map(Number);
348
- return !t || !s || !r ? "TBD" : new Date(t, s - 1, r).toLocaleDateString("en-US", e || { weekday: "short", month: "short", day: "numeric" });
349
- }
350
- function E(a) {
351
- if (!a) return "";
352
- const [e, t] = String(a).split(":").map(Number);
353
- if (Number.isNaN(e)) return "";
354
- const s = e >= 12 ? "PM" : "AM";
355
- return `${(e + 11) % 12 + 1}:${String(t || 0).padStart(2, "0")} ${s}`;
356
- }
357
- function he(a) {
358
- return a ? `${Math.floor(a / 12)}-${a % 12}` : "·";
359
- }
360
- function A(a = /* @__PURE__ */ new Date()) {
361
- const e = a.getFullYear();
362
- return a.getMonth() >= 6 ? `${e}-${e + 1}` : `${e - 1}-${e}`;
363
- }
364
- function O(a = /* @__PURE__ */ new Date()) {
365
- const e = (t) => String(t).padStart(2, "0");
366
- return `${a.getFullYear()}-${e(a.getMonth() + 1)}-${e(a.getDate())}`;
367
- }
368
- function M(a) {
369
- return a ? (a.abbr || a.name || "?").slice(0, 4).toUpperCase() : "?";
370
- }
371
- function F(a) {
372
- if (!a || !/^#[0-9a-fA-F]{6}$/.test(a)) return "#FFFFFF";
373
- const e = parseInt(a.slice(1), 16), t = e >> 16 & 255, s = e >> 8 & 255, r = e & 255;
374
- return 0.299 * t + 0.587 * s + 0.114 * r > 150 ? "#0F1B33" : "#FFFFFF";
375
- }
376
- const me = (a) => {
377
- const e = ["th", "st", "nd", "rd"], t = a % 100;
378
- return a + (e[(t - 20) % 10] || e[t] || e[0]);
379
- };
380
- function pe(a) {
381
- if (a.state === "live") return { kind: "live", label: `Live · ${a.period || ""}`.replace(/ · $/, "") };
382
- if (a.state === "final") {
383
- const e = [];
384
- return a.finish === "overtime" && e.push("OT"), a.finish === "shootout" && e.push("PK-SO"), a.forfeit && a.forfeit !== "none" && e.push("Forfeit"), { kind: "final", label: `Final${e.length ? ` · ${e.join(" · ")}` : ""}` };
385
- }
386
- return a.state === "postponed" ? { kind: "warn", label: "Postponed" } : a.state === "canceled" ? { kind: "warn", label: "Canceled" } : { kind: "sched", label: `${$(a.date, { month: "short", day: "numeric" })} · ${E(a.time)}`.replace(/ · $/, "") };
387
- }
388
- function Fe(a, e, t, s = "") {
496
+ function Me(a, e, t, s = "") {
389
497
  let r = null;
390
498
  for (const o of a || [])
391
499
  o.sport === e && (t && o.effectiveDate > t || s && o.gender && o.gender !== s || (!r || o.effectiveDate > r.effectiveDate) && (r = o));
392
500
  return r;
393
501
  }
394
- function X(a, e, t, s, r) {
502
+ function V(a, e, t, s, r) {
395
503
  const o = e[t];
396
504
  if (!o) return null;
397
- const n = /* @__PURE__ */ new Map();
398
- for (const m of a || []) {
399
- if (m.sport !== s || r && m.effectiveDate > r || m.gender && o.gender !== m.gender && o.gender !== "coed") continue;
400
- const d = m.gender || "", c = n.get(d);
401
- (!c || m.effectiveDate > c.effectiveDate) && n.set(d, m);
402
- }
403
- let i = null;
404
- for (const m of n.values()) {
405
- const d = (m.teamIds || []).indexOf(t);
406
- d !== -1 && (!i || m.effectiveDate > i.effectiveDate) && (i = { poll: m, rank: d + 1 });
407
- }
408
- return i ? i.rank : null;
505
+ const c = /* @__PURE__ */ new Map();
506
+ for (const h of a || []) {
507
+ if (h.sport !== s || r && h.effectiveDate > r || h.gender && o.gender !== h.gender && o.gender !== "coed") continue;
508
+ const l = h.gender || "", d = c.get(l);
509
+ (!d || h.effectiveDate > d.effectiveDate) && c.set(l, h);
510
+ }
511
+ let n = null;
512
+ for (const h of c.values()) {
513
+ const l = (h.teamIds || []).indexOf(t);
514
+ l !== -1 && (!n || h.effectiveDate > n.effectiveDate) && (n = { poll: h, rank: l + 1 });
515
+ }
516
+ return n ? n.rank : null;
409
517
  }
410
- function fe(a, e, t) {
518
+ function Te(a, e, t) {
411
519
  if (!a) return { kind: "none", delta: 0 };
412
520
  const s = (a.teamIds || []).indexOf(t) + 1;
413
521
  if (!s) return { kind: "none", delta: 0 };
@@ -417,121 +525,158 @@ function fe(a, e, t) {
417
525
  const o = r - s;
418
526
  return o > 0 ? { kind: "up", delta: o } : o < 0 ? { kind: "down", delta: -o } : { kind: "same", delta: 0 };
419
527
  }
420
- function ue(a) {
528
+ function Ie(a) {
421
529
  return /^https?:\/\//i.test(String(a || ""));
422
530
  }
423
- function P(a, e) {
531
+ function _(a, e) {
424
532
  const t = a?.logoAssetId;
425
- if (!ue(t)) return "";
533
+ if (!Ie(t)) return "";
426
534
  const s = Math.max(1, Math.round(e * 2)), r = t.includes("?") ? "&" : "?";
427
535
  return `${t}${r}w=${s}&h=${s}&f=webp`;
428
536
  }
429
- const T = (a, e) => {
537
+ function Y(a, e, { title: t, sub: s, teams: r }) {
538
+ const o = se(), n = !!a.querySelector(':scope > a[slot="nav"]') || fe(o, e.hrefs, e.sport) !== null;
539
+ return i`
540
+ <div class="band section">
541
+ <div class="inner">
542
+ <h1>${t}</h1>
543
+ ${s ? i`<p class="sub">${s}</p>` : p}
544
+ </div>
545
+ ${n ? i`
546
+ <nav class="sectionnav" aria-label="${T(e.sport)} section">
547
+ <div class="navrow">
548
+ <slot name="nav">
549
+ ${ue(e.sport, r, e.hrefs).map((h) => i`<a href=${h.href}
550
+ aria-current=${o && x(h.href) === o ? "page" : p}>${h.label}</a>`)}
551
+ </slot>
552
+ </div>
553
+ </nav>` : p}
554
+ </div>
555
+ `;
556
+ }
557
+ const S = (a, e) => {
430
558
  const t = a.teamsById[e];
431
559
  return t ? a.schoolsById[t.schoolId] : null;
432
- }, k = (a, e) => T(a, e)?.name || "TBD", z = (a, e) => T(a, e)?.abbr || "TBD";
433
- function I(a, e = 26) {
560
+ }, I = (a, e) => S(a, e)?.name || "TBD", A = (a, e) => S(a, e)?.abbr || "TBD";
561
+ function C(a, e = 26) {
434
562
  if (!a) return p;
435
- const t = P(a, e);
563
+ const t = _(a, e);
436
564
  if (t)
437
- return l`<img class="swatch logo" aria-hidden="true" alt="" loading="lazy"
565
+ return i`<img class="swatch logo" aria-hidden="true" alt="" loading="lazy"
438
566
  src=${t} style="width:${e}px;height:${e}px" />`;
439
- const s = a.colorPrimary || "#030711", r = F(s);
440
- return l`<span class="swatch" aria-hidden="true"
567
+ const s = a.colorPrimary || "#030711", r = E(s);
568
+ return i`<span class="swatch" aria-hidden="true"
441
569
  style="width:${e}px;height:${e}px;background:${s};color:${r};font-size:${Math.max(8, e * 0.28)}px"
442
- >${M(a)}</span>`;
570
+ >${G(a)}</span>`;
443
571
  }
444
- function G(a, e, t) {
445
- const s = X(a.rankings, a.teamsById, e, a.sport, t);
446
- return s ? l`<span class="rankbadge">#${s}</span>` : p;
572
+ function K(a, e, t) {
573
+ const s = V(a.rankings, a.teamsById, e, a.sport, t);
574
+ return s ? i`<span class="rankbadge">#${s}</span>` : p;
447
575
  }
448
- function U(a, e, t) {
449
- const s = T(a, e);
450
- return s ? l`${G(a, e, t)}<a href=${v(a.hrefs.school, { id: s.id })}>${s.name}</a>` : l`<span class="mut">TBD</span>`;
576
+ function M(a, e, t) {
577
+ const s = S(a, e);
578
+ return s ? i`${K(a, e, t)}<a href=${u(a.hrefs.school, { id: s.id })}>${s.name}</a>` : i`<span class="mut">TBD</span>`;
451
579
  }
452
- function W(a, e, t = 5) {
580
+ function Q(a, e, t = 5) {
453
581
  const s = a.records[e];
454
- if (!s || !s.results.length) return l`<span class="mut">·</span>`;
582
+ if (!s || !s.results.length) return i`<span class="mut">·</span>`;
455
583
  const r = s.results.slice(-1 * t);
456
- return l`<span class="dots" role="img" aria-label="last ${r.length} results">
457
- ${r.map((o) => l`<a class="dot ${o.mark}"
458
- title="${o.mark} ${o.my}-${o.their} vs ${k(a, o.opp)}"
459
- href=${v(a.hrefs.game, { sport: a.sport, id: o.gameId })}>${o.mark}</a>`)}
584
+ return i`<span class="dots" role="img" aria-label="last ${r.length} results">
585
+ ${r.map((o) => i`<a class="dot ${o.mark}"
586
+ title="${o.mark} ${o.my}-${o.their} vs ${I(a, o.opp)}"
587
+ href=${u(a.hrefs.game, { sport: a.sport, id: o.gameId })}>${o.mark}</a>`)}
460
588
  </span>`;
461
589
  }
462
- function B(a) {
463
- const e = pe(a);
464
- return l`<span class="pill ${e.kind}">${e.label}</span>`;
590
+ function B(a, e) {
591
+ return a.querySelector(':scope > [slot="rail"]') ? i`<div class="view withrail">
592
+ <div class="viewmain">${e}</div>
593
+ <aside class="viewrail"><slot name="rail"></slot></aside>
594
+ </div>` : i`<div class="view">${e}</div>`;
595
+ }
596
+ function P(a) {
597
+ if (!a.promoImage) return p;
598
+ const e = i`<img src=${a.promoImage} alt=${a.promoAlt || "Sponsor"}>`;
599
+ return i`<div class="promo">${a.promoHref ? i`<a href=${a.promoHref} target="_blank" rel="sponsored noopener">${e}</a>` : e}</div>`;
465
600
  }
466
- function Z(a, e, t) {
467
- if (!e) return l`<span class="mut">·</span>`;
601
+ function R(a) {
602
+ const e = me(a);
603
+ return i`<span class="pill ${e.kind}">${e.label}</span>`;
604
+ }
605
+ function re(a, e, t) {
606
+ if (!e) return i`<span class="mut">·</span>`;
468
607
  const s = e.homeTeamId === t ? e.awayTeamId : e.homeTeamId, r = e.homeTeamId === t ? "vs" : "at";
469
- return l`${e.state === "live" ? l`<span class="pill live">Live</span> ` : l`${$(e.date, { month: "numeric", day: "numeric" })} `}${r} ${z(a, s)}`;
608
+ return i`${e.state === "live" ? i`<span class="pill live">Live</span> ` : i`${$(e.date, { month: "numeric", day: "numeric" })} `}${r} ${A(a, s)}`;
470
609
  }
471
- class ge extends b {
472
- static styles = S;
610
+ class Se extends y {
611
+ static styles = F;
473
612
  static properties = {
474
- ...b.properties,
613
+ ...y.properties,
475
614
  sport: { type: String },
476
615
  season: { type: String },
477
616
  date: { type: String }
478
617
  };
479
618
  constructor() {
480
- super(), this.sport = "football", this.season = "", this.date = "";
619
+ super(), this.sport = "football", this.season = "", this.date = "", this._datePinned = !1;
481
620
  }
482
621
  connectedCallback() {
483
622
  if (super.connectedCallback(), !this.date) {
484
623
  const e = new URLSearchParams(globalThis.location?.search || "").get("date");
485
- this.date = e || O();
624
+ e && (this.date = e);
486
625
  }
626
+ this._datePinned = !!this.date;
487
627
  }
488
628
  async fetchData(e) {
489
- const t = this.season || A(), [s, r, o, n, i] = await Promise.all([
629
+ const t = this.season || N(), [s, r, o, c, n] = await Promise.all([
490
630
  e.listSchools(),
491
631
  e.listTeams({ sport: this.sport }),
492
632
  e.listConferences(),
493
633
  e.listGames({ sport: this.sport, season: t }),
494
634
  e.listRankings({ sport: this.sport })
495
635
  ]);
496
- return {
636
+ return this._datePinned || (this.date = de(c.items.map((h) => h.date)), this._datePinned = !0), {
497
637
  season: t,
498
638
  schools: s.items,
499
639
  teams: r.items,
500
640
  conferences: o.items,
501
- games: n.items,
502
- rankings: i.items
641
+ games: c.items,
642
+ rankings: n.items
503
643
  };
504
644
  }
505
645
  get ctx() {
506
646
  return (!this._ctx || this._ctxData !== this.data) && (this._ctx = {
507
- teamsById: g(this.data.teams),
508
- schoolsById: g(this.data.schools),
509
- records: D(this.data.games),
647
+ teamsById: v(this.data.teams),
648
+ schoolsById: v(this.data.schools),
649
+ records: z(this.data.games),
510
650
  rankings: this.data.rankings,
511
- hrefs: C(this),
651
+ hrefs: D(this),
512
652
  sport: this.sport
513
653
  }, this._ctxData = this.data), this._ctx;
514
654
  }
515
655
  renderView() {
516
- const e = this.ctx, t = g(this.data.conferences), s = [...new Set(this.data.games.map((n) => n.date).filter(Boolean))].sort(), r = this.data.games.filter((n) => n.date === this.date).sort((n, i) => (n.state === "live" ? -1 : 1) - (i.state === "live" ? -1 : 1)), o = /* @__PURE__ */ new Map();
517
- return r.forEach((n) => {
518
- const i = n.gameType === "conference" && n.conferenceId ? t[n.conferenceId]?.name || "Conference" : n.gameType === "playoff" ? "Playoffs" : n.gameType === "scrimmage" ? "Scrimmages" : "Nonconference";
519
- o.has(i) || o.set(i, []), o.get(i).push(n);
520
- }), l`
521
- <div class="band">
522
- <div class="inner">
523
- <h1>${R(this.sport)} scores &amp; schedules</h1>
524
- <p class="sub">${$(this.date, { weekday: "long", month: "long", day: "numeric", year: "numeric" })} · ${r.length} games</p>
525
- </div>
526
- </div>
527
- <div class="view">
656
+ const e = this.ctx, t = v(this.data.conferences), s = [...new Set(this.data.games.map((l) => l.date).filter(Boolean))].sort(), r = Number.MAX_SAFE_INTEGER, o = (l) => {
657
+ const d = [l.awayTeamId, l.homeTeamId].map((m) => V(e.rankings, e.teamsById, m, this.sport, l.date)).filter(Boolean);
658
+ return d.length ? Math.min(...d) : r;
659
+ }, c = this.data.games.filter((l) => l.date === this.date), n = new Map(c.map((l) => [l, o(l)]));
660
+ c.sort((l, d) => (l.state === "live" ? 0 : 1) - (d.state === "live" ? 0 : 1) || n.get(l) - n.get(d));
661
+ const h = /* @__PURE__ */ new Map();
662
+ return c.forEach((l) => {
663
+ const d = l.gameType === "conference" && l.conferenceId ? t[l.conferenceId]?.name || "Conference" : l.gameType === "playoff" ? "Playoffs" : l.gameType === "scrimmage" ? "Scrimmages" : "Nonconference";
664
+ h.has(d) || h.set(d, []), h.get(d).push(l);
665
+ }), i`
666
+ ${Y(this, e, {
667
+ title: i`${T(this.sport)} scores &amp; schedules`,
668
+ sub: i`${$(this.date, { weekday: "long", month: "long", day: "numeric", year: "numeric" })} · ${c.length} games`,
669
+ teams: this.data.teams
670
+ })}
671
+ ${B(this, i`
672
+ ${P(this)}
528
673
  <div class="toolbar">
529
674
  <label class="asof" for="datesel">Date</label>
530
- <select id="datesel" @change=${(n) => {
531
- this.date = n.target.value;
675
+ <select id="datesel" @change=${(l) => {
676
+ this.date = l.target.value;
532
677
  }}>
533
- ${s.map((n) => l`<option value=${n} ?selected=${n === this.date}>
534
- ${$(n, { weekday: "short", month: "short", day: "numeric" })}${n === O() ? " · today" : ""}
678
+ ${(s.includes(this.date) ? s : [...s, this.date].sort()).map((l) => i`<option value=${l} ?selected=${l === this.date}>
679
+ ${$(l, { weekday: "short", month: "short", day: "numeric" })}${l === j() ? " · today" : ""}
535
680
  </option>`)}
536
681
  </select>
537
682
  <button class="chip" ?disabled=${s.indexOf(this.date) <= 0}
@@ -545,35 +690,35 @@ class ge extends b {
545
690
  <span class="spacer"></span>
546
691
  <span class="asof">Live games first · report a score to see it update here</span>
547
692
  </div>
548
- ${r.length ? p : l`<p class="empty">No ${this.sport} games on this date.</p>`}
549
- ${[...o.entries()].map(([n, i]) => l`
550
- <div class="section-title">${n}</div>
693
+ ${c.length ? p : i`<p class="empty">No ${this.sport} games on this date.</p>`}
694
+ ${[...h.entries()].map(([l, d]) => i`
695
+ <div class="section-title">${l}</div>
551
696
  <div class="card"><ul class="gamelist">
552
- ${i.map((m) => this.renderGame(e, m))}
697
+ ${d.map((m) => this.renderGame(e, m))}
553
698
  </ul></div>
554
699
  `)}
555
- </div>
700
+ `)}
556
701
  `;
557
702
  }
558
703
  renderGame(e, t) {
559
- const s = t.state === "final" || t.state === "live" ? `${t.awayScore}-${t.homeScore}` : E(t.time);
560
- return l`
704
+ const s = t.state === "final" || t.state === "live" ? `${t.awayScore}-${t.homeScore}` : L(t.time);
705
+ return i`
561
706
  <li>
562
- ${B(t)}
563
- <span class="opp">${U(e, t.awayTeamId, t.date)} at ${U(e, t.homeTeamId, t.date)}</span>
707
+ ${R(t)}
708
+ <span class="opp">${M(e, t.awayTeamId, t.date)} at ${M(e, t.homeTeamId, t.date)}</span>
564
709
  <span class="res" style="width:auto">${s}</span>
565
710
  <span class="where">${t.venue || ""}</span>
566
- ${t.broadcast ? l`<span class="pill class">${t.broadcast}</span>` : p}
567
- <a class="box" href=${v(e.hrefs.game, { sport: this.sport, id: t.id })}>Box score →</a>
711
+ ${t.broadcast ? i`<span class="pill class">${t.broadcast}</span>` : p}
712
+ <a class="box" href=${u(e.hrefs.game, { sport: this.sport, id: t.id })}>Box score →</a>
568
713
  </li>
569
714
  `;
570
715
  }
571
716
  }
572
- globalThis?.customElements && !globalThis.customElements.get("hsot-scores") && globalThis.customElements.define("hsot-scores", ge);
573
- class ve extends b {
574
- static styles = S;
717
+ globalThis?.customElements && !globalThis.customElements.get("hsot-scores") && globalThis.customElements.define("hsot-scores", Se);
718
+ class Ce extends y {
719
+ static styles = F;
575
720
  static properties = {
576
- ...b.properties,
721
+ ...y.properties,
577
722
  sport: { type: String },
578
723
  season: { type: String },
579
724
  classFilter: { state: !0 },
@@ -583,7 +728,7 @@ class ve extends b {
583
728
  super(), this.sport = "football", this.season = "", this.classFilter = "All", this.query = "";
584
729
  }
585
730
  async fetchData(e) {
586
- const t = this.season || A(), [s, r, o, n, i] = await Promise.all([
731
+ const t = this.season || N(), [s, r, o, c, n] = await Promise.all([
587
732
  e.listConferences({ active: !0 }),
588
733
  e.listSchools(),
589
734
  e.listTeams({ sport: this.sport }),
@@ -595,33 +740,33 @@ class ve extends b {
595
740
  conferences: s.items,
596
741
  schools: r.items,
597
742
  teams: o.items,
598
- games: n.items,
599
- rankings: i.items
743
+ games: c.items,
744
+ rankings: n.items
600
745
  };
601
746
  }
602
747
  get ctx() {
603
748
  return (!this._ctx || this._ctxData !== this.data) && (this._ctx = {
604
- teamsById: g(this.data.teams),
605
- schoolsById: g(this.data.schools),
606
- records: D(this.data.games),
749
+ teamsById: v(this.data.teams),
750
+ schoolsById: v(this.data.schools),
751
+ records: z(this.data.games),
607
752
  rankings: this.data.rankings,
608
- hrefs: C(this),
753
+ hrefs: D(this),
609
754
  sport: this.sport
610
755
  }, this._ctxData = this.data), this._ctx;
611
756
  }
612
757
  renderView() {
613
758
  const e = this.ctx, t = ["All", ...new Set(this.data.conferences.flatMap((r) => r.classifications || []))].slice(0, 9), s = this.data.conferences.filter((r) => r.active !== !1).filter((r) => this.classFilter === "All" || (r.classifications || []).includes(this.classFilter));
614
- return l`
615
- <div class="band">
616
- <div class="inner">
617
- <h1>${R(this.sport)} standings</h1>
618
- <p class="sub">${this.data.season} season · every conference, computed live from reported results</p>
619
- </div>
620
- </div>
621
- <div class="view">
759
+ return i`
760
+ ${Y(this, e, {
761
+ title: i`${T(this.sport)} standings`,
762
+ sub: i`${this.data.season} season · every conference, computed live from reported results`,
763
+ teams: this.data.teams
764
+ })}
765
+ ${B(this, i`
766
+ ${P(this)}
622
767
  <div class="toolbar">
623
768
  <div role="group" aria-label="Classification filter">
624
- ${t.map((r) => l`<button class="chip ${this.classFilter === r ? "on" : ""}"
769
+ ${t.map((r) => i`<button class="chip ${this.classFilter === r ? "on" : ""}"
625
770
  @click=${() => {
626
771
  this.classFilter = r;
627
772
  }}>${r}</button>`)}
@@ -631,21 +776,21 @@ class ve extends b {
631
776
  this.query = r.target.value;
632
777
  }}>
633
778
  <span class="spacer"></span>
634
- <span class="asof">Records through ${$(O(), { month: "long", day: "numeric" })} · conference games count toward both records · scrimmages toward neither</span>
779
+ <span class="asof">Records through ${$(j(), { month: "long", day: "numeric" })} · conference games count toward both records · scrimmages toward neither</span>
635
780
  </div>
636
781
  ${s.map((r) => this.renderConference(e, r))}
637
- </div>
782
+ `)}
638
783
  `;
639
784
  }
640
785
  renderConference(e, t) {
641
- const s = this.data.teams.filter((n) => n.conferenceId === t.id);
786
+ const s = this.data.teams.filter((c) => c.conferenceId === t.id);
642
787
  if (!s.length) return p;
643
- const r = this.query.trim().toLowerCase(), o = K(s, e.records);
644
- return l`
788
+ const r = this.query.trim().toLowerCase(), o = ae(s, e.records);
789
+ return i`
645
790
  <div class="card">
646
791
  <div class="card-head">
647
792
  <h2>${t.name}</h2>
648
- ${(t.classifications || []).map((n) => l`<span class="pill class">${n}</span>`)}
793
+ ${(t.classifications || []).map((c) => i`<span class="pill class">${c}</span>`)}
649
794
  <span class="meta">${o.length} teams · membership derives from teams</span>
650
795
  </div>
651
796
  <div class="tablewrap"><table class="data">
@@ -655,44 +800,44 @@ class ve extends b {
655
800
  <th>Streak</th><th>Last 5</th><th>Next</th>
656
801
  </tr></thead>
657
802
  <tbody>
658
- ${o.map((n, i) => this.renderRow(e, n, i, r))}
803
+ ${o.map((c, n) => this.renderRow(e, c, n, r))}
659
804
  </tbody>
660
805
  </table></div>
661
806
  </div>
662
807
  `;
663
808
  }
664
809
  renderRow(e, t, s, r) {
665
- const o = e.schoolsById[t.team.schoolId], n = o?.name || t.team.name || "TBD";
666
- if (r && !n.toLowerCase().includes(r)) return p;
667
- const i = t.rec.pf - t.rec.pa, m = H(this.data.games, t.team.id), d = (t.team.championships || []).map((h) => l`
668
- <span class="pill champ" title="${h.season} ${h.title} champion">★ ${h.season} ${h.title}</span>`), c = () => {
669
- location.href = v(e.hrefs.school, { id: t.team.schoolId });
810
+ const o = e.schoolsById[t.team.schoolId], c = o?.name || t.team.name || "TBD";
811
+ if (r && !c.toLowerCase().includes(r)) return p;
812
+ const n = t.rec.pf - t.rec.pa, h = W(this.data.games, t.team.id), l = (t.team.championships || []).map((m) => i`
813
+ <span class="pill champ" title="${m.season} ${m.title} champion">★ ${m.season} ${m.title}</span>`), d = () => {
814
+ location.href = u(e.hrefs.school, { id: t.team.schoolId });
670
815
  };
671
- return l`
672
- <tr class="rowlink" @click=${(h) => {
673
- h.target.closest("a") || c();
816
+ return i`
817
+ <tr class="rowlink" @click=${(m) => {
818
+ m.target.closest("a") || d();
674
819
  }}>
675
820
  <td class="mut">${s + 1}</td>
676
821
  <td class="teamcell">
677
- ${I(o)}${G(e, t.team.id, null)}
678
- <a href=${v(e.hrefs.school, { id: t.team.schoolId })}>${n}</a> ${d}
822
+ ${C(o)}${K(e, t.team.id, null)}
823
+ <a href=${u(e.hrefs.school, { id: t.team.schoolId })}>${c}</a> ${l}
679
824
  </td>
680
825
  <td class="num">${w(t.rec, !0)}</td>
681
- <td class="num">${Y(t.confPct)}</td>
826
+ <td class="num">${J(t.confPct)}</td>
682
827
  <td class="num">${w(t.rec)}</td>
683
- <td class="num">${Y(t.overallPct)}</td>
828
+ <td class="num">${J(t.overallPct)}</td>
684
829
  <td class="num">${t.rec.pf}</td>
685
830
  <td class="num">${t.rec.pa}</td>
686
- <td class="num" style="color:${i >= 0 ? "var(--hsot-win)" : "var(--hsot-loss)"}">${i > 0 ? "+" : ""}${i}</td>
687
- <td>${_(t.rec.results) || "·"}</td>
688
- <td>${W(e, t.team.id)}</td>
689
- <td>${Z(e, m, t.team.id)}</td>
831
+ <td class="num" style="color:${n >= 0 ? "var(--hsot-win)" : "var(--hsot-loss)"}">${n > 0 ? "+" : ""}${n}</td>
832
+ <td>${O(t.rec.results) || "·"}</td>
833
+ <td>${Q(e, t.team.id)}</td>
834
+ <td>${re(e, h, t.team.id)}</td>
690
835
  </tr>
691
836
  `;
692
837
  }
693
838
  }
694
- globalThis?.customElements && !globalThis.customElements.get("hsot-standings") && globalThis.customElements.define("hsot-standings", ve);
695
- const $e = y`
839
+ globalThis?.customElements && !globalThis.customElements.get("hsot-standings") && globalThis.customElements.define("hsot-standings", Ce);
840
+ const De = b`
696
841
  .hero1 {
697
842
  border-radius: var(--hsot-radius-md); color: var(--hsot-white);
698
843
  padding: 1.3rem 1.4rem; display: flex; align-items: center; gap: 1.2rem;
@@ -709,10 +854,10 @@ const $e = y`
709
854
  .delta.new { background: var(--hsot-straw); color: #6b5900; border-radius: var(--hsot-radius-xs); padding: 0.1rem 0.3rem; font-size: 0.7rem; }
710
855
  .sparkline { vertical-align: middle; }
711
856
  `;
712
- class be extends b {
713
- static styles = [...S, $e];
857
+ class Fe extends y {
858
+ static styles = [...F, De];
714
859
  static properties = {
715
- ...b.properties,
860
+ ...y.properties,
716
861
  sport: { type: String },
717
862
  gender: { type: String },
718
863
  season: { type: String },
@@ -727,73 +872,73 @@ class be extends b {
727
872
  e && (this.pollDate = e);
728
873
  }
729
874
  async fetchData(e) {
730
- const t = this.season || A(), [s, r, o, n, i] = await Promise.all([
875
+ const t = this.season || N(), [s, r, o, c, n] = await Promise.all([
731
876
  e.listRankings({ sport: this.sport, ...this.gender ? { gender: this.gender } : {} }),
732
877
  e.listSchools(),
733
878
  e.listTeams({ sport: this.sport }),
734
879
  e.listConferences(),
735
880
  e.listGames({ sport: this.sport, season: t })
736
- ]), m = s.items.filter((d) => !this.gender || !d.gender || d.gender === this.gender).sort((d, c) => c.effectiveDate.localeCompare(d.effectiveDate));
881
+ ]), h = s.items.filter((l) => !this.gender || !l.gender || l.gender === this.gender).sort((l, d) => d.effectiveDate.localeCompare(l.effectiveDate));
737
882
  return {
738
883
  season: t,
739
- polls: m,
884
+ polls: h,
740
885
  schools: r.items,
741
886
  teams: o.items,
742
- conferences: n.items,
743
- games: i.items
887
+ conferences: c.items,
888
+ games: n.items
744
889
  };
745
890
  }
746
891
  get ctx() {
747
892
  return (!this._ctx || this._ctxData !== this.data) && (this._ctx = {
748
- teamsById: g(this.data.teams),
749
- schoolsById: g(this.data.schools),
750
- records: D(this.data.games),
893
+ teamsById: v(this.data.teams),
894
+ schoolsById: v(this.data.schools),
895
+ records: z(this.data.games),
751
896
  rankings: this.data.polls,
752
- hrefs: C(this),
897
+ hrefs: D(this),
753
898
  sport: this.sport
754
899
  }, this._ctxData = this.data), this._ctx;
755
900
  }
756
901
  sparkline(e, t, s) {
757
- const i = t.map((h, f) => {
758
- const u = (h.teamIds || []).indexOf(e);
759
- if (u === -1) return null;
760
- const x = t.length === 1 ? 96 / 2 : f / (t.length - 1) * 90 + 3, L = 3 + u / 24 * 20;
761
- return { x, y: L };
762
- }), m = [];
763
- let d = [];
764
- if (i.forEach((h) => {
765
- h ? d.push(h) : d.length && (m.push(d), d = []);
766
- }), d.length && m.push(d), !m.length) return p;
767
- const c = i[s];
768
- return l`<svg class="sparkline" width=${96} height=${26} viewBox="0 0 ${96} ${26}" role="img" aria-label="rank history">
769
- ${m.map((h) => q`<polyline fill="none" stroke="var(--hsot-red)" stroke-width="2"
770
- points=${h.map((f) => `${f.x.toFixed(1)},${f.y.toFixed(1)}`).join(" ")}></polyline>`)}
771
- ${c ? q`<circle cx=${c.x.toFixed(1)} cy=${c.y.toFixed(1)} r="3" fill="var(--hsot-black)"></circle>` : p}
902
+ const n = t.map((m, f) => {
903
+ const g = (m.teamIds || []).indexOf(e);
904
+ if (g === -1) return null;
905
+ const k = t.length === 1 ? 96 / 2 : f / (t.length - 1) * 90 + 3, H = 3 + g / 24 * 20;
906
+ return { x: k, y: H };
907
+ }), h = [];
908
+ let l = [];
909
+ if (n.forEach((m) => {
910
+ m ? l.push(m) : l.length && (h.push(l), l = []);
911
+ }), l.length && h.push(l), !h.length) return p;
912
+ const d = n[s];
913
+ return i`<svg class="sparkline" width=${96} height=${26} viewBox="0 0 ${96} ${26}" role="img" aria-label="rank history">
914
+ ${h.map((m) => X`<polyline fill="none" stroke="var(--hsot-red)" stroke-width="2"
915
+ points=${m.map((f) => `${f.x.toFixed(1)},${f.y.toFixed(1)}`).join(" ")}></polyline>`)}
916
+ ${d ? X`<circle cx=${d.x.toFixed(1)} cy=${d.y.toFixed(1)} r="3" fill="var(--hsot-black)"></circle>` : p}
772
917
  </svg>`;
773
918
  }
774
919
  movement(e, t, s) {
775
- const r = fe(e, t, s);
776
- return r.kind === "up" ? l`<span class="delta up">▲ ${r.delta}</span>` : r.kind === "down" ? l`<span class="delta down">▼ ${r.delta}</span>` : r.kind === "new" ? l`<span class="delta new">NEW</span>` : r.kind === "same" ? l`<span class="delta same">—</span>` : l`<span class="delta same">·</span>`;
920
+ const r = Te(e, t, s);
921
+ return r.kind === "up" ? i`<span class="delta up">▲ ${r.delta}</span>` : r.kind === "down" ? i`<span class="delta down">▼ ${r.delta}</span>` : r.kind === "new" ? i`<span class="delta new">NEW</span>` : r.kind === "same" ? i`<span class="delta same">—</span>` : i`<span class="delta same">·</span>`;
777
922
  }
778
923
  renderView() {
779
924
  const e = this.ctx, t = this.data.polls;
780
- if (!t.length) return l`<div class="view"><p class="empty">No ${this.sport} polls published yet this season.</p></div>`;
781
- const s = Math.max(0, t.findIndex((h) => h.effectiveDate === this.pollDate)), r = t[s] || t[0], o = t[s + 1] || null, n = t.slice().reverse(), i = n.indexOf(r), m = g(this.data.conferences), d = (r.teamIds || [])[0], c = d ? T(e, d) : null;
782
- return l`
783
- <div class="band">
784
- <div class="inner">
785
- <h1>${R(this.sport)} Top 25</h1>
786
- <p class="sub">The HighSchoolOT poll · updated weekly · ${t.length} polls this season</p>
787
- </div>
788
- </div>
789
- <div class="view">
925
+ if (!t.length) return i`<div class="view"><p class="empty">No ${this.sport} polls published yet this season.</p></div>`;
926
+ const s = Math.max(0, t.findIndex((m) => m.effectiveDate === this.pollDate)), r = t[s] || t[0], o = t[s + 1] || null, c = t.slice().reverse(), n = c.indexOf(r), h = v(this.data.conferences), l = (r.teamIds || [])[0], d = l ? S(e, l) : null;
927
+ return i`
928
+ ${Y(this, e, {
929
+ title: i`${T(this.sport)} Top 25`,
930
+ sub: i`The HighSchoolOT poll · updated weekly · ${t.length} polls this season`,
931
+ teams: this.data.teams
932
+ })}
933
+ ${B(this, i`
934
+ ${P(this)}
790
935
  <div class="toolbar">
791
936
  <label class="asof" for="pollsel">Poll of</label>
792
- <select id="pollsel" @change=${(h) => {
793
- this.pollDate = h.target.value;
937
+ <select id="pollsel" @change=${(m) => {
938
+ this.pollDate = m.target.value;
794
939
  }}>
795
- ${t.map((h, f) => l`<option value=${h.effectiveDate} ?selected=${h === r}>
796
- ${$(h.effectiveDate, { month: "long", day: "numeric", year: "numeric" })}${f === 0 ? " · current" : ""}
940
+ ${t.map((m, f) => i`<option value=${m.effectiveDate} ?selected=${m === r}>
941
+ ${$(m.effectiveDate, { month: "long", day: "numeric", year: "numeric" })}${f === 0 ? " · current" : ""}
797
942
  </option>`)}
798
943
  </select>
799
944
  <button class="chip" ?disabled=${s >= t.length - 1}
@@ -807,65 +952,65 @@ class be extends b {
807
952
  <span class="spacer"></span>
808
953
  <span class="asof">Movement vs. the previous poll · sparkline = season rank history</span>
809
954
  </div>
810
- ${c ? this.renderHero(e, r, o, d, c, m) : p}
955
+ ${d ? this.renderHero(e, r, o, l, d, h) : p}
811
956
  <div class="card"><div class="tablewrap"><table class="data">
812
957
  <thead><tr>
813
958
  <th class="num">Rk</th><th>Mvmt</th><th>Team</th><th class="num">Record</th>
814
959
  <th>Conference</th><th>Last result</th><th>Next</th><th>Season</th>
815
960
  </tr></thead>
816
961
  <tbody>
817
- ${(r.teamIds || []).map((h, f) => f === 0 || !h ? p : this.renderRow(e, r, o, n, i, m, h, f + 1))}
962
+ ${(r.teamIds || []).map((m, f) => f === 0 || !m ? p : this.renderRow(e, r, o, c, n, h, m, f + 1))}
818
963
  </tbody>
819
964
  </table></div></div>
820
965
  <p class="note">Ranks elsewhere on the site resolve the poll in effect on the game date, so past box scores keep the ranks they were played under.</p>
821
- </div>
966
+ `)}
822
967
  `;
823
968
  }
824
- renderHero(e, t, s, r, o, n) {
825
- const i = e.records[r], m = Q(e.records, r), d = n[e.teamsById[r]?.conferenceId], c = `linear-gradient(120deg, ${o.colorPrimary || "#030711"} 0%, var(--hsot-black) 85%)`;
826
- return l`
827
- <div class="hero1" style="background:${c}">
969
+ renderHero(e, t, s, r, o, c) {
970
+ const n = e.records[r], h = ee(e.records, r), l = c[e.teamsById[r]?.conferenceId], d = `linear-gradient(120deg, ${o.colorPrimary || "#030711"} 0%, var(--hsot-black) 85%)`;
971
+ return i`
972
+ <div class="hero1" style="background:${d}">
828
973
  <div class="bigrank">#1</div>
829
- ${I(o, 64)}
974
+ ${C(o, 64)}
830
975
  <div>
831
- <h2><a href=${v(e.hrefs.school, { id: o.id })}>${o.name} ${o.mascot || ""}</a></h2>
976
+ <h2><a href=${u(e.hrefs.school, { id: o.id })}>${o.name} ${o.mascot || ""}</a></h2>
832
977
  <div class="facts">
833
- ${w(i)} overall${d ? l` · ${w(i, !0)} ${d.name}` : p}
834
- · streak ${_(i?.results) || "·"}
835
- ${m ? l` · last: ${m.mark} ${m.my}-${m.their} vs ${z(e, m.opp)}` : p}
978
+ ${w(n)} overall${l ? i` · ${w(n, !0)} ${l.name}` : p}
979
+ · streak ${O(n?.results) || "·"}
980
+ ${h ? i` · last: ${h.mark} ${h.my}-${h.their} vs ${A(e, h.opp)}` : p}
836
981
  &nbsp;${this.movement(t, s, r)}
837
982
  </div>
838
983
  </div>
839
984
  </div>
840
985
  `;
841
986
  }
842
- renderRow(e, t, s, r, o, n, i, m) {
843
- const d = T(e, i);
844
- if (!d) return p;
845
- const c = e.records[i], h = Q(e.records, i), f = H(this.data.games, i), u = n[e.teamsById[i]?.conferenceId], x = () => {
846
- location.href = v(e.hrefs.school, { id: d.id });
987
+ renderRow(e, t, s, r, o, c, n, h) {
988
+ const l = S(e, n);
989
+ if (!l) return p;
990
+ const d = e.records[n], m = ee(e.records, n), f = W(this.data.games, n), g = c[e.teamsById[n]?.conferenceId], k = () => {
991
+ location.href = u(e.hrefs.school, { id: l.id });
847
992
  };
848
- return l`
849
- <tr class="rowlink" @click=${(L) => {
850
- L.target.closest("a") || x();
993
+ return i`
994
+ <tr class="rowlink" @click=${(H) => {
995
+ H.target.closest("a") || k();
851
996
  }}>
852
- <td class="num" style="font-weight:700">${m}</td>
853
- <td>${this.movement(t, s, i)}</td>
854
- <td class="teamcell">${I(d)}<a href=${v(e.hrefs.school, { id: d.id })}>${d.name}</a>
855
- <span class="mut" style="font-size:0.78rem">${d.mascot || ""}</span></td>
856
- <td class="num">${w(c)}</td>
857
- <td class="mut">${u?.name || "Independent"}</td>
858
- <td>${h ? l`<a class="box" style="text-decoration:none" href=${v(e.hrefs.game, { sport: this.sport, id: h.gameId })}>
859
- <b style="color:${h.mark === "W" ? "var(--hsot-win)" : h.mark === "L" ? "var(--hsot-loss)" : "var(--hsot-tie)"}">${h.mark}</b>
860
- ${h.my}-${h.their} vs ${z(e, h.opp)}</a>` : l`<span class="mut">·</span>`}</td>
861
- <td>${Z(e, f, i)}</td>
862
- <td>${this.sparkline(i, r, o)}</td>
997
+ <td class="num" style="font-weight:700">${h}</td>
998
+ <td>${this.movement(t, s, n)}</td>
999
+ <td class="teamcell">${C(l)}<a href=${u(e.hrefs.school, { id: l.id })}>${l.name}</a>
1000
+ <span class="mut" style="font-size:0.78rem">${l.mascot || ""}</span></td>
1001
+ <td class="num">${w(d)}</td>
1002
+ <td class="mut">${g?.name || "Independent"}</td>
1003
+ <td>${m ? i`<a class="box" style="text-decoration:none" href=${u(e.hrefs.game, { sport: this.sport, id: m.gameId })}>
1004
+ <b style="color:${m.mark === "W" ? "var(--hsot-win)" : m.mark === "L" ? "var(--hsot-loss)" : "var(--hsot-tie)"}">${m.mark}</b>
1005
+ ${m.my}-${m.their} vs ${A(e, m.opp)}</a>` : i`<span class="mut">·</span>`}</td>
1006
+ <td>${re(e, f, n)}</td>
1007
+ <td>${this.sparkline(n, r, o)}</td>
863
1008
  </tr>
864
1009
  `;
865
1010
  }
866
1011
  }
867
- globalThis?.customElements && !globalThis.customElements.get("hsot-rankings") && globalThis.customElements.define("hsot-rankings", be);
868
- const ye = y`
1012
+ globalThis?.customElements && !globalThis.customElements.get("hsot-rankings") && globalThis.customElements.define("hsot-rankings", Fe);
1013
+ const ze = b`
869
1014
  .schoolhero { color: var(--hsot-white); padding: 1.6rem 1.25rem 1.3rem; }
870
1015
  .schoolhero .inner { max-width: 1366px; margin: 0 auto; display: flex; gap: 1.2rem; align-items: center; flex-wrap: wrap; }
871
1016
  .schoolhero .crest {
@@ -890,10 +1035,10 @@ const ye = y`
890
1035
  .cols { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 1.25rem; }
891
1036
  @media (max-width: 900px) { .cols { grid-template-columns: 1fr; } .schoolhero h1 { font-size: 1.9rem; } }
892
1037
  `;
893
- class we extends b {
894
- static styles = [...S, ye];
1038
+ class Be extends y {
1039
+ static styles = [...F, ze];
895
1040
  static properties = {
896
- ...b.properties,
1041
+ ...y.properties,
897
1042
  schoolId: { type: String, attribute: "school-id" },
898
1043
  sport: { type: String },
899
1044
  season: { type: String },
@@ -908,38 +1053,38 @@ class we extends b {
908
1053
  e && !this.sport && (this.sport = e);
909
1054
  }
910
1055
  async fetchData(e) {
911
- const t = this.season || A(), s = await e.getSchool(this.schoolId), o = (await e.listTeams({ schoolId: this.schoolId })).items, n = o.find((x) => x.sport === (this.sport || "football")) || o[0] || null, [i, m, d, c, h, f, u] = await Promise.all([
912
- n ? e.listGames({ sport: n.sport, season: t }) : Promise.resolve({ items: [] }),
913
- n ? e.listTeams({ sport: n.sport }) : Promise.resolve({ items: [] }),
1056
+ const t = this.season || N(), s = await e.getSchool(this.schoolId), o = (await e.listTeams({ schoolId: this.schoolId })).items, c = o.find((k) => k.sport === (this.sport || "football")) || o[0] || null, [n, h, l, d, m, f, g] = await Promise.all([
1057
+ c ? e.listGames({ sport: c.sport, season: t }) : Promise.resolve({ items: [] }),
1058
+ c ? e.listTeams({ sport: c.sport }) : Promise.resolve({ items: [] }),
914
1059
  e.listSchools(),
915
1060
  e.listConferences(),
916
- n ? e.listRankings({ sport: n.sport }) : Promise.resolve({ items: [] }),
917
- n ? e.listRosters({ teamId: n.id }) : Promise.resolve({ items: [] }),
1061
+ c ? e.listRankings({ sport: c.sport }) : Promise.resolve({ items: [] }),
1062
+ c ? e.listRosters({ teamId: c.id }) : Promise.resolve({ items: [] }),
918
1063
  // teamId is the public surface's one players filter (roster
919
1064
  // membership) — never fetch the whole collection.
920
- n ? e.listPlayers({ teamId: n.id }) : Promise.resolve({ items: [] })
1065
+ c ? e.listPlayers({ teamId: c.id }) : Promise.resolve({ items: [] })
921
1066
  ]);
922
1067
  return {
923
1068
  season: t,
924
1069
  school: s,
925
1070
  teams: o,
926
- active: n,
927
- games: i.items,
928
- allTeams: m.items,
929
- schools: d.items,
930
- conferences: c.items,
931
- rankings: h.items,
932
- roster: f.items.find((x) => x.season === t) || null,
933
- players: u.items
1071
+ active: c,
1072
+ games: n.items,
1073
+ allTeams: h.items,
1074
+ schools: l.items,
1075
+ conferences: d.items,
1076
+ rankings: m.items,
1077
+ roster: f.items.find((k) => k.season === t) || null,
1078
+ players: g.items
934
1079
  };
935
1080
  }
936
1081
  get ctx() {
937
1082
  return (!this._ctx || this._ctxData !== this.data) && (this._ctx = {
938
- teamsById: g(this.data.allTeams.length ? this.data.allTeams : this.data.teams),
939
- schoolsById: g(this.data.schools),
940
- records: D(this.data.games),
1083
+ teamsById: v(this.data.allTeams.length ? this.data.allTeams : this.data.teams),
1084
+ schoolsById: v(this.data.schools),
1085
+ records: z(this.data.games),
941
1086
  rankings: this.data.rankings,
942
- hrefs: C(this),
1087
+ hrefs: D(this),
943
1088
  sport: this.data.active?.sport || "football"
944
1089
  }, this._ctxData = this.data), this._ctx;
945
1090
  }
@@ -948,61 +1093,62 @@ class we extends b {
948
1093
  }
949
1094
  renderView() {
950
1095
  const { school: e, teams: t, active: s, season: r } = this.data;
951
- if (!e) return l`<div class="view"><p class="empty">School not found.</p></div>`;
952
- const o = this.ctx, n = F(e.colorPrimary || "#030711"), i = (e.adm || [])[0], m = g(this.data.conferences), d = s ? m[s.conferenceId] : null;
953
- return l`
954
- <div class="schoolhero" style="background:linear-gradient(115deg, ${e.colorPrimary || "#030711"} 0%, ${e.colorPrimary || "#030711"} 55%, var(--hsot-black) 100%);color:${n}">
1096
+ if (!e) return i`<div class="view"><p class="empty">School not found.</p></div>`;
1097
+ const o = this.ctx, c = E(e.colorPrimary || "#030711"), n = (e.adm || [])[0], h = v(this.data.conferences), l = s ? h[s.conferenceId] : null;
1098
+ return i`
1099
+ <div class="schoolhero" style="background:linear-gradient(115deg, ${e.colorPrimary || "#030711"} 0%, ${e.colorPrimary || "#030711"} 55%, var(--hsot-black) 100%);color:${c}">
955
1100
  <div class="inner">
956
- ${P(e, 84) ? l`<img class="crest logo" alt="" loading="lazy" src=${P(e, 84)} />` : l`<div class="crest" style="background:${e.colorSecondary || "#7C7C7C"};color:${F(e.colorSecondary || "#7C7C7C")}">${M(e)}</div>`}
1101
+ ${_(e, 84) ? i`<img class="crest logo" alt="" loading="lazy" src=${_(e, 84)} />` : i`<div class="crest" style="background:${e.colorSecondary || "#7C7C7C"};color:${E(e.colorSecondary || "#7C7C7C")}">${G(e)}</div>`}
957
1102
  <div style="min-width:260px">
958
1103
  <h1>${e.name} <span class="mascot">${e.mascot || ""}</span></h1>
959
1104
  <div class="facts">
960
- ${e.location ? l`<span><b>Location</b>${e.location}${e.county ? l` · ${e.county} County` : p}</span>` : p}
961
- ${e.association ? l`<span><b>League</b>${e.association}${e.classification ? l` · ${e.classification}` : p}</span>` : p}
962
- ${d ? l`<span><b>Conference</b>${d.name}</span>` : p}
963
- ${i ? l`<span><b>Enrollment</b>${i.value.toLocaleString()} (${i.season} ADM)</span>` : p}
964
- ${e.openingYear ? l`<span><b>Opened</b>${e.openingYear}</span>` : p}
965
- ${e.areaCode ? l`<span><b>Area</b>${e.areaCode}</span>` : p}
966
- ${e.tagSlug ? l`<span><b>Tag</b>#${e.tagSlug}</span>` : p}
1105
+ ${e.location ? i`<span><b>Location</b>${e.location}${e.county ? i` · ${e.county} County` : p}</span>` : p}
1106
+ ${e.association ? i`<span><b>League</b>${e.association}${e.classification ? i` · ${e.classification}` : p}</span>` : p}
1107
+ ${l ? i`<span><b>Conference</b>${l.name}</span>` : p}
1108
+ ${n ? i`<span><b>Enrollment</b>${n.value.toLocaleString()} (${n.season} ADM)</span>` : p}
1109
+ ${e.openingYear ? i`<span><b>Opened</b>${e.openingYear}</span>` : p}
1110
+ ${e.areaCode ? i`<span><b>Area</b>${e.areaCode}</span>` : p}
1111
+ ${e.tagSlug ? i`<span><b>Tag</b>#${e.tagSlug}</span>` : p}
967
1112
  </div>
968
1113
  </div>
969
1114
  </div>
970
1115
  </div>
971
1116
  <div class="band">
972
1117
  <nav class="tabs" aria-label="Teams">
973
- ${t.map((c) => c.id === s?.id ? l`<a class="on" href="#" @click=${(h) => h.preventDefault()}>${c.name}</a>` : l`<a href="#" @click=${(h) => {
974
- h.preventDefault(), this.switchSport(c.sport);
975
- }}>${c.name}</a>`)}
1118
+ ${t.map((d) => d.id === s?.id ? i`<a class="on" href="#" @click=${(m) => m.preventDefault()}>${d.name}</a>` : i`<a href="#" @click=${(m) => {
1119
+ m.preventDefault(), this.switchSport(d.sport);
1120
+ }}>${d.name}</a>`)}
976
1121
  </nav>
977
1122
  </div>
978
- <div class="view">
979
- ${s ? this.renderTeam(o, s, d, r) : l`<p class="empty">No teams recorded for this school yet.</p>`}
980
- </div>
1123
+ ${B(this, i`
1124
+ ${P(this)}
1125
+ ${s ? this.renderTeam(o, s, l, r) : i`<p class="empty">No teams recorded for this school yet.</p>`}
1126
+ `)}
981
1127
  `;
982
1128
  }
983
1129
  renderTeam(e, t, s, r) {
984
- const o = e.records[t.id] || { w: 0, l: 0, t: 0, cw: 0, cl: 0, ct: 0, pf: 0, pa: 0, results: [] }, n = o.w + o.l + o.t, i = s ? this.data.allTeams.filter((h) => h.conferenceId === s.id) : [], m = s ? K(i, e.records).findIndex((h) => h.team.id === t.id) + 1 : 0, d = X(e.rankings, e.teamsById, t.id, t.sport, null), c = this.data.games.filter((h) => h.homeTeamId === t.id || h.awayTeamId === t.id).sort((h, f) => String(h.date).localeCompare(String(f.date)));
985
- return l`
1130
+ const o = e.records[t.id] || { w: 0, l: 0, t: 0, cw: 0, cl: 0, ct: 0, pf: 0, pa: 0, results: [] }, c = o.w + o.l + o.t, n = s ? this.data.allTeams.filter((m) => m.conferenceId === s.id) : [], h = s ? ae(n, e.records).findIndex((m) => m.team.id === t.id) + 1 : 0, l = V(e.rankings, e.teamsById, t.id, t.sport, null), d = this.data.games.filter((m) => m.homeTeamId === t.id || m.awayTeamId === t.id).sort((m, f) => String(m.date).localeCompare(String(f.date)));
1131
+ return i`
986
1132
  <div class="tiles">
987
- <div class="tile"><div class="k">Overall</div><div class="v">${w(o)}</div><div class="s">${n} games played</div></div>
1133
+ <div class="tile"><div class="k">Overall</div><div class="v">${w(o)}</div><div class="s">${c} games played</div></div>
988
1134
  <div class="tile"><div class="k">${s?.name || "Conference"}</div><div class="v">${w(o, !0)}</div>
989
- <div class="s">${m ? `${me(m)} of ${i.length}` : "·"}</div></div>
990
- <div class="tile"><div class="k">Points</div><div class="v">${n ? (o.pf / n).toFixed(1) : "0.0"}</div>
991
- <div class="s">scored per game · ${n ? (o.pa / n).toFixed(1) : "0.0"} allowed</div></div>
992
- <div class="tile"><div class="k">Streak</div><div class="v">${_(o.results) || "·"}</div>
993
- <div class="s">last 5: ${W(e, t.id)}</div></div>
994
- <div class="tile"><div class="k">HSOT Top 25</div><div class="v">${d ? `#${d}` : "NR"}</div>
995
- <div class="s"><a href=${v(e.hrefs.section, { sport: t.sport, view: "rankings" })}>full poll</a></div></div>
1135
+ <div class="s">${h ? `${he(h)} of ${n.length}` : "·"}</div></div>
1136
+ <div class="tile"><div class="k">Points</div><div class="v">${c ? (o.pf / c).toFixed(1) : "0.0"}</div>
1137
+ <div class="s">scored per game · ${c ? (o.pa / c).toFixed(1) : "0.0"} allowed</div></div>
1138
+ <div class="tile"><div class="k">Streak</div><div class="v">${O(o.results) || "·"}</div>
1139
+ <div class="s">last 5: ${Q(e, t.id)}</div></div>
1140
+ <div class="tile"><div class="k">HSOT Top 25</div><div class="v">${l ? `#${l}` : "NR"}</div>
1141
+ <div class="s"><a href=${u(e.hrefs.section, { sport: t.sport, view: "rankings" })}>full poll</a></div></div>
996
1142
  </div>
997
- ${(t.championships || []).length ? l`
1143
+ ${(t.championships || []).length ? i`
998
1144
  <div style="margin:-0.2rem 0 1rem;display:flex;gap:0.4rem;flex-wrap:wrap">
999
- ${t.championships.map((h) => l`<span class="pill champ">★ ${h.season} ${h.title} champion${h.classification ? ` · ${h.classification}` : ""}${h.region ? ` · ${h.region}` : ""}</span>`)}
1145
+ ${t.championships.map((m) => i`<span class="pill champ">★ ${m.season} ${m.title} champion${m.classification ? ` · ${m.classification}` : ""}${m.region ? ` · ${m.region}` : ""}</span>`)}
1000
1146
  </div>` : p}
1001
1147
  <div class="cols">
1002
1148
  <div>
1003
1149
  <div class="section-title">Schedule &amp; results</div>
1004
1150
  <div class="card">
1005
- ${c.length ? l`<ul class="gamelist">${c.map((h) => this.renderGameRow(e, t, h))}</ul>` : l`<p class="empty">No ${t.sport} games recorded for ${r}.</p>`}
1151
+ ${d.length ? i`<ul class="gamelist">${d.map((m) => this.renderGameRow(e, t, m))}</ul>` : i`<p class="empty">No ${t.sport} games recorded for ${r}.</p>`}
1006
1152
  </div>
1007
1153
  </div>
1008
1154
  <div>
@@ -1013,45 +1159,45 @@ class we extends b {
1013
1159
  `;
1014
1160
  }
1015
1161
  renderGameRow(e, t, s) {
1016
- const r = s.homeTeamId === t.id, o = r ? s.awayTeamId : s.homeTeamId, n = r ? s.homeScore : s.awayScore, i = r ? s.awayScore : s.homeScore;
1017
- let m = l`<span class="mut">${E(s.time)}</span>`;
1162
+ const r = s.homeTeamId === t.id, o = r ? s.awayTeamId : s.homeTeamId, c = r ? s.homeScore : s.awayScore, n = r ? s.awayScore : s.homeScore;
1163
+ let h = i`<span class="mut">${L(s.time)}</span>`;
1018
1164
  if (s.state === "final") {
1019
- const c = j(s), h = c === "tie" ? "T" : c === (r ? "home" : "away") ? "W" : "L";
1020
- m = l`<span class=${h}>${h}</span> ${n}-${i}${s.finish === "overtime" ? l` <span class="mut">OT</span>` : p}${s.forfeit && s.forfeit !== "none" ? l` <span class="mut">FF</span>` : p}`;
1021
- } else s.state === "live" && (m = l`<span style="color:var(--hsot-red)">${n}-${i}</span>`);
1022
- const d = s.gameType === "conference" ? "Conf" : s.gameType === "nonconference" ? "Non-conf" : s.gameType === "playoff" ? `Playoff${s.label ? ` · ${s.label}` : ""}` : "Scrimmage";
1023
- return l`
1165
+ const d = q(s), m = d === "tie" ? "T" : d === (r ? "home" : "away") ? "W" : "L";
1166
+ h = i`<span class=${m}>${m}</span> ${c}-${n}${s.finish === "overtime" ? i` <span class="mut">OT</span>` : p}${s.forfeit && s.forfeit !== "none" ? i` <span class="mut">FF</span>` : p}`;
1167
+ } else s.state === "live" && (h = i`<span style="color:var(--hsot-red)">${c}-${n}</span>`);
1168
+ const l = s.gameType === "conference" ? "Conf" : s.gameType === "nonconference" ? "Non-conf" : s.gameType === "playoff" ? `Playoff${s.label ? ` · ${s.label}` : ""}` : "Scrimmage";
1169
+ return i`
1024
1170
  <li>
1025
1171
  <span class="d">${$(s.date)}</span>
1026
- ${B(s)}
1027
- <span class="res">${m}</span>
1028
- <span class="opp">${r ? "vs" : "at"} ${U(e, o, s.date)}
1029
- <span class="pill type">${d}</span>
1030
- ${s.broadcast ? l`<span class="pill class">${s.broadcast}</span>` : p}
1172
+ ${R(s)}
1173
+ <span class="res">${h}</span>
1174
+ <span class="opp">${r ? "vs" : "at"} ${M(e, o, s.date)}
1175
+ <span class="pill type">${l}</span>
1176
+ ${s.broadcast ? i`<span class="pill class">${s.broadcast}</span>` : p}
1031
1177
  </span>
1032
1178
  <span class="where">${s.venue || ""}</span>
1033
- <a class="box" href=${v(e.hrefs.game, { sport: t.sport, id: s.id })}>Box score →</a>
1179
+ <a class="box" href=${u(e.hrefs.game, { sport: t.sport, id: s.id })}>Box score →</a>
1034
1180
  </li>
1035
1181
  `;
1036
1182
  }
1037
1183
  renderRoster(e) {
1038
1184
  const t = this.data.roster;
1039
1185
  if (!t)
1040
- return l`<p class="empty">Roster not published for ${e}.</p>`;
1041
- const s = g(this.data.players), r = t.entries.slice().sort((o, n) => (o.number || 0) - (n.number || 0));
1042
- return l`
1186
+ return i`<p class="empty">Roster not published for ${e}.</p>`;
1187
+ const s = v(this.data.players), r = t.entries.slice().sort((o, c) => (o.number || 0) - (c.number || 0));
1188
+ return i`
1043
1189
  <div class="tablewrap"><table class="data">
1044
1190
  <thead><tr><th class="num">No.</th><th>Player</th><th>Pos</th><th>Class</th><th class="num">Ht</th><th class="num">Wt</th></tr></thead>
1045
1191
  <tbody>
1046
1192
  ${r.map((o) => {
1047
- const n = s[o.playerId];
1048
- return n ? l`<tr>
1193
+ const c = s[o.playerId];
1194
+ return c ? i`<tr>
1049
1195
  <td class="num mut">${o.number ?? "·"}</td>
1050
- <td style="font-weight:500">${n.firstName} ${n.lastName}</td>
1196
+ <td style="font-weight:500">${c.firstName} ${c.lastName}</td>
1051
1197
  <td>${o.position || "·"}</td>
1052
- <td class="mut">${n.classOf || "·"}</td>
1053
- <td class="num">${he(n.heightIn)}</td>
1054
- <td class="num">${n.weightLb || "·"}</td>
1198
+ <td class="mut">${c.classOf || "·"}</td>
1199
+ <td class="num">${ce(c.heightIn)}</td>
1200
+ <td class="num">${c.weightLb || "·"}</td>
1055
1201
  </tr>` : p;
1056
1202
  })}
1057
1203
  </tbody>
@@ -1059,16 +1205,16 @@ class we extends b {
1059
1205
  `;
1060
1206
  }
1061
1207
  }
1062
- globalThis?.customElements && !globalThis.customElements.get("hsot-school") && globalThis.customElements.define("hsot-school", we);
1063
- const xe = "https://api.wral.com/search";
1064
- function ke(a) {
1208
+ globalThis?.customElements && !globalThis.customElements.get("hsot-school") && globalThis.customElements.define("hsot-school", Be);
1209
+ const Pe = "https://api.wral.com/search";
1210
+ function Ee(a) {
1065
1211
  return a.map((e) => `uri:"${e}"`).join(" OR ");
1066
1212
  }
1067
- function Te(a, e) {
1068
- const t = String(a || xe).replace(/\/+$/, ""), s = new URLSearchParams({ query: ke(e), sort: "score", lang: "en" });
1213
+ function _e(a, e) {
1214
+ const t = String(a || Pe).replace(/\/+$/, ""), s = new URLSearchParams({ query: Ee(e), sort: "score", lang: "en" });
1069
1215
  return `${t}/v1/query?${s}`;
1070
1216
  }
1071
- function J(a) {
1217
+ function oe(a) {
1072
1218
  try {
1073
1219
  const e = new URL(a);
1074
1220
  if (/(^|\.)smugmug\.com$/i.test(e.hostname)) {
@@ -1083,13 +1229,13 @@ function J(a) {
1083
1229
  }
1084
1230
  return { uri: a, title: a };
1085
1231
  }
1086
- async function Ie(a, e, t) {
1087
- const r = await ((...i) => fetch(...i))(Te(a, e));
1232
+ async function Ae(a, e, t) {
1233
+ const r = await ((...n) => fetch(...n))(_e(a, e));
1088
1234
  if (!r.ok) throw new Error(`search answered ${r.status}`);
1089
- const o = await r.json(), n = new Map((o.items || []).map((i) => [i.uri, i]));
1090
- return e.map((i) => n.get(i) || J(i));
1235
+ const o = await r.json(), c = new Map((o.items || []).map((n) => [n.uri, n]));
1236
+ return e.map((n) => c.get(n) || oe(n));
1091
1237
  }
1092
- const Se = y`
1238
+ const Re = b`
1093
1239
  .breadcrumbs { font-size: 0.8125rem; margin: 0.9rem 0 0; color: var(--hsot-gray-5); }
1094
1240
  .breadcrumbs a { text-decoration: none; }
1095
1241
  .scorehead { display: grid; grid-template-columns: 1fr auto 1fr; gap: 1rem; align-items: center; padding: 1.4rem 1rem; }
@@ -1128,10 +1274,10 @@ const Se = y`
1128
1274
  .cols { grid-template-columns: 1fr; }
1129
1275
  }
1130
1276
  `;
1131
- class De extends b {
1132
- static styles = [...S, Se];
1277
+ class Le extends y {
1278
+ static styles = [...F, Re];
1133
1279
  static properties = {
1134
- ...b.properties,
1280
+ ...y.properties,
1135
1281
  gameId: { type: String, attribute: "game-id" },
1136
1282
  // The public site search that resolves Game.coverageUrls into cards
1137
1283
  // (DEV-1236). Shared cross-stage by design — see the studio host's
@@ -1143,7 +1289,7 @@ class De extends b {
1143
1289
  super(), this.gameId = "", this.searchApi = "";
1144
1290
  }
1145
1291
  async fetchData(e) {
1146
- const t = await e.getGame(this.gameId), s = Array.isArray(t.coverageUrls) ? t.coverageUrls : [], [r, o, n, i, m, d] = await Promise.all([
1292
+ const t = await e.getGame(this.gameId), s = Array.isArray(t.coverageUrls) ? t.coverageUrls : [], [r, o, c, n, h, l] = await Promise.all([
1147
1293
  e.listSchools(),
1148
1294
  e.listTeams({ sport: t.sport }),
1149
1295
  e.listConferences(),
@@ -1151,73 +1297,74 @@ class De extends b {
1151
1297
  e.listGames({ sport: t.sport, season: t.season }),
1152
1298
  // A search outage must not blank the box score — degrade to bare
1153
1299
  // links (fetchCoverage already degrades per-URL index misses).
1154
- s.length ? Ie(this.searchApi, s).catch(() => s.map(J)) : Promise.resolve([])
1300
+ s.length ? Ae(this.searchApi, s).catch(() => s.map(oe)) : Promise.resolve([])
1155
1301
  ]);
1156
1302
  return {
1157
1303
  game: t,
1158
1304
  schools: r.items,
1159
1305
  teams: o.items,
1160
- conferences: n.items,
1161
- rankings: i.items,
1162
- games: m.items,
1163
- coverage: d
1306
+ conferences: c.items,
1307
+ rankings: n.items,
1308
+ games: h.items,
1309
+ coverage: l
1164
1310
  };
1165
1311
  }
1166
1312
  get ctx() {
1167
1313
  return (!this._ctx || this._ctxData !== this.data) && (this._ctx = {
1168
- teamsById: g(this.data.teams),
1169
- schoolsById: g(this.data.schools),
1170
- records: D(this.data.games),
1314
+ teamsById: v(this.data.teams),
1315
+ schoolsById: v(this.data.schools),
1316
+ records: z(this.data.games),
1171
1317
  rankings: this.data.rankings,
1172
- hrefs: C(this),
1318
+ hrefs: D(this),
1173
1319
  sport: this.data.game.sport
1174
1320
  }, this._ctxData = this.data), this._ctx;
1175
1321
  }
1176
1322
  renderView() {
1177
1323
  const e = this.data.game;
1178
- if (!e) return l`<div class="view"><p class="empty">Game not found.</p></div>`;
1179
- const t = this.ctx, s = g(this.data.conferences), r = t.teamsById[e.awayTeamId] ? t.schoolsById[t.teamsById[e.awayTeamId].schoolId] : null, o = t.teamsById[e.homeTeamId] ? t.schoolsById[t.teamsById[e.homeTeamId].schoolId] : null, n = j(e), i = (c) => e.state === "final" && n !== c && n !== "tie" ? "opacity:0.45" : "", m = e.conferenceId ? s[e.conferenceId] : null, d = this.data.games.filter((c) => c.id !== e.id && c.state === "final" && c.gameType !== "scrimmage" && (c.homeTeamId === e.homeTeamId && c.awayTeamId === e.awayTeamId || c.homeTeamId === e.awayTeamId && c.awayTeamId === e.homeTeamId));
1180
- return l`
1181
- <div class="view">
1324
+ if (!e) return i`<div class="view"><p class="empty">Game not found.</p></div>`;
1325
+ const t = this.ctx, s = v(this.data.conferences), r = t.teamsById[e.awayTeamId] ? t.schoolsById[t.teamsById[e.awayTeamId].schoolId] : null, o = t.teamsById[e.homeTeamId] ? t.schoolsById[t.teamsById[e.homeTeamId].schoolId] : null, c = q(e), n = (d) => e.state === "final" && c !== d && c !== "tie" ? "opacity:0.45" : "", h = e.conferenceId ? s[e.conferenceId] : null, l = this.data.games.filter((d) => d.id !== e.id && d.state === "final" && d.gameType !== "scrimmage" && (d.homeTeamId === e.homeTeamId && d.awayTeamId === e.awayTeamId || d.homeTeamId === e.awayTeamId && d.awayTeamId === e.homeTeamId));
1326
+ return i`
1327
+ ${B(this, i`
1328
+ ${P(this)}
1182
1329
  <p class="breadcrumbs">
1183
- <a href=${v(t.hrefs.section, { sport: e.sport, view: "scores" })}>${R(e.sport)}</a> /
1184
- <a href=${v(t.hrefs.section, { sport: e.sport, view: "scores" })}>Scores/Schedules</a> /
1185
- ${k(t, e.awayTeamId)} at ${k(t, e.homeTeamId)}
1330
+ <a href=${u(t.hrefs.section, { sport: e.sport, view: "scores" })}>${T(e.sport)}</a> /
1331
+ <a href=${u(t.hrefs.section, { sport: e.sport, view: "scores" })}>Scores/Schedules</a> /
1332
+ ${I(t, e.awayTeamId)} at ${I(t, e.homeTeamId)}
1186
1333
  </p>
1187
1334
  <div class="card">
1188
1335
  <div class="scorehead">
1189
1336
  ${this.teamBlock(t, e, e.awayTeamId, r, !1)}
1190
1337
  <div class="mid">
1191
1338
  <div class="bigscore">
1192
- <span style=${i("away")}>${e.awayScore}</span>
1339
+ <span style=${n("away")}>${e.awayScore}</span>
1193
1340
  <span class="mut" style="font-size:1.6rem">–</span>
1194
- <span style=${i("home")}>${e.homeScore}</span>
1341
+ <span style=${n("home")}>${e.homeScore}</span>
1195
1342
  </div>
1196
- <div class="status">${B(e)}</div>
1197
- <div class="status">${$(e.date, { weekday: "short", month: "short", day: "numeric", year: "numeric" })}${e.state === "scheduled" && e.time ? l` · ${E(e.time)}` : p} · ${e.venue || "Venue TBD"}
1198
- ${e.broadcast ? l` · <span class="pill class">${e.broadcast}</span>` : p}</div>
1343
+ <div class="status">${R(e)}</div>
1344
+ <div class="status">${$(e.date, { weekday: "short", month: "short", day: "numeric", year: "numeric" })}${e.state === "scheduled" && e.time ? i` · ${L(e.time)}` : p} · ${e.venue || "Venue TBD"}
1345
+ ${e.broadcast ? i` · <span class="pill class">${e.broadcast}</span>` : p}</div>
1199
1346
  <div class="status">
1200
- <span class="pill type">${e.gameType === "conference" ? `${m?.name || "Conference"} game` : e.gameType}</span>
1201
- ${e.label ? l`<span class="pill type">Bracket ${e.label}</span>` : p}
1202
- ${(e.tags || []).map((c) => l`<span class="pill type">${c}</span>`)}
1347
+ <span class="pill type">${e.gameType === "conference" ? `${h?.name || "Conference"} game` : e.gameType}</span>
1348
+ ${e.label ? i`<span class="pill type">Bracket ${e.label}</span>` : p}
1349
+ ${(e.tags || []).map((d) => i`<span class="pill type">${d}</span>`)}
1203
1350
  </div>
1204
1351
  </div>
1205
1352
  ${this.teamBlock(t, e, e.homeTeamId, o, !0)}
1206
1353
  </div>
1207
1354
  ${this.renderLineScore(e, r, o)}
1208
- ${e.notes ? l`<p class="note" style="padding:0 1rem 0.9rem;text-align:center">${e.notes}</p>` : p}
1355
+ ${e.notes ? i`<p class="note" style="padding:0 1rem 0.9rem;text-align:center">${e.notes}</p>` : p}
1209
1356
  </div>
1210
- ${(this.data.coverage || []).length ? l`
1357
+ ${(this.data.coverage || []).length ? i`
1211
1358
  <div class="section-title">Coverage</div>
1212
1359
  <div class="covgrid">
1213
- ${this.data.coverage.map((c) => l`
1214
- <a class="card covcard" href=${c.uri}>
1215
- ${c.image ? l`<img class="covimg" src=${c.image} alt="" loading="lazy" />` : p}
1360
+ ${this.data.coverage.map((d) => i`
1361
+ <a class="card covcard" href=${d.uri}>
1362
+ ${d.image ? i`<img class="covimg" src=${d.image} alt="" loading="lazy" />` : p}
1216
1363
  <div class="covbody">
1217
- <div class="covtitle">${c.videoDuration ? l`<span class="pill live" style="animation:none">Video</span> ` : p}${c.photos ? l`<span class="pill live" style="animation:none">Photos</span> ` : p}${c.title || c.uri}</div>
1218
- ${c.description ? l`<p class="covdesc">${c.description}</p>` : p}
1219
- ${c.author || c.publishedTime ? l`
1220
- <div class="covmeta">${[c.author, c.publishedTime ? new Date(c.publishedTime).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" }) : ""].filter(Boolean).join(" · ")}</div>
1364
+ <div class="covtitle">${d.videoDuration ? i`<span class="pill live" style="animation:none">Video</span> ` : p}${d.photos ? i`<span class="pill live" style="animation:none">Photos</span> ` : p}${d.title || d.uri}</div>
1365
+ ${d.description ? i`<p class="covdesc">${d.description}</p>` : p}
1366
+ ${d.author || d.publishedTime ? i`
1367
+ <div class="covmeta">${[d.author, d.publishedTime ? new Date(d.publishedTime).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" }) : ""].filter(Boolean).join(" · ")}</div>
1221
1368
  ` : p}
1222
1369
  </div>
1223
1370
  </a>
@@ -1225,29 +1372,29 @@ class De extends b {
1225
1372
  </div>` : p}
1226
1373
  <div class="section-title">Season context</div>
1227
1374
  <div class="cols">
1228
- ${[[e.awayTeamId, r], [e.homeTeamId, o]].map(([c, h]) => this.renderContext(t, c, h))}
1375
+ ${[[e.awayTeamId, r], [e.homeTeamId, o]].map(([d, m]) => this.renderContext(t, d, m))}
1229
1376
  </div>
1230
- ${d.length ? l`
1377
+ ${l.length ? i`
1231
1378
  <div class="section-title">Head to head this season</div>
1232
1379
  <div class="card"><ul class="gamelist">
1233
- ${d.map((c) => l`<li>
1234
- <span class="d">${$(c.date)}</span>${B(c)}
1235
- <span class="opp">${k(t, c.awayTeamId)} ${c.awayScore}, ${k(t, c.homeTeamId)} ${c.homeScore}</span>
1236
- <a class="box" href=${v(t.hrefs.game, { sport: e.sport, id: c.id })}>Box score →</a>
1380
+ ${l.map((d) => i`<li>
1381
+ <span class="d">${$(d.date)}</span>${R(d)}
1382
+ <span class="opp">${I(t, d.awayTeamId)} ${d.awayScore}, ${I(t, d.homeTeamId)} ${d.homeScore}</span>
1383
+ <a class="box" href=${u(t.hrefs.game, { sport: e.sport, id: d.id })}>Box score →</a>
1237
1384
  </li>`)}
1238
1385
  </ul></div>` : p}
1239
- </div>
1386
+ `)}
1240
1387
  `;
1241
1388
  }
1242
1389
  teamBlock(e, t, s, r, o) {
1243
- if (!r) return l`<div class="teamblock ${o ? "right" : ""}"><div class="tname">TBD</div></div>`;
1244
- const n = e.teamsById[s], i = e.records[s], m = P(r, 58);
1245
- return l`
1390
+ if (!r) return i`<div class="teamblock ${o ? "right" : ""}"><div class="tname">TBD</div></div>`;
1391
+ const c = e.teamsById[s], n = e.records[s], h = _(r, 58);
1392
+ return i`
1246
1393
  <div class="teamblock ${o ? "right" : ""}">
1247
- ${m ? l`<img class="crest logo" alt="" loading="lazy" src=${m} />` : l`<span class="crest" style="background:${r.colorPrimary || "#030711"};color:${F(r.colorPrimary || "#030711")}">${M(r)}</span>`}
1394
+ ${h ? i`<img class="crest logo" alt="" loading="lazy" src=${h} />` : i`<span class="crest" style="background:${r.colorPrimary || "#030711"};color:${E(r.colorPrimary || "#030711")}">${G(r)}</span>`}
1248
1395
  <div>
1249
- <div class="tname">${G(e, s, t.date)}<a href=${v(e.hrefs.school, { id: r.id })}>${r.name}</a></div>
1250
- <div class="trec">${r.mascot || ""} · ${w(i)}${n?.conferenceId ? l` · ${w(i, !0)} conf` : p}</div>
1396
+ <div class="tname">${K(e, s, t.date)}<a href=${u(e.hrefs.school, { id: r.id })}>${r.name}</a></div>
1397
+ <div class="trec">${r.mascot || ""} · ${w(n)}${c?.conferenceId ? i` · ${w(n, !0)} conf` : p}</div>
1251
1398
  </div>
1252
1399
  </div>
1253
1400
  `;
@@ -1255,23 +1402,23 @@ class De extends b {
1255
1402
  renderLineScore(e, t, s) {
1256
1403
  const r = e.periodScores || [];
1257
1404
  if (!r.length)
1258
- return l`<p class="empty" style="text-align:center">Period scoring will appear once the game starts.</p>`;
1259
- const o = Math.max(4, ...r.map((d) => d.period)), n = (d) => d <= 4 ? String(d) : `OT${d > 5 ? d - 4 : ""}`, i = (d, c) => {
1260
- const h = r.find((f) => f.period === c);
1261
- return h ? h[d] : e.state === "final" ? 0 : "·";
1262
- }, m = (d, c, h) => l`
1405
+ return i`<p class="empty" style="text-align:center">Period scoring will appear once the game starts.</p>`;
1406
+ const o = Math.max(4, ...r.map((l) => l.period)), c = (l) => l <= 4 ? String(l) : `OT${l > 5 ? l - 4 : ""}`, n = (l, d) => {
1407
+ const m = r.find((f) => f.period === d);
1408
+ return m ? m[l] : e.state === "final" ? 0 : "·";
1409
+ }, h = (l, d, m) => i`
1263
1410
  <tr>
1264
- <td class="teamcell">${I(d, 20)}${d?.abbr || "TBD"}</td>
1265
- ${Array.from({ length: o }, (f, u) => l`<td class="num">${i(c, u + 1)}</td>`)}
1266
- <td class="num" style="font-weight:700">${h}</td>
1411
+ <td class="teamcell">${C(l, 20)}${l?.abbr || "TBD"}</td>
1412
+ ${Array.from({ length: o }, (f, g) => i`<td class="num">${n(d, g + 1)}</td>`)}
1413
+ <td class="num" style="font-weight:700">${m}</td>
1267
1414
  </tr>`;
1268
- return l`
1415
+ return i`
1269
1416
  <div class="tablewrap" style="border-top:1px solid var(--hsot-gray-2)">
1270
1417
  <table class="data" style="max-width:560px;margin:0.6rem auto 0.9rem">
1271
- <thead><tr><th>Team</th>${Array.from({ length: o }, (d, c) => l`<th class="num">${n(c + 1)}</th>`)}<th class="num">T</th></tr></thead>
1418
+ <thead><tr><th>Team</th>${Array.from({ length: o }, (l, d) => i`<th class="num">${c(d + 1)}</th>`)}<th class="num">T</th></tr></thead>
1272
1419
  <tbody>
1273
- ${m(t, "away", e.awayScore)}
1274
- ${m(s, "home", e.homeScore)}
1420
+ ${h(t, "away", e.awayScore)}
1421
+ ${h(s, "home", e.homeScore)}
1275
1422
  </tbody>
1276
1423
  </table>
1277
1424
  </div>
@@ -1279,37 +1426,217 @@ class De extends b {
1279
1426
  }
1280
1427
  renderContext(e, t, s) {
1281
1428
  if (!s) return p;
1282
- const r = e.records[t], o = H(this.data.games, t);
1283
- return l`
1429
+ const r = e.records[t], o = W(this.data.games, t);
1430
+ return i`
1284
1431
  <div class="card ctxcard">
1285
- <div class="who">${I(s)}${s.name}</div>
1432
+ <div class="who">${C(s)}${s.name}</div>
1286
1433
  <div class="row">
1287
- <span>Last 5: ${W(e, t)}</span>
1288
- <span>Streak: <b>${r ? _(r.results) : "·"}</b></span>
1434
+ <span>Last 5: ${Q(e, t)}</span>
1435
+ <span>Streak: <b>${r ? O(r.results) : "·"}</b></span>
1289
1436
  <span>PF/PA: <b>${r ? `${r.pf} / ${r.pa}` : "·"}</b></span>
1290
- <span>Next: ${o ? l`${$(o.date, { month: "numeric", day: "numeric" })}
1291
- ${o.homeTeamId === t ? "vs" : "at"} ${z(e, o.homeTeamId === t ? o.awayTeamId : o.homeTeamId)}` : "·"}</span>
1437
+ <span>Next: ${o ? i`${$(o.date, { month: "numeric", day: "numeric" })}
1438
+ ${o.homeTeamId === t ? "vs" : "at"} ${A(e, o.homeTeamId === t ? o.awayTeamId : o.homeTeamId)}` : "·"}</span>
1292
1439
  </div>
1293
1440
  </div>
1294
1441
  `;
1295
1442
  }
1296
1443
  }
1297
- globalThis?.customElements && !globalThis.customElements.get("hsot-boxscore") && globalThis.customElements.define("hsot-boxscore", De);
1444
+ globalThis?.customElements && !globalThis.customElements.get("hsot-boxscore") && globalThis.customElements.define("hsot-boxscore", Le);
1445
+ const Ne = 250, Oe = 2;
1446
+ class He extends te {
1447
+ static properties = {
1448
+ api: { type: String },
1449
+ schoolHref: { type: String, attribute: "school-href" },
1450
+ limit: { type: Number },
1451
+ placeholder: { type: String },
1452
+ results: { state: !0 },
1453
+ open: { state: !0 },
1454
+ activeIndex: { state: !0 },
1455
+ searched: { state: !0 }
1456
+ };
1457
+ static styles = b`
1458
+ :host {
1459
+ display: block;
1460
+ position: relative;
1461
+ font-family: var(--font-family, sans-serif);
1462
+ }
1463
+ input {
1464
+ width: 100%;
1465
+ box-sizing: border-box;
1466
+ padding: 0.625rem 0.75rem;
1467
+ font-size: 1rem;
1468
+ font-family: inherit;
1469
+ color: var(--color-black, #000);
1470
+ background: var(--color-white, #fff);
1471
+ border: 1px solid var(--color-gray-4, #ccc);
1472
+ border-bottom: 3px solid var(--color-red, #b90100);
1473
+ border-radius: 2px;
1474
+ }
1475
+ input:focus {
1476
+ outline: 2px solid var(--color-red, #b90100);
1477
+ outline-offset: -1px;
1478
+ }
1479
+ ul {
1480
+ position: absolute;
1481
+ z-index: 10;
1482
+ left: 0;
1483
+ right: 0;
1484
+ margin: 0;
1485
+ padding: 0;
1486
+ list-style: none;
1487
+ max-height: 20rem;
1488
+ overflow-y: auto;
1489
+ background: var(--color-white, #fff);
1490
+ border: 1px solid var(--color-gray-4, #ccc);
1491
+ border-top: none;
1492
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
1493
+ }
1494
+ li {
1495
+ padding: 0.5rem 0.75rem;
1496
+ cursor: pointer;
1497
+ }
1498
+ li[aria-selected="true"], li:hover {
1499
+ background: var(--color-gray-1, #f9f9f9);
1500
+ }
1501
+ li .name {
1502
+ font-weight: 700;
1503
+ color: var(--color-black, #000);
1504
+ }
1505
+ li .where {
1506
+ display: block;
1507
+ font-size: 0.8rem;
1508
+ color: var(--color-gray-5, #666);
1509
+ }
1510
+ li.empty {
1511
+ cursor: default;
1512
+ color: var(--color-gray-5, #666);
1513
+ }
1514
+ li.empty:hover {
1515
+ background: none;
1516
+ }
1517
+ `;
1518
+ constructor() {
1519
+ super(), this.api = "https://api.highschoolot.com/hsot/v1/public", this.schoolHref = "/school/{id}/", this.limit = 10, this.placeholder = "Find Your School", this.results = [], this.open = !1, this.activeIndex = -1, this.searched = !1;
1520
+ }
1521
+ disconnectedCallback() {
1522
+ super.disconnectedCallback(), clearTimeout(this.debounceTimer), this.abortController?.abort();
1523
+ }
1524
+ onInput(e) {
1525
+ const t = e.target.value.trim();
1526
+ if (clearTimeout(this.debounceTimer), t.length < Oe) {
1527
+ this.abortController?.abort(), this.results = [], this.open = !1, this.searched = !1;
1528
+ return;
1529
+ }
1530
+ this.debounceTimer = setTimeout(() => this.search(t), Ne);
1531
+ }
1532
+ async search(e) {
1533
+ this.abortController?.abort(), this.abortController = new AbortController();
1534
+ try {
1535
+ const t = `${this.api}/schools?q=${encodeURIComponent(e)}&limit=${this.limit}`, s = await fetch(t, {
1536
+ signal: this.abortController.signal
1537
+ });
1538
+ if (!s.ok)
1539
+ return;
1540
+ const r = await s.json();
1541
+ this.results = r.items || [], this.activeIndex = -1, this.searched = !0, this.open = !0;
1542
+ } catch (t) {
1543
+ t.name !== "AbortError" && console.warn("school search failed", t);
1544
+ }
1545
+ }
1546
+ onKeyDown(e) {
1547
+ if (e.key === "Escape") {
1548
+ this.open = !1;
1549
+ return;
1550
+ }
1551
+ if (!(!this.open || !this.results.length))
1552
+ if (e.key === "ArrowDown")
1553
+ e.preventDefault(), this.activeIndex = (this.activeIndex + 1) % this.results.length;
1554
+ else if (e.key === "ArrowUp") {
1555
+ e.preventDefault();
1556
+ const t = this.results.length;
1557
+ this.activeIndex = (this.activeIndex - 1 + t) % t;
1558
+ } else e.key === "Enter" && (e.preventDefault(), this.go(this.results[this.activeIndex] || this.results[0]));
1559
+ }
1560
+ onBlur() {
1561
+ setTimeout(() => {
1562
+ this.open = !1;
1563
+ }, 150);
1564
+ }
1565
+ onFocus() {
1566
+ this.results.length && (this.open = !0);
1567
+ }
1568
+ go(e) {
1569
+ e && (globalThis.location.href = this.schoolHref.replace("{id}", e.id));
1570
+ }
1571
+ where(e) {
1572
+ return [e.location, e.county && `${e.county} County`].filter(Boolean).join(" — ");
1573
+ }
1574
+ renderOption(e, t) {
1575
+ const s = this.where(e), r = (o) => {
1576
+ o.preventDefault(), this.go(e);
1577
+ };
1578
+ return i`
1579
+ <li
1580
+ id="school-option-${t}"
1581
+ role="option"
1582
+ aria-selected="${t === this.activeIndex ? "true" : "false"}"
1583
+ @pointerdown="${r}"
1584
+ @mousemove="${() => {
1585
+ this.activeIndex = t;
1586
+ }}"
1587
+ >
1588
+ <span class="name">${e.name}</span>
1589
+ ${s ? i`<span class="where">${s}</span>` : p}
1590
+ </li>
1591
+ `;
1592
+ }
1593
+ renderListbox() {
1594
+ const e = this.searched && !this.results.length, t = i`<li class="empty">No schools found</li>`;
1595
+ return i`
1596
+ <ul id="school-search-listbox" role="listbox" aria-label="Schools">
1597
+ ${this.results.map((s, r) => this.renderOption(s, r))}
1598
+ ${e ? t : p}
1599
+ </ul>
1600
+ `;
1601
+ }
1602
+ render() {
1603
+ const e = this.activeIndex >= 0 ? `school-option-${this.activeIndex}` : "";
1604
+ return i`
1605
+ <input
1606
+ type="text"
1607
+ role="combobox"
1608
+ aria-label="Find your school"
1609
+ aria-expanded="${this.open ? "true" : "false"}"
1610
+ aria-controls="school-search-listbox"
1611
+ aria-activedescendant="${e}"
1612
+ autocomplete="off"
1613
+ placeholder="${this.placeholder}"
1614
+ @input="${this.onInput}"
1615
+ @keydown="${this.onKeyDown}"
1616
+ @blur="${this.onBlur}"
1617
+ @focus="${this.onFocus}"
1618
+ >
1619
+ ${this.open ? this.renderListbox() : p}
1620
+ `;
1621
+ }
1622
+ }
1623
+ globalThis?.customElements && !globalThis.customElements.get("hsot-school-search") && globalThis.customElements.define("hsot-school-search", He);
1298
1624
  export {
1299
- N as D,
1300
- De as H,
1301
- be as a,
1302
- we as b,
1303
- ge as c,
1304
- ve as d,
1305
- D as e,
1306
- ae as f,
1307
- v as g,
1308
- j as h,
1309
- Fe as i,
1310
- _ as j,
1311
- fe as p,
1625
+ U as D,
1626
+ Le as H,
1627
+ Fe as a,
1628
+ Be as b,
1629
+ He as c,
1630
+ Se as d,
1631
+ Ce as e,
1632
+ z as f,
1633
+ le as g,
1634
+ u as h,
1635
+ q as i,
1636
+ Me as j,
1637
+ O as k,
1638
+ Te as p,
1312
1639
  w as r,
1313
- K as s,
1314
- X as t
1640
+ ae as s,
1641
+ V as t
1315
1642
  };