@sensiblestats/widget-react 0.3.0 → 0.5.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.
package/dist/index.d.ts CHANGED
@@ -33,6 +33,6 @@ type StatsWidgetProps = {
33
33
  };
34
34
  declare function StatsWidget(props: StatsWidgetProps): JSX.Element | null;
35
35
 
36
- declare const WIDGET_CSS = ".ss-w-root { all: revert; }\n.ss-w-root, .ss-w-root * { box-sizing: border-box; margin: 0; padding: 0; }\n.ss-w-root {\n --ss-w-accent: #17936a;\n --ss-w-ink: #14181d; --ss-w-faint: #6b7580; --ss-w-line: #e4e8ec;\n --ss-w-panel: #ffffff; --ss-w-bubble: #f3f5f7; --ss-w-nav: #0e1622;\n --ss-w-radius: 16px; --ss-w-offset-x: 20px; --ss-w-offset-y: 20px;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;\n font-size: 13px; line-height: 1.5; color: var(--ss-w-ink);\n}\n@media (prefers-color-scheme: dark) {\n .ss-w-root[data-ss-w-theme=\"auto\"] {\n --ss-w-accent: #37c891; --ss-w-ink: #e8edf2; --ss-w-faint: #8b95a1;\n --ss-w-line: #2a3441; --ss-w-panel: #141b24; --ss-w-bubble: #1e2732; --ss-w-nav: #0a0f16;\n }\n}\n.ss-w-root[data-ss-w-theme=\"dark\"] {\n --ss-w-accent: #37c891; --ss-w-ink: #e8edf2; --ss-w-faint: #8b95a1;\n --ss-w-line: #2a3441; --ss-w-panel: #141b24; --ss-w-bubble: #1e2732; --ss-w-nav: #0a0f16;\n}\n.ss-w-root[data-ss-w-theme=\"light\"] {\n --ss-w-accent: #17936a; --ss-w-ink: #14181d; --ss-w-faint: #6b7580;\n --ss-w-line: #e4e8ec; --ss-w-panel: #ffffff; --ss-w-bubble: #f3f5f7; --ss-w-nav: #0e1622;\n}\n\n/* launcher */\n.ss-w-fab-wrap { position: fixed; bottom: var(--ss-w-offset-y); z-index: 2147483000; display: flex; flex-direction: column; align-items: flex-end; gap: 10px; }\n.ss-w-root[data-ss-w-pos=\"right\"] .ss-w-fab-wrap { right: var(--ss-w-offset-x); }\n.ss-w-root[data-ss-w-pos=\"left\"] .ss-w-fab-wrap { left: var(--ss-w-offset-x); align-items: flex-start; }\n.ss-w-fab { width: 56px; height: 56px; border: none; border-radius: 50%; background: var(--ss-w-nav); color: #fff; cursor: pointer; display: grid; place-items: center; box-shadow: 0 6px 20px rgba(0,0,0,.28); }\n.ss-w-fab-mark { width: 30px; height: 30px; display: block; }\n.ss-w-greeting { max-width: 240px; display: flex; align-items: flex-start; background: var(--ss-w-panel); color: var(--ss-w-ink); border: 1px solid var(--ss-w-line); border-radius: 12px; box-shadow: 0 4px 14px rgba(0,0,0,.14); }\n.ss-w-greeting-body { flex: 1; min-width: 0; text-align: left; background: none; border: none; color: inherit; font: inherit; cursor: pointer; padding: 9px 4px 9px 12px; }\n.ss-w-greeting-x { flex: none; background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 17px; line-height: 1; padding: 7px 9px 0 2px; }\n\n/* panel */\n.ss-w-panel { position: fixed; bottom: calc(var(--ss-w-offset-y) + 72px); z-index: 2147483000; display: flex; flex-direction: column; width: min(400px, calc(100vw - 40px)); height: min(620px, calc(100vh - 120px)); background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: var(--ss-w-radius); overflow: hidden; box-shadow: 0 12px 40px rgba(0,0,0,.24); }\n.ss-w-root[data-ss-w-pos=\"right\"] .ss-w-panel { right: var(--ss-w-offset-x); }\n.ss-w-root[data-ss-w-pos=\"left\"] .ss-w-panel { left: var(--ss-w-offset-x); }\n@media (max-width: 639px) {\n /* Fill via inset with no explicit height (like the site's working panel) so the\n input stays visible when the mobile keyboard/URL-bar shrinks the viewport. The\n position-specific selectors override the right/left offsets set above. */\n .ss-w-root[data-ss-w-pos=\"right\"] .ss-w-panel,\n .ss-w-root[data-ss-w-pos=\"left\"] .ss-w-panel { inset: 0; width: auto; height: auto; border: none; border-radius: 0; }\n}\n.ss-w-header { display: flex; align-items: center; gap: 8px; padding: 12px 14px; border-bottom: 1px solid var(--ss-w-line); }\n.ss-w-header-mark { width: 18px; height: 18px; display: block; }\n.ss-w-header-title { font-weight: 660; }\n.ss-w-close { margin-left: auto; background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 16px; display: grid; place-items: center; }\n\n/* messages */\n.ss-w-list { flex: 1; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 12px; }\n.ss-w-msg { display: flex; }\n.ss-w-user { justify-content: flex-end; }\n.ss-w-user .ss-w-bubble { background: color-mix(in srgb, var(--ss-w-accent) 14%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 30%, var(--ss-w-line)); border-radius: 14px; padding: 8px 12px; max-width: 80%; }\n.ss-w-bot { flex-direction: column; gap: 8px; }\n.ss-w-status { font-size: 11px; color: var(--ss-w-faint); font-style: italic; }\n.ss-w-error { display: flex; align-items: center; gap: 8px; font-size: 12px; color: #c0392b; }\n.ss-w-retry { background: none; border: 1px solid currentColor; border-radius: 10px; padding: 2px 8px; cursor: pointer; color: inherit; }\n\n/* markdown */\n.ss-w-md { display: flex; flex-direction: column; gap: 8px; }\n.ss-w-md :where(p, ul, ol, table, pre, blockquote, h1, h2, h3, h4) { margin: 0; }\n.ss-w-md > *:first-child { margin-top: 0; }\n.ss-w-md > *:last-child { margin-bottom: 0; }\n.ss-w-md-ul { list-style: disc outside; padding-left: 18px; }\n.ss-w-md-ol { list-style: decimal outside; padding-left: 18px; }\n.ss-w-md-ul li::marker, .ss-w-md-ol li::marker { color: var(--ss-w-accent); }\n.ss-w-md-link { color: var(--ss-w-accent); text-decoration: underline; }\n.ss-w-table-wrap { overflow-x: auto; max-width: 100%; -webkit-overflow-scrolling: touch; }\n.ss-w-md-table { border-collapse: collapse; width: max-content; min-width: 100%; font-variant-numeric: tabular-nums; }\n.ss-w-md-table td, .ss-w-md-table th { border: 1px solid var(--ss-w-line); padding: 4px 8px; text-align: left; white-space: nowrap; }\n.ss-w-md-table th { background: color-mix(in srgb, var(--ss-w-accent) 12%, var(--ss-w-panel)); font-weight: 700; }\n.ss-w-md-table tbody tr:nth-child(even) { background: var(--ss-w-bubble); }\n.ss-w-md-code { background: var(--ss-w-bubble); border-radius: 5px; padding: 1px 5px; font-family: ui-monospace, monospace; }\n\n/* entity cards */\n.ss-w-cards { display: flex; flex-direction: column; gap: 7px; }\n.ss-w-ecard { display: flex; align-items: center; gap: 11px; width: 100%; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 8px 11px; text-align: left; }\n.ss-w-thumb { width: 40px; height: 40px; flex: none; border-radius: 50%; display: grid; place-items: center; font-size: 13px; font-weight: 700; color: #fff; background-color: var(--ss-w-nav); background-size: cover; background-position: center; }\n.ss-w-thumb.ss-w-team { border-radius: 10px; }\n.ss-w-ecard[data-kind=\"player\"] .ss-w-thumb { background-color: var(--ss-w-accent); }\n.ss-w-meta { display: flex; flex-direction: column; min-width: 0; }\n.ss-w-kind { font-size: 8.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--ss-w-faint); line-height: 1.3; }\n.ss-w-nm { font-weight: 660; }\n.ss-w-sub { font-size: 11px; color: var(--ss-w-faint); }\n.ss-w-stat { margin-left: auto; text-align: center; }\n.ss-w-stat b { display: block; font-variant-numeric: tabular-nums; }\n.ss-w-stat span { font-size: 9px; text-transform: uppercase; color: var(--ss-w-faint); }\n.ss-w-cards-more { align-self: flex-start; font-size: 11.5px; font-weight: 560; color: var(--ss-w-accent); background: none; border: none; cursor: pointer; padding: 3px 2px; }\n.ss-w-cards-more:hover:not(:disabled) { text-decoration: underline; }\n.ss-w-cards-more:disabled { opacity: .5; cursor: default; }\n\n/* action buttons */\n.ss-w-actions { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }\n.ss-w-abtn { font-size: 12px; font-weight: 560; color: var(--ss-w-accent); background: var(--ss-w-panel); border: 1px solid var(--ss-w-accent); border-radius: 16px; padding: 6px 12px; cursor: pointer; }\n.ss-w-abtn:disabled { opacity: .5; cursor: default; }\n.ss-w-abtn-shimmer { width: 140px; height: 30px; border-radius: 16px; background: linear-gradient(90deg, var(--ss-w-bubble), var(--ss-w-line), var(--ss-w-bubble)); background-size: 200% 100%; animation: ss-w-shimmer 1.2s infinite; }\n@keyframes ss-w-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }\n\n/* intent chips */\n.ss-w-chips { display: flex; flex-wrap: wrap; gap: 6px; }\n.ss-w-chip { font-size: 11.5px; font-weight: 550; color: var(--ss-w-ink); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 14px; padding: 5px 11px; cursor: pointer; }\n\n/* input */\n.ss-w-input { display: flex; align-items: flex-end; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--ss-w-line); }\n.ss-w-textarea { flex: 1; resize: none; border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 8px 10px; font: inherit; color: inherit; background: var(--ss-w-panel); max-height: 96px; }\n.ss-w-textarea:disabled { opacity: .55; cursor: not-allowed; }\n/* iOS Safari zooms the page when a focused field's font-size is < 16px. Bump it\n on touch devices only, so the desktop 13px design is unchanged. */\n@media (pointer: coarse) {\n .ss-w-textarea { font-size: 16px; }\n}\n.ss-w-send { width: 36px; height: 36px; flex: none; border: none; border-radius: 50%; background: var(--ss-w-accent); color: #fff; cursor: pointer; display: grid; place-items: center; font-size: 16px; }\n.ss-w-stop-glyph { width: 11px; height: 11px; background: currentColor; border-radius: 2px; }\n\n@media (prefers-reduced-motion: reduce) {\n .ss-w-abtn-shimmer { animation: none; }\n}\n";
36
+ declare const WIDGET_CSS = ".ss-w-root { all: revert; }\n.ss-w-root, .ss-w-root * { box-sizing: border-box; margin: 0; padding: 0; }\n.ss-w-root {\n --ss-w-accent: #17936a;\n --ss-w-ink: #14181d; --ss-w-faint: #6b7580; --ss-w-line: #e4e8ec;\n --ss-w-panel: #ffffff; --ss-w-bubble: #f3f5f7; --ss-w-nav: #0e1622;\n --ss-w-radius: 16px; --ss-w-offset-x: 20px; --ss-w-offset-y: 20px;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;\n font-size: 13px; line-height: 1.5; color: var(--ss-w-ink);\n}\n@media (prefers-color-scheme: dark) {\n .ss-w-root[data-ss-w-theme=\"auto\"] {\n --ss-w-accent: #37c891; --ss-w-ink: #e8edf2; --ss-w-faint: #8b95a1;\n --ss-w-line: #2a3441; --ss-w-panel: #141b24; --ss-w-bubble: #1e2732; --ss-w-nav: #0a0f16;\n }\n}\n.ss-w-root[data-ss-w-theme=\"dark\"] {\n --ss-w-accent: #37c891; --ss-w-ink: #e8edf2; --ss-w-faint: #8b95a1;\n --ss-w-line: #2a3441; --ss-w-panel: #141b24; --ss-w-bubble: #1e2732; --ss-w-nav: #0a0f16;\n}\n.ss-w-root[data-ss-w-theme=\"light\"] {\n --ss-w-accent: #17936a; --ss-w-ink: #14181d; --ss-w-faint: #6b7580;\n --ss-w-line: #e4e8ec; --ss-w-panel: #ffffff; --ss-w-bubble: #f3f5f7; --ss-w-nav: #0e1622;\n}\n\n/* launcher */\n.ss-w-fab-wrap { position: fixed; bottom: var(--ss-w-offset-y); z-index: 2147483000; display: flex; flex-direction: column; align-items: flex-end; gap: 10px; }\n.ss-w-root[data-ss-w-pos=\"right\"] .ss-w-fab-wrap { right: var(--ss-w-offset-x); }\n.ss-w-root[data-ss-w-pos=\"left\"] .ss-w-fab-wrap { left: var(--ss-w-offset-x); align-items: flex-start; }\n.ss-w-fab { width: 56px; height: 56px; border: none; border-radius: 50%; background: var(--ss-w-nav); color: #fff; cursor: pointer; display: grid; place-items: center; box-shadow: 0 6px 20px rgba(0,0,0,.28); }\n.ss-w-fab-mark { width: 30px; height: 30px; display: block; }\n.ss-w-greeting { max-width: 240px; display: flex; align-items: flex-start; background: var(--ss-w-panel); color: var(--ss-w-ink); border: 1px solid var(--ss-w-line); border-radius: 12px; box-shadow: 0 4px 14px rgba(0,0,0,.14); }\n.ss-w-greeting-body { flex: 1; min-width: 0; text-align: left; background: none; border: none; color: inherit; font: inherit; cursor: pointer; padding: 9px 4px 9px 12px; }\n.ss-w-greeting-x { flex: none; background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 17px; line-height: 1; padding: 7px 9px 0 2px; }\n\n/* panel */\n.ss-w-panel { position: fixed; bottom: calc(var(--ss-w-offset-y) + 72px); z-index: 2147483000; display: flex; flex-direction: column; width: min(400px, calc(100vw - 40px)); height: min(620px, calc(100vh - 120px)); background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: var(--ss-w-radius); overflow: hidden; box-shadow: 0 12px 40px rgba(0,0,0,.24); }\n.ss-w-root[data-ss-w-pos=\"right\"] .ss-w-panel { right: var(--ss-w-offset-x); }\n.ss-w-root[data-ss-w-pos=\"left\"] .ss-w-panel { left: var(--ss-w-offset-x); }\n@media (max-width: 639px) {\n /* Fill via inset with no explicit height (like the site's working panel) so the\n input stays visible when the mobile keyboard/URL-bar shrinks the viewport. The\n position-specific selectors override the right/left offsets set above. */\n .ss-w-root[data-ss-w-pos=\"right\"] .ss-w-panel,\n .ss-w-root[data-ss-w-pos=\"left\"] .ss-w-panel { inset: 0; width: auto; height: auto; border: none; border-radius: 0; }\n}\n.ss-w-header { display: flex; align-items: center; gap: 8px; padding: 12px 14px; border-bottom: 1px solid var(--ss-w-line); }\n.ss-w-header-mark { width: 18px; height: 18px; display: block; }\n.ss-w-header-title { font-weight: 660; }\n.ss-w-close { margin-left: auto; background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 16px; display: grid; place-items: center; }\n\n/* messages */\n.ss-w-list { flex: 1; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 12px; }\n.ss-w-msg { display: flex; }\n.ss-w-user { justify-content: flex-end; }\n.ss-w-user .ss-w-bubble { background: color-mix(in srgb, var(--ss-w-accent) 14%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 30%, var(--ss-w-line)); border-radius: 14px; padding: 8px 12px; max-width: 80%; }\n.ss-w-bot { flex-direction: column; gap: 8px; }\n.ss-w-status { font-size: 11px; color: var(--ss-w-faint); font-style: italic; }\n.ss-w-error { display: flex; align-items: center; gap: 8px; font-size: 12px; color: #c0392b; }\n.ss-w-retry { background: none; border: 1px solid currentColor; border-radius: 10px; padding: 2px 8px; cursor: pointer; color: inherit; }\n\n/* markdown */\n.ss-w-md { display: flex; flex-direction: column; gap: 8px; }\n.ss-w-md :where(p, ul, ol, table, pre, blockquote, h1, h2, h3, h4) { margin: 0; }\n.ss-w-md > *:first-child { margin-top: 0; }\n.ss-w-md > *:last-child { margin-bottom: 0; }\n.ss-w-md-ul { list-style: disc outside; padding-left: 18px; }\n.ss-w-md-ol { list-style: decimal outside; padding-left: 18px; }\n.ss-w-md-ul li::marker, .ss-w-md-ol li::marker { color: var(--ss-w-accent); }\n.ss-w-md-link { color: var(--ss-w-accent); text-decoration: underline; }\n.ss-w-table-wrap { overflow-x: auto; max-width: 100%; -webkit-overflow-scrolling: touch; }\n.ss-w-md-table { border-collapse: collapse; width: max-content; min-width: 100%; font-variant-numeric: tabular-nums; }\n.ss-w-md-table td, .ss-w-md-table th { border: 1px solid var(--ss-w-line); padding: 4px 8px; text-align: left; white-space: nowrap; }\n.ss-w-md-table th { background: color-mix(in srgb, var(--ss-w-accent) 12%, var(--ss-w-panel)); font-weight: 700; }\n.ss-w-md-table tbody tr:nth-child(even) { background: var(--ss-w-bubble); }\n.ss-w-md-code { background: var(--ss-w-bubble); border-radius: 5px; padding: 1px 5px; font-family: ui-monospace, monospace; }\n\n/* entity cards */\n.ss-w-cards { display: flex; flex-direction: column; gap: 7px; }\n.ss-w-ecard { display: flex; align-items: center; gap: 11px; width: 100%; background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 8px 11px; text-align: left; }\n.ss-w-thumb { width: 40px; height: 40px; flex: none; border-radius: 50%; display: grid; place-items: center; font-size: 13px; font-weight: 700; color: #fff; background-color: var(--ss-w-nav); background-size: cover; background-position: center; }\n.ss-w-thumb.ss-w-team { border-radius: 10px; }\n.ss-w-ecard[data-kind=\"player\"] .ss-w-thumb { background-color: var(--ss-w-accent); }\n.ss-w-meta { display: flex; flex-direction: column; min-width: 0; }\n.ss-w-kind { font-size: 8.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--ss-w-faint); line-height: 1.3; }\n.ss-w-nm { font-weight: 660; }\n.ss-w-sub { font-size: 11px; color: var(--ss-w-faint); }\n.ss-w-stat { margin-left: auto; text-align: center; }\n.ss-w-stat b { display: block; font-variant-numeric: tabular-nums; }\n.ss-w-stat span { font-size: 9px; text-transform: uppercase; color: var(--ss-w-faint); }\n.ss-w-cards-more { align-self: flex-start; font-size: 11.5px; font-weight: 560; color: var(--ss-w-accent); background: none; border: none; cursor: pointer; padding: 3px 2px; }\n.ss-w-cards-more:hover:not(:disabled) { text-decoration: underline; }\n.ss-w-cards-more:disabled { opacity: .5; cursor: default; }\n\n/* betting insights */\n.ss-w-binsights { display: flex; flex-direction: column; gap: 7px; }\n.ss-w-binsight { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); padding: 9px 11px; display: flex; flex-direction: column; gap: 6px; }\n.ss-w-bi-status { display: flex; align-items: center; gap: 6px; min-width: 0; }\n.ss-w-bi-fixture { font-size: 11px; color: var(--ss-w-ink); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.ss-w-bi-live { font-size: 8.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: #fff; background: #c0392b; border-radius: 4px; padding: 1px 5px; display: inline-flex; align-items: center; gap: 4px; flex: none; }\n.ss-w-bi-live-dot { width: 5px; height: 5px; border-radius: 50%; background: #fff; }\n.ss-w-bi-head { display: flex; align-items: flex-start; gap: 10px; }\n.ss-w-bi-mkt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }\n.ss-w-bi-market { font-size: 13px; font-weight: 660; line-height: 1.3; color: var(--ss-w-ink); }\n.ss-w-bi-sel { font-size: 11px; line-height: 1.3; color: var(--ss-w-faint); }\n.ss-w-bi-odds { margin-left: auto; flex: none; display: flex; flex-direction: column; align-items: center; justify-content: center; background: color-mix(in srgb, var(--ss-w-accent) 12%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 24%, var(--ss-w-line)); border-radius: 8px; padding: 3px 9px; min-width: 56px; }\n.ss-w-bi-odds-cap { font-size: 8px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--ss-w-faint); }\n.ss-w-bi-odds b { font-size: 15px; font-family: ui-monospace, monospace; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ss-w-accent); line-height: 1.15; }\n.ss-w-bi-book { font-size: 9.5px; color: var(--ss-w-faint); }\n.ss-w-bi-text { font-size: 12px; color: var(--ss-w-ink); }\n.ss-w-bi-rows { display: flex; flex-direction: column; }\n.ss-w-bi-row { display: flex; align-items: baseline; gap: 8px; padding: 4px 0; border-top: 1px solid var(--ss-w-line); }\n.ss-w-bi-row:first-child { border-top: none; }\n.ss-w-bi-row-lbl { font-size: 11px; color: var(--ss-w-faint); min-width: 0; }\n.ss-w-bi-row-dots { flex: 1; border-bottom: 1px dotted var(--ss-w-line); transform: translateY(-3px); min-width: 12px; }\n.ss-w-bi-row-num { font-family: ui-monospace, monospace; font-weight: 700; font-variant-numeric: tabular-nums; font-size: 12.5px; flex: none; color: var(--ss-w-ink); }\n.ss-w-bi-more { align-self: flex-start; background: none; border: none; color: var(--ss-w-accent); font: inherit; font-size: 11px; font-weight: 560; padding: 2px 0; cursor: pointer; }\n.ss-w-bi-more:hover { text-decoration: underline; }\n.ss-w-bi-disc { font-size: 10px; font-style: italic; color: var(--ss-w-faint); }\n.ss-w-bi-scoped { display: flex; flex-direction: column; gap: 6px; }\n.ss-w-bi-scopes { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }\n.ss-w-bi-chip { font-size: 11px; font-weight: 550; border: 1px solid var(--ss-w-line); border-radius: 14px; padding: 3px 10px; color: var(--ss-w-ink); background: var(--ss-w-bubble); cursor: pointer; }\n.ss-w-bi-chip[aria-pressed=\"true\"] { color: #fff; background: var(--ss-w-accent); border-color: var(--ss-w-accent); }\n\n/* action buttons */\n.ss-w-actions { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }\n.ss-w-abtn { font-size: 12px; font-weight: 560; color: var(--ss-w-accent); background: var(--ss-w-panel); border: 1px solid var(--ss-w-accent); border-radius: 16px; padding: 6px 12px; cursor: pointer; }\n.ss-w-abtn:disabled { opacity: .5; cursor: default; }\n.ss-w-abtn-shimmer { width: 140px; height: 30px; border-radius: 16px; background: linear-gradient(90deg, var(--ss-w-bubble), var(--ss-w-line), var(--ss-w-bubble)); background-size: 200% 100%; animation: ss-w-shimmer 1.2s infinite; }\n@keyframes ss-w-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }\n\n/* intent chips */\n.ss-w-chips { display: flex; flex-wrap: wrap; gap: 6px; }\n.ss-w-chip { font-size: 11.5px; font-weight: 550; color: var(--ss-w-ink); background: var(--ss-w-bubble); border: 1px solid var(--ss-w-line); border-radius: 14px; padding: 5px 11px; cursor: pointer; }\n\n/* input */\n.ss-w-input { display: flex; align-items: flex-end; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--ss-w-line); }\n.ss-w-textarea { flex: 1; resize: none; border: 1px solid var(--ss-w-line); border-radius: 12px; padding: 8px 10px; font: inherit; color: inherit; background: var(--ss-w-panel); max-height: 96px; }\n.ss-w-textarea:disabled { opacity: .55; cursor: not-allowed; }\n/* iOS Safari zooms the page when a focused field's font-size is < 16px. Bump it\n on touch devices only, so the desktop 13px design is unchanged. */\n@media (pointer: coarse) {\n .ss-w-textarea { font-size: 16px; }\n}\n.ss-w-send { width: 36px; height: 36px; flex: none; border: none; border-radius: 50%; background: var(--ss-w-accent); color: #fff; cursor: pointer; display: grid; place-items: center; font-size: 16px; }\n.ss-w-stop-glyph { width: 11px; height: 11px; background: currentColor; border-radius: 2px; }\n\n@media (prefers-reduced-motion: reduce) {\n .ss-w-abtn-shimmer { animation: none; }\n}\n";
37
37
 
38
38
  export { StatsWidget, type StatsWidgetConfig, type StatsWidgetProps, WIDGET_CSS };
package/dist/index.js CHANGED
@@ -15,7 +15,9 @@ var STRINGS = {
15
15
  somethingWentWrong: "Something went wrong.",
16
16
  retry: "Retry",
17
17
  showLess: "Show less",
18
- showMore: (n) => `Show ${n} more`
18
+ showMore: (n) => `Show ${n} more`,
19
+ oddsLabel: "Odds",
20
+ liveLabel: "Live"
19
21
  },
20
22
  tr: {
21
23
  launcherLabel: "SensibleStats ile sohbet et",
@@ -28,7 +30,9 @@ var STRINGS = {
28
30
  somethingWentWrong: "Bir \u015Feyler ters gitti.",
29
31
  retry: "Tekrar dene",
30
32
  showLess: "Daha az g\xF6ster",
31
- showMore: (n) => `${n} tane daha g\xF6ster`
33
+ showMore: (n) => `${n} tane daha g\xF6ster`,
34
+ oddsLabel: "Oran",
35
+ liveLabel: "Canl\u0131"
32
36
  }
33
37
  };
34
38
  function resolveLocaleStrings(locale) {
@@ -58,7 +62,9 @@ function normalizeUi(cfg) {
58
62
  somethingWentWrong: strings.somethingWentWrong,
59
63
  retry: strings.retry,
60
64
  showLess: strings.showLess,
61
- showMore: strings.showMore
65
+ showMore: strings.showMore,
66
+ oddsLabel: strings.oddsLabel,
67
+ liveLabel: strings.liveLabel
62
68
  };
63
69
  }
64
70
  function toClientOptions(cfg) {
@@ -95,16 +101,19 @@ function str(v) {
95
101
  function num(v) {
96
102
  return typeof v === "number" && Number.isFinite(v) ? String(v) : void 0;
97
103
  }
98
- function readStats(card) {
99
- if (!Array.isArray(card.stats)) return [];
104
+ function readStatCells(raw) {
105
+ if (!Array.isArray(raw)) return [];
100
106
  const cells = [];
101
- for (const entry of card.stats) {
107
+ for (const entry of raw) {
102
108
  const label = str(entry.label);
103
109
  const value = num(entry.value) ?? str(entry.value);
104
110
  if (label !== void 0 && value !== void 0) cells.push({ label, value });
105
111
  }
106
112
  return cells;
107
113
  }
114
+ function readStats(card) {
115
+ return readStatCells(card.stats);
116
+ }
108
117
  function toCardVM(card) {
109
118
  const entityType = str(card.entityType)?.toLowerCase();
110
119
  const kind = entityType === "player" ? "player" : entityType === "team" ? "team" : "generic";
@@ -130,6 +139,31 @@ function toChipVM(intent) {
130
139
  function chipFromText(text) {
131
140
  return { text };
132
141
  }
142
+ function toInsightVM(insight) {
143
+ const market = str(insight.marketLabel) ?? str(insight.marketDeveloperName) ?? "";
144
+ const selection = [str(insight.selectionLabel), str(insight.line)].filter(Boolean).join(" ") || void 0;
145
+ const value = insight.odds?.value;
146
+ const odds = typeof value === "number" && Number.isFinite(value) ? value.toFixed(2) : void 0;
147
+ const home = str(insight.homeTeamName);
148
+ const away = str(insight.awayTeamName);
149
+ const fixture = home && away ? `${home} vs ${away}` : void 0;
150
+ const scopes = Array.isArray(insight.scopes) ? insight.scopes.map((s) => ({ key: str(s.key), label: str(s.label), stats: readStatCells(s.stats) })).filter((s) => !!s.key && !!s.label) : void 0;
151
+ return {
152
+ id: str(insight.insightId) ?? `${str(insight.ruleId) ?? "insight"}:${num(insight.matchId) ?? ""}`,
153
+ market,
154
+ selection,
155
+ odds,
156
+ // The wire payload carries bookmakerId (not a name); render a name only if one is present.
157
+ bookmaker: str(insight.odds?.bookmakerName),
158
+ isLive: insight.odds?.isLive === true,
159
+ phase: str(insight.phase),
160
+ fixture,
161
+ scopes,
162
+ text: str(insight.text) ?? "",
163
+ stats: readStatCells(insight.stats),
164
+ disclaimer: str(insight.disclaimer)
165
+ };
166
+ }
133
167
 
134
168
  // src/reducer.ts
135
169
  var POPUP_MAX = 160;
@@ -156,6 +190,8 @@ function applyEvent(state, event) {
156
190
  return { ...state, messages: mapActive(state, (t) => ({ ...t, cards: [...t.cards, toCardVM(event.data.card)] })) };
157
191
  case "action_button":
158
192
  return { ...state, actionsLoading: false, messages: mapActive(state, (t) => ({ ...t, actions: [...t.actions, toActionVM(event.data.action)] })) };
193
+ case "betting_insight":
194
+ return { ...state, messages: mapActive(state, (t) => ({ ...t, insights: [...t.insights, toInsightVM(event.data.insight)] })) };
159
195
  case "intent_chip": {
160
196
  const chip = toChipVM(event.data.intent);
161
197
  return chip ? { ...state, starters: [...state.starters, chip] } : state;
@@ -173,6 +209,7 @@ function applyEvent(state, event) {
173
209
  return { ...state, error: suppress ? state.error : event.data, isStreaming: false, status: null, actionsLoading: false, messages: mapActive(state, (t) => ({ ...t, done: true })) };
174
210
  }
175
211
  }
212
+ return state;
176
213
  }
177
214
  function reducer(state, action) {
178
215
  switch (action.kind) {
@@ -182,11 +219,11 @@ function reducer(state, action) {
182
219
  return { ...state, isOpen: false, isStreaming: false, status: null, actionsLoading: false };
183
220
  case "USER_SENT": {
184
221
  const user = { role: "user", id: action.userId, text: action.displayText ?? action.input.message };
185
- const assistant = { role: "assistant", id: action.assistantId, text: "", cards: [], actions: [], done: false };
222
+ const assistant = { role: "assistant", id: action.assistantId, text: "", cards: [], actions: [], insights: [], done: false };
186
223
  return { ...state, messages: [...state.messages, user, assistant], isStreaming: true, status: null, actionsLoading: false, starters: [], error: null, lastUserInput: action.input, lastDisplayText: action.displayText ?? null };
187
224
  }
188
225
  case "GREETING_SENT": {
189
- const assistant = { role: "assistant", id: action.assistantId, text: "", cards: [], actions: [], done: false, isGreeting: true };
226
+ const assistant = { role: "assistant", id: action.assistantId, text: "", cards: [], actions: [], insights: [], done: false, isGreeting: true };
190
227
  return { ...state, messages: [...state.messages, assistant], isStreaming: true, status: null, error: null };
191
228
  }
192
229
  case "DISMISS_POPUP":
@@ -308,7 +345,7 @@ function ChatFab({ label, greeting, popupText, onOpen, onDismissPopup, dismissLa
308
345
  }
309
346
 
310
347
  // src/components/ChatPanel.tsx
311
- import { useEffect as useEffect3, useState as useState3 } from "react";
348
+ import { useEffect as useEffect3, useState as useState4 } from "react";
312
349
 
313
350
  // src/components/ChatHeader.tsx
314
351
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
@@ -374,37 +411,94 @@ function EntityCardList({ cards, disabled, showLessLabel = "Show less", showMore
374
411
  ] });
375
412
  }
376
413
 
414
+ // src/components/BettingInsightList.tsx
415
+ import { useState as useState2 } from "react";
416
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
417
+ var MAX_ROWS = 3;
418
+ function StatRows({ stats, ui }) {
419
+ const [expanded, setExpanded] = useState2(false);
420
+ const shown = expanded ? stats : stats.slice(0, MAX_ROWS);
421
+ const overflow = stats.length - MAX_ROWS;
422
+ return /* @__PURE__ */ jsxs5("div", { className: "ss-w-bi-rows", children: [
423
+ shown.map((s) => /* @__PURE__ */ jsxs5("div", { className: "ss-w-bi-row", children: [
424
+ /* @__PURE__ */ jsx7("span", { className: "ss-w-bi-row-lbl", children: s.label }),
425
+ /* @__PURE__ */ jsx7("span", { className: "ss-w-bi-row-dots", "aria-hidden": "true" }),
426
+ /* @__PURE__ */ jsx7("span", { className: "ss-w-bi-row-num", children: s.value })
427
+ ] }, `${s.label}:${s.value}`)),
428
+ overflow > 0 ? /* @__PURE__ */ jsx7("button", { type: "button", className: "ss-w-bi-more", onClick: () => setExpanded((v) => !v), children: expanded ? ui?.showLess ?? "Show less" : (ui?.showMore ?? ((n) => `Show ${n} more`))(overflow) }) : null
429
+ ] });
430
+ }
431
+ function ScopedStats({ scopes, ui }) {
432
+ const [active, setActive] = useState2(0);
433
+ const current = scopes[active] ?? scopes[0] ?? { key: "", label: "", stats: [] };
434
+ return /* @__PURE__ */ jsxs5("div", { className: "ss-w-bi-scoped", children: [
435
+ /* @__PURE__ */ jsx7("div", { className: "ss-w-bi-scopes", role: "group", children: scopes.map((s, i) => /* @__PURE__ */ jsx7("button", { type: "button", className: "ss-w-bi-chip", "aria-pressed": i === active, onClick: () => setActive(i), children: s.label }, s.key)) }),
436
+ /* @__PURE__ */ jsx7(StatRows, { stats: current.stats, ui }, current.key)
437
+ ] });
438
+ }
439
+ function InsightCard({ it, ui }) {
440
+ const live = it.isLive || it.phase === "live";
441
+ return /* @__PURE__ */ jsxs5("div", { className: "ss-w-binsight", children: [
442
+ live || it.fixture ? /* @__PURE__ */ jsxs5("div", { className: "ss-w-bi-status", children: [
443
+ live ? /* @__PURE__ */ jsxs5("span", { className: "ss-w-bi-live", children: [
444
+ /* @__PURE__ */ jsx7("span", { className: "ss-w-bi-live-dot", "aria-hidden": "true" }),
445
+ ui?.liveLabel ?? "Live"
446
+ ] }) : null,
447
+ it.fixture ? /* @__PURE__ */ jsx7("span", { className: "ss-w-bi-fixture", children: it.fixture }) : null
448
+ ] }) : null,
449
+ /* @__PURE__ */ jsxs5("div", { className: "ss-w-bi-head", children: [
450
+ /* @__PURE__ */ jsxs5("span", { className: "ss-w-bi-mkt", children: [
451
+ /* @__PURE__ */ jsx7("span", { className: "ss-w-bi-market", children: it.market }),
452
+ it.selection ? /* @__PURE__ */ jsx7("span", { className: "ss-w-bi-sel", children: it.selection }) : null
453
+ ] }),
454
+ it.odds ? /* @__PURE__ */ jsxs5("span", { className: "ss-w-bi-odds", children: [
455
+ /* @__PURE__ */ jsx7("span", { className: "ss-w-bi-odds-cap", children: ui?.oddsLabel ?? "Odds" }),
456
+ /* @__PURE__ */ jsx7("b", { children: it.odds }),
457
+ it.bookmaker ? /* @__PURE__ */ jsx7("span", { className: "ss-w-bi-book", children: it.bookmaker }) : null
458
+ ] }) : null
459
+ ] }),
460
+ it.text ? /* @__PURE__ */ jsx7("p", { className: "ss-w-bi-text", children: it.text }) : null,
461
+ it.scopes && it.scopes.length >= 2 ? /* @__PURE__ */ jsx7(ScopedStats, { scopes: it.scopes, ui }) : it.stats.length > 0 ? /* @__PURE__ */ jsx7(StatRows, { stats: it.stats, ui }) : null,
462
+ it.disclaimer ? /* @__PURE__ */ jsx7("p", { className: "ss-w-bi-disc", children: it.disclaimer }) : null
463
+ ] });
464
+ }
465
+ function BettingInsightList({ insights, ui }) {
466
+ if (!insights || insights.length === 0) return null;
467
+ return /* @__PURE__ */ jsx7("div", { className: "ss-w-binsights", children: insights.map((it) => /* @__PURE__ */ jsx7(InsightCard, { it, ui }, it.id)) });
468
+ }
469
+
377
470
  // src/components/ActionButtons.tsx
378
- import { Fragment, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
471
+ import { Fragment, jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
379
472
  function ActionButtons({ actions, loading, disabled, onAct }) {
380
473
  if (actions.length === 0 && !loading) return null;
381
- return /* @__PURE__ */ jsxs5("div", { className: "ss-w-actions", children: [
382
- actions.map((a, i) => /* @__PURE__ */ jsx7("button", { type: "button", className: "ss-w-abtn", disabled, onClick: () => onAct(a), children: a.label }, `${a.label}-${i}`)),
383
- actions.length === 0 && loading ? /* @__PURE__ */ jsxs5(Fragment, { children: [
384
- /* @__PURE__ */ jsx7("span", { className: "ss-w-abtn-shimmer" }),
385
- /* @__PURE__ */ jsx7("span", { className: "ss-w-abtn-shimmer" })
474
+ return /* @__PURE__ */ jsxs6("div", { className: "ss-w-actions", children: [
475
+ actions.map((a, i) => /* @__PURE__ */ jsx8("button", { type: "button", className: "ss-w-abtn", disabled, onClick: () => onAct(a), children: a.label }, `${a.label}-${i}`)),
476
+ actions.length === 0 && loading ? /* @__PURE__ */ jsxs6(Fragment, { children: [
477
+ /* @__PURE__ */ jsx8("span", { className: "ss-w-abtn-shimmer" }),
478
+ /* @__PURE__ */ jsx8("span", { className: "ss-w-abtn-shimmer" })
386
479
  ] }) : null
387
480
  ] });
388
481
  }
389
482
 
390
483
  // src/components/ChatMessage.tsx
391
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
484
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
392
485
  function ChatMessage({ message, disabled, onAct, ui }) {
393
486
  if (message.role === "user") {
394
- return /* @__PURE__ */ jsx8("div", { className: "ss-w-msg ss-w-user", children: /* @__PURE__ */ jsx8("div", { className: "ss-w-bubble", children: message.text }) });
487
+ return /* @__PURE__ */ jsx9("div", { className: "ss-w-msg ss-w-user", children: /* @__PURE__ */ jsx9("div", { className: "ss-w-bubble", children: message.text }) });
395
488
  }
396
- return /* @__PURE__ */ jsxs6("div", { className: "ss-w-msg ss-w-bot", children: [
397
- message.text ? /* @__PURE__ */ jsx8(Markdown, { text: message.text }) : null,
398
- /* @__PURE__ */ jsx8(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
399
- /* @__PURE__ */ jsx8(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
489
+ return /* @__PURE__ */ jsxs7("div", { className: "ss-w-msg ss-w-bot", children: [
490
+ message.text ? /* @__PURE__ */ jsx9(Markdown, { text: message.text }) : null,
491
+ /* @__PURE__ */ jsx9(EntityCardList, { cards: message.cards, disabled, showLessLabel: ui?.showLess, showMoreLabel: ui?.showMore }),
492
+ /* @__PURE__ */ jsx9(BettingInsightList, { insights: message.insights, ui }),
493
+ /* @__PURE__ */ jsx9(ActionButtons, { actions: message.actions, loading: false, disabled, onAct })
400
494
  ] });
401
495
  }
402
496
 
403
497
  // src/components/IntentChips.tsx
404
- import { jsx as jsx9 } from "react/jsx-runtime";
498
+ import { jsx as jsx10 } from "react/jsx-runtime";
405
499
  function IntentChips({ chips, onPick }) {
406
500
  if (chips.length === 0) return null;
407
- return /* @__PURE__ */ jsx9("div", { className: "ss-w-chips", children: chips.map((c, i) => /* @__PURE__ */ jsx9("button", { type: "button", className: "ss-w-chip", onClick: () => onPick(c.text), children: c.text }, `${c.text}-${i}`)) });
501
+ return /* @__PURE__ */ jsx10("div", { className: "ss-w-chips", children: chips.map((c, i) => /* @__PURE__ */ jsx10("button", { type: "button", className: "ss-w-chip", onClick: () => onPick(c.text), children: c.text }, `${c.text}-${i}`)) });
408
502
  }
409
503
 
410
504
  // src/scroll.ts
@@ -414,7 +508,7 @@ function isPinnedToBottom(el, threshold = PIN_THRESHOLD) {
414
508
  }
415
509
 
416
510
  // src/components/MessageList.tsx
417
- import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
511
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
418
512
  function MessageList({ controller, ui }) {
419
513
  const { state, send } = controller;
420
514
  const listRef = useRef2(null);
@@ -424,7 +518,7 @@ function MessageList({ controller, ui }) {
424
518
  if (pinnedRef.current) endRef.current?.scrollIntoView({ block: "end" });
425
519
  }, [state.messages, state.status]);
426
520
  const empty = state.messages.length === 0;
427
- return /* @__PURE__ */ jsxs7(
521
+ return /* @__PURE__ */ jsxs8(
428
522
  "div",
429
523
  {
430
524
  className: "ss-w-list",
@@ -434,7 +528,7 @@ function MessageList({ controller, ui }) {
434
528
  if (listRef.current) pinnedRef.current = isPinnedToBottom(listRef.current);
435
529
  },
436
530
  children: [
437
- state.messages.map((m) => /* @__PURE__ */ jsx10(
531
+ state.messages.map((m) => /* @__PURE__ */ jsx11(
438
532
  ChatMessage,
439
533
  {
440
534
  message: m,
@@ -444,25 +538,25 @@ function MessageList({ controller, ui }) {
444
538
  },
445
539
  m.id
446
540
  )),
447
- state.isStreaming && state.actionsLoading ? /* @__PURE__ */ jsx10(ActionButtons, { actions: [], loading: true, onAct: () => {
541
+ state.isStreaming && state.actionsLoading ? /* @__PURE__ */ jsx11(ActionButtons, { actions: [], loading: true, onAct: () => {
448
542
  } }) : null,
449
- state.status ? /* @__PURE__ */ jsx10("div", { className: "ss-w-status", children: state.status }) : null,
450
- state.error ? /* @__PURE__ */ jsxs7("div", { className: "ss-w-error", role: "alert", children: [
451
- /* @__PURE__ */ jsx10("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
452
- /* @__PURE__ */ jsx10("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
543
+ state.status ? /* @__PURE__ */ jsx11("div", { className: "ss-w-status", children: state.status }) : null,
544
+ state.error ? /* @__PURE__ */ jsxs8("div", { className: "ss-w-error", role: "alert", children: [
545
+ /* @__PURE__ */ jsx11("span", { children: "message" in state.error ? state.error.message : ui.somethingWentWrong }),
546
+ /* @__PURE__ */ jsx11("button", { type: "button", className: "ss-w-retry", onClick: () => controller.retry(), children: ui.retry })
453
547
  ] }) : null,
454
- empty ? /* @__PURE__ */ jsx10(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
455
- /* @__PURE__ */ jsx10("div", { ref: endRef })
548
+ empty ? /* @__PURE__ */ jsx11(IntentChips, { chips: state.starters, onPick: (t) => send(t) }) : null,
549
+ /* @__PURE__ */ jsx11("div", { ref: endRef })
456
550
  ]
457
551
  }
458
552
  );
459
553
  }
460
554
 
461
555
  // src/components/ChatInput.tsx
462
- import { useState as useState2 } from "react";
463
- import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
556
+ import { useState as useState3 } from "react";
557
+ import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
464
558
  function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop response", sendLabel = "Send message" }) {
465
- const [value, setValue] = useState2("");
559
+ const [value, setValue] = useState3("");
466
560
  const submit = () => {
467
561
  const t = value.trim();
468
562
  if (!t) return;
@@ -475,17 +569,17 @@ function ChatInput({ placeholder, streaming, onSend, onStop, stopLabel = "Stop r
475
569
  submit();
476
570
  }
477
571
  };
478
- return /* @__PURE__ */ jsxs8("div", { className: "ss-w-input", children: [
479
- /* @__PURE__ */ jsx11("textarea", { className: "ss-w-textarea", rows: 1, placeholder, value, disabled: streaming, onChange: (e) => setValue(e.target.value), onKeyDown }),
480
- streaming ? /* @__PURE__ */ jsx11("button", { type: "button", className: "ss-w-send ss-w-stop", "aria-label": stopLabel, onClick: onStop, children: /* @__PURE__ */ jsx11("span", { className: "ss-w-stop-glyph" }) }) : /* @__PURE__ */ jsx11("button", { type: "button", className: "ss-w-send", "aria-label": sendLabel, onClick: submit, children: /* @__PURE__ */ jsx11(SendIcon, {}) })
572
+ return /* @__PURE__ */ jsxs9("div", { className: "ss-w-input", children: [
573
+ /* @__PURE__ */ jsx12("textarea", { className: "ss-w-textarea", rows: 1, placeholder, value, disabled: streaming, onChange: (e) => setValue(e.target.value), onKeyDown }),
574
+ streaming ? /* @__PURE__ */ jsx12("button", { type: "button", className: "ss-w-send ss-w-stop", "aria-label": stopLabel, onClick: onStop, children: /* @__PURE__ */ jsx12("span", { className: "ss-w-stop-glyph" }) }) : /* @__PURE__ */ jsx12("button", { type: "button", className: "ss-w-send", "aria-label": sendLabel, onClick: submit, children: /* @__PURE__ */ jsx12(SendIcon, {}) })
481
575
  ] });
482
576
  }
483
577
 
484
578
  // src/components/ChatPanel.tsx
485
- import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
579
+ import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
486
580
  var FULLSCREEN_QUERY = "(max-width: 639px)";
487
581
  function useIsModal() {
488
- const [modal, setModal] = useState3(false);
582
+ const [modal, setModal] = useState4(false);
489
583
  useEffect3(() => {
490
584
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
491
585
  const mql = window.matchMedia(FULLSCREEN_QUERY);
@@ -506,10 +600,10 @@ function ChatPanel({ controller, ui }) {
506
600
  window.addEventListener("keydown", onKey);
507
601
  return () => window.removeEventListener("keydown", onKey);
508
602
  }, [close]);
509
- return /* @__PURE__ */ jsxs9("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
510
- /* @__PURE__ */ jsx12(ChatHeader, { onClose: close, closeLabel: ui.closeChat }),
511
- /* @__PURE__ */ jsx12(MessageList, { controller, ui }),
512
- /* @__PURE__ */ jsx12(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: (t) => send(t), onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
603
+ return /* @__PURE__ */ jsxs10("div", { className: "ss-w-panel", role: "dialog", "aria-modal": isModal, "aria-label": ui.chatDialogLabel, children: [
604
+ /* @__PURE__ */ jsx13(ChatHeader, { onClose: close, closeLabel: ui.closeChat }),
605
+ /* @__PURE__ */ jsx13(MessageList, { controller, ui }),
606
+ /* @__PURE__ */ jsx13(ChatInput, { placeholder: ui.placeholder, streaming: state.isStreaming, onSend: (t) => send(t), onStop: stop, stopLabel: ui.stopResponse, sendLabel: ui.sendMessage })
513
607
  ] });
514
608
  }
515
609
 
@@ -608,6 +702,36 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
608
702
  .ss-w-cards-more:hover:not(:disabled) { text-decoration: underline; }
609
703
  .ss-w-cards-more:disabled { opacity: .5; cursor: default; }
610
704
 
705
+ /* betting insights */
706
+ .ss-w-binsights { display: flex; flex-direction: column; gap: 7px; }
707
+ .ss-w-binsight { background: var(--ss-w-panel); border: 1px solid var(--ss-w-line); border-radius: 12px; border-left: 3px solid var(--ss-w-accent); padding: 9px 11px; display: flex; flex-direction: column; gap: 6px; }
708
+ .ss-w-bi-status { display: flex; align-items: center; gap: 6px; min-width: 0; }
709
+ .ss-w-bi-fixture { font-size: 11px; color: var(--ss-w-ink); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
710
+ .ss-w-bi-live { font-size: 8.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: #fff; background: #c0392b; border-radius: 4px; padding: 1px 5px; display: inline-flex; align-items: center; gap: 4px; flex: none; }
711
+ .ss-w-bi-live-dot { width: 5px; height: 5px; border-radius: 50%; background: #fff; }
712
+ .ss-w-bi-head { display: flex; align-items: flex-start; gap: 10px; }
713
+ .ss-w-bi-mkt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
714
+ .ss-w-bi-market { font-size: 13px; font-weight: 660; line-height: 1.3; color: var(--ss-w-ink); }
715
+ .ss-w-bi-sel { font-size: 11px; line-height: 1.3; color: var(--ss-w-faint); }
716
+ .ss-w-bi-odds { margin-left: auto; flex: none; display: flex; flex-direction: column; align-items: center; justify-content: center; background: color-mix(in srgb, var(--ss-w-accent) 12%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 24%, var(--ss-w-line)); border-radius: 8px; padding: 3px 9px; min-width: 56px; }
717
+ .ss-w-bi-odds-cap { font-size: 8px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--ss-w-faint); }
718
+ .ss-w-bi-odds b { font-size: 15px; font-family: ui-monospace, monospace; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ss-w-accent); line-height: 1.15; }
719
+ .ss-w-bi-book { font-size: 9.5px; color: var(--ss-w-faint); }
720
+ .ss-w-bi-text { font-size: 12px; color: var(--ss-w-ink); }
721
+ .ss-w-bi-rows { display: flex; flex-direction: column; }
722
+ .ss-w-bi-row { display: flex; align-items: baseline; gap: 8px; padding: 4px 0; border-top: 1px solid var(--ss-w-line); }
723
+ .ss-w-bi-row:first-child { border-top: none; }
724
+ .ss-w-bi-row-lbl { font-size: 11px; color: var(--ss-w-faint); min-width: 0; }
725
+ .ss-w-bi-row-dots { flex: 1; border-bottom: 1px dotted var(--ss-w-line); transform: translateY(-3px); min-width: 12px; }
726
+ .ss-w-bi-row-num { font-family: ui-monospace, monospace; font-weight: 700; font-variant-numeric: tabular-nums; font-size: 12.5px; flex: none; color: var(--ss-w-ink); }
727
+ .ss-w-bi-more { align-self: flex-start; background: none; border: none; color: var(--ss-w-accent); font: inherit; font-size: 11px; font-weight: 560; padding: 2px 0; cursor: pointer; }
728
+ .ss-w-bi-more:hover { text-decoration: underline; }
729
+ .ss-w-bi-disc { font-size: 10px; font-style: italic; color: var(--ss-w-faint); }
730
+ .ss-w-bi-scoped { display: flex; flex-direction: column; gap: 6px; }
731
+ .ss-w-bi-scopes { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
732
+ .ss-w-bi-chip { font-size: 11px; font-weight: 550; border: 1px solid var(--ss-w-line); border-radius: 14px; padding: 3px 10px; color: var(--ss-w-ink); background: var(--ss-w-bubble); cursor: pointer; }
733
+ .ss-w-bi-chip[aria-pressed="true"] { color: #fff; background: var(--ss-w-accent); border-color: var(--ss-w-accent); }
734
+
611
735
  /* action buttons */
612
736
  .ss-w-actions { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
613
737
  .ss-w-abtn { font-size: 12px; font-weight: 560; color: var(--ss-w-accent); background: var(--ss-w-panel); border: 1px solid var(--ss-w-accent); border-radius: 16px; padding: 6px 12px; cursor: pointer; }
@@ -637,7 +761,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
637
761
  `;
638
762
 
639
763
  // src/StatsWidget.tsx
640
- import { jsx as jsx13 } from "react/jsx-runtime";
764
+ import { jsx as jsx14 } from "react/jsx-runtime";
641
765
  function buildClient(props) {
642
766
  try {
643
767
  if ("client" in props && props.client) {
@@ -673,7 +797,7 @@ function StatsWidget(props) {
673
797
  }, [built, ui.injectStyles]);
674
798
  if (!built) return null;
675
799
  const attrs = themeAttrs(ui);
676
- return /* @__PURE__ */ jsx13("div", { ref: rootRef, className: "ss-w-root", "data-ss-w-theme": attrs["data-ss-w-theme"], "data-ss-w-pos": attrs["data-ss-w-pos"], style: attrs.style, children: controller.state.isOpen ? /* @__PURE__ */ jsx13(ChatPanel, { controller, ui }) : /* @__PURE__ */ jsx13(
800
+ return /* @__PURE__ */ jsx14("div", { ref: rootRef, className: "ss-w-root", "data-ss-w-theme": attrs["data-ss-w-theme"], "data-ss-w-pos": attrs["data-ss-w-pos"], style: attrs.style, children: controller.state.isOpen ? /* @__PURE__ */ jsx14(ChatPanel, { controller, ui }) : /* @__PURE__ */ jsx14(
677
801
  ChatFab,
678
802
  {
679
803
  label: ui.launcherLabel,