@aparte/plugin-cards 0.0.0-stage → 0.29.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.
Files changed (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +148 -2
  3. package/dist/carousel-CPy-0JGN.js +63 -0
  4. package/dist/carousel-CPy-0JGN.js.map +1 -0
  5. package/dist/controls-BVX2u7sK.js +62 -0
  6. package/dist/controls-BVX2u7sK.js.map +1 -0
  7. package/dist/format-CchcJRum.js +720 -0
  8. package/dist/format-CchcJRum.js.map +1 -0
  9. package/dist/index.d.ts +28 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +35 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/items/icons.d.ts +12 -0
  14. package/dist/items/icons.d.ts.map +1 -0
  15. package/dist/items/index.d.ts +100 -0
  16. package/dist/items/index.d.ts.map +1 -0
  17. package/dist/items.js +698 -0
  18. package/dist/items.js.map +1 -0
  19. package/dist/kit/carousel.d.ts +17 -0
  20. package/dist/kit/carousel.d.ts.map +1 -0
  21. package/dist/kit/controls.d.ts +51 -0
  22. package/dist/kit/controls.d.ts.map +1 -0
  23. package/dist/kit/define.d.ts +194 -0
  24. package/dist/kit/define.d.ts.map +1 -0
  25. package/dist/kit/dom.d.ts +40 -0
  26. package/dist/kit/dom.d.ts.map +1 -0
  27. package/dist/kit/format.d.ts +49 -0
  28. package/dist/kit/format.d.ts.map +1 -0
  29. package/dist/kit/rating.d.ts +19 -0
  30. package/dist/kit/rating.d.ts.map +1 -0
  31. package/dist/kit/sparkline.d.ts +19 -0
  32. package/dist/kit/sparkline.d.ts.map +1 -0
  33. package/dist/kit/strings.d.ts +139 -0
  34. package/dist/kit/strings.d.ts.map +1 -0
  35. package/dist/link/icons.d.ts +16 -0
  36. package/dist/link/icons.d.ts.map +1 -0
  37. package/dist/link/index.d.ts +98 -0
  38. package/dist/link/index.d.ts.map +1 -0
  39. package/dist/link.js +387 -0
  40. package/dist/link.js.map +1 -0
  41. package/dist/media/icons.d.ts +28 -0
  42. package/dist/media/icons.d.ts.map +1 -0
  43. package/dist/media/index.d.ts +107 -0
  44. package/dist/media/index.d.ts.map +1 -0
  45. package/dist/media.js +610 -0
  46. package/dist/media.js.map +1 -0
  47. package/dist/order/icons.d.ts +49 -0
  48. package/dist/order/icons.d.ts.map +1 -0
  49. package/dist/order/index.d.ts +204 -0
  50. package/dist/order/index.d.ts.map +1 -0
  51. package/dist/order.js +1843 -0
  52. package/dist/order.js.map +1 -0
  53. package/dist/place/icons.d.ts +18 -0
  54. package/dist/place/icons.d.ts.map +1 -0
  55. package/dist/place/index.d.ts +207 -0
  56. package/dist/place/index.d.ts.map +1 -0
  57. package/dist/place.js +1456 -0
  58. package/dist/place.js.map +1 -0
  59. package/dist/plan/icons.d.ts +25 -0
  60. package/dist/plan/icons.d.ts.map +1 -0
  61. package/dist/plan/index.d.ts +153 -0
  62. package/dist/plan/index.d.ts.map +1 -0
  63. package/dist/plan.js +1191 -0
  64. package/dist/plan.js.map +1 -0
  65. package/dist/product/icons.d.ts +16 -0
  66. package/dist/product/icons.d.ts.map +1 -0
  67. package/dist/product/index.d.ts +133 -0
  68. package/dist/product/index.d.ts.map +1 -0
  69. package/dist/product.js +1245 -0
  70. package/dist/product.js.map +1 -0
  71. package/dist/rating-B8Mdx_b_.js +35 -0
  72. package/dist/rating-B8Mdx_b_.js.map +1 -0
  73. package/dist/score/icons.d.ts +35 -0
  74. package/dist/score/icons.d.ts.map +1 -0
  75. package/dist/score/index.d.ts +185 -0
  76. package/dist/score/index.d.ts.map +1 -0
  77. package/dist/score.js +1843 -0
  78. package/dist/score.js.map +1 -0
  79. package/dist/sparkline-C-cA9obz.js +56 -0
  80. package/dist/sparkline-C-cA9obz.js.map +1 -0
  81. package/dist/stats/icons.d.ts +19 -0
  82. package/dist/stats/icons.d.ts.map +1 -0
  83. package/dist/stats/index.d.ts +137 -0
  84. package/dist/stats/index.d.ts.map +1 -0
  85. package/dist/stats.js +1085 -0
  86. package/dist/stats.js.map +1 -0
  87. package/dist/stock/chart.d.ts +135 -0
  88. package/dist/stock/chart.d.ts.map +1 -0
  89. package/dist/stock/icons.d.ts +15 -0
  90. package/dist/stock/icons.d.ts.map +1 -0
  91. package/dist/stock/index.d.ts +195 -0
  92. package/dist/stock/index.d.ts.map +1 -0
  93. package/dist/stock.js +1013 -0
  94. package/dist/stock.js.map +1 -0
  95. package/dist/weather/conditions.d.ts +25 -0
  96. package/dist/weather/conditions.d.ts.map +1 -0
  97. package/dist/weather/icons.d.ts +12 -0
  98. package/dist/weather/icons.d.ts.map +1 -0
  99. package/dist/weather/index.d.ts +146 -0
  100. package/dist/weather/index.d.ts.map +1 -0
  101. package/dist/weather.js +1162 -0
  102. package/dist/weather.js.map +1 -0
  103. package/package.json +137 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"score.js","sources":["../src/score/icons.ts","../src/score/score.css?raw","../src/score/index.ts"],"sourcesContent":["/**\n * The score card's glyphs: one per sport, one per match event, and the few the footer\n * wears (the venue, the broadcast, the way to the match page).\n *\n * Drawn on a 24 × 24 grid in `currentColor`, so the sheet colours them through `color`\n * and a theme follows — the cards are the exception, filled, because a yellow card is a\n * filled rectangle and nothing else reads as one. Constants of this package: the only\n * markup the card parses.\n */\n\nconst svg = (body: string) =>\n `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.7\" stroke-linecap=\"round\" stroke-linejoin=\"round\" xmlns=\"http://www.w3.org/2000/svg\">${body}</svg>`; // safe-text: this package's own SVG, built from its glyph constants\n\n/** A football: the centre pentagon and the seams running out of it. */\nconst FOOTBALL = svg('<circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M12 7.6l4.2 3-1.6 4.9H9.4L7.8 10.6z\"/><path d=\"M12 7.6V3.2M16.2 10.6l4.3-1.3M14.6 15.5l2.6 3.7M9.4 15.5l-2.6 3.7M7.8 10.6L3.5 9.3\"/>');\n\nconst BASKETBALL = svg('<circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M3 12h18M12 3v18\"/><path d=\"M5.7 5.6a9 9 0 0 1 0 12.8M18.3 5.6a9 9 0 0 0 0 12.8\"/>');\n\nconst TENNIS = svg('<circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M5.9 5.2c2.5 1.9 3.9 4.2 3.9 6.8s-1.4 4.9-3.9 6.8\"/><path d=\"M18.1 5.2c-2.5 1.9-3.9 4.2-3.9 6.8s1.4 4.9 3.9 6.8\"/>');\n\n/** An oval ball with its seam: rugby. American football has the same ball with laces. */\nconst RUGBY = svg('<ellipse cx=\"12\" cy=\"12\" rx=\"9.6\" ry=\"5.6\" transform=\"rotate(-45 12 12)\"/><path d=\"M7.2 16.8C10 15.6 15.6 10 16.8 7.2\"/>');\n\nconst AMERICAN_FOOTBALL = svg('<ellipse cx=\"12\" cy=\"12\" rx=\"9.6\" ry=\"5.6\" transform=\"rotate(-45 12 12)\"/><path d=\"M9.6 14.4l4.8-4.8M10.4 11.6l2 2M11.6 10.4l2 2\"/>');\n\n/** A stick and its puck. */\nconst HOCKEY = svg('<path d=\"M6.5 3l6.6 14.2a1.4 1.4 0 0 0 1.3.8H20\"/><ellipse cx=\"7.5\" cy=\"18.4\" rx=\"3.2\" ry=\"1.5\"/>');\n\nconst BASEBALL = svg('<circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M7.3 4.3a11 11 0 0 1 0 15.4M16.7 4.3a11 11 0 0 0 0 15.4\"/><path d=\"M8.6 8.2l1.4-.5M9 12h1.5M8.6 15.8l1.4.5M15.4 8.2l-1.4-.5M15 12h-1.5M15.4 15.8l-1.4.5\"/>');\n\n/** A cup: any other sport, and the card's own glyph for its one-line states. */\nexport const TROPHY = svg('<path d=\"M8 4h8v5.2a4 4 0 0 1-8 0z\"/><path d=\"M8 6H5.2a3 3 0 0 0 3 4.2M16 6h2.8a3 3 0 0 1-3 4.2\"/><path d=\"M12 13.2v3.6M8.5 20h7M9.8 16.8h4.4V20H9.8z\"/>');\n\n/** The glyph a match wears beside its competition, by sport. */\nexport const SPORT_GLYPHS = {\n football: FOOTBALL,\n basketball: BASKETBALL,\n tennis: TENNIS,\n rugby: RUGBY,\n hockey: HOCKEY,\n baseball: BASEBALL,\n 'american-football': AMERICAN_FOOTBALL,\n generic: TROPHY,\n} as const;\n\n/** A card held up: the sheet fills it yellow or red. */\nconst CARD = '<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><rect x=\"7\" y=\"3.5\" width=\"10\" height=\"16\" rx=\"1.6\" fill=\"currentColor\" transform=\"rotate(8 12 11.5)\"/></svg>';\n\n/** Two arrows, one going off, one coming on. */\nconst SUB = svg('<path d=\"M7.5 4v13.5M4 14l3.5 3.5L11 14\"/><path d=\"M16.5 20V6.5M13 10l3.5-3.5L20 10\"/>');\n\n/** A goal is the ball; a penalty and an own goal also say their word beside it. */\nexport const EVENT_GLYPHS = {\n goal: FOOTBALL,\n penalty: FOOTBALL,\n 'own-goal': FOOTBALL,\n yellow: CARD,\n red: CARD,\n sub: SUB,\n} as const;\n\nexport const PIN = svg('<path d=\"M12 21s-6.5-5.6-6.5-11a6.5 6.5 0 0 1 13 0c0 5.4-6.5 11-6.5 11z\"/><circle cx=\"12\" cy=\"10\" r=\"2.3\"/>');\n\nexport const TV = svg('<rect x=\"3\" y=\"6.5\" width=\"18\" height=\"12\" rx=\"2\"/><path d=\"M8.5 21h7M9 3l3 3.5L15 3\"/>');\n\nexport const CHEVRON = svg('<path d=\"M9.5 6l6 6-6 6\"/>');\n","export default \"/* =========================================\\n The score card — @aparte/plugin-cards/score\\n =========================================\\n Three variants of one card, chosen by `data-variant` on its root:\\n card the scoreboard: competition over it, the two teams facing each other, the\\n score big between them, the state of play under it, venue and channel below.\\n compact one row per match: the state or the kick-off in a column, the two teams\\n stacked with their scores at the end. Several matches are always rows.\\n detail the card's board, then the score by period (a table) and the events,\\n each on its team's side of a centre line.\\n A team's colour is the tool's, validated as a hex and set as `--aparte-score-team`\\n (its crest), `--aparte-score-home` / `--aparte-score-away` (the band and the glow).\\n Everything else is a theme token or derived from one, so light and dark follow the chat.\\n The winner is told by weight and, on a row, by a mark — never by colour alone; a live\\n match says \\\"Live\\\" in a word beside its red dot.\\n */\\n\\n.aparte-score-card {\\n --aparte-score-pad: var(--aparte-space-6);\\n --aparte-score-live: var(--aparte-error);\\n --aparte-score-live-ink: var(--aparte-error-ink);\\n --aparte-score-neutral: color-mix(in oklab, var(--aparte-text) 9%, var(--aparte-surface-1));\\n --aparte-score-rule: color-mix(in oklab, var(--aparte-border) 80%, transparent);\\n --aparte-score-num-size: calc(2.625rem * var(--aparte-font-scale));\\n --aparte-score-crest-lg: 3.25rem;\\n --aparte-score-crest-sm: 1.375rem;\\n --aparte-score-band-size: 3px;\\n /* A football card's colours are the same in daylight and at night: they are the\\n referee's, not the theme's. Text on a team's colour is black or white, picked by the\\n colour's own luminance — a theme grey would fail on half the clubs. */\\n --aparte-score-yellow: #f4c20d;\\n --aparte-score-red: #dc2626;\\n --aparte-score-ink-light: #ffffff;\\n --aparte-score-ink-dark: #15121a;\\n}\\n\\n/* ── Widths: each variant asks for its own; the bubble's limit caps them all ── */\\n\\n.aparte-score-card[data-variant=\\\"card\\\"] { --aparte-rich-card-max-inline-size: 25rem; }\\n.aparte-score-card[data-variant=\\\"compact\\\"] { --aparte-rich-card-max-inline-size: 24rem; }\\n.aparte-score-card[data-variant=\\\"detail\\\"] { --aparte-rich-card-max-inline-size: 28rem; }\\n.aparte-score-card:has(.aparte-score__board-list) { --aparte-rich-card-max-inline-size: 26rem; }\\n\\n/* ── Visually hidden: said to a reader, not drawn ─────────────────────── */\\n\\n.aparte-score__sr {\\n position: absolute;\\n inline-size: 1px;\\n block-size: 1px;\\n padding: 0;\\n margin: -1px;\\n overflow: hidden;\\n clip: rect(0 0 0 0);\\n white-space: nowrap;\\n border: 0;\\n}\\n\\n/* ── The match, with its band in the two teams' colours ─────────────────── */\\n\\n.aparte-score {\\n /* The board, the table and the events read the match's width, not the window's. */\\n container: aparte-score / inline-size;\\n position: relative;\\n display: flex;\\n flex-direction: column;\\n min-inline-size: 0;\\n}\\n\\n.aparte-score::before {\\n content: \\\"\\\";\\n display: block;\\n block-size: var(--aparte-score-band-size);\\n background: linear-gradient(to right,\\n var(--aparte-score-home, var(--aparte-score-rule)) 0 50%,\\n var(--aparte-score-away, var(--aparte-score-rule)) 50% 100%);\\n}\\n\\n/* The home team is at the start of the line, so its colour is too. */\\n.aparte-score:dir(rtl)::before {\\n background: linear-gradient(to left,\\n var(--aparte-score-home, var(--aparte-score-rule)) 0 50%,\\n var(--aparte-score-away, var(--aparte-score-rule)) 50% 100%);\\n}\\n\\n/* A live match's band is the live red: the state of play, seen from the top of the card. */\\n.aparte-score[data-phase=\\\"live\\\"]::before {\\n background: var(--aparte-score-live);\\n}\\n\\n/* ── The line over the board: sport, competition, round, day ─────────── */\\n\\n.aparte-score__head,\\n.aparte-score__heading {\\n display: flex;\\n align-items: center;\\n gap: var(--aparte-space-3);\\n min-inline-size: 0;\\n padding: var(--aparte-space-5) var(--aparte-score-pad) 0;\\n color: var(--aparte-text-muted);\\n font-size: var(--aparte-font-size-sm);\\n}\\n\\n.aparte-score__sport {\\n --aparte-rich-card-glyph-size: 1rem;\\n color: var(--aparte-text-muted);\\n}\\n\\n.aparte-score__meta {\\n display: flex;\\n flex-wrap: wrap;\\n align-items: baseline;\\n gap: 0 var(--aparte-space-2);\\n min-inline-size: 0;\\n}\\n\\n.aparte-score__competition {\\n color: var(--aparte-text);\\n font-weight: var(--aparte-font-weight-semibold);\\n overflow-wrap: anywhere;\\n}\\n\\n.aparte-score__round { overflow-wrap: anywhere; }\\n.aparte-score__dot { color: color-mix(in oklab, var(--aparte-text-muted) 60%, transparent); }\\n\\n.aparte-score__date {\\n margin-inline-start: auto;\\n white-space: nowrap;\\n font-variant-numeric: tabular-nums;\\n}\\n\\n/* ── The board ───────────────────────────────────────────────────────── */\\n\\n.aparte-score__board {\\n display: grid;\\n grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);\\n align-items: start;\\n gap: var(--aparte-space-4);\\n padding: var(--aparte-space-7) var(--aparte-score-pad) var(--aparte-space-8);\\n /* Each team's side is lit faintly in its colour, the way a broadcast frames a fixture. */\\n background:\\n radial-gradient(60% 90% at 0% 40%, color-mix(in oklab, var(--aparte-score-home, transparent) 11%, transparent), transparent 70%),\\n radial-gradient(60% 90% at 100% 40%, color-mix(in oklab, var(--aparte-score-away, transparent) 11%, transparent), transparent 70%);\\n}\\n\\n.aparte-score__board:dir(rtl) {\\n background:\\n radial-gradient(60% 90% at 100% 40%, color-mix(in oklab, var(--aparte-score-home, transparent) 11%, transparent), transparent 70%),\\n radial-gradient(60% 90% at 0% 40%, color-mix(in oklab, var(--aparte-score-away, transparent) 11%, transparent), transparent 70%);\\n}\\n\\n.aparte-score__team {\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n gap: var(--aparte-space-3);\\n min-inline-size: 0;\\n text-align: center;\\n}\\n\\n.aparte-score__team-name {\\n display: -webkit-box;\\n -webkit-box-orient: vertical;\\n -webkit-line-clamp: 2;\\n overflow: hidden;\\n max-inline-size: 100%;\\n color: var(--aparte-text);\\n font-size: var(--aparte-font-size-base);\\n font-weight: var(--aparte-font-weight-semibold);\\n line-height: 1.25;\\n overflow-wrap: anywhere;\\n}\\n\\n.aparte-score__team[data-lead=\\\"lose\\\"] .aparte-score__team-name { font-weight: var(--aparte-font-weight-medium); }\\n\\n.aparte-score__record {\\n margin-block-start: calc(var(--aparte-space-2) * -1);\\n color: var(--aparte-text-muted);\\n font-size: var(--aparte-font-size-xs);\\n font-variant-numeric: tabular-nums;\\n}\\n\\n/* ── The crest: a logo over a monogram disc ─────────────────────────────── */\\n\\n.aparte-score__crest {\\n position: relative;\\n display: inline-grid;\\n place-items: center;\\n flex: none;\\n inline-size: var(--aparte-score-crest-size);\\n block-size: var(--aparte-score-crest-size);\\n border-radius: var(--aparte-radius-full);\\n background: var(--aparte-score-team, var(--aparte-score-neutral));\\n box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--aparte-text) 10%, transparent);\\n color: var(--aparte-text);\\n overflow: hidden;\\n}\\n\\n.aparte-score__crest--lg {\\n --aparte-score-crest-size: var(--aparte-score-crest-lg);\\n font-size: calc(var(--aparte-score-crest-lg) * 0.3);\\n}\\n\\n.aparte-score__crest--sm {\\n --aparte-score-crest-size: var(--aparte-score-crest-sm);\\n font-size: calc(var(--aparte-score-crest-sm) * 0.36);\\n}\\n\\n.aparte-score__crest[data-ink=\\\"light\\\"] { color: var(--aparte-score-ink-light); }\\n.aparte-score__crest[data-ink=\\\"dark\\\"] { color: var(--aparte-score-ink-dark); }\\n\\n.aparte-score__monogram {\\n font-weight: var(--aparte-font-weight-bold);\\n letter-spacing: -0.02em;\\n line-height: 1;\\n white-space: nowrap;\\n}\\n\\n/* A logo is drawn on the card's own ground: a crest's shape is its own, not a disc's. */\\n.aparte-score__crest[data-logo] {\\n background: transparent;\\n box-shadow: none;\\n border-radius: 0;\\n}\\n\\n.aparte-score__crest[data-logo] .aparte-score__monogram { visibility: hidden; }\\n\\n.aparte-score__logo {\\n position: absolute;\\n inset: 0;\\n inline-size: 100%;\\n block-size: 100%;\\n object-fit: contain;\\n}\\n\\n/* ── The middle: score, kick-off, status ───────────────────────────────── */\\n\\n.aparte-score__centre {\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n gap: var(--aparte-space-3);\\n min-inline-size: 5.5rem;\\n /* The numbers sit level with the crests' middles. */\\n padding-block-start: calc((var(--aparte-score-crest-lg) - var(--aparte-score-num-size)) / 2);\\n}\\n\\n.aparte-score__result {\\n display: flex;\\n align-items: center;\\n gap: var(--aparte-space-3);\\n color: var(--aparte-text);\\n font-size: var(--aparte-score-num-size);\\n font-weight: var(--aparte-font-weight-bold);\\n font-variant-numeric: tabular-nums;\\n letter-spacing: -0.03em;\\n line-height: 1;\\n}\\n\\n/* The loser's number steps back; the winner's keeps its weight. Weight, not colour alone. */\\n.aparte-score__num[data-lead=\\\"lose\\\"] {\\n color: var(--aparte-text-muted);\\n font-weight: var(--aparte-font-weight-medium);\\n}\\n\\n.aparte-score__sep {\\n color: color-mix(in oklab, var(--aparte-text-muted) 70%, transparent);\\n font-weight: var(--aparte-font-weight-normal);\\n}\\n\\n.aparte-score__kickoff {\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n gap: var(--aparte-space-1);\\n font-variant-numeric: tabular-nums;\\n}\\n\\n.aparte-score__kickoff .aparte-score__day {\\n color: var(--aparte-text-muted);\\n font-size: var(--aparte-font-size-xs);\\n font-weight: var(--aparte-font-weight-semibold);\\n letter-spacing: 0.04em;\\n text-transform: uppercase;\\n}\\n\\n.aparte-score__kickoff .aparte-score__hour {\\n color: var(--aparte-text);\\n font-size: var(--aparte-font-size-xl);\\n font-weight: var(--aparte-font-weight-bold);\\n letter-spacing: -0.01em;\\n white-space: nowrap;\\n}\\n\\n/* A kick-off that will not happen is struck through — and the pill under it says why. */\\n.aparte-score[data-phase=\\\"postponed\\\"] .aparte-score__hour,\\n.aparte-score[data-phase=\\\"cancelled\\\"] .aparte-score__hour,\\n.aparte-score__row[data-phase=\\\"postponed\\\"] .aparte-score__hour,\\n.aparte-score__row[data-phase=\\\"cancelled\\\"] .aparte-score__hour {\\n color: var(--aparte-text-muted);\\n text-decoration: line-through;\\n}\\n\\n.aparte-score__pill {\\n display: inline-flex;\\n align-items: center;\\n gap: var(--aparte-space-2);\\n padding: var(--aparte-space-1) var(--aparte-space-4);\\n border-radius: var(--aparte-radius-full);\\n background: var(--aparte-score-neutral);\\n color: var(--aparte-text-muted);\\n font-size: var(--aparte-font-size-xs);\\n font-weight: var(--aparte-font-weight-semibold);\\n line-height: 1.4;\\n white-space: nowrap;\\n}\\n\\n.aparte-score__pill[data-phase=\\\"live\\\"] {\\n background: color-mix(in oklab, var(--aparte-score-live) 14%, transparent);\\n color: var(--aparte-score-live-ink);\\n}\\n\\n.aparte-score__pill[data-phase=\\\"live\\\"] .aparte-score__live-word {\\n letter-spacing: 0.05em;\\n text-transform: uppercase;\\n}\\n\\n.aparte-score__pill[data-phase=\\\"halftime\\\"],\\n.aparte-score__pill[data-phase=\\\"postponed\\\"] {\\n background: color-mix(in oklab, var(--aparte-warning) 16%, transparent);\\n color: var(--aparte-warning-ink);\\n}\\n\\n.aparte-score__pill[data-phase=\\\"cancelled\\\"] {\\n background: color-mix(in oklab, var(--aparte-error) 12%, transparent);\\n color: var(--aparte-error-ink);\\n}\\n\\n.aparte-score__clock {\\n font-variant-numeric: tabular-nums;\\n font-weight: var(--aparte-font-weight-bold);\\n}\\n\\n/* The red dot of a live match, and the ring that leaves it. Still under reduced motion. */\\n.aparte-score__live-dot {\\n position: relative;\\n flex: none;\\n inline-size: 0.45rem;\\n block-size: 0.45rem;\\n border-radius: var(--aparte-radius-full);\\n background: var(--aparte-score-live);\\n}\\n\\n.aparte-score__live-dot::after {\\n content: \\\"\\\";\\n position: absolute;\\n inset: 0;\\n border-radius: inherit;\\n background: var(--aparte-score-live);\\n animation: aparte-score-pulse 1.8s ease-out infinite;\\n}\\n\\n@keyframes aparte-score-pulse {\\n 0% { opacity: 0.6; transform: scale(1); }\\n 70%, 100% { opacity: 0; transform: scale(2.8); }\\n}\\n\\n/* ── The footer: venue, channel, the match's page ──────────────────────── */\\n\\n.aparte-score__foot {\\n display: flex;\\n flex-wrap: wrap;\\n align-items: center;\\n gap: var(--aparte-space-2) var(--aparte-space-5);\\n padding: var(--aparte-space-4) var(--aparte-score-pad);\\n border-block-start: var(--aparte-border-width) solid var(--aparte-score-rule);\\n color: var(--aparte-text-muted);\\n font-size: var(--aparte-font-size-xs);\\n}\\n\\n.aparte-score__facts {\\n display: flex;\\n flex-wrap: wrap;\\n gap: var(--aparte-space-1) var(--aparte-space-5);\\n min-inline-size: 0;\\n}\\n\\n.aparte-score__fact {\\n display: inline-flex;\\n align-items: center;\\n gap: var(--aparte-space-2);\\n min-inline-size: 0;\\n overflow-wrap: anywhere;\\n}\\n\\n.aparte-score__fact-glyph { --aparte-rich-card-glyph-size: 0.95rem; opacity: 0.8; }\\n\\n.aparte-score__more {\\n display: inline-flex;\\n align-items: center;\\n gap: var(--aparte-space-1);\\n margin-inline-start: auto;\\n border-radius: var(--aparte-radius-sm);\\n color: var(--aparte-primary-ink);\\n font-weight: var(--aparte-font-weight-semibold);\\n text-decoration: none;\\n white-space: nowrap;\\n}\\n\\n.aparte-score__more:hover {\\n text-decoration: underline;\\n text-decoration-thickness: 1px;\\n text-underline-offset: 0.18em;\\n}\\n\\n.aparte-score__more:focus-visible {\\n outline: var(--aparte-focus-outline-width) solid var(--aparte-border-focus);\\n outline-offset: var(--aparte-focus-outline-offset);\\n}\\n\\n.aparte-score__chevron {\\n --aparte-rich-card-glyph-size: 0.9rem;\\n transition: translate var(--aparte-duration-base) ease;\\n}\\n\\n.aparte-score__chevron:dir(rtl) { transform: scaleX(-1); }\\n.aparte-score__more:hover .aparte-score__chevron { translate: 2px 0; }\\n.aparte-score__more:hover .aparte-score__chevron:dir(rtl) { translate: -2px 0; }\\n\\n/* ── detail: the score by period ────────────────────────────────────────── */\\n\\n.aparte-score__section {\\n padding: var(--aparte-space-5) var(--aparte-score-pad);\\n border-block-start: var(--aparte-border-width) solid var(--aparte-score-rule);\\n}\\n\\n.aparte-score__table-wrap { overflow-x: auto; }\\n\\n.aparte-score__periods {\\n inline-size: 100%;\\n border-collapse: collapse;\\n font-size: var(--aparte-font-size-sm);\\n font-variant-numeric: tabular-nums;\\n}\\n\\n.aparte-score__periods th,\\n.aparte-score__periods td {\\n padding: var(--aparte-space-2) var(--aparte-space-3);\\n text-align: center;\\n white-space: nowrap;\\n}\\n\\n.aparte-score__periods thead th {\\n padding-block-start: 0;\\n color: var(--aparte-text-muted);\\n font-size: var(--aparte-font-size-xs);\\n font-weight: var(--aparte-font-weight-medium);\\n}\\n\\n.aparte-score__periods tbody tr + tr { border-block-start: var(--aparte-border-width) solid var(--aparte-score-rule); }\\n.aparte-score__periods td { color: var(--aparte-text); }\\n\\n.aparte-score__periods .aparte-score__corner,\\n.aparte-score__row-team {\\n inline-size: 100%;\\n text-align: start;\\n padding-inline-start: 0;\\n}\\n\\n.aparte-score__row-team { font-weight: var(--aparte-font-weight-medium); }\\n\\n.aparte-score__row-label {\\n display: flex;\\n align-items: center;\\n gap: var(--aparte-space-3);\\n min-inline-size: 0;\\n max-inline-size: 10rem;\\n}\\n\\n.aparte-score__row-name {\\n min-inline-size: 0;\\n overflow: hidden;\\n text-overflow: ellipsis;\\n}\\n\\n.aparte-score__periods .aparte-score__total {\\n border-radius: var(--aparte-radius-sm);\\n background: var(--aparte-score-neutral);\\n font-weight: var(--aparte-font-weight-bold);\\n}\\n\\n.aparte-score__periods tbody tr[data-lead=\\\"lose\\\"] td,\\n.aparte-score__periods tbody tr[data-lead=\\\"lose\\\"] .aparte-score__row-team { color: var(--aparte-text-muted); }\\n\\n/* A set won is in bold, as a tennis table writes it. */\\n.aparte-score__periods td[data-lead=\\\"win\\\"] { font-weight: var(--aparte-font-weight-bold); }\\n\\n/* ── detail: the events, each on its team's side ─────────────────────── */\\n\\n.aparte-score__timeline { container: aparte-score-events / inline-size; }\\n\\n.aparte-score__events {\\n --aparte-score-minute-col: 3.25rem;\\n position: relative;\\n display: flex;\\n flex-direction: column;\\n gap: var(--aparte-space-2);\\n margin: 0;\\n padding: 0;\\n list-style: none;\\n}\\n\\n/* The centre line the minutes sit on. */\\n.aparte-score__events::before {\\n content: \\\"\\\";\\n position: absolute;\\n inset-block: var(--aparte-space-2);\\n inset-inline-start: 50%;\\n inline-size: 1px;\\n background: var(--aparte-score-rule);\\n}\\n\\n.aparte-score__event {\\n position: relative;\\n display: grid;\\n grid-template-columns: minmax(0, 1fr) var(--aparte-score-minute-col) minmax(0, 1fr);\\n align-items: center;\\n min-block-size: 1.875rem;\\n font-size: var(--aparte-font-size-sm);\\n}\\n\\n.aparte-score__minute {\\n grid-column: 2;\\n grid-row: 1;\\n justify-self: center;\\n min-inline-size: 2.5rem;\\n padding: 1px var(--aparte-space-2);\\n border-radius: var(--aparte-radius-full);\\n background: var(--aparte-surface-1);\\n box-shadow: inset 0 0 0 1px var(--aparte-score-rule);\\n color: var(--aparte-text-muted);\\n font-size: var(--aparte-font-size-xs);\\n font-weight: var(--aparte-font-weight-semibold);\\n font-variant-numeric: tabular-nums;\\n text-align: center;\\n}\\n\\n.aparte-score__minute:empty { visibility: hidden; }\\n\\n.aparte-score__event-body {\\n grid-row: 1;\\n display: flex;\\n align-items: center;\\n gap: var(--aparte-space-3);\\n min-inline-size: 0;\\n}\\n\\n/* The home team's events lean on the line from the start side, the glyph nearest it. */\\n.aparte-score__event[data-team=\\\"home\\\"] .aparte-score__event-body {\\n grid-column: 1;\\n flex-direction: row-reverse;\\n justify-self: end;\\n text-align: end;\\n}\\n\\n.aparte-score__event[data-team=\\\"away\\\"] .aparte-score__event-body {\\n grid-column: 3;\\n justify-self: start;\\n}\\n\\n.aparte-score__event-text {\\n display: flex;\\n flex-wrap: wrap;\\n align-items: baseline;\\n gap: 0 var(--aparte-space-2);\\n min-inline-size: 0;\\n}\\n\\n.aparte-score__event[data-team=\\\"home\\\"] .aparte-score__event-text { justify-content: flex-end; }\\n\\n.aparte-score__player {\\n color: var(--aparte-text);\\n font-weight: var(--aparte-font-weight-medium);\\n overflow-wrap: anywhere;\\n}\\n\\n.aparte-score__event-detail {\\n color: var(--aparte-text-muted);\\n font-size: var(--aparte-font-size-xs);\\n overflow-wrap: anywhere;\\n}\\n\\n/* The kind is said by the glyph for a goal, a card, a change; a penalty and an own goal\\n look like a goal, so they also write their word. A reader hears it for every kind. */\\n.aparte-score__event-type {\\n position: absolute;\\n inline-size: 1px;\\n block-size: 1px;\\n overflow: hidden;\\n clip: rect(0 0 0 0);\\n white-space: nowrap;\\n}\\n\\n.aparte-score__event[data-type=\\\"penalty\\\"] .aparte-score__event-type,\\n.aparte-score__event[data-type=\\\"own-goal\\\"] .aparte-score__event-type {\\n position: static;\\n inline-size: auto;\\n block-size: auto;\\n overflow: visible;\\n clip: auto;\\n color: var(--aparte-text-muted);\\n font-size: var(--aparte-font-size-xs);\\n}\\n\\n.aparte-score__event-glyph {\\n --aparte-rich-card-glyph-size: 1rem;\\n color: var(--aparte-text);\\n}\\n\\n.aparte-score__event[data-type=\\\"own-goal\\\"] .aparte-score__event-glyph { color: var(--aparte-error-ink); }\\n.aparte-score__event[data-type=\\\"yellow\\\"] .aparte-score__event-glyph { color: var(--aparte-score-yellow); }\\n.aparte-score__event[data-type=\\\"red\\\"] .aparte-score__event-glyph { color: var(--aparte-score-red); }\\n.aparte-score__event[data-type=\\\"sub\\\"] .aparte-score__event-glyph { color: var(--aparte-text-muted); }\\n\\n.aparte-score__event[data-type=\\\"sub\\\"] .aparte-score__player { font-weight: var(--aparte-font-weight-normal); }\\n\\n/* The team's name beside each event, for when the side no longer says it (below). */\\n.aparte-score__event-team {\\n position: absolute;\\n inline-size: 1px;\\n block-size: 1px;\\n overflow: hidden;\\n clip: rect(0 0 0 0);\\n white-space: nowrap;\\n}\\n\\n/* A narrow card: one column, the minute first, the team written beside each event. */\\n@container aparte-score-events (max-width: 22rem) {\\n .aparte-score__events::before { inset-inline-start: calc(var(--aparte-score-minute-col) / 2); }\\n\\n .aparte-score__event { grid-template-columns: var(--aparte-score-minute-col) minmax(0, 1fr); }\\n .aparte-score__minute { grid-column: 1; }\\n\\n .aparte-score__event[data-team] .aparte-score__event-body {\\n grid-column: 2;\\n flex-direction: row;\\n justify-self: stretch;\\n padding-inline-start: var(--aparte-space-3);\\n text-align: start;\\n }\\n\\n .aparte-score__event[data-team=\\\"home\\\"] .aparte-score__event-text { justify-content: flex-start; }\\n\\n .aparte-score__event-team {\\n position: static;\\n inline-size: auto;\\n block-size: auto;\\n overflow: hidden;\\n clip: auto;\\n flex: none;\\n max-inline-size: 6rem;\\n margin-inline-start: auto;\\n padding: 0 var(--aparte-space-3);\\n border-radius: var(--aparte-radius-full);\\n background: var(--aparte-score-team, var(--aparte-score-neutral));\\n color: var(--aparte-text);\\n font-size: var(--aparte-font-size-2xs);\\n font-weight: var(--aparte-font-weight-semibold);\\n line-height: 1.6;\\n text-overflow: ellipsis;\\n }\\n\\n .aparte-score__event-team[data-ink=\\\"light\\\"] { color: var(--aparte-score-ink-light); }\\n .aparte-score__event-team[data-ink=\\\"dark\\\"] { color: var(--aparte-score-ink-dark); }\\n}\\n\\n/* ── compact and several matches: rows ─────────────────────────────────── */\\n\\n.aparte-score__single,\\n.aparte-score__board-list {\\n display: flex;\\n flex-direction: column;\\n min-inline-size: 0;\\n}\\n\\n.aparte-score__heading {\\n padding-block-end: var(--aparte-space-3);\\n color: var(--aparte-text);\\n font-weight: var(--aparte-font-weight-semibold);\\n}\\n\\n.aparte-score__heading-text { min-inline-size: 0; overflow-wrap: anywhere; }\\n\\n.aparte-score__list {\\n margin: 0;\\n padding: 0;\\n list-style: none;\\n}\\n\\n.aparte-score__row {\\n position: relative;\\n display: grid;\\n grid-template-columns: 4.5rem minmax(0, 1fr);\\n align-items: center;\\n gap: 0 var(--aparte-space-5);\\n padding: var(--aparte-space-4) var(--aparte-score-pad);\\n}\\n\\n.aparte-score__list .aparte-score__row + .aparte-score__row,\\n.aparte-score__single .aparte-score__head + .aparte-score__row {\\n border-block-start: var(--aparte-border-width) solid var(--aparte-score-rule);\\n}\\n\\n.aparte-score__single .aparte-score__head { padding-block-end: var(--aparte-space-3); }\\n.aparte-score__single .aparte-score__head + .aparte-score__row { margin-block-start: var(--aparte-space-2); }\\n\\n/* A row's band is a short bar at its start, red while the match is live. */\\n.aparte-score__row[data-phase=\\\"live\\\"]::before {\\n content: \\\"\\\";\\n position: absolute;\\n inset-block: var(--aparte-space-4);\\n inset-inline-start: 0;\\n inline-size: var(--aparte-score-band-size);\\n border-start-end-radius: var(--aparte-radius-full);\\n border-end-end-radius: var(--aparte-radius-full);\\n background: var(--aparte-score-live);\\n}\\n\\n.aparte-score__when {\\n display: flex;\\n flex-direction: column;\\n align-items: center;\\n justify-content: center;\\n gap: var(--aparte-space-1);\\n align-self: stretch;\\n padding-inline-end: var(--aparte-space-4);\\n border-inline-end: var(--aparte-border-width) solid var(--aparte-score-rule);\\n color: var(--aparte-text-muted);\\n font-size: var(--aparte-font-size-xs);\\n font-weight: var(--aparte-font-weight-semibold);\\n font-variant-numeric: tabular-nums;\\n line-height: 1.25;\\n text-align: center;\\n}\\n\\n.aparte-score__when[data-phase=\\\"live\\\"] {\\n flex-direction: row;\\n gap: var(--aparte-space-2);\\n color: var(--aparte-score-live-ink);\\n}\\n\\n.aparte-score__when[data-phase=\\\"live\\\"] .aparte-score__clock { font-size: var(--aparte-font-size-sm); }\\n.aparte-score__when[data-phase=\\\"halftime\\\"],\\n.aparte-score__when[data-phase=\\\"postponed\\\"] { color: var(--aparte-warning-ink); }\\n.aparte-score__when[data-phase=\\\"cancelled\\\"] { color: var(--aparte-error-ink); }\\n\\n.aparte-score__kickoff--row .aparte-score__day { font-weight: var(--aparte-font-weight-medium); }\\n\\n.aparte-score__kickoff--row .aparte-score__hour {\\n color: var(--aparte-text);\\n font-size: var(--aparte-font-size-sm);\\n font-weight: var(--aparte-font-weight-semibold);\\n}\\n\\n.aparte-score__lines {\\n display: flex;\\n flex-direction: column;\\n gap: var(--aparte-space-2);\\n min-inline-size: 0;\\n}\\n\\n.aparte-score__row-meta {\\n color: var(--aparte-text-muted);\\n font-size: var(--aparte-font-size-2xs);\\n font-weight: var(--aparte-font-weight-semibold);\\n letter-spacing: 0.03em;\\n text-transform: uppercase;\\n overflow-wrap: anywhere;\\n}\\n\\n.aparte-score__line {\\n display: grid;\\n grid-template-columns: auto minmax(0, 1fr) auto 0.75rem;\\n align-items: center;\\n gap: var(--aparte-space-3);\\n color: var(--aparte-text);\\n font-size: var(--aparte-font-size-md);\\n}\\n\\n.aparte-score__line-name {\\n min-inline-size: 0;\\n overflow: hidden;\\n text-overflow: ellipsis;\\n white-space: nowrap;\\n}\\n\\n.aparte-score__line-score {\\n grid-column: 3;\\n min-inline-size: 1.5ch;\\n font-size: var(--aparte-font-size-base);\\n font-weight: var(--aparte-font-weight-semibold);\\n font-variant-numeric: tabular-nums;\\n text-align: end;\\n}\\n\\n.aparte-score__win-mark {\\n grid-column: 4;\\n color: var(--aparte-text);\\n font-size: var(--aparte-font-size-2xs);\\n line-height: 1;\\n}\\n\\n.aparte-score__win-mark:dir(rtl) { transform: scaleX(-1); }\\n\\n.aparte-score__line[data-lead=\\\"win\\\"] .aparte-score__line-name,\\n.aparte-score__line[data-lead=\\\"win\\\"] .aparte-score__line-score { font-weight: var(--aparte-font-weight-bold); }\\n\\n.aparte-score__line[data-lead=\\\"lose\\\"] { color: var(--aparte-text-muted); }\\n\\n/* A linked row: the whole row is the link; its ring is drawn inside the card's clipped edge. */\\n.aparte-score__link::after {\\n content: \\\"\\\";\\n position: absolute;\\n inset: 0;\\n}\\n\\n.aparte-score__link:focus-visible { outline: none; }\\n\\n.aparte-score__row[data-linked] { transition: background var(--aparte-duration-fast) ease; }\\n.aparte-score__row[data-linked]:hover { background: var(--aparte-surface-2); }\\n\\n.aparte-score__row:has(.aparte-score__link:focus-visible) {\\n outline: var(--aparte-focus-outline-width) solid var(--aparte-border-focus);\\n outline-offset: calc(var(--aparte-focus-outline-width) * -1);\\n}\\n\\n/* ── Skeleton: the shapes of what is coming ───────────────────────────── */\\n\\n.aparte-score__sk-meta { inline-size: 9rem; }\\n.aparte-score__sk-name { inline-size: 5rem; }\\n.aparte-score__team .aparte-score__sk-name { inline-size: 70%; margin-inline: auto; }\\n.aparte-score__sk-score { inline-size: 5rem; block-size: var(--aparte-score-num-size); border-radius: var(--aparte-radius-md); }\\n.aparte-score__sk-pill { inline-size: 4rem; block-size: 1.25rem; border-radius: var(--aparte-radius-full); }\\n.aparte-score__sk-num { inline-size: 1.25rem; block-size: 1rem; border-radius: var(--aparte-radius-sm); grid-column: 3; }\\n.aparte-score__sk-when { inline-size: 2.5rem; }\\n.aparte-score__sk-lines { display: flex; flex-direction: column; gap: var(--aparte-space-4); }\\n.aparte-score__sk-line:nth-child(even) { inline-size: 70%; }\\n.aparte-score__crest.aparte-skeleton {\\n inline-size: var(--aparte-score-crest-size);\\n block-size: var(--aparte-score-crest-size);\\n box-shadow: none;\\n}\\n\\n/* ── Narrow: a smaller board, still the same board ──────────────────────── */\\n\\n@container aparte-score (max-width: 20rem) {\\n .aparte-score__board { gap: var(--aparte-space-3); padding-inline: var(--aparte-space-4); }\\n .aparte-score__team-name { font-size: var(--aparte-font-size-md); }\\n .aparte-score__centre { min-inline-size: 4.5rem; }\\n}\\n\\n@media (max-width: 380px) {\\n .aparte-score-card {\\n --aparte-score-pad: var(--aparte-space-5);\\n --aparte-score-num-size: calc(2.125rem * var(--aparte-font-scale));\\n --aparte-score-crest-lg: 2.75rem;\\n }\\n\\n .aparte-score__row { grid-template-columns: 3.75rem minmax(0, 1fr); gap: 0 var(--aparte-space-4); }\\n}\\n\\n/* The kit stops every animation and transition under reduced motion; the live dot's ring\\n and the chevron's nudge are named here too, so the rule reads where they are drawn. */\\n@media (prefers-reduced-motion: reduce) {\\n .aparte-score__live-dot::after { animation: none; opacity: 0; }\\n .aparte-score__more:hover .aparte-score__chevron,\\n .aparte-score__more:hover .aparte-score__chevron:dir(rtl) { translate: none; }\\n}\\n\"","/**\n * @aparte/plugin-cards/score — a tool's matches, drawn as a scoreboard: football,\n * basketball, tennis, rugby, hockey, baseball, American football, any other sport.\n *\n * import { setupScoreCard } from '@aparte/plugin-cards/score';\n *\n * setupScoreCard({ tool: 'get_match', map: (result) => result.response });\n *\n * One match, a list of them (a round, a scoreboard), or `{ title, matches: [...] }`. Three\n * variants of one card: `card` (the two teams facing each other, the score big between\n * them, the state of play under it), `compact` (one row per match, the teams stacked with\n * their scores at the end) and `detail` (the card's board, then the score by period and\n * the match's events, each on the side of the team it belongs to).\n *\n * Several matches are always rows, whatever the variant: a scoreboard is read down a\n * column, one glance per match, and a carousel would hide all but one score behind a swipe.\n *\n * Your tool keeps its own fields: `readMatches` reads the usual shapes — API-Football\n * (`fixture`, `teams`, `goals`, the `FT`/`HT`/`1H`/`NS` codes), football-data.org\n * (`homeTeam`, `score.fullTime`, `utcDate`, `goals`/`bookings`), ESPN (`competitions[0]\n * .competitors[]` with `homeAway`, `linescores`, `status.type`), TheSportsDB (`strHomeTeam`,\n * `intHomeScore`) and what a model writes by hand — and `map` says the rest.\n */\nimport type { AparteConfig } from '@aparte/core';\nimport { defineCard, type CardContext, type CardSetupOptions } from '../kit/define.js';\nimport { el, glyph, num, str, webUrl } from '../kit/dom.js';\nimport { formatDay, formatHour, formatNumber, toDate } from '../kit/format.js';\nimport { intlTag, word, type CardWord } from '../kit/strings.js';\nimport { CHEVRON, EVENT_GLYPHS, PIN, SPORT_GLYPHS, TROPHY, TV } from './icons.js';\nimport scoreStyles from './score.css?raw';\n\nexport type ScoreVariant = 'card' | 'compact' | 'detail';\n\n/** Where a match stands. A status a tool writes that is none of these is kept as its text. */\nexport type MatchStatus = 'scheduled' | 'live' | 'halftime' | 'final' | 'postponed' | 'cancelled';\n\n/** The sport, which picks the match's glyph and how its end is said (\"Full time\", \"Final\"). */\nexport type Sport = keyof typeof SPORT_GLYPHS;\n\nexport type MatchSide = 'home' | 'away';\n\nexport type MatchEventType = keyof typeof EVENT_GLYPHS;\n\n/** A team as `map` returns it. Only `name` is needed. */\nexport interface TeamInput {\n name: string;\n /** \"LOSC\", \"LIL\" — the monogram's letters when there is no logo, and the name on a narrow row. */\n shortName?: string;\n /** An `http(s)` image; anything else is ignored and the monogram is drawn. */\n logo?: string;\n score?: number | string;\n /** The team's record, as the sport writes it: \"12-4\", \"W8 D2 L1\". */\n record?: string;\n /** A CSS hex colour the team wears (`#c8102e`, `c8102e`, `#c12`) — anything else is ignored. */\n color?: string;\n}\n\n/** One period of play: a quarter, a half, a set, an inning. */\nexport interface MatchPeriodInput {\n label?: string;\n home?: number | string;\n away?: number | string;\n}\n\nexport interface MatchEventInput {\n /** \"23'\", \"90+2'\", or a number of minutes. */\n minute?: string | number;\n team: MatchSide;\n type: MatchEventType;\n player?: string;\n /** A line beside the player: the assist, the player going off. */\n detail?: string;\n}\n\n/** A match as `map` returns it. Only the two teams' names are needed. */\nexport interface MatchInput {\n home: TeamInput | string;\n away: TeamInput | string;\n /** One of `MatchStatus`, a feed's code (`FT`, `HT`, `1H`, `NS`, `PST`, `IN_PLAY`…), or any text. */\n status?: MatchStatus | string;\n /** The match clock while it is live: \"67'\", \"Q3 4:12\". A number is minutes. */\n clock?: string | number;\n /** The period being played, when the clock does not already say it. */\n period?: string | number;\n /** Kick-off: an ISO string, an epoch, or a Date. */\n startTime?: string | number | Date;\n competition?: string;\n /** Another name for `competition`. */\n league?: string;\n round?: string;\n venue?: string;\n sport?: Sport | string;\n periods?: MatchPeriodInput[];\n events?: MatchEventInput[];\n /** Who won; worked out from a finished match's score when it is not given. */\n winner?: MatchSide;\n /** Where to watch it: \"Canal+\", or several. */\n broadcast?: string | string[];\n /** The match's own page. */\n url?: string;\n}\n\n/** What `map` returns: one match, a scoreboard of them, or a scoreboard with a heading. */\nexport type ScoreInput = MatchInput | MatchInput[] | { title?: string; matches: MatchInput[] };\n\n/** A team as the card draws it, once read. */\nexport interface Team {\n name: string;\n shortName?: string;\n logo?: string;\n score?: number;\n record?: string;\n /** `#rrggbb`, always. */\n color?: string;\n}\n\nexport interface MatchPeriod {\n label: string;\n home?: number;\n away?: number;\n}\n\nexport interface MatchEvent {\n /** As drawn: \"23'\", \"90+2'\". */\n minute?: string;\n team: MatchSide;\n type: MatchEventType;\n player?: string;\n detail?: string;\n}\n\n/** A match as the card draws it, once read. */\nexport interface Match {\n home: Team;\n away: Team;\n /** Absent when the tool said nothing, or something that is none of these (see `statusText`). */\n status?: MatchStatus;\n /** A status the card has no word for, as the tool wrote it: \"Suspended\", \"Abandoned\". */\n statusText?: string;\n clock?: string;\n period?: string;\n startTime?: Date;\n competition?: string;\n round?: string;\n /** A league's matchday, said in the chat's language (\"Matchday 12\", \"12e journée\"). */\n matchday?: number;\n venue?: string;\n sport: Sport;\n periods?: MatchPeriod[];\n events?: MatchEvent[];\n winner?: MatchSide;\n broadcast?: string;\n url?: string;\n}\n\n/** The card's data: one match or several, and the scoreboard's title. */\nexport interface ScoreData {\n title?: string;\n matches: Match[];\n}\n\n/** How an app plugs the score card in: the kit's options, and the clock \"Today\" is read against. */\nexport interface ScoreCardOptions extends CardSetupOptions<ScoreData, ScoreVariant> {\n /** The time \"Today\" and \"Tomorrow\" are worked out from (the device's clock by default). */\n now?: () => Date;\n}\n\nconst S = {\n cardsScoreTitle: { en: 'Match', fr: 'Match', de: 'Spiel', es: 'Partido', it: 'Partita', ja: '試合', ko: '경기', pt: 'Partida', ru: 'Матч', zh: '比赛' },\n cardsScoreCount: { en: '{n} matches', fr: '{n} matchs', de: '{n} Spiele', es: '{n} partidos', it: '{n} partite', ja: '{n}試合', ko: '{n}경기', pt: '{n} partidas', ru: 'Матчей: {n}', zh: '{n} 场比赛' },\n cardsScoreVersus: { en: '{home} vs {away}', fr: '{home} – {away}', de: '{home} gegen {away}', es: '{home} vs. {away}', it: '{home} - {away}', ja: '{home} 対 {away}', ko: '{home} 대 {away}', pt: '{home} x {away}', ru: '{home} — {away}', zh: '{home} 对 {away}' },\n cardsScoreLive: { en: 'Live', fr: 'En direct', de: 'Live', es: 'En vivo', it: 'In diretta', ja: '試合中', ko: '진행 중', pt: 'Ao vivo', ru: 'Идёт', zh: '进行中' },\n cardsScoreHalfTime: { en: 'Half-time', fr: 'Mi-temps', de: 'Halbzeit', es: 'Descanso', it: 'Intervallo', ja: 'ハーフタイム', ko: '하프타임', pt: 'Intervalo', ru: 'Перерыв', zh: '中场休息' },\n cardsScoreFullTime: { en: 'Full time', fr: 'Terminé', de: 'Spielende', es: 'Final', it: 'Finale', ja: '試合終了', ko: '경기 종료', pt: 'Encerrado', ru: 'Матч завершён', zh: '完场' },\n cardsScoreFinal: { en: 'Final', fr: 'Terminé', de: 'Beendet', es: 'Final', it: 'Finale', ja: '試合終了', ko: '경기 종료', pt: 'Final', ru: 'Завершён', zh: '已结束' },\n cardsScoreEnded: { en: 'Finished', fr: 'Terminé', de: 'Beendet', es: 'Finalizado', it: 'Terminato', ja: '終了', ko: '종료', pt: 'Encerrado', ru: 'Завершён', zh: '已结束' },\n cardsScorePostponed: { en: 'Postponed', fr: 'Reporté', de: 'Verschoben', es: 'Aplazado', it: 'Rinviato', ja: '延期', ko: '연기', pt: 'Adiado', ru: 'Перенесён', zh: '延期' },\n cardsScoreCancelled: { en: 'Cancelled', fr: 'Annulé', de: 'Abgesagt', es: 'Cancelado', it: 'Annullato', ja: '中止', ko: '취소', pt: 'Cancelado', ru: 'Отменён', zh: '取消' },\n cardsScoreUpcoming: { en: 'Upcoming', fr: 'À venir', de: 'Demnächst', es: 'Próximamente', it: 'In programma', ja: '開始前', ko: '예정', pt: 'Em breve', ru: 'Скоро', zh: '未开始' },\n cardsScoreMatchday: { en: 'Matchday {n}', fr: '{n}e journée', de: '{n}. Spieltag', es: 'Jornada {n}', it: '{n}ª giornata', ja: '第{n}節', ko: '{n}라운드', pt: 'Rodada {n}', ru: '{n}-й тур', zh: '第{n}轮' },\n cardsScoreTeam: { en: 'Team', fr: 'Équipe', de: 'Team', es: 'Equipo', it: 'Squadra', ja: 'チーム', ko: '팀', pt: 'Time', ru: 'Команда', zh: '球队' },\n cardsScoreTotal: { en: 'Total', fr: 'Total', de: 'Gesamt', es: 'Total', it: 'Totale', ja: '計', ko: '합계', pt: 'Total', ru: 'Итог', zh: '总分' },\n cardsScoreSets: { en: 'Sets', fr: 'Sets', de: 'Sätze', es: 'Sets', it: 'Set', ja: 'セット', ko: '세트', pt: 'Sets', ru: 'Сеты', zh: '盘' },\n cardsScorePeriods: { en: 'Score by period', fr: 'Score par période', de: 'Ergebnis nach Abschnitten', es: 'Marcador por periodo', it: 'Punteggio per periodo', ja: 'ピリオド別スコア', ko: '구간별 점수', pt: 'Placar por período', ru: 'Счёт по периодам', zh: '分节比分' },\n cardsScoreEvents: { en: 'Match events', fr: 'Faits du match', de: 'Spielereignisse', es: 'Incidencias', it: 'Eventi della partita', ja: '試合経過', ko: '경기 기록', pt: 'Lances da partida', ru: 'События матча', zh: '比赛事件' },\n cardsScoreDetails: { en: 'Match details', fr: 'Détails du match', de: 'Spieldetails', es: 'Detalles del partido', it: 'Dettagli partita', ja: '試合の詳細', ko: '경기 상세', pt: 'Detalhes da partida', ru: 'Подробнее о матче', zh: '比赛详情' },\n} satisfies Record<string, CardWord>;\n\nconst EVENT_WORDS: Record<MatchEventType, CardWord> = {\n goal: { en: 'Goal', fr: 'But', de: 'Tor', es: 'Gol', it: 'Gol', ja: 'ゴール', ko: '골', pt: 'Gol', ru: 'Гол', zh: '进球' },\n penalty: { en: 'Penalty', fr: 'Penalty', de: 'Elfmeter', es: 'Penalti', it: 'Rigore', ja: 'PK', ko: '페널티킥', pt: 'Pênalti', ru: 'Пенальти', zh: '点球' },\n 'own-goal': { en: 'Own goal', fr: 'Contre son camp', de: 'Eigentor', es: 'En propia puerta', it: 'Autogol', ja: 'オウンゴール', ko: '자책골', pt: 'Gol contra', ru: 'Автогол', zh: '乌龙球' },\n yellow: { en: 'Yellow card', fr: 'Carton jaune', de: 'Gelbe Karte', es: 'Tarjeta amarilla', it: 'Cartellino giallo', ja: 'イエローカード', ko: '옐로카드', pt: 'Cartão amarelo', ru: 'Жёлтая карточка', zh: '黄牌' },\n red: { en: 'Red card', fr: 'Carton rouge', de: 'Rote Karte', es: 'Tarjeta roja', it: 'Cartellino rosso', ja: 'レッドカード', ko: '레드카드', pt: 'Cartão vermelho', ru: 'Красная карточка', zh: '红牌' },\n sub: { en: 'Substitution', fr: 'Remplacement', de: 'Auswechslung', es: 'Sustitución', it: 'Sostituzione', ja: '選手交代', ko: '선수 교체', pt: 'Substituição', ru: 'Замена', zh: '换人' },\n};\n\n/** The locale key an app sets to reword an event's kind. */\nconst EVENT_KEYS: Record<MatchEventType, string> = {\n goal: 'cardsScoreGoal', penalty: 'cardsScorePenalty', 'own-goal': 'cardsScoreOwnGoal',\n yellow: 'cardsScoreYellowCard', red: 'cardsScoreRedCard', sub: 'cardsScoreSubstitution',\n};\n\ntype WordKey = keyof typeof S;\n\n/** Twelve: a round of a league fits, a whole season does not. */\nconst MAX_MATCHES = 12;\n/** Thirty events: every goal and card of a busy match; past that it is a commentary. */\nconst MAX_EVENTS = 30;\n/** Periods kept: an extra-innings game, not a spreadsheet. */\nconst MAX_PERIODS = 12;\nconst MAX_BROADCASTS = 3;\n\n// ── Reading ──────────────────────────────────────────────────────────────────\n\ntype Raw = Record<string, unknown>;\n\nconst isObject = (value: unknown): value is Raw => !!value && typeof value === 'object' && !Array.isArray(value);\n\n/** The first of `keys` that `r` has a value for. */\nfunction pick(r: Raw | undefined, keys: readonly string[]): unknown {\n if (!r) return undefined;\n for (const key of keys) if (r[key] !== undefined && r[key] !== null && r[key] !== '') return r[key];\n return undefined;\n}\n\n/** A name given as a string or as `{ name | displayName | fullName | title }`. */\nfunction textOf(value: unknown): string | undefined {\n if (isObject(value)) return str(pick(value, ['name', 'displayName', 'fullName', 'title', 'shortName', 'abbreviation']));\n return str(value);\n}\n\n/** Lowercase, `_` and `-` as spaces: `IN_PLAY`, `in-play` and `In play` are one key. */\nconst keyOf = (value: string) => value.trim().toLowerCase().replace(/[_-]+/g, ' ').replace(/\\s+/g, ' ');\n\n/**\n * Every spelling of a status the feeds use, by what it means. API-Football's short codes\n * (`NS`, `1H`, `HT`, `FT`, `AET`, `PEN`, `PST`, `CANC`), football-data.org's states\n * (`TIMED`, `IN_PLAY`, `PAUSED`, `FINISHED`), ESPN's `STATUS_*` names and `pre/in/post`\n * states. A suspension or an abandonment is none of them: it keeps the tool's own words.\n */\nconst STATUS_WORDS: Record<MatchStatus, readonly string[]> = {\n scheduled: ['scheduled', 'ns', 'tbd', 'timed', 'not started', 'pre', 'upcoming', 'fixture', 'status scheduled', 'pre match', 'prematch'],\n live: ['live', 'in play', 'inplay', 'in progress', 'playing', 'ongoing', 'started', '1h', '2h', 'et', 'bt', 'p', 'in', 'status in progress', 'status end period', 'status first half', 'status second half', 'first half', 'second half', 'extra time', 'penalty in progress', 'end of period'],\n halftime: ['halftime', 'half time', 'ht', 'paused', 'status halftime', 'interval'],\n final: ['final', 'ft', 'finished', 'full time', 'fulltime', 'ended', 'aet', 'pen', 'awarded', 'awd', 'wo', 'post', 'complete', 'completed', 'closed', 'match finished', 'after extra time', 'after penalties', 'status final', 'status full time', 'status final aet', 'status final pen', 'ft pen'],\n postponed: ['postponed', 'pst', 'status postponed'],\n cancelled: ['cancelled', 'canceled', 'canc', 'status canceled', 'status cancelled'],\n};\n\nconst STATUS_BY_WORD = new Map<string, MatchStatus>(\n (Object.entries(STATUS_WORDS) as Array<[MatchStatus, readonly string[]]>).flatMap(([status, words]) => words.map((w) => [w, status] as const)),\n);\n\n/** A status from what a tool wrote, or `undefined` when the card has no word for it. */\nfunction statusOf(value: unknown): MatchStatus | undefined {\n const text = str(value);\n return text ? STATUS_BY_WORD.get(keyOf(text)) : undefined;\n}\n\nconst SPORT_WORDS: Array<[Sport, RegExp]> = [\n ['american-football', /^(american[\\s_-]?football|nfl|ncaaf|gridiron|football \\(american\\))$/],\n ['football', /^(football|soccer|futbol|fútbol|calcio|fussball|fußball)$/],\n ['basketball', /^(basketball|basket|nba|wnba|ncaab|euroleague)$/],\n ['tennis', /^(tennis|atp|wta)$/],\n ['rugby', /^rugby/],\n ['hockey', /^((ice|field)[\\s_-]?)?hockey$|^nhl$/],\n ['baseball', /^(baseball|mlb|softball)$/],\n];\n\nfunction sportOf(value: unknown): Sport | undefined {\n const text = textOf(value)?.toLowerCase();\n if (!text) return undefined;\n return SPORT_WORDS.find(([, re]) => re.test(text))?.[0];\n}\n\n/**\n * ESPN never names the sport: its uids start with the sport's number instead —\n * `s:600~l:700~e:401879254` is soccer, `s:40~l:46` basketball. Only the numbers seen in its\n * answers are listed; an unknown one says nothing.\n */\nconst ESPN_SPORTS: Record<string, Sport> = { 1: 'baseball', 20: 'american-football', 40: 'basketball', 70: 'hockey', 600: 'football', 850: 'tennis' };\n\nfunction espnSport(uid: unknown): Sport | undefined {\n const id = typeof uid === 'string' ? /^s:(\\d+)(?:~|$)/.exec(uid.trim())?.[1] : undefined;\n return id ? ESPN_SPORTS[id] : undefined;\n}\n\n/**\n * The sport a league says: its ESPN uid, then its sport, its abbreviation (`NBA`), its slug\n * (`atp`), its name. ESPN's soccer league says it in its uid alone — `English Premier\n * League`, `Premier League` and `eng.1` name no sport.\n */\nfunction leagueSport(league: unknown): Sport | undefined {\n if (!isObject(league)) return sportOf(league);\n return espnSport(league['uid']) ?? [league['sport'], league['abbreviation'], league['slug'], league['name']].map(sportOf).find((s) => s !== undefined);\n}\n\n/** `#c8102e`, `c8102e` (ESPN writes it bare) or `#c12` → `#c8102e`; anything else is no colour. */\nexport function teamColor(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined;\n const match = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(value.trim());\n if (!match) return undefined;\n const hex = match[1]!.toLowerCase();\n return `#${hex.length === 3 ? [...hex].map((c) => c + c).join('') : hex}`;\n}\n\n/** A score: a number, `\"2\"`, or `{ value }` / `{ displayValue }` as ESPN nests it. */\nfunction scoreOf(value: unknown): number | undefined {\n if (isObject(value)) return num(pick(value, ['value', 'displayValue', 'score', 'total']));\n return num(value);\n}\n\n/** The match clock as drawn: a number of minutes is `67'`, with stoppage time `90+3'`. */\nfunction minuteOf(value: unknown, extra?: unknown): string | undefined {\n if (isObject(value)) return minuteOf(pick(value, ['elapsed', 'minute', 'displayValue', 'value']), pick(value, ['extra', 'added', 'injuryTime']));\n const n = num(value);\n if (n !== undefined) {\n const plus = num(extra);\n return `${Math.round(n)}${plus ? `+${Math.round(plus)}` : ''}'`;\n }\n return str(value);\n}\n\ninterface TeamRead extends Team {\n id?: string;\n won?: boolean;\n lines?: unknown[];\n}\n\n// `displayName` first: ESPN's `name` is the nickname (\"Wizards\"), its `displayName` the team (\"Washington Wizards\").\nconst NAME_KEYS = ['displayName', 'name', 'fullName', 'teamName', 'team_name', 'title', 'shortDisplayName'] as const;\nconst SHORT_KEYS = ['shortName', 'short_name', 'abbreviation', 'abbr', 'tla', 'code', 'shortDisplayName'] as const;\nconst LOGO_KEYS = ['logo', 'crest', 'logoUrl', 'logo_url', 'badge', 'emblem', 'image', 'imageUrl'] as const;\nconst SCORE_KEYS = ['score', 'goals', 'points', 'pts', 'runs'] as const;\nconst COLOR_KEYS = ['color', 'colour', 'primaryColor', 'primary_color', 'teamColor'] as const;\n\n/** One team from a string, a team, or a competitor that wraps a `team` (ESPN). */\nfunction readTeam(raw: unknown): TeamRead | null {\n if (typeof raw === 'string') {\n const name = str(raw);\n return name ? { name } : null;\n }\n if (!isObject(raw)) return null;\n const inner: Raw = isObject(raw['team']) ? raw['team'] : {};\n const both = (keys: readonly string[]) => pick(raw, keys) ?? pick(inner, keys);\n const name = str(pick(raw, NAME_KEYS)) ?? (typeof raw['team'] === 'string' ? str(raw['team']) : undefined) ?? str(pick(inner, NAME_KEYS));\n if (!name) return null;\n const shortName = str(both(SHORT_KEYS));\n const logos = both(['logos']);\n const logo = webUrl(textOrUrl(both(LOGO_KEYS))) ?? (Array.isArray(logos) ? webUrl(textOrUrl(logos[0])) : null);\n const score = scoreOf(pick(raw, SCORE_KEYS));\n const records = raw['records'];\n const record = str(pick(raw, ['record', 'recordSummary', 'standing'])) ?? (Array.isArray(records) ? str(isObject(records[0]) ? records[0]['summary'] : records[0]) : undefined);\n const color = teamColor(both(COLOR_KEYS));\n const id = str(both(['id', 'teamId', 'team_id', 'idTeam']));\n const won = typeof raw['winner'] === 'boolean' ? raw['winner'] : undefined;\n const lines = Array.isArray(raw['linescores']) ? raw['linescores'] : undefined;\n return {\n name,\n ...(shortName && shortName !== name ? { shortName } : {}),\n ...(logo ? { logo } : {}),\n ...(score !== undefined ? { score } : {}),\n ...(record ? { record } : {}),\n ...(color ? { color } : {}),\n ...(id ? { id } : {}),\n ...(won !== undefined ? { won } : {}),\n ...(lines ? { lines } : {}),\n };\n}\n\n/** A link given as a string or as `{ href | url | src }`. */\nfunction textOrUrl(value: unknown): unknown {\n return isObject(value) ? pick(value, ['href', 'url', 'src']) : value;\n}\n\n/** Whether something looks like a match rather than an event of one: it has teams. */\nfunction looksLikeMatch(value: unknown): boolean {\n if (!isObject(value)) return false;\n return ['home', 'homeTeam', 'home_team', 'teams', 'competitors', 'competitions', 'strHomeTeam', 'participants'].some((key) => value[key] !== undefined);\n}\n\n/** The two sides: `home`/`away` in any spelling, `teams.home`, or a `competitors` pair. */\nfunction sidesOf(m: Raw): [unknown, unknown] {\n const home = pick(m, ['home', 'homeTeam', 'home_team', 'hometeam']);\n const away = pick(m, ['away', 'awayTeam', 'away_team', 'awayteam', 'visitor', 'visitors']);\n if (home !== undefined || away !== undefined) return [home, away];\n const teams = m['teams'];\n if (isObject(teams)) return [teams['home'], teams['away']];\n const list = [m['competitors'], m['participants'], teams].find(Array.isArray) as unknown[] | undefined;\n if (list) {\n const side = (wanted: MatchSide) => list.find((c) => isObject(c) && (c['homeAway'] === wanted || c['qualifier'] === wanted || c['side'] === wanted));\n return [side('home') ?? list[0], side('away') ?? list[1]];\n }\n if (m['strHomeTeam'] !== undefined) {\n // TheSportsDB: one flat record, `strHomeTeam`, `intHomeScore`, `strHomeTeamBadge`.\n return [\n { name: m['strHomeTeam'], score: m['intHomeScore'], logo: m['strHomeTeamBadge'] },\n { name: m['strAwayTeam'], score: m['intAwayScore'], logo: m['strAwayTeamBadge'] },\n ];\n }\n return [undefined, undefined];\n}\n\n/** A score the match gives beside its teams: `goals.home`, `score.fullTime.home`, `homeScore`, `\"2-1\"`. */\nfunction matchScores(m: Raw): [number | undefined, number | undefined] {\n const pair = (value: unknown): [number | undefined, number | undefined] | undefined => {\n if (!isObject(value)) return undefined;\n const h = scoreOf(value['home']);\n const a = scoreOf(value['away']);\n return h !== undefined || a !== undefined ? [h, a] : undefined;\n };\n const score = m['score'];\n const text = typeof score === 'string' ? /^\\s*(\\d+)\\s*[-–:]\\s*(\\d+)\\s*$/.exec(score) : null;\n return pair(m['goals'])\n ?? pair(score)\n ?? pair(m['scores'])\n ?? (isObject(score) ? pair(score['fullTime']) ?? pair(score['fulltime']) ?? pair(score['current']) : undefined)\n ?? (text ? [Number(text[1]), Number(text[2])] : undefined)\n ?? [scoreOf(pick(m, ['homeScore', 'home_score', 'scoreHome'])), scoreOf(pick(m, ['awayScore', 'away_score', 'scoreAway']))];\n}\n\n/** The status, the clock and the period, from a string or a status object of any feed. */\nfunction readState(m: Raw, fixture: Raw): Pick<Match, 'status' | 'statusText' | 'clock' | 'period'> & { periodNumber?: number } {\n const raw = pick(m, ['status', 'state', 'strStatus', 'matchStatus', 'match_status']) ?? fixture['status'];\n let status: MatchStatus | undefined;\n let text: string | undefined;\n // football-data.org puts the stoppage time beside the minute, on the match: `minute: 90, injuryTime: 7`.\n let clock = minuteOf(pick(m, ['clock', 'minute', 'elapsed', 'time_elapsed']), pick(m, ['injuryTime', 'injury_time']));\n let period: unknown = pick(m, ['period', 'currentPeriod']);\n if (isObject(raw)) {\n const type: Raw = isObject(raw['type']) ? raw['type'] : {};\n const said = [raw['short'], type['name'], type['state'], raw['long'], type['shortDetail'], type['description'], raw['name'], raw['state'], raw['description']];\n status = said.map(statusOf).find((s) => s !== undefined);\n text = str(raw['long'] ?? type['description'] ?? type['detail'] ?? raw['short'] ?? raw['description']);\n clock ??= minuteOf(pick(raw, ['elapsed', 'minute']), raw['extra']) ?? str(raw['displayClock'] ?? raw['clock']);\n period ??= pick(raw, ['period']);\n } else {\n status = statusOf(raw);\n text = str(raw);\n }\n const periodNumber = num(period);\n return {\n ...(status ? { status } : text ? { statusText: text } : {}),\n ...(clock ? { clock } : {}),\n ...(typeof period === 'string' && str(period) ? { period: str(period)! } : {}),\n ...(periodNumber !== undefined && typeof period !== 'string' ? { periodNumber } : {}),\n };\n}\n\n/**\n * \"Q3\" for a quarter, \"P2\" for a hockey period — what a clock needs beside it. A football\n * half or a tennis set given as a bare number says nothing a reader wants beside \"67'\".\n */\nfunction periodName(sport: Sport, n: number): string | undefined {\n if (sport === 'basketball' || sport === 'american-football') return `Q${n}`;\n if (sport === 'hockey') return `P${n}`;\n return undefined;\n}\n\nfunction readPeriods(m: Raw, home: TeamRead, away: TeamRead): MatchPeriod[] | undefined {\n let periods: MatchPeriod[] = [];\n const list = [m['periods'], m['sets'], m['linescores'], m['innings']].find(Array.isArray) as unknown[] | undefined;\n if (list) {\n periods = list.map((p, i): MatchPeriod | null => {\n if (Array.isArray(p)) return { label: String(i + 1), ...side('home', num(p[0])), ...side('away', num(p[1])) };\n if (!isObject(p)) return null;\n const label = str(pick(p, ['label', 'name', 'period', 'set', 'number'])) ?? String(i + 1);\n return { label, ...side('home', scoreOf(pick(p, ['home', 'homeScore', 'home_score', 'h']))), ...side('away', scoreOf(pick(p, ['away', 'awayScore', 'away_score', 'a']))) };\n }).filter((p): p is MatchPeriod => p !== null);\n } else if (home.lines || away.lines) {\n // ESPN: each competitor carries its own `linescores`; zipped into one row per period.\n const count = Math.max(home.lines?.length ?? 0, away.lines?.length ?? 0);\n for (let i = 0; i < count; i++) {\n const at = (lines: unknown[] | undefined) => scoreOf(lines?.[i]);\n const p = home.lines?.[i] ?? away.lines?.[i];\n const label = (isObject(p) ? str(pick(p, ['label', 'period'])) : undefined) ?? String(i + 1);\n periods.push({ label, ...side('home', at(home.lines)), ...side('away', at(away.lines)) });\n }\n }\n periods = periods.filter((p) => p.home !== undefined || p.away !== undefined).slice(0, MAX_PERIODS);\n return periods.length ? periods : undefined;\n}\n\nconst side = (key: MatchSide, value: number | undefined) => (value !== undefined ? { [key]: value } : {});\n\n/** An event's kind from its type and detail, as any feed writes them; `null` for one the card does not draw. */\nfunction eventType(type: unknown, detail: unknown, flags: Raw): MatchEventType | null {\n if (flags['ownGoal'] === true) return 'own-goal';\n if (flags['penaltyKick'] === true && flags['scoringPlay'] !== false) return 'penalty';\n if (flags['redCard'] === true) return 'red';\n if (flags['yellowCard'] === true) return 'yellow';\n // A VAR review is not an event of its own: what it confirmed (\"Penalty confirmed\") is\n // already in the list as the goal or the card, and what it cancelled never happened.\n const typed = typeof type === 'string' ? keyOf(type) : isObject(type) ? keyOf(String(type['text'] ?? type['type'] ?? '')) : '';\n if (/^var\\b/.test(typed)) return null;\n for (const value of [detail, type]) {\n const t = typeof value === 'string' ? keyOf(value) : isObject(value) ? keyOf(String(value['text'] ?? value['type'] ?? '')) : '';\n if (!t) continue;\n if (/missed|saved|cancel|disallow/.test(t)) return null;\n if (/own goal|^og$|^own$/.test(t)) return 'own-goal';\n if (/penalty|^pen$|^pk$/.test(t) && !/card/.test(t)) return 'penalty';\n if (/red|second yellow|yellow red|yellowred/.test(t)) return 'red';\n if (/yellow/.test(t)) return 'yellow';\n if (/^sub|substitution|^subst|replacement/.test(t)) return 'sub';\n if (/goal|^regular$|^normal$|scor/.test(t)) return 'goal';\n }\n if (flags['scoringPlay'] === true) return 'goal';\n return null;\n}\n\n/** Which side an event belongs to: `home`/`away`, or a team named or numbered like one of the two. */\nfunction eventSide(e: Raw, home: TeamRead, away: TeamRead): MatchSide | null {\n const said = pick(e, ['side', 'homeAway', 'team']);\n if (said === 'home' || said === 'away') return said;\n if (typeof e['isHome'] === 'boolean') return e['isHome'] ? 'home' : 'away';\n const team = pick(e, ['team', 'club']);\n const id = isObject(team) ? str(team['id']) : undefined;\n const name = textOf(team)?.toLowerCase();\n const matches = (t: TeamRead) => (id !== undefined && t.id === id) || (!!name && (t.name.toLowerCase() === name || t.shortName?.toLowerCase() === name));\n if (matches(home)) return 'home';\n if (matches(away)) return 'away';\n return null;\n}\n\nfunction readEvent(raw: unknown, home: TeamRead, away: TeamRead, implied?: MatchEventType): MatchEvent | null {\n if (!isObject(raw)) return null;\n const e = raw;\n const team = eventSide(e, home, away);\n if (!team) return null;\n // football-data.org's lists say what they hold: its bookings carry `card: 'YELLOW_RED'`,\n // its goals `type: 'OWN'`. Every other feed says the kind on the event itself.\n const kind = implied === 'sub' ? 'sub'\n : implied === 'yellow' ? eventType(e['card'] ?? e['type'], undefined, e) ?? 'yellow'\n : eventType(e['type'] ?? e['kind'] ?? e['card'], e['detail'], e) ?? (implied === 'goal' ? 'goal' : null);\n if (!kind) return null;\n const minute = minuteOf(pick(e, ['minute', 'time', 'clock', 'elapsed', 'min']), e['extra'] ?? e['injuryTime']);\n const athletes = e['athletesInvolved'];\n const player = textOf(pick(e, ['player', 'scorer', 'playerIn', 'athlete', 'playerName', 'player_name'])) ?? (Array.isArray(athletes) ? textOf(athletes[0]) : undefined);\n // What the type was read from is not repeated as the detail (\"Normal Goal\", \"Yellow Card\").\n const typed = typeof e['detail'] === 'string' && eventType(undefined, e['detail'], {}) !== null;\n const detail = (typed ? undefined : str(e['detail'])) ?? textOf(pick(e, ['assist', 'playerOut', 'note', 'description']));\n return {\n ...(minute ? { minute } : {}),\n team,\n type: kind,\n ...(player ? { player } : {}),\n ...(detail && detail !== player ? { detail } : {}),\n };\n}\n\nfunction readEvents(m: Raw, home: TeamRead, away: TeamRead): MatchEvent[] | undefined {\n const events: Array<MatchEvent | null> = [];\n const list = [m['events'], m['incidents'], m['timeline'], m['details'], m['keyEvents']].find(Array.isArray) as unknown[] | undefined;\n for (const e of list ?? []) events.push(readEvent(e, home, away));\n // football-data.org: the goals, the cards and the changes in three lists.\n if (!list) {\n const lists: Array<[unknown, MatchEventType]> = [[m['goals'], 'goal'], [m['bookings'], 'yellow'], [m['substitutions'], 'sub']];\n for (const [items, type] of lists) if (Array.isArray(items)) for (const e of items) events.push(readEvent(e, home, away, type));\n }\n const kept = events.filter((e): e is MatchEvent => e !== null);\n if (!list && kept.length) kept.sort((a, b) => minuteValue(a.minute) - minuteValue(b.minute));\n const shown = kept.slice(0, MAX_EVENTS);\n return shown.length ? shown : undefined;\n}\n\n/** `90+3'` → 90.03, for putting three lists back in order. */\nfunction minuteValue(minute: string | undefined): number {\n const match = /(\\d+)(?:\\s*\\+\\s*(\\d+))?/.exec(minute ?? '');\n return match ? Number(match[1]) + Number(match[2] ?? 0) / 100 : Infinity;\n}\n\n/** The round: a string, a matchday number, or API-Football's \"Regular Season - 12\". */\nfunction readRound(m: Raw, league: Raw): Pick<Match, 'round' | 'matchday'> {\n const week = m['week'];\n const matchday = num(pick(m, ['matchday', 'matchDay', 'gameweek', 'intRound'])) ?? num(isObject(week) ? week['number'] : week);\n const round = str(pick(m, ['round', 'roundName'])) ?? str(league['round']);\n const regular = round ? /^regular season\\s*[-–]\\s*(\\d+)$/i.exec(round) : null;\n if (regular) return { matchday: Number(regular[1]) };\n if (round) return { round };\n if (matchday !== undefined) return { matchday };\n const stage = str(m['stage']);\n // football-data.org says `REGULAR_SEASON` on every league match: that is no round.\n if (stage && !/^regular[_\\s]season$/i.test(stage)) {\n const words = stage.replace(/_/g, ' ').toLowerCase();\n return { round: words.charAt(0).toUpperCase() + words.slice(1) };\n }\n return {};\n}\n\nfunction readBroadcast(m: Raw): string | undefined {\n const raw = pick(m, ['broadcast', 'broadcasts', 'tv', 'channel', 'channels', 'strTVStation', 'geoBroadcasts']);\n const names = (Array.isArray(raw) ? raw : [raw]).flatMap((b) => {\n if (isObject(b) && Array.isArray(b['names'])) return b['names'].map(str);\n if (isObject(b) && isObject(b['media'])) return [textOf(b['media'])];\n return [textOf(b)];\n }).filter((n): n is string => !!n);\n const unique = [...new Set(names)].slice(0, MAX_BROADCASTS);\n return unique.length ? unique.join(', ') : undefined;\n}\n\nfunction readVenue(value: unknown): string | undefined {\n if (!isObject(value)) return str(value);\n const name = textOf(value);\n const address = isObject(value['address']) ? value['address'] : {};\n const city = str(value['city'] ?? address['city']);\n return name && city && !name.includes(city) ? `${name}, ${city}` : name ?? city;\n}\n\n/** A date a feed gives without its zone, as TheSportsDB's `strTimestamp`, is UTC. */\nconst utc = (value: unknown) => (typeof value === 'string' && /^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d(:\\d\\d)?$/.test(value.trim()) ? `${value.trim()}Z` : value);\n\n/** `league`: the envelope's league (ESPN's `leagues[0]`), for the sport its events do not say. */\nfunction readMatch(raw: unknown, league0?: unknown): Match | null {\n if (!isObject(raw)) return null;\n // ESPN puts the teams, the venue and the status in the event's first competition.\n const competitions = raw['competitions'];\n const m: Raw = Array.isArray(competitions) && isObject(competitions[0]) ? { ...raw, ...competitions[0], status: competitions[0]['status'] ?? raw['status'] } : raw;\n const fixture: Raw = isObject(m['fixture']) ? m['fixture'] : {};\n const league: Raw = isObject(m['league']) ? m['league'] : {};\n\n const [rawHome, rawAway] = sidesOf(m);\n const home = readTeam(rawHome);\n const away = readTeam(rawAway);\n if (!home || !away) return null;\n const [homeScore, awayScore] = matchScores(m);\n if (home.score === undefined && homeScore !== undefined) home.score = homeScore;\n if (away.score === undefined && awayScore !== undefined) away.score = awayScore;\n\n const sport = sportOf(pick(m, ['sport', 'strSport', 'sportName', 'discipline']) ?? league['sport'])\n ?? espnSport(raw['uid'] ?? m['uid'])\n ?? (league0 !== undefined ? leagueSport(league0) : undefined)\n // API-Football and football-data.org only ever carry football.\n ?? (m['fixture'] !== undefined || m['goals'] !== undefined || (isObject(m['score']) && isObject(m['score']['fullTime'])) ? 'football' : 'generic');\n const state = readState(m, fixture);\n const period = state.period ?? (state.periodNumber !== undefined ? periodName(sport, state.periodNumber) : undefined);\n const startTime = toDate(utc(pick(m, ['startTime', 'start_time', 'start', 'kickoff', 'kickOff', 'kick_off', 'utcDate', 'date', 'datetime', 'dateTime', 'startDate', 'commence_time', 'strTimestamp'])))\n ?? toDate(fixture['date'] ?? fixture['timestamp']);\n const competition = textOf(pick(m, ['competition', 'tournament', 'strLeague', 'leagueName']) ?? m['league']);\n const venue = readVenue(pick(m, ['venue', 'stadium', 'strVenue', 'arena']) ?? fixture['venue']);\n const periods = readPeriods(m, home, away);\n const events = readEvents(m, home, away);\n const links = m['links'];\n const url = webUrl(textOrUrl(pick(m, ['url', 'link', 'href', 'matchUrl', 'match_url']))) ?? (Array.isArray(links) ? webUrl(textOrUrl(links[0])) : null);\n const broadcast = readBroadcast(m);\n\n // Tennis gives the sets and not always the sets won: those are counted from the games —\n // the sets DECIDED only. A live 6–4, 3–2 is one set to none, not two: the set being played\n // is no one's yet (nor the one a retirement stopped in).\n for (const key of ['home', 'away'] as const) {\n const team = key === 'home' ? home : away;\n if (team.score !== undefined || !periods || state.status === 'scheduled') continue;\n const other: MatchSide = key === 'home' ? 'away' : 'home';\n const own = periods.map((p) => p[key]);\n if (own.some((v) => v === undefined)) continue;\n team.score = sport === 'tennis'\n ? periods.filter((p) => setWon(p[key] ?? 0, p[other] ?? 0)).length\n : own.reduce<number>((sum, v) => sum + (v ?? 0), 0);\n }\n\n const winner = readWinner(m, home, away, state.status);\n const strip = ({ id: _id, won: _won, lines: _lines, ...team }: TeamRead): Team => team;\n return {\n home: strip(home),\n away: strip(away),\n ...(state.status ? { status: state.status } : {}),\n ...(state.statusText ? { statusText: state.statusText } : {}),\n ...(state.clock ? { clock: state.clock } : {}),\n ...(period ? { period } : {}),\n ...(startTime ? { startTime } : {}),\n ...(competition ? { competition } : {}),\n ...readRound(m, league),\n ...(venue ? { venue } : {}),\n sport,\n ...(periods ? { periods } : {}),\n ...(events ? { events } : {}),\n ...(winner ? { winner } : {}),\n ...(broadcast ? { broadcast } : {}),\n ...(url ? { url } : {}),\n };\n}\n\n/**\n * A set won: six games and two clear (a 10–8 match tie-break too), or seven — a tie-break's\n * 7–6. Anything short of that is a set still being played.\n */\nconst setWon = (own: number, other: number) => own > other && own >= 6 && (own - other >= 2 || own === 7);\n\n/** Who won: said by the tool in one of its ways, else the higher score of a finished match. */\nfunction readWinner(m: Raw, home: TeamRead, away: TeamRead, status: MatchStatus | undefined): MatchSide | undefined {\n const score = isObject(m['score']) ? m['score'] : {};\n const said = str(m['winner'] ?? score['winner'])?.toLowerCase();\n if (said === 'home' || said === 'home_team') return 'home';\n if (said === 'away' || said === 'away_team') return 'away';\n if (said && said === home.name.toLowerCase()) return 'home';\n if (said && said === away.name.toLowerCase()) return 'away';\n if (home.won === true || (away.won === false && home.won === undefined)) return 'home';\n if (away.won === true) return 'away';\n if (said === 'draw' || status !== 'final' || home.score === undefined || away.score === undefined || home.score === away.score) return undefined;\n return home.score > away.score ? 'home' : 'away';\n}\n\n/**\n * The card's data from the loose shape `map` returns — one match, a list, or an envelope\n * (`matches`, `fixtures`, `games`, `events` of matches, API-Football's `response`) with its\n * `title` (or the competition's name) — or `null` when not one match has two named teams.\n * At most twelve are kept.\n */\nexport function readMatches(raw: unknown): ScoreData | null {\n let list: unknown[];\n let title: string | undefined;\n let league: unknown;\n if (Array.isArray(raw)) {\n list = raw;\n } else if (isObject(raw)) {\n const found = [raw['matches'], raw['fixtures'], raw['games'], raw['results'], raw['response'], raw['data'], raw['scores'], raw['events']]\n .find((v) => Array.isArray(v) && v.some(looksLikeMatch)) as unknown[] | undefined;\n if (found && !looksLikeMatch(raw)) {\n list = found;\n const leagues = raw['leagues'];\n league = Array.isArray(leagues) ? leagues[0] : raw['league'];\n title = str(raw['title'] ?? raw['heading'])\n ?? textOf(raw['competition'] ?? raw['league'])\n ?? (Array.isArray(leagues) ? textOf(leagues[0]) : undefined);\n } else {\n list = [raw];\n }\n } else {\n return null;\n }\n const matches = list.map((item) => readMatch(item, league)).filter((m): m is Match => m !== null).slice(0, MAX_MATCHES);\n if (!matches.length) return null;\n return { ...(title ? { title } : {}), matches };\n}\n\n// ── What a match says ────────────────────────────────────────────────────────\n\n/** How the card shows a match: what it is, worked out once from its status, scores and time. */\ntype Phase = MatchStatus | 'other' | 'none';\n\nfunction phaseOf(match: Match): Phase {\n if (match.status) return match.status;\n if (match.statusText) return 'other';\n if (hasScore(match)) return 'none';\n return match.startTime ? 'scheduled' : 'none';\n}\n\nconst hasScore = (match: Match) => match.home.score !== undefined && match.away.score !== undefined;\n\n/** Whether the board shows the score: a match under way or over, with both numbers. */\nfunction showsScore(match: Match): boolean {\n const phase = phaseOf(match);\n return hasScore(match) && phase !== 'scheduled' && !((phase === 'postponed' || phase === 'cancelled') && match.home.score === 0 && match.away.score === 0);\n}\n\n/** \"Full time\" for football and rugby, \"Final\" for the American sports, \"Finished\" for the rest. */\nfunction endWord(sport: Sport): WordKey {\n if (sport === 'football' || sport === 'rugby') return 'cardsScoreFullTime';\n if (sport === 'tennis' || sport === 'generic') return 'cardsScoreEnded';\n return 'cardsScoreFinal';\n}\n\n/** The live clock as one line: \"Q3 4:12\", \"67'\" — the period only when the clock does not say it. */\nfunction clockText(match: Match): string | undefined {\n const parts = [match.period && !match.clock?.includes(match.period) ? match.period : undefined, match.clock].filter(Boolean);\n return parts.length ? parts.join(' ') : undefined;\n}\n\n/** The state of play in words — `undefined` for a scheduled match, which is said by its time. */\nfunction statusText(config: AparteConfig, match: Match): string | undefined {\n const phase = phaseOf(match);\n switch (phase) {\n case 'live': {\n const clock = clockText(match);\n return `${word(config, 'cardsScoreLive', S.cardsScoreLive)}${clock ? ` ${clock}` : ''}`;\n }\n case 'halftime': return word(config, 'cardsScoreHalfTime', S.cardsScoreHalfTime);\n case 'final': return word(config, endWord(match.sport), S[endWord(match.sport)]);\n case 'postponed': return word(config, 'cardsScorePostponed', S.cardsScorePostponed);\n case 'cancelled': return word(config, 'cardsScoreCancelled', S.cardsScoreCancelled);\n case 'other': return match.statusText;\n default: return undefined;\n }\n}\n\nconst startOfDay = (d: Date) => new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();\n\n/**\n * The day of a match as a person says it: \"Yesterday\", \"Today\", \"Tomorrow\", \"Sat\" within\n * the week, \"Sat 14 Nov\" further off — a bare weekday a fortnight away would be a lie.\n */\nfunction dayText(config: AparteConfig, date: Date, now: Date): string {\n const days = Math.round((startOfDay(date) - startOfDay(now)) / 86_400_000);\n if (days === -1) {\n const tag = intlTag(config);\n const text = new Intl.RelativeTimeFormat(tag, { numeric: 'auto' }).format(-1, 'day');\n return text.charAt(0).toLocaleUpperCase(tag) + text.slice(1);\n }\n if (days >= 0 && days <= 6) return formatDay(config, date, 'short', now);\n return new Intl.DateTimeFormat(intlTag(config), { weekday: 'short', day: 'numeric', month: 'short' }).format(date);\n}\n\n/** Kick-off as one line: \"Today 21:00\", \"Sat 9 PM\". */\nconst whenText = (config: AparteConfig, date: Date, now: Date) => `${dayText(config, date, now)} ${formatHour(config, date)}`;\n\nconst versus = (config: AparteConfig, match: Match) => word(config, 'cardsScoreVersus', S.cardsScoreVersus, { home: match.home.name, away: match.away.name });\n\n/**\n * Kick-off with nothing relative in it — `Mon, Nov 2, 2026, 9:00 PM GMT+1` — for the\n * fallback: it is stored in the history and read again days later, by a model or a person,\n * when \"Today\" has become a lie.\n */\nconst absoluteWhen = (config: AparteConfig, date: Date) => new Intl.DateTimeFormat(intlTag(config), {\n weekday: 'short', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit', timeZoneName: 'short',\n}).format(date);\n\n/**\n * \"Lille 2–1 Lens (Full time)\", \"Lille vs Lens — Sat 21:00\", \"Lille vs Lens (Postponed)\".\n * `now` reads the day against the clock (\"Today\"); without it, the date is written out.\n */\nfunction matchSentence(config: AparteConfig, match: Match, now?: Date): string {\n const said = statusText(config, match);\n if (showsScore(match)) {\n const score = `${match.home.name} ${formatNumber(config, match.home.score!)}–${formatNumber(config, match.away.score!)} ${match.away.name}`;\n return said ? `${score} (${said})` : score;\n }\n if (said) return `${versus(config, match)} (${said})`;\n if (!match.startTime) return versus(config, match);\n return `${versus(config, match)} — ${now ? whenText(config, match.startTime, now) : absoluteWhen(config, match.startTime)}`;\n}\n\n// ── Drawing ──────────────────────────────────────────────────────────────────\n\ninterface Settings {\n now: () => Date;\n}\n\nconst notNull = <T>(value: T | null | undefined | false): value is T => value !== null && value !== undefined && value !== false;\n\n/** The middle dot between two facts on a line — drawn, not read. */\nconst dot = () => el('span', { class: 'aparte-score__dot', attrs: { 'aria-hidden': 'true' }, text: '·' });\n\n/**\n * A team's letters for its monogram: its short name when it is one (`PSG`), else the\n * initials of its name's words (`Paris Saint-Germain` → `PSG`, `Real Madrid` → `RM`), else\n * the first three letters of its one word (`Lille` → `LIL`), as broadcasters write them.\n * A club's `FC` or `AC` is not a word of its name. Two characters for Chinese, Japanese and\n * Korean names, which a disc fits.\n */\nexport function monogram(team: Pick<Team, 'name' | 'shortName'>): string {\n const short = team.shortName?.replace(/[^\\p{L}\\p{N}]/gu, '');\n if (short && [...short].length <= 3) return short.toLocaleUpperCase();\n const name = team.name;\n if (/[\\u3040-\\u30ff\\u3400-\\u9fff\\uac00-\\ud7af]/.test(name)) return [...name.replace(/\\s+/g, '')].slice(0, 2).join('');\n const words = name.split(/[\\s\\-–.'’/&]+/).map((w) => w.replace(/[^\\p{L}\\p{N}]/gu, '')).filter(Boolean);\n const meaningful = words.filter((w) => !CLUB_PARTS.has(w.toLowerCase()));\n const kept = meaningful.length ? meaningful : words;\n if (!kept.length) return '?';\n const letters = kept.length === 1 ? [...kept[0]!].slice(0, 3).join('') : kept.slice(0, 3).map((w) => [...w][0]).join('');\n return letters.toLocaleUpperCase();\n}\n\nconst CLUB_PARTS = new Set(['fc', 'cf', 'afc', 'ac', 'as', 'sc', 'sv', 'cd', 'rc', 'ssc', 'club', 'de', 'del', 'the', 'of', 'and', 'vfb', 'vfl', 'tsg', 'bk', 'if', 'fk', 'sk']);\n\n/** Light or dark text on a team's colour: whichever reads better, by the colour's luminance. */\nexport function inkOn(hex: string): 'light' | 'dark' {\n const channel = (i: number) => {\n const c = parseInt(hex.slice(1 + i * 2, 3 + i * 2), 16) / 255;\n return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;\n };\n const luminance = 0.2126 * channel(0) + 0.7152 * channel(1) + 0.0722 * channel(2);\n // 0.179: where black and white text have the same contrast on the colour.\n return luminance > 0.179 ? 'dark' : 'light';\n}\n\n/** A team's colour on an element, as the custom property its sheet reads. */\nfunction wear(node: HTMLElement, property: string, color: string | undefined): void {\n if (color) node.style.setProperty(property, color);\n}\n\n/**\n * The team's crest: its logo over its monogram, so a logo that fails to load leaves the\n * monogram — on a disc in the team's colour, or a neutral tint. Decorative (`alt=\"\"`): the\n * team's name is always written beside it.\n */\nfunction crestOf(team: Team, size: 'lg' | 'sm'): HTMLElement {\n const box = el('span', { class: `aparte-score__crest aparte-score__crest--${size}`, attrs: { 'aria-hidden': 'true', 'data-ink': team.color ? inkOn(team.color) : undefined } },\n el('span', { class: 'aparte-score__monogram', text: monogram(team) }));\n wear(box, '--aparte-score-team', team.color);\n if (team.logo) {\n const img = el('img', { class: 'aparte-score__logo', attrs: { src: team.logo, alt: '', loading: 'lazy', decoding: 'async' } });\n img.addEventListener('error', () => {\n img.remove();\n box.removeAttribute('data-logo');\n }, { once: true });\n box.setAttribute('data-logo', '');\n box.append(img);\n }\n return box;\n}\n\n/** `win` and `lose` once a winner is known; nothing for a draw or a match still to finish. */\nconst leadOf = (match: Match, key: MatchSide) => (match.winner ? (match.winner === key ? 'win' : 'lose') : undefined);\n\nfunction numberOf(ctx: CardContext, value: number, className: string, attrs: Record<string, string | undefined> = {}): HTMLElement {\n const node = el('span', { class: className, attrs });\n ctx.bind(node, () => formatNumber(ctx.config, value));\n return node;\n}\n\n/** The status as a pill: a live one breathes, and every one says its state in a word. */\nfunction pillOf(ctx: CardContext, match: Match): HTMLElement | null {\n const phase = phaseOf(match);\n if (phase === 'scheduled' || phase === 'none') return null;\n const pill = el('span', { class: 'aparte-score__pill', attrs: { 'data-phase': phase } });\n if (phase === 'live') {\n const said = el('span', { class: 'aparte-score__live-word' });\n ctx.word(said, 'cardsScoreLive', S.cardsScoreLive);\n const clock = clockText(match);\n pill.append(el('span', { class: 'aparte-score__live-dot', attrs: { 'aria-hidden': 'true' } }), said);\n if (clock) pill.append(el('span', { class: 'aparte-score__clock', text: clock }));\n return pill;\n }\n ctx.bind(pill, () => statusText(ctx.config, match)!);\n return pill;\n}\n\n/** Kick-off as a `<time>`: the day over the hour, or the two on one line. */\nfunction kickoffOf(ctx: CardContext, date: Date, now: Date, className: string): HTMLElement {\n const node = el('time', { class: className, attrs: { datetime: date.toISOString() } });\n const day = el('span', { class: 'aparte-score__day' });\n const hour = el('span', { class: 'aparte-score__hour' });\n ctx.bind(day, () => dayText(ctx.config, date, now));\n ctx.bind(hour, () => formatHour(ctx.config, date));\n node.append(day, hour);\n return node;\n}\n\n/** The middle of the board: the score, else the kick-off, else a dash, with the status under it. */\nfunction centreOf(ctx: CardContext, match: Match, now: Date): HTMLElement {\n const centre = el('div', { class: 'aparte-score__centre' });\n const phase = phaseOf(match);\n if (showsScore(match)) {\n const result = el('div', { class: 'aparte-score__result', attrs: { 'aria-hidden': 'true' } },\n numberOf(ctx, match.home.score!, 'aparte-score__num', { 'data-lead': leadOf(match, 'home') }),\n el('span', { class: 'aparte-score__sep', text: '–' }),\n numberOf(ctx, match.away.score!, 'aparte-score__num', { 'data-lead': leadOf(match, 'away') }));\n // The numbers are drawn for the eye between the two crests; a reader hears who has which.\n const said = el('span', { class: 'aparte-score__sr' });\n ctx.bind(said, () => `${match.home.name} ${formatNumber(ctx.config, match.home.score!)}, ${match.away.name} ${formatNumber(ctx.config, match.away.score!)}`);\n centre.append(result, said);\n } else if (match.startTime) {\n centre.append(kickoffOf(ctx, match.startTime, now, 'aparte-score__kickoff'));\n } else {\n centre.append(el('div', { class: 'aparte-score__result', attrs: { 'aria-hidden': 'true' } }, el('span', { class: 'aparte-score__sep', text: '–' })));\n }\n const pill = pillOf(ctx, match);\n if (pill) centre.append(pill);\n else if (phase === 'scheduled' && !match.startTime) {\n const upcoming = el('span', { class: 'aparte-score__pill', attrs: { 'data-phase': 'scheduled' } });\n ctx.word(upcoming, 'cardsScoreUpcoming', S.cardsScoreUpcoming);\n centre.append(upcoming);\n }\n return centre;\n}\n\nfunction teamOf(match: Match, key: MatchSide): HTMLElement {\n const team = match[key];\n return el('div', { class: `aparte-score__team aparte-score__team--${key}`, attrs: { 'data-lead': leadOf(match, key) } },\n crestOf(team, 'lg'),\n el('span', { class: 'aparte-score__team-name', text: team.name }),\n team.record ? el('span', { class: 'aparte-score__record', text: team.record }) : null);\n}\n\n/** The competition and the round over the board, and the day of a match that is not still to come. */\nfunction headOf(ctx: CardContext, match: Match, now: Date): HTMLElement | null {\n const parts: HTMLElement[] = [];\n if (match.competition) parts.push(el('span', { class: 'aparte-score__competition', text: match.competition }));\n if (match.round) parts.push(el('span', { class: 'aparte-score__round', text: match.round }));\n else if (match.matchday !== undefined) {\n const day = match.matchday;\n const round = el('span', { class: 'aparte-score__round' });\n ctx.bind(round, () => word(ctx.config, 'cardsScoreMatchday', S.cardsScoreMatchday, { n: formatNumber(ctx.config, day) }));\n parts.push(round);\n }\n // A scheduled match says its day in the middle of the board; any other says it here.\n const date = match.startTime && showsScore(match) ? match.startTime : undefined;\n if (!parts.length && !date) return null;\n const line = el('div', { class: 'aparte-score__meta' });\n parts.forEach((part, i) => line.append(...(i ? [dot(), part] : [part])));\n let when: HTMLElement | null = null;\n if (date) {\n when = el('time', { class: 'aparte-score__date', attrs: { datetime: date.toISOString() } });\n ctx.bind(when, () => dayText(ctx.config, date, now));\n }\n return el('div', { class: 'aparte-score__head' },\n glyph(SPORT_GLYPHS[match.sport], 'aparte-rich-card__glyph aparte-score__sport'),\n line,\n when);\n}\n\n/** The venue, the broadcast, and the way to the match's page. */\nfunction footOf(ctx: CardContext, match: Match): HTMLElement | null {\n const facts = [\n match.venue ? el('span', { class: 'aparte-score__fact aparte-score__venue' }, glyph(PIN, 'aparte-rich-card__glyph aparte-score__fact-glyph'), el('span', { text: match.venue })) : null,\n match.broadcast ? el('span', { class: 'aparte-score__fact aparte-score__broadcast' }, glyph(TV, 'aparte-rich-card__glyph aparte-score__fact-glyph'), el('span', { text: match.broadcast })) : null,\n ].filter(notNull);\n let link: HTMLElement | null = null;\n if (match.url) {\n const text = el('span');\n ctx.word(text, 'cardsScoreDetails', S.cardsScoreDetails);\n link = el('a', { class: 'aparte-score__more', attrs: { href: match.url, target: '_blank', rel: 'noopener noreferrer' } },\n text, glyph(CHEVRON, 'aparte-rich-card__glyph aparte-score__chevron'));\n }\n if (!facts.length && !link) return null;\n return el('div', { class: 'aparte-score__foot' }, facts.length ? el('div', { class: 'aparte-score__facts' }, ...facts) : null, link);\n}\n\n/** The board: the two teams facing each other, the score between them. */\nfunction boardOf(ctx: CardContext, match: Match, now: Date): HTMLElement {\n return el('div', { class: 'aparte-score__board', attrs: { 'data-winner': match.winner } },\n teamOf(match, 'home'),\n centreOf(ctx, match, now),\n teamOf(match, 'away'));\n}\n\n/** The match's root, wearing both teams' colours for its band. */\nfunction matchRoot(match: Match, className: string, tag: 'article' | 'li' | 'div' = 'article'): HTMLElement {\n const node = el(tag, { class: className, attrs: { 'data-phase': phaseOf(match), 'data-sport': match.sport } });\n wear(node, '--aparte-score-home', match.home.color);\n wear(node, '--aparte-score-away', match.away.color);\n return node;\n}\n\n/** The `card` variant: the scoreboard. */\nfunction cardOf(ctx: CardContext, match: Match, now: Date): HTMLElement {\n const node = matchRoot(match, 'aparte-score aparte-score--card');\n node.append(...[headOf(ctx, match, now), boardOf(ctx, match, now), footOf(ctx, match)].filter(notNull));\n return node;\n}\n\n/** The score by period: periods as columns, the teams as rows, the total at the end. */\nfunction periodsOf(ctx: CardContext, match: Match): HTMLElement | null {\n const periods = match.periods;\n if (!periods) return null;\n const tennis = match.sport === 'tennis';\n const caption = el('caption', { class: 'aparte-score__sr' });\n ctx.word(caption, 'cardsScorePeriods', S.cardsScorePeriods);\n const team = el('span', { class: 'aparte-score__sr' });\n ctx.word(team, 'cardsScoreTeam', S.cardsScoreTeam);\n const corner = el('th', { class: 'aparte-score__corner', attrs: { scope: 'col' } }, team);\n const total = el('th', { class: 'aparte-score__total', attrs: { scope: 'col' } });\n ctx.word(total, tennis ? 'cardsScoreSets' : 'cardsScoreTotal', tennis ? S.cardsScoreSets : S.cardsScoreTotal);\n const head = el('tr', {}, corner, ...periods.map((p) => el('th', { attrs: { scope: 'col' }, text: p.label })), total);\n const row = (key: MatchSide) => {\n const other: MatchSide = key === 'home' ? 'away' : 'home';\n const team = match[key];\n const cells = periods.map((p) => {\n const value = p[key];\n // A set is won game by game: the side that took it is marked, as a tennis table does.\n const took = tennis && value !== undefined && p[other] !== undefined && value > p[other]!;\n const cell = el('td', { attrs: { 'data-lead': took ? 'win' : undefined } });\n if (value !== undefined) ctx.bind(cell, () => formatNumber(ctx.config, value));\n return cell;\n });\n const sum = el('td', { class: 'aparte-score__total' });\n if (team.score !== undefined) ctx.bind(sum, () => formatNumber(ctx.config, team.score!));\n return el('tr', { attrs: { 'data-lead': leadOf(match, key) } },\n // The cell stays a cell; the crest and the name line up in a box inside it.\n el('th', { class: 'aparte-score__row-team', attrs: { scope: 'row' } },\n el('span', { class: 'aparte-score__row-label' }, crestOf(team, 'sm'), el('span', { class: 'aparte-score__row-name', text: team.shortName ?? team.name }))),\n ...cells, sum);\n };\n const table = el('table', { class: 'aparte-score__periods' }, caption, el('thead', {}, head), el('tbody', {}, row('home'), row('away')));\n return el('div', { class: 'aparte-score__section aparte-score__table-wrap' }, table);\n}\n\n/**\n * The match's events, in order, each on the side of its team: the home team's at the start,\n * the away team's at the end, the minute between. On a narrow card they fall into one\n * column, and the team is written beside each instead — the side never says it alone: a\n * reader hears the team's name either way.\n */\nfunction eventsOf(ctx: CardContext, match: Match): HTMLElement | null {\n const events = match.events;\n if (!events) return null;\n const list = el('ol', { class: 'aparte-score__events' });\n ctx.bind(list, () => word(ctx.config, 'cardsScoreEvents', S.cardsScoreEvents), 'aria-label');\n for (const event of events) {\n const team = match[event.team];\n const type = el('span', { class: 'aparte-score__event-type' });\n ctx.word(type, EVENT_KEYS[event.type], EVENT_WORDS[event.type]);\n const marker = el('span', { class: 'aparte-score__event-team', attrs: { 'data-ink': team.color ? inkOn(team.color) : undefined }, text: team.shortName ?? team.name });\n wear(marker, '--aparte-score-team', team.color);\n const body = el('span', { class: 'aparte-score__event-body' },\n glyph(EVENT_GLYPHS[event.type], 'aparte-rich-card__glyph aparte-score__event-glyph'),\n el('span', { class: 'aparte-score__event-text' },\n event.player ? el('span', { class: 'aparte-score__player', text: event.player }) : null,\n type,\n event.detail ? el('span', { class: 'aparte-score__event-detail', text: event.detail }) : null),\n marker);\n list.append(el('li', { class: 'aparte-score__event', attrs: { 'data-team': event.team, 'data-type': event.type } },\n el('span', { class: 'aparte-score__minute', text: event.minute ?? '' }),\n body));\n }\n return el('div', { class: 'aparte-score__section aparte-score__timeline' }, list);\n}\n\n/** The `detail` variant: the board, then the score by period and the events. */\nfunction detailOf(ctx: CardContext, match: Match, now: Date): HTMLElement {\n const node = matchRoot(match, 'aparte-score aparte-score--detail');\n node.append(...[headOf(ctx, match, now), boardOf(ctx, match, now), periodsOf(ctx, match), eventsOf(ctx, match), footOf(ctx, match)].filter(notNull));\n return node;\n}\n\n/** The status column of a row: the live clock, the state, or the kick-off. */\nfunction whenOf(ctx: CardContext, match: Match, now: Date): HTMLElement {\n const box = el('div', { class: 'aparte-score__when' });\n const phase = phaseOf(match);\n if (phase === 'live') {\n const said = el('span', { class: 'aparte-score__live-word' });\n ctx.word(said, 'cardsScoreLive', S.cardsScoreLive);\n const clock = clockText(match);\n // With a clock the dot and the minute say it to the eye; the word stays for a reader.\n box.append(el('span', { class: 'aparte-score__live-dot', attrs: { 'aria-hidden': 'true' } }), clock ? el('span', { class: 'aparte-score__sr' }, said) : said);\n if (clock) box.append(el('span', { class: 'aparte-score__clock', text: clock }));\n } else if (phase === 'scheduled' || (phase === 'none' && !showsScore(match))) {\n if (match.startTime) box.append(kickoffOf(ctx, match.startTime, now, 'aparte-score__kickoff aparte-score__kickoff--row'));\n else ctx.word(box, 'cardsScoreUpcoming', S.cardsScoreUpcoming);\n } else {\n const said = statusText(ctx.config, match);\n if (said !== undefined) ctx.bind(box, () => statusText(ctx.config, match)!);\n else if (match.startTime) {\n const date = match.startTime;\n ctx.bind(box, () => dayText(ctx.config, date, now));\n }\n }\n box.setAttribute('data-phase', phase);\n return box;\n}\n\n/** One team's line in a row: crest, name, then its score at the end; the winner's in bold, with a mark. */\nfunction lineOf(ctx: CardContext, match: Match, key: MatchSide, withScore: boolean): HTMLElement {\n const team = match[key];\n const lead = leadOf(match, key);\n return el('div', { class: 'aparte-score__line', attrs: { 'data-lead': lead } },\n crestOf(team, 'sm'),\n el('span', { class: 'aparte-score__line-name', text: team.name }),\n withScore && team.score !== undefined ? numberOf(ctx, team.score, 'aparte-score__line-score') : null,\n // The winner is not told by weight alone: a mark points at the score, as the scoreboards do.\n el('span', { class: 'aparte-score__win-mark', attrs: { 'aria-hidden': 'true' }, text: lead === 'win' ? '◂' : '' }));\n}\n\n/** The `compact` variant's row: the status column, then the two teams stacked. */\nfunction rowOf(ctx: CardContext, match: Match, now: Date, tag: 'li' | 'div', withCompetition: boolean): HTMLElement {\n const node = matchRoot(match, 'aparte-score__row', tag);\n const scored = showsScore(match);\n const lines = el('div', { class: 'aparte-score__lines' },\n withCompetition && match.competition ? el('span', { class: 'aparte-score__row-meta', text: match.competition }) : null,\n lineOf(ctx, match, 'home', scored),\n lineOf(ctx, match, 'away', scored));\n node.append(whenOf(ctx, match, now), lines);\n if (match.url) {\n // The whole row is the link; its name is the match in one sentence.\n const link = el('a', { class: 'aparte-score__link', attrs: { href: match.url, target: '_blank', rel: 'noopener noreferrer' } });\n ctx.bind(link, () => matchSentence(ctx.config, match, now), 'aria-label');\n node.setAttribute('data-linked', '');\n node.append(link);\n }\n return node;\n}\n\nfunction countLabel(ctx: CardContext, data: Partial<ScoreData>): string {\n return data.title ?? commonCompetition(data.matches ?? []) ?? word(ctx.config, 'cardsScoreCount', S.cardsScoreCount, { n: formatNumber(ctx.config, data.matches?.length ?? 0) });\n}\n\n/** The competition every match shares, if they share one — the scoreboard's natural heading. */\nfunction commonCompetition(matches: Match[]): string | undefined {\n const first = matches[0]?.competition;\n return first && matches.every((m) => m.competition === first) ? first : undefined;\n}\n\n/** A scoreboard's heading: its sport's glyph and its name. */\nfunction headingOf(ctx: CardContext, data: ScoreData): HTMLElement {\n const text = el('span', { class: 'aparte-score__heading-text' });\n ctx.bind(text, () => countLabel(ctx, data));\n const sports = new Set(data.matches.map((m) => m.sport));\n const sport = sports.size === 1 ? [...sports][0]! : 'generic';\n return el('div', { class: 'aparte-score__heading' }, glyph(SPORT_GLYPHS[sport], 'aparte-rich-card__glyph aparte-score__sport'), text);\n}\n\nfunction render(data: ScoreData, ctx: CardContext<ScoreVariant>, settings: Settings): Node[] {\n const now = settings.now();\n const [first] = data.matches as [Match];\n if (data.matches.length > 1) {\n // Several matches are rows whatever the variant: see the module's comment.\n const shared = commonCompetition(data.matches) !== undefined || data.title !== undefined && data.matches.every((m) => !m.competition);\n const list = el('ul', { class: 'aparte-score__list', attrs: { role: 'list' } },\n ...data.matches.map((m) => rowOf(ctx, m, now, 'li', !shared)));\n ctx.bind(list, () => countLabel(ctx, data), 'aria-label');\n return [el('div', { class: 'aparte-score__board-list' }, headingOf(ctx, data), list)];\n }\n if (ctx.variant === 'compact') {\n const head = headOf(ctx, first, now);\n return [el('div', { class: 'aparte-score__single' }, head, rowOf(ctx, first, now, 'div', false))];\n }\n return [ctx.variant === 'detail' ? detailOf(ctx, first, now) : cardOf(ctx, first, now)];\n}\n\nfunction skeleton(partial: Partial<ScoreData> | null, ctx: CardContext<ScoreVariant>): Node[] {\n const block = (cls: string, kind: 'text' | 'rect' | 'circle' = 'rect') =>\n el('span', { class: `aparte-skeleton aparte-skeleton--${kind} ${cls}`, attrs: { 'aria-hidden': 'true' } });\n const known = partial?.matches?.[0];\n const name = (key: MatchSide, cls: string) => (known?.[key].name ? el('span', { class: cls, text: known[key].name }) : block(`${cls} aparte-score__sk-name`, 'text'));\n const head = partial?.title\n ? el('div', { class: 'aparte-score__heading' }, glyph(TROPHY, 'aparte-rich-card__glyph aparte-score__sport'), el('span', { class: 'aparte-score__heading-text', text: partial.title }))\n : el('div', { class: 'aparte-score__head' }, block('aparte-score__sk-meta', 'text'));\n if (ctx.variant === 'compact') {\n const line = (key: MatchSide) => el('div', { class: 'aparte-score__line' }, block('aparte-score__crest aparte-score__crest--sm', 'circle'), name(key, 'aparte-score__line-name'), block('aparte-score__sk-num'));\n return [el('div', { class: 'aparte-score__single' }, head,\n el('div', { class: 'aparte-score__row' }, el('div', { class: 'aparte-score__when' }, block('aparte-score__sk-when', 'text')),\n el('div', { class: 'aparte-score__lines' }, line('home'), line('away'))))];\n }\n const team = (key: MatchSide) => el('div', { class: `aparte-score__team aparte-score__team--${key}` },\n block('aparte-score__crest aparte-score__crest--lg', 'circle'), name(key, 'aparte-score__team-name'));\n const parts: HTMLElement[] = [head, el('div', { class: 'aparte-score__board' },\n team('home'),\n el('div', { class: 'aparte-score__centre' }, block('aparte-score__sk-score'), block('aparte-score__sk-pill')),\n team('away'))];\n if (ctx.variant === 'detail') {\n parts.push(el('div', { class: 'aparte-score__section aparte-score__sk-lines' }, ...[0, 1, 2, 3].map(() => block('aparte-score__sk-line', 'text'))));\n }\n return [el('article', { class: `aparte-score aparte-score--${ctx.variant}` }, ...parts)];\n}\n\nfunction label(data: Partial<ScoreData> | null, ctx: CardContext): string {\n const matches = data?.matches ?? [];\n if (matches.length === 1) {\n const [m] = matches as [Match];\n const names = [m.home.name, m.away.name].filter(Boolean);\n return names.length === 2 ? versus(ctx.config, m) : names[0] ?? word(ctx.config, 'cardsScoreTitle', S.cardsScoreTitle);\n }\n if (matches.length > 1 || data?.title) return countLabel(ctx, data!);\n return word(ctx.config, 'cardsScoreTitle', S.cardsScoreTitle);\n}\n\nfunction fallback(data: ScoreData, ctx: CardContext): string {\n const lines = data.matches.map((m) => matchSentence(ctx.config, m));\n return data.title ? `${data.title}:\\n${lines.join('\\n')}` : lines.join('\\n');\n}\n\n/** What a running call's input already says: the two teams, one team, or what was searched. */\nfunction partial(input: Record<string, unknown>): Partial<ScoreData> | null {\n const home = textOf(input['home'] ?? input['homeTeam'] ?? input['home_team'] ?? input['team'] ?? input['teamName'] ?? input['club']);\n const away = textOf(input['away'] ?? input['awayTeam'] ?? input['away_team'] ?? input['opponent']);\n if (home || away) return { matches: [{ home: { name: home ?? '' }, away: { name: away ?? '' }, sport: sportOf(input['sport']) ?? 'generic' }] };\n const query = str(input['query'] ?? input['q'] ?? input['search'] ?? input['competition'] ?? input['league']);\n return query ? { title: query } : null;\n}\n\nfunction createScoreCard(settings: Settings) {\n return defineCard<ScoreData, ScoreVariant>({\n name: 'score',\n variants: ['card', 'compact', 'detail'],\n styles: scoreStyles,\n icon: TROPHY,\n normalize: readMatches,\n render: (data, ctx) => render(data, ctx, settings),\n skeleton,\n label,\n fallback,\n partial,\n });\n}\n\n/**\n * The score card on the device's clock — for `scoreCard.segment(data)`. Plug it in with\n * `setupScoreCard`, which also hears the card's own option.\n */\nexport const scoreCard = createScoreCard({ now: () => new Date() });\n\n/** Draw a tool's matches as this card — returns the function that stops it. */\nexport function setupScoreCard(options: ScoreCardOptions = {}): () => void {\n const { now, ...rest } = options;\n return createScoreCard({ now: now ?? (() => new Date()) }).setup(rest);\n}\n"],"names":["name","side","label","team","partial"],"mappings":";AAUA,MAAM,MAAM,CAAC,SACT,mKAAmK,IAAI;AAG3K,MAAM,WAAW,IAAI,8KAA8K;AAEnM,MAAM,aAAa,IAAI,4HAA4H;AAEnJ,MAAM,SAAS,IAAI,4JAA4J;AAG/K,MAAM,QAAQ,IAAI,0HAA0H;AAE5I,MAAM,oBAAoB,IAAI,qIAAqI;AAGnK,MAAM,SAAS,IAAI,mGAAmG;AAEtH,MAAM,WAAW,IAAI,oMAAoM;AAGlN,MAAM,SAAS,IAAI,0JAA0J;AAG7K,MAAM,eAAe;AAAA,EACxB,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,qBAAqB;AAAA,EACrB,SAAS;AACb;AAGA,MAAM,OAAO;AAGb,MAAM,MAAM,IAAI,wFAAwF;AAGjG,MAAM,eAAe;AAAA,EACxB,MAAM;AAAA,EACN,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,KAAK;AACT;AAEO,MAAM,MAAM,IAAI,6GAA6G;AAE7H,MAAM,KAAK,IAAI,yFAAyF;AAExG,MAAM,UAAU,IAAI,4BAA4B;ACjEvD,MAAA,cAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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"}
@@ -0,0 +1,56 @@
1
+ const SVG = "http://www.w3.org/2000/svg";
2
+ function sparklinePath(values, { pad = 0.15, range } = {}) {
3
+ const finite = values.filter(Number.isFinite);
4
+ if (finite.length === 0) return { line: "", area: "", points: [] };
5
+ const series = finite.length === 1 ? [finite[0], finite[0]] : finite;
6
+ const lo = range ? range[0] : Math.min(...finite);
7
+ const hi = range ? range[1] : Math.max(...finite);
8
+ const span = hi - lo;
9
+ const h = 40;
10
+ const step = 100 / (series.length - 1);
11
+ const points = series.map((v, i) => [
12
+ i * step,
13
+ span === 0 ? h / 2 : h - (pad * h + (v - lo) / span * (h - 2 * pad * h))
14
+ ]);
15
+ let line = `M${points[0][0].toFixed(2)} ${points[0][1].toFixed(2)}`;
16
+ for (let i = 0; i < points.length - 1; i++) {
17
+ const p0 = points[i - 1] ?? points[i];
18
+ const p1 = points[i];
19
+ const p2 = points[i + 1];
20
+ const p3 = points[i + 2] ?? p2;
21
+ const c1 = [p1[0] + (p2[0] - p0[0]) / 6, p1[1] + (p2[1] - p0[1]) / 6];
22
+ const c2 = [p2[0] - (p3[0] - p1[0]) / 6, p2[1] - (p3[1] - p1[1]) / 6];
23
+ line += ` C${c1[0].toFixed(2)} ${c1[1].toFixed(2)} ${c2[0].toFixed(2)} ${c2[1].toFixed(2)} ${p2[0].toFixed(2)} ${p2[1].toFixed(2)}`;
24
+ }
25
+ const last = points[points.length - 1];
26
+ const area = `${line} L${last[0].toFixed(2)} ${h} L${points[0][0].toFixed(2)} ${h} Z`;
27
+ return { line, area, points };
28
+ }
29
+ function sparkline(values, options = {}) {
30
+ const svg = document.createElementNS(SVG, "svg");
31
+ svg.setAttribute("viewBox", "0 0 100 40");
32
+ svg.setAttribute("preserveAspectRatio", "none");
33
+ svg.setAttribute("aria-hidden", "true");
34
+ svg.setAttribute("focusable", "false");
35
+ svg.classList.add("aparte-rich-card__sparkline");
36
+ for (const name of options.className?.split(/\s+/) ?? []) if (name) svg.classList.add(name);
37
+ const { line, area } = sparklinePath(values, options);
38
+ if (!line) return svg;
39
+ if (options.area) {
40
+ const fill = document.createElementNS(SVG, "path");
41
+ fill.setAttribute("d", area);
42
+ fill.setAttribute("class", "aparte-rich-card__sparkline-area");
43
+ svg.append(fill);
44
+ }
45
+ const stroke = document.createElementNS(SVG, "path");
46
+ stroke.setAttribute("d", line);
47
+ stroke.setAttribute("class", "aparte-rich-card__sparkline-line");
48
+ stroke.setAttribute("vector-effect", "non-scaling-stroke");
49
+ svg.append(stroke);
50
+ return svg;
51
+ }
52
+ export {
53
+ sparklinePath as a,
54
+ sparkline as s
55
+ };
56
+ //# sourceMappingURL=sparkline-C-cA9obz.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sparkline-C-cA9obz.js","sources":["../src/kit/sparkline.ts"],"sourcesContent":["/**\n * A small line chart in SVG, with no dependency: the temperature over the next hours, a\n * price over a day. Built with `createElementNS` from numbers only, so a tool's values\n * never reach a parser. Stretched to its box (`preserveAspectRatio=\"none\"`), the stroke\n * kept at its width by `vector-effect`.\n */\nconst SVG = 'http://www.w3.org/2000/svg';\n\nexport interface SparklineOptions {\n /** Extra class on the `<svg>`. */\n className?: string;\n /** Fill the area under the line (a gradient from the stroke's colour, in the sheet). */\n area?: boolean;\n /** Padding above and below the line, as a share of the height (0.15 by default). */\n pad?: number;\n /** The value range to scale against, when several charts must share one. */\n range?: [number, number];\n}\n\n/** The points of a smooth line through `values`, in a 100 × 40 box. */\nexport function sparklinePath(values: number[], { pad = 0.15, range }: SparklineOptions = {}): { line: string; area: string; points: Array<[number, number]> } {\n // A gap (`null`, `NaN`) is left out: written into the path it would stop the drawing there.\n const finite = values.filter(Number.isFinite);\n if (finite.length === 0) return { line: '', area: '', points: [] };\n // One value is a level, drawn flat across the box: a single point would draw nothing.\n const series = finite.length === 1 ? [finite[0]!, finite[0]!] : finite;\n const lo = range ? range[0] : Math.min(...finite);\n const hi = range ? range[1] : Math.max(...finite);\n const span = hi - lo;\n const h = 40;\n const step = 100 / (series.length - 1);\n // A series that does not move is a flat line through the middle, not along the floor.\n const points = series.map((v, i): [number, number] => [\n i * step,\n span === 0 ? h / 2 : h - (pad * h + ((v - lo) / span) * (h - 2 * pad * h)),\n ]);\n // A Catmull-Rom curve through the points, written as cubic Béziers.\n let line = `M${points[0]![0].toFixed(2)} ${points[0]![1].toFixed(2)}`;\n for (let i = 0; i < points.length - 1; i++) {\n const p0 = points[i - 1] ?? points[i]!;\n const p1 = points[i]!;\n const p2 = points[i + 1]!;\n const p3 = points[i + 2] ?? p2;\n const c1: [number, number] = [p1[0] + (p2[0] - p0[0]) / 6, p1[1] + (p2[1] - p0[1]) / 6];\n const c2: [number, number] = [p2[0] - (p3[0] - p1[0]) / 6, p2[1] - (p3[1] - p1[1]) / 6];\n line += ` C${c1[0].toFixed(2)} ${c1[1].toFixed(2)} ${c2[0].toFixed(2)} ${c2[1].toFixed(2)} ${p2[0].toFixed(2)} ${p2[1].toFixed(2)}`;\n }\n const last = points[points.length - 1]!;\n const area = `${line} L${last[0].toFixed(2)} ${h} L${points[0]![0].toFixed(2)} ${h} Z`;\n return { line, area, points };\n}\n\n/** The chart as an `<svg>`; decorative (`aria-hidden`), so put the numbers in text beside it. */\nexport function sparkline(values: number[], options: SparklineOptions = {}): SVGSVGElement {\n const svg = document.createElementNS(SVG, 'svg');\n svg.setAttribute('viewBox', '0 0 100 40');\n svg.setAttribute('preserveAspectRatio', 'none');\n svg.setAttribute('aria-hidden', 'true');\n svg.setAttribute('focusable', 'false');\n svg.classList.add('aparte-rich-card__sparkline');\n // The caller's own class (its own prefix is its business), added beside ours.\n for (const name of options.className?.split(/\\s+/) ?? []) if (name) svg.classList.add(name);\n const { line, area } = sparklinePath(values, options);\n if (!line) return svg;\n if (options.area) {\n const fill = document.createElementNS(SVG, 'path');\n fill.setAttribute('d', area);\n fill.setAttribute('class', 'aparte-rich-card__sparkline-area');\n svg.append(fill);\n }\n const stroke = document.createElementNS(SVG, 'path');\n stroke.setAttribute('d', line);\n stroke.setAttribute('class', 'aparte-rich-card__sparkline-line');\n stroke.setAttribute('vector-effect', 'non-scaling-stroke');\n svg.append(stroke);\n return svg;\n}\n"],"names":[],"mappings":"AAMA,MAAM,MAAM;AAcL,SAAS,cAAc,QAAkB,EAAE,MAAM,MAAM,MAAA,IAA4B,IAAqE;AAE3J,QAAM,SAAS,OAAO,OAAO,OAAO,QAAQ;AAC5C,MAAI,OAAO,WAAW,EAAG,QAAO,EAAE,MAAM,IAAI,MAAM,IAAI,QAAQ,GAAC;AAE/D,QAAM,SAAS,OAAO,WAAW,IAAI,CAAC,OAAO,CAAC,GAAI,OAAO,CAAC,CAAE,IAAI;AAChE,QAAM,KAAK,QAAQ,MAAM,CAAC,IAAI,KAAK,IAAI,GAAG,MAAM;AAChD,QAAM,KAAK,QAAQ,MAAM,CAAC,IAAI,KAAK,IAAI,GAAG,MAAM;AAChD,QAAM,OAAO,KAAK;AAClB,QAAM,IAAI;AACV,QAAM,OAAO,OAAO,OAAO,SAAS;AAEpC,QAAM,SAAS,OAAO,IAAI,CAAC,GAAG,MAAwB;AAAA,IAClD,IAAI;AAAA,IACJ,SAAS,IAAI,IAAI,IAAI,KAAK,MAAM,KAAM,IAAI,MAAM,QAAS,IAAI,IAAI,MAAM;AAAA,EAAA,CAC1E;AAED,MAAI,OAAO,IAAI,OAAO,CAAC,EAAG,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,OAAO,CAAC,EAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;AACnE,WAAS,IAAI,GAAG,IAAI,OAAO,SAAS,GAAG,KAAK;AACxC,UAAM,KAAK,OAAO,IAAI,CAAC,KAAK,OAAO,CAAC;AACpC,UAAM,KAAK,OAAO,CAAC;AACnB,UAAM,KAAK,OAAO,IAAI,CAAC;AACvB,UAAM,KAAK,OAAO,IAAI,CAAC,KAAK;AAC5B,UAAM,KAAuB,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC;AACtF,UAAM,KAAuB,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC;AACtF,YAAQ,KAAK,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,EACrI;AACA,QAAM,OAAO,OAAO,OAAO,SAAS,CAAC;AACrC,QAAM,OAAO,GAAG,IAAI,KAAK,KAAK,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,EAAG,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC;AAClF,SAAO,EAAE,MAAM,MAAM,OAAA;AACzB;AAGO,SAAS,UAAU,QAAkB,UAA4B,IAAmB;AACvF,QAAM,MAAM,SAAS,gBAAgB,KAAK,KAAK;AAC/C,MAAI,aAAa,WAAW,YAAY;AACxC,MAAI,aAAa,uBAAuB,MAAM;AAC9C,MAAI,aAAa,eAAe,MAAM;AACtC,MAAI,aAAa,aAAa,OAAO;AACrC,MAAI,UAAU,IAAI,6BAA6B;AAE/C,aAAW,QAAQ,QAAQ,WAAW,MAAM,KAAK,KAAK,CAAA,EAAI,KAAI,KAAM,KAAI,UAAU,IAAI,IAAI;AAC1F,QAAM,EAAE,MAAM,KAAA,IAAS,cAAc,QAAQ,OAAO;AACpD,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,QAAQ,MAAM;AACd,UAAM,OAAO,SAAS,gBAAgB,KAAK,MAAM;AACjD,SAAK,aAAa,KAAK,IAAI;AAC3B,SAAK,aAAa,SAAS,kCAAkC;AAC7D,QAAI,OAAO,IAAI;AAAA,EACnB;AACA,QAAM,SAAS,SAAS,gBAAgB,KAAK,MAAM;AACnD,SAAO,aAAa,KAAK,IAAI;AAC7B,SAAO,aAAa,SAAS,kCAAkC;AAC/D,SAAO,aAAa,iBAAiB,oBAAoB;AACzD,MAAI,OAAO,MAAM;AACjB,SAAO;AACX;"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The stats card's glyphs: the six a figure may wear beside its label, and the card's own
3
+ * for its one-line states.
4
+ *
5
+ * Drawn on a 24 × 24 grid in `currentColor` strokes, so the sheet colours them through
6
+ * `color` and a theme follows. Constants of this package — the only markup the card parses.
7
+ */
8
+ /** The glyphs a figure may name in its `icon`. */
9
+ export declare const STAT_ICONS: {
10
+ readonly money: string;
11
+ readonly users: string;
12
+ readonly cart: string;
13
+ readonly chart: string;
14
+ readonly clock: string;
15
+ readonly star: string;
16
+ };
17
+ /** Three bars of rising height: the card's own glyph, for its one-line states. */
18
+ export declare const BARS: string;
19
+ //# sourceMappingURL=icons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../src/stats/icons.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAuBH,kDAAkD;AAClD,eAAO,MAAM,UAAU;;;;;;;CAA8F,CAAC;AAEtH,kFAAkF;AAClF,eAAO,MAAM,IAAI,QAAgG,CAAC"}