/* ---------------------------------------------------------------------------
   Play home and chooser — the app's home ("how do you want to play" mode cards), the game-chooser pages,
   the matchmaking wait, and the happening-now shelf.
   Backed by PlayPage.razor, PlayModeCard.razor, PlayModeChoices.razor, PlayChooserPage.razor,
   MatchmakingWait.razor, HappeningNowShelf.razor.
   --------------------------------------------------------------------------- *//* ===========================================================================
   Play home (Components/Pages/PlayPage.razor, PlayModeCard.razor)
   The app's home asks one question — how do you want to play — and answers it with
   three peer cards. They share one treatment and differ only in tone, so no way in
   reads as the default. Side by side on a wide screen, stacked at phone width.
   =========================================================================== */
/* The home is a screen, not a document: it has one question and three answers and nothing below them, so the
   column takes the height it is given and centres its content in it rather than stacking at the top and
   leaving the rest of a desktop monitor as a dead grey field. Grow but never shrink, so a short viewport (a
   landscape phone) scrolls instead of compressing the cards. */
.play-home {
    flex: 1 0 auto;
    justify-content: center;
    padding-block: clamp(1rem, 4vh, 3rem);
}

.play-home__heading {
    margin: 0;
    font-size: clamp(1.9rem, 5vw, 2.6rem);
    line-height: 1.1;
    color: var(--text-primary);
}

/* One column or three, never two. The three ways in are peers, so a 2 + 1 wrap — which is what an auto-fit
   track list produces on a tablet — reads as a ranking the page does not mean. The count is therefore stated
   at the same stop the card's composition changes at, so the row shape and the card shape always agree. */
.play-modes {
    display: grid;
    grid-template-columns: 1fr;
    gap: clamp(0.75rem, 2vw, 1.25rem);
}

/* The create-a-table host wraps its card so the card keeps its waiting/refusal states; it is the grid item, and
   the card fills it. */
.create-table { display: flex; min-width: 0; }
.create-table > .play-mode { flex: 1 1 auto; }

.play-mode {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    min-width: 0;
}
.play-mode__cta {
    position: relative;
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    gap: 0.6rem;
    min-height: 10.5rem;
    padding: 1.15rem 1.25rem 1.15rem 1.35rem;
    border: 1px solid color-mix(in srgb, var(--play-mode-accent) 45%, transparent);
    border-radius: 1.4rem;
    background:
        radial-gradient(120% 120% at 100% 0%, color-mix(in srgb, var(--play-mode-accent) 30%, transparent), transparent 65%),
        linear-gradient(150deg, color-mix(in srgb, var(--play-mode-accent) 92%, white), var(--play-mode-accent-deep));
    color: var(--text-on-accent);
    text-align: left;
    cursor: pointer;
    /* Three layers make a saturated panel read as a lit object on a dark canvas rather than a flat swatch: a
       lit top edge inside the border, a deep cast shadow under it, and the card's own accent bleeding onto the
       canvas around it — the glow is what says the panel is emitting light, not just painted a colour. */
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.26),
        0 18px 44px -20px color-mix(in srgb, var(--play-mode-accent) 70%, transparent),
        0 22px 48px -26px rgba(0, 0, 0, 0.85);
    transition: transform 160ms var(--ease-spring, ease), filter 160ms ease, box-shadow 160ms ease;
}
.play-mode__cta:hover:not(:disabled) {
    filter: brightness(1.07);
    transform: translateY(-3px);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.3),
        0 26px 56px -20px color-mix(in srgb, var(--play-mode-accent) 85%, transparent),
        0 26px 54px -26px rgba(0, 0, 0, 0.9);
}
.play-mode__cta:active:not(:disabled) { transform: translateY(0); }
.play-mode__body { flex: 1 1 auto; display: flex; flex-direction: column; gap: 0.4rem; min-width: 0; }
.play-mode__title { font-size: clamp(1.45rem, 6vw, 1.95rem); line-height: 1.05; letter-spacing: 0.005em; }
.play-mode__sub { font-size: 0.95rem; line-height: 1.35; opacity: 0.94; max-width: 24ch; }
.play-mode__art { flex: none; display: grid; place-items: center; }
/* The mode's illustration. Sized against the viewport rather than the card so the three stay the same size as
   each other at every width; a drop shadow under it lifts the object off the panel it is painted on. */
.play-mode__art .app-icon.play-mode__illus {
    width: clamp(7rem, 35vw, 11rem);
    height: auto;
    filter: drop-shadow(0 12px 18px rgba(0, 0, 0, 0.42));
}
/* The forward cue: two borders of a rotated square, so it is the same crisp mark at every size and needs no
   glyph from whichever face resolves. */
.play-mode__chevron {
    position: absolute;
    right: 1.35rem;
    bottom: 1.1rem;
    width: 0.8rem;
    height: 0.8rem;
    border-top: 0.19rem solid currentColor;
    border-right: 0.19rem solid currentColor;
    border-radius: 0.08rem;
    transform: rotate(45deg);
    opacity: 0.85;
}
.play-mode__status { margin: 0; color: var(--text-muted); font-size: 0.85rem; }
.play-mode__refusal { margin: 0; color: var(--warn-ember-ink); font-size: 0.85rem; }

/* Tones: one accent pair per mode — the table's teal, the solo blue, the open-internet ember. */
.play-mode--table { --play-mode-accent: var(--accent-teal); --play-mode-accent-deep: var(--accent-teal-deep); }
.play-mode--solo  { --play-mode-accent: var(--accent-blue); --play-mode-accent-deep: color-mix(in srgb, var(--accent-blue) 62%, var(--scrim)); }
.play-mode--find  { --play-mode-accent: var(--warn-ember); --play-mode-accent-deep: var(--warn-ember-deep); }

/* --- The wide composition ---
   Three cards side by side is a different picture from three stacked full-width ones, so the card recomposes
   rather than being squeezed: the copy moves to the top of a tall panel and the illustration drops into the
   corner under it, bleeding a little past the padding so the object sits *in* the card rather than on it.

   Width is the only thing the page recomposes on. A phone held landscape reaches this row on its width alone
   (844px) and gets it at whatever height it has, scrolling where the height runs out: the app outside a match
   is composed portrait-only below `xl`, so no shorter second composition sits under this one
   (docs/design/overview.md → Devices and orientation). */
@media (min-width: 48rem) {
    .play-modes { grid-template-columns: repeat(3, 1fr); }
    .play-mode__cta {
        flex-direction: column;
        align-items: stretch;
        justify-content: flex-start;
        gap: 0.5rem;
        /* The card takes a share of the screen's height rather than a fixed one, so a desktop monitor gets three
           panels with real presence instead of three short tiles marooned at the top of it. Bounded both ways:
           17rem is the height the composition needs, 25rem is where a panel stops gaining from being taller and
           starts being a copy line above a void. */
        min-height: clamp(17rem, 38vh, 25rem);
        padding: 1.6rem 1.6rem 1.35rem;
    }
    .play-mode__body { flex: 0 0 auto; }
    .play-mode__title { font-size: clamp(1.45rem, 2.6vw, 1.85rem); }
    .play-mode__sub { max-width: 21ch; }
    .play-mode__art { flex: 1 1 auto; place-items: end; margin: 0 -0.7rem -0.5rem 0; }
    /* The illustration takes whatever the copy leaves, capped, so the object grows with the panel instead of
       floating at a fixed size in the middle of a tall one. */
    .play-mode__art .app-icon.play-mode__illus {
        width: auto;
        height: 100%;
        max-width: min(17rem, 100%);
        object-fit: contain;
        object-position: bottom right;
    }
}

/* --- The chooser pages (Components/Pages/PlayChooserPage.razor) ---
   Play solo and Find a table on the whole screen: a way back, the question, and the playable catalog under it.
   The bounded column and its padding come from .landing, so only the header stack and a tighter rhythm are set
   here — the column's own gap is sized for shelves and would leave the question stranded above its answers. */
.play-chooser { gap: clamp(0.9rem, 2vw, 1.35rem); }
/* The chooser's search sits over its grid the way the catalog's sits over its shelves: a focused field, not a
   rule across the whole column. Same cap as .landing__search, so the two pages' search reads as one control. */
.play-chooser .game-start-catalog__search { max-width: 34rem; }
.play-chooser__topbar { display: flex; align-items: center; gap: 1rem; }
.play-chooser__intro { display: flex; flex-direction: column; gap: 0.35rem; }
.play-chooser__heading {
    margin: 0;
    font-size: clamp(1.9rem, 5vw, 2.6rem);
    line-height: 1.1;
    color: var(--text-primary);
}
.play-chooser__sub {
    margin: 0;
    max-width: 48ch;
    color: var(--text-secondary);
    font-size: 0.98rem;
    line-height: 1.4;
}

/* --- The matchmaking wait (MatchmakingWait.razor) ---
   The step between committing to a match and being seated at one, on the whole screen and above the chrome, the
   way the room it hands off to is — so the handover is one surface changing its content, not a card giving way
   to a screen. Its own sky rather than the shell's: the surface is opaque, because a translucent one would show
   the three ways in behind it and read as a dialog again. The stop just under the room's z-index (55) states
   which wins should a repaint ever catch both up at once; they never render together. */
.mm-wait {
    position: fixed;
    inset: 0;
    z-index: var(--z-match);
    display: flex;
    flex-direction: column;
    background:
        radial-gradient(120% 70% at 50% -18%, color-mix(in srgb, var(--accent-blue) 10%, transparent), transparent 62%),
        linear-gradient(180deg, var(--bg-hover) 0%, var(--bg-primary) 45%);
}
/* The way back sits where every other back control does — the top-left inset, clear of the notch. */
.mm-wait__topbar {
    display: flex;
    align-items: center;
    padding: calc(clamp(0.6rem, 2vw, 1rem) + env(safe-area-inset-top)) clamp(0.9rem, 3vw, 2.5rem) 0;
}
/* The status centered in what is left, a little above true center so it sits where the eye rests. */
.mm-wait__body {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1.5rem;
    padding: 0 clamp(1rem, 3vw, 2.5rem) 10vh;
}
.mm-wait__status {
    margin: 0;
    text-align: center;
    font-size: clamp(1.4rem, 4vw, 2.1rem);
    line-height: 1.2;
    color: var(--text-primary);
}
/* The table being laid, lit from behind. The art is the subject; the halo is the "still running" cue, and it is
   deliberately not a progress bar — the wait has no measurable progress to report, and a bar filling against
   nothing states a completion it cannot know. */
.mm-wait__stage {
    flex: 0 1 auto;                   /* a column flex item: it may shrink on a short screen, never grow past its art */
    position: relative;
    display: grid;
    place-items: center;
    isolation: isolate;
}
.mm-wait__art {
    position: relative;
    z-index: 1;
    width: clamp(9rem, 34vmin, 17rem);
    height: auto;
    filter: drop-shadow(0 22px 34px rgba(0, 0, 0, 0.55));
}
.mm-wait__pulse {
    position: absolute;
    z-index: 0;
    width: 118%;
    aspect-ratio: 1;
    border-radius: 9999px;
    background: radial-gradient(circle,
        color-mix(in srgb, var(--accent-teal) 42%, transparent),
        transparent 68%);
    animation: mm-wait-breathe 2.6s ease-in-out infinite;
}
@keyframes mm-wait-breathe {
    0%, 100% { transform: scale(0.82); opacity: 0.45; }
    50%      { transform: scale(1.04); opacity: 0.95; }
}
/* Reduced motion keeps the halo — it is the "still running" cue — and only stops it moving. */
@media (prefers-reduced-motion: reduce) {
    .mm-wait__pulse { animation: none; opacity: 0.7; }
}

/* --- Happening now (HappeningNowShelf.razor) ---
   Live context under the three ways in, deliberately the quietest thing on the page: no card, no accent fill, no
   call to action, small muted type. It exists to tilt one of the three choices above it, so anything that gave it
   card weight would make the page read as four choices instead of three. Absent entirely when there is nothing
   true to say, so the resting play home is still only the three answers. */
/* On the dark canvas "quiet" cannot mean "faint": muted type on navy at this size stops being read at all. The
   weight it is denied in colour it takes in structure instead — a hairline rule above the rows and a whisper of
   inset tint, the shape of a status strip. Still no card, no fill, and no action of its own, so it reads as
   what is true right now rather than as a fourth thing to press. */
.happening-now {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding-top: 0.9rem;
    border-top: 1px solid var(--border-color);
}
.happening-now__title {
    margin: 0;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.happening-now__rows {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 1.75rem;
}
.happening-now__row { display: flex; align-items: center; gap: 0.5rem; font-size: 0.92rem; color: var(--text-secondary); }
/* A small live pulse — the one thing that says "now" without a word for it. */
.happening-now__dot {
    flex: 0 0 auto;
    width: 0.45rem;
    height: 0.45rem;
    border-radius: 9999px;
    background: var(--accent-teal);
    animation: happening-pulse 2.4s ease-in-out infinite;
}
.happening-now__link { color: var(--text-secondary); text-decoration: underline; text-underline-offset: 0.15em; }
.happening-now__link:hover { color: var(--accent-blue-ink); }
.happening-now__text { min-width: 0; }

@keyframes happening-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.35; }
}
/* Reduced motion: the dot stays put and simply reads as a live marker. */
@media (prefers-reduced-motion: reduce) {
    .happening-now__dot { animation: none; }
}
