﻿/* 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.

   Colors 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. */
/* Never -webkit-overflow-scrolling: touch, here or anywhere inside the app. iPhones have
   had momentum scrolling without it since iOS 13, and it clips everything position: fixed
   inside it to this box: an ad lost its top and bottom to the title bar and tab bar, with
   no way to close it (2026-11-04). */
.chrome-body {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    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. */
.feed-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    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);
}

/* The price on a post that is selling something. Loud enough to be the second thing
   read after the name, and in the partner's own signal color - the one the theme
   uses for the things it wants looked at - so it reads as an offer rather than as more
   of the description. */
.feed-post-price {
    margin: 2px 0 0;
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--wx-signal);
}

.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;
}

/* On the website the title, the stream's name and the rail are links a search engine
   follows (2026-11-01) - drawn exactly as the text and buttons they were. */
.feed-post-title a,
a.feed-post-stream,
a.feed-rail-item {
    color: inherit;
    text-decoration: none;
}

/* A button centers what's in it and a link doesn't - the initials in a rail circle sat
   in its corner. And the site's own a:hover / a:focus (partner base.css) underlined and
   recolored the links that were buttons; they keep the buttons' looks. */
a.feed-rail-item {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

a.feed-more,
a.feed-more:hover,
a.feed-more:focus,
a.post-step,
a.post-step:hover,
a.post-step:focus {
    color: var(--wx-ink, #fff);
    text-decoration: none;
}

a.wx-back,
a.wx-back:hover,
a.wx-back:focus {
    color: var(--wx-signal, #d4af37);
    text-decoration: none;
}

/* 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;
}

/* A thing for sale, where the photo is the subject rather than a crop of a scene.
   Square, because a product shot almost always is - a Printful mockup certainly is -
   and contained rather than covering, so a tall bottle or a wide board is shown whole
   instead of having its ends cut off. The padding keeps it off the corners so the
   letterboxing reads as a frame rather than a mistake. */
.feed-post-media.is-item {
    aspect-ratio: 1 / 1;
    padding: 8px;
    box-sizing: border-box;
}

.feed-post-media.is-item img {
    object-fit: contain;
    border-radius: 6px;
}

/* A podcast episode. Its artwork is square - a show's cover - and a 16:9 crop cuts
   the title off it, so it is shown whole in the middle of the box (2026-10-12). */
.feed-post-media.is-audio { position: relative; }
.feed-post-media.is-audio img { object-fit: contain; }

/* "Play · 42 min" in the artwork's corner. */
.feed-post-media { position: relative; }
.feed-post-play {
    position: absolute;
    left: 10px;
    bottom: 10px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 10px;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.72);
    color: #fff;
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1;
}
.feed-post-play i { font-size: 0.7rem; }

/* The episode's player on its own page, the width of the card. */
.feed-post-audio {
    display: block;
    width: 100%;
    margin: 0 0 14px;
}

.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, set for reading (2026-10-12): its paragraphs kept (ToParagraphs sends the
   breaks; the clamped card above ignores them), 17px on a 1.65 line, full-strength
   text rather than the card's muted gray, and no wider than about 70 characters a
   line - the comfortable span for long text; at the post column's full width it ran
   past 90. */
.feed-post-text.is-expanded {
    display: block;
    -webkit-line-clamp: unset;
    overflow: visible;
    white-space: pre-line;
    font-size: 1.0625rem;
    line-height: 1.65;
    color: var(--wx-ink, #ececec);
    max-width: 70ch;
}

.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 centered. A centered 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;
    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 centered 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 color 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-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) {
    /* Centered 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; }
/* A YouTube link the article's text carried, playing where it stood - set apart from
   the paragraphs around it by the same space they keep between themselves. */
.feed-post-media.is-inline { margin: 6px 0 20px; }

.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. Real space under the row, not the -4px it once
   had: that counted on 14px of empty card above the title, and in a theme that draws
   the card as a bordered box (Playbook) the box's top edge has none, so the post ran
   up into the buttons (2026-10-12). */
.post-nav {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 10px 14px 0;
    margin-bottom: 10px;
}

.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; }

    /* As tall as the post beside it - the post, its button and the ad - and scrolling
       inside that (Frank, 2026-11-10). It used to stop at the window's height less the
       header's, short of the left column. contain: size gives it no height of its own,
       so the row is the post's height and a long thread scrolls rather than stretching
       the row; stretch then fills that height. A short post still leaves room to talk. */
    .post.is-wide .post-comments {
        align-self: stretch;
        contain: size;
        min-height: 420px;
        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)); }
}

/* Full rows above Load More (2026-10-19): with more to come, the cards that would start
   an unfinished last row wait for the next page instead of leaving blanks beside the
   button. They are only hidden - Load More adds posts after them, and they come back as
   part of a full row. Counted among the cards alone (ad cards are .feed-post too), so a
   page's mix doesn't matter. Once the feed is all caught up, everything shows. */
@media (min-width: 900px) and (max-width: 1199px) {
    .feed.is-wide .feed-scroll:has(> .feed-more) > .feed-post:nth-last-child(1 of .feed-post):nth-child(2n + 1 of .feed-post) { display: none; }
}

@media (min-width: 1200px) {
    .feed.is-wide .feed-scroll:has(> .feed-more) > .feed-post:nth-last-child(1 of .feed-post):nth-child(3n + 1 of .feed-post),
    .feed.is-wide .feed-scroll:has(> .feed-more) > .feed-post:nth-last-child(1 of .feed-post):nth-child(3n + 2 of .feed-post),
    .feed.is-wide .feed-scroll:has(> .feed-more) > .feed-post:nth-last-child(2 of .feed-post):nth-child(3n + 1 of .feed-post) { display: none; }
}

/* An ad card in the feed (2026-10-18): a post's shape, so the theme dresses it like
   one, labeled in the post's stream-name place. The whole card is the link. */
.feed-post.feed-ad { display: flex; flex-direction: column; gap: 10px; }
/* The link: everything but the counts. Top-aligned, as a post is (2026-10-21) - it
   used to sit in the middle of the row's height. */
.feed-ad-in,
.feed-ad-in:hover,
.feed-ad-in:focus { display: block; flex: 1 1 auto; color: inherit; text-decoration: none; }
.feed-ad-body { display: flex; flex-direction: column; gap: 4px; width: 100%; }
.feed-ad .feed-post-title,
.feed-ad .feed-post-media { display: block; }
/* In the round logo's place on a post: a yellow circle saying AD, so the card's head
   reads like every other card's - the mark, then the name. */
.feed-ad-mark {
    display: grid;
    place-items: center;
    background: #f5c518;
    color: #1a1a1a;
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.04em;
    line-height: 1;
}
.feed-ad .feed-post-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.feed-ad-line { display: block; color: var(--wx-muted, #9a9a9a); font-size: 0.95rem; line-height: 1.4; }

/* Pins - the partner's staff only (2026-10-29). The slider sits at the upper right of
   the post, with when it runs out beside it; the comment pin sits by the like. */
.post-pin {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 10px;
    padding: 0 14px;
    margin-bottom: 8px;
    font-size: 0.85rem;
}

.post-pin-until { color: var(--wx-muted, #8a8a8a); }

.post-pin-ask {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    justify-content: flex-end;
}

.post-pin-days { width: 4.5em; text-align: center; }

.post-pin-message { padding: 0 14px; text-align: right; }

.post-composer-buttons { display: flex; gap: 8px; }

.post-comment-pinner {
    appearance: none;
    border: 0;
    background: none;
    padding: 0;
    font: inherit;
    font-size: 0.75rem;
    color: var(--wx-muted-dim, #9a9a9a);
    cursor: pointer;
}

.post-comment-pinner.is-pinned { color: var(--wx-signal, #d4af37); }

/* An ad under an open post, and one among its comments every ten (2026-11-03): the feed's
   ad card, given room so it reads as its own thing and never as part of the post or a
   comment. Nothing to show draws nothing - the wrapper is empty then. */
.post-ad:not(:empty) { margin: 14px 0 4px; }
.post-comment-ad:not(:empty) { margin: 10px 0; }
