/* ============================================================
 * TRM Odds Data — card-layout scoreboard.
 * Visual style mirrors the original trm-sports-data plugin's
 * compact card so cards from either plugin sit comfortably
 * on the same site. BEM prefix here is .trm-od (sibling to
 * the original's .trm-sd) so styles never collide.
 * ============================================================ */

.trm-od {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    margin: 1.25em 0;
    color: #1f2937;
}

.trm-od--message {
    padding: 12px 16px;
    background: #f6f7f7;
    border: 1px solid #e5e7eb;
    border-radius: 6px;
    color: #6b7280;
}

/* ============================================================
 *  Operator-customizable accent palette.
 * ============================================================
 *  Two colors drive every emerald / blue accent in the plugin:
 *    --trm-od-scoreboard-accent  — scoreboard winner/live tint
 *    --trm-od-featured-highlight — featured-lines "best pick" tint
 *  Both can be overridden in Settings → Colors. The shade ladder
 *  below derives bg/border/hover from each base color via
 *  color-mix so picking one swatch updates the whole family. */
:root {
    --trm-od-scoreboard-accent:             #16a34a;
    --trm-od-scoreboard-accent-text:        color-mix(in srgb, var(--trm-od-scoreboard-accent) 80%, black);
    --trm-od-scoreboard-accent-bg:          color-mix(in srgb, var(--trm-od-scoreboard-accent) 10%, white);
    --trm-od-scoreboard-accent-header-bg:   color-mix(in srgb, var(--trm-od-scoreboard-accent)  6%, white);
    --trm-od-scoreboard-accent-border-soft: color-mix(in srgb, var(--trm-od-scoreboard-accent) 30%, white);
    --trm-od-scoreboard-accent-hover-bg:    color-mix(in srgb, var(--trm-od-scoreboard-accent) 18%, white);

    /* Odds-cell (clickable box) palette. Border is the accent itself;
     * the fill is the accent at low opacity (transparent, so it tints
     * whatever the card background is). On hover both switch to the
     * "mouseover" color — which defaults to the accent, so an operator
     * only sets it when they want a distinct hover color. */
    --trm-od-scoreboard-hover:              var(--trm-od-scoreboard-accent);
    --trm-od-odds-border:                   var(--trm-od-scoreboard-accent);
    --trm-od-odds-bg:                       color-mix(in srgb, var(--trm-od-scoreboard-accent) 8%, transparent);
    --trm-od-odds-hover-border:             var(--trm-od-scoreboard-hover);
    --trm-od-odds-hover-bg:                 color-mix(in srgb, var(--trm-od-scoreboard-hover) 16%, transparent);

    --trm-od-featured-highlight:            #1d4ed8;
    --trm-od-featured-highlight-border:     color-mix(in srgb, var(--trm-od-featured-highlight) 90%, white);
    --trm-od-featured-highlight-bg:         color-mix(in srgb, var(--trm-od-featured-highlight) 10%, white);
    --trm-od-featured-highlight-hover-bg:   color-mix(in srgb, var(--trm-od-featured-highlight) 18%, white);
}

/* ---- Header (heading + "Updated X ago") ---- */
.trm-od__header {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    padding-bottom: 10px;
    margin-bottom: 12px;
    border-bottom: 1px solid #e5e7eb;
}

.trm-od__heading {
    margin: 0;
    font-size: 1.1em;
    font-weight: 700;
    color: #111827;
}

.trm-od__updated {
    font-size: 12px;
    color: #9ca3af;
    white-space: nowrap;
}

@media (max-width: 480px) {
    .trm-od__header {
        flex-direction: column;
        align-items: flex-start;
        gap: 2px;
    }
}

/* ---- Card grid ----
 * Column count is operator-configurable via the block's "Columns"
 * sidebar control (1-3). The wrapper picks up a .trm-od--cols-N
 * modifier and these rules supply the matching grid template.
 * Without a modifier (legacy posts saved before this attribute
 * existed), the default 3-column rule below applies. */
.trm-od__grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 10px;
}

/* Column rules apply to both the scoreboard grid (.trm-od__grid)
 * and the futures grid (.trm-od-futures__grid) so the operator
 * picks columns once per block and the same CSS produces a
 * matching template in either layout. */
.trm-od--cols-1 .trm-od__grid,
.trm-od--cols-1 .trm-od-futures__grid { grid-template-columns: 1fr; }
.trm-od--cols-2 .trm-od__grid,
.trm-od--cols-2 .trm-od-futures__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.trm-od--cols-3 .trm-od__grid,
.trm-od--cols-3 .trm-od-futures__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* Full Panel template — the three-panel card needs the full row
 * width to lay its odds / pitchers / meta panels side by side, so
 * it ignores the column control entirely and always renders one
 * card per row. The wrapper carries .trm-od--tpl-panels (and no
 * .trm-od--cols-N modifier), so this single rule pins the grid to
 * a single column at every breakpoint. */
.trm-od--tpl-panels .trm-od__grid { grid-template-columns: 1fr; }

/* Tablet — 3 columns collapses to 2 so cards don't crush below
 * the readable minimum (~250px including the odds boxes).
 * 1- and 2-column choices stay as-is. */
@media (max-width: 1159px) {
    .trm-od--cols-3 .trm-od__grid,
    .trm-od--cols-3 .trm-od-futures__grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* Mobile — every multi-column setting collapses to 1. A 2-up
 * card row at phone width makes the odds cells fall off the
 * grid entirely. */
@media (max-width: 785px) {
    .trm-od--cols-2 .trm-od__grid,
    .trm-od--cols-2 .trm-od-futures__grid,
    .trm-od--cols-3 .trm-od__grid,
    .trm-od--cols-3 .trm-od-futures__grid {
        grid-template-columns: 1fr;
    }
}

/* ---- Date groups (multi-day slates) ----
 * The cards layout groups games by local calendar date when the
 * slate spans more than one day (an NFL/NCAAF week). Each day is a
 * .trm-od__group section: a date heading strip on top, then that
 * day's card grid. Single-day slates skip the grouping entirely
 * and render a bare .trm-od__grid, so these rules never apply. */
.trm-od__group + .trm-od__group {
    margin-top: 20px;
}

.trm-od__group-date {
    margin: 0 0 10px;
    padding-bottom: 6px;
    font-size: 0.95em;
    font-weight: 700;
    color: #374151;
    border-bottom: 1px solid #e5e7eb;
}

/* ---- 1-column override ----
 * When the operator picks 1 column, each card takes the full
 * content width and the 62px odds cells end up bunched against
 * the right edge while the team column absorbs all the extra
 * space. Bump the cell width and the gap between cells so the
 * three boxes spread out — strictly horizontal, no height,
 * padding, or font changes so the card stays the same height
 * as a multi-column card. */
.trm-od--cols-1 .trm-od-card__body {
    grid-template-columns: minmax(0, 1fr) 26px 96px 96px 96px;
    column-gap: 8px;
}

/* Narrow viewport guard — at phone widths the bumped 96px
 * cells overflow the card. Revert to the compact column
 * template below 540px. */
@media (max-width: 540px) {
    .trm-od--cols-1 .trm-od-card__body {
        grid-template-columns: minmax(0, 1fr) 26px 62px 62px 62px;
        column-gap: 5px;
    }
}

/* ---- Card chrome ---- */

.trm-od-card {
    background: #fff;
    border: 1px solid #e5e7eb;
    border-radius: 6px;
    /* overflow:hidden so the header's tinted background clips cleanly
     * to the card's rounded corners. */
    overflow: hidden;
    padding: 5px 8px 3px;
    font-size: 12px;
    line-height: 1.25;
    display: flex;
    flex-direction: column;
}

/* Header bar: extends edge-to-edge via negative margins so the subtle
 * grey background reads as a tinted strip at the top of the card. */
.trm-od-card__header {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 8px;
    margin: -5px -8px 6px;
    padding: 7px 10px;
    background: #f9fafb;
    border-bottom: 1px solid #e5e7eb;
    font-size: 13px;
    color: #4b5563;
}

.trm-od-card__when {
    font-weight: 600;
    color: #1f2937;
    white-space: nowrap;
}

.trm-od-card__venue {
    text-align: right;
    color: #4b5563;
    font-size: 12px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Live-game variant: tint the header bar so live games stand out in
 * the grid. Pulsing dot before the "when" string signals real-time
 * state without needing a separate badge. */
.trm-od-card--live .trm-od-card__header {
    background: var(--trm-od-scoreboard-accent-header-bg);
    border-bottom-color: var(--trm-od-scoreboard-accent-border-soft);
}
.trm-od-card--live .trm-od-card__when {
    color: var(--trm-od-scoreboard-accent-text);
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.trm-od-card--live .trm-od-card__when::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--trm-od-scoreboard-accent);
    box-shadow: 0 0 0 0 rgba(22, 163, 74, 0.6);
    animation: trm-od-pulse 1.6s infinite;
}

@keyframes trm-od-pulse {
    0%   { box-shadow: 0 0 0 0    rgba(22, 163, 74, 0.5); }
    70%  { box-shadow: 0 0 0 6px  rgba(22, 163, 74, 0); }
    100% { box-shadow: 0 0 0 0    rgba(22, 163, 74, 0); }
}

/* Final-game variant: desaturate the whole card slightly so finished
 * games recede compared to scheduled/live ones in a mixed grid. The
 * Final label in the header gets bolded so the status still reads
 * clearly at a glance. */
.trm-od-card--final {
    background: #fafafa;
}
.trm-od-card--final .trm-od-card__header {
    background: #f3f4f6;
    border-bottom-color: #e5e7eb;
}
.trm-od-card--final .trm-od-card__when {
    color: #374151;
    font-weight: 700;
    letter-spacing: 0.02em;
}
.trm-od-card--final .trm-od-team__name,
.trm-od-card--final .trm-od-team__record {
    color: #6b7280;
}
/* Odds boxes on finished games are non-actionable — drop the emerald
 * border to a neutral grey so they don't read as "click me." */
.trm-od-card--final .trm-od-odds {
    border-color: #d1d5db;
    background: #fafafa;
}
.trm-od-card--final .trm-od-odds:hover {
    background: #f3f4f6;
    border-color: #d1d5db;
}

/* ---- Body grid ----
 * 5 columns: team flexes, fixed score (26px), three 62px odds cells.
 * 62px is tuned to be the smallest width that comfortably fits the
 * "MONEYLINE" header without wrapping. */
.trm-od-card__body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 26px 62px 62px 62px;
    column-gap: 5px;
    row-gap: 2px;
    align-items: center;
    padding: 3px 0 2px;
}

.trm-od-card__col-headers { display: contents; }
.trm-od-card__col-headers > span {
    font-size: 10.5px;
    letter-spacing: 0.05em;
    color: #9ca3af;
    text-transform: uppercase;
    text-align: center;
    padding-bottom: 1px;
}
.trm-od-card__col-headers .trm-od-col--spread { grid-column: 3; }
.trm-od-card__col-headers .trm-od-col--ml     { grid-column: 4; }
.trm-od-card__col-headers .trm-od-col--total  { grid-column: 5; }

/* ---- "AT" separator ----
 * Thin line spans the full card width between the two team rows.
 * The "AT" label sits in column 1 with a white background so it
 * "breaks" the line cleanly around the text. */
.trm-od-card__at {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: subgrid;
    align-items: center;
    margin: -1px 0;
    line-height: 1;
}

.trm-od-card__at-line {
    grid-column: 1 / -1;
    grid-row: 1;
    height: 1px;
    background: #e5e7eb;
    align-self: center;
    z-index: 0;
}

.trm-od-card__at-label {
    grid-column: 1;
    grid-row: 1;
    z-index: 1;
    justify-self: center;
    background: #fff;
    padding: 0 6px;
    color: #9ca3af;
    font-size: 9.5px;
    letter-spacing: 0.08em;
}

/* ---- Team row ----
 * The row wrapper uses display:contents so its children flow into
 * the parent .trm-od-card__body grid — that's what lines the two
 * teams up into shared columns. */
.trm-od-team { display: contents; }

.trm-od-team__id {
    grid-column: 1;
    display: flex;
    align-items: center;
    gap: 7px;
    min-width: 0;
}

.trm-od-team__text { min-width: 0; }

/* Cards layout logo: small (20px) square so it sits next to the
 * team name without growing the row. object-fit:contain so any
 * aspect ratio inside the file (some PNGs are square, others
 * are wider) is preserved instead of squished. flex-shrink:0
 * stops the team-text from pushing the logo down to nothing on
 * narrow cards. */
.trm-od-team__logo {
    width: 23px;
    height: 23px;
    object-fit: contain;
    flex-shrink: 0;
}

.trm-od-team__name {
    font-weight: 500;
    color: #111827;
    font-size: 12.5px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Poll rank in front of the name — "#1 Texas Longhorns". Smaller and
   quieter than the name so it reads as a tag on it rather than part of
   it; only the sports whose payload carries a rank ever show one. */
.trm-od-team__rank {
    font-weight: 700;
    font-size: 0.82em;
    color: #6b7280;
    margin-right: 4px;
}

.trm-od-team__record {
    font-size: 12px;
    color: #9ca3af;
    margin-top: 0;
}

.trm-od-team__score {
    grid-column: 2;
    text-align: center;
    color: #d4a017;
    font-weight: 700;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}

/* ---- Odds cells ----
 * Accent-colored border in the default state signals "clickable" so
 * each box reads like a tappable affiliate link at a glance. Border +
 * low-opacity fill both derive from the Scoreboard accent (Settings →
 * Appearance); hover swaps to the mouseover color. */
.trm-od-odds {
    border: 1px solid var(--trm-od-odds-border);
    border-radius: 3px;
    padding: 2px 3px;
    text-align: center;
    background: var(--trm-od-odds-bg);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    line-height: 1.1;
    min-height: 30px;
    color: inherit;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease;
    /* Stretch to fill the grid row so the single-line moneyline box
     * matches the height of the two-line spread/total boxes on either
     * side. The parent .trm-od-card__body grid is set to
     * align-items: center, which would otherwise size each odds box
     * to its content. */
    align-self: stretch;
}

.trm-od-odds:hover {
    background: var(--trm-od-odds-hover-bg);
    border-color: var(--trm-od-odds-hover-border);
}

.trm-od-odds:focus-visible {
    outline: 2px solid var(--trm-od-odds-hover-border);
    outline-offset: 1px;
}

.trm-od-odds__line,
.trm-od-odds__price,
.trm-od-odds__price--solo {
    font-variant-numeric: tabular-nums;
    font-weight: 400;
}

/* Price-movement arrow.
 *
 * The renderer prints a <span> with a ▲ or ▼ glyph inside the price
 * span when the current price differs from previous_price AND the
 * price's source_updated_at is fresh. We hide the actual glyph and
 * paint a tall, skinny CSS triangle via ::before instead — pinned
 * to the right edge of the odds box, vertically centered. The
 * triangle is taller than wide for a "ticker" silhouette that
 * reads as movement without competing with the price text.
 *
 * Anchoring uses position:absolute against .trm-od-odds (which we
 * promote to position:relative below). Because the arrow is taken
 * out of flow, the centered price text doesn't shift when an arrow
 * appears or disappears on refresh — the layout is stable. */

/* Make the parent a positioning context for the absolutely-placed
 * arrow. Compatible with the existing flex column layout. */
.trm-od-odds { position: relative; }

/* Price-movement arrow rendered as a Font Awesome–style "arrow-down"
 * shape (stem + triangular head). Drawn via CSS mask using an inline
 * SVG so we can paint the shape any color we want via the element's
 * background-color. The unicode glyph in the underlying span is
 * hidden so the visible shape is the SVG; the glyph + aria-label
 * stay in the DOM for assistive tech.
 *
 * The base SVG points DOWN. The .--up modifier flips it via rotate
 * so we only carry one path through the cascade. */
.trm-od-odds__arrow {
    position: absolute;
    top: 50%;
    right: 2px;
    transform: translateY(-50%);
    /* Sized for visual presence — taller than wide for the
     * directional "ticker" feel, but fatter than the earlier
     * triangle so the stem reads at small card sizes too. */
    width: 13px;
    height: 26px;
    /* Hide the underlying ▲/▼ text glyph — the visible shape comes
     * from the SVG mask below. */
    font-size: 0;
    line-height: 0;
    color: transparent;
    pointer-events: none;
    -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 640'><path d='M297.4 598.6C309.9 611.1 330.2 611.1 342.7 598.6L470.7 470.6C483.2 458.1 483.2 437.8 470.7 425.3C458.2 412.8 437.9 412.8 425.4 425.3L352 498.7L352 64C352 46.3 337.7 32 320 32C302.3 32 288 46.3 288 64L288 498.7L214.6 425.3C202.1 412.8 181.8 412.8 169.3 425.3C156.8 437.8 156.8 458.1 169.3 470.6L297.3 598.6z'/></svg>") no-repeat center / contain;
            mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 640'><path d='M297.4 598.6C309.9 611.1 330.2 611.1 342.7 598.6L470.7 470.6C483.2 458.1 483.2 437.8 470.7 425.3C458.2 412.8 437.9 412.8 425.4 425.3L352 498.7L352 64C352 46.3 337.7 32 320 32C302.3 32 288 46.3 288 64L288 498.7L214.6 425.3C202.1 412.8 181.8 412.8 169.3 425.3C156.8 437.8 156.8 458.1 169.3 470.6L297.3 598.6z'/></svg>") no-repeat center / contain;
}
/* Down arrow uses the SVG as-is. Red. */
.trm-od-odds__arrow--down {
    background-color: #dc2626;
}
/* Up arrow rotates the same SVG 180°. Green. Combine with the
 * translateY for vertical centering so we don't clobber it. */
.trm-od-odds__arrow--up {
    background-color: var(--trm-od-scoreboard-accent);
    transform: translateY(-50%) rotate(180deg);
}

.trm-od-odds__line {
    font-size: 12px;
    color: #111827;
}

.trm-od-odds__price {
    font-size: 12px;
    color: #6b7280;
    margin-top: 1px;
}

.trm-od-odds__price--solo {
    font-size: 12px;
    color: #111827;
    margin-top: 0;
}

/* ---- Footer ---- */
.trm-od-card__footer {
    margin-top: 2px;
    padding-top: 3px;
    border-top: 1px solid #f1f1f4;
    font-size: 12px;
    color: #9ca3af;
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
}

.trm-od-card__weather {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.trm-od-card__attribution { flex-shrink: 0; }

.trm-od-card__affiliate {
    text-decoration: underline;
    text-decoration-color: #d1d5db;
    text-underline-offset: 2px;
    color: #6b7280;
}

/* Status pill rendered just before "Odds provided by …". Two
 * variants share the same shape so they line up across cards in
 * the grid:
 *   --live    green, with pulsing white dot (in-progress game)
 *   --pregame blue, solid              (game hasn't started yet)
 * Finished games show no pill — the desaturated --final card style
 * already signals that state. */
.trm-od-card__status-pill,
.trm-od-row__status-pill {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 1px 6px 1px 5px;
    margin-right: 4px;
    border-radius: 3px;
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    vertical-align: 1px;
}

.trm-od-card__status-pill--live,
.trm-od-row__status-pill--live {
    background: var(--trm-od-scoreboard-accent);
}

.trm-od-card__status-pill--live::before,
.trm-od-row__status-pill--live::before {
    content: "";
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7);
    animation: trm-od-pulse-light 1.6s infinite;
}

@keyframes trm-od-pulse-light {
    0%   { box-shadow: 0 0 0 0   rgba(255, 255, 255, 0.65); }
    70%  { box-shadow: 0 0 0 4px rgba(255, 255, 255, 0); }
    100% { box-shadow: 0 0 0 0   rgba(255, 255, 255, 0); }
}

.trm-od-card__status-pill--pregame,
.trm-od-row__status-pill--pregame {
    background: var(--trm-od-featured-highlight-border);
}

/* Pregame pill gets a static white dot — no pulse, since the game
 * isn't moving yet. Same shape as the live dot so the family reads
 * cohesively. */
.trm-od-card__status-pill--pregame::before,
.trm-od-row__status-pill--pregame::before {
    content: "";
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: #fff;
}

/* ============================================================
 * Table layout (.trm-od--table)
 * Stacked row-groups read as one continuous table — outer border
 * lives on the container, rows share thin dividers, and the last
 * row drops its bottom border so the container's stroke isn't
 * doubled. Shares the body font and color tokens with the cards
 * layout so the two layouts feel like siblings.
 * ============================================================ */
.trm-od--table .trm-od__table {
    display: flex;
    flex-direction: column;
    gap: 0;
    /* Container owns the outer chrome — border, radius, and the
     * overflow:hidden that clips the first row's grey venue strip
     * to the rounded top corners. */
    border: 1px solid #e5e7eb;
    border-radius: 6px;
    overflow: hidden;
    background: #fff;
}

.trm-od-row {
    background: #fff;
    /* No per-row border-radius or outer border — the container
     * supplies both. Bottom border acts as the divider between
     * rows; :last-child drops it so the container's border isn't
     * doubled at the bottom edge. */
    border-bottom: 1px solid #e5e7eb;
    font-size: 12.5px;
    line-height: 1.3;
}

.trm-od-row:last-child {
    border-bottom: none;
}

/* Finished games dim slightly so upcoming games dominate visually
 * in a mixed slate. Matches the cards layout's --final variant. */
.trm-od-row--final {
    background: #fafafa;
    opacity: 0.92;
}

/* Live / final strip treatments — mirror the cards layout's
 * .trm-od-card__header variants so an in-progress game reads
 * the same in either view. The green dot + pulse animation
 * reuses the @keyframes trm-od-pulse already declared above
 * for the cards layout. */
.trm-od-row--live .trm-od-row__strip {
    background: var(--trm-od-scoreboard-accent-header-bg);
    border-bottom-color: var(--trm-od-scoreboard-accent-border-soft);
}
.trm-od-row--live .trm-od-row__when {
    color: var(--trm-od-scoreboard-accent-text);
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.trm-od-row--live .trm-od-row__when::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--trm-od-scoreboard-accent);
    box-shadow: 0 0 0 0 rgba(22, 163, 74, 0.6);
    animation: trm-od-pulse 1.6s infinite;
}

.trm-od-row--final .trm-od-row__strip {
    background: #f3f4f6;
    border-bottom-color: #e5e7eb;
}
.trm-od-row--final .trm-od-row__when {
    color: #374151;
    font-weight: 700;
    letter-spacing: 0.02em;
}

/* ---- Venue strip ---- */
.trm-od-row__strip {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 8px;
    padding: 7px 12px;
    background: #f9fafb;
    border-bottom: 1px solid #e5e7eb;
    font-size: 12px;
    color: #4b5563;
}

.trm-od-row__when {
    font-weight: 600;
    color: #1f2937;
    white-space: nowrap;
}

.trm-od-row__venue {
    text-align: right;
    color: #4b5563;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* ---- Odds table ---- */
.trm-od-row__table {
    width: 100%;
    border-collapse: collapse;
    /* table-layout:fixed lets us assign predictable column widths
     * via th widths below — without it, the team-column would
     * absorb all the slack and the odds columns shrink to nothing
     * on tight breakpoints. */
    table-layout: fixed;
    /* Reset margin — most WP themes (GeneratePress included) apply
     * a default margin-bottom to <table> for prose readability,
     * which here would push the footer down by ~1em. caption-side
     * + spacing zeroed for defense-in-depth. */
    margin: 0;
    padding: 0;
    border-spacing: 0;
}

.trm-od-row__table caption,
.trm-od-row__table thead,
.trm-od-row__table tbody,
.trm-od-row__table tr,
.trm-od-row__table th,
.trm-od-row__table td {
    /* Belt-and-suspenders reset for theme rules that target
     * descendants of the table — some themes give tbody/td their
     * own padding which would re-introduce the gap. */
    margin: 0;
}

.trm-od-row__th {
    text-align: center;
    font-size: 10.5px;
    font-weight: 600;
    color: #9ca3af;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: 5px 6px;
    background: #fafafa;
    border-bottom: 1px solid #f1f1f4;
}

.trm-od-row__th--team {
    text-align: left;
    padding-left: 12px;
    width: auto;
}

.trm-od-row__th--spread,
.trm-od-row__th--ml,
.trm-od-row__th--total {
    width: 22%;
}

.trm-od-row__team-cell,
.trm-od-row__cell {
    padding: 7px 6px;
    vertical-align: middle;
    border-top: 1px solid #f1f1f4;
}

.trm-od-row__team-cell {
    padding-left: 12px;
    text-align: left;
    /* Important: this stays as the default table-cell layout. We
     * tried `display: flex` here previously and it broke row-height
     * equality with the adjacent <td> cells — once a <td> stops
     * being display:table-cell, the table-row layout can't keep its
     * height in sync with siblings, and the editor iframe surfaces
     * the mismatch even where the front-end masks it. Flex behavior
     * is on the inner div below. */
}

.trm-od-row__team-inner {
    /* Flex container so the team name/record block flows on the
     * left and the score sits anchored to the right. min-width:0
     * on the text block lets long team names ellipsize instead of
     * pushing the score off-cell. */
    display: flex;
    align-items: center;
    gap: 10px;
}

/* Table layout logo: same 20px sizing as cards so the two
 * layouts share a visual scale for the team identifier. Sits
 * inside the same flex inner that hosts the team-text and
 * team-score, so the existing gap:10px already separates it
 * from the team name. */
.trm-od-row__team-logo {
    width: 23px;
    height: 23px;
    object-fit: contain;
    flex-shrink: 0;
}

.trm-od-row__team-text {
    flex: 1;
    min-width: 0;
}

.trm-od-row__cell {
    text-align: center;
}

.trm-od-row__team-name {
    font-weight: 500;
    color: #111827;
    font-size: 13px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The table's rank, matching the cards'. */
.trm-od-row__team-rank {
    font-weight: 700;
    font-size: 0.82em;
    color: #6b7280;
    margin-right: 4px;
}

.trm-od-row__team-meta {
    font-size: 12px;
    color: #9ca3af;
    margin-top: 1px;
}

/* Score box on the right of the team cell — same gold + tabular-nums
 * treatment the cards use, scaled up slightly since the table row
 * has more vertical breathing room than a card grid. Empty score
 * (pregame games) renders no element at all from the PHP side, so
 * there's no orphan space here. */
.trm-od-row__team-score {
    color: #d4a017;
    font-weight: 700;
    font-size: 16px;
    font-variant-numeric: tabular-nums;
    line-height: 1;
    min-width: 24px;
    text-align: right;
    flex-shrink: 0;
}

.trm-od-row--final .trm-od-row__team-name,
.trm-od-row--final .trm-od-row__team-meta {
    color: #6b7280;
}

/* Finished games desaturate the gold score the same way the card
 * layout dims its team text — keeps finals visually quiet. */
.trm-od-row--final .trm-od-row__team-score {
    color: #9ca3af;
}

/* ---- Odds cell (link or span inside <td>) ----
 * Sized to match the card-layout .trm-od-odds box exactly
 * (same min-height, padding, and line-height) so an odds box
 * looks identical whether the operator chose the cards layout
 * or the stacked-table layout. min-width keeps the box from
 * collapsing in narrow table cells. */
.trm-od-row__odds {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-width: 60px;
    min-height: 30px;
    padding: 2px 3px;
    border: 1px solid #10b981;
    border-radius: 3px;
    background: #fff;
    color: inherit;
    text-decoration: none;
    line-height: 1.1;
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease;
}

.trm-od-row__odds:hover {
    background: var(--trm-od-scoreboard-accent-bg);
}

.trm-od-row__odds:focus-visible {
    outline: 2px solid #10b981;
    outline-offset: 1px;
}

/* Finished-game odds boxes drop the emerald to neutral grey —
 * they're not actionable for the user anymore. */
.trm-od-row--final .trm-od-row__odds {
    border-color: #d1d5db;
    background: #fafafa;
    cursor: default;
}

.trm-od-row--final .trm-od-row__odds:hover {
    background: #f3f4f6;
}

/* ---- Footer ----
 * Mirrors the cards layout footer exactly: weather summary on the
 * left, optional LIVE/PREGAME pill + "Odds provided by X" on the
 * right. Flex with space-between so the two ends anchor visually
 * opposite to the venue strip at the top of the row (which also
 * splits date/time left, venue right). */
.trm-od-row__footer {
    display: flex;
    justify-content: space-between;
    /* Center alignment instead of baseline — the attribution span
     * uses inline-flex (so the LIVE/PREGAME pill aligns with the
     * text), and inline-flex elements report their baseline at the
     * bottom of the box, not the text baseline. With baseline
     * alignment that drags the weather text downward to match the
     * attribution's bottom-of-box, leaving a visible gap above the
     * weather. align-items:center sidesteps that. */
    align-items: center;
    gap: 12px;
    /* Tight vertical padding so the weather/attribution strip
     * doesn't take more space than the team rows above it. */
    padding: 3px 12px;
    border-top: 1px solid #f1f1f4;
    font-size: 12px;
    line-height: 1.4;
    color: #9ca3af;
}

.trm-od-row__weather {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.trm-od-row__attribution {
    display: inline-flex;
    align-items: center;
    gap: 0;
    flex-shrink: 0;
}

.trm-od-row__affiliate {
    text-decoration: underline;
    text-decoration-color: #d1d5db;
    text-underline-offset: 2px;
    color: #6b7280;
    margin-left: 2px;
}

/* Responsive — at narrow widths the 4-col table gets tight. Drop
 * the team-cell to be slimmer so the odds columns keep their
 * minimum width. Below ~520px the user can horizontally scroll
 * the table within its container — we don't try to stack into
 * mini-cards because that'd just be re-implementing the card
 * layout inside the table layout. */
@media (max-width: 640px) {
    .trm-od-row__th,
    .trm-od-row__team-cell,
    .trm-od-row__cell {
        padding-left: 8px;
        padding-right: 4px;
    }
    .trm-od-row__team-name { font-size: 12px; }
    .trm-od-row__th { font-size: 10px; }
    .trm-od-row__odds { min-width: 52px; min-height: 30px; padding: 2px 3px; }
}

/* ============================================================
 * Futures block (.trm-od--futures)
 *
 * One card per outcome. Cards stack in a responsive grid — at
 * full width 2 columns, narrows to 1 column on mobile. Each
 * card has the outcome name on the left and the cascade-chosen
 * odds box on the right. The odds box reuses .trm-od-odds so
 * it visually belongs to the scoreboard family.
 * ============================================================ */
/* Base grid declaration only — display, gap, and the bit of
 * top spacing. Column template is supplied by the shared
 * .trm-od--cols-N rules near the top of this file (which target
 * both .trm-od__grid and .trm-od-futures__grid).
 *
 * NOTE: deliberately no `grid-template-columns` here. This rule
 * has the same specificity as `.trm-od--cols-N .trm-od-futures__grid`
 * but sits later in the source, so any column template declared
 * in this block would override the cols-N rules and lock the
 * futures grid at one column count regardless of the modifier.
 * Leaving the template out lets the cols-N rules drive it. */
.trm-od--futures .trm-od-futures__grid {
    display: grid;
    gap: 6px 8px; /* row-gap 6, column-gap 8 — tighten vertical stacking between cards */
    margin-top: 8px;
}

.trm-od-futures-card {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 6px 10px;
    border: 1px solid #e5e7eb;
    border-radius: 6px;
    font-size: 12.5px;
}

.trm-od-futures-card__name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: #111827;
    font-weight: 500;
}

/* The .trm-od-odds--futures modifier locks a comfortable width
 * for the price box and tightens it vertically. The base
 * .trm-od-odds class (defined in the scoreboard section above)
 * already supplies the emerald border, hover state, focus ring,
 * and tabular-nums typography.
 *
 * Vertical overrides: scoreboard cells hold two text rows
 * (line value + price) and need ~30px of room, but futures
 * cells show a single price line. Shrink the min-height and
 * zero out the inherited vertical padding so the box collapses
 * to roughly content height, condensing each futures card. The
 * inherited `align-self: stretch` would re-stretch the box to
 * the parent flex card's height — switch to `center` so the
 * card shrinks along with the box. */
.trm-od-odds--futures {
    min-width: 70px;
    flex-shrink: 0;
    /* Tighter than scoreboard's 30px but still gives the price
     * some breathing room — text is ~16-18px, this leaves a
     * couple px of air top and bottom. */
    min-height: 24px;
    padding-top: 2px;
    padding-bottom: 2px;
    align-self: center;
}

/* Align scores to the left edge on final games so the digits in
 * the away and home rows occupy the same x-position regardless of
 * whether either row carries a ::after checkmark. Without this,
 * centered/right alignment shifts the digits when the checkmark
 * appears on one row but not the other. Scoped to --final so
 * live/scheduled games keep their original centered (cards) or
 * right-aligned (table) score placement. */
.trm-od-card--final .trm-od-team__score {
    text-align: left;
}
.trm-od-row--final .trm-od-row__team-score {
    text-align: left;
}

/* ============================================================
 *  Final-game winner highlight
 * ============================================================
 * The losing team keeps the standard .--final dim treatment
 * inherited from the parent card/row. The winning team's row
 * carries a --winner modifier so we can override that dim
 * back to full color and bump the name to bold — making the
 * outcome scannable at a glance in a grid of completed games.
 *
 * Small green chevron sits before the team name as a redundant
 * cue for readers who don't rely on color contrast.
 */

/* ---- Cards layout ---- */
.trm-od-card--final .trm-od-team--winner .trm-od-team__name {
    color: #111827;
    font-weight: 700;
}
.trm-od-card--final .trm-od-team--winner .trm-od-team__record {
    color: #4b5563;
}
.trm-od-card--final .trm-od-team--winner .trm-od-team__score {
    color: var(--trm-od-scoreboard-accent-text);
    font-weight: 700;
}
.trm-od-card--final .trm-od-team--winner .trm-od-team__score::after {
    /* Small inline checkmark to the right of the score number.
     * Compact font + tight margin so it fits inside the 26px
     * score grid column for typical 1-2 digit scores; 3-digit
     * scores will overflow slightly into the 5px column gap,
     * which is acceptable for the rare blowout. */
    content: "\2713";          /* ✓ U+2713 CHECK MARK */
    color: var(--trm-od-scoreboard-accent);
    margin-left: 3px;
    font-size: 1.15em;
    font-weight: 700;
}

/* ---- Table layout ---- */
.trm-od-row--final .trm-od-row__team--winner .trm-od-row__team-name {
    color: #111827;
    font-weight: 700;
}
.trm-od-row--final .trm-od-row__team--winner .trm-od-row__team-meta {
    color: #4b5563;
}
.trm-od-row--final .trm-od-row__team--winner .trm-od-row__team-score {
    color: var(--trm-od-scoreboard-accent-text);
    font-weight: 700;
}
.trm-od-row--final .trm-od-row__team--winner .trm-od-row__team-score::after {
    /* Same inline checkmark for the table layout. The score sits
     * inside a flex row with flexible width, so there's no grid
     * column to overflow — the checkmark just sits to the right
     * of the digits. */
    content: "\2713";
    color: var(--trm-od-scoreboard-accent);
    margin-left: 4px;
    font-size: 1.15em;
    font-weight: 700;
}

/* ============================================================
 * Final-game period scores (line score)
 * ============================================================
 * When a card or table row represents a finished game and the API
 * returned per-period scores, the renderer swaps the 3-cell odds
 * area for a per-sport line score. The grid template is driven by
 * a --period-count CSS custom property the PHP sets on the body
 * element, so the same CSS adapts to 3 (NHL), 4 (NFL/NBA), 9
 * (MLB), or more (extras / OT) periods. */

/* Cards layout ------------------------------------------------- */
.trm-od-card__body--periods {
    display: grid;
    /* Team identity flexes on the left; then up to 4 period cells
     * (renderer caps the visible count, default 4); then a wider,
     * bolder final-total cell on the right edge. Cells are sized
     * generously now that we're not trying to fit 9 innings — the
     * extra breathing room helps the numbers land where the eye
     * expects them on a scoreboard line. */
    grid-template-columns:
        minmax(0, 1fr)
        repeat(var(--period-count, 4), 30px)
        40px;
    column-gap: 4px;
    row-gap: 3px;
    align-items: center;
    padding: 4px 0 3px;
}

/* Period-mode header row reuses the display:contents trick so the
 * little 1/2/3/F header spans flow directly into the parent grid. */
.trm-od-card__col-headers--periods {
    display: contents;
}
.trm-od-card__col-headers--periods > span {
    font-size: 11px;
    color: #9ca3af;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    text-align: center;
    font-weight: 600;
    padding-bottom: 2px;
}
/* First slot is the empty team-name placeholder — keep it blank so
 * the column headers align with their cells, not the team name. */
.trm-od-card__col-headers--periods > .trm-od-period-header--label {
    text-align: left;
}
.trm-od-card__col-headers--periods > .trm-od-period-header--final {
    color: #111827;
    font-weight: 700;
}

/* Each period cell — small tabular-num number centered in its
 * slot. Final cell uses bolder weight to stand apart from the
 * period numbers. */
.trm-od-period {
    text-align: center;
    font-variant-numeric: tabular-nums;
    font-size: 14px;
    color: #1f2937;
    line-height: 1.3;
}
.trm-od-period--final {
    font-weight: 700;
    color: #111827;
    font-size: 15px;
}

/* In a final card the loser's text is already dimmed via the
 * --final modifier on the parent card. Apply the same dim to
 * period numbers + un-dim them on the winner row. */
.trm-od-card--final .trm-od-period {
    color: #6b7280;
}
.trm-od-card--final .trm-od-team--winner .trm-od-period {
    color: #111827;
}
.trm-od-card--final .trm-od-team--winner .trm-od-period--final {
    color: var(--trm-od-scoreboard-accent-text); /* green like the winner's total score */
}

/* AT separator inside the periods grid — span all columns. */
.trm-od-card__at--periods {
    grid-column: 1 / -1;
}

/* Tighten period cells further when there are many of them (MLB
 * with 9 innings) to avoid squeezing the team-name column. The
 * --period-count value is exposed to JS via getComputedStyle but
 * CSS itself can't read it as a number — so just use a generic
 * narrower padding at small card widths. */
@media (max-width: 540px) {
    .trm-od-card__body--periods {
        grid-template-columns:
            minmax(0, 1fr)
            repeat(var(--period-count, 4), 24px)
            32px;
        column-gap: 3px;
    }
    .trm-od-period { font-size: 13px; }
    .trm-od-period--final { font-size: 14px; }
}

/* Table layout ------------------------------------------------- */
/* Same idea as cards: replace the 3 odds <th>/<td>s with N period
 * cells plus a bold final cell. Native <table> handles the column
 * sizing — we just need to style the cells and dim the loser. */
.trm-od-row__th--period,
.trm-od-row__cell--period {
    text-align: center;
    font-variant-numeric: tabular-nums;
    padding: 6px 10px;
    min-width: 36px;
}
.trm-od-row__th--period {
    font-size: 11px;
    font-weight: 600;
    color: #6b7280;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}
.trm-od-row__th--final,
.trm-od-row__cell--final {
    text-align: center;
    font-variant-numeric: tabular-nums;
    padding: 6px 12px;
    min-width: 44px;
    font-weight: 700;
}
.trm-od-row__th--final {
    font-size: 11px;
    color: #1f2937;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.trm-od-row__cell--period {
    color: #1f2937;
    font-size: 15px;
}
.trm-od-row__cell--final {
    color: #111827;
    font-size: 16px;
}
.trm-od-row--final .trm-od-row__cell--period {
    color: #6b7280;
}
.trm-od-row--final .trm-od-row__team--winner .trm-od-row__cell--period {
    color: #111827;
}
.trm-od-row--final .trm-od-row__team--winner .trm-od-row__cell--final {
    color: var(--trm-od-scoreboard-accent-text);
}

/* Winner checkmark for period-mode finals.
 * The team name carries the indicator instead of the F-total cell
 * — keeps the result attached to the team identity rather than to
 * a number that already reads as a final score on its own. Selectors
 * are scoped to period-mode parents (.trm-od-card__body--periods /
 * .trm-od-row__table--periods) so the odds-mode rendering keeps
 * its score-column checkmark unchanged. */
.trm-od-card--final .trm-od-card__body--periods .trm-od-team--winner .trm-od-team__name::after {
    content: "\2713";          /* ✓ U+2713 CHECK MARK */
    color: var(--trm-od-scoreboard-accent);
    margin-left: 5px;
    font-size: 1.15em;
    font-weight: 700;
    /* Keep the glyph inline with the team-name baseline. */
    display: inline-block;
    vertical-align: baseline;
}

.trm-od-row--final .trm-od-row__table--periods .trm-od-row__team--winner .trm-od-row__team-name::after {
    content: "\2713";
    color: var(--trm-od-scoreboard-accent);
    margin-left: 5px;
    font-size: 1.15em;
    font-weight: 700;
    display: inline-block;
    vertical-align: baseline;
}

/* Winner's final-total cell — green box matching the checkmark.
 * Cards: the .trm-od-period--final is a span inside a CSS grid
 *   cell. We give it a real border + light-green background; the
 *   parent grid column is 40px (32px on narrow), so box-sizing
 *   keeps the border inside that allotment.
 * Tables: the same effect on the <td> via inset box-shadow so the
 *   td's intrinsic width/height isn't shifted by adding a border. */
.trm-od-card--final .trm-od-card__body--periods .trm-od-team--winner .trm-od-period--final {
    display: block;
    box-sizing: border-box;
    border: 1.5px solid var(--trm-od-scoreboard-accent);
    border-radius: 3px;
    background: var(--trm-od-scoreboard-accent-bg);
    padding: 1px 0;
    color: var(--trm-od-scoreboard-accent-text);
}

.trm-od-row--final .trm-od-row__table--periods .trm-od-row__team--winner .trm-od-row__cell--final {
    box-shadow: inset 0 0 0 1.5px var(--trm-od-scoreboard-accent);
    background: var(--trm-od-scoreboard-accent-bg);
    color: var(--trm-od-scoreboard-accent-text);
    border-radius: 3px;
}

/* ============================================================
 *  Featured Lines block
 * ============================================================
 * Reuses the scoreboard's card chrome (.trm-od-card +
 * .trm-od-card__header / __title / __when) so the visual
 * language stays identical across blocks. Featured-lines-
 * specific bits below cover the body content only — a three-
 * pill odds row and a small affiliate footer.
 *
 * Outer container shares the scoreboard's .trm-od__grid layout
 * so the responsive 1/2/3-col rules above apply for free. The
 * `card_count` block attribute controls how many cards render
 * (1-3); CSS doesn't know or care. */

.trm-od-card--featured-line {
    /* Most of the chrome is inherited from .trm-od-card. We
     * only need to override the body padding back up since the
     * default scorecard card uses tight 5px top padding to make
     * the team-row grid hug the header strip; featured-lines
     * has a different body shape and benefits from a bit more
     * vertical breathing room around the odds pills. */
    padding-bottom: 8px;
}

/* Inherit the grey strip from .trm-od-card__header. Title goes
 * on the left (Away @ Home), kickoff time on the right —
 * justify-content: space-between is already set on the parent
 * selector. We just need text styling for the title since it
 * doesn't exist in the scoreboard card. */
.trm-od-card--featured-line .trm-od-card__title {
    font-weight: 600;
    color: #1f2937;
    font-size: 13px;
    line-height: 1.25;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
    flex: 1 1 auto;
}

/* Criterion row — small "Why: X" line that surfaces the API's
 * scoring rule (Longest Underdog / Biggest Spread / Highest
 * Total). Sits between the grey header strip and the odds rows.
 * Lightweight type weight so it doesn't compete with the
 * matchup name above or the odds pills below. */
.trm-od-featured-line__criterion {
    display: flex;
    align-items: baseline;
    gap: 6px;
    padding: 4px 0 0;
    font-size: 11px;
    line-height: 1.3;
}

.trm-od-featured-line__criterion-label {
    color: #9ca3af;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.trm-od-featured-line__criterion-value {
    color: var(--trm-od-featured-highlight);
    font-weight: 600;
}

/* Content wrapper inside the card — separate from the
 * scoreboard's .trm-od-card__body so we don't inherit its
 * 5-column grid. Just a vertical stack of the odds row plus
 * the small affiliate footer. */
.trm-od-featured-line__content {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 6px 0 2px;
}

/* Three stacked rows — each row puts the market label on the
 * left and the value box on the right. The label column is a
 * fixed-ish width so the value boxes line up vertically across
 * the three rows, regardless of label text length. */
.trm-od-featured-line__odds {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.trm-od-featured-line__odds-cell {
    /* 40 / 60 split — label column on the left, value box on the
     * right at roughly 60% of the card's interior width. 2fr / 3fr
     * keeps the three rows perfectly aligned vertically and scales
     * with the card width on narrow viewports. */
    display: grid;
    grid-template-columns: 2fr 3fr;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.trm-od-featured-line__odds-label {
    color: #6b7280;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    text-align: left;
}

/* Value box — rendered as a rounded rectangle. Either an <a>
 * (when the pick has an affiliate URL) or a <span> fallback;
 * both classes get the same dimensions so hover-affordance is
 * the only visual difference. The fixed 144px grid column above
 * sets the width; the pill stretches to fill it. */
.trm-od-featured-line__odds-pill {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    background: #f3f4f6;
    border: 1px solid #e5e7eb;
    color: #111827;
    font-weight: 500;
    font-size: 12px;
    line-height: 1.2;
    padding: 6px 10px;
    border-radius: 5px;
    text-align: center;
    min-height: 28px;
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    box-sizing: border-box;
    transition: background-color 120ms ease, border-color 120ms ease;
}

/* Anchor variant — hover/focus state for the clickable pills.
 * Subtle background bump signals "this opens the book" without
 * underlining the value (which would look weird on odds digits). */
a.trm-od-featured-line__odds-pill:hover,
a.trm-od-featured-line__odds-pill:focus {
    background: #e5e7eb;
    border-color: #d1d5db;
    color: #111827;
    text-decoration: none;
}

/* Highlighted cell — blue tint to call out the best pick
 * of the three markets for this game. Both label + pill flip
 * to blue so the column reads as one unit. */
.trm-od-featured-line__odds-cell--highlight .trm-od-featured-line__odds-pill {
    background: var(--trm-od-featured-highlight-bg);
    border-color: var(--trm-od-featured-highlight-border);
    color: var(--trm-od-featured-highlight);
    box-shadow: 0 0 0 1px var(--trm-od-featured-highlight-border) inset;
}

/* Highlighted + clickable: deepen the blue on hover so the
 * "best pick" call-to-action reads as the obvious target. */
a.trm-od-featured-line__odds-cell--highlight .trm-od-featured-line__odds-pill:hover,
.trm-od-featured-line__odds-cell--highlight a.trm-od-featured-line__odds-pill:hover,
.trm-od-featured-line__odds-cell--highlight a.trm-od-featured-line__odds-pill:focus {
    background: var(--trm-od-featured-highlight-hover-bg);
    border-color: var(--trm-od-featured-highlight);
    color: var(--trm-od-featured-highlight);
}

.trm-od-featured-line__odds-cell--highlight .trm-od-featured-line__odds-label {
    color: var(--trm-od-featured-highlight);
}

/* ============================================================
 *  Team Stats block — leaderboard table
 * ============================================================
 * Replaces the earlier card-style layout. Renders one <table>
 * with rank | team | league | configurable stat columns. The
 * active sort column gets a subtle grey background highlight
 * (header + body cells both) so the operator can see which stat
 * the API actually sorted on.
 *
 * Stat values come pre-formatted from the API (".243", "3.20",
 * etc.) — the renderer just prints them. Numeric tabular-nums
 * keeps the digit columns vertically aligned even when a row
 * has a smaller value (".07" next to ".333").
 *
 * Horizontal scroll wrapper: a 16-stat hitting table on a
 * narrow content column overflows the page. .scroller wraps
 * the table in an overflow-x:auto so the row stays readable
 * without forcing the operator to enable full-width alignment. */

.trm-od--team-stats {
    /* Inherits .trm-od top margin (1.25em) so the block has the
     * same vertical rhythm as the other blocks. */
}

/* --- Tabs ---------------------------------------------------
 * Visitor-facing toggle that switches between the categories
 * the API ships (Batting / Pitching / Fielding for MLB, etc.).
 * Clean underline-tab style matches the screenshot the design
 * was built from. Active tab gets a thicker accent-coloured
 * border; hover state on the others previews the affordance. */
.trm-od-team-stats__tabs {
    display: flex;
    align-items: stretch;
    gap: 0;
    margin: 0 0 12px;
    padding: 0;
    border-bottom: 1px solid #e5e7eb;
    overflow-x: auto;
    /* Chrome promotes overflow-y to "auto" whenever overflow-x !=
     * visible. Pin overflow-y to hidden so the strip doesn't
     * sprout a vertical scrollbar (with up/down arrows) when
     * the tabs fit fine on screen. */
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
}

.trm-od-team-stats__tab {
    appearance: none;
    background: transparent;
    border: 0;
    border-bottom: 2px solid transparent;
    margin: 0;
    padding: 8px 18px 10px;
    font-size: 14px;
    font-weight: 700;
    color: #6b7280;
    cursor: pointer;
    line-height: 1.2;
    transition: color 120ms ease, border-color 120ms ease;
    white-space: nowrap;
    margin-bottom: -1px;  /* pull tab onto the strip's bottom border */
}

.trm-od-team-stats__tab:hover,
.trm-od-team-stats__tab:focus {
    color: #111827;
    outline: none;
}

.trm-od-team-stats__tab.is-active {
    color: #111827;
    border-bottom-color: var(--trm-od-scoreboard-accent, #111827);
}

/* --- Views -------------------------------------------------- */
.trm-od-team-stats__view {
    display: none;
}

.trm-od-team-stats__view.is-active {
    display: block;
}

.trm-od-team-stats__scroller {
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
}

.trm-od-team-stats__table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
    line-height: 1.3;
    color: #1f2937;
}

/* --- Header row ---------------------------------------------
 * Uppercase, letter-spaced labels in muted grey. Bottom border
 * separates header from body without competing with the cell-
 * level dotted underlines. */
.trm-od-team-stats__th {
    padding: 10px 8px;
    text-align: right;
    vertical-align: bottom;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: #6b7280;
    border-bottom: 1px solid #e5e7eb;
    white-space: nowrap;
}

/* The rank column has no header label — keep it narrow + flush
 * left so the row numbers below sit cleanly beneath nothing. */
.trm-od-team-stats__th--rank {
    width: 28px;
    text-align: left;
    padding-left: 4px;
    padding-right: 4px;
}

.trm-od-team-stats__th--team,
.trm-od-team-stats__th--league {
    text-align: left;
}

.trm-od-team-stats__th--team {
    padding-left: 4px;
    min-width: 140px;
}

.trm-od-team-stats__th--league {
    padding-left: 12px;
    padding-right: 12px;
}

/* Active sort column — both the header and every cell in that
 * column get a faint grey tint so the eye can lock onto the
 * sorted axis. is-sort modifier comes from the renderer based
 * on the resolved sort key. */
.trm-od-team-stats__th.is-sort {
    background: #f3f4f6;
    color: #111827;
}

/* --- Body rows ----------------------------------------------
 * Per-cell padding mirrors the header so columns stay aligned.
 * Right-aligned for numerics; team/league columns override. */
.trm-od-team-stats__td {
    padding: 10px 8px;
    text-align: right;
    border-bottom: 1px solid #f3f4f6;
    font-variant-numeric: tabular-nums;
    color: #1f2937;
    white-space: nowrap;
}

.trm-od-team-stats__td--rank {
    color: #9ca3af;
    font-weight: 500;
    text-align: left;
    padding-left: 4px;
    padding-right: 4px;
    font-variant-numeric: tabular-nums;
}

.trm-od-team-stats__td--team {
    text-align: left;
    padding-left: 4px;
    font-weight: 700;
    color: #111827;
    white-space: nowrap;
}

.trm-od-team-stats__td--league {
    text-align: left;
    padding-left: 12px;
    padding-right: 12px;
    color: #6b7280;
    font-weight: 600;
}

/* Sort-column tint on body cells. Slightly lighter than the
 * header tint so the row's existing background-on-hover (if
 * any) can layer on top without fighting. */
.trm-od-team-stats__td.is-sort {
    background: #f9fafb;
    color: #111827;
    font-weight: 600;
}

/* Last row drops its bottom border so the table tail reads
 * clean against whatever sits below. */
.trm-od-team-stats__table tbody tr:last-child .trm-od-team-stats__td {
    border-bottom: 0;
}

/* Subtle row-hover affordance — helps the eye track across a
 * long row when stats are densely packed. Skips on touch
 * because hover misfires on tap. */
@media (hover: hover) {
    .trm-od-team-stats__row:hover .trm-od-team-stats__td {
        background: #fbfbfd;
    }
    .trm-od-team-stats__row:hover .trm-od-team-stats__td.is-sort {
        background: #f1f3f6;
    }
}

/* ---- No-vig win probability bar (derived from moneyline) ---- */
.trm-od-winprob{margin-top:.6rem;padding-top:.55rem;border-top:1px solid rgba(0,0,0,.06);}
.trm-od-winprob__head{font-size:.62rem;letter-spacing:.06em;text-transform:uppercase;color:#8a8f98;margin-bottom:.3rem;text-align:center;}
.trm-od-winprob__bar{display:flex;height:8px;border-radius:999px;overflow:hidden;background:#e9ebee;}
.trm-od-winprob__seg{display:block;height:100%;}
/* Favored side green ("good"), underdog red, exact pick'em neutral. */
.trm-od-winprob__seg--fav{background:#16a34a;}
.trm-od-winprob__seg--dog{background:#dc2626;}
.trm-od-winprob__seg--even{background:#9ca3af;}
.trm-od-winprob__labels{display:flex;justify-content:space-between;margin-top:.3rem;font-size:.72rem;font-weight:600;color:#4b5563;}
.trm-od-winprob__pct--fav{color:#15803d;}
.trm-od-winprob__pct--dog{color:#b91c1c;}
.trm-od-winprob__pct--even{color:#6b7280;}

/* ---- Multi-panel card layout (odds | meta | probable pitchers) ---- */
.trm-od-card--panels .trm-od-card__panels{display:flex;flex-wrap:wrap;align-items:stretch;}
.trm-od-card--panels .trm-od-card__panel{padding:10px 14px;}
.trm-od-card--panels .trm-od-card__panel--odds{flex:1 1 320px;min-width:300px;}
.trm-od-card--panels .trm-od-card__panel--meta{flex:1 1 180px;min-width:170px;border-left:1px solid rgba(0,0,0,.06);}
.trm-od-card--panels .trm-od-card__panel--pitchers{flex:1 1 150px;min-width:150px;border-left:1px solid rgba(0,0,0,.06);}
.trm-od-card--panels .trm-od-card__panel--odds .trm-od-card__body{padding:0;}
.trm-od-meta__line{font-size:.78rem;color:#4b5563;margin-bottom:.4rem;}
.trm-od-card__panel--meta .trm-od-winprob{border-top:0;margin-top:.5rem;padding-top:0;}
.trm-od-panel__cap{font-size:.62rem;letter-spacing:.06em;text-transform:uppercase;color:#8a8f98;margin:0 0 .45rem;}
.trm-od-pitchers__row{margin-bottom:.55rem;}
/* Line 1: name + hand + team (team smaller/muted, on the same line). */
.trm-od-pitchers__head{display:block;line-height:1.2;}
.trm-od-pitchers__name{font-size:.85rem;font-weight:600;color:#1f2937;}
.trm-od-pitchers__num{font-size:.7rem;color:#9ca3af;margin-left:4px;}
.trm-od-pitchers__hand{font-size:.7rem;color:#6b7280;margin-left:6px;}
.trm-od-pitchers__team{font-size:.62rem;letter-spacing:.04em;text-transform:uppercase;color:#9ca3af;margin-left:6px;}
/* Line 2: season W-L · ERA. */
.trm-od-pitchers__stats{display:block;font-size:.7rem;color:#6b7280;margin-top:.1rem;}
/* Phone: panels stack full-width; dividing left-borders become top-borders. */
@media (max-width:600px){
  .trm-od-card--panels .trm-od-card__panel--meta,
  .trm-od-card--panels .trm-od-card__panel--pitchers{border-left:0;border-top:1px solid rgba(0,0,0,.06);flex-basis:100%;}
}

/* Keep the odds body compact inside the panel layout regardless of the
   block's column setting — the odds panel is the phone-width column. */
.trm-od-card--panels .trm-od-card__panel--odds .trm-od-card__body{
  grid-template-columns: minmax(0,1fr) 26px 62px 62px 62px;
  column-gap:5px;
}

/* Column-segmented card header — segments mirror the panel flex widths so the
   "Probable pitchers" label lines up over the pitchers panel. Drop the
   edge-bleed margins so the segment x-offsets match the panels (card padding). */
.trm-od-card--panels .trm-od-card__header--cols{
  display:flex;align-items:baseline;gap:0;margin:-5px -8px 6px;padding:7px 0;
}
.trm-od-card__hcol{padding:0 14px;}
.trm-od-card__hcol--odds{flex:1 1 320px;min-width:300px;}
.trm-od-card__hcol--pitchers{flex:1 1 150px;min-width:150px;border-left:1px solid transparent;font-size:.66rem;letter-spacing:.06em;text-transform:uppercase;color:#6b7280;}
.trm-od-card__hcol--meta{flex:1 1 180px;min-width:170px;border-left:1px solid transparent;display:flex;justify-content:flex-end;}

/* Align the header segments to the panel origin (no horizontal edge-bleed) so
   the column labels sit exactly over their panels. */
.trm-od-card--panels .trm-od-card__header--cols{margin-left:0;margin-right:0;}

/* Center each pitcher on its team's odds row: offset past the column-header
   row (~14px + 2px row-gap), then two equal flex slots that center their
   content — since both team rows are equal height, each pitcher lands on its
   row. Tune --offset / --gap if it sits a hair high or low. */
.trm-od-card__panel--pitchers{display:flex;flex-direction:column;}
.trm-od-pitchers__offset{flex:0 0 16px;}
.trm-od-pitchers__gap{flex:0 0 18px;}
.trm-od-pitchers__slot{flex:1 1 0;display:flex;flex-direction:column;justify-content:center;}
.trm-od-card__panel--pitchers .trm-od-pitchers__row{margin-bottom:0;}

/* ============================================================
 * Team Summary block
 * A vertical stack of card "boxes": division standings,
 * conference standings, and a stat-tile summary. Each box is a
 * rounded panel matching the rest of the plugin's light theme.
 * ============================================================ */
/* Boxes sit side by side in a single row. flex:1 on each child means
 * the column count follows the number of visible boxes automatically:
 * three boxes -> three columns, two -> two, one -> full width. Stacks
 * on narrow screens (see the media query below). */
.trm-od--summary{
    display:flex;
    flex-direction:row;
    align-items:flex-start;   /* each box keeps its natural height, no stretch-to-tallest */
    gap:16px;
}
.trm-od-summary-box{
    flex:1 1 0;
    min-width:0;          /* let the standings table shrink instead of overflowing a narrow column */
    background:#fff;
    border:1px solid #e5e7eb;
    border-radius:12px;
    padding:16px 18px;
    box-shadow:0 1px 2px rgba(0,0,0,0.04);
}
/* Stack the boxes once a single row would crush them. In column mode
 * align-items:flex-start (kept for natural heights in the row) would
 * otherwise shrink each box to its content width, so pin them to full
 * width so every stacked box — and the table/tiles inside it — spans
 * the parent. */
@media (max-width: 782px){
    .trm-od--summary{flex-direction:column;}
    .trm-od-summary-box{width:100%;}
}
.trm-od-summary-box__title{
    margin:0 0 12px;
    font-size:1.05em;
    font-weight:700;
    color:#111827;
}
.trm-od-summary-box__note{
    margin:10px 0 0;
    font-size:11px;
    line-height:1.4;
    color:#9ca3af;
}

/* ---- Standings table (Team / W / L / T / PCT) ----
 * Compact but readable: a single hairline under the header, no
 * per-row rules, tight vertical rhythm, and centered tabular stat
 * columns that stay aligned down the table. The team column takes the
 * slack so the stat columns hug their content on the right. */
.trm-od-summary-standings{
    width:100%;
    border-collapse:collapse;
    font-size:13px;
    line-height:1.25;
}
.trm-od-summary-standings thead th{
    font-size:10px;
    font-weight:600;
    text-transform:uppercase;
    letter-spacing:0.04em;
    color:#9ca3af;
    padding:0 10px 7px;
    border-bottom:1px solid #e5e7eb;
    white-space:nowrap;
}
.trm-od-summary-standings tbody td{
    /* Horizontal padding gives the text room from the cell dividers;
     * vertical padding stays at 6px so the box height (matched to the
     * Team Stats box) doesn't change. */
    padding:6px 10px;
    color:#4b5563;
    white-space:nowrap;
}
.trm-od-summary-standings tbody tr:first-child td{padding-top:9px;}
/* Team column — left, flexible, wraps instead of overflowing a
 * narrow (sidebar) column. Sits flush to the box's left edge. */
.trm-od-summary-standings th.trm-od-summary-standings__team,
.trm-od-summary-standings td.trm-od-summary-standings__team{
    text-align:left;
    width:100%;
    padding-left:0;
    white-space:normal;
    color:#374151;
}
/* Stat columns — centered, shrink-to-content, tabular figures. */
.trm-od-summary-standings th.trm-od-summary-standings__num,
.trm-od-summary-standings td.trm-od-summary-standings__num{
    text-align:center;
    width:1%;
    font-variant-numeric:tabular-nums;
}
.trm-od-summary-standings tbody tr.is-active td{
    font-weight:700;
    color:#111827;
}

/* ---- Stat tiles (2-up grid with hairline dividers) ---- */
.trm-od-summary-tiles{
    display:grid;
    grid-template-columns:repeat(2, minmax(0, 1fr));
    /* Tile padding adjusts the box height in 2px steps (top+bottom
     * across two rows), so this one-off +1px lands the box on the
     * exact target height the per-tile padding can't hit alone. */
    margin-bottom:1px;
}
.trm-od-summary-tile{
    text-align:center;
    padding:9px 12px;
    border-top:1px solid #f3f4f6;
}
/* Drop the top border on the first row so the grid reads as an
 * internal divider set, not a boxed-in table. */
.trm-od-summary-tiles .trm-od-summary-tile:nth-child(1),
.trm-od-summary-tiles .trm-od-summary-tile:nth-child(2){border-top:0;}
/* Vertical divider between the two columns. */
.trm-od-summary-tile:nth-child(odd){border-right:1px solid #f3f4f6;}
.trm-od-summary-tile__label{
    font-size:13px;
    color:#6b7280;
    margin-bottom:3px;
}
.trm-od-summary-tile__value{
    font-size:23px;
    font-weight:600;
    line-height:1.15;
    color:#111827;
}
.trm-od-summary-tile__rank{
    font-size:12px;
    color:#9ca3af;
    margin-top:2px;
}

/* Single-column stack on narrow screens. Kill the column divider
 * and rely on the top borders for separation. */
@media (max-width: 480px){
    .trm-od-summary-tiles{grid-template-columns:1fr;}
    .trm-od-summary-tile{border-right:0 !important;}
    .trm-od-summary-tiles .trm-od-summary-tile:nth-child(2){border-top:1px solid #f3f4f6;}
}

/* ==================================================================
 * [trm_prop] — player prop cards
 *
 * The cards sit inside a stadium panel headed by the player's name.
 * Every surface, border, rule, mark, muted label and odds box is a
 * color-mix() of --trm-pp-accent against --trm-pp-ground; each panel
 * theme (trm-pp--theme-<name>, near the end) sets those, plus its ink
 * and heading colours.
 *
 * Nothing in here is shared with the scoreboard: these cards are
 * their own design, so restyling one never disturbs the other.
 * ================================================================== */

:root {
    /* Overridden inline by Settings → Appearance when it differs. */
    --trm-pp-accent: #2f6fed;
}

.trm-pp {
    /* ---- the two inputs -------------------------------------- */
    /* ground and ink come from the panel theme */

    /* ---- everything else, derived ----------------------------- */
    --trm-pp-surface:      color-mix(in srgb, var(--trm-pp-accent)  7%, var(--trm-pp-ground));
    --trm-pp-surface-head: color-mix(in srgb, var(--trm-pp-accent) 13%, var(--trm-pp-ground));
    --trm-pp-border:       color-mix(in srgb, var(--trm-pp-accent) 32%, var(--trm-pp-ground));
    /* Divider between outcome rows. Mixed against TRANSPARENT, not the
       ground, so the card artwork carries on through it — an opaque
       line painted a stripe across the stadium. Built from the ink so
       it inverts with the palette on its own: a faint light line on a
       dark card, a faint dark one on white. */
    --trm-pp-rule:         color-mix(in srgb, var(--trm-pp-ink) 14%, transparent);

    /* Two steps so "muted" is genuinely dimmer than ink, then tinted
       by the accent — a single mix would only shift the hue. */
    --trm-pp-dim:          color-mix(in srgb, var(--trm-pp-ink) 45%, var(--trm-pp-ground));
    --trm-pp-muted:        color-mix(in srgb, var(--trm-pp-accent) 30%, var(--trm-pp-dim));

    /* The furniture colour: the bar beside the title, the mark, the rule
       under the header and the odds box. Follows the accent by default,
       so a palette that wants one colour throughout sets nothing extra —
       but a card can now carry blue artwork and red controls, which a
       single accent could not express. */
    --trm-pp-highlight:    var(--trm-pp-accent);

    /* The stroke beside the title and the rule under it. A fixed blue
       rather than a mix of the accent; a theme can override it. */
    --trm-pp-bar:          #2f6fed;

    /* What the odds box is mixed against. Its own variable because red
       controls on a blue card must be mixed against near-black to stay
       red: mixing crimson into a navy ground turns it muddy purple. */
    --trm-pp-odds-ground:  var(--trm-pp-ground);

    /* How hard the odds box leans on the highlight. Intensity is a
       per-palette decision, not a global one: a deep crimson over
       near-black wants a much heavier fill than a mid blue over navy
       before it reads as the same design. */
    --trm-pp-odds-edge:    70%;
    --trm-pp-odds-fill:    16%;
    --trm-pp-odds-lift:    32%;

    --trm-pp-odds-border:  color-mix(in srgb, var(--trm-pp-highlight) var(--trm-pp-odds-edge), var(--trm-pp-odds-ground));
    --trm-pp-odds-bg:      color-mix(in srgb, var(--trm-pp-highlight) var(--trm-pp-odds-fill), var(--trm-pp-odds-ground));
    --trm-pp-odds-hover:   color-mix(in srgb, var(--trm-pp-highlight) var(--trm-pp-odds-lift), var(--trm-pp-odds-ground));

    /* The figures in the odds box. The ink by default; its own variable
       so a light card can carry a deep red box with white figures. */
    --trm-pp-odds-ink:     var(--trm-pp-ink);

    /* The settled line under a row. Brighter than --trm-pp-muted, which
       is tuned for the tiny uppercase attribution and is too faint at
       reading size. */
    --trm-pp-sub:          color-mix(in srgb, var(--trm-pp-ink) 74%, var(--trm-pp-ground));

    /* Settled results. Deliberately NOT mixed from the accent: hit and
       miss have to stay green and red whatever colour the card is, or
       a red-themed card would show a red tick. */
    --trm-pp-hit:          #22c55e;
    --trm-pp-miss:         #ef4444;

    --trm-pp-radius:       7px;
    --trm-pp-gap:          16px;
    --trm-pp-row-margin:   10px;

    /* The rule under the header. Brighter than --trm-pp-rule, which is
       for the quiet dividers between outcome rows. Mixed from the
       ACCENT, not the highlight: it belongs to the card surface, so it
       stays with the artwork colour even when the controls do not. */
    --trm-pp-head-rule:    color-mix(in srgb, var(--trm-pp-accent) 70%, var(--trm-pp-ground));

    /* flow-root, not block: the row of cards carries its own top and
       bottom margin, and a plain block would let those collapse out
       through this element instead of spacing the cards inside it. */
    display: flow-root;
    margin: 20px 0;
}

/* ---- the grid -------------------------------------------------- */

.trm-pp__grid {
    display: grid;
    margin: var(--trm-pp-row-margin) 0;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--trm-pp-gap);
    /* stretch, not start: side-by-side cards match the tallest in the
       row whatever they hold, so a one-outcome scorer card squares up
       with a two-outcome over/under instead of stopping short. The
       leftover height falls below the rows — see .trm-pp-card__rows. */
    align-items: stretch;
}

/* Fewer than three markets should not leave gaps at the right. */
.trm-pp--count-1 .trm-pp__grid { grid-template-columns: minmax(0, 1fr); align-items: start; }
.trm-pp--count-2 .trm-pp__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* Four sit in one row where there is room for them; below that the
   normal breakpoints take over and they fall to two by two. Five and
   six keep three across and wrap. */
@media (min-width: 901px) {
    .trm-pp--count-4 .trm-pp__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@media (max-width: 900px) {
    .trm-pp__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---- the card ------------------------------------------------- */

.trm-pp-card {
    /* Column flex so the rows region can absorb the extra height a
       stretched grid item gets, keeping the header pinned to the top
       and the spare space at the bottom. */
    display: flex;
    flex-direction: column;
    background: var(--trm-pp-surface);
    border: 1px solid var(--trm-pp-border);
    border-radius: var(--trm-pp-radius);
    overflow: hidden;
    color: var(--trm-pp-ink);
}

.trm-pp-card__head {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    background: var(--trm-pp-surface-head);
    border-bottom: 1px solid var(--trm-pp-head-rule);
}

.trm-pp-card__mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    /* The accent unless a palette gives the mark its own colour. */
    color: var(--trm-pp-mark, var(--trm-pp-accent));
}

/* The rule between mark and text is the header's only ornament. */
.trm-pp-card__titles {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
    padding-left: 12px;
    border-left: 2px solid var(--trm-pp-bar);
}

/* Status and score under the market name, on a settled card only. */
.trm-pp-card__score {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    line-height: 1.2;
    color: var(--trm-pp-muted);
}

/* Status pill at the right of the header. Neutral rather than accent
   tinted: it reports the game clock, not the book, so it should not
   compete with the mark and the bar for the eye. */
/* All caps and no descenders, so a centred line box leaves the letters
   riding high: the space reserved below the baseline for descenders is
   empty. line-height: 1 stops the theme's 1.5 adding more of it, and the
   extra 1px on top puts the caps at the true centre (7.5px of space above
   and below the letters, measured). Corners match the card's. */
.trm-pp-card__pill {
    margin-left: auto;
    flex: 0 0 auto;
    align-self: center;
    padding: 7px 12px 6px;
    border-radius: var(--trm-pp-radius);
    line-height: 1;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--trm-pp-ink);
    background: color-mix(in srgb, var(--trm-pp-ink) 16%, transparent);
}

.trm-pp-card__title {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    line-height: 1.2;
    color: var(--trm-pp-ink);
}

/* ---- rows ------------------------------------------------------ */

.trm-pp-card__rows { flex: 1 1 auto; }

/* ---- ladder cards ----------------------------------------------
 * A run of thresholds (150+, 175+ …) instead of an over/under. The
 * renderer puts ladders after the standard cards; each spans the whole
 * row beneath them and lays its rungs out three across, reading left to
 * right, so twelve rungs are four short rows rather than one tall card
 * that stretches its neighbours to match.
 *
 * Column count follows the card's own width, not the viewport, so it
 * is right in both layouts and whatever the page puts around it.
 * Dividers: a line above every rung but the first row, and a line
 * between rungs side by side — each set per column count, because
 * which rungs start a row changes with it.
 * -------------------------------------------------------------- */

.trm-pp-card--ladder {
    grid-column: 1 / -1;
    container-type: inline-size;
}

.trm-pp-card--ladder .trm-pp-card__rows {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-content: start;
}

.trm-pp-card--ladder .trm-pp-row:nth-of-type(n)          { border-top: 0; }
.trm-pp-card--ladder .trm-pp-row:nth-of-type(n+4)        { border-top: 1px solid var(--trm-pp-rule); }
.trm-pp-card--ladder .trm-pp-row:not(:nth-of-type(3n+1)) { border-left: 1px solid var(--trm-pp-rule); }

/* The settled result, once for the whole ladder. */
.trm-pp-card__actual {
    grid-column: 1 / -1;
    margin: 0;
    padding: 8px 16px;
    border-bottom: 1px solid var(--trm-pp-rule);
    font-size: 12px;
    font-weight: 500;
    color: var(--trm-pp-sub);
}

@container (max-width: 840px) {
    .trm-pp-card--ladder .trm-pp-card__rows { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .trm-pp-card--ladder .trm-pp-row:nth-of-type(n)          { border-top: 0; border-left: 0; }
    .trm-pp-card--ladder .trm-pp-row:nth-of-type(n+3)        { border-top: 1px solid var(--trm-pp-rule); }
    .trm-pp-card--ladder .trm-pp-row:nth-of-type(2n)         { border-left: 1px solid var(--trm-pp-rule); }
}

@container (max-width: 480px) {
    .trm-pp-card--ladder .trm-pp-card__rows { grid-template-columns: minmax(0, 1fr); }
    .trm-pp-card--ladder .trm-pp-row:nth-of-type(n)          { border-top: 0; border-left: 0; }
    .trm-pp-card--ladder .trm-pp-row:nth-of-type(n+2)        { border-top: 1px solid var(--trm-pp-rule); }
}

/* Equal card height alone still leaves the header rules ragged when one
   title wraps to two lines and its neighbour does not — the rows then
   start at different heights across the row. subgrid puts every card's
   header in a shared track so the rules line up and the outcomes start
   level. Behind @supports because the flex rules above already give
   equal heights on their own; a browser without subgrid keeps exactly
   today's result rather than losing anything. */
@supports (grid-template-rows: subgrid) {
    .trm-pp__grid {
        grid-template-rows: auto 1fr;
        /* Wrapped rows of cards — and the ladder card below the row —
           get auto, not another 1fr. In a grid of unset height every
           1fr track is sized to the largest of them, so a 1fr here made
           the standard cards' rows as tall as the ladder's and left
           them mostly empty. Cards sharing a row still match, since
           they share the track. */
        grid-auto-rows: auto auto;
    }
    .trm-pp-card {
        display: grid;
        grid-template-rows: subgrid;
        grid-row: span 2;
        /* A subgrid inherits the parent grid's gap, so the 16px meant to
           separate cards was also opening between the header and the
           outcomes inside every card. The card wants no internal gap —
           its own borders and padding do that work. */
        row-gap: 0;
    }
}

.trm-pp-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    padding: 8px 16px;
}

.trm-pp-row + .trm-pp-row { border-top: 1px solid var(--trm-pp-rule); }

/* Left side of a row: the line, plus the settled result beneath it on
   a fallback card. A column so the odds box stays vertically centred
   against both together rather than against the line alone. */
.trm-pp-row__text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1 1 auto;
    min-width: 0;
}

.trm-pp-row__actual {
    font-size: 12px;
    font-weight: 500;
    color: var(--trm-pp-sub);
    overflow-wrap: anywhere;
}

.trm-pp-row__label {
    font-size: 13px;
    font-weight: 700;
    color: var(--trm-pp-ink);
    min-width: 0;
    overflow-wrap: anywhere;
}

.trm-pp-odds {
    /* Always renders as an <a>, so it carries its own link reset rather
       than inheriting a theme's underline and link colour. */
    display: block;
    text-decoration: none;
    cursor: pointer;
    flex: 0 0 auto;
    min-width: 86px;
    padding: 6px 8px;
    text-align: center;
    font-size: 12px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--trm-pp-odds-ink);
    background: var(--trm-pp-odds-bg);
    border: 1px solid var(--trm-pp-odds-border);
    border-radius: 8px;
    transition: background-color 120ms ease, border-color 120ms ease;
}

/* Hover only where a pointer exists — on touch it would stick after
   a tap and read as a selected state that means nothing. */
@media (hover: hover) {
    .trm-pp-odds:hover { background: var(--trm-pp-odds-hover); }
}

/* Every link state pinned to the card's own ink.
 *
 * A theme's own a:hover was repainting the price on hover, and the
 * previous selector could not stop it: a.trm-pp-odds:hover is (0,2,1),
 * which a rule like .entry-content a:hover ties — and a tie goes to
 * whichever stylesheet loads later, which is not reliably ours.
 * Scoping under .trm-pp makes it (0,3,1) and wins without !important,
 * which would take the colour away from an operator theming the block.
 *
 * :visited and :active are listed too: a price that has been clicked
 * once must not come back in a theme's visited purple. */
.trm-pp a.trm-pp-odds,
.trm-pp a.trm-pp-odds:link,
.trm-pp a.trm-pp-odds:visited,
.trm-pp a.trm-pp-odds:hover,
.trm-pp a.trm-pp-odds:focus,
.trm-pp a.trm-pp-odds:active {
    color: var(--trm-pp-odds-ink);
    text-decoration: none;
}

.trm-pp a.trm-pp-odds:focus-visible {
    outline: 2px solid var(--trm-pp-highlight);
    outline-offset: 2px;
}

/* ---- attribution ---------------------------------------------- */

/* ---- settled prices -------------------------------------------
 *
 * A fallback card shows last week's prices, which have already run.
 * They are spans rather than links — there is nothing left to bet —
 * and they carry how they finished instead.
 *
 * The badge sits beside the price, so the box becomes a row. It keeps
 * its min-width, so a settled card lines up with a live one. The box
 * itself keeps the normal odds colours — only the badge says hit or
 * miss.
 * -------------------------------------------------------------- */

.trm-pp-odds--hit,
.trm-pp-odds--miss {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    cursor: default;
}

/* The tick / cross: a white stroked glyph on a disc of the result
   colour, lit from the top-left and ringed with a soft halo of the
   same colour so it reads as a badge rather than a flat dot. The SVG
   is block-level and exactly the disc's size, so there is no inline
   baseline gap to push it off centre. */
.trm-pp-odds__badge {
    --trm-pp-badge: var(--trm-pp-hit);
    display: block;
    flex: 0 0 auto;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    color: #fff;
    background: radial-gradient(circle at 32% 28%, color-mix(in srgb, var(--trm-pp-badge) 55%, #fff), var(--trm-pp-badge) 62%);
    box-shadow:
        0 0 0 2px color-mix(in srgb, var(--trm-pp-badge) 28%, transparent),
        0 1px 3px rgba(0, 0, 0, .35);
}

.trm-pp-odds__badge svg { display: block; }

.trm-pp-odds--miss .trm-pp-odds__badge { --trm-pp-badge: var(--trm-pp-miss); }

/* Settled boxes do not react to the pointer — nothing happens if you
   click one. */
@media (hover: hover) {
    .trm-pp-odds--hit:hover,
    .trm-pp-odds--miss:hover { background: var(--trm-pp-odds-bg); }
}

/* ==================================================================
 * The panel
 *
 * The market cards, set inside a stadium panel headed by the player's
 * name. The panel artwork is --trm-pp-panel-bg; the cards carry no
 * artwork of their own, only a translucent fill, so the stadium reads
 * through as one image rather than three competing ones.
 * ================================================================== */

.trm-pp--hero {
    /* Colours, set per panel theme below. These are the dark panels'
       defaults, for any theme without a block of its own. */
    --trm-pp-ground:      #070b16;
    --trm-pp-ink:         #f3f6ff;
    --trm-pp-hero-ink:    #fff;
    /* Three layers: a tight dark edge that outlines each letter, a close
       halo that knocks the stadium lights back behind the name, and the
       original soft spread. One soft shadow alone was too faint over
       the floodlights on the left. */
    --trm-pp-hero-shadow: 0 1px 2px rgba(0, 0, 0, .9), 0 0 10px rgba(0, 0, 0, .85), 0 2px 18px rgba(0, 0, 0, .55);
    --trm-pp-hero-tag:    #5aaaff;
    --trm-pp-eyebrow:     #5aaaff;

    position: relative;
    padding: 0;
    border-radius: 8px;
    overflow: hidden;
    background-color: var(--trm-pp-ground);
    background-image: var(--trm-pp-panel-bg);
    background-size: cover;
    background-position: center top;
    background-repeat: no-repeat;
    border: 1px solid color-mix(in srgb, var(--trm-pp-accent) 45%, var(--trm-pp-ground));
}

/* ---- heading ---- */

/* Left-aligned, and inset the same 20px as the card grid below, so
   both lines start on the first card's left edge. */
.trm-pp-hero {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    padding: 24px 20px 20px;
    text-align: left;
}

.trm-pp-hero__name {
    font-size: 28px;
    font-weight: 800;
    line-height: 1.05;
    letter-spacing: -0.01em;
    /* The name's own colour when a panel gives it one, else the ink. */
    color: var(--trm-pp-hero-name, var(--trm-pp-hero-ink));
    /* The lights sit directly behind the name; a soft shadow keeps it
       legible over the brightest part of the artwork. */
    text-shadow: var(--trm-pp-hero-shadow);
}

/* "Player Props" after the name. Same type as the name; only its
   colour is the panel's to set. */
.trm-pp-hero__tag { color: var(--trm-pp-hero-tag); }

/* The name and the position/team share one line, centred against each
   other so the small caps sit mid-height on the name rather than on its
   baseline. Where the line runs out of room the position wraps beneath,
   still on the left. */
.trm-pp-hero__line {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    column-gap: 14px;
}

/* The | between the name and the position/team: a 1px white rule,
   drawn rather than typed so its width is exact, and sized off the
   name's type. It sits inside the position/team block so the two wrap
   under the name together on a phone. That block is nudged down 3px;
   -2px here leaves the rule 1px down, centred on the name's capitals. */
.trm-pp-hero__sep {
    position: relative;
    top: -2px;
    width: 1px;
    height: .85em;
    font-size: 28px;
    background: var(--trm-pp-hero-sep, #fff);
}

.trm-pp-hero__meta {
    /* A row of its own: the separator, then the text, centred together. */
    display: inline-flex;
    align-items: center;
    column-gap: 14px;
    /* Nudged down to sit visually centred on the name — 3px, set by eye
       on the live page (the measured cap-height midpoint match was 1px,
       which read as sitting high). */
    position: relative;
    top: 3px;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: .22em;
    text-transform: uppercase;
    color: var(--trm-pp-hero-ink);
}

/* ---- cards inside the panel ---- */

.trm-pp--hero .trm-pp__grid {
    margin: 0;
    padding: 0 20px 20px;
    gap: 18px;
}

/* The panel supplies the scene, so the card is a translucent pane over
   it rather than a second image. */
.trm-pp--hero .trm-pp-card {
    background-color: color-mix(in srgb, var(--trm-pp-ground) 62%, transparent);
    border-color: color-mix(in srgb, var(--trm-pp-accent) 55%, transparent);
    backdrop-filter: blur(2px);
}

.trm-pp--hero .trm-pp-card__head {
    background: color-mix(in srgb, var(--trm-pp-ground) 30%, transparent);
}

/* The attribution, beneath the cards inside the panel — over the
   stadium rather than the page, so it is wrapped in an eyebrow: a
   translucent pill tinted with the panel's eyebrow colour, text mixed
   toward the ink so it reads on the dark panels and the light one alike.
   Only as wide as its text, and inset 20px like the cards so it starts
   on the first card's left edge. The 12px radius is a full pill on one
   line and a rounded box if the fallback note wraps it on a phone. */
.trm-pp--hero .trm-pp__meta {
    width: fit-content;
    margin: 0 20px 16px;
    padding: 3px 12px;
    border-radius: 12px;
    font-size: 11px;
    font-weight: 500;
    color: color-mix(in srgb, var(--trm-pp-eyebrow) 30%, var(--trm-pp-ink));
    background: color-mix(in srgb, var(--trm-pp-eyebrow) 18%, color-mix(in srgb, var(--trm-pp-ground) 70%, transparent));
    border: 1px solid color-mix(in srgb, var(--trm-pp-eyebrow) 40%, transparent);
    backdrop-filter: blur(2px);
}

/* ---- panel palettes ----
 * One block per theme="" name, keyed on the trm-pp--theme-<name> class
 * the renderer adds alongside that theme's panel artwork. The panel
 * decides the whole palette — ground, ink and accent for the cards,
 * plus the heading colours — so picking the artwork picks the look.
 * Declared after .trm-pp--hero so they win over its defaults. Grounds
 * are sampled from the bottom of each image, which is what shows below
 * the artwork on a phone.
 *
 * The stroke beside each card title is the fixed --trm-pp-bar blue on
 * the blue and green panels; the red and default panels set it red. */

/* Blue — dark navy, lights in light blue. The name takes that light
   blue and "Player Props" a lime green. */
.trm-pp--theme-blue {
    --trm-pp-ground:    #070b16;
    --trm-pp-ink:       #f3f6ff;
    --trm-pp-hero-name: #5aaaff;
    --trm-pp-hero-tag:  #a2de27;
}

/* Green — the blue design in green: the card accent is the green
   palette's sampled #50b964, and the tag and eyebrow take a lighter
   green, as the blue panel's take a lighter blue. */
.trm-pp--theme-green {
    --trm-pp-ground:    #03100a;
    --trm-pp-ink:       #f2fff6;
    --trm-pp-accent:    #50b964;
    --trm-pp-hero-tag:  #7ddf94;
    --trm-pp-eyebrow:   #7ddf94;
}

/* Red — the stadium in crimson, lights and seat-lights in red. Near-
   black red ground sampled from the image; the red (#e3263b, the same
   red the default panel uses for its odds boxes) drives the card
   borders, header rules, marks and the stroke beside each title, so
   nothing blue is left on a red panel. The odds boxes lean on it much
   harder than the blue panel's do — crimson mixed thinly into near-
   black reads as brown, so it takes a near-full edge and a real maroon
   fill, as the earlier red card reference did. White name, with
   "Player Props" and the eyebrow in a lighter coral red. */
.trm-pp--theme-red {
    --trm-pp-ground:     #0f0404;
    --trm-pp-ink:        #fff4f4;
    --trm-pp-accent:     #e3263b;
    --trm-pp-bar:        #e3263b;
    --trm-pp-odds-edge:  92%;
    --trm-pp-odds-fill:  40%;
    --trm-pp-odds-lift:  55%;
    --trm-pp-hero-tag:   #ff6b78;
    --trm-pp-eyebrow:    #ff6b78;
}

/* Default — used when no theme is named. The light, near-white
   stadium, and the only light panel, so it flips everything the dark
   ones assume: near-black ink on a pale ground and a white glow behind
   the name instead of a dark shadow.

   Its colours are the red-and-navy reference card's, on the white
   ground. Red is the furniture — the odds boxes (deep red fill, bright
   red edge, white figures, mixed against a near-black red so they stay
   red rather than turning pink on white), the marks, the stroke beside
   each title and the rule under the name. Navy is the structure — card
   borders and the rule under each card header. The tag and eyebrow keep
   the brighter blue. */
.trm-pp--theme-default {
    --trm-pp-ground:      #eef0f2;
    --trm-pp-ink:         #0b0f16;
    --trm-pp-accent:      #24508f;
    --trm-pp-highlight:   #e3263b;
    --trm-pp-mark:        #e3263b;
    --trm-pp-bar:         #e3263b;
    --trm-pp-odds-ground: #2a060b;
    --trm-pp-odds-edge:   100%;
    --trm-pp-odds-fill:   55%;
    --trm-pp-odds-lift:   70%;
    --trm-pp-odds-ink:    #fff;
    --trm-pp-hero-ink:    #0b0f16;
    /* White would vanish on this ground; the rule takes the ink. */
    --trm-pp-hero-sep:    #0b0f16;
    --trm-pp-hero-shadow: 0 1px 14px rgba(255, 255, 255, .8);
    --trm-pp-hero-tag:    #2f6fed;
    --trm-pp-eyebrow:     #2f6fed;
}

/* ---- narrow screens ----
 * The mockup's mobile view is the same panel with the cards stacked;
 * the heading simply gets smaller, which the clamp() sizes already
 * handle, so only the grid needs saying. */
@media (max-width: 860px) {
    .trm-pp--hero .trm-pp__grid { grid-template-columns: minmax(0, 1fr); align-items: start; }
    .trm-pp-hero { padding: 10px 20px 12px; }

    /* Fit the artwork to the WIDTH rather than covering the panel.
       The image is about 2.3:1; covering a tall narrow panel scales it
       until the height fills, which crops the sides away — exactly the
       lights and stands that make it a stadium. Fitted to width the
       whole scene is visible across the top and the ground colour
       carries the rest of the panel down. */
    .trm-pp--hero {
        background-size: 100% auto;
        background-position: center top;
    }
}

/* One column: undo the subgrid.
 *
 * align-items alone cannot un-stretch these — a subgrid card spans two
 * explicit parent tracks, and the second is 1fr, so it fills whatever
 * the tallest sibling created. Stacked there is nothing to align with,
 * so the card goes back to plain flex at its natural height. */
@media (max-width: 860px) {
    .trm-pp--hero .trm-pp__grid { grid-template-rows: none; grid-auto-rows: auto; }
    .trm-pp--hero .trm-pp-card  { display: flex; grid-row: auto; grid-template-rows: none; }
}
