﻿/* ============================================================================
   Partner storefront - structure.

   This file lays the site out and owns no colours, no typefaces and no corner
   radii of its own. Every one of those comes from a token in the theme
   contract (WinWrxCore/Models/PartnerTheme.cs), which a theme stylesheet sets
   and a partner then overrides. Put a literal colour in here and it becomes the
   one thing a partner cannot change, so don't.

   Load order in Partner/Layout/MainLayout.razor:
       base.css  ->  themes/<key>.css  ->  inline partner overrides
   ========================================================================== */

/* ---- reset ------------------------------------------------------------- */

body, h1, h2, h3, h4, h5, p, ul, li, a {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: var(--wx-font-body);
    line-height: 1.6;
    color: var(--wx-ink);
    background-color: var(--wx-ground);
    margin: 0;
    /* Themes are designed as a pair; telling the browser which one is showing
       gets form controls and scrollbars to match rather than fight. */
    color-scheme: var(--wx-color-scheme, light);

    /* A column the height of the window at least, so on a short page the footer sits
       at the foot of the window rather than halfway up it (see footer). */
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
}

h1, h2, h3, h4, h5 {
    font-family: var(--wx-font-display);
    color: var(--wx-ink);
    text-wrap: balance;
}

img {
    max-width: 100%;
}

/* ---- shell ------------------------------------------------------------- */

/* The site's own header, by class. A bare `header` here also dressed every other
   header on the page - a game's title row got the site's border and its z-index of
   1000, drew a second line under the first and sat over the account menu. */
header.site-header {
    background: var(--wx-surface);
    border-bottom: 1px solid var(--wx-line);
    z-index: 1000;
}

header .container,
footer .container {
    max-width: var(--wx-shell);
    margin: 0 auto;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

header .logo {
    flex: 0 0 auto;
    text-align: left;
    padding: 5px 0;
}

header .logo img {
    max-height: 50px;
    display: block;
    margin: 0;
}

header nav {
    flex: 1;
    text-align: center;
}

header nav ul,
footer nav ul {
    list-style: none;
    display: inline-flex;
    gap: 20px;
    margin: 0;
    padding: 0;
}

header nav ul li a {
    text-decoration: none;
    color: var(--wx-ink);
    font-weight: bold;
    padding: 5px 10px;
    border-radius: var(--wx-radius);
    transition: background 0.3s, color 0.3s;
}

header nav ul li a:hover,
header nav ul li a.active {
    background: var(--wx-signal);
    color: var(--wx-signal-ink);
    text-decoration: none;
}

main {
    padding: 10px 20px 20px;
    background: var(--wx-surface);
    margin: 20px auto;
    /* A flex item with auto margins shrinks to its content; this keeps the frame the
       shell's width. */
    width: 100%;
    box-sizing: border-box;
    max-width: var(--wx-shell);
    box-shadow: var(--wx-shadow, 0 2px 5px rgba(0, 0, 0, 0.1));
    border-radius: var(--wx-radius);
}

footer {
    background: var(--wx-ground-deep);
    color: var(--wx-ink);
    text-align: center;
    padding: 15px 20px;
    /* Pushed to the foot of the window when the page is shorter than it; main's own
       bottom margin is the gap otherwise. */
    margin-top: auto;
}

footer nav ul li a {
    text-decoration: none;
    color: var(--wx-ink);
    font-weight: bold;
    padding: 5px 10px;
    border-radius: var(--wx-radius);
    transition: background 0.3s, color 0.3s;
}

footer nav ul li a:hover,
footer nav ul li a.active {
    background: var(--wx-signal);
    color: var(--wx-signal-ink);
    text-decoration: none;
}

/* ---- links and buttons ------------------------------------------------- */

a {
    color: var(--wx-muted);
    text-decoration: none;
    transition: color 0.3s ease;
}

a:hover {
    color: var(--wx-ink);
    text-decoration: underline;
}

a:active,
a:focus {
    color: var(--wx-muted-dim);
}

/* Keyboard focus stays visible everywhere; a theme may restyle the ring
   through the tokens but cannot remove it. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
    outline: 2px solid var(--wx-signal);
    outline-offset: 2px;
}

/* The website's own buttons - .btn, and a bare <button> with no class of its own.
   A button that has a class is a shared component's, and that component owns its
   look (ui.css): styling every <button> here repainted the app's rows, cards and links
   as filled buttons, and every theme's case and letter-spacing came along with it. */
.btn, button:not([class]) {
    background-color: var(--wx-signal);
    color: var(--wx-signal-ink);
    font-family: var(--wx-font-body);
    font-weight: bold;
    padding: 10px 20px;
    border: none;
    border-radius: var(--wx-radius);
    cursor: pointer;
    transition: background 0.3s, color 0.3s, transform 0.2s;
}

.btn:hover, button:not([class]):hover {
    background-color: var(--wx-signal);
    color: var(--wx-signal-ink);
    filter: brightness(1.1);
}

.btn:active, button:not([class]):active {
    transform: scale(0.99);
    filter: none;
}

/* Disabled is the button's own look at half strength - never a different colour.
   Repainting it in the second surface colour with dim text made a disabled Save or
   Continue nearly invisible against a dark theme, and it outranked every button
   class's own look. */
button:disabled, .btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    filter: none;
    transform: none;
}

/* ---- product detail ---------------------------------------------------- */

.single-product {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    max-width: var(--wx-shell);
    margin: 20px auto 15px;
    background-color: var(--wx-surface);
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    padding: 20px;
    gap: 20px;
}

.product-image-gallery {
    position: relative;
    width: 100%;
    max-width: 600px;
    flex: 1;
}

.product-image-gallery .carousel {
    display: flex;
    transition: transform 0.5s ease-in-out;
    overflow: hidden;
}

.product-image-gallery .carousel-item {
    min-width: 100%;
    text-align: center;
}

.product-image-gallery .carousel-item img {
    width: 100%;
    height: auto;
    border-radius: var(--wx-radius);
}

/* "Sold out" and friends - a warning, so it reads from the semantic token
   rather than the brand colour. */
.product-image-gallery .overlay-text,
.product-grid .product-image .overlay-text {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) rotate(-15deg);
    background-color: var(--wx-bad);
    color: #fff;
    font-size: 1rem;
    font-weight: bold;
    text-align: center;
    padding: 5px 10px;
    border-radius: var(--wx-radius);
    z-index: 2;
    pointer-events: none;
}

/* No picture, or one that won't load: a square with an image icon, so the card keeps
   its shape. */
.product-grid .product-noimage,
.product-image-gallery .product-noimage {
    aspect-ratio: 1 / 1;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--wx-ground);
    color: var(--wx-muted-dim);
    font-size: 2rem;
    border-radius: var(--wx-radius);
}

.product-grid .product-noimage[hidden] { display: none; }

.product-image-gallery .product-noimage { font-size: 3rem; }

.members-tag.is-on-card {
    margin: 2px 0 4px;
}

.product-image-gallery .carousel-controls {
    position: absolute;
    top: 50%;
    left: 0;
    width: 100%;
    display: flex;
    justify-content: space-between;
    transform: translateY(-50%);
}

.product-image-gallery .carousel-control {
    background-color: rgba(0, 0, 0, 0.5);
    border: none;
    color: #fff;
    padding: 10px;
    cursor: pointer;
    border-radius: 50%;
    font-size: 1.5rem;
    transition: background-color 0.3s;
}

.product-image-gallery .carousel-control:hover {
    background-color: rgba(0, 0, 0, 0.8);
}

.product-details-section {
    flex: 1;
    padding: 10px;
    display: flex;
    flex-direction: column;
    gap: 15px;
}

.product-details-section .product-name {
    font-family: var(--wx-font-display);
    font-size: 1.5rem;
    font-weight: bold;
    text-transform: capitalize;
    color: var(--wx-ink);
}

.product-details-section .product-description {
    font-size: 1rem;
    color: var(--wx-muted);
    line-height: 1.5;
}

.product-details-section .product-purchase {
    justify-content: flex-end;
    display: flex;
    gap: 10px;
    font-size: 1rem;
    color: var(--wx-good);
    font-weight: bold;
}

.product-details-section .product-purchase .points,
.product-details-section .product-purchase .price {
    display: flex;
    align-items: center;
    gap: 5px;
}

.product-details-section .product-purchase .plus {
    flex: 0;
    text-align: center;
}

.product-details-section .product-discount {
    background-color: var(--wx-ground);
    text-align: center;
    border: 1px dashed var(--wx-line);
    padding: 10px;
    border-radius: var(--wx-radius);
    font-size: 0.9rem;
    color: var(--wx-muted);
}

.product-details-section .product-variants,
.product-details-section .product-modifiers {
    background-color: var(--wx-surface);
    padding: 10px;
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    font-size: 0.9rem;
}

.product-details-section .product-variants label {
    font-weight: bold;
    color: var(--wx-ink);
}

/* The option groups, and the note under them about price and stock, each with room
   of their own - a label ran straight on from the row of buttons above it. */
.product-details-section .product-variants {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.product-details-section .product-option label {
    display: block;
    margin-bottom: 6px;
}

.product-details-section .product-variants .alert { margin: 0; }

.product-details-section .product-modifiers input[type="checkbox"] {
    margin-right: 10px;
    accent-color: var(--wx-signal);
}

.product-details-section .product-checkout {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 10px;
}

.product-details-section .product-checkout .count {
    flex: 0.6;
    text-align: left;
}

.product-description ul,
.product-info ul {
    margin-left: 0;
    padding-left: 10px;
}

.product-description li,
.product-info li {
    display: list-item;
    border: none;
    background-color: transparent;
    box-shadow: none;
    padding: 0;
    margin: 5px;
    font-size: 0.75rem;
}

/* ---- product grid ------------------------------------------------------ */

/* The checkout pages are a stack of collapsible panels, not a grid of
   products. They used to say class="product-grid" to borrow the section
   heading, which was harmless only while that grid was scoped to an ancestor
   they did not have - the moment it was not, the whole page laid itself out in
   250px columns. */
.checkout-panels {
    display: grid;
    /* One column that can never be wider than the page. Left to size itself, the column
       grew to its widest child's natural width - Profile's form made it 580px on a 390px
       phone and the whole page scrolled sideways. */
    grid-template-columns: minmax(0, 1fr);
    gap: 6px;
}

.product-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 2px;
    padding: 2px;
}

/* An account room's top (RoomHead): the title sits in the back row on a phone, the
   way the app draws a room, and in the header bar on a wide screen. */
.room-nav .room-title { display: none; }

/* Back to the account hub: a phone's way round only - see RoomHead. */
@media (min-width: 900px) {
    .room-nav .wx-back.is-hub-back { display: none; }
}
@media (max-width: 899px) {
    .room-nav .room-title { display: block; }
    .display-header.room-bar { display: none; }
}

.display-header {
    padding: 5px;
    margin-bottom: 5px;
    cursor: pointer;
    align-content: center;
    grid-column: 1 / -1;
    display: flex;
    justify-content: flex-start;
    height: 100%;
    width: 100%;
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    background-color: var(--wx-surface-2);
    color: var(--wx-ink);
}

.display-header:hover {
    background-color: var(--wx-signal);
    color: var(--wx-signal-ink);
}

.display-header .name {
    /* Authored in sentence case; the header bar is a heading, and this is where a
       heading is set in capitals (design spec: themes may uppercase headings only). */
    text-transform: uppercase;
    flex: 1;
    min-width: 0;
    text-align: left;
    padding-left: 5px;
    color: inherit;
    /* A long section name in capitals, in a wide display face, wraps rather than
       pushing the page sideways on a phone ("Redeem Points for Giveaway Entries"). */
    overflow-wrap: anywhere;
}

.display-header .count {
    flex: 0 0 auto;
    white-space: nowrap;
    text-align: right;
    padding-right: 5px;
    color: inherit;
}

.product-grid .product-card {
    cursor: pointer;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    height: 100%;
    margin: 0 auto;
    padding: 0;
    background: var(--wx-surface);
    border-radius: var(--wx-radius);
    border: 1px solid var(--wx-line);
    transition: border-color 0.2s ease, transform 0.2s ease;
}

.product-grid .product-card:hover {
    border-color: var(--wx-signal);
}

.product-grid .product-image {
    position: relative;
    width: 100%;
    height: auto;
    overflow: hidden;
}

.product-grid .product-image img {
    max-width: 100%;
    height: auto;
    border-radius: var(--wx-radius);
    margin-bottom: 2px;
    display: block;
    width: 100%;
}

.product-grid .product-info {
    padding: 0 5px;
    font-size: 0.9rem;
    text-align: left;
}

.product-grid .name {
    font-family: var(--wx-font-display);
    font-weight: bold;
    color: var(--wx-ink);
}

.product-grid .desc {
    color: var(--wx-muted);
}

.product-grid .product-purchase {
    width: 100%;
    margin-top: auto;
    display: flex;
    font-size: 1rem;
    color: var(--wx-good);
    font-weight: bold;
    justify-content: space-between;
    font-family: var(--wx-font-data);
}

.product-grid .product-purchase.single-item {
    justify-content: flex-end;
}

.product-grid .product-purchase .points {
    text-align: left;
    padding: 0 5px;
}

.product-grid .product-purchase .plus {
    flex: 1;
    text-align: center;
}

.product-grid .product-purchase .price {
    text-align: right;
    padding: 0 5px;
}

/* ---- rewards ----------------------------------------------------------- */

/* Points and entries are currency, so they are gold in every theme - a brand
   colour that happened to be gold would make them invisible. */
.product-rewards,
.product-details-section .product-rewards,
.product-grid .product-rewards {
    display: flex;
    justify-content: space-between;
    font-size: 0.9rem;
    font-weight: bold;
    color: var(--wx-coin);
    gap: 5px;
}

.product-rewards {
    flex: 2;
}

.product-grid .product-rewards {
    width: 100%;
    font-size: 1rem;
}

.product-details-section .product-rewards .entries,
.product-details-section .product-rewards .tokens {
    display: flex;
    align-items: center;
    gap: 5px;
}

/* The icon, the count and the word each get a space - the markup runs them together. */
.product-grid .product-rewards .entries {
    display: flex;
    align-items: center;
    gap: 5px;
    text-align: left;
    padding-left: 5px;
}

.product-grid .product-rewards .tokens {
    padding: 0 5px;
}

.container .points {
    /* Balances are the secondary colour everywhere - see ThemeTokens.Coin. */
    color: var(--wx-coin);
    font-weight: bold;
}

/* ---- cart -------------------------------------------------------------- */

.cart-items {
    max-height: 525px;
    overflow-y: auto;
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    background-color: var(--wx-surface);
}

.cart-item {
    padding: 10px 0;
    display: flex;
    align-items: stretch;
    justify-content: space-between;
}

.cart-item-border {
    border-bottom: 1px solid var(--wx-line);
}

.cart-item-image {
    max-width: 250px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex: 1;
    text-align: center;
}

.cart-item-image img {
    width: 125px;
    height: 125px;
    object-fit: cover;
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
}

.cart-item-actions {
    padding-top: 10px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 10px;
}

/* Points and entries in the secondary colour, like every other balance; the plus
   between two prices is just punctuation. */
.product-rewards .entries .fas,
.product-purchase .points .fas { color: var(--wx-coin); }
.product-purchase .plus .fas { color: var(--wx-muted); }

.cart-item-details {
    display: flex;
    max-width: 400px;
    flex-direction: column;
    justify-content: flex-start;
    flex: 2;
    gap: 5px;
    padding: 5px 0;
}

.cart-item-details h5 {
    margin: 0;
    font-size: 1rem;
    font-weight: bold;
    line-height: 1.2;
}

.cart-item-details p {
    margin: 0;
    font-size: 0.9rem;
    line-height: 1.4;
    color: var(--wx-muted);
}

.cart-item-pricing {
    padding-right: 25px;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    flex: 1;
    text-align: right;
    gap: 10px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cart-item-pricing p {
    margin: 0;
    font-size: 0.9rem;
    line-height: 1.2;
}

.empty-cart {
    text-align: center;
    color: var(--wx-muted);
}

.cart-edit-button {
    min-width: 250px;
}

.subtotal-container {
    display: flex;
    justify-content: flex-end;
}

.pricing-content {
    margin-top: auto;
}

.cart-footer {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    width: 100%;
}

.cart-footer-edit {
    padding-top: 10px;
    flex: 0 0 200px;
    display: flex;
    justify-content: center;
    align-items: flex-start;
}

.cart-footer-rewards {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    text-align: left;
    margin: 0;
}

.cart-footer-rewards .product-rewards {
    padding-top: 20px;
    display: flex;
    align-items: center;
    gap: 5px;
    color: var(--wx-coin);
    font-weight: bold;
}

.cart-footer-rewards .product-rewards .entries {
    padding-left: 50px;
}

.cart-footer-rewards .product-rewards .tokens {
    padding-left: 25px;
}

.cart-footer-total {
    flex: 0 0 250px;
    text-align: right;
    display: flex;
    flex-direction: column;
    white-space: nowrap;
    margin-top: auto;
    padding-right: 10px;
}

.order-note {
    flex: 1;
}

.order-note textarea {
    width: 100%;
    background: var(--wx-surface);
    color: var(--wx-ink);
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    font-family: var(--wx-font-body);
    padding: 8px;
}

.cart-summary {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 10px;
}

.cart-actions button {
    margin-top: 15px;
    margin-left: 10px;
}

/* ---- checkout ---------------------------------------------------------- */

.payment-cart-footer {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    width: 100%;
    padding: 0 12px;
}

.payment-cart-footer-edit-delivery {
    padding-top: 10px;
    flex: 0 0 200px;
    display: flex;
    justify-content: center;
    align-items: flex-start;
}

.payment-cart-footer-edit-delivery button {
    width: 200px;
}

.payment-cart-footer-delivery-address {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    text-align: left;
    margin: 0;
    padding-left: 45px;
    line-height: 1.2;
}

.payment-cart-footer-total {
    flex: 0 0 250px;
    text-align: right;
    display: flex;
    flex-direction: column;
    padding-right: 10px;
}

/* An outline button: the payment methods are a choice, not the commit, so they
   do not take the brand fill that the confirm button gets. */
.payment-btn {
    flex: 1;
    min-width: 120px;
    background-color: var(--wx-surface);
    color: var(--wx-ink);
    border: 1px solid var(--wx-line);
    font-weight: bold;
    padding: 10px 15px;
    text-align: center;
    border-radius: var(--wx-radius);
    transition: all 0.2s ease-in-out;
}

.payment-btn:hover {
    color: var(--wx-ink);
    background-color: var(--wx-surface-2);
    border-color: var(--wx-signal);
    filter: none;
}

.payment-btn i {
    margin-right: 5px;
}

.subtotal {
    display: flex;
    flex-direction: column;
}

.subtotal-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
}

.subtotal-item h5 {
    margin: 0;
    text-align: right;
    font-size: 1rem;
}

.subtotal-title {
    text-align: left;
    font-size: 0.75rem;
}

.subtotal-amount {
    text-align: right;
    font-size: 0.75rem;
    font-weight: normal;
    font-family: var(--wx-font-data);
    font-variant-numeric: tabular-nums;
}

.subtotal-divider {
    border-top: 1px solid var(--wx-line);
    width: 250px;
    padding: 5px 25px 5px 0;
}

.subtotal .subtotal-item:last-child {
    font-size: 0.75rem;
    font-weight: bold;
}

/* ---- points slider ----------------------------------------------------- */

.slider-wrapper {
    padding: 25px 0 35px 10px;
    display: flex;
    align-items: center;
    flex-grow: 1;
    position: relative;
    width: 70%;
}

.slider-max-value {
    margin-left: 20px;
    font-size: 0.8rem;
    white-space: nowrap;
    cursor: pointer;
    font-weight: bold;
}

.slider-values {
    text-align: center;
    white-space: nowrap;
    padding-right: 10px;
    display: flex;
    justify-content: center;
    align-items: center;
    width: 30%;
    min-width: 250px;
    gap: 15px;
    margin-left: 20px;
}

/* The balance falling as the slider moves - a second, quieter line under the
   redeem figure, so the number being chosen stays the loud one. */
.slider-balance {
    display: block;
    font-size: 0.8rem;
    color: var(--wx-muted);
    margin-top: 3px;
}

.slider-balance strong {
    color: var(--wx-coin);
    font-family: var(--wx-font-data);
    font-variant-numeric: tabular-nums;
}


/* ---- option picker ----------------------------------------------------- */

/* Variant chips. Radios rather than a list box: one size, one colour. The
   input is hidden and the label is the chip, so the browser still gives us the
   group, arrow keys and focus. */
.wx-optionpick {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
}

.wx-optionpick label {
    display: inline-flex;
    align-items: center;
    padding: 6px 14px;
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    background: var(--wx-surface);
    color: var(--wx-ink);
    white-space: nowrap;
    cursor: pointer;
}

.wx-optionpick input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.wx-optionpick label:hover {
    border-color: var(--wx-muted-dim);
}

.wx-optionpick label.is-on {
    border-color: var(--wx-signal);
    background: var(--wx-signal);
    color: var(--wx-signal-ink);
}

.wx-optionpick label:has(input:focus-visible) {
    outline: 2px solid var(--wx-signal);
    outline-offset: 2px;
}

/* ---- spinner ----------------------------------------------------------- */

@keyframes rolling {
    0% { transform: translateY(-25px); }
    100% { transform: translateY(20px); }
}

.spinning i {
    animation: slide-down 0.5s ease-out, rolling 0.1s linear infinite;
}

.stopped i {
    animation: none;
}

@media (prefers-reduced-motion: reduce) {
    .spinning i {
        animation: none;
    }

    * {
        transition-duration: 0.01ms !important;
    }
}

/* ---- responsive -------------------------------------------------------- */

@media (max-width: 768px) {
    nav ul {
        flex-direction: column;
        gap: 10px;
    }

    header.site-header {
        flex-wrap: wrap;
    }

    header .container {
        flex-direction: column;
        align-items: center;
    }

    main {
        margin: 10px;
        padding: 15px;
        width: auto;
    }

    .slider-wrapper,
    .slider-values {
        width: 100%;
        min-width: 0;
    }

    .cart-footer,
    .payment-cart-footer {
        flex-wrap: wrap;
        gap: 10px;
    }
}

/* ============================================================================
   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 colour 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 colours 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; }

/* ---- 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;
    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;
    background: var(--wx-surface-2);
    display: grid;
    place-items: center;
    overflow: hidden;
}

.wx-tile-shot img { width: 100%; height: 100%; object-fit: cover; 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 neighbours'. */
.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; }

.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;
}

.wx-post-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    color: var(--wx-muted-dim);
    font-size: 0.74rem;
    font-family: var(--wx-font-data);
}

/* ---- 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; }

.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); }

.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 62px;
    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; }
}

/* ---- order confirmation ------------------------------------------------- */

.wx-thanks {
    background: var(--wx-surface);
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    padding: var(--wx-pad);
    display: grid;
    gap: 6px;
}

.wx-thanks h2 {
    margin: 0;
    font-size: 1.5rem;
    line-height: 1.15;
}

.wx-thanks p { margin: 0; color: var(--wx-muted); }

/* An order that looks paid but took no money should be impossible to miss. */
.wx-test-notice {
    margin-top: 6px !important;
    padding: 7px 11px;
    border-radius: var(--wx-radius);
    background: var(--wx-coin-soft);
    color: var(--wx-coin) !important;
    font-size: 0.84rem;
    font-weight: 700;
}

.wx-earned {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 10px;
}

.wx-earned-cell {
    display: grid;
    gap: 2px;
    padding: 13px 15px;
    background: var(--wx-surface);
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
}

/* The running balance is the quieter one - what was just earned is the news. */
.wx-earned-cell.is-balance { background: var(--wx-surface-2); }

.wx-earned-n {
    font-family: var(--wx-font-data);
    font-variant-numeric: tabular-nums;
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.05;
    color: var(--wx-coin);
}

.wx-earned-l {
    font-size: 0.74rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--wx-muted-dim);
}

.wx-earned-sub { font-size: 0.76rem; color: var(--wx-muted); }

/* The grand prize is the one the partner is promoting, so it reads first. */
.wx-gcard.is-grand { border-color: var(--wx-signal); }

.wx-receipt {
    display: grid;
    gap: 5px;
    background: var(--wx-surface);
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    padding: var(--wx-pad);
}

.wx-receipt-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 14px;
    font-size: 0.88rem;
    color: var(--wx-muted);
    min-width: 0;
}

.wx-receipt-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }

.wx-receipt-amt {
    flex: 0 0 auto;
    font-family: var(--wx-font-data);
    font-variant-numeric: tabular-nums;
}

.wx-receipt-row.is-total {
    color: var(--wx-ink);
    font-weight: 700;
    font-size: 1rem;
    padding-top: 4px;
}

.wx-thanks-actions {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    padding-top: 4px;
}

/* A failure placing the order sits with the button that caused it. */
.wx-order-error {
    margin: 0 0 8px;
    color: var(--wx-bad);
    font-size: 0.88rem;
    font-weight: 600;
}

/* Legal text at a reading width: a policy set across a monitor is 200 characters a
   line. The same column the official rules use (giveaways.css .wx-rules-page). */
.wx-reading {
    max-width: 760px;
    margin: 0 auto;
    padding: 10px;
}

/* The standing agreement, above both halves of a policy. Set apart so it reads as the
   sentence that matters rather than as the first paragraph of the document. Uses the
   theme's own tokens so it belongs to whichever partner is wearing it. */
.wx-policy-notice {
    margin: 0 0 16px;
    padding: 12px 14px;
    border-left: 3px solid var(--wx-signal, #888);
    background: var(--wx-surface, rgba(128, 128, 128, 0.08));
    color: var(--wx-ink, inherit);
    font-size: 0.95rem;
    line-height: 1.5;
}

/* Choosing a face on the storefront. The marks themselves come from the WinWrxUI
   stylesheet, so this is only the panel around them.

   A row: the face, then what you can do to it. Stacked it took the whole top of the
   profile page and pushed the form below the fold. */
.wx-avatar-panel {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    gap: 16px;
    padding: 16px;
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    background: var(--wx-surface);
}

/* min-width:0 is what lets the scroller inside actually scroll - without it this
   column grows to its content and the row overflows the panel instead. */
.wx-avatar-controls {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    gap: 10px;
    min-width: 0;
}

.wx-avatar-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

/* On a narrow screen the face goes back above the controls - side by side there leaves
   neither enough room. */
@media (max-width: 560px) {
    .wx-avatar-panel { flex-direction: column; }
}

/* The upload control is a label wrapping a file input and the other is a button, so
   they need telling to be the same shape. A shared width keeps them a pair rather than
   two controls that happen to sit together. */
.wx-avatar-btn {
    min-width: 10.5rem;
    margin-bottom: 0;
    text-align: center;
}

/* Shown when an address has no partner behind it. Deliberately plain: there is no
   partner, so there is no branding to wear. */
.wx-nohost {
    max-width: 34rem;
    margin: 4rem auto;
    padding: 0 1.5rem;
    text-align: center;
}

.wx-nohost h1 {
    font-size: 1.5rem;
    margin-bottom: .75rem;
}

/* ── The account menu ───────────────────────────────────────────────────────────

   Profile and Sign Out used to be two more words in the header row, which is most of what
   made it wrap. They hang off the customer icon now, which sits last in the row the way it
   does in the phone app.

   Built on <details>: this layout renders statically, so there is no circuit behind the
   header to run a click handler. The browser opens and closes it by itself, and it is
   keyboard-reachable without any help.

   Note for anyone adding to the header later - the storefront loads base.css, layouts.css
   and a theme, NOT wwwroot/css/partner.css. That file is not linked from anywhere. */

/* The cart: the app's bag, with the count as a badge that is there only when the cart
   has something in it. [hidden] is spelled out because the display rule would
   otherwise beat it, and wxHeader.setCartCount flips it without a reload. */
header nav ul li.cart-link a { display: inline-flex; align-items: center; gap: 5px; }
/* The bag only once there is something in it, as in the app: an empty bag leads to a
   disappointment. wxHeader.js keeps the badge's hidden in step with the cart; the cart
   page itself keeps its icon, lit. */
header nav ul li.cart-link:has(.cart-link-n[hidden]):not(:has(a.active)) { display: none; }
header nav ul li.cart-link .cart-link-n {
    min-width: 18px;
    padding: 2px 5px;
    border-radius: 9px;
    background: var(--wx-signal);
    color: var(--wx-signal-ink);
    font-size: 0.7rem;
    font-weight: 700;
    line-height: 1.2;
    text-align: center;
}
header nav ul li.cart-link a:hover .cart-link-n,
header nav ul li.cart-link a.active .cart-link-n { background: var(--wx-signal-ink); color: var(--wx-signal); }
header nav ul li.cart-link .cart-link-n[hidden] { display: none; }

header nav ul li.account-menu { position: relative; }
header nav ul li.account-menu details { position: relative; }

/* One icon, two behaviours. On a desktop it is the dropdown; on a phone it is a link to
   the account hub, the same screen the app's account tab draws. The layouts' own
   breakpoint (899px) decides which. */
header nav ul li.account-link a {
    display: block;
    padding: 5px 10px;
    border-radius: var(--wx-radius);
    color: var(--wx-ink);
    font-size: 1.3rem;
    line-height: 1;
}

header nav ul li.account-link a:hover { background: var(--wx-signal); color: var(--wx-signal-ink); }
header nav ul li.account-link a.active:not(:hover),
header nav ul li.account-menu details:not([open]) > summary.active:not(:hover) { color: var(--wx-signal); }

@media (min-width: 900px) { header nav ul li.account-link { display: none; } }
@media (max-width: 899px) { header nav ul li.account-menu { display: none; } }

header nav ul li.account-menu summary {
    /* display:block is what removes the disclosure triangle. list-style alone does not,
       and the two vendor rules below only cover half the browsers between them - so all
       three, because a stray ">" beside the icon survives for months. */
    display: block;
    list-style: none;
    cursor: pointer;

    padding: 5px 10px;
    border-radius: var(--wx-radius);
    color: var(--wx-ink);
    font-size: 1.3rem;
    line-height: 1;
}

header nav ul li.account-menu summary::-webkit-details-marker { display: none; }
header nav ul li.account-menu summary::marker { content: ""; }

header nav ul li.account-menu summary:hover,
header nav ul li.account-menu[open] summary,
header nav ul li.account-menu details[open] summary {
    background: var(--wx-signal);
    color: var(--wx-signal-ink);
}

/* Floats over the page rather than taking a place in the row. Without this the list is
   laid out inline like every other <ul> in this header, which is what pushed the header
   taller and put "My Profile" and "Sign Out" on a second line. */
header nav ul li.account-menu .account-menu-list {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 1200;

    display: block;
    min-width: 170px;
    margin: 0;
    padding: 6px;
    list-style: none;

    background: var(--wx-surface);
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.45);
    text-align: left;
}

header nav ul li.account-menu .account-menu-list li { display: block; }

header nav ul li.account-menu .account-menu-list a {
    display: block;
    padding: 9px 12px;
    white-space: nowrap;
    font-weight: 600;
}

/* ── The store's category rail ──────────────────────────────────────────────────

   The same shape the app carries across the top of its store, so the two surfaces are
   navigated the same way.

   On a phone it scrolls sideways: a dozen categories should cost one row, not four, and
   a thumb is already used to pushing a row along. On a wide screen there is nothing to
   push and nothing telling you there is more, so anything that does not fit would simply
   be invisible - Gift Cards and Membership sat off the right edge of a seven-category
   rail that way. Above the phone width it wraps instead. */

.store-rail {
    display: flex;
    gap: 8px;
    align-items: center;
    overflow-x: auto;
    scrollbar-width: none;
    padding: 14px 0 6px;
}

.store-rail::-webkit-scrollbar { display: none; }

@media (min-width: 768px) {
    .store-rail {
        flex-wrap: wrap;
        overflow-x: visible;
        row-gap: 10px;
    }
}

/* ---- a return, under the line it is about ------------------------------- */

.wx-return {
    margin: 2px 0 10px;
    padding: 10px 12px;
    border-left: 3px solid var(--wx-line);
    background: var(--wx-surface);
    font-size: 0.85rem;
    color: var(--wx-muted);
    display: grid;
    gap: 8px;
}

.wx-return strong { color: var(--wx-ink); }
.wx-return.is-waiting { border-left-color: var(--wx-warn); }
.wx-return.is-approved { border-left-color: var(--wx-good); }
.wx-return.is-declined { border-left-color: var(--wx-bad); }
.wx-return.is-done { border-left-color: var(--wx-signal); }
.wx-return-sub { display: block; font-size: 0.8rem; color: var(--wx-muted-dim); }

.wx-return-ask { margin: -4px 0 8px; }

.wx-linkbtn {
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--wx-signal);
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 3px;
}

.wx-return-label { font-weight: 600; color: var(--wx-ink); }

.wx-return-in {
    width: 100%;
    font: inherit;
    font-size: 0.9rem;
    color: var(--wx-ink);
    background: var(--wx-ground);
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    padding: 8px 10px;
}

.wx-return-in:focus { outline: 2px solid var(--wx-signal); outline-offset: 1px; }
textarea.wx-return-in { resize: vertical; }

.wx-return-actions { display: flex; gap: 10px; flex-wrap: wrap; }

.wx-return-flag {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 7px;
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--wx-signal-ink);
    background: var(--wx-warn);
    border-radius: var(--wx-radius);
}

/* ---- messages: the support thread ---------------------------------------- */

.wx-thread { display: grid; gap: 10px; margin: 0 0 16px; }
.wx-msg {
    max-width: 88%;
    padding: 10px 12px;
    border-left: 3px solid var(--wx-line);
    background: var(--wx-surface);
    font-size: 0.88rem;
    color: var(--wx-ink);
}
.wx-msg.is-me { justify-self: end; border-left: 0; border-right: 3px solid var(--wx-signal); }
.wx-msg-head { display: flex; gap: 10px; align-items: baseline; margin-bottom: 4px; font-size: 0.8rem; color: var(--wx-muted); }
.wx-msg-head b { color: var(--wx-ink); }
.wx-msg-body { white-space: pre-wrap; line-height: 1.5; }
.wx-receipt-name .sub { display: block; font-size: 0.78rem; color: var(--wx-muted-dim); }

.wx-msg-pics { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.wx-msg-pics img { width: 110px; height: 110px; object-fit: cover; border: 1px solid var(--wx-line); display: block; }

/* 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); }

/* ---- gift cards --------------------------------------------------------------
   Lifted out of a style tag inside GiftCards.razor. In the markup it could not reach
   the partner's theme and nothing could override it, so the one page in the store
   reached from the rail was also the one that looked like somebody else's site.

   Sized and spaced like the store grid around it: the same surface, the same line, the
   same radius, and the buttons built from .store-rail-item's own shape so a row of
   amounts reads as the same furniture as a row of categories. */
.gift-page {
    max-width: 640px;
    margin: 0 auto;
    padding: 18px 16px 48px;
    display: grid;
    gap: 18px;
}

.gift-title {
    margin: 0;
    font-family: var(--wx-font-display, inherit);
    font-size: 1.6rem;
    letter-spacing: .01em;
}

.gift-lede { margin: 0; opacity: .8; line-height: 1.5; }

.gift-amounts { display: flex; flex-wrap: wrap; gap: 10px; }

.gift-amount {
    padding: 12px 20px;
    border: 1px solid var(--wx-line, #d2dadf);
    border-radius: 10px;
    background: var(--wx-surface, #fff);
    color: inherit;
    font: inherit;
    font-weight: 700;
    cursor: pointer;
    transition: border-color .12s ease;
}

.gift-amount:hover { border-color: var(--wx-signal, #e5841e); }

.gift-amount.is-selected {
    border-color: var(--wx-signal, #e5841e);
    box-shadow: inset 0 0 0 1px var(--wx-signal, #e5841e);
}

.gift-amount { display: grid; gap: 2px; justify-items: center; }
.gift-amount-price { font-size: 0.85rem; font-weight: 600; color: var(--wx-signal, #e5841e); }
.gift-amount-earn { font-size: 0.75rem; opacity: .75; }

.gift-label { display: grid; gap: 6px; font-weight: 600; }

.gift-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 4px; }

/* ---- get the app ------------------------------------------------------- */

/* The strip in the footer and the card on the account page - see GetTheApp.razor. Both
   point at the one smart link; the QR carries the partner code. On a phone the QR is
   useless (it is the phone you would scan with) and the badges are the whole point, so
   the QR goes and the badges stay. */
.wx-getapp {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    text-align: left;
}

.wx-getapp.is-strip {
    max-width: var(--wx-shell);
    margin: 0 auto 16px;
    padding: 16px 20px;
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    background: var(--wx-surface);
}

.wx-getapp.is-card {
    margin: 16px 0 0;
    padding: 18px 16px;
    border: 1px solid var(--wx-line);
    border-radius: var(--wx-radius);
    background: var(--wx-surface);
}

.wx-getapp-words { flex: 1; min-width: 0; }

.wx-getapp-words h3 {
    margin: 0 0 4px;
    font-family: var(--wx-font-display, inherit);
    font-size: 1.05rem;
}

.wx-getapp-words p {
    margin: 0 0 10px;
    color: var(--wx-muted);
    font-size: 0.9rem;
}

.wx-getapp-badges { display: flex; gap: 10px; flex-wrap: wrap; }

.wx-getapp-badge {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 8px 14px;
    border: 1px solid var(--wx-line);
    border-radius: 10px;
    background: #000;
    color: #fff;
    text-decoration: none;
    line-height: 1.1;
    font-weight: 700;
}

.wx-getapp-badge i { font-size: 1.4rem; }

.wx-getapp-badge small {
    display: block;
    font-size: 0.6rem;
    font-weight: 400;
    color: #bbb;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.wx-getapp-badge:hover { border-color: var(--wx-signal); color: #fff; }

.wx-getapp-qr {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    color: var(--wx-muted);
    font-size: 0.75rem;
    text-decoration: none;
}

.wx-getapp-qr img {
    display: block;
    padding: 6px;
    background: #fff;
    border-radius: 10px;
}

@media (max-width: 899px) {
    .wx-getapp-qr { display: none; }
}

/* ---- phone: the app's title bar and tab bar ---------------------------------

   At phone widths the website wears the app's frame. The header becomes a slim title
   bar - logo, balances, cart, account - and the section links move to a tab bar fixed
   along the bottom with the app's icons in the app's order (see AppChrome and
   .chrome-tabs in WinWrxUI's streams.css). Last in the file so it wins over the older
   column-stacking rules above. */

.wx-tabbar { display: none; }

@media (max-width: 768px) {
    header {
        position: sticky;
        top: 0;
    }

    header .container {
        flex-direction: row;
        justify-content: space-between;
        align-items: center;
        gap: 8px;
        padding: 0 12px;
        padding-top: env(safe-area-inset-top);
    }

    header .logo img { max-height: 34px; }

    header nav {
        flex: 0 1 auto;
        min-width: 0;
        text-align: right;
    }

    header nav ul {
        flex-direction: row;
        align-items: center;
        gap: 4px;
    }

    header nav ul li.nav-section { display: none; }

    /* An item's picture above its details, not squeezed beside them - both columns
       are flex: 1, which beat Bootstrap's widths and kept them on one line. */
    .product-image-gallery,
    .product-details-section {
        flex: 1 1 100%;
        max-width: 100%;
    }

    header nav ul li a { padding: 5px 8px; }

    header nav ul li.points {
        white-space: nowrap;
        font-size: 0.9rem;
        font-weight: 600;
    }

    .balance-label { display: none; }

    /* Room at the foot of every page for the bar, and for the home indicator under it. */
    body { padding-bottom: calc(56px + env(safe-area-inset-bottom)); }

    .wx-tabbar {
        display: grid;
        grid-auto-flow: column;
        grid-auto-columns: 1fr;
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 1000;
        background: var(--wx-surface);
        border-top: 1px solid var(--wx-line);
        padding-bottom: env(safe-area-inset-bottom);
    }

    .wx-tab {
        display: flex;
        align-items: center;
        justify-content: center;
        /* 52px clears the usual minimum touch target on a small phone. */
        min-height: 52px;
        color: var(--wx-ink);
        font-size: 1.2rem;
        text-decoration: none;
    }

    .wx-tab.active { color: var(--wx-signal); }
}

/* Printing a receipt: the receipt, not the site around it. */
@media print {
    header,
    footer,
    nav.wx-tabbar,
    .wx-nav,
    .wx-thanks-actions,
    .return-form {
        display: none !important;
    }

    body { padding: 0 !important; background: #fff !important; }
    main { margin: 0 !important; box-shadow: none !important; }
}

