/*
 * cubing-play.css
 *
 * Visual styling for the cubing module's per-state surfaces — the active-match render branch in
 * ChallengeContent.razor (rendered inside the play surface's center-left content area at
 * /challenge/{id}) and the seed flow at /events/cubing/{event-code}/seed. Pinned in doc 23
 * §"Active-match layout" (2026-05-03 revision): full-width center stage with scramble + timer,
 * horizontal solves strip below.
 *
 * Loaded from App.razor as _content/Haxahedron.Modules.Cubing/css/cubing-play.css. Class names
 * are the .cubing-* prefix the Razor pages already reference. Per-event grid column counts are
 * driven by .cubing-event-aoX / .cubing-seed-page parent classes.
 */

/* ----- Outer containers ----- */
.cubing-active-match,
.cubing-waiting-view,
.cubing-resolved,
.cubing-seed-page {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    padding: 1rem;
    position: relative;
    min-height: 22rem;
}

.cubing-pre-accept {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    padding: 1rem;
}

/* ----- Event banner -----
   Two-line title + subtitle layout (operator design 2026-05-22) — flex container holds
   the ::before icon (first flex child) alongside the .cubing-event-banner-text column
   (second flex child) containing the discipline title above the event-name subtitle.
   Saves horizontal width on long event names that previously wrapped mid-banner on
   mobile (e.g. "Cubing · 3×3 Hit Your Mark · Ao5"). */
.cubing-event-banner {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--mud-palette-text-secondary);
    font-weight: 600;
}

.cubing-event-banner::before {
    content: '';
    flex-shrink: 0;
    width: 52px;
    height: 52px;
    background-image: url('/icons/disciplines/icon-rubikcube-default.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}

.cubing-event-banner-text {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
    min-width: 0;
}

.cubing-event-banner-title {
    font-size: 1.25rem;
    font-weight: 600;
}

.cubing-event-banner-subtitle {
    font-size: 0.9rem;
    font-weight: 500;
    opacity: 0.85;
}

.cubing-event-banner--corner {
    position: absolute;
    top: 0.75rem;
    left: 1rem;
    margin: 0;
}

.cubing-event-banner--inline {
    margin-bottom: 0.5rem;
}

/* ----- Center stage (scramble + timer or pre-submit summary) ----- */
.cubing-center-stage--full {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    flex-grow: 1;
    padding: 1.5rem 1rem 0.5rem;
    gap: 1rem;
}

/* Active-state timer row (operator decision 2026-05-08): timer dead-centered, mark
   pinned to the far-right edge of the row, mark text center-justified within its
   card. 3-column grid (1fr | auto | 1fr) keeps the timer in the middle column at
   natural width while the equal 1fr spacer columns guarantee the timer's center
   stays at the row's horizontal midpoint. The mark sits in column 3 with
   justify-self: end so it hugs the row's right edge. text-align centered is
   inherited from the parent .cubing-center-stage--full so the mark's label-over-
   value reads centered around the card's vertical midline. */
.cubing-timer-row {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    width: 100%;
}

.cubing-timer-row > .cubing-timer {
    grid-column: 2;
}

.cubing-timer-row > dl.cubing-summary-stats {
    grid-column: 3;
    justify-self: end;
    /* The dl's own auto-fit grid (.cubing-summary-stats: grid-template-columns:
       repeat(auto-fit, minmax(8rem, 1fr))) wants to expand to fill the parent grid
       column. width: max-content shrinks the dl to its intrinsic content width so
       justify-self: end has space to do its job and the dl actually slides to the
       right edge of column 3 instead of left-aligning inside an expanded column. */
    width: max-content;
    /* Explicit center alignment instead of relying on inheritance from
       .cubing-center-stage--full so the label + value center around the dl's
       vertical midline regardless of any intermediate text-align rules. */
    text-align: center;
}

@media (max-width: 600px) {
    .cubing-timer-row {
        grid-template-columns: 1fr;
        gap: 1rem;
    }

    .cubing-timer-row > .cubing-timer,
    .cubing-timer-row > dl.cubing-summary-stats {
        grid-column: 1;
        justify-self: center;
    }
}

.cubing-scramble {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
}

.cubing-scramble-label {
    font-size: 1.25rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary);
    letter-spacing: 0.01em;
}

.cubing-scramble-notation {
    color: #A3E635;
    font-family: ui-monospace, "Cascadia Code", "Source Code Pro", Consolas, monospace;
    font-size: 1.25rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    word-spacing: 0.5em;
    margin: 0;
    padding: 0;
    background: transparent;
    white-space: pre-wrap;
    text-align: center;
    max-width: 100%;
}

/* ----- Timer face ----- */
.cubing-timer {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-top: 0.5rem;
    user-select: none;
    -webkit-user-select: none;
}

.cubing-timer-display {
    font-family: ui-monospace, "Cascadia Code", "Source Code Pro", Consolas, monospace;
    font-size: 5rem;
    font-weight: 300;
    line-height: 1;
    color: var(--mud-palette-text-primary);
    letter-spacing: 0.02em;
    transition: color 120ms ease-out;
}

.cubing-timer--ready .cubing-timer-display {
    color: var(--mud-palette-primary);
}

.cubing-timer--running .cubing-timer-display {
    color: var(--mud-palette-text-primary);
}

.cubing-timer--arming .cubing-timer-display {
    color: var(--mud-palette-text-secondary);
}

.cubing-one-hand-icon {
    font-size: 1.75rem;
    color: var(--mud-palette-primary);
    margin-bottom: 0.25rem;
}

/* ----- Solves strip (horizontal grid below center stage) ----- */
.cubing-solves-strip-wrapper {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-top: auto;
}

.cubing-solves-label {
    font-size: 1rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary);
}

.cubing-solve-list {
    display: grid;
    gap: 0.75rem 1.25rem;
    list-style: none;
    padding: 0;
    margin: 0;
}

/* Per-event grid column counts driven by parent classes. Ao5 / Ao5-1H ship one row of 5;
   Ao12 ships two rows of 6 (12 cells flow naturally); seed page ships two rows of 5. */
.cubing-event-ao5 .cubing-solve-list,
.cubing-event-ao5-1h .cubing-solve-list {
    grid-template-columns: repeat(5, minmax(0, 1fr));
}

.cubing-event-ao12 .cubing-solve-list {
    grid-template-columns: repeat(6, minmax(0, 1fr));
}

.cubing-seed-page .cubing-solve-list {
    grid-template-columns: repeat(5, minmax(0, 1fr));
}

/* ----- Per-cell ----- */
.cubing-solve-row {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.125rem;
    padding: 0.25rem 0.5rem;
    border-left: 2px solid transparent;
    transition: border-color 120ms ease-out, background-color 120ms ease-out;
}

.cubing-solve-row--active {
    border-left-color: var(--mud-palette-primary);
    background-color: rgba(16, 185, 129, 0.06);
}

.cubing-solve-row--dnf .cubing-solve-time {
    text-decoration: line-through;
    opacity: 0.6;
}

.cubing-solve-row--trimmed .cubing-solve-time {
    opacity: 0.55;
}

.cubing-solve-line {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
}

.cubing-solve-ordinal {
    color: var(--mud-palette-text-primary);
    font-size: 1rem;
}

.cubing-solve-time {
    font-family: ui-monospace, "Cascadia Code", "Source Code Pro", Consolas, monospace;
    font-size: 1rem;
    color: var(--mud-palette-text-primary);
}

/* Per-solve sign-aware color (operator decision 2026-05-08): solves slower than the locked
   mark shade red-400, solves faster shade lime-400 — same asymmetric HYM treatment as the
   Distance display + Step G, applied per-solve so the player has a running visual cue
   during the run. Selectors compound .cubing-solve-time with the modifier so the new rules
   outrank the parent .cubing-solve-time text-primary fallback. The existing --dnf and
   --trimmed row rules layer their own opacity/strikethrough independently, so a trimmed
   above-mark solve still renders dimmed-red and a DNF stays struck-through (the
   SolveTimeClass helper deliberately skips DNFs). */
.cubing-solve-time.cubing-solve-time--above {
    color: #F87171;
}
.cubing-solve-time.cubing-solve-time--below {
    color: #A3E635;
}

.cubing-solve-dnf-checkbox {
    margin: 0;
}

.cubing-solve-dnf-chip {
    background: var(--mud-palette-error);
    color: white;
    padding: 0.125rem 0.375rem;
    border-radius: 0.25rem;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.05em;
}

.cubing-solve-redo {
    align-self: flex-start;
    margin-top: 0.125rem;
}

/* ----- Pre-submit summary takes over center stage when capture is complete ----- */
.cubing-pre-submit-summary {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
    text-align: center;
    width: 100%;
}

.cubing-summary-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
    gap: 1.25rem 2rem;
    margin: 0;
    text-align: left;
    max-width: 36rem;
    width: 100%;
}

.cubing-summary-stats > div {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
}

.cubing-summary-stats dt {
    font-size: 1rem;
    color: var(--mud-palette-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.cubing-summary-stats dd {
    font-family: ui-monospace, "Cascadia Code", "Source Code Pro", Consolas, monospace;
    font-size: 1.25rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary);
    margin: 0;
}

/* Sign-aware Distance color (operator decision 2026-05-08): above-mark is penalized per
   the asymmetric HYM rule pinned 2026-05-03 — render in red-400; under-mark is rewarded
   — render in lime-400 to match the scramble notation accent. Selector is scoped to the
   .cubing-summary-stats dd to outrank the parent rule's text-primary color rather than
   relying on source-order tie-breaking. */
.cubing-summary-stats dd.cubing-distance--above {
    color: #F87171;
}
.cubing-summary-stats dd.cubing-distance--below {
    color: #A3E635;
}

/* ----- Voice-aligned framing line (used across multiple states) ----- */
.cubing-voice-line {
    color: var(--mud-palette-text-secondary);
    font-size: 1rem;
    margin: 0;
}

/* Waiting view: the voice line ("Done on your side. Waiting on …") is the only normal-flow
   element at the top of .cubing-waiting-view, so it collides with the absolutely-positioned
   corner banner sharing the same top-left slot. Center it horizontally (escapes the banner's
   left-edge column the same way the resolved headline does) + add top margin for breathing
   room beneath the banner's 0.75rem top offset. Closes the deferred WaitingView overlap
   carried forward from the 2026-05-07/08 walk-through. Mobile (≤600px) already restacks the
   banner via `position: static` so the centering is harmless there. */
.cubing-waiting-view .cubing-voice-line {
    text-align: center;
    margin: 0.75rem 0 0.5rem;
}

/* ----- Seed page headline ----- */
.cubing-seed-headline {
    font-size: 1.5rem;
    font-weight: 600;
    margin: 0 0 0.25rem 0;
}

/* ----- Resolved view: solves grid + per-player summary stats below ----- */
.cubing-resolved-headline {
    font-size: 1.75rem;
    font-weight: 600;
    text-align: center;
    /* Top-only margin: pushes the headline below the absolutely-positioned event
       banner (--corner) on desktop, and stacks naturally below the in-flow banner
       on mobile (where --corner becomes position: static via the media block).
       Bumped 2rem → 4rem 2026-05-22 after the banner gained the two-line title +
       subtitle layout and the 52px ::before icon — the old 2rem cleared a single-
       line banner cleanly but the taller new banner was crowding the headline.
       Bottom margin stays zero — headline-to-grid gap collapses to the parent
       container's `gap: 1.5rem`. */
    margin: 4rem 0 0;
}

.cubing-resolved-headline--win {
    color: #A3E635;
}

/* Players on Y axis, solve ordinals on X axis. grid-template-columns is set inline by the
   Razor render so it can vary with RequiredSolveCount (Ao5 = 6 cols, Ao12 = 13 cols).
   Mobile rewrites the layout entirely (see @media block at the bottom). */
.cubing-resolved-grid {
    display: grid;
    gap: 0.5rem 0.75rem;
    align-items: center;
    padding: 1rem;
    border-radius: 0.5rem;
    background-color: rgba(255, 255, 255, 0.03);
}

.cubing-resolved-grid-corner {
    /* Top-left empty cell aligning the ordinal headers with the player-name column. */
}

.cubing-resolved-grid-header {
    text-align: center;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

/* Each row contains (label) + (N solve cells). The row-level container needs `display: contents`
   so the label and cells participate in the parent grid directly — the Razor renders each row
   inside a wrapping <div> for winner-class targeting. */
.cubing-resolved-grid-row {
    display: contents;
}

.cubing-resolved-grid-label {
    font-weight: 600;
    color: var(--mud-palette-text-primary);
    font-size: 1rem;
}

.cubing-resolved-grid-row--winner .cubing-resolved-grid-label {
    color: #A3E635;
}

/* Winner's counted solve cells render lime — the values pop for the player
   who took the match. Trimmed (best+worst dropped per WCA convention) and
   DNF cells stay at default color so the "didn't count" signal isn't
   overloaded with lime; the trimmed opacity + DNF strike-through already
   carry the recede semantic. Operator decision 2026-05-18 — "all the stats
   for the winner lime", scoped to counted via the operator's solve-grid
   highlights. */
.cubing-resolved-grid-row--winner .cubing-resolved-grid-cell:not(.cubing-resolved-grid-cell--trimmed):not(.cubing-resolved-grid-cell--dnf) {
    color: #A3E635;
}

.cubing-resolved-grid-cell {
    text-align: center;
    font-family: ui-monospace, "Cascadia Code", "Source Code Pro", Consolas, monospace;
    font-size: 1rem;
    color: var(--mud-palette-text-primary);
    padding: 0.25rem 0.125rem;
    border-radius: 0.25rem;
}

.cubing-resolved-grid-cell--dnf {
    text-decoration: line-through;
    opacity: 0.6;
}

/* Trimmed cells (best + worst dropped per WCA convention) recede via smaller
   font-size + reduced opacity, so the three counted solves visually anchor
   the row and the dropped scores read as supporting context. Operator
   eyeball pass 2026-05-18 — the earlier opacity-only treatment was too
   subtle to read at a glance. Counted cells stay at the original 1rem;
   the relative gap comes from shrinking the trimmed cells only. */
.cubing-resolved-grid-cell--trimmed {
    font-size: 0.8rem;
    opacity: 0.55;
}

/* Per-player summary stats sit in two rows below the grid. */
.cubing-resolved-stats {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.cubing-resolved-stats-row {
    display: grid;
    grid-template-columns: minmax(6rem, auto) 1fr;
    gap: 1rem;
    align-items: center;
    padding: 0.75rem 1rem;
    border-radius: 0.5rem;
    background-color: rgba(255, 255, 255, 0.03);
}

.cubing-resolved-stats-row--winner {
    box-shadow: inset 0 0 0 2px #A3E635;
}

.cubing-resolved-stats-label {
    font-weight: 600;
    font-size: 1rem;
    color: var(--mud-palette-text-primary);
}

.cubing-resolved-stats-row--winner .cubing-resolved-stats-label {
    color: #A3E635;
}

/* Winner's stats values render lime for Ao5 + Locked mark; Distance keeps
   the asymmetric HYM sign-aware color (above-mark stays red even for the
   winner, below-mark stays lime) per the rule pinned 2026-05-03 — so the
   :not() filter excludes the distance dd from this winner-paint pass.
   Operator decision 2026-05-18 — "all the stats for the winner lime". */
.cubing-resolved-stats-row--winner .cubing-summary-stats dd:not(.cubing-distance--above):not(.cubing-distance--below) {
    color: #A3E635;
}

.cubing-resolved-actions {
    display: flex;
    gap: 0.75rem;
    align-items: center;
    justify-content: center;
    margin-top: 1rem;
}

/* ----- Mark detail expansion ----- */
.cubing-mark-detail {
    background-color: rgba(255, 255, 255, 0.03);
    padding: 0.75rem 1rem;
    border-radius: 0.5rem;
    font-size: 0.9rem;
}

.cubing-mark-detail ul {
    margin: 0.5rem 0 0 1.25rem;
    padding: 0;
}

/* ----- Pre-acceptance ----- */
.cubing-pre-accept-actions {
    display: flex;
    gap: 0.75rem;
    margin-top: 0.5rem;
}

.cubing-mark-line {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
}

.cubing-mark-value {
    font-family: ui-monospace, "Cascadia Code", "Source Code Pro", Consolas, monospace;
    font-weight: 500;
}

/* ----- Mobile reshape -----
   Below 600px viewport, all cubing events collapse the solves strip to 2 columns regardless of
   per-event desktop count. Operator decision 2026-05-03: 5 cells across at 375px (iPhone X
   viewport) overlap on ordinal + time + DNF checkbox; 2 columns gives each cell room without
   horizontal scrolling. So Ao5 → 2 × 3 (last cell solo), Ao12 → 2 × 6, Seed → 2 × 5. *@ */
@media (max-width: 600px) {
    .cubing-active-match,
    .cubing-waiting-view,
    .cubing-resolved,
    .cubing-seed-page {
        gap: 1rem;
        padding: 0.75rem;
    }

    .cubing-event-banner--corner {
        position: static;
    }

    /* Desktop puts the event banner in absolute position at top-left of the resolved
       container, so the headline carries `margin: 2rem 0 0` to clear it visually. On
       mobile the banner falls into the document flow (position: static above), so the
       headline's top margin stacks ON TOP of the parent flex container's `gap: 1rem`
       and the result is a visible empty band between banner and headline. Zero out the
       headline margin here — flex gap handles the spacing. */
    .cubing-resolved-headline {
        margin-top: 0;
    }

    .cubing-center-stage--full {
        padding-top: 0.5rem;
    }

    .cubing-timer-display {
        font-size: 3.5rem;
    }

    .cubing-scramble-notation {
        font-size: 1rem;
        word-spacing: 0.4em;
    }

    /* Collapse to 2 columns for every event-class variant the desktop rules cover. */
    .cubing-event-ao5 .cubing-solve-list,
    .cubing-event-ao5-1h .cubing-solve-list,
    .cubing-event-ao12 .cubing-solve-list,
    .cubing-seed-page .cubing-solve-list {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 0.5rem 0.75rem;
    }

    .cubing-solve-ordinal,
    .cubing-solve-time {
        font-size: 0.95rem;
    }

    /* Resolved view restructures on mobile: the cross-player grid (players on Y, solves on X)
       doesn't fit at narrow widths because 6+ columns become too cramped. So we override the
       inline grid-template-columns and stack each player as their own block with a 2-column
       solves grid below the player name. CSS counter prepends the ordinal per cell since the
       desktop header row (1, 2, 3, ...) is hidden on mobile. min-width:0 across the board
       prevents grid/flex items from forcing parents wider than the viewport — distance strings
       like "+0.061s above mark" have an intrinsic width that pushes the per-player stat columns
       off-screen without it. */
    .cubing-resolved {
        min-width: 0;
        max-width: 100%;
        overflow-x: hidden;
    }

    .cubing-resolved-grid {
        display: flex !important;
        flex-direction: column;
        gap: 1rem;
        grid-template-columns: none !important;
        min-width: 0;
    }

    .cubing-resolved-grid-corner,
    .cubing-resolved-grid-header {
        display: none;
    }

    .cubing-resolved-grid-row {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 0.25rem 0.5rem;
        padding: 0.75rem;
        border-radius: 0.5rem;
        background-color: rgba(255, 255, 255, 0.03);
        counter-reset: solve-ordinal;
        min-width: 0;
    }

    .cubing-resolved-grid-row--winner {
        box-shadow: inset 0 0 0 2px #A3E635;
    }

    .cubing-resolved-grid-label {
        grid-column: 1 / -1;
        font-size: 1.05rem;
        margin-bottom: 0.25rem;
    }

    .cubing-resolved-grid-cell {
        text-align: left;
        padding: 0.125rem 0.25rem;
        min-width: 0;
    }

    .cubing-resolved-grid-cell::before {
        counter-increment: solve-ordinal;
        content: counter(solve-ordinal) "  ";
        color: var(--mud-palette-text-secondary);
        font-size: 0.85rem;
    }

    /* Per-player stats: stack the label on top + force the stat list into a single column with
       a smaller monospace value font so distance strings ("+0.061s above mark") fit without
       overflowing. The desktop auto-fit grid template forces minmax(8rem, 1fr) which can demand
       more width than mobile has — we override to a single-column flex column unconditionally. */
    .cubing-resolved-stats-row {
        grid-template-columns: 1fr;
        gap: 0.5rem;
        min-width: 0;
        padding: 0.75rem;
    }

    .cubing-resolved-stats-row .cubing-summary-stats {
        display: flex;
        flex-direction: column;
        gap: 0.5rem;
        max-width: 100%;
        min-width: 0;
    }

    .cubing-resolved-stats-row .cubing-summary-stats > div {
        flex-direction: row;
        align-items: baseline;
        gap: 0.5rem;
        flex-wrap: wrap;
        min-width: 0;
    }

    .cubing-resolved-stats-row .cubing-summary-stats dt {
        font-size: 0.85rem;
        flex-shrink: 0;
    }

    .cubing-resolved-stats-row .cubing-summary-stats dd {
        font-size: 1.15rem;
        word-break: break-word;
        overflow-wrap: anywhere;
        min-width: 0;
    }
}
