﻿/* The home page - on the website, in the app and in the admin's phone preview
   (2026-10-08). The website's bands and its row layout, moved here from the website's
   base.css and layouts.css so all three surfaces load one sheet and the six themes,
   written against .wx-band / .wx-hero / .wx-pin and the rest, dress the home page
   everywhere. The website loads this right after base.css, where layouts.css was, so
   the order the rules meet each other in is unchanged; its own page framing (the open
   page, natural heights on a desktop) stays in base.css.

   The fixed short/tall module heights start at 900px, so a phone - the app, the
   preview, the website on a phone - is one column of modules at their natural height. */

/* ---------- the bands (from base.css) ---------- */

/* ============================================================================
   Home page bands.

   One layout, restyled five ways. The section heading (.wx-band-head) is the
   element the themes lean on hardest - it appears once per band, so restyling
   that one rule changes the rhythm of the whole page. Everything else here is
   structure and takes its color from the contract.
   ========================================================================== */

/* .wx-home and the slots are laid out in layouts.css, which owns the shapes. */

.wx-band {
    display: grid;
    gap: calc(var(--wx-pad) * 0.6);
}

/* The one line every theme redraws. */
.wx-band-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 14px;
    padding: 6px 10px;
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    background: var(--wx-surface-2);
    color: var(--wx-ink);
    min-width: 0;
}

.wx-band-head h2 {
    margin: 0;
    font-size: 1rem;
    font-weight: 700;
    color: inherit;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.wx-band-more,
.wx-band-aside {
    flex: 0 0 auto;
    font-size: 0.82rem;
    color: inherit;
    opacity: 0.85;
    white-space: nowrap;
}

.wx-band-more:hover { opacity: 1; }

/* ---- hero -------------------------------------------------------------- */

.wx-hero {
    position: relative;
    overflow: hidden;
    border-radius: var(--wx-radius);
    /* Without an uploaded image the theme's own colors make the backdrop, so
       a partner who has supplied nothing still gets something composed. */
    background:
        radial-gradient(120% 90% at 20% 15%, var(--wx-signal-soft), transparent 62%),
        linear-gradient(155deg, var(--wx-surface-2), var(--wx-ground));
    display: grid;
    place-items: center;
    min-height: 200px;
    padding: calc(var(--wx-pad) * 1.4) var(--wx-pad);
    text-align: center;
}

.wx-hero-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Only when there is a photograph behind it does the text need a scrim. */
.wx-hero.has-image .wx-hero-in {
    position: relative;
    background: rgba(0, 0, 0, 0.45);
    padding: 18px 22px;
    border-radius: var(--wx-radius);
    color: #fff;
}

.wx-hero.has-image .wx-hero-name,
.wx-hero.has-image .wx-hero-tag { color: #fff; }

.wx-hero-in { display: grid; gap: 8px; justify-items: center; max-width: 46rem; }

.wx-hero-logo { max-height: 84px; width: auto; }

.wx-hero-name {
    margin: 0;
    font-family: var(--wx-font-display);
    font-size: clamp(1.6rem, 4vw, 2.5rem);
    font-weight: 800;
    line-height: 1.1;
    color: var(--wx-ink);
}

.wx-hero-tag {
    margin: 0;
    color: var(--wx-muted);
    font-size: 1.02rem;
    max-width: 52ch;
}

/* ---- pinned post ------------------------------------------------------- */

.wx-pin {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    gap: var(--wx-pad);
    align-items: center;
    background: var(--wx-surface);
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    overflow: hidden;
}

.wx-pin-shot { align-self: stretch; min-height: 220px; }

.wx-pin-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }

.wx-pin-in { display: grid; gap: 10px; padding: var(--wx-pad); min-width: 0; }

.wx-pin-flag {
    justify-self: start;
    font-family: var(--wx-font-data);
    font-size: 0.66rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--wx-signal);
    background: var(--wx-signal-soft);
    border-radius: var(--wx-radius);
    padding: 3px 9px;
}

.wx-pin-in h2 {
    margin: 0;
    font-size: 1.5rem;
    line-height: 1.15;
    color: var(--wx-ink);
}

.wx-pin-in p { margin: 0; color: var(--wx-muted); max-width: 56ch; }

.wx-pin-in a.wx-btn { justify-self: start; }

/* One giveaway with the box to itself (GiveawaysBand): the pinned post's shape, as a
   link. The whole card is the link, so the button inside is only its label. */
a.wx-gfeature {
    text-decoration: none;
    color: inherit;
    transition: border-color 120ms ease;
}

a.wx-gfeature:hover,
a.wx-gfeature:focus-visible { border-color: var(--wx-signal); text-decoration: none; }

.wx-gfeature .wx-btn { justify-self: start; }

/* In a module of fixed height it fills the box - the one row stretches to it, so the
   picture runs to the bottom rather than leaving a strip of card under it. */
.wx-mod .wx-gfeature { height: 100%; grid-template-rows: minmax(0, 1fr); }

/* ---- giveaway cards ---------------------------------------------------- */

.wx-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 12px;
}

.wx-gcard {
    display: flex;
    flex-direction: column;
    background: var(--wx-surface);
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    overflow: hidden;
}

/* A card that is a link keeps the card's look, not the browser's idea of one, and
   says it can be opened on hover. Cards that are still plain articles are unaffected. */
a.wx-gcard {
    text-decoration: none;
    color: inherit;
    transition: border-color 120ms ease, transform 120ms ease;
}

a.wx-gcard:hover,
a.wx-gcard:focus-visible {
    border-color: var(--wx-signal);
    transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {
    a.wx-gcard { transition: none; }
    a.wx-gcard:hover, a.wx-gcard:focus-visible { transform: none; }
}

.wx-gcard-shot {
    position: relative;
    aspect-ratio: 4 / 3;
    background: var(--wx-surface-2);
}

.wx-gcard-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Where the card's tag sits - the tag itself is ui.css's .wx-tag. */
.wx-gcard-tag {
    position: absolute;
    top: 8px;
    left: 8px;
}

.wx-gcard-in { padding: 10px 12px 14px; display: grid; gap: 3px; }

.wx-gcard-in h3 {
    margin: 0;
    font-size: 0.98rem;
    line-height: 1.25;
    color: var(--wx-ink);
}

.wx-gcard-prize { margin: 0; color: var(--wx-muted); font-size: 0.85rem; }

.wx-gcard-value {
    margin: 0;
    color: var(--wx-coin);
    font-family: var(--wx-font-data);
    font-size: 0.82rem;
    font-weight: 700;
}

/* ---- game tiles -------------------------------------------------------- */

.wx-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 12px;
}

.wx-tile {
    position: relative;
    /* Its own width for the art's height to follow - see .wx-tile-shot. */
    container-type: inline-size;
    background: var(--wx-surface);
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    overflow: hidden;
    transition: border-color 0.2s ease;
}

.wx-tile:not(.is-flat):hover { border-color: var(--wx-signal); }

/* A stretched anchor, so the whole tile is one target without nesting the
   card's text inside a link. */
.wx-tile-hit { position: absolute; inset: 0; z-index: 1; }

.wx-tile-shot {
    aspect-ratio: 16 / 9;
    /* As tall as a post card's header and picture together, so a row of games lines
       up with a row of posts (2026-11-03): the post card's picture sits under its
       stream line (.wx-post-head), and the game's art takes that room as well. */
    aspect-ratio: auto;
    height: calc(100cqi * 9 / 16 + var(--wx-post-head-h, 46px));
    background: var(--wx-surface-2);
    display: grid;
    place-items: center;
    overflow: hidden;
}

/* Cropped from the left: the taller box trims the art's sides, and a game's art carries
   its title on the left and its picture on the right - the title stays whole. */
.wx-tile-shot img { width: 100%; height: 100%; object-fit: cover; object-position: left center; display: block; }
.wx-tile-shot img.is-icon { width: auto; height: 54%; object-fit: contain; }

.wx-tile-in { padding: 10px 12px 14px; display: grid; gap: 3px; }

.wx-tile-in h3 { margin: 0; font-size: 0.96rem; color: var(--wx-ink); }
.wx-tile-in p { margin: 0; color: var(--wx-muted); font-size: 0.82rem; }

/* ---- posts ------------------------------------------------------------- */

.wx-posts {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 12px;
}

.wx-post {
    display: flex;
    flex-direction: column;
    background: var(--wx-surface);
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    overflow: hidden;
}

/* overflow: hidden is what holds the 16:9 - without it a portrait picture stretched
   its box taller than its neighbors'. */
.wx-post-shot { aspect-ratio: 16 / 9; background: var(--wx-surface-2); overflow: hidden; }
.wx-post-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* The stream's logo, its name and when - the Streams feed's card header, smaller. A
   fixed height, which a game tile's art adds to its own (.wx-tile-shot). */
.wx-post-head { display: flex; align-items: center; gap: 9px; padding: 9px 12px; min-width: 0; box-sizing: border-box; height: var(--wx-post-head-h, 46px); }
.wx-post-avatar { flex: none; width: 28px; height: 28px; border-radius: 50%; object-fit: cover; background: var(--wx-surface-2); }
.wx-post-headtext { display: flex; flex-direction: column; min-width: 0; }
.wx-post-stream { font-size: 0.8rem; font-weight: 700; color: var(--wx-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wx-post-headtext time { font-size: 0.72rem; color: var(--wx-muted-dim); }

.wx-post-in { padding: 10px 12px 12px; display: grid; gap: 5px; min-width: 0; }

.wx-post-in h3 {
    margin: 0;
    font-size: 0.95rem;
    line-height: 1.3;
    color: var(--wx-ink);
}

/* Two lines, then stop - posts are imported, so their length is not ours to
   rely on. */
.wx-post-text {
    margin: 0;
    color: var(--wx-muted);
    font-size: 0.84rem;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* One line, always: wrapping to a second pushed the card's text up over its title
   (2026-10-25). A card too narrow for all of it ends in an ellipsis instead. */
.wx-post-meta {
    display: block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--wx-muted-dim);
    font-size: 0.74rem;
    font-family: var(--wx-font-data);
}

.wx-post-meta > * + * { margin-left: 10px; }

/* ---- winners ----------------------------------------------------------- */

.wx-winners {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
    gap: 10px;
}

.wx-winner {
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--wx-surface);
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    padding: 9px 11px;
    min-width: 0;
}

.wx-winner-shot {
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    border-radius: var(--wx-radius);
    overflow: hidden;
    background: var(--wx-surface-2);
}

.wx-winner-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }

.wx-winner-in { display: grid; gap: 1px; min-width: 0; }

.wx-winner-who { font-weight: 700; color: var(--wx-ink); font-size: 0.88rem; }

.wx-winner-what {
    color: var(--wx-muted);
    font-size: 0.8rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.wx-winner-when {
    color: var(--wx-muted-dim);
    font-size: 0.72rem;
    font-family: var(--wx-font-data);
}

/* ---- points ------------------------------------------------------------ */

.wx-points {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
    gap: var(--wx-pad);
    align-items: center;
    background: var(--wx-surface);
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    padding: var(--wx-pad);
}

.wx-tally { display: flex; gap: 10px; flex-wrap: wrap; }

/* Each count's icon - a star, a ticket, a gift. Off unless a theme lays the counts out
   with room for one (cadenscoots.css stacks them). */
.wx-tally-i { display: none; }

.wx-tally-cell {
    flex: 1 1 90px;
    display: grid;
    gap: 1px;
    padding: 11px 13px;
    background: var(--wx-surface-2);
    border-radius: var(--wx-radius);
}

.wx-tally-n {
    font-family: var(--wx-font-data);
    font-variant-numeric: tabular-nums;
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--wx-coin);
    line-height: 1.1;
}

.wx-tally-l {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--wx-muted-dim);
}

.wx-points-cta { display: grid; gap: 11px; justify-items: start; }
.wx-points-cta p { margin: 0; color: var(--wx-muted); }

/* Signed out: what an account gets them - an icon, a line in bold, a line under it. */
.wx-perks { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.wx-perks li { display: flex; gap: 12px; align-items: flex-start; }
.wx-perks i { flex: none; width: 1.25rem; margin-top: 3px; text-align: center; color: var(--wx-signal); }
.wx-perks span { color: var(--wx-muted); font-size: 0.86rem; line-height: 1.4; }
.wx-perks b { display: block; color: var(--wx-ink); font-size: 0.95rem; }

/* The ways to earn, under their own title (Frank, 2026-11-10). */
.wx-earn-wrap { display: grid; gap: 10px; }

.wx-earn-h {
    margin: 0;
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--wx-ink);
}

.wx-earn { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }

.wx-earn li {
    display: flex;
    gap: 10px;
    align-items: baseline;
    color: var(--wx-muted);
    font-size: 0.86rem;
}

.wx-earn-k {
    flex: 0 0 76px;
    font-family: var(--wx-font-data);
    font-size: 0.7rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--wx-signal);
}

/* ---- app promo --------------------------------------------------------- */

.wx-promo {
    background:
        radial-gradient(110% 140% at 88% 12%, var(--wx-signal-soft), transparent 60%),
        var(--wx-surface);
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    padding: var(--wx-pad);
}

.wx-promo-in { display: grid; gap: 13px; max-width: 44rem; }
.wx-promo-in p { margin: 0; color: var(--wx-muted); font-size: 0.95rem; }
.wx-promo-links { display: flex; gap: 10px; flex-wrap: wrap; }

/* ---- narrow ------------------------------------------------------------ */

@media (max-width: 720px) {
    .wx-pin,
    .wx-points {
        grid-template-columns: 1fr;
    }

    .wx-pin-shot { min-height: 170px; }
}

/* The grand prize is the one the partner is promoting, so it reads first. */
.wx-gcard.is-grand { border-color: var(--wx-signal); }

/* Cards on the home page that are links: the same card, plus a hand and a lift. */
a.wx-post, a.wx-winner, a.wx-tally-cell { color: inherit; text-decoration: none; cursor: pointer; }
a.wx-post:hover, a.wx-winner:hover, a.wx-tally-cell:hover { border-color: var(--wx-signal); }
a.wx-tally-cell:hover { background: var(--wx-signal-soft); }

/* A Giveaways module's entry packs - "Get Entries for ..." - under the prizes. Small
   cards in a row that wraps: how many entries, and the price the store charges. */
.wx-packs { display: grid; gap: 8px; margin-top: 12px; }

.wx-packs-h { margin: 0; font-size: 0.95rem; color: var(--wx-ink); }

.wx-packs-list { display: flex; flex-wrap: wrap; gap: 8px; }

.wx-pack {
    display: grid;
    gap: 2px;
    min-width: 120px;
    padding: 8px 12px;
    background: var(--wx-surface);
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    color: inherit;
    text-decoration: none;
    transition: border-color 120ms ease;
}

/* The edge lights and nothing else: the partner sheet underlines every a:hover, which
   outranks .wx-pack on its own (2026-10-28). */
.wx-pack:hover, .wx-pack:focus-visible { border-color: var(--wx-signal); text-decoration: none; }

.wx-pack-n { font-weight: 700; color: var(--wx-ink); }

.wx-pack-price { font-family: var(--wx-font-data); font-size: 0.85rem; color: var(--wx-coin); }

/* ---- the cover ------------------------------------------------------------ */

.wx-hero-logo { display: none; }

@media (min-width: 900px) {
    :where(.wx-home.is-wide) .wx-mod[data-module="Hero"] .wx-hero { min-height: 440px; }
}

.wx-hero-tag {
    font-family: var(--wx-font-display);
    font-size: clamp(2.2rem, 5vw, 4.2rem);
    line-height: 1.04;
    letter-spacing: -0.02em;
    color: var(--wx-ink);
    max-width: 16ch;
}

@media (max-width: 899px) {
    .wx-hero-tag { font-size: clamp(2rem, 9vw, 2.8rem); }
}

/* ---------- the row layout (from layouts.css) ---------- */

/* ============================================================================
   Home page layouts.

   Structure only - every color, face and radius still comes from the theme
   contract. A page is rows of one, two or three columns (PageLayout), each column
   a slot holding modules stacked.

   Two rules hold this together:

   Slots are containers. A module sizes itself against the space it was given
   rather than the viewport, because a rail is narrow on a 27" monitor too. Any
   module that adapts must use container queries, not media queries.

   The narrow-screen order is declared, not inherited. Each cell carries its place
   in its row's stack (--stack), so what a phone shows first is a decision rather
   than an accident of source order. A gutter on the left is the case that proves
   it: drawn first and stacked second.
   ========================================================================== */

.wx-home {
    display: grid;
    gap: var(--wx-mod-gap);
}

.wx-slot {
    display: grid;
    gap: var(--wx-mod-gap);
    align-content: start;
    min-width: 0;

    /* What lets a module know how much room it actually has. */
    container-type: inline-size;
}

/* On a phone a cell with nothing in it gives its space back. On a wide screen it
   keeps it - it is a column of its row, and hiding it would slide the next column
   into its place. Not :empty - the markup leaves whitespace inside the element, so
   :empty never matches; :has(*) asks the question that was meant. */
@media (max-width: 899px) {
    .wx-slot:not(:has(*)) {
        display: none;
    }
}

/* ---- heights ----------------------------------------------------------- */

/* Every module sits in a box of one of two heights on a wide screen - short, or
   tall, which is exactly two shorts and the gap between them - so columns line up
   whatever is in them: two shorts side by side, two talls, or a tall beside two
   stacked shorts (Frank, 2026-10-01). The height does not change with the width; a
   module rearranges itself to fit (container queries on .wx-slot). A phone stacks
   everything at its natural height, so none of this applies below 900px.

   220, not 260: measured on WAY-EZ (2026-10-02), the most any short module needed was
   216 (the hero) - the streak 186, the balances 158 - and the tallest list in a tall box
   450, inside the 475 this makes it. At 260 every short row ended in a band of nothing. */
.wx-home {
    /* How far past a clipping box a card's solid edge may hang - see .wx-mod below.
       The deepest theme edge is Playbook's 9px offset plus its 3px spread. */
    --wx-edge-room: 12px;
    --wx-mod-gap: calc(var(--wx-pad) * 1.6);
    --wx-short: 220px;
    --wx-tall: calc(var(--wx-short) * 2 + var(--wx-mod-gap));
}

/* A module with nothing to show - the streak for a visitor - takes no room. */
.wx-mod:not(:has(*)) {
    display: none;
}

@media (min-width: 900px) {
    /* Clipped, but with room past the edge for a theme's solid card edge - Playbook draws
       its border as a shadow hanging up to 12px below each card (0 9px 0 3px), and the
       modules are sized to fit their rows exactly, so a plain overflow: hidden sliced it
       flat at the bottom of every list module (2026-10-19, the third time). The edge
       hangs into the gap between modules instead. Where overflow-clip-margin isn't
       supported it clips at the edge, as before. e2e/tests/signed-in/edges.spec.ts
       checks it. */
    :where(.wx-home.is-wide) .wx-mod {
        display: flex;
        flex-direction: column;
        min-width: 0;
        overflow: hidden;
        overflow: clip;
        overflow-clip-margin: var(--wx-edge-room);
    }

    :where(.wx-home.is-wide) .wx-mod > * {
        flex: 1 1 auto;
        min-height: 0;
    }

    :where(.wx-home.is-wide) .wx-mod[data-height="short"] { height: var(--wx-short); }
    :where(.wx-home.is-wide) .wx-mod[data-height="tall"] { height: var(--wx-tall); }

    /* ---- fitting the box --------------------------------------------------
       Every module fills its box, at full, half or third width. A band keeps its
       heading and gives the rest to its body; a list in a band shows the whole cards
       that fit and no part of the next one (wxFit.js hides the rest - its heading's
       "See All" has them). The narrow arrangements key off the slot's width, which is
       what each module is given. */

    :where(.wx-home.is-wide) .wx-mod > .wx-band {
        display: flex;
        flex-direction: column;
    }

    :where(.wx-home.is-wide) .wx-mod > .wx-band > :not(.wx-band-head) {
        flex: 1 1 auto;
        min-height: 0;
        overflow: hidden;
        overflow: clip;
        overflow-clip-margin: var(--wx-edge-room);
        align-content: start;
    }

    /* A Giveaways module's entry packs keep their natural height at the foot; the
       giveaways above give way. */
    :where(.wx-home.is-wide) .wx-mod > .wx-band > .wx-packs { flex: none; }

    /* A list keeps every card its natural height. In a box of fixed height the grid
       would otherwise shrink its rows to fit and squash every card - the text cut
       off inside each - instead of letting the ones that don't fit fall past the
       bottom, where wxFit.js finds them. */
    :where(.wx-home.is-wide) .wx-mod :is(.wx-posts, .wx-cards, .wx-tiles, .wx-winners, .product-grid) {
        grid-auto-rows: max-content;
        align-content: start;
    }

    :where(.wx-home.is-wide) .wx-mod :is(.wx-posts, .wx-cards, .wx-tiles, .wx-winners, .product-grid) > * {
        flex-shrink: 0;
    }

    /* Compact cards in a tall box: narrower columns, and the picture and the title
       without the paragraph under it - so the count a partner set fits. Six posts or
       six games at half width is three across and two down; at the store page's or
       the feed's own size two big cards were all a half-width box could hold. */
    /* 150, not 170: three across has to fit half width with a theme's own gap - Slate
       spaces cards 22px apart, and 3 x 170 + 44 is wider than a half-width box (546px
       at 1280), so it fell to two across and a tall box held one row (2026-10-02). */
    :where(.wx-home.is-wide) .wx-mod[data-height="tall"] .wx-posts, :where(.wx-home.is-wide) .wx-mod[data-height="tall"] .wx-tiles, :where(.wx-home.is-wide) .wx-mod[data-height="tall"] .product-grid {
        grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    }

    :where(.wx-home.is-wide) .wx-mod[data-height="tall"] :is(.wx-post-text, .wx-tile-in p, .product-info .desc) {
        display: none;
    }

    /* One card size for posts and games: the same picture, and the same room under it
       - two lines of title and the line under those - so two tall modules side by side
       have rows that match (Frank, 2026-10-01). */
    :where(.wx-home.is-wide) .wx-mod[data-height="tall"] :is(.wx-post-in, .wx-tile-in) {
        box-sizing: border-box;
        height: 82px;
        align-content: start;
        overflow: hidden;
    }

    :where(.wx-home.is-wide) .wx-mod[data-height="tall"] :is(.wx-post-in h3, .wx-tile-in h3) {
        font-size: 0.86rem;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }

    /* The hero fills the box; its photograph crops to it. */
    :where(.wx-home.is-wide) .wx-mod > .wx-hero { min-height: 0; height: 100%; }

    /* The streak and the balances sit in the middle of a box that is taller than
       they need. */
    :where(.wx-home.is-wide) .wx-mod > .vs { height: 100%; align-content: center; }
    :where(.wx-home.is-wide) .wx-mod > .wx-band > .wx-points { height: 100%; align-content: center; }

    /* A pinned post fills its box: picture and words side by side. */
    :where(.wx-home.is-wide) .wx-mod > .wx-pin { height: 100%; }
    :where(.wx-home.is-wide) .wx-mod > .wx-pin .wx-pin-shot { min-height: 0; }

    /* Text that runs past its box fades out rather than stopping mid-line. */
    :where(.wx-home.is-wide) .wx-mod > .wx-textblock { height: 100%; overflow: hidden; }
    :where(.wx-home.is-wide) .wx-mod > .wx-textblock.is-clipped {
        -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 48px), transparent);
        mask-image: linear-gradient(to bottom, #000 calc(100% - 48px), transparent);
    }

    /* A third: one product to a row, and a square picture would make that one card
       taller than the box. A landscape crop keeps at least one in it. */
    @container (max-width: 520px) {
        :where(.wx-home.is-wide) .wx-mod .product-grid .product-image img, :where(.wx-home.is-wide) .wx-mod .product-grid .product-noimage {
            aspect-ratio: 4 / 3;
            object-fit: cover;
        }
    }

    /* Half or a third: the balances alone - the ways to earn need the room. */
    @container (max-width: 760px) {
        :where(.wx-home.is-wide) .wx-mod[data-height="short"] .wx-points { grid-template-columns: minmax(0, 1fr); }
        :where(.wx-home.is-wide) .wx-mod[data-height="short"] .wx-earn-wrap { display: none; }
    }

    /* A short pinned post in a narrow column has no room for its picture. */
    @container (max-width: 520px) {
        :where(.wx-home.is-wide) .wx-mod[data-height="short"] .wx-pin { grid-template-columns: minmax(0, 1fr); }
        :where(.wx-home.is-wide) .wx-mod[data-height="short"] .wx-pin-shot { display: none; }
    }

    /* A tall pinned post in a narrow column: picture above, words below. */
    @container (max-width: 520px) {
        :where(.wx-home.is-wide) .wx-mod[data-height="tall"] .wx-pin {
            grid-template-columns: minmax(0, 1fr);
            grid-template-rows: minmax(0, 1fr) auto;
        }
    }
}

/* ---- rows ------------------------------------------------------------- */

/* A page is rows the partner built (PageLayout), each a shape. (wx-layout-row, not
   wx-row: that is ui.css's list row, and sharing the name hid every list row on the
   website with no module in it - the cart's entries list among them.) On a wide screen a
   row's columns are its shape's widths - the 2:1 of a gutter, halves, thirds; a
   gutter is a third, as the old rail was. */
.wx-layout-row {
    display: grid;
    gap: var(--wx-mod-gap);
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
}

/* A row with nothing to show in any of its cells gives its space back. */
.wx-layout-row:not(:has(.wx-mod > *)) {
    display: none;
}

/* And a cell with nothing to show steps aside, so the rest of its row shares the width:
   a streak beside the points is only drawn for somebody signed in, and signed out the
   points sat in half a row with an empty half beside them (Frank, 2026-11-10). The row
   test is :empty because :has() cannot hold another :has() - a cell whose module was
   left out entirely is empty; the slot rule also catches a module that drew nothing. */
.wx-layout-row > .wx-slot:not(:has(.wx-mod > *)) { display: none; }

@media (min-width: 900px) {
    :where(.wx-home.is-wide) .wx-layout-row:has(> .wx-slot:empty) {
        grid-template-columns: none;
        grid-auto-flow: column;
        grid-auto-columns: minmax(0, 1fr);
    }
}

@media (min-width: 900px) {
    :where(.wx-home.is-wide) .wx-layout-row[data-shape="two-split"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    :where(.wx-home.is-wide) .wx-layout-row[data-shape="gutter-right"] { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
    :where(.wx-home.is-wide) .wx-layout-row[data-shape="gutter-left"] { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); }
    :where(.wx-home.is-wide) .wx-layout-row[data-shape="three"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ---- narrow ------------------------------------------------------------ */

/* One column, in each row's stack order: left to right, except that a gutter on the
   left comes after its wide column - nobody scrolls past a sidebar to reach the shop.
   The order is the cell's own --stack (RowShapes.StackOrder), not source order. */
@media (max-width: 899px) {
    .wx-layout-row {
        display: flex;
        flex-direction: column;
        /* Full width - the wide screen's align-items: start would shrink each cell
           to its content here. */
        align-items: stretch;
    }

    .wx-layout-row > .wx-slot { order: var(--stack, 0); }
}

/* ---- modules in a narrow slot ------------------------------------------ */

/* A rail is about a third of the shell. Everything that lays out in columns
   has to collapse against the slot, not the window. */
@container (max-width: 460px) {
    .product-grid,
    .wx-cards,
    .wx-tiles,
    .wx-posts,
    .wx-winners {
        grid-template-columns: minmax(0, 1fr);
    }

    .wx-pin,
    .wx-points {
        grid-template-columns: minmax(0, 1fr);
    }

    .wx-pin-shot {
        min-height: 150px;
    }

    /* The hero carries less weight in a rail than across the page. */
    .wx-hero {
        min-height: 150px;
    }

    .wx-hero-name {
        font-size: clamp(1.2rem, 6cqi, 1.8rem);
    }
}

@container (min-width: 461px) and (max-width: 700px) {
    .product-grid,
    .wx-cards,
    .wx-tiles,
    .wx-posts {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* ---- text module ------------------------------------------------------- */

.wx-textblock {
    display: grid;
    gap: 10px;
    justify-items: start;
    background: var(--wx-surface);
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    padding: var(--wx-pad);
}

.wx-textblock h2 {
    margin: 0;
    font-size: 1.25rem;
    line-height: 1.2;
    color: var(--wx-ink);
}

/* Line breaks the partner typed survive without any of it being markup. */
.wx-textblock p {
    margin: 0;
    color: var(--wx-muted);
    white-space: pre-wrap;
    max-width: 62ch;
}

/* A card wxFit.js found past the bottom of its module's box. */
.wx-fit-out { display: none !important; }


/* ---------- a phone, whatever the window ----------
   The app and the admin's phone preview - a phone-sized frame in a wide window - get
   the phone's rules above by the screen's own flag (is-app), not the window's width
   (2026-10-08: the preview drew the desktop grid in a phone and the cards overran). */

.wx-home.is-app .wx-pin, .wx-home.is-app .wx-points {
        grid-template-columns: 1fr;
    }

    .wx-home.is-app .wx-pin-shot { min-height: 170px; }

.wx-home.is-app .wx-hero-tag { font-size: clamp(2rem, 9vw, 2.8rem); }

.wx-home.is-app .wx-slot:not(:has(*)) {
        display: none;
    }

.wx-home.is-app .wx-layout-row {
        display: flex;
        flex-direction: column;
        /* Full width - the wide screen's align-items: start would shrink each cell
           to its content here. */
        align-items: stretch;
    }

    .wx-home.is-app .wx-layout-row > .wx-slot { order: var(--stack, 0); }

/* The screen owns its scrolling in the app, inside the chrome, with the app's inset. */
.wx-home.is-app {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior-y: contain;
    padding: 14px 14px 32px;
    --wx-mod-gap: 22px;
}

/* Products on the app's home: two to a row with room between them (2026-10-08) - one
   to a row they filled the screen, and a theme's offset shadow (Playbook's) closed the
   gap so the cards read as overlapping. */
.wx-home.is-app .product-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 22px 12px;
    padding: 0 0 6px;
}

.wx-home.is-app .product-grid .product-info .desc { display: none; }
.wx-home.is-app .product-grid .product-purchase { flex-wrap: wrap; font-size: 0.9rem; }

/* The same sizing the website gets from Bootstrap - see store.css. */
.wx-home.is-app,
.wx-home.is-app * {
    box-sizing: border-box;
}

/* The Ad module (2026-10-18): one ad, drawn like the other bands' cards so the theme
   dresses it. The whole tile is the link. Short puts the picture beside the words;
   Tall stacks them with the picture on top. */
.wx-adtile {
    display: block;
    height: 100%;
    color: inherit;
    text-decoration: none;
    background: var(--wx-surface);
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    overflow: hidden;
}

.wx-adtile-in {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
    height: 100%;
}

.wx-adtile-img {
    width: 100%;
    height: 100%;
    min-height: 140px;
    object-fit: cover;
    display: block;
}

.wx-adtile-text {
    display: grid;
    align-content: center;
    justify-items: start;
    gap: 8px;
    padding: var(--wx-pad);
}

.wx-adtile-tag {
    font-size: 0.72rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--wx-muted);
}

.wx-adtile-head {
    font-size: 1.2rem;
    line-height: 1.2;
    font-weight: 700;
    color: var(--wx-ink);
}

.wx-adtile-line {
    color: var(--wx-muted);
    max-width: 52ch;
}

.wx-adtile-in:not(:has(.wx-adtile-img)) { grid-template-columns: 1fr; }

.wx-mod[data-height="tall"] .wx-adtile-in { grid-template-columns: 1fr; grid-template-rows: minmax(0, 1fr) auto; }
.wx-mod[data-height="tall"] .wx-adtile-img { min-height: 200px; }

/* A phone stacks it, picture on top, at its natural height. */
.wx-home.is-app .wx-adtile-in { grid-template-columns: 1fr; }
.wx-home.is-app .wx-adtile-img { aspect-ratio: 16 / 9; height: auto; min-height: 0; }

/* The giveaway band's smaller cards - the giveaways page's own (giveaways.css), under the
   Grand drawn large, or on their own when there is no Grand (2026-10-27). Links here,
   not buttons, so they take the text's color and no underline. */
.wx-gfeature + .wx-home-gw { margin-top: 12px; }

/* The heading over them, when the partner gave one - "Weekly Giveaways" (2026-11-10). */
.wx-gw-others-h {
    flex: none;
    margin: 18px 0 0;
    font-size: 1.05rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}

.wx-gw-others-h + .wx-home-gw { margin-top: 10px; }

/* The partner's line under a band's heading (the module's Text setting). */
.wx-band-intro {
    margin: -6px 0 0;
    max-width: 70ch;
    color: var(--wx-muted);
    font-size: 1rem;
    line-height: 1.5;
}
a.gw-card, a.gw-card:hover { color: inherit; text-decoration: none; }
.wx-home-gw .gw-card > :last-child { padding-bottom: 10px; }

/* In a box of fixed height (a wide screen): the small cards keep their own height, in a
   row along the foot, and the Grand takes what is left above them. Cards that don't fit
   the row are cut at the box's edge; See All has them. */
@media (min-width: 900px) {
    :where(.wx-home.is-wide) .wx-mod > .wx-band > .wx-home-gw {
        flex: none;
        /* auto-fit, so one card takes the row and two share it (Frank, 2026-10-28). */
        grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
        grid-auto-rows: max-content;
    }

    :where(.wx-home.is-wide) .wx-mod > .wx-band > .wx-gfeature:has(~ .wx-home-gw) { height: auto; }

    /* The large giveaway is itself a rounded card, so it clips at its own corners. The
       band's clip margin above (room for a theme's edge) let the photo run 12px past
       them (2026-10-28). Its own edge is a box-shadow, which no clip touches. */
    :where(.wx-home.is-wide) .wx-mod > .wx-band > .wx-gfeature { overflow: hidden; }
}


/* ---- a module's Background (2026-11-10) -----------------------------------
   Plain sits on the page. Dark is a band of its own, on the theme's dark ground
   (--wx-band-dark, dark in both of a theme's modes); Photo is that band with the
   partner's picture behind it under the theme's wash. The rest of the palette inside
   the band is mixed from the band's two colors, so the cards, lines and muted text in
   it follow without any module knowing it is in one. The brand colors stay the
   theme's own. What lets a home page alternate dark and light bands the way a
   creator's own site does (Caden Scoots). */

.wx-mod[data-bg="dark"],
.wx-mod[data-bg="photo"] {
    --wx-ground: var(--wx-band-dark);
    --wx-ground-deep: color-mix(in srgb, var(--wx-band-dark-ink) 3%, var(--wx-band-dark));
    --wx-surface: color-mix(in srgb, var(--wx-band-dark-ink) 7%, var(--wx-band-dark));
    --wx-surface-2: color-mix(in srgb, var(--wx-band-dark-ink) 12%, var(--wx-band-dark));
    --wx-line: color-mix(in srgb, var(--wx-band-dark-ink) 22%, var(--wx-band-dark));
    --wx-line-soft: color-mix(in srgb, var(--wx-band-dark-ink) 14%, var(--wx-band-dark));
    --wx-ink: var(--wx-band-dark-ink);
    --wx-muted: color-mix(in srgb, var(--wx-band-dark-ink) 74%, var(--wx-band-dark));
    --wx-muted-dim: color-mix(in srgb, var(--wx-band-dark-ink) 54%, var(--wx-band-dark));
    --wx-color-scheme: dark;
    color-scheme: dark;

    position: relative;
    isolation: isolate;
    box-sizing: border-box;
    padding: calc(var(--wx-pad) * 1.1);
    border-radius: var(--wx-radius);
    background: var(--wx-ground);
    color: var(--wx-ink);
}

/* The picture fills the band behind everything in it, and the wash sits between them. */
.wx-mod-bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    z-index: -2;
    display: block;
    border-radius: inherit;
}

.wx-mod[data-bg="photo"]::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    background: var(--wx-scrim);
}

/* On the photo the band's heading bar would be a box floating on the picture; it lets
   the picture through instead, and the text takes the color made for pictures. */
.wx-mod[data-bg="photo"] {
    --wx-ink: var(--wx-on-image);
    background: var(--wx-band-dark);
}

.wx-mod[data-bg="photo"] .wx-band-head {
    background: transparent;
    border-color: transparent;
}

/* A text block or the balances in a dark band read on the band, not on a card of their
   own laid over it. */
.wx-mod:is([data-bg="dark"], [data-bg="photo"]) > :is(.wx-textblock, .wx-promo) {
    background: transparent;
    border-color: transparent;
    box-shadow: none;
}

/* ---- a hero's line and button (2026-11-10) --------------------------------------- */

.wx-hero-line {
    margin: 0;
    max-width: 40rem;
    color: var(--wx-muted);
    font-size: 1rem;
    line-height: 1.45;
}

.wx-hero.has-image .wx-hero-line { color: var(--wx-on-image); }

.wx-hero-btn { margin-top: 10px; }

/* ---- scrolling words (2026-11-10) -----------------------------------------------
   The partner's words, repeated across, sliding left. The track holds the words twice
   over (sixteen), so moving it half its width brings the second half to where the
   first began and the loop shows no seam. Still for anybody who turned motion off. */

.wx-marquee {
    overflow: hidden;
    padding: 14px 0;
    /* Its width is the page's, never its words': the track is many times wider than
       the screen, and a box sized to it pushed the phone's page sideways. */
    contain: inline-size;
}

.wx-mod[data-module="Marquee"] { min-width: 0; }

.wx-marquee-hit,
.wx-marquee-hit:hover {
    display: block;
    color: inherit;
    text-decoration: none;
}

.wx-marquee-track {
    display: inline-flex;
    gap: 2.4em;
    white-space: nowrap;
    animation: wx-marquee 40s linear infinite;
}

.wx-marquee-word {
    font-family: var(--wx-font-display);
    font-weight: 800;
    font-size: clamp(1.1rem, 2.4vw, 1.7rem);
    text-transform: uppercase;
    color: var(--wx-ink);
}

@keyframes wx-marquee {
    from { transform: translateX(0); }
    to { transform: translateX(calc(-50% - 1.2em)); }
}

@media (prefers-reduced-motion: reduce) {
    .wx-marquee-track { animation: none; }
}

/* A strip has no box of its own to fill: on a wide screen it keeps its own height. */
@media (min-width: 900px) {
    :where(.wx-home.is-wide) .wx-mod[data-module="Marquee"] { height: auto; }
}

/* ---- a page of the partner's own, and its questions (2026-11-10) ------------------ */

.wx-page-title {
    margin: 8px 0 24px;
    font-family: var(--wx-font-display);
    font-size: clamp(1.8rem, 4vw, 3rem);
    line-height: 1.05;
    text-align: center;
    color: var(--wx-ink);
}

.wx-questions { display: grid; border-top: 1px solid var(--wx-line); }

.wx-question { border-bottom: 1px solid var(--wx-line); }

.wx-question summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 14px 2px;
    cursor: pointer;
    list-style: none;
    font-weight: 700;
    color: var(--wx-ink);
}

.wx-question summary::-webkit-details-marker { display: none; }

.wx-question summary::after {
    content: "\f078";
    font-family: "Font Awesome 6 Free", "Font Awesome 5 Free";
    font-weight: 900;
    font-size: 0.8em;
    flex: none;
    transition: transform 0.2s;
}

.wx-question[open] summary::after { transform: rotate(180deg); }

.wx-question p {
    margin: 0 2px 16px;
    max-width: 70ch;
    color: var(--wx-muted);
    white-space: pre-wrap;
}

@media (prefers-reduced-motion: reduce) {
    .wx-question summary::after { transition: none; }
}

/* A page's blocks keep their natural height - a list of questions is as long as it is. */
@media (min-width: 900px) {
    :where(.wx-home.is-wide) .wx-mod[data-module="Questions"] { height: auto; }
}
