@wral/hsot-data 0.5.0 → 0.6.0

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,4 +1,4 @@
1
- import { LitElement as ce, html as n, css as $, nothing as p, svg as ee } from "lit";
1
+ import { LitElement as ce, html as n, css as $, nothing as p, svg as te } from "lit";
2
2
  import { createClient as Be } from "./client.mjs";
3
3
  const P = {
4
4
  game: "/{sport}/game/{id}/",
@@ -29,7 +29,7 @@ function x(a, e) {
29
29
  const [t, s, r] = String(a).split("-").map(Number);
30
30
  return !t || !s || !r ? "TBD" : new Date(t, s - 1, r).toLocaleDateString("en-US", e || { weekday: "short", month: "short", day: "numeric" });
31
31
  }
32
- function W(a) {
32
+ function V(a) {
33
33
  if (!a) return "";
34
34
  const [e, t] = String(a).split(":").map(Number);
35
35
  if (Number.isNaN(e)) return "";
@@ -46,17 +46,17 @@ function _(a = /* @__PURE__ */ new Date()) {
46
46
  const e = a.getFullYear();
47
47
  return a.getMonth() >= 6 ? `${e}-${e + 1}` : `${e - 1}-${e}`;
48
48
  }
49
- function V(a = /* @__PURE__ */ new Date()) {
49
+ function Y(a = /* @__PURE__ */ new Date()) {
50
50
  const e = (t) => String(t).padStart(2, "0");
51
51
  return `${a.getFullYear()}-${e(a.getMonth() + 1)}-${e(a.getDate())}`;
52
52
  }
53
- function ze(a, e = V()) {
53
+ function ze(a, e = Y()) {
54
54
  const t = [...new Set((a || []).filter(Boolean))].sort();
55
55
  if (!t.length || t.includes(e)) return e;
56
56
  const s = t.filter((r) => r < e);
57
57
  return s.length ? s[s.length - 1] : t[0];
58
58
  }
59
- function Y(a) {
59
+ function K(a) {
60
60
  return a ? (a.abbr || a.name || "?").slice(0, 4).toUpperCase() : "?";
61
61
  }
62
62
  function G(a) {
@@ -68,7 +68,7 @@ const Ae = (a) => {
68
68
  const e = ["th", "st", "nd", "rd"], t = a % 100;
69
69
  return a + (e[(t - 20) % 10] || e[t] || e[0]);
70
70
  };
71
- function te(a, e) {
71
+ function q(a, e) {
72
72
  const t = (o) => {
73
73
  const i = /^\d+/.exec(String(o ?? ""));
74
74
  return i ? Number(i[0]) : null;
@@ -88,7 +88,7 @@ function me(a) {
88
88
  const e = [];
89
89
  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(" · ")}` : ""}` };
90
90
  }
91
- return a.state === "postponed" ? { kind: "warn", label: "Postponed" } : a.state === "canceled" ? { kind: "warn", label: "Canceled" } : { kind: "sched", label: `${x(a.date, { month: "short", day: "numeric" })} · ${W(a.time)}`.replace(/ · $/, "") };
91
+ return a.state === "postponed" ? { kind: "warn", label: "Postponed" } : a.state === "canceled" ? { kind: "warn", label: "Canceled" } : { kind: "sched", label: `${x(a.date, { month: "short", day: "numeric" })} · ${V(a.time)}`.replace(/ · $/, "") };
92
92
  }
93
93
  const Pe = ["boys", "girls"];
94
94
  function pe(a, e) {
@@ -97,11 +97,11 @@ function pe(a, e) {
97
97
  function fe(a, e) {
98
98
  return e ? (a || []).filter((t) => pe(t, e)) : a || [];
99
99
  }
100
- function q(a) {
100
+ function W(a) {
101
101
  const e = new Set((a || []).map((t) => t && t.gender));
102
102
  return Pe.filter((t) => e.has(t));
103
103
  }
104
- const Ee = (a) => q(a).length === 2, _e = /* @__PURE__ */ new Set(["game", "story", "page", "forum", "video", "gallery"]);
104
+ const Ee = (a) => W(a).length === 2, _e = /* @__PURE__ */ new Set(["game", "story", "page", "forum", "video", "gallery"]);
105
105
  function S(a) {
106
106
  let e = String(a || "").replace(/^[a-z][a-z0-9+.-]*:\/\/[^/#?]*/i, "");
107
107
  const t = e.indexOf("#");
@@ -212,7 +212,7 @@ class w extends ce {
212
212
  return n``;
213
213
  }
214
214
  }
215
- const b = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), Me = $`
215
+ const y = (a) => Object.fromEntries((a || []).map((e) => [e.id, e])), Me = $`
216
216
  :host {
217
217
  --hsot-red: var(--color-red, #D1232A);
218
218
  --hsot-red-deep: var(--color-red-dark, #951C21);
@@ -514,20 +514,20 @@ function ge(a, e) {
514
514
  return { team: t, rec: s, confPct: se(s.cw, s.cl, s.ct), overallPct: se(s.w, s.l, s.t) };
515
515
  }).sort((t, s) => s.confPct - t.confPct || s.overallPct - t.overallPct || s.rec.pf - s.rec.pa - (t.rec.pf - t.rec.pa));
516
516
  }
517
- function K(a, e) {
517
+ function Q(a, e) {
518
518
  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;
519
519
  }
520
520
  function re(a, e) {
521
521
  const t = a[e];
522
522
  return t && t.results.length ? t.results[t.results.length - 1] : null;
523
523
  }
524
- function Nt(a, e, t, s = "") {
524
+ function Mt(a, e, t, s = "") {
525
525
  let r = null;
526
526
  for (const o of a || [])
527
527
  o.sport === e && (t && o.effectiveDate > t || s && o.gender && o.gender !== s || (!r || o.effectiveDate > r.effectiveDate) && (r = o));
528
528
  return r;
529
529
  }
530
- function Q(a, e, t, s, r) {
530
+ function Z(a, e, t, s, r) {
531
531
  const o = e[t];
532
532
  if (!o) return null;
533
533
  const i = /* @__PURE__ */ new Map();
@@ -603,17 +603,17 @@ function C(a, e = 26) {
603
603
  const s = a.colorPrimary || "#030711", r = G(s);
604
604
  return n`<span class="swatch" aria-hidden="true"
605
605
  style="width:${e}px;height:${e}px;background:${s};color:${r};font-size:${Math.max(8, e * 0.28)}px"
606
- >${Y(a)}</span>`;
606
+ >${K(a)}</span>`;
607
607
  }
608
- function Z(a, e, t) {
609
- const s = Q(a.rankings, a.teamsById, e, a.sport, t);
608
+ function X(a, e, t) {
609
+ const s = Z(a.rankings, a.teamsById, e, a.sport, t);
610
610
  return s ? n`<span class="rankbadge">#${s}</span>` : p;
611
611
  }
612
612
  function O(a, e, t) {
613
613
  const s = T(a, e);
614
- return s ? n`${Z(a, e, t)}<a href=${g(a.hrefs.school, { id: s.id })}>${s.name}</a>` : n`<span class="mut">TBD</span>`;
614
+ return s ? n`${X(a, e, t)}<a href=${g(a.hrefs.school, { id: s.id })}>${s.name}</a>` : n`<span class="mut">TBD</span>`;
615
615
  }
616
- function X(a, e, t = 5) {
616
+ function J(a, e, t = 5) {
617
617
  const s = a.records[e];
618
618
  if (!s || !s.results.length) return n`<span class="mut">·</span>`;
619
619
  const r = s.results.slice(-1 * t);
@@ -643,20 +643,67 @@ function be(a, e, t) {
643
643
  const s = e.homeTeamId === t ? e.awayTeamId : e.homeTeamId, r = e.homeTeamId === t ? "vs" : "at";
644
644
  return n`${e.state === "live" ? n`<span class="pill live">Live</span> ` : n`${x(e.date, { month: "numeric", day: "numeric" })} `}${r} ${L(a, s)}`;
645
645
  }
646
- const Qe = ["all", "conferences"], ye = "all", oe = (a) => Qe.includes(a) ? a : ye, $e = Number.MAX_SAFE_INTEGER, we = (a, e, t) => {
646
+ const Qe = "https://api.wral.com/search";
647
+ function Ze(a) {
648
+ return a.map((e) => `uri:"${e}"`).join(" OR ");
649
+ }
650
+ function Xe(a, e) {
651
+ const t = String(a || Qe).replace(/\/+$/, ""), s = new URLSearchParams({ query: Ze(e), sort: "score", lang: "en" });
652
+ return `${t}/v1/query?${s}`;
653
+ }
654
+ function ye(a) {
655
+ try {
656
+ const e = new URL(a);
657
+ if (/(^|\.)smugmug\.com$/i.test(e.hostname)) {
658
+ const t = e.pathname.split("/").filter(Boolean).pop() || "", s = !t || /^[ni]-[A-Za-z0-9]+$/.test(t);
659
+ return {
660
+ uri: a,
661
+ title: s ? a : decodeURIComponent(t).replace(/-/g, " "),
662
+ photos: !0
663
+ };
664
+ }
665
+ } catch {
666
+ }
667
+ return { uri: a, title: a };
668
+ }
669
+ async function Je(a, e, t) {
670
+ const r = await ((...l) => fetch(...l))(Xe(a, e));
671
+ if (!r.ok) throw new Error(`search answered ${r.status}`);
672
+ const o = await r.json(), i = new Map((o.items || []).map((l) => [l.uri, l]));
673
+ return e.map((l) => i.get(l) || ye(l));
674
+ }
675
+ function et(a) {
676
+ try {
677
+ const e = new URL(a);
678
+ if (/(^|\.)smugmug\.com$/i.test(e.hostname)) return "Photos";
679
+ const t = e.pathname.split("/").filter(Boolean)[0] || "";
680
+ if (t === "video") return "Video";
681
+ if (t === "news" || t === "story") return "Story";
682
+ } catch {
683
+ }
684
+ return "Coverage";
685
+ }
686
+ function tt(a) {
687
+ const e = /* @__PURE__ */ new Map();
688
+ return (Array.isArray(a) ? a : []).filter((t) => /^https?:\/\//i.test(String(t || ""))).map((t) => {
689
+ const s = et(t), r = (e.get(s) || 0) + 1;
690
+ return e.set(s, r), { href: t, label: r > 1 ? `${s} ${r}` : s };
691
+ });
692
+ }
693
+ const st = ["all", "conferences"], $e = "all", oe = (a) => st.includes(a) ? a : $e, we = Number.MAX_SAFE_INTEGER, xe = (a, e, t) => {
647
694
  const s = a[t];
648
695
  return s && e[s.schoolId] || null;
649
696
  };
650
- function Ze(a, e) {
697
+ function at(a, e) {
651
698
  const t = (a || []).map((s) => e[s.schoolId]?.areaCode).filter(Boolean);
652
699
  return [...new Set(t)].sort();
653
700
  }
654
- function Xe(a, e, t, s) {
655
- return e ? [a.awayTeamId, a.homeTeamId].some((r) => we(t, s, r)?.areaCode === e) : !0;
701
+ function rt(a, e, t, s) {
702
+ return e ? [a.awayTeamId, a.homeTeamId].some((r) => xe(t, s, r)?.areaCode === e) : !0;
656
703
  }
657
- function Je(a, e, t, s) {
658
- const r = (l) => we(t, s, l)?.name || "", o = (l, d) => !l - !d || he(l, d), i = new Map((a || []).map((l) => [l, {
659
- rank: e(l) || $e,
704
+ function ot(a, e, t, s) {
705
+ const r = (l) => xe(t, s, l)?.name || "", o = (l, d) => !l - !d || he(l, d), i = new Map((a || []).map((l) => [l, {
706
+ rank: e(l) || we,
660
707
  away: r(l.awayTeamId),
661
708
  home: r(l.homeTeamId)
662
709
  }]));
@@ -665,30 +712,41 @@ function Je(a, e, t, s) {
665
712
  return m.rank - h.rank || o(m.away, h.away) || o(m.home, h.home) || String(l.time || "").localeCompare(String(d.time || ""));
666
713
  });
667
714
  }
668
- function et(a, e) {
669
- const t = new Map((a || []).map((r) => [r, e(r) || $e])), s = (r) => r.state === "live" ? 0 : 1;
715
+ function nt(a, e) {
716
+ const t = new Map((a || []).map((r) => [r, e(r) || we])), s = (r) => r.state === "live" ? 0 : 1;
670
717
  return [...t.keys()].sort((r, o) => s(r) - s(o) || t.get(r) - t.get(o));
671
718
  }
672
- function tt(a, e) {
673
- return a.gameType === "conference" && a.conferenceId ? e[a.conferenceId]?.name || "Conference" : a.gameType === "playoff" ? "Playoffs" : a.gameType === "scrimmage" ? "Scrimmages" : "Nonconference";
719
+ function it(a, e) {
720
+ if (a.gameType === "conference" && a.conferenceId) {
721
+ const t = e[a.conferenceId] || null;
722
+ return { name: t?.name || "Conference", conference: t };
723
+ }
724
+ return a.gameType === "playoff" ? { name: "Playoffs", conference: null } : a.gameType === "scrimmage" ? { name: "Scrimmages", conference: null } : { name: "Nonconference", conference: null };
674
725
  }
675
- function st(a, e) {
726
+ function lt(a, e) {
676
727
  const t = /* @__PURE__ */ new Map();
677
728
  return (a || []).forEach((s) => {
678
- const r = tt(s, e);
679
- t.has(r) || t.set(r, []), t.get(r).push(s);
680
- }), t;
729
+ const { name: r, conference: o } = it(s, e);
730
+ t.has(r) || t.set(r, { name: r, conference: o, games: [] }), t.get(r).games.push(s);
731
+ }), [...t.values()];
681
732
  }
682
- const at = $`
733
+ const ct = $`
683
734
  .toolbar.filters { gap: 0.5rem 1.1rem; }
684
735
  .filters [role="group"] { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; }
685
736
  .filters .asof { margin-right: 0.1rem; }
686
737
  /* A phone can't fit the label and six chips on one line; the label takes
687
738
  its own row so the chips stay together instead of stranding the last. */
688
739
  @media (max-width: 480px) { .filters .asof { flex-basis: 100%; } }
740
+ /* Conference headings carry the standings cards' classification pills. */
741
+ .section-title .pill { margin-left: 0.3rem; vertical-align: 0.1em; }
742
+ /* The desk's coverage links ride in one group with the box-score link, in
743
+ its style, so a narrow row wraps them together instead of leaving a
744
+ lone "Story" beside the matchup and "Box score" on the next line. */
745
+ .gamelist .links { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 0.2rem 0.6rem; }
746
+ .gamelist .links a { font-size: 0.78rem; }
689
747
  `;
690
- class rt extends w {
691
- static styles = [...A, at];
748
+ class dt extends w {
749
+ static styles = [...A, ct];
692
750
  static properties = {
693
751
  ...w.properties,
694
752
  sport: { type: String },
@@ -724,8 +782,8 @@ class rt extends w {
724
782
  }
725
783
  get ctx() {
726
784
  return (!this._ctx || this._ctxData !== this.data) && (this._ctx = {
727
- teamsById: b(this.data.teams),
728
- schoolsById: b(this.data.schools),
785
+ teamsById: y(this.data.teams),
786
+ schoolsById: y(this.data.schools),
729
787
  records: R(this.data.games),
730
788
  rankings: this.data.rankings,
731
789
  hrefs: z(this),
@@ -737,15 +795,19 @@ class rt extends w {
737
795
  e !== null && (this.view = e), t !== null && (this.areaCode = t);
738
796
  try {
739
797
  const s = new URL(globalThis.location.href), r = (o, i, l) => i && i !== l ? s.searchParams.set(o, i) : s.searchParams.delete(o);
740
- r("view", oe(this.view), ye), r("area", this.areaCode, ""), globalThis.history?.replaceState(null, "", s);
798
+ r("view", oe(this.view), $e), r("area", this.areaCode, ""), globalThis.history?.replaceState(null, "", s);
741
799
  } catch {
742
800
  }
743
801
  }
744
802
  renderView() {
745
- const e = this.ctx, t = b(this.data.conferences), s = [...new Set(this.data.games.map((c) => c.date).filter(Boolean))].sort(), r = oe(this.view), o = Ze(this.data.teams, e.schoolsById), i = o.includes(this.areaCode) ? this.areaCode : "", l = (c) => {
746
- const f = [c.awayTeamId, c.homeTeamId].map((u) => Q(e.rankings, e.teamsById, u, this.sport, c.date)).filter(Boolean);
803
+ const e = this.ctx, t = y(this.data.conferences), s = [...new Set(this.data.games.map((c) => c.date).filter(Boolean))].sort(), r = oe(this.view), o = at(this.data.teams, e.schoolsById), i = o.includes(this.areaCode) ? this.areaCode : "", l = (c) => {
804
+ const f = [c.awayTeamId, c.homeTeamId].map((u) => Z(e.rankings, e.teamsById, u, this.sport, c.date)).filter(Boolean);
747
805
  return f.length ? Math.min(...f) : null;
748
- }, d = this.data.games.filter((c) => c.date === this.date), m = d.filter((c) => Xe(c, i, e.teamsById, e.schoolsById)), h = r === "conferences" ? st(et(m, l), t) : new Map(m.length ? [[i ? `All games · ${i}` : "All games", Je(m, l, e.teamsById, e.schoolsById)]] : []);
806
+ }, d = this.data.games.filter((c) => c.date === this.date), m = d.filter((c) => rt(c, i, e.teamsById, e.schoolsById)), h = r === "conferences" ? lt(nt(m, l), t) : m.length ? [{
807
+ name: i ? `All games · ${i}` : "All games",
808
+ conference: null,
809
+ games: ot(m, l, e.teamsById, e.schoolsById)
810
+ }] : [];
749
811
  return n`
750
812
  ${j(this, e, {
751
813
  title: n`${k(this.sport)} scores &amp; schedules`,
@@ -760,7 +822,7 @@ class rt extends w {
760
822
  this.date = c.target.value;
761
823
  }}>
762
824
  ${(s.includes(this.date) ? s : [...s, this.date].sort()).map((c) => n`<option value=${c} ?selected=${c === this.date}>
763
- ${x(c, { weekday: "short", month: "short", day: "numeric" })}${c === V() ? " · today" : ""}
825
+ ${x(c, { weekday: "short", month: "short", day: "numeric" })}${c === Y() ? " · today" : ""}
764
826
  </option>`)}
765
827
  </select>
766
828
  <button class="chip" ?disabled=${s.indexOf(this.date) <= 0}
@@ -792,10 +854,10 @@ class rt extends w {
792
854
  ${d.length ? p : n`<p class="empty">No ${this.sport} games on this date.</p>`}
793
855
  ${d.length && !m.length ? n`<p class="empty">No ${this.sport} games in the ${i} area code on this date.
794
856
  <button class="chip" @click=${() => this.pick({ area: "" })}>Every area</button></p>` : p}
795
- ${[...h.entries()].map(([c, f]) => n`
796
- <div class="section-title">${c}</div>
857
+ ${h.map(({ name: c, conference: f, games: u }) => n`
858
+ <div class="section-title">${c}${[...f?.classifications || []].sort(q).map((v) => n`<span class="pill class">${v}</span>`)}</div>
797
859
  <div class="card"><ul class="gamelist">
798
- ${f.map((u) => this.renderGame(e, u))}
860
+ ${u.map((v) => this.renderGame(e, v))}
799
861
  </ul></div>
800
862
  `)}
801
863
  `)}
@@ -804,6 +866,10 @@ class rt extends w {
804
866
  // Each team's score rides in a block beside its name (reader feedback:
805
867
  // a lone score column on the far right read as detached from the teams).
806
868
  // Scheduled games carry their start time on the status pill alone.
869
+ // The desk's coverage links (Game.coverageUrls, already on the games
870
+ // list, so they cost no request) sit before the box score link, labelled
871
+ // from each URL's shape (lib/search.mjs) rather than the site search the
872
+ // box score's coverage cards query.
807
873
  renderGame(e, t) {
808
874
  const s = t.state === "final" || t.state === "live", r = (i, l, d = p) => n`<span class="side">${O(e, i, t.date)}${s ? n`<span class="score">${l}</span>` : p}${d}</span>`, o = We(t);
809
875
  return n`
@@ -813,13 +879,16 @@ class rt extends w {
813
879
  ${o ? n`<span class="ff">${F(e, o === "home" ? t.homeTeamId : t.awayTeamId)} forfeited</span>` : p}
814
880
  <span class="where">${t.venue || ""}</span>
815
881
  ${t.broadcast ? n`<span class="pill class">${t.broadcast}</span>` : p}
816
- <a class="box" href=${g(e.hrefs.game, { sport: this.sport, id: t.id })}>Box score →</a>
882
+ <span class="links">
883
+ ${tt(t.coverageUrls).map((i) => n`<a href=${i.href}>${i.label}</a>`)}
884
+ <a class="box" href=${g(e.hrefs.game, { sport: this.sport, id: t.id })}>Box score →</a>
885
+ </span>
817
886
  </li>
818
887
  `;
819
888
  }
820
889
  }
821
- globalThis?.customElements && !globalThis.customElements.get("hsot-scores") && globalThis.customElements.define("hsot-scores", rt);
822
- class ot extends w {
890
+ globalThis?.customElements && !globalThis.customElements.get("hsot-scores") && globalThis.customElements.define("hsot-scores", dt);
891
+ class ht extends w {
823
892
  static styles = A;
824
893
  static properties = {
825
894
  ...w.properties,
@@ -840,7 +909,7 @@ class ot extends w {
840
909
  */
841
910
  get viewGender() {
842
911
  if (this.gender) return this.gender;
843
- const e = q(this.data?.teams);
912
+ const e = W(this.data?.teams);
844
913
  return e.length < 2 ? "" : e.includes(this.pickedGender) ? this.pickedGender : e[0];
845
914
  }
846
915
  async fetchData(e) {
@@ -868,8 +937,8 @@ class ot extends w {
868
937
  }
869
938
  get ctx() {
870
939
  return (!this._ctx || this._ctxData !== this.data || this._ctxGender !== this.viewGender) && (this._ctx = {
871
- teamsById: b(this.data.teams),
872
- schoolsById: b(this.data.schools),
940
+ teamsById: y(this.data.teams),
941
+ schoolsById: y(this.data.schools),
873
942
  records: R(this.data.games),
874
943
  rankings: this.data.rankings,
875
944
  hrefs: z(this),
@@ -880,7 +949,7 @@ class ot extends w {
880
949
  }, this._ctxData = this.data, this._ctxGender = this.viewGender), this._ctx;
881
950
  }
882
951
  renderView() {
883
- const e = this.ctx, t = this.viewGender, s = this.gender ? [] : q(this.data.teams), r = ["All", ...[...new Set(this.data.conferences.flatMap((i) => i.classifications || []))].sort(te)].slice(0, 9), o = this.data.conferences.filter((i) => i.active !== !1).filter((i) => this.classFilter === "All" || (i.classifications || []).includes(this.classFilter)).sort(he);
952
+ const e = this.ctx, t = this.viewGender, s = this.gender ? [] : W(this.data.teams), r = ["All", ...[...new Set(this.data.conferences.flatMap((i) => i.classifications || []))].sort(q)].slice(0, 9), o = this.data.conferences.filter((i) => i.active !== !1).filter((i) => this.classFilter === "All" || (i.classifications || []).includes(this.classFilter)).sort(he);
884
953
  return n`
885
954
  ${j(this, e, {
886
955
  title: n`${t ? `${k(t)} ` : ""}${k(this.sport)} standings`,
@@ -912,7 +981,7 @@ class ot extends w {
912
981
  this.query = i.target.value;
913
982
  }}>
914
983
  <span class="spacer"></span>
915
- <span class="asof">Records through ${x(V(), { month: "long", day: "numeric" })} · conference games count toward both records · scrimmages toward neither</span>
984
+ <span class="asof">Records through ${x(Y(), { month: "long", day: "numeric" })} · conference games count toward both records · scrimmages toward neither</span>
916
985
  </div>
917
986
  ${o.map((i) => this.renderConference(e, i))}
918
987
  `)}
@@ -926,7 +995,7 @@ class ot extends w {
926
995
  <div class="card">
927
996
  <div class="card-head">
928
997
  <h2>${t.name}</h2>
929
- ${[...t.classifications || []].sort(te).map((i) => n`<span class="pill class">${i}</span>`)}
998
+ ${[...t.classifications || []].sort(q).map((i) => n`<span class="pill class">${i}</span>`)}
930
999
  <span class="meta">${o.length} teams · membership derives from teams</span>
931
1000
  </div>
932
1001
  <div class="tablewrap"><table class="data">
@@ -945,7 +1014,7 @@ class ot extends w {
945
1014
  renderRow(e, t, s, r) {
946
1015
  const o = e.schoolsById[t.team.schoolId], i = o?.name || t.team.name || "TBD";
947
1016
  if (r && !i.toLowerCase().includes(r)) return p;
948
- const l = t.rec.pf - t.rec.pa, d = K(this.data.games, t.team.id), m = () => {
1017
+ const l = t.rec.pf - t.rec.pa, d = Q(this.data.games, t.team.id), m = () => {
949
1018
  location.href = g(e.hrefs.school, { id: t.team.schoolId });
950
1019
  };
951
1020
  return n`
@@ -954,7 +1023,7 @@ class ot extends w {
954
1023
  }}>
955
1024
  <td class="mut">${s + 1}</td>
956
1025
  <td class="teamcell">
957
- ${C(o)}${Z(e, t.team.id, null)}
1026
+ ${C(o)}${X(e, t.team.id, null)}
958
1027
  <a href=${g(e.hrefs.school, { id: t.team.schoolId })}>${i}</a>
959
1028
  </td>
960
1029
  <td class="num">${I(t.rec, !0)}</td>
@@ -965,14 +1034,14 @@ class ot extends w {
965
1034
  <td class="num">${t.rec.pa}</td>
966
1035
  <td class="num" style="color:${l >= 0 ? "var(--hsot-win)" : "var(--hsot-loss)"}">${l > 0 ? "+" : ""}${l}</td>
967
1036
  <td>${U(t.rec.results) || "·"}</td>
968
- <td>${X(e, t.team.id)}</td>
1037
+ <td>${J(e, t.team.id)}</td>
969
1038
  <td>${be(e, d, t.team.id)}</td>
970
1039
  </tr>
971
1040
  `;
972
1041
  }
973
1042
  }
974
- globalThis?.customElements && !globalThis.customElements.get("hsot-standings") && globalThis.customElements.define("hsot-standings", ot);
975
- const nt = $`
1043
+ globalThis?.customElements && !globalThis.customElements.get("hsot-standings") && globalThis.customElements.define("hsot-standings", ht);
1044
+ const mt = $`
976
1045
  .hero1 {
977
1046
  border-radius: var(--hsot-radius-md); color: var(--hsot-white);
978
1047
  padding: 1.3rem 1.4rem; display: flex; align-items: center; gap: 1.2rem;
@@ -989,8 +1058,8 @@ const nt = $`
989
1058
  .delta.new { background: var(--hsot-straw); color: #6b5900; border-radius: var(--hsot-radius-xs); padding: 0.1rem 0.3rem; font-size: 0.7rem; }
990
1059
  .sparkline { vertical-align: middle; }
991
1060
  `;
992
- class it extends w {
993
- static styles = [...A, nt];
1061
+ class pt extends w {
1062
+ static styles = [...A, mt];
994
1063
  static properties = {
995
1064
  ...w.properties,
996
1065
  sport: { type: String },
@@ -1025,8 +1094,8 @@ class it extends w {
1025
1094
  }
1026
1095
  get ctx() {
1027
1096
  return (!this._ctx || this._ctxData !== this.data) && (this._ctx = {
1028
- teamsById: b(this.data.teams),
1029
- schoolsById: b(this.data.schools),
1097
+ teamsById: y(this.data.teams),
1098
+ schoolsById: y(this.data.schools),
1030
1099
  records: R(this.data.games),
1031
1100
  rankings: this.data.polls,
1032
1101
  hrefs: z(this),
@@ -1037,8 +1106,8 @@ class it extends w {
1037
1106
  const l = t.map((c, f) => {
1038
1107
  const u = (c.teamIds || []).indexOf(e);
1039
1108
  if (u === -1) return null;
1040
- const y = t.length === 1 ? 96 / 2 : f / (t.length - 1) * 90 + 3, v = 3 + u / 24 * 20;
1041
- return { x: y, y: v };
1109
+ const v = t.length === 1 ? 96 / 2 : f / (t.length - 1) * 90 + 3, b = 3 + u / 24 * 20;
1110
+ return { x: v, y: b };
1042
1111
  }), d = [];
1043
1112
  let m = [];
1044
1113
  if (l.forEach((c) => {
@@ -1046,9 +1115,9 @@ class it extends w {
1046
1115
  }), m.length && d.push(m), !d.length) return p;
1047
1116
  const h = l[s];
1048
1117
  return n`<svg class="sparkline" width=${96} height=${26} viewBox="0 0 ${96} ${26}" role="img" aria-label="rank history">
1049
- ${d.map((c) => ee`<polyline fill="none" stroke="var(--hsot-red)" stroke-width="2"
1118
+ ${d.map((c) => te`<polyline fill="none" stroke="var(--hsot-red)" stroke-width="2"
1050
1119
  points=${c.map((f) => `${f.x.toFixed(1)},${f.y.toFixed(1)}`).join(" ")}></polyline>`)}
1051
- ${h ? ee`<circle cx=${h.x.toFixed(1)} cy=${h.y.toFixed(1)} r="3" fill="var(--hsot-black)"></circle>` : p}
1120
+ ${h ? te`<circle cx=${h.x.toFixed(1)} cy=${h.y.toFixed(1)} r="3" fill="var(--hsot-black)"></circle>` : p}
1052
1121
  </svg>`;
1053
1122
  }
1054
1123
  movement(e, t, s) {
@@ -1058,7 +1127,7 @@ class it extends w {
1058
1127
  renderView() {
1059
1128
  const e = this.ctx, t = this.data.polls;
1060
1129
  if (!t.length) return n`<div class="view"><p class="empty">No ${this.sport} polls published yet this season.</p></div>`;
1061
- const s = Math.max(0, t.findIndex((c) => c.effectiveDate === this.pollDate)), r = t[s] || t[0], o = t[s + 1] || null, i = t.slice().reverse(), l = i.indexOf(r), d = b(this.data.conferences), m = (r.teamIds || [])[0], h = m ? T(e, m) : null;
1130
+ const s = Math.max(0, t.findIndex((c) => c.effectiveDate === this.pollDate)), r = t[s] || t[0], o = t[s + 1] || null, i = t.slice().reverse(), l = i.indexOf(r), d = y(this.data.conferences), m = (r.teamIds || [])[0], h = m ? T(e, m) : null;
1062
1131
  return n`
1063
1132
  ${j(this, e, {
1064
1133
  title: n`${k(this.sport)} Top 25`,
@@ -1122,12 +1191,12 @@ class it extends w {
1122
1191
  renderRow(e, t, s, r, o, i, l, d) {
1123
1192
  const m = T(e, l);
1124
1193
  if (!m) return p;
1125
- const h = e.records[l], c = re(e.records, l), f = K(this.data.games, l), u = i[e.teamsById[l]?.conferenceId], y = () => {
1194
+ const h = e.records[l], c = re(e.records, l), f = Q(this.data.games, l), u = i[e.teamsById[l]?.conferenceId], v = () => {
1126
1195
  location.href = g(e.hrefs.school, { id: m.id });
1127
1196
  };
1128
1197
  return n`
1129
- <tr class="rowlink" @click=${(v) => {
1130
- v.target.closest("a") || y();
1198
+ <tr class="rowlink" @click=${(b) => {
1199
+ b.target.closest("a") || v();
1131
1200
  }}>
1132
1201
  <td class="num" style="font-weight:700">${d}</td>
1133
1202
  <td>${this.movement(t, s, l)}</td>
@@ -1144,8 +1213,8 @@ class it extends w {
1144
1213
  `;
1145
1214
  }
1146
1215
  }
1147
- globalThis?.customElements && !globalThis.customElements.get("hsot-rankings") && globalThis.customElements.define("hsot-rankings", it);
1148
- const lt = $`
1216
+ globalThis?.customElements && !globalThis.customElements.get("hsot-rankings") && globalThis.customElements.define("hsot-rankings", pt);
1217
+ const ft = $`
1149
1218
  .schoolhero { color: var(--hsot-white); padding: 1.6rem 1.25rem 1.3rem; }
1150
1219
  .schoolhero .inner { max-width: 1366px; margin: 0 auto; display: flex; gap: 1.2rem; align-items: center; flex-wrap: wrap; }
1151
1220
  .schoolhero .crest {
@@ -1199,8 +1268,8 @@ const lt = $`
1199
1268
  table.data.roster .sub { display: block; font-weight: 400; font-size: 0.78rem; color: var(--hsot-gray-5); }
1200
1269
  }
1201
1270
  `;
1202
- class ct extends w {
1203
- static styles = [...A, lt];
1271
+ class ut extends w {
1272
+ static styles = [...A, ft];
1204
1273
  static properties = {
1205
1274
  ...w.properties,
1206
1275
  schoolId: { type: String, attribute: "school-id" },
@@ -1218,7 +1287,7 @@ class ct extends w {
1218
1287
  t && !this.sport && (this.sport = t), s && !this.gender && (this.gender = s);
1219
1288
  }
1220
1289
  async fetchData(e) {
1221
- const t = this.season || _(), s = await e.getSchool(this.schoolId), o = (await e.listTeams({ schoolId: this.schoolId })).items, i = this.sport || "football", l = o.find((v) => v.id === this.activeTeamId) || o.find((v) => v.sport === i && pe(v, this.gender)) || o.find((v) => v.sport === i) || o[0] || null, [d, m, h, c, f, u, y] = await Promise.all([
1290
+ const t = this.season || _(), s = await e.getSchool(this.schoolId), o = (await e.listTeams({ schoolId: this.schoolId })).items, i = this.sport || "football", l = o.find((b) => b.id === this.activeTeamId) || o.find((b) => b.sport === i && pe(b, this.gender)) || o.find((b) => b.sport === i) || o[0] || null, [d, m, h, c, f, u, v] = await Promise.all([
1222
1291
  l ? e.listGames({ sport: l.sport, season: t }) : Promise.resolve({ items: [] }),
1223
1292
  l ? e.listTeams({ sport: l.sport }) : Promise.resolve({ items: [] }),
1224
1293
  e.listSchools(),
@@ -1239,14 +1308,14 @@ class ct extends w {
1239
1308
  schools: h.items,
1240
1309
  conferences: c.items,
1241
1310
  rankings: f.items,
1242
- roster: u.items.find((v) => v.season === t) || null,
1243
- players: y.items
1311
+ roster: u.items.find((b) => b.season === t) || null,
1312
+ players: v.items
1244
1313
  };
1245
1314
  }
1246
1315
  get ctx() {
1247
1316
  return (!this._ctx || this._ctxData !== this.data) && (this._ctx = {
1248
- teamsById: b(this.data.allTeams.length ? this.data.allTeams : this.data.teams),
1249
- schoolsById: b(this.data.schools),
1317
+ teamsById: y(this.data.allTeams.length ? this.data.allTeams : this.data.teams),
1318
+ schoolsById: y(this.data.schools),
1250
1319
  records: R(this.data.games),
1251
1320
  rankings: this.data.rankings,
1252
1321
  hrefs: z(this),
@@ -1264,11 +1333,11 @@ class ct extends w {
1264
1333
  renderView() {
1265
1334
  const { school: e, teams: t, active: s, season: r } = this.data;
1266
1335
  if (!e) return n`<div class="view"><p class="empty">School not found.</p></div>`;
1267
- const o = this.ctx, i = G(e.colorPrimary || "#030711"), l = (e.adm || [])[0], d = b(this.data.conferences), m = s ? d[s.conferenceId] : null;
1336
+ const o = this.ctx, i = G(e.colorPrimary || "#030711"), l = (e.adm || [])[0], d = y(this.data.conferences), m = s ? d[s.conferenceId] : null;
1268
1337
  return n`
1269
1338
  <div class="schoolhero" style="background:linear-gradient(115deg, ${e.colorPrimary || "#030711"} 0%, ${e.colorPrimary || "#030711"} 55%, var(--hsot-black) 100%);color:${i}">
1270
1339
  <div class="inner">
1271
- ${M(e, 84) ? n`<img class="crest logo" alt="" loading="lazy" src=${M(e, 84)} />` : n`<div class="crest" style="background:${e.colorSecondary || "#7C7C7C"};color:${G(e.colorSecondary || "#7C7C7C")}">${Y(e)}</div>`}
1340
+ ${M(e, 84) ? n`<img class="crest logo" alt="" loading="lazy" src=${M(e, 84)} />` : n`<div class="crest" style="background:${e.colorSecondary || "#7C7C7C"};color:${G(e.colorSecondary || "#7C7C7C")}">${K(e)}</div>`}
1272
1341
  <div style="min-width:260px">
1273
1342
  <h1>${e.name} <span class="mascot">${e.mascot || ""}</span></h1>
1274
1343
  <div class="facts">
@@ -1296,7 +1365,7 @@ class ct extends w {
1296
1365
  `;
1297
1366
  }
1298
1367
  renderTeam(e, t, s, r) {
1299
- const o = e.records[t.id] || { w: 0, l: 0, t: 0, cw: 0, cl: 0, ct: 0, pf: 0, pa: 0, results: [] }, i = o.w + o.l + o.t, l = s ? fe(this.data.allTeams.filter((c) => c.conferenceId === s.id), t.gender) : [], d = s ? ge(l, e.records).findIndex((c) => c.team.id === t.id) + 1 : 0, m = Q(e.rankings, e.teamsById, t.id, t.sport, null), h = this.data.games.filter((c) => c.homeTeamId === t.id || c.awayTeamId === t.id).sort((c, f) => String(c.date).localeCompare(String(f.date)));
1368
+ const o = e.records[t.id] || { w: 0, l: 0, t: 0, cw: 0, cl: 0, ct: 0, pf: 0, pa: 0, results: [] }, i = o.w + o.l + o.t, l = s ? fe(this.data.allTeams.filter((c) => c.conferenceId === s.id), t.gender) : [], d = s ? ge(l, e.records).findIndex((c) => c.team.id === t.id) + 1 : 0, m = Z(e.rankings, e.teamsById, t.id, t.sport, null), h = this.data.games.filter((c) => c.homeTeamId === t.id || c.awayTeamId === t.id).sort((c, f) => String(c.date).localeCompare(String(f.date)));
1300
1369
  return n`
1301
1370
  <div class="tiles">
1302
1371
  <div class="tile"><div class="k">Overall</div><div class="v">${I(o)}</div><div class="s">${i} games played</div></div>
@@ -1305,7 +1374,7 @@ class ct extends w {
1305
1374
  <div class="tile"><div class="k">Points</div><div class="v">${i ? (o.pf / i).toFixed(1) : "0.0"}</div>
1306
1375
  <div class="s">scored per game · ${i ? (o.pa / i).toFixed(1) : "0.0"} allowed</div></div>
1307
1376
  <div class="tile"><div class="k">Streak</div><div class="v">${U(o.results) || "·"}</div>
1308
- <div class="s">last 5: ${X(e, t.id)}</div></div>
1377
+ <div class="s">last 5: ${J(e, t.id)}</div></div>
1309
1378
  <div class="tile"><div class="k">HSOT Top 25</div><div class="v">${m ? `#${m}` : "NR"}</div>
1310
1379
  <div class="s"><a href=${g(e.hrefs.section, { sport: t.sport, view: "rankings" })}>full poll</a></div></div>
1311
1380
  </div>
@@ -1329,7 +1398,7 @@ class ct extends w {
1329
1398
  }
1330
1399
  renderGameRow(e, t, s) {
1331
1400
  const r = s.homeTeamId === t.id, o = r ? s.awayTeamId : s.homeTeamId, i = r ? s.homeScore : s.awayScore, l = r ? s.awayScore : s.homeScore;
1332
- let d = n`<span class="mut">${W(s.time)}</span>`;
1401
+ let d = n`<span class="mut">${V(s.time)}</span>`;
1333
1402
  if (s.state === "final") {
1334
1403
  const h = H(s), c = h === "tie" ? "T" : h === (r ? "home" : "away") ? "W" : "L";
1335
1404
  d = n`<span class=${c}>${c}</span> ${i}-${l}${s.finish === "overtime" ? n` <span class="mut">OT</span>` : p}${s.forfeit && s.forfeit !== "none" ? n` <span class="mut">FF</span>` : p}`;
@@ -1353,7 +1422,7 @@ class ct extends w {
1353
1422
  const s = this.data.roster;
1354
1423
  if (!s)
1355
1424
  return n`<p class="empty">Roster not published for ${t}.</p>`;
1356
- const r = Ke(s, 560), o = this.data.school?.name || "", i = b(this.data.players), l = s.entries.slice().sort((m, h) => (m.number || 0) - (h.number || 0)), d = l.some((m) => i[m.playerId]?.college);
1425
+ const r = Ke(s, 560), o = this.data.school?.name || "", i = y(this.data.players), l = s.entries.slice().sort((m, h) => (m.number || 0) - (h.number || 0)), d = l.some((m) => i[m.playerId]?.college);
1357
1426
  return n`
1358
1427
  ${r ? n`<img class="rosterphoto" src=${r} loading="lazy" decoding="async"
1359
1428
  alt="${o} ${e.name} ${t} team photo" />` : p}
@@ -1379,8 +1448,8 @@ class ct extends w {
1379
1448
  `;
1380
1449
  }
1381
1450
  }
1382
- globalThis?.customElements && !globalThis.customElements.get("hsot-school") && globalThis.customElements.define("hsot-school", ct);
1383
- const xe = {
1451
+ globalThis?.customElements && !globalThis.customElements.get("hsot-school") && globalThis.customElements.define("hsot-school", ut);
1452
+ const ke = {
1384
1453
  football: ["quarters", 4],
1385
1454
  flag_football: ["quarters", 4],
1386
1455
  basketball: ["quarters", 4],
@@ -1391,78 +1460,49 @@ const xe = {
1391
1460
  softball: ["innings", 7],
1392
1461
  volleyball: ["sets", 3]
1393
1462
  };
1394
- function ke(a) {
1395
- return (xe[a] || ["quarters", 4])[0];
1463
+ function Ie(a) {
1464
+ return (ke[a] || ["quarters", 4])[0];
1396
1465
  }
1397
- function J(a) {
1398
- return (xe[a] || ["quarters", 4])[1];
1466
+ function ee(a) {
1467
+ return (ke[a] || ["quarters", 4])[1];
1399
1468
  }
1400
- function dt(a, e) {
1401
- const t = ke(a), s = J(a);
1469
+ function gt(a, e) {
1470
+ const t = Ie(a), s = ee(a);
1402
1471
  if (e <= s || t === "innings" || t === "sets") return String(e);
1403
1472
  const r = e - s;
1404
1473
  return `OT${r > 1 ? r : ""}`;
1405
1474
  }
1406
- function ht(a, e) {
1475
+ function vt(a, e) {
1407
1476
  const t = String(a ?? "").trim();
1408
1477
  let s;
1409
- return (s = /^(\d+)Q$/i.exec(t)) || (s = /^(\d+)H$/i.exec(t)) ? Number(s[1]) : /^half$/i.test(t) ? ke(e) === "halves" ? 1 : 2 : (s = /^(\d*)OT(\d*)$/i.exec(t)) ? J(e) + Number(s[1] || s[2] || 1) : (s = /^[TB](\d+)$/i.exec(t)) || (s = /^(\d+)(?:st|nd|rd|th)\s*set$/i.exec(t)) || (s = /^set\s*(\d+)$/i.exec(t)) ? Number(s[1]) : null;
1478
+ return (s = /^(\d+)Q$/i.exec(t)) || (s = /^(\d+)H$/i.exec(t)) ? Number(s[1]) : /^half$/i.test(t) ? Ie(e) === "halves" ? 1 : 2 : (s = /^(\d*)OT(\d*)$/i.exec(t)) ? ee(e) + Number(s[1] || s[2] || 1) : (s = /^[TB](\d+)$/i.exec(t)) || (s = /^(\d+)(?:st|nd|rd|th)\s*set$/i.exec(t)) || (s = /^set\s*(\d+)$/i.exec(t)) ? Number(s[1]) : null;
1410
1479
  }
1411
1480
  const N = (a) => Number.isInteger(a) && a >= 0 ? a : null;
1412
- function mt(a) {
1481
+ function bt(a) {
1413
1482
  const e = Array.isArray(a?.scoringPlays) ? a.scoringPlays : [];
1414
1483
  if (!e.length) return null;
1415
1484
  const t = a.sport, s = /* @__PURE__ */ new Map();
1416
1485
  for (const c of e) {
1417
- const f = ht(c?.period, t), u = N(c?.homeScore), y = N(c?.awayScore);
1418
- if (!f || u === null || y === null) return null;
1419
- const v = s.get(f) || { home: 0, away: 0 };
1420
- v.home = Math.max(v.home, u), v.away = Math.max(v.away, y), s.set(f, v);
1486
+ const f = vt(c?.period, t), u = N(c?.homeScore), v = N(c?.awayScore);
1487
+ if (!f || u === null || v === null) return null;
1488
+ const b = s.get(f) || { home: 0, away: 0 };
1489
+ b.home = Math.max(b.home, u), b.away = Math.max(b.away, v), s.set(f, b);
1421
1490
  }
1422
1491
  const r = Math.max(...s.keys()), o = [];
1423
1492
  let i = !0, l = { home: 0, away: 0 };
1424
1493
  for (let c = 1; c <= r; c += 1) {
1425
- const f = s.get(c) || l, u = f.home - l.home, y = f.away - l.away;
1426
- (u < 0 || y < 0) && (i = !1), o.push({ period: c, home: Math.max(u, 0), away: Math.max(y, 0) }), l = { home: Math.max(f.home, l.home), away: Math.max(f.away, l.away) };
1494
+ const f = s.get(c) || l, u = f.home - l.home, v = f.away - l.away;
1495
+ (u < 0 || v < 0) && (i = !1), o.push({ period: c, home: Math.max(u, 0), away: Math.max(v, 0) }), l = { home: Math.max(f.home, l.home), away: Math.max(f.away, l.away) };
1427
1496
  }
1428
1497
  const d = N(a.homeScore) ?? 0, m = N(a.awayScore) ?? 0, h = i && l.home === d && l.away === m;
1429
1498
  return i = i && l.home <= d && l.away <= m, { periods: o, reconciled: h, consistent: i };
1430
1499
  }
1431
- function pt(a) {
1500
+ function yt(a) {
1432
1501
  if (Array.isArray(a?.periodScores) && a.periodScores.length) return a.periodScores;
1433
- const e = mt(a);
1502
+ const e = bt(a);
1434
1503
  return e ? a.state === "final" ? e.reconciled ? e.periods : null : e.consistent ? e.periods : null : null;
1435
1504
  }
1436
- const ft = "https://api.wral.com/search";
1437
- function ut(a) {
1438
- return a.map((e) => `uri:"${e}"`).join(" OR ");
1439
- }
1440
- function gt(a, e) {
1441
- const t = String(a || ft).replace(/\/+$/, ""), s = new URLSearchParams({ query: ut(e), sort: "score", lang: "en" });
1442
- return `${t}/v1/query?${s}`;
1443
- }
1444
- function Ie(a) {
1445
- try {
1446
- const e = new URL(a);
1447
- if (/(^|\.)smugmug\.com$/i.test(e.hostname)) {
1448
- const t = e.pathname.split("/").filter(Boolean).pop() || "", s = !t || /^[ni]-[A-Za-z0-9]+$/.test(t);
1449
- return {
1450
- uri: a,
1451
- title: s ? a : decodeURIComponent(t).replace(/-/g, " "),
1452
- photos: !0
1453
- };
1454
- }
1455
- } catch {
1456
- }
1457
- return { uri: a, title: a };
1458
- }
1459
- async function vt(a, e, t) {
1460
- const r = await ((...l) => fetch(...l))(gt(a, e));
1461
- if (!r.ok) throw new Error(`search answered ${r.status}`);
1462
- const o = await r.json(), i = new Map((o.items || []).map((l) => [l.uri, l]));
1463
- return e.map((l) => i.get(l) || Ie(l));
1464
- }
1465
- const bt = $`
1505
+ const $t = $`
1466
1506
  .breadcrumbs { font-size: 0.8125rem; margin: 0.9rem 0 0; color: var(--hsot-gray-5); }
1467
1507
  .breadcrumbs a { text-decoration: none; }
1468
1508
  .scorehead { display: grid; grid-template-columns: 1fr auto 1fr; gap: 1rem; align-items: center; padding: 1.4rem 1rem; }
@@ -1518,8 +1558,8 @@ const bt = $`
1518
1558
  .cols { grid-template-columns: 1fr; }
1519
1559
  }
1520
1560
  `;
1521
- class yt extends w {
1522
- static styles = [...A, bt];
1561
+ class wt extends w {
1562
+ static styles = [...A, $t];
1523
1563
  static properties = {
1524
1564
  ...w.properties,
1525
1565
  gameId: { type: String, attribute: "game-id" },
@@ -1549,7 +1589,7 @@ class yt extends w {
1549
1589
  // links (fetchCoverage already degrades per-URL index misses).
1550
1590
  // The embed drops the Coverage grid, so it skips the search
1551
1591
  // round-trip entirely rather than fetching cards it will not render.
1552
- s.length && !this.embed ? vt(this.searchApi, s).catch(() => s.map(Ie)) : Promise.resolve([])
1592
+ s.length && !this.embed ? Je(this.searchApi, s).catch(() => s.map(ye)) : Promise.resolve([])
1553
1593
  ]);
1554
1594
  return {
1555
1595
  game: t,
@@ -1563,8 +1603,8 @@ class yt extends w {
1563
1603
  }
1564
1604
  get ctx() {
1565
1605
  return (!this._ctx || this._ctxData !== this.data) && (this._ctx = {
1566
- teamsById: b(this.data.teams),
1567
- schoolsById: b(this.data.schools),
1606
+ teamsById: y(this.data.teams),
1607
+ schoolsById: y(this.data.schools),
1568
1608
  records: R(this.data.games),
1569
1609
  rankings: this.data.rankings,
1570
1610
  hrefs: z(this),
@@ -1574,7 +1614,7 @@ class yt extends w {
1574
1614
  renderView() {
1575
1615
  const e = this.data.game;
1576
1616
  if (!e) return n`<div class="view"><p class="empty">Game not found.</p></div>`;
1577
- const t = this.ctx, s = b(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, i = H(e), l = (h) => e.state === "final" && i !== h && i !== "tie" ? "opacity:0.45" : "", d = e.conferenceId ? s[e.conferenceId] : null, m = this.data.games.filter((h) => h.id !== e.id && h.state === "final" && h.gameType !== "scrimmage" && (h.homeTeamId === e.homeTeamId && h.awayTeamId === e.awayTeamId || h.homeTeamId === e.awayTeamId && h.awayTeamId === e.homeTeamId));
1617
+ const t = this.ctx, s = y(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, i = H(e), l = (h) => e.state === "final" && i !== h && i !== "tie" ? "opacity:0.45" : "", d = e.conferenceId ? s[e.conferenceId] : null, m = this.data.games.filter((h) => h.id !== e.id && h.state === "final" && h.gameType !== "scrimmage" && (h.homeTeamId === e.homeTeamId && h.awayTeamId === e.awayTeamId || h.homeTeamId === e.awayTeamId && h.awayTeamId === e.homeTeamId));
1578
1618
  return n`
1579
1619
  ${B(this, n`
1580
1620
  ${D(this)}
@@ -1594,7 +1634,7 @@ class yt extends w {
1594
1634
  <span style=${l("home")}>${e.homeScore}</span>
1595
1635
  </div>
1596
1636
  <div class="status">${E(e)}</div>
1597
- <div class="status">${x(e.date, { weekday: "short", month: "short", day: "numeric", year: "numeric" })}${e.state === "scheduled" && e.time ? n` · ${W(e.time)}` : p} · ${e.venue || "Venue TBD"}
1637
+ <div class="status">${x(e.date, { weekday: "short", month: "short", day: "numeric", year: "numeric" })}${e.state === "scheduled" && e.time ? n` · ${V(e.time)}` : p} · ${e.venue || "Venue TBD"}
1598
1638
  ${e.broadcast ? n` · <span class="pill class">${e.broadcast}</span>` : p}</div>
1599
1639
  <div class="status">
1600
1640
  <span class="pill type">${e.gameType === "conference" ? `${d?.name || "Conference"} game` : e.gameType}</span>
@@ -1653,19 +1693,19 @@ class yt extends w {
1653
1693
  const i = e.teamsById[s], l = e.records[s], d = M(r, 58);
1654
1694
  return n`
1655
1695
  <div class="teamblock ${o ? "right" : ""}">
1656
- ${d ? n`<img class="crest logo" alt="" loading="lazy" src=${d} />` : n`<span class="crest" style="background:${r.colorPrimary || "#030711"};color:${G(r.colorPrimary || "#030711")}">${Y(r)}</span>`}
1696
+ ${d ? n`<img class="crest logo" alt="" loading="lazy" src=${d} />` : n`<span class="crest" style="background:${r.colorPrimary || "#030711"};color:${G(r.colorPrimary || "#030711")}">${K(r)}</span>`}
1657
1697
  <div>
1658
- <div class="tname">${Z(e, s, t.date)}<a href=${g(e.hrefs.school, { id: r.id })}>${r.name}</a></div>
1698
+ <div class="tname">${X(e, s, t.date)}<a href=${g(e.hrefs.school, { id: r.id })}>${r.name}</a></div>
1659
1699
  <div class="trec">${r.mascot || ""} · ${I(l)}${i?.conferenceId ? n` · ${I(l, !0)} conf` : p}</div>
1660
1700
  </div>
1661
1701
  </div>
1662
1702
  `;
1663
1703
  }
1664
1704
  renderLineScore(e, t, s) {
1665
- const r = pt(e);
1705
+ const r = yt(e);
1666
1706
  if (!r)
1667
1707
  return e.state === "scheduled" ? n`<p class="empty" style="text-align:center">Period scoring will appear once the game starts.</p>` : p;
1668
- const o = Math.max(J(e.sport), ...r.map((m) => m.period)), i = (m) => dt(e.sport, m), l = (m, h) => {
1708
+ const o = Math.max(ee(e.sport), ...r.map((m) => m.period)), i = (m) => gt(e.sport, m), l = (m, h) => {
1669
1709
  const c = r.find((f) => f.period === h);
1670
1710
  return c ? c[m] : e.state === "final" ? 0 : "·";
1671
1711
  }, d = (m, h, c) => n`
@@ -1714,12 +1754,12 @@ class yt extends w {
1714
1754
  }
1715
1755
  renderContext(e, t, s) {
1716
1756
  if (!s) return p;
1717
- const r = e.records[t], o = K(this.data.games, t);
1757
+ const r = e.records[t], o = Q(this.data.games, t);
1718
1758
  return n`
1719
1759
  <div class="card ctxcard">
1720
1760
  <div class="who">${C(s)}${s.name}</div>
1721
1761
  <div class="row">
1722
- <span>Last 5: ${X(e, t)}</span>
1762
+ <span>Last 5: ${J(e, t)}</span>
1723
1763
  <span>Streak: <b>${r ? U(r.results) : "·"}</b></span>
1724
1764
  <span>PF/PA: <b>${r ? `${r.pf} / ${r.pa}` : "·"}</b></span>
1725
1765
  <span>Next: ${o ? n`${x(o.date, { month: "numeric", day: "numeric" })}
@@ -1729,9 +1769,9 @@ class yt extends w {
1729
1769
  `;
1730
1770
  }
1731
1771
  }
1732
- globalThis?.customElements && !globalThis.customElements.get("hsot-boxscore") && globalThis.customElements.define("hsot-boxscore", yt);
1733
- const $t = 250, wt = 2;
1734
- class xt extends ce {
1772
+ globalThis?.customElements && !globalThis.customElements.get("hsot-boxscore") && globalThis.customElements.define("hsot-boxscore", wt);
1773
+ const xt = 250, kt = 2;
1774
+ class It extends ce {
1735
1775
  static properties = {
1736
1776
  api: { type: String },
1737
1777
  schoolHref: { type: String, attribute: "school-href" },
@@ -1811,11 +1851,11 @@ class xt extends ce {
1811
1851
  }
1812
1852
  onInput(e) {
1813
1853
  const t = e.target.value.trim();
1814
- if (clearTimeout(this.debounceTimer), t.length < wt) {
1854
+ if (clearTimeout(this.debounceTimer), t.length < kt) {
1815
1855
  this.abortController?.abort(), this.results = [], this.open = !1, this.searched = !1;
1816
1856
  return;
1817
1857
  }
1818
- this.debounceTimer = setTimeout(() => this.search(t), $t);
1858
+ this.debounceTimer = setTimeout(() => this.search(t), xt);
1819
1859
  }
1820
1860
  async search(e) {
1821
1861
  this.abortController?.abort(), this.abortController = new AbortController();
@@ -1908,7 +1948,7 @@ class xt extends ce {
1908
1948
  `;
1909
1949
  }
1910
1950
  }
1911
- globalThis?.customElements && !globalThis.customElements.get("hsot-school-search") && globalThis.customElements.define("hsot-school-search", xt);
1951
+ globalThis?.customElements && !globalThis.customElements.get("hsot-school-search") && globalThis.customElements.define("hsot-school-search", It);
1912
1952
  function Se(a, e) {
1913
1953
  const t = new Map(a.map((d) => [d.id, d])), s = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map();
1914
1954
  for (const d of e || [])
@@ -1928,17 +1968,17 @@ function Te(a, e = [], t = 0) {
1928
1968
  for (const s of a.children || []) Te(s, e, t + 1);
1929
1969
  return e;
1930
1970
  }
1931
- const kt = (a) => Math.max(1, Math.round(Math.log2(a || 2)));
1932
- function It({ round: a, perGroup: e, groupCount: t = 1 }) {
1933
- const s = kt(e), o = (t === 4 ? s + 2 : t === 2 ? s + 1 : s) - a;
1971
+ const St = (a) => Math.max(1, Math.round(Math.log2(a || 2)));
1972
+ function Tt({ round: a, perGroup: e, groupCount: t = 1 }) {
1973
+ const s = St(e), o = (t === 4 ? s + 2 : t === 2 ? s + 1 : s) - a;
1934
1974
  return o === 0 ? t > 1 ? "Championship" : "Final" : o === 1 ? "Semifinal" : `Round ${a}`;
1935
1975
  }
1936
- function St(a) {
1976
+ function Ct(a) {
1937
1977
  if (!a || !a.length) return "setup";
1938
1978
  const e = Math.max(...a.map((s) => s.round ?? 0)), t = a.filter((s) => (s.round ?? 0) === e);
1939
1979
  return t.length && t.every((s) => s.state === "final") ? "complete" : a.some((s) => s.state !== "scheduled" || s.homeScore || s.awayScore || s.round === 1 && (s.homeTeamId || s.awayTeamId)) ? "active" : "setup";
1940
1980
  }
1941
- function Tt(a, e) {
1981
+ function Bt(a, e) {
1942
1982
  const t = a?.groupNames || [];
1943
1983
  if (t.length >= 2) {
1944
1984
  const r = t.map((o) => ({ key: o, name: o }));
@@ -1947,11 +1987,11 @@ function Tt(a, e) {
1947
1987
  const s = [...new Set((e || []).map((r) => r.bracketGroup).filter(Boolean))];
1948
1988
  return [{ key: null, name: s.length === 1 ? s[0] : "Bracket" }];
1949
1989
  }
1950
- const Ct = (a, e) => e?.key == null ? [...a || []] : (a || []).filter((t) => t.bracketGroup === e.key), ne = (a) => {
1990
+ const Dt = (a, e) => e?.key == null ? [...a || []] : (a || []).filter((t) => t.bracketGroup === e.key), ne = (a) => {
1951
1991
  const e = /(\d+)\s*$/.exec(a.label || "");
1952
1992
  return e ? Number(e[1]) : 1 / 0;
1953
1993
  }, ie = (a, e) => ne(a) - ne(e) || String(a.id).localeCompare(String(e.id));
1954
- function Bt(a, e) {
1994
+ function Ft(a, e) {
1955
1995
  if (a.every((r) => Number.isInteger(r.round))) return (r) => r.round;
1956
1996
  const t = Se(a, e), s = /* @__PURE__ */ new Map();
1957
1997
  for (const r of Array.isArray(t) ? t : [t]) {
@@ -1960,10 +2000,10 @@ function Bt(a, e) {
1960
2000
  }
1961
2001
  return (r) => Number.isInteger(r.round) ? r.round : s.get(r.id) || 1;
1962
2002
  }
1963
- function Dt(a, e, t) {
1964
- const s = Ct(a, t);
2003
+ function zt(a, e, t) {
2004
+ const s = Dt(a, t);
1965
2005
  if (!s.length) return [];
1966
- const r = Bt(a || [], e || []), o = /* @__PURE__ */ new Map();
2006
+ const r = Ft(a || [], e || []), o = /* @__PURE__ */ new Map();
1967
2007
  for (const m of s) {
1968
2008
  const h = r(m);
1969
2009
  o.has(h) || o.set(h, []), o.get(h).push(m);
@@ -1977,7 +2017,7 @@ function Dt(a, e, t) {
1977
2017
  let h = [...o.get(m)];
1978
2018
  if (d) {
1979
2019
  const c = (f) => {
1980
- const u = (i.get(f.id) || []).map((y) => d.get(y)).filter((y) => y !== void 0);
2020
+ const u = (i.get(f.id) || []).map((v) => d.get(v)).filter((v) => v !== void 0);
1981
2021
  return u.length ? Math.min(...u) : 1 / 0;
1982
2022
  };
1983
2023
  h.sort((f, u) => c(f) - c(u) || ie(f, u));
@@ -1987,7 +2027,7 @@ function Dt(a, e, t) {
1987
2027
  }
1988
2028
  return l;
1989
2029
  }
1990
- function Ft(a, e, t) {
2030
+ function At(a, e, t) {
1991
2031
  const s = a[`${e}TeamId`] || null, r = (t || []).find((i) => i.gameId === a.id && i.slot === e), o = a[`${e}Seed`] ?? r?.seed ?? null;
1992
2032
  return { teamId: s, seed: o, bye: !s && !!r?.isBye };
1993
2033
  }
@@ -1995,14 +2035,14 @@ function Ce(a) {
1995
2035
  const e = H(a);
1996
2036
  return e === "home" || e === "away" ? e : null;
1997
2037
  }
1998
- function zt(a, e) {
2038
+ function Pt(a, e) {
1999
2039
  const t = Se(a || [], e || []);
2000
2040
  if (!t || Array.isArray(t)) return null;
2001
2041
  const s = Ce(t.game);
2002
2042
  return s && t.game[`${s}TeamId`] || null;
2003
2043
  }
2004
2044
  const le = { active: 0, setup: 1, complete: 2 };
2005
- function At(a, { id: e, param: t } = {}) {
2045
+ function Et(a, { id: e, param: t } = {}) {
2006
2046
  const s = a || [];
2007
2047
  if (!s.length) return null;
2008
2048
  for (const r of [e, t]) {
@@ -2012,7 +2052,7 @@ function At(a, { id: e, param: t } = {}) {
2012
2052
  }
2013
2053
  return [...s].sort((r, o) => (le[r.status] ?? 3) - (le[o.status] ?? 3) || String(r.name || "").localeCompare(String(o.name || "")))[0];
2014
2054
  }
2015
- const Pt = $`
2055
+ const _t = $`
2016
2056
  .bracket { display: flex; gap: 1rem; align-items: stretch; overflow-x: auto; padding-bottom: 0.5rem; }
2017
2057
  .round { flex: 0 0 250px; display: flex; flex-direction: column; min-width: 0; }
2018
2058
  .roundhead {
@@ -2058,8 +2098,8 @@ const Pt = $`
2058
2098
  .champ .tname a { color: inherit; text-decoration: none; font-weight: 700; }
2059
2099
  @media (max-width: 720px) { .round { flex-basis: 215px; } }
2060
2100
  `;
2061
- class Et extends w {
2062
- static styles = [A, Pt];
2101
+ class Rt extends w {
2102
+ static styles = [A, _t];
2063
2103
  static properties = {
2064
2104
  ...w.properties,
2065
2105
  sport: { type: String },
@@ -2072,7 +2112,7 @@ class Et extends w {
2072
2112
  super(), this.sport = "football", this.season = "", this.tournamentId = "", this.picked = "", this.group = null;
2073
2113
  }
2074
2114
  async fetchData(e) {
2075
- const t = this.season || _(), s = (await e.listTournaments({ sport: this.sport, season: t })).items, r = new URLSearchParams(globalThis.location?.search || "").get("tournament"), o = At(s, { id: this.picked || this.tournamentId, param: r });
2115
+ const t = this.season || _(), s = (await e.listTournaments({ sport: this.sport, season: t })).items, r = new URLSearchParams(globalThis.location?.search || "").get("tournament"), o = Et(s, { id: this.picked || this.tournamentId, param: r });
2076
2116
  if (!o) return { season: t, tournaments: s, tournament: null };
2077
2117
  const [i, l, d, m, h] = await Promise.all([
2078
2118
  e.listSeedings(o.id),
@@ -2094,8 +2134,8 @@ class Et extends w {
2094
2134
  }
2095
2135
  get ctx() {
2096
2136
  return (!this._ctx || this._ctxData !== this.data) && (this._ctx = {
2097
- teamsById: b(this.data.teams),
2098
- schoolsById: b(this.data.schools),
2137
+ teamsById: y(this.data.teams),
2138
+ schoolsById: y(this.data.schools),
2099
2139
  records: {},
2100
2140
  rankings: [],
2101
2141
  hrefs: z(this),
@@ -2125,7 +2165,7 @@ class Et extends w {
2125
2165
  ${D(this)}
2126
2166
  <div class="card"><div class="empty">No ${this.sport} brackets have been published for the ${e.season} season yet.</div></div>
2127
2167
  `)}`;
2128
- const r = Tt(e.tournament, e.games), o = r.find((c) => c.key === this.group) || r[0], i = (e.tournament.groupNames || []).length >= 2 ? e.tournament.groupNames.length : 1, l = (Number(e.tournament.size) || 0) / i, d = Dt(e.games, e.edges, o), m = St(e.games), h = zt(e.games, e.edges);
2168
+ const r = Bt(e.tournament, e.games), o = r.find((c) => c.key === this.group) || r[0], i = (e.tournament.groupNames || []).length >= 2 ? e.tournament.groupNames.length : 1, l = (Number(e.tournament.size) || 0) / i, d = zt(e.games, e.edges, o), m = Ct(e.games), h = Pt(e.games, e.edges);
2129
2169
  return n`
2130
2170
  ${s}
2131
2171
  ${B(this, n`
@@ -2154,7 +2194,7 @@ class Et extends w {
2154
2194
  <div class="bracket" role="region" aria-label="${o.name} bracket">
2155
2195
  ${d.map((c) => n`
2156
2196
  <section class="round">
2157
- <h3 class="roundhead">${It({ round: c.round, perGroup: l, groupCount: i })}</h3>
2197
+ <h3 class="roundhead">${Tt({ round: c.round, perGroup: l, groupCount: i })}</h3>
2158
2198
  <div class="games">${c.games.map((f) => this.renderMatchup(t, f))}</div>
2159
2199
  </section>`)}
2160
2200
  </div>` : n`<div class="card"><div class="empty">This bracket has no games yet.</div></div>`}
@@ -2177,7 +2217,7 @@ class Et extends w {
2177
2217
  `;
2178
2218
  }
2179
2219
  renderSlot(e, t, s) {
2180
- const { teamId: r, seed: o, bye: i } = Ft(t, s, this.data.seedings), l = Ce(t), d = t.state === "live" || t.state === "final";
2220
+ const { teamId: r, seed: o, bye: i } = At(t, s, this.data.seedings), l = Ce(t), d = t.state === "live" || t.state === "final";
2181
2221
  return n`
2182
2222
  <div class="slot ${l ? l === s ? "winner" : "loser" : ""}">
2183
2223
  <span class="seed">${o ?? ""}</span>
@@ -2187,30 +2227,30 @@ class Et extends w {
2187
2227
  `;
2188
2228
  }
2189
2229
  }
2190
- globalThis?.customElements && !globalThis.customElements.get("hsot-brackets") && globalThis.customElements.define("hsot-brackets", Et);
2230
+ globalThis?.customElements && !globalThis.customElements.get("hsot-brackets") && globalThis.customElements.define("hsot-brackets", Rt);
2191
2231
  export {
2192
2232
  P as D,
2193
- yt as H,
2194
- Et as a,
2195
- it as b,
2196
- ct as c,
2197
- xt as d,
2198
- rt as e,
2199
- ot as f,
2200
- Tt as g,
2233
+ wt as H,
2234
+ Rt as a,
2235
+ pt as b,
2236
+ ut as c,
2237
+ It as d,
2238
+ dt as e,
2239
+ ht as f,
2240
+ Bt as g,
2201
2241
  Se as h,
2202
- zt as i,
2242
+ Pt as i,
2203
2243
  R as j,
2204
- St as k,
2244
+ Ct as k,
2205
2245
  g as l,
2206
2246
  H as m,
2207
- Nt as n,
2208
- It as o,
2247
+ Mt as n,
2248
+ Tt as o,
2209
2249
  Ve as p,
2210
- Dt as q,
2250
+ zt as q,
2211
2251
  I as r,
2212
2252
  ge as s,
2213
2253
  U as t,
2214
- Q as u,
2254
+ Z as u,
2215
2255
  Te as v
2216
2256
  };