﻿/* Streams feed + app chrome. Mobile-first, like slots.css: the phone layout is the
   default and wider screens adjust, because the app is the primary target.

   Colours come from the partner's theme. This file paints the shell every screen sits
   in - the title bar, the body, the tab bar - so while it hardcoded a dark palette a
   partner on a light theme got white store cards inside a black frame. Each fallback is
   the value that was here before, so a surface with no theme loaded looks unchanged. */

/* ---------- app chrome ---------- */

.chrome {
    /* dvh, not vh: mobile browsers change the viewport as their toolbars hide, and vh
       leaves the tab bar floating above the fold when they do. */
    height: 100dvh;
    display: flex;
    flex-direction: column;
    background: var(--wx-ground, #111);
    color: var(--wx-ink, #fff);
    overflow: hidden;
}

.chrome-top {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 10px 14px;
    background: var(--wx-surface, #1b1b1b);
    border-bottom: 1px solid var(--wx-line, #2c2c2c);
    /* Keeps the title clear of a notch / the device status bar. */
    padding-top: max(10px, env(safe-area-inset-top));
}

.chrome-partner {
    font-weight: 700;
    font-size: 1rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.chrome-balances {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.9rem;
    font-weight: 600;
    white-space: nowrap;
}

.chrome-balances i {
    color: var(--wx-coin, goldenrod);
}

/* min-height:0 lets this flex child actually shrink, which is what allows the feed
   inside it to own the scrolling instead of the whole page growing.

   overflow-y:auto lets each screen decide how it scrolls, rather than forcing one answer.
   The feed sets min-height:0 on itself, so it is capped at this height and scrolls in its
   own .feed-scroll - nothing overflows here and this scroller stays idle. The game keeps
   the default min-height:auto, so it stays its natural height and scrolls here instead.
   Without this the game was simply clipped: measured at 956px tall in a 751px shell, with
   the bottom of the payout key unreachable. */
.chrome-body {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-y: contain;
}

/* Account, in the title bar. Tucked against the right edge, and deliberately quieter
   than the tab bar - it is somewhere you go occasionally, not somewhere you move
   between. */
.chrome-account {
    appearance: none;
    background: none;
    border: 0;
    /* A 44px target round a 22px glyph, pulled back by the margin so the icon sits
       where it did. A bare glyph was easy to miss with a thumb. */
    display: inline-grid;
    place-items: center;
    min-width: 44px;
    min-height: 44px;
    margin: -10px -12px -10px -8px;
    padding: 0;
    color: var(--wx-muted, #cfcfcf);
    font-size: 1.35rem;
    line-height: 1;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.chrome-account.is-active {
    color: var(--wx-signal, #e5841e);
}

/* The cart, beside it, the same weight: the bag and a small count, no button around
   them. Only drawn when there is something in it - see AppChrome. */
.chrome-cart {
    appearance: none;
    background: none;
    border: 0;
    padding: 0 6px 0 4px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: var(--wx-muted, #cfcfcf);
    font-size: 1.2rem;
    line-height: 1;
    cursor: pointer;
}

.chrome-cart.is-active {
    color: var(--wx-signal, #e5841e);
}

.chrome-cart-n {
    min-width: 18px;
    padding: 2px 5px;
    border-radius: 9px;
    background: var(--wx-signal, #e5841e);
    color: var(--wx-signal-ink, #111);
    font-family: var(--wx-font-data, ui-monospace, Consolas, monospace);
    font-size: 0.7rem;
    font-weight: 700;
    text-align: center;
}

/* The balances sit between the name and the account button, so the name takes what is
   left rather than pushing them off the edge. */
.chrome-top .chrome-partner {
    flex: 1 1 auto;
    min-width: 0;
}

/* Columns from the number of tabs, not a fixed five: the bar has already been four
   and six while the screens were being decided. */
.chrome-tabs {
    flex: 0 0 auto;
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    background: var(--wx-surface, #1b1b1b);
    border-top: 1px solid var(--wx-line, #2c2c2c);
    padding-bottom: env(safe-area-inset-bottom);
}

.chrome-tab {
    appearance: none;
    background: none;
    border: 0;
    color: var(--wx-ink, #fff);
    /* 48px clears the usual minimum touch target even on small phones. */
    min-height: 48px;
    font-size: 1.15rem;
    cursor: pointer;
}

.chrome-tab.is-active {
    color: var(--wx-signal, #e5841e);
}

/* ---------- feed ---------- */

.feed {
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1 1 auto;
    background: var(--wx-ground, #111);
}

.feed-rail {
    flex: 0 0 auto;
    display: flex;
    gap: 10px;
    padding: 10px 14px;
    overflow-x: auto;
    background: var(--wx-surface, #161616);
    border-bottom: 1px solid var(--wx-line, #2c2c2c);
    /* Sides match the posts below it, so the rail and the cards share a left edge. */
    /* Hidden because a phone swipes it. With a mouse there is nothing to swipe, so
       rails.js makes it draggable - hence the cursor. */
    scrollbar-width: none;
    cursor: grab;
}

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

.feed-rail-item {
    flex: 0 0 auto;
    width: 52px;
    height: 52px;
    padding: 0;
    border-radius: 50%;
    border: 2px solid transparent;
    background: var(--wx-surface-2, #262626);
    color: var(--wx-muted, #ddd);
    overflow: hidden;
    cursor: pointer;
}

.feed-rail-item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.feed-rail-item.is-selected {
    border-color: var(--wx-signal, #e5841e);
}

.feed-rail-all {
    font-size: 0.8rem;
    font-weight: 700;
}

/* The one scrolling element. -webkit-overflow-scrolling keeps momentum scrolling on
   iOS WebViews, which is most of what makes a feed feel native rather than webby. */
.feed-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-y: contain;
}

.feed-post {
    padding: 14px 14px 16px;
    border-bottom: 8px solid var(--wx-ground-deep, #0b0b0b);
    /* Isolates each card's layout/paint from the rest of the list, so a long feed stays
       cheap to scroll. contain-intrinsic-size gives unrendered cards a plausible height
       so the scrollbar doesn't jump around as they come into view. */
    content-visibility: auto;
    contain-intrinsic-size: auto 420px;
}

.feed-post-head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
}

.feed-post-avatar {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    object-fit: cover;
    flex: 0 0 auto;
    background: var(--wx-surface-2, #262626);
}

.feed-post-headtext {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.feed-post-stream {
    font-size: 0.85rem;
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.feed-post-date {
    font-size: 0.75rem;
    color: var(--wx-muted-dim, #8f8f8f);
}

.feed-post-title {
    margin: 0 0 10px;
    font-size: 1rem;
    line-height: 1.3;
    font-weight: 600;
}

/* Fixed aspect box: the slot is the right size before the image loads, so arriving
   images can't shove the rest of the feed down mid-scroll. */
.feed-post-media {
    aspect-ratio: 16 / 9;
    background: var(--wx-surface-2, #1d1d1d);
    border-radius: 10px;
    overflow: hidden;
    margin-bottom: 10px;
}

.feed-post-media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.feed-post-text {
    margin: 0 0 10px;
    font-size: 0.9rem;
    line-height: 1.45;
    color: var(--wx-muted, #c9c9c9);
    /* Long syndicated descriptions would otherwise dominate the card. */
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* On the post's own screen the description is what you came to read, so all of
   it. Syndicated text arrives flattened to one paragraph (see ToPlainText), so
   there are no line breaks to keep - just no ceiling. */
.feed-post-text.is-expanded {
    display: block;
    -webkit-line-clamp: unset;
    overflow: visible;
}

.feed-post-meta {
    display: flex;
    gap: 18px;
    font-size: 0.8rem;
    color: var(--wx-muted-dim, #9a9a9a);
}

.feed-post-meta i {
    margin-left: 4px;
}

.feed-post-comment {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin-top: 10px;
    padding: 8px 10px;
    background: var(--wx-surface, #1a1a1a);
    border-radius: 8px;
    font-size: 0.82rem;
}

/* Smaller than the thread's: a teaser, not the comment itself. */
.feed-post-comment-face {
    position: relative;
    flex: 0 0 auto;
    width: 24px;
    height: 24px;
}

.feed-post-comment-face .wx-avatar.is-sm { width: 24px; height: 24px; }
.feed-post-comment-face .post-comment-face-badge { width: 13px; height: 13px; font-size: 7px; left: -3px; bottom: -3px; }

.feed-post-comment-body {
    flex: 1 1 auto;
    min-width: 0;
}

.feed-post-comment-author {
    font-weight: 700;
    margin-right: 6px;
}

.feed-post-comment-text {
    color: var(--wx-muted, #bdbdbd);
}

.wx-btn.feed-more {
    display: flex;
    width: calc(100% - 28px);
    margin: var(--wx-s4) 14px var(--wx-s5);
}

/* ---------- wider screens ---------- */

@media (min-width: 820px) {
    .feed-post {
        max-width: 640px;
        margin: 0 auto;
        border-bottom-width: 1px;
        border-bottom-color: var(--wx-line, #262626);
    }

    /* Left, not centred. A centred rail floats away from the left edge everything
       below it lines up on, and reads as a separate ornament rather than as the
       control for the list underneath. */
}

.feed-rail.is-dragging {
    cursor: grabbing;
    user-select: none;
}
.feed-rail.is-dragging img { pointer-events: none; }

.feed-rail img {
    /* See home.css: the native image drag has to be off before a press turns
       into a scroll, not after. */
    -webkit-user-drag: none;
    user-select: none;
}

/* ---------- one post, with its comments ---------- */

.post {
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1 1 auto;
    background: var(--wx-ground, #111);
}

.post-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-y: contain;
}

/* Quiet, and out of the way of the post itself - it is how you leave, not what you
   came for. */
/* The shared button, as wide as the page's text, with the note under it centred to
   match. An anchor rather than a button so the website's new tab still works. */
.post-source {
    display: flex;
    margin: 0 14px 8px;
    text-decoration: none;
}

.post-source-wrap .post-source-note {
    text-align: center;
}

.post-comments {
    padding: 4px 14px 24px;
    border-top: 8px solid var(--wx-ground-deep, #0b0b0b);
    margin-top: 8px;
}

.post-comments-head {
    margin: 12px 0 10px;
    font-size: 0.95rem;
    font-weight: 700;
}

.post-comments-none {
    margin: 0;
    color: var(--wx-muted-dim, #9a9a9a);
    font-size: 0.9rem;
}

.post-comment {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 0;
    border-bottom: 1px solid var(--wx-line-soft, #1f1f1f);
}

/* The face's own column. Fixed width so comments with and without one line up. */
.post-comment-face {
    position: relative;
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    margin-top: 1px;
}

/* The star on a member's face: tucked onto the ring at the bottom-right, sized so it
   reads as a badge on the face rather than a second icon beside it. Its own ground
   in the page colour so it stands off a photograph. */
.post-comment-face-badge {
    position: absolute;
    left: -4px;
    bottom: -4px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--wx-signal, #e5841e);
    color: var(--wx-signal-ink, #111);
    font-size: 8px;
    line-height: 1;
    box-shadow: 0 0 0 2px var(--wx-ground, #111);
}

.post-comment-body {
    flex: 1 1 auto;
    min-width: 0;
}

.post-comment:last-child { border-bottom: 0; }

.post-comment-head {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 4px;
}

.post-comment-author {
    font-size: 0.85rem;
    font-weight: 700;
}

.post-comment-date {
    font-size: 0.75rem;
    color: var(--wx-muted-dim, #8f8f8f);
}

.post-comment-text {
    margin: 0;
    font-size: 0.9rem;
    line-height: 1.45;
    color: var(--wx-muted, #c9c9c9);
}

/* Like on the left, report on the right, and the whole row between them. The two are
   different kinds of tap - one is idle, one cannot be undone - so they get the width
   of the comment between them rather than sitting a thumb apart. */
.post-comment-meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 6px;
    font-size: 0.8rem;
    color: var(--wx-muted-dim, #9a9a9a);
}

@media (min-width: 820px) {
    .post-main, .post-comments { max-width: 640px; margin-inline: auto; width: 100%; }
}

/* The card is the tap target itself now (see StreamPostCard's OnOpen) rather than
   something wrapped in its own button - .feed-post already has real padding and needs
   no chrome reset, only the two rules an interactive region needs. */
.feed-post.is-open {
    cursor: pointer;
}

.feed-post.is-open:focus-visible {
    outline: 2px solid var(--wx-signal, #e5841e);
    outline-offset: -2px;
}

.feed-post-badges {
    display: flex;
    gap: 6px;
    margin-bottom: 6px;
}

/* The heart in .feed-post-meta, made a real button. Font/color reset because it sits
   beside two plain <span>s and has to read as one more of them, not a form control. */
.feed-post-like {
    appearance: none;
    border: 0;
    background: none;
    padding: 0;
    margin: 0;
    font: inherit;
    font-size: 0.8rem;
    color: var(--wx-muted-dim, #9a9a9a);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    /* Flex drops the space the markup has between the heart and the count. */
    gap: 5px;
}

/* The heart comes first here, so the meta row's margin for a trailing icon isn't wanted. */
.feed-post-like i {
    margin-left: 0;
}

.feed-post-like.is-liked {
    color: var(--wx-signal, #e5841e);
}

.feed-post-like:disabled {
    opacity: 0.6;
    cursor: default;
}

.post-comment-like {
    appearance: none;
    border: 0;
    background: none;
    padding: 0;
    font: inherit;
    font-size: 0.8rem;
    color: var(--wx-muted-dim, #9a9a9a);
    cursor: pointer;
}

.post-comment-like.is-liked {
    color: var(--wx-signal, #e5841e);
}

.post-comment-like:disabled {
    opacity: 0.6;
    cursor: default;
}

/* The handle box: the @ is part of the field's chrome, not something they type. */
.post-composer-handle {
    display: flex;
    align-items: center;
    gap: 0;
}

.post-composer-at {
    flex: 0 0 auto;
    padding: 0 6px 0 2px;
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--wx-muted-dim, #9a9a9a);
}

.post-composer-handle .wx-input {
    flex: 1 1 auto;
    min-width: 0;
}

/* Composer: the handle prompt and the comment box share this shell, so picking a name
   and leaving a comment read as the same kind of moment rather than two different UIs. */
.post-composer {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin: 4px 0 16px;
    padding: 14px;
}

.post-composer-prompt {
    margin: 0;
    font-size: 0.9rem;
    font-weight: 600;
}

.post-composer-actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

.post-composer-count {
    font-size: 0.78rem;
    color: var(--wx-muted-dim, #9a9a9a);
}

/* A reviewer's note to the viewer, over the box it is about. Not an error and not a
   toast: it stays until they say they have read it. */
.post-notice {
    display: grid;
    gap: 6px;
    margin: 0 0 12px;
    padding: 12px 14px;
    border-left: 3px solid var(--wx-signal, #e5841e);
    border-radius: 8px;
    background: var(--wx-surface, #1a1a1a);
    font-size: 0.9rem;
    line-height: 1.45;
}

.post-notice p { margin: 0; overflow-wrap: anywhere; white-space: pre-wrap; }

.post-notice-link {
    justify-self: start;
    font-size: 0.85rem;
    color: var(--wx-signal, #e5841e);
    text-decoration: none;
}

.post-notice-link:hover { text-decoration: underline; }

.post-notice-ok { justify-self: start; }

.post-note {
    margin: 4px 0 16px;
    font-size: 0.9rem;
    color: var(--wx-muted, #cfcfcf);
}

/* ---- reporting ---------------------------------------------------------- */

/* Quieter than the like beside it. Reporting is rare and cannot be undone, so it
   should be findable rather than inviting - a control as loud as the like button
   collects idle taps on the one thing nobody can take back. */
.post-comment-report {
    appearance: none;
    border: 0;
    background: none;
    padding: 0;
    margin-left: auto;
    font: inherit;
    font-size: 0.75rem;
    color: var(--wx-muted-dim, #9a9a9a);
    opacity: 0.75;
    cursor: pointer;
}

.post-comment-report:hover { opacity: 1; }

.post-comment-report:disabled {
    opacity: 0.5;
    cursor: default;
}

/* Delete's second tap, in the same quiet register as the control itself. */
.post-comment-delete-confirm {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    font-size: 0.75rem;
    color: var(--wx-muted, #b9b9b9);
}

.post-comment-delete-confirm .post-comment-report { margin-left: 0; }

.post-comment-report.is-confirm { color: var(--wx-bad, #e5484d); opacity: 1; }

.post-note.is-error { color: var(--wx-bad, #e5484d); }

/* A face that opens the person. Looks exactly like the face that does not - the
   affordance is the tap, and a ring or a shadow on every avatar in a thread would be
   noise - so the button chrome goes and only the focus state announces itself. */
.post-comment-face.is-person {
    display: block;
    appearance: none;
    border: 0;
    background: none;
    padding: 0;
    margin: 0;
    font: inherit;
    color: inherit;
    cursor: pointer;
}

.post-comment-face.is-person:focus-visible {
    outline: 2px solid var(--wx-signal, #6cc);
    outline-offset: 2px;
    border-radius: 50%;
}

/* The person's card - see ProfileSheet. Same sheet as a report, laid out around a
   face rather than a form. */
.profile-sheet { align-items: center; text-align: center; }

.profile-face { display: flex; justify-content: center; }

.profile-who { display: flex; flex-direction: column; align-items: center; gap: 0.2rem; }

.profile-member {
    font-size: 0.72rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--wx-signal, #6cc);
}

.profile-place {
    font-size: 0.85rem;
    color: var(--wx-muted, #b9b9b9);
}

.profile-sheet .wx-sheet-actions { width: 100%; }

@media (min-width: 40rem) {
    /* Centred once there is room, rather than clinging to the bottom edge of a
       desktop window where it reads as a phone control that got lost. */
    
}

.report-title { margin: 0; font-size: 1.05rem; }

/* What is being reported, quoted back. The whole point is that nobody reports the
   comment above the one they meant. */
.report-subject {
    padding: 0.6rem 0.7rem;
    border-radius: 0.5rem;
    background: var(--wx-surface-2, #202126);
}

.report-quote {
    margin: 0;
    font-size: 0.9rem;
    line-height: 1.45;

    /* A long comment must not push the buttons off the screen. */
    max-height: 7rem;
    overflow-y: auto;

    /* Somebody else's words, so they wrap wherever they have to rather than
       stretching the sheet. */
    overflow-wrap: anywhere;
}

.report-person {
    display: flex;
    align-items: center;
    gap: 0.7rem;
}

.report-person-who {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    font-size: 0.95rem;
}

.report-person + .report-quote { margin-top: 0.6rem; }

.report-byline {
    display: block;
    margin-top: 0.35rem;
    font-size: 0.78rem;
    color: var(--wx-muted-dim, #9a9a9a);
}

.report-image {
    display: block;
    max-width: 100%;
    max-height: 12rem;
    margin: 0 auto;
    border-radius: 0.5rem;
}

.report-warning {
    margin: 0;
    font-size: 0.78rem;
    line-height: 1.45;
    color: var(--wx-muted, #b9b9b9);
}

.report-error {
    margin: 0;
    font-size: 0.82rem;
    color: var(--wx-bad, #e5643e);
}

.report-sent { margin: 0; font-size: 0.9rem; }

/* ---------- the post's source: the player in the page, or the trip out and back ---------- */

/* The card's media box holding a player rather than a picture. */
.feed-post-media.is-player { background: #000; }
.feed-post-media.is-player iframe { width: 100%; height: 100%; border: 0; display: block; }

.post-source-wrap { margin: 0 0 6px; }
.post-main { display: flex; flex-direction: column; min-width: 0; }

.post-source-note {
    margin: 0 14px 6px;
    font-size: 0.8rem;
    color: var(--wx-muted-dim, #6b6863);
}

.post-returned {
    margin: 0 14px 8px;
    padding: 8px 12px;
    border-left: 3px solid var(--wx-signal, #e5841e);
    background: var(--wx-surface, #1b1b1d);
    color: var(--wx-ink, #fff);
    font-size: 0.9rem;
    font-weight: 600;
    animation: post-returned-in 240ms ease-out;
}

@keyframes post-returned-in {
    from { opacity: 0; transform: translateY(-4px); }
    to { opacity: 1; transform: none; }
}

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

/* Back / Previous / Next along the top of an open post. */
/* Inset to the card's own padding, so the way back lines up with the title under it
   rather than hanging off the edge. The card brings 14px of its own above the title;
   the negative margin takes that down to the 10px above the row, so the row sits
   evenly between the top of the page and the post. */
.post-nav {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 10px 14px 0;
    margin-bottom: -4px;
}

.post-nav-spacer { flex: 1; }

/* On the post page the picture goes where the post points, and so do the last
   few words of the text - dressed as the words around them. */
.feed-post-media.is-link { display: block; cursor: pointer; }
/* Every state spelled out: the partner's own stylesheet styles a:hover and
   a:focus, and this must not change at all - the pointer is the only tell. */
.feed-post-tail,
.feed-post-tail:hover,
.feed-post-tail:focus,
.feed-post-tail:active,
.feed-post-tail:visited {
    color: inherit;
    text-decoration: none;
    cursor: pointer;
    transition: none;
    outline: none;
}

/* A pinned comment: held at the top, marked with a tack. */
.post-comment.is-pinned { border-left: 3px solid var(--wx-signal, #e5841e); }
.post-comment-pin { color: var(--wx-signal, #e5841e); font-size: 0.8rem; margin-right: 6px; }
/* Sits after the name, where the pin sits before it - quiet on purpose. A badge that
   shouted would read as a claim about the person rather than a mark on the account. */

.post-comment-face-badge.is-patron { background: var(--wx-patron, #8b5cf6); color: #fff; }
.profile-member.is-patron { color: var(--wx-patron, #8b5cf6); }

/* ---------- wide: a browser window, from 900px ----------

   The one place the feed changes shape for a desktop (StreamsFeed Wide, set only by the
   website). The page scrolls as a whole rather than the feed inside a box; the cards go
   two across, three from 1200px; one post sits beside its conversation. */
@media (min-width: 900px) {
    /* The page's own frame is the one frame: no second, darker panel inside it. */
    .feed.is-wide,
    .post.is-wide { background: none; }

    .feed.is-wide,
    .feed.is-wide .feed-scroll,
    .post.is-wide,
    .post.is-wide .post-scroll { overflow: visible; flex: none; min-height: 0; height: auto; }

    .feed.is-wide .feed-scroll {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 0 18px;
        align-content: start;
    }

    /* A sentence or a button, not a card - across the whole width. */
    .feed.is-wide .feed-scroll > .wx-empty,
    .feed.is-wide .feed-scroll > .wx-loading,
    .feed.is-wide .feed-scroll > .feed-more { grid-column: 1 / -1; }

    .feed.is-wide .feed-post { max-width: none; margin: 0; }

    /* One post: the post on the left, the conversation on the right with the box to
       write in at its top. The comments keep their own scroll so a long thread never
       pushes the post off the top. */
    .post.is-wide .post-scroll {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(360px, 440px);
        gap: 0 28px;
        align-items: start;
        padding: 0 12px;
    }

    .post.is-wide .post-main,
    .post.is-wide .post-comments { max-width: none; margin-inline: 0; }

    .post.is-wide .post-main .feed-post { max-width: none; margin: 0; }

    .post.is-wide .post-comments {
        position: sticky;
        top: 0;
        max-height: calc(100vh - 190px);
        overflow-y: auto;
        border-top: 0;
        border-left: 1px solid var(--wx-line, #2c2c2c);
        margin-top: 12px;
        padding: 4px 0 24px 22px;
    }
}

@media (min-width: 1200px) {
    .feed.is-wide .feed-scroll { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
