/* ==========================================================================
   SocialHub — User panel shell
   Phone: sticky top bar + scrolling content + bottom tab bar.
   Desktop: fixed header + left sidebar + centre feed + right rail.
   ========================================================================== */

.sh-app {
    min-height: 100vh;
    background: var(--sh-page-bg);
}

/* ==========================================================================
   Brand wordmark
   ========================================================================== */

.sh-brand {
    display: inline-flex;
    align-items: center;
    gap: var(--sh-sp-2);
    flex-shrink: 0;
}

.sh-brand-mark {
    width: 34px;
    height: 34px;
    border-radius: 10px;
    background: var(--sh-brand-gradient);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--sh-white);
    flex-shrink: 0;
    box-shadow: 0 4px 10px rgba(124, 58, 237, 0.28);
}

.sh-brand-mark svg {
    width: 20px;
    height: 20px;
}

.sh-brand-text {
    font-family: var(--sh-font-display);
    font-size: var(--sh-fs-xl);
    font-weight: var(--sh-fw-extrabold);
    letter-spacing: -0.03em;
    color: var(--sh-text-strong);
    line-height: 1;
    white-space: nowrap;
}

/* The "Hub" half picks up the brand violet. */
.sh-brand-text em {
    font-style: normal;
    color: var(--sh-brand-purple);
}

.sh-brand-tag {
    display: block;
    font-size: var(--sh-fs-2xs);
    font-weight: var(--sh-fw-medium);
    color: var(--sh-text-muted);
    letter-spacing: 0;
    margin-top: 1px;
}

/* ==========================================================================
   Top header
   ========================================================================== */

.sh-header {
    position: sticky;
    top: 0;
    z-index: var(--sh-z-header);
    height: var(--sh-header-h);
    background: var(--sh-surface);
    border-bottom: 1px solid var(--sh-border);
}

.sh-header-inner {
    display: flex;
    align-items: center;
    gap: var(--sh-sp-2);
    height: 100%;
    /* Fluid by default — the panel runs edge to edge. Capped only when the
       admin turns on appearance.boxed_layout (see .sh-boxed below). */
    max-width: none;
    margin-inline: auto;
    padding-inline: var(--sh-gutter);
}

/* Desktop-only search sitting beside the logo */
.sh-header-search {
    display: none;
}

/* Centre icon nav — desktop only */
.sh-header-nav {
    display: none;
}

.sh-header-actions {
    display: flex;
    align-items: center;
    gap: 2px;
    margin-inline-start: auto;
    flex-shrink: 0;
}

.sh-header-action {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    color: var(--sh-text);
    transition: background var(--sh-dur-fast) var(--sh-ease);
}

.sh-header-action:hover {
    background: var(--sh-surface-sunken);
    color: var(--sh-text);
}

.sh-header-action svg {
    width: 21px;
    height: 21px;
}

/* Avatar + caret trigger for the account menu */
.sh-header-user {
    display: flex;
    align-items: center;
    gap: var(--sh-sp-2);
    padding: 3px 3px 3px 3px;
    border-radius: var(--sh-radius-pill);
    margin-inline-start: 4px;
}

.sh-header-user:hover {
    background: var(--sh-surface-sunken);
}

.sh-header-user-name {
    display: none;
    font-size: var(--sh-fs-base);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text-strong);
}

.sh-header-user-caret {
    display: none;
    color: var(--sh-text-muted);
}

.sh-header-user-caret svg { width: 16px; height: 16px; }

/* ==========================================================================
   Shell grid
   ========================================================================== */

.sh-shell {
    max-width: none;
    margin-inline: auto;
    padding: var(--sh-sp-4) var(--sh-gutter);
    /* Clear the fixed bottom tab bar on phones. */
    padding-bottom: calc(var(--sh-tabbar-h) + var(--sh-sp-6));
}

.sh-shell-wide {
    max-width: none;
}

/* ==========================================================================
   Boxed layout
   Opt-in via the appearance.boxed_layout setting. Off by default, so the
   panel fills the viewport the way the design intends.
   ========================================================================== */

/* One cap for both, so the header and the columns below it stay aligned. */
.sh-boxed .sh-header-inner,
.sh-boxed .sh-shell {
    max-width: var(--sh-shell-max);
}

/* ==========================================================================
   Site Layout
   Appearance → Layout Settings → Site Layout. Was validated, stored and
   read by nothing; `layouts/app` puts `sh-layout-<key>` on the body now.

   Each variant owns something no other control does. Corner radius
   belongs to Rounded Corners and spacing scale to nothing else, so
   Classic takes the shadow and Compact takes the density — neither is
   a second owner of a setting that already exists.
   ========================================================================== */

/* Modern is the design as drawn, so it adds nothing. */

/* Classic: flat. A visible edge instead of a lifted card. */
.sh-layout-classic .sh-card {
    box-shadow: none;
    border-color: var(--sh-border-strong);
}

/* Compact: the same layout, closer together. */
.sh-layout-compact .sh-feed,
.sh-layout-compact .sh-rail {
    gap: var(--sh-sp-3);
}

.sh-layout-compact .sh-card-head,
.sh-layout-compact .sh-card-body {
    padding: var(--sh-sp-3);
}

.sh-layout-compact .sh-shell {
    padding-block: var(--sh-sp-3);
}

/* ==========================================================================
   Left sidebar — hidden on phones, where the tab bar + drawer take over
   ========================================================================== */

.sh-sidebar {
    display: none;
}

.sh-nav {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.sh-nav-item {
    display: flex;
    align-items: center;
    gap: var(--sh-sp-3);
    width: 100%;
    height: 44px;
    padding: 0 var(--sh-sp-3);
    border-radius: var(--sh-radius-sm);
    font-size: var(--sh-fs-md);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text);
    /* The "More" entry is a <button>, which would otherwise centre its label. */
    text-align: start;
    transition: background var(--sh-dur-fast) var(--sh-ease),
        color var(--sh-dur-fast) var(--sh-ease);
}

.sh-nav-item:hover {
    background: var(--sh-surface-sunken);
    color: var(--sh-text);
}

.sh-nav-item.is-active {
    background: var(--sh-primary-50);
    color: var(--sh-primary-700);
}

.sh-nav-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    flex-shrink: 0;
    color: var(--sh-text-muted);
}

.sh-nav-item.is-active .sh-nav-icon {
    color: var(--sh-primary-600);
}

.sh-nav-icon svg {
    width: 21px;
    height: 21px;
}

.sh-nav-label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sh-nav-count {
    flex-shrink: 0;
}

/* Mini profile card under the nav */
.sh-side-profile {
    display: flex;
    align-items: center;
    gap: var(--sh-sp-3);
    padding: var(--sh-sp-3);
}

.sh-side-stats {
    display: flex;
    border-top: 1px solid var(--sh-border);
}

.sh-side-stat {
    flex: 1 1 0;
    padding: var(--sh-sp-3) var(--sh-sp-2);
    text-align: center;
}

.sh-side-stat + .sh-side-stat {
    border-inline-start: 1px solid var(--sh-border);
}

.sh-side-stat-value {
    font-size: var(--sh-fs-md);
    font-weight: var(--sh-fw-bold);
    color: var(--sh-text-strong);
    line-height: 1.2;
}

.sh-side-stat-label {
    font-size: var(--sh-fs-xs);
    color: var(--sh-text-muted);
}

/* ==========================================================================
   Right rail — hidden below desktop
   ========================================================================== */

/* The rails live in one grid column. Below 1400 they stack inside it;
   above, they sit side by side. Either way nothing is hidden by the
   window size — only by the admin's switches. */
.sh-rails {
    display: none;
}

/* Widgets in either column stick while the feed scrolls. */
.sh-sticky {
    position: sticky;
    top: calc(var(--sh-header-h) + var(--sh-sp-4));
}

/* ==========================================================================
   Feed column
   ========================================================================== */

.sh-feed {
    display: flex;
    flex-direction: column;
    gap: var(--sh-sp-4);
    min-width: 0;
}

/* ==========================================================================
   Mobile bottom tab bar
   ========================================================================== */

.sh-tabbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: var(--sh-z-tabbar);
    height: calc(var(--sh-tabbar-h) + env(safe-area-inset-bottom, 0px));
    padding-bottom: env(safe-area-inset-bottom, 0px);
    display: flex;
    align-items: stretch;
    background: var(--sh-surface);
    border-top: 1px solid var(--sh-border);
}

.sh-tabbar-item {
    position: relative;
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    font-size: var(--sh-fs-2xs);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text-muted);
    min-width: 0;
}

.sh-tabbar-item svg {
    width: 23px;
    height: 23px;
}

.sh-tabbar-item.is-active {
    color: var(--sh-primary-600);
}

/* Active underline stub, matching the mockups */
.sh-tabbar-item.is-active::after {
    content: "";
    position: absolute;
    bottom: 6px;
    width: 22px;
    height: 3px;
    border-radius: var(--sh-radius-pill);
    background: var(--sh-primary-600);
}

.sh-tabbar-label {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Centre compose button lifts above the bar */
.sh-tabbar-fab {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 72px;
}

.sh-tabbar-fab .sh-fab {
    margin-top: -18px;
    border: 4px solid var(--sh-surface);
    width: 56px;
    height: 56px;
}

/* ==========================================================================
   Mobile drawer (full nav behind the hamburger / "More")
   ========================================================================== */

.sh-drawer {
    position: fixed;
    inset: 0;
    z-index: var(--sh-z-drawer);
    display: none;
}

.sh-drawer.is-open {
    display: block;
}

.sh-drawer-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(15, 23, 42, 0.5);
}

.sh-drawer-panel {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: min(86vw, 320px);
    background: var(--sh-surface);
    box-shadow: var(--sh-shadow-lg);
    display: flex;
    flex-direction: column;
    animation: sh-drawer-in var(--sh-dur) var(--sh-ease);
}

.sh-drawer-panel-right {
    left: auto;
    right: 0;
    animation: sh-drawer-in-right var(--sh-dur) var(--sh-ease);
}

@keyframes sh-drawer-in {
    from { transform: translateX(-100%); }
    to { transform: translateX(0); }
}

@keyframes sh-drawer-in-right {
    from { transform: translateX(100%); }
    to { transform: translateX(0); }
}

.sh-drawer-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sh-sp-3);
    padding: var(--sh-sp-3) var(--sh-sp-4);
    border-bottom: 1px solid var(--sh-border);
    flex-shrink: 0;
}

.sh-drawer-body {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: var(--sh-sp-3);
}

/* ==========================================================================
   Stories rail
   ========================================================================== */

.sh-stories {
    padding: var(--sh-sp-3) 0 var(--sh-sp-3) var(--sh-sp-3);
}

.sh-stories .sh-scroll-x {
    gap: var(--sh-sp-3);
    padding-inline-end: var(--sh-sp-3);
}

.sh-story {
    width: 66px;
    text-align: center;
}

.sh-story-name {
    display: block;
    margin-top: 5px;
    font-size: var(--sh-fs-xs);
    font-weight: var(--sh-fw-medium);
    color: var(--sh-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sh-story-add {
    position: relative;
}

.sh-story-add-badge {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--sh-primary-600);
    color: var(--sh-white);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 2px solid var(--sh-surface);
}

.sh-story-add-badge svg { width: 12px; height: 12px; }

/* Tall card story tile — the arrangement the feed mockup uses. */
.sh-story-tile {
    position: relative;
    display: block;
    width: 84px;
    border-radius: var(--sh-radius);
    overflow: hidden;
    background: var(--sh-surface-sunken);
    box-shadow: var(--sh-shadow-sm);
}

.sh-story-tile .sh-ratio {
    padding-top: 150%;
}

/* Bottom scrim so the name stays readable over any cover. */
.sh-story-tile-overlay {
    position: absolute;
    inset: auto 0 0 0;
    padding: var(--sh-sp-4) 6px 7px;
    background: linear-gradient(to top, rgba(8, 15, 35, 0.9), transparent);
    color: var(--sh-white);
    font-size: var(--sh-fs-2xs);
    font-weight: var(--sh-fw-semibold);
    text-align: center;
    line-height: 1.25;
}

.sh-story-tile-overlay span {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Author avatar pinned to the top-left of the tile.
   The blue ring means "not watched yet"; .is-seen drops it back to a plain
   white outline, which is what the ring is for. */
.sh-story-tile-avatar {
    position: absolute;
    top: 7px;
    left: 7px;
    z-index: 1;
    display: block;
    border-radius: 50%;
    padding: 2px;
    background: var(--sh-primary-600);
    line-height: 0;
}

.sh-story-tile-avatar .sh-avatar {
    display: block;
    border: 2px solid var(--sh-surface);
}

.sh-story-tile-avatar.is-seen {
    background: transparent;
    padding: 0;
}

.sh-story-tile-avatar.is-seen .sh-avatar {
    border-color: rgba(255, 255, 255, 0.85);
}

/* "Add Story": photo on top, white footer, plus button straddling the seam. */
.sh-story-add {
    background: var(--sh-surface);
    display: flex;
    flex-direction: column;
}

.sh-story-add-photo {
    display: block;
    position: relative;
    flex: 1 1 auto;
    overflow: hidden;
}

.sh-story-add-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.sh-story-add-foot {
    position: relative;
    display: block;
    flex-shrink: 0;
    padding: 18px 4px 9px;
    background: var(--sh-surface);
    text-align: center;
}

.sh-story-add-plus {
    position: absolute;
    left: 50%;
    top: 0;
    transform: translate(-50%, -50%);
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: var(--sh-primary-600);
    color: var(--sh-white);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 3px solid var(--sh-surface);
}

.sh-story-add-plus svg { width: 15px; height: 15px; }

.sh-story-add-label {
    display: block;
    font-size: var(--sh-fs-2xs);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Arrow that scrolls the rail on wide screens. */
.sh-story-next {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    display: none;
    background: var(--sh-surface);
    box-shadow: var(--sh-shadow-md);
    border-radius: 50%;
}

@media (min-width: 1024px) {
    .sh-story-tile { width: 92px; }

    .sh-stories { position: relative; }

    .sh-story-next { display: inline-flex; }
}

/* ==========================================================================
   Composer
   ========================================================================== */

.sh-composer-top {
    display: flex;
    align-items: center;
    gap: var(--sh-sp-3);
    padding: var(--sh-sp-3);
}

.sh-composer-trigger {
    flex: 1 1 auto;
    min-width: 0;
    height: 42px;
    padding: 0 var(--sh-sp-4);
    border-radius: var(--sh-radius-pill);
    background: var(--sh-surface-sunken);
    color: var(--sh-text-subtle);
    font-size: var(--sh-fs-md);
    text-align: start;
    display: flex;
    align-items: center;
}

.sh-composer-trigger:hover {
    background: var(--sh-gray-150);
}

.sh-composer-actions {
    display: flex;
    gap: var(--sh-sp-2);
    padding: 0 var(--sh-sp-3) var(--sh-sp-3);
    overflow-x: auto;
    scrollbar-width: none;
}

.sh-composer-actions::-webkit-scrollbar { display: none; }

.sh-composer-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    flex: 1 1 auto;
    min-width: max-content;
    height: 38px;
    padding: 0 var(--sh-sp-3);
    border-radius: var(--sh-radius-sm);
    font-size: var(--sh-fs-sm);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text);
    background: var(--sh-surface-alt);
    white-space: nowrap;
}

.sh-composer-action:hover {
    background: var(--sh-surface-sunken);
    color: var(--sh-text);
}

.sh-composer-action svg { width: 18px; height: 18px; }

.sh-composer-action-photo svg { color: var(--sh-success-500); }
.sh-composer-action-reel svg { color: var(--sh-pink-500); }
.sh-composer-action-live svg { color: var(--sh-danger-500); }
.sh-composer-action-feeling svg { color: var(--sh-warning-500); }
.sh-composer-action-poll svg { color: var(--sh-primary-600); }
.sh-composer-action-event svg { color: var(--sh-violet-600); }

/* ==========================================================================
   Post card
   ========================================================================== */

.sh-post-head {
    display: flex;
    align-items: flex-start;
    gap: var(--sh-sp-3);
    padding: var(--sh-sp-3) var(--sh-sp-4) var(--sh-sp-2);
}

.sh-post-author {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: var(--sh-fs-md);
    font-weight: var(--sh-fw-bold);
    color: var(--sh-text-strong);
    line-height: 1.3;
}

.sh-post-meta {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: var(--sh-fs-xs);
    color: var(--sh-text-muted);
    line-height: 1.4;
}

.sh-post-meta svg { width: 12px; height: 12px; }

.sh-post-text {
    padding: 0 var(--sh-sp-4) var(--sh-sp-3);
    font-size: var(--sh-fs-md);
    line-height: var(--sh-lh-relaxed);
    color: var(--sh-text);
    overflow-wrap: anywhere;
}

.sh-post-text a {
    font-weight: var(--sh-fw-medium);
}

/* -- Media grid ---------------------------------------------------------- */

.sh-post-media {
    display: grid;
    gap: 3px;
    background: var(--sh-border);
}

.sh-post-media-1 { grid-template-columns: 1fr; }
.sh-post-media-2 { grid-template-columns: 1fr 1fr; }

/* Three: a wide hero above a two-up strip. */
.sh-post-media-3 { grid-template-columns: 1fr 1fr; }
.sh-post-media-3 > :first-child { grid-column: 1 / -1; }

/* Four: hero above a three-up strip. */
.sh-post-media-4 { grid-template-columns: repeat(3, 1fr); }
.sh-post-media-4 > :first-child { grid-column: 1 / -1; }

/* Five or more: one tall image on the left, a 2x2 block on the right.
   This is the arrangement the feed mockup uses for a large photo set. */
.sh-post-media-5 {
    grid-template-columns: 1.85fr 1fr 1fr;
    grid-template-rows: 1fr 1fr;
}

.sh-post-media-5 > :first-child {
    grid-row: 1 / 3;
}

.sh-post-media-item {
    position: relative;
    overflow: hidden;
    background: var(--sh-surface-sunken);
}

.sh-post-media-item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* A video in the grid. `display: block` is load-bearing: this item is a
   <span> rather than the theatre's <a>, and on an inline box the cell
   collapses. `contain`, not `cover`, because cropping a video to a grid
   cell hides the part somebody framed the shot around. */
.sh-post-media-video {
    display: block;
    background: var(--sh-media-backdrop);
}

.sh-post-media-video video {
    width: 100%;
    height: 100%;
    max-height: 520px;
    object-fit: contain;
    display: block;
}

.sh-post-media-1 .sh-post-media-item { max-height: 520px; }

/* Keep the multi-image grids from growing taller than the feed column. */
.sh-post-media-3,
.sh-post-media-4 { max-height: 460px; }
.sh-post-media-5 { height: min(62vw, 430px); }

.sh-post-media-3 > :first-child,
.sh-post-media-4 > :first-child { max-height: 300px; }

.sh-post-media-more {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(15, 23, 42, 0.55);
    color: var(--sh-white);
    font-size: var(--sh-fs-2xl);
    font-weight: var(--sh-fw-bold);
}

/* -- Reaction summary row ------------------------------------------------ */

.sh-post-stats {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sh-sp-3);
    padding: var(--sh-sp-3) var(--sh-sp-4);
    font-size: var(--sh-fs-sm);
    color: var(--sh-text-muted);
}

.sh-reactions {
    display: inline-flex;
    align-items: center;
}

.sh-reaction-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    border: 2px solid var(--sh-surface);
    margin-inline-start: -6px;
    font-size: 11px;
    line-height: 1;
}

.sh-reaction-chip:first-child { margin-inline-start: 0; }

.sh-reaction-like { background: var(--sh-primary-600); color: var(--sh-white); }
.sh-reaction-love { background: var(--sh-danger-500); color: var(--sh-white); }
.sh-reaction-wow { background: var(--sh-warning-500); color: var(--sh-white); }

.sh-reaction-chip svg { width: 11px; height: 11px; }

.sh-post-stats-count {
    margin-inline-start: 6px;
    font-weight: var(--sh-fw-medium);
}

/* -- Action bar ---------------------------------------------------------- */

.sh-post-actions {
    display: flex;
    border-top: 1px solid var(--sh-border);
}

.sh-post-action {
    flex: 1 1 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 44px;
    font-size: var(--sh-fs-sm);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text-muted);
    min-width: 0;
}

.sh-post-action:hover {
    background: var(--sh-surface-alt);
    color: var(--sh-text);
}

.sh-post-action svg { width: 18px; height: 18px; }

.sh-post-action.is-active {
    color: var(--sh-primary-600);
}

.sh-post-action-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* -- Comments ------------------------------------------------------------ */

.sh-comments {
    padding: var(--sh-sp-3) var(--sh-sp-4);
    border-top: 1px solid var(--sh-border);
    background: var(--sh-surface-alt);
}

.sh-comment {
    display: flex;
    gap: var(--sh-sp-2);
    padding: var(--sh-sp-2) 0;
}

.sh-comment-bubble {
    background: var(--sh-surface);
    border: 1px solid var(--sh-border);
    border-radius: var(--sh-radius);
    padding: var(--sh-sp-2) var(--sh-sp-3);
    min-width: 0;
    overflow-wrap: anywhere;
}

.sh-comment-author {
    font-size: var(--sh-fs-sm);
    font-weight: var(--sh-fw-bold);
    color: var(--sh-text-strong);
}

.sh-comment-text {
    font-size: var(--sh-fs-base);
    line-height: var(--sh-lh-snug);
}

.sh-comment-tools {
    display: flex;
    gap: var(--sh-sp-3);
    margin-top: 4px;
    padding-inline-start: var(--sh-sp-3);
    font-size: var(--sh-fs-xs);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text-muted);
}

/* ==========================================================================
   Tablet
   ========================================================================== */

@media (min-width: 768px) {
    .sh-header-user-name,
    .sh-header-user-caret {
        display: block;
    }

    .sh-header-user {
        padding-inline-end: var(--sh-sp-2);
    }

    .sh-shell {
        padding-top: var(--sh-sp-5);
    }

    .sh-stories {
        padding: var(--sh-sp-4) 0 var(--sh-sp-4) var(--sh-sp-4);
    }

    .sh-stories .sh-scroll-x {
        padding-inline-end: var(--sh-sp-4);
    }

    .sh-composer-top {
        padding: var(--sh-sp-4);
    }

    .sh-composer-actions {
        padding: 0 var(--sh-sp-4) var(--sh-sp-4);
    }

    .sh-post-head { padding: var(--sh-sp-4) var(--sh-sp-4) var(--sh-sp-2); }
    .sh-post-text { padding: 0 var(--sh-sp-4) var(--sh-sp-4); }
    .sh-post-action { height: 46px; font-size: var(--sh-fs-base); }
}

/* ==========================================================================
   Desktop — sidebar appears, tab bar retires
   ========================================================================== */

@media (min-width: 1024px) {
    .sh-header-search {
        display: block;
        flex: 0 1 380px;
        margin-inline-start: var(--sh-sp-4);
    }

    .sh-header-nav {
        display: flex;
        align-items: center;
        gap: var(--sh-sp-1);
        margin-inline: auto;
    }

    .sh-header-nav-item {
        position: relative;
        display: inline-flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 2px;
        min-width: 64px;
        height: 50px;
        padding: 0 var(--sh-sp-2);
        border-radius: var(--sh-radius-sm);
        font-size: var(--sh-fs-2xs);
        font-weight: var(--sh-fw-semibold);
        color: var(--sh-text-muted);
    }

    .sh-header-nav-item:hover {
        background: var(--sh-surface-sunken);
        color: var(--sh-text);
    }

    .sh-header-nav-item svg { width: 21px; height: 21px; }

    .sh-header-nav-item.is-active {
        color: var(--sh-primary-600);
    }

    .sh-header-nav-item.is-active::after {
        content: "";
        position: absolute;
        left: var(--sh-sp-2);
        right: var(--sh-sp-2);
        bottom: -7px;
        height: 3px;
        border-radius: var(--sh-radius-pill);
        background: var(--sh-primary-600);
    }

    .sh-tabbar {
        display: none;
    }

    .sh-shell {
        display: grid;
        grid-template-columns: var(--sh-sidebar-w) minmax(0, 1fr);
        gap: var(--sh-sp-5);
        align-items: start;
        padding-bottom: var(--sh-sp-8);
    }

    /* Pinned beside the feed: only the centre column scrolls with the page.
       The sidebar is taller than most viewports, so it carries its own
       scroll — with a VISIBLE scrollbar, otherwise the overflow just reads
       as a card chopped in half. Markup adds .sh-scroll-thin for the thumb. */
    .sh-sidebar {
        display: flex;
        flex-direction: column;
        gap: var(--sh-sp-4);
        position: sticky;
        top: calc(var(--sh-header-h) + var(--sh-sp-5));
        max-height: calc(100vh - var(--sh-header-h) - var(--sh-sp-8));
        overflow-y: auto;
        /* `auto`, not `contain`. Containment is for a modal or a
           drawer, where scrolling the panel must not move the page
           behind it. This column is part of the page: with `contain`,
           putting the pointer over it trapped the wheel — once the
           column's own scroll hit an end, the page would not move at
           all, so you had to aim at the centre column to carry on
           scrolling. `auto` chains to the page at the boundary, which
           is what every other site does. */
        overscroll-behavior: auto;
        /* Keeps the thumb clear of the card edges. */
        padding-inline-end: 6px;
    }

    /* Critical: this is a column flex container with a max-height, so its
       children would otherwise shrink to fit and squash their own content
       (a half-height profile card) instead of overflowing into the scroll. */
    .sh-sidebar > * {
        flex-shrink: 0;
    }

    .sh-feed {
        gap: var(--sh-sp-5);
    }
}

/* Three columns once there is room for the rail. */
@media (min-width: 1280px) {
    .sh-shell-3col {
        grid-template-columns: var(--sh-sidebar-w) minmax(0, 1fr) var(--sh-rail-w);
    }

    /* Sidebar Position → Left of the feed. The nav stays where it is;
       the rails move in beside it. `order` on the main column rather
       than reordering the markup, so the document still reads
       navigation → content → suggestions for a screen reader. */
    .sh-shell-rails-start.sh-shell-3col {
        grid-template-columns: var(--sh-sidebar-w) var(--sh-rail-w) minmax(0, 1fr);
    }

    .sh-shell-rails-start .sh-main {
        order: 9;
    }

    /* The column pins the same way as the sidebar, and it is the
       scroller — the rails inside it are plain stacks now. */
    .sh-rails {
        display: flex;
        flex-direction: column;
        gap: var(--sh-sp-4);
        position: sticky;
        top: calc(var(--sh-header-h) + var(--sh-sp-5));
        max-height: calc(100vh - var(--sh-header-h) - var(--sh-sp-8));
        overflow-y: auto;
        /* `auto`, not `contain`. Containment is for a modal or a
           drawer, where scrolling the panel must not move the page
           behind it. This column is part of the page: with `contain`,
           putting the pointer over it trapped the wheel — once the
           column's own scroll hit an end, the page would not move at
           all, so you had to aim at the centre column to carry on
           scrolling. `auto` chains to the page at the boundary, which
           is what every other site does. */
        overscroll-behavior: auto;
        padding-inline-end: 6px;
    }

    .sh-rail {
        display: flex;
        flex-direction: column;
        gap: var(--sh-sp-4);
        min-width: 0;
    }

    /* The action sits beside the text in a rail, as the mockups draw
       it. `.sh-list-row` wraps globally because a 220px column left
       the title 87px and broke it mid-word — but the narrowest rail is
       265px, which leaves ~116px, wider than the 110px basis that
       triggers the wrap. Wrapping there only made every row 102px tall
       with the button stranded on a line of its own. */
    .sh-rails .sh-list-row {
        flex-wrap: nowrap;
    }

    /* Same reason as the sidebar: don't let the widgets compress. */
    .sh-rails > *,
    .sh-rail > * {
        flex-shrink: 0;
    }
}

/* Wide enough for the two rails to sit side by side, as the feed
   mockup shows. Below this they are stacked in the same column — the
   content is there either way. */
@media (min-width: 1400px) {
    .sh-shell-4col {
        --sh-rail-w: 268px;
        --sh-rails-w: calc(var(--sh-rail-w) * 2 + var(--sh-sp-4));

        grid-template-columns:
            var(--sh-sidebar-w)
            minmax(0, 1fr)
            var(--sh-rails-w);
        gap: var(--sh-sp-4);
    }

    .sh-shell-4col .sh-rails {
        flex-direction: row;
        align-items: flex-start;
    }

    /* `1 1 0`, not `auto`: the two tracks must match whatever is in
       them, or a rail with a tall widget takes the width. */
    .sh-shell-4col .sh-rails > .sh-rail {
        flex: 1 1 0;
    }

    .sh-shell-rails-start.sh-shell-4col {
        grid-template-columns:
            var(--sh-sidebar-w)
            var(--sh-rails-w)
            minmax(0, 1fr);
    }

    /* A single rail where there was room for two. Without this the feed
       absorbed nearly all the freed space — the rail went from 268 to
       316 while the feed went from 720 to 948, so switching the second
       sidebar off barely looked like it had widened anything.

       `:not(.sh-shell-4col)` is what makes it mean "one rail": the feed
       carries both classes when both rails are on, and pages with a
       single rail carry only this one. */
    .sh-shell-3col:not(.sh-shell-4col) {
        --sh-rail-w: var(--sh-rail-w-solo);
    }
}

/* ==========================================================================
   Poll
   ========================================================================== */

.sh-poll {
    display: flex;
    flex-direction: column;
    gap: var(--sh-sp-2);
}

.sh-poll-form {
    margin: 0;
}

.sh-poll-option {
    justify-content: flex-start;
    font-weight: var(--sh-fw-medium);
}

.sh-poll-result-head {
    margin-bottom: 5px;
}

.sh-poll-result.is-mine .sh-progress-bar {
    background: var(--sh-brand-gradient);
}

/* ==========================================================================
   Feed hero banner
   Sits above the stories rail. Copy and artwork come from settings, so the
   text lives on an overlay rather than being baked into the image.
   ========================================================================== */

.sh-feed-hero {
    position: relative;
    border-radius: var(--sh-radius-lg);
    overflow: hidden;
    background: var(--sh-gray-800);
    min-height: 190px;
    display: flex;
    align-items: center;
}

.sh-feed-hero-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Dark wash so the headline stays legible over any photo. */
.sh-feed-hero::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(
        100deg,
        rgba(8, 15, 35, 0.82) 0%,
        rgba(8, 15, 35, 0.55) 42%,
        rgba(8, 15, 35, 0.12) 72%
    );
}

.sh-feed-hero-body {
    position: relative;
    z-index: 1;
    padding: var(--sh-sp-5);
    max-width: 30ch;
}

.sh-feed-hero-title {
    font-family: var(--sh-font-display);
    font-size: var(--sh-fs-3xl);
    font-weight: var(--sh-fw-extrabold);
    line-height: 1.04;
    letter-spacing: -0.03em;
    color: var(--sh-white);
    /* Settings store the headline with newlines; honour them. */
    white-space: pre-line;
}

.sh-feed-hero-text {
    margin-top: var(--sh-sp-3);
    font-size: var(--sh-fs-sm);
    line-height: var(--sh-lh-snug);
    color: rgba(255, 255, 255, 0.86);
}

.sh-feed-hero-cta {
    margin-top: var(--sh-sp-4);
    /* Sits on the brand gradient, which does not change with the theme, so
       both of these stay fixed rather than following the text tokens. */
    background: var(--sh-white);
    color: var(--sh-brand-blue);
}

.sh-feed-hero-cta:hover {
    background: var(--sh-gray-100);
    color: var(--sh-text-strong);
}

/* Handwritten-style note in the top right of the banner. */
.sh-feed-hero-note {
    display: none;
}

/* ==========================================================================
   Sidebar shortcuts
   ========================================================================== */

.sh-side-heading {
    font-size: var(--sh-fs-md);
    font-weight: var(--sh-fw-bold);
    color: var(--sh-text-strong);
    margin: 0;
}

.sh-shortcut {
    display: flex;
    align-items: center;
    gap: var(--sh-sp-3);
    padding: var(--sh-sp-2) 0;
    color: var(--sh-text);
    min-width: 0;
}

.sh-shortcut:hover {
    color: var(--sh-primary-700);
}

.sh-shortcut-name {
    font-size: var(--sh-fs-base);
    font-weight: var(--sh-fw-medium);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ==========================================================================
   Premium promo card
   ========================================================================== */

.sh-promo {
    position: relative;
    border-radius: var(--sh-radius-lg);
    overflow: hidden;
    background: linear-gradient(150deg, #4c1d95 0%, #7c3aed 45%, #c026d3 100%);
    color: var(--sh-white);
    padding: var(--sh-sp-5);
}

.sh-promo-crown {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.16);
    color: #fbbf24;
    margin-bottom: var(--sh-sp-3);
}

.sh-promo-crown svg { width: 22px; height: 22px; }

.sh-promo-title {
    font-size: var(--sh-fs-xl);
    font-weight: var(--sh-fw-extrabold);
    letter-spacing: -0.02em;
    color: var(--sh-white);
    line-height: 1.2;
}

.sh-promo-list {
    margin: var(--sh-sp-3) 0 var(--sh-sp-4);
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.sh-promo-item {
    display: flex;
    align-items: flex-start;
    gap: var(--sh-sp-2);
    font-size: var(--sh-fs-sm);
    color: rgba(255, 255, 255, 0.92);
    line-height: 1.35;
}

.sh-promo-item svg {
    width: 15px;
    height: 15px;
    flex-shrink: 0;
    margin-top: 2px;
    color: #4ade80;
}

.sh-promo-cta {
    background: linear-gradient(90deg, #fbbf24 0%, #f59e0b 100%);
    color: #422006;
    border: 0;
    font-weight: var(--sh-fw-bold);
}

.sh-promo-cta:hover {
    color: #422006;
    filter: brightness(1.05);
}

/* ==========================================================================
   Feed toolbar — filter tabs with a sort control on the right
   ========================================================================== */

.sh-feed-toolbar {
    display: flex;
    align-items: center;
    gap: var(--sh-sp-3);
    padding-inline-end: var(--sh-sp-3);
}

.sh-feed-toolbar .sh-tabs {
    flex: 1 1 auto;
    min-width: 0;
    border-bottom: 0;
}

.sh-feed-sort {
    flex-shrink: 0;
    display: none;
}

@media (min-width: 768px) {
    .sh-feed-hero {
        min-height: 230px;
    }

    .sh-feed-hero-body {
        padding: var(--sh-sp-6);
    }

    .sh-feed-hero-title {
        font-size: var(--sh-fs-4xl);
    }

    .sh-feed-sort {
        display: flex;
    }

    /* The script-style note only has room from tablet up. */
    .sh-feed-hero-note {
        position: absolute;
        top: var(--sh-sp-5);
        right: var(--sh-sp-6);
        z-index: 1;
        display: block;
        font-size: var(--sh-fs-sm);
        font-weight: var(--sh-fw-semibold);
        font-style: italic;
        line-height: 1.25;
        text-align: end;
        color: var(--sh-white);
        white-space: pre-line;
        text-shadow: 0 1px 6px rgba(8, 15, 35, 0.5);
    }
}

/* ==========================================================================
   Post tally row — outline icon + count, Facebook style
   ========================================================================== */

.sh-tally {
    display: flex;
    align-items: center;
    gap: var(--sh-sp-4);
}

.sh-tally-item {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: var(--sh-fs-base);
    font-weight: var(--sh-fw-medium);
    color: var(--sh-text-muted);
    background: none;
    border: 0;
    padding: 0;
}

.sh-tally-item svg {
    width: 20px;
    height: 20px;
}

button.sh-tally-item {
    cursor: pointer;
}

button.sh-tally-item:hover {
    color: var(--sh-text);
}

button.sh-tally-item:hover span {
    text-decoration: underline;
}

/* ==========================================================================
   Hover tooltip — who reacted
   Anchored to its trigger purely in CSS; the script only toggles .is-open,
   so no element ever carries an inline style.
   ========================================================================== */

.sh-tip {
    position: absolute;
    left: 0;
    bottom: calc(100% + 10px);
    z-index: var(--sh-z-modal);
    display: none;
    flex-direction: column;
    gap: 1px;
    min-width: 190px;
    max-width: 280px;
    max-height: 320px;
    overflow-y: auto;
    padding: var(--sh-sp-3) var(--sh-sp-4);
    border-radius: var(--sh-radius);
    background: rgba(15, 23, 42, 0.94);
    color: var(--sh-white);
    font-size: var(--sh-fs-sm);
    font-weight: var(--sh-fw-medium);
    line-height: 1.5;
    text-align: start;
    box-shadow: var(--sh-shadow-lg);
    pointer-events: none;
}

.sh-tip.is-open {
    display: flex;
}

.sh-tip-title {
    font-weight: var(--sh-fw-bold);
    margin-bottom: 3px;
}

.sh-tip-name {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sh-tip-more {
    margin-top: 4px;
    color: var(--sh-gray-400);
}

/* The tooltip has to escape the card, so post cards do not clip their
   overflow. Their media grid clips itself instead. */
.sh-post-card {
    overflow: visible;
}

.sh-post-card .sh-post-media {
    overflow: hidden;
}

/* With the card no longer clipping, the action bar rounds its own corners so
   a hover background cannot square them off. */
.sh-post-card .sh-post-actions {
    border-bottom-left-radius: var(--sh-radius-lg);
    border-bottom-right-radius: var(--sh-radius-lg);
    overflow: hidden;
}

/* ==========================================================================
   Post dialog (comments popup)
   ========================================================================== */

.sh-pv-body {
    padding-inline: 0;
}

.sh-pv-media {
    display: flex;
    flex-direction: column;
    gap: 3px;
    background: var(--sh-gray-900);
}

.sh-pv-media img {
    width: 100%;
    max-height: 70vh;
    object-fit: contain;
}

.sh-pv-comments {
    padding: var(--sh-sp-3) var(--sh-sp-4);
}

.sh-pv-foot {
    justify-content: stretch;
}

.sh-pv-input {
    min-height: 40px;
    border-radius: var(--sh-radius-lg);
    background: var(--sh-surface-sunken);
    border-color: transparent;
    resize: none;
}

.sh-pv-loading {
    display: flex;
    flex-direction: column;
    gap: var(--sh-sp-3);
}

.sh-pv-skeleton {
    display: block;
    height: 18px;
}

.sh-pv-skeleton-tall {
    height: 220px;
}

/* ==========================================================================
   Composer modal
   A single dialog with several screens. Only one .sh-cmp-screen is active at
   a time; the script toggles the class and the `hidden` attribute.
   ========================================================================== */

.sh-cmp-dialog {
    max-width: 520px;
    padding: 0;
}

.sh-cmp-screen {
    display: none;
    flex-direction: column;
    max-height: 90vh;
}

.sh-cmp-screen.is-active {
    display: flex;
}

/* -- Header -------------------------------------------------------------- */

.sh-cmp-head {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 60px;
    padding: var(--sh-sp-3) var(--sh-sp-4);
    border-bottom: 1px solid var(--sh-border);
    flex-shrink: 0;
}

.sh-cmp-title {
    font-size: var(--sh-fs-xl);
    font-weight: var(--sh-fw-bold);
    color: var(--sh-text-strong);
    margin: 0;
    text-align: center;
}

/* Round grey control, top-left for back and top-right for close. */
.sh-cmp-round {
    position: absolute;
    top: 50%;
    right: var(--sh-sp-4);
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--sh-surface-sunken);
    color: var(--sh-text);
    flex-shrink: 0;
}

.sh-cmp-round:hover {
    background: var(--sh-gray-200);
}

.sh-cmp-round svg { width: 19px; height: 19px; }

.sh-cmp-head [data-sh-screen-back].sh-cmp-round {
    right: auto;
    left: var(--sh-sp-4);
}

/* Not absolutely placed — used inline beside the text area. */
.sh-cmp-round-plain {
    position: static;
    transform: none;
    background: transparent;
    color: var(--sh-text-muted);
}

.sh-cmp-round-plain:hover {
    background: var(--sh-surface-sunken);
    color: var(--sh-text);
}

/* -- Body ---------------------------------------------------------------- */

.sh-cmp-body {
    padding: var(--sh-sp-4);
    overflow-y: auto;
    flex: 1 1 auto;
}

.sh-cmp-foot {
    padding: var(--sh-sp-4);
    border-top: 1px solid var(--sh-border);
    flex-shrink: 0;
}

.sh-cmp-author {
    display: flex;
    align-items: flex-start;
    gap: var(--sh-sp-3);
    margin-bottom: var(--sh-sp-3);
}

.sh-cmp-name {
    display: block;
    font-size: var(--sh-fs-md);
    font-weight: var(--sh-fw-bold);
    color: var(--sh-text-strong);
    line-height: 1.3;
}

.sh-cmp-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 5px;
}

.sh-cmp-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 28px;
    padding: 0 9px;
    border-radius: var(--sh-radius-xs);
    background: var(--sh-surface-sunken);
    color: var(--sh-text);
    font-size: var(--sh-fs-xs);
    font-weight: var(--sh-fw-bold);
    white-space: nowrap;
}

.sh-cmp-chip:hover {
    background: var(--sh-gray-200);
}

.sh-cmp-chip svg { width: 13px; height: 13px; }

.sh-cmp-chip-dark {
    background: var(--sh-gray-900);
    color: var(--sh-white);
}

.sh-cmp-chip-dark:hover {
    background: var(--sh-gray-800);
}

/* -- Writing area --------------------------------------------------------- */

.sh-cmp-write {
    border-radius: var(--sh-radius);
    transition: background var(--sh-dur) var(--sh-ease);
}

.sh-cmp-input {
    display: block;
    width: 100%;
    min-height: 110px;
    padding: var(--sh-sp-2) 0;
    border: 0;
    background: transparent;
    color: var(--sh-text);
    font-family: inherit;
    font-size: var(--sh-fs-2xl);
    line-height: var(--sh-lh-snug);
    resize: none;
}

.sh-cmp-input::placeholder {
    color: var(--sh-text-subtle);
}

.sh-cmp-input:focus {
    outline: none;
}

/* On a background the text centres and turns white, as in the design. */
.sh-cmp-write.has-bg {
    padding: var(--sh-sp-6) var(--sh-sp-5);
    min-height: 260px;
    display: flex;
    align-items: center;
}

.sh-cmp-write.has-bg .sh-cmp-input {
    min-height: auto;
    text-align: center;
    color: var(--sh-white);
    font-weight: var(--sh-fw-bold);
    font-size: var(--sh-fs-3xl);
}

.sh-cmp-write.has-bg .sh-cmp-input::placeholder {
    color: rgba(255, 255, 255, 0.8);
}

/* -- Tools row (Aa + emoji) ----------------------------------------------- */

.sh-cmp-tools {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--sh-sp-2) 0;
}

.sh-cmp-aa {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: var(--sh-radius-sm);
    background: var(--sh-brand-gradient);
    color: var(--sh-white);
    font-weight: var(--sh-fw-bold);
    font-size: var(--sh-fs-base);
    box-shadow: var(--sh-shadow-sm);
}

/* -- Emoji picker ---------------------------------------------------------- */

.sh-emoji {
    position: absolute;
    right: 0;
    bottom: calc(100% + 8px);
    z-index: 2;
    display: none;
    width: min(340px, 84vw);
    max-height: 300px;
    overflow-y: auto;
    padding: var(--sh-sp-3);
    background: var(--sh-surface);
    border: 1px solid var(--sh-border);
    border-radius: var(--sh-radius);
    box-shadow: var(--sh-shadow-lg);
}

.sh-emoji.is-open {
    display: block;
}

.sh-emoji-group {
    display: block;
    margin: var(--sh-sp-2) 0 6px;
    font-size: var(--sh-fs-xs);
    font-weight: var(--sh-fw-bold);
    color: var(--sh-text-muted);
}

.sh-emoji-grid {
    display: grid;
    grid-template-columns: repeat(8, 1fr);
    gap: 2px;
}

.sh-emoji-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 34px;
    border-radius: var(--sh-radius-xs);
    font-size: 20px;
    line-height: 1;
}

.sh-emoji-btn:hover {
    background: var(--sh-surface-sunken);
}

/* -- Extra field panels ----------------------------------------------------- */

/* A spaced column, not a plain block. The poll panel stacks four inputs
   and they sat flush, doubling their borders into one grey ladder. The
   visually-hidden labels between them are `position: absolute`, so they
   are out of flow and never claim a gap of their own. */
.sh-cmp-extra {
    display: flex;
    flex-direction: column;
    gap: var(--sh-sp-2);
    padding: var(--sh-sp-3);
    margin-bottom: var(--sh-sp-3);
    border: 1px solid var(--sh-border);
    border-radius: var(--sh-radius);
    background: var(--sh-surface-alt);
}

/* The gap supplies the spacing now, so the label must not add its own on
   top of it. */
.sh-cmp-extra > .sh-label {
    margin-bottom: 0;
}

.sh-cmp-extra > :is(.sh-help, .sh-error) {
    margin: 0;
}

.sh-cmp-types {
    display: none;
}

/* -- Add to your post -------------------------------------------------------- */

.sh-cmp-add {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sh-sp-3);
    padding: var(--sh-sp-2) var(--sh-sp-3);
    border: 1px solid var(--sh-border-strong);
    border-radius: var(--sh-radius);
    margin-bottom: var(--sh-sp-4);
}

.sh-cmp-add-label {
    font-size: var(--sh-fs-base);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text);
}

.sh-cmp-add-icons {
    display: flex;
    align-items: center;
    gap: 2px;
    flex-wrap: wrap;
}

.sh-cmp-add-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    color: var(--sh-text-muted);
    flex-shrink: 0;
}

button.sh-cmp-add-btn:hover {
    background: var(--sh-surface-sunken);
}

.sh-cmp-add-btn svg { width: 22px; height: 22px; }

.sh-cmp-add-btn.is-active {
    background: var(--sh-primary-50);
}

/* Icon tints, matching the reference design. */
.sh-cmp-tone-success { color: var(--sh-success-500); }
.sh-cmp-tone-primary { color: var(--sh-primary-600); }
.sh-cmp-tone-warning { color: var(--sh-warning-500); }
.sh-cmp-tone-danger { color: var(--sh-danger-500); }
.sh-cmp-tone-violet { color: var(--sh-violet-600); }
.sh-cmp-tone-teal { color: #14b8a6; }

/* Disabled until there is something to post. */
.sh-cmp-submit:disabled {
    background: var(--sh-surface-sunken);
    color: var(--sh-text-subtle);
    opacity: 1;
}

/* -- Audience screen ---------------------------------------------------------- */

.sh-cmp-subtitle {
    font-size: var(--sh-fs-lg);
    font-weight: var(--sh-fw-bold);
    color: var(--sh-text-strong);
    margin: 0;
}

.sh-cmp-note {
    margin: 4px 0 var(--sh-sp-4);
    font-size: var(--sh-fs-base);
    color: var(--sh-text-muted);
}

.sh-cmp-radios {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.sh-cmp-radio {
    display: flex;
    align-items: center;
    gap: var(--sh-sp-3);
    padding: var(--sh-sp-3);
    border-radius: var(--sh-radius-sm);
    cursor: pointer;
}

.sh-cmp-radio:hover {
    background: var(--sh-surface-sunken);
}

.sh-cmp-radio.is-active {
    background: var(--sh-primary-50);
}

.sh-cmp-radio input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
}

.sh-cmp-radio-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--sh-surface-sunken);
    color: var(--sh-text);
    flex-shrink: 0;
}

.sh-cmp-radio-icon svg { width: 18px; height: 18px; }

.sh-cmp-radio-title {
    display: block;
    font-size: var(--sh-fs-md);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text-strong);
}

.sh-cmp-radio-hint {
    display: block;
    font-size: var(--sh-fs-sm);
    color: var(--sh-text-muted);
}

.sh-cmp-dot {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    border: 2px solid var(--sh-gray-400);
    flex-shrink: 0;
    position: relative;
}

.sh-cmp-radio.is-active .sh-cmp-dot {
    border-color: var(--sh-primary-600);
    border-width: 6px;
}

/* -- More screen ---------------------------------------------------------------- */

.sh-cmp-more {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sh-sp-2);
}

.sh-cmp-more-item {
    display: flex;
    align-items: center;
    gap: var(--sh-sp-3);
    padding: var(--sh-sp-2);
    border-radius: var(--sh-radius-sm);
    font-size: var(--sh-fs-base);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text);
    text-align: start;
}

.sh-cmp-more-item:hover {
    background: var(--sh-surface-sunken);
}

/* -- Background picker ------------------------------------------------------------ */

.sh-cmp-group-label {
    display: block;
    margin-bottom: var(--sh-sp-3);
    font-size: var(--sh-fs-lg);
    font-weight: var(--sh-fw-bold);
    color: var(--sh-text-strong);
}

.sh-bg-grid {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: var(--sh-sp-2);
}

.sh-bg-swatch {
    aspect-ratio: 1 / 1;
    border-radius: var(--sh-radius);
    border: 2px solid transparent;
    box-shadow: inset 0 0 0 1px rgba(15, 23, 42, 0.08);
}

.sh-bg-swatch.is-active {
    border-color: var(--sh-primary-600);
}

.sh-bg-none {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--sh-surface-sunken);
    color: var(--sh-text-muted);
}

/* ==========================================================================
   Post backgrounds
   One class per key in config('socialhub.feed.post_backgrounds'). Used by
   both the composer swatches and the rendered post, so a gradient is
   declared exactly once.
   ========================================================================== */

.sh-bg-aurora { background: linear-gradient(135deg, #a78bfa 0%, #f0abfc 50%, #bae6fd 100%); }
.sh-bg-dusk { background: linear-gradient(135deg, #4f46e5 0%, #9333ea 55%, #db2777 100%); }
.sh-bg-sand { background: linear-gradient(135deg, #fde68a 0%, #d6bfa3 60%, #a8836a 100%); }
.sh-bg-rose { background: linear-gradient(135deg, #fb7185 0%, #be123c 100%); }
.sh-bg-midnight { background: linear-gradient(135deg, #0f172a 0%, #1e293b 60%, #334155 100%); }
.sh-bg-mint { background: linear-gradient(135deg, #6ee7b7 0%, #14b8a6 100%); }
.sh-bg-citrus { background: linear-gradient(135deg, #fde047 0%, #f59e0b 100%); }
.sh-bg-berry { background: linear-gradient(135deg, #c026d3 0%, #7c3aed 100%); }
.sh-bg-ocean { background: linear-gradient(135deg, #38bdf8 0%, #2563eb 100%); }
.sh-bg-ember { background: linear-gradient(135deg, #fb923c 0%, #ef4444 60%, #7f1d1d 100%); }

/* A post rendered on its background. */
.sh-post-bg {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 280px;
    padding: var(--sh-sp-8) var(--sh-sp-6);
    text-align: center;
    color: var(--sh-white);
    font-size: var(--sh-fs-2xl);
    font-weight: var(--sh-fw-bold);
    line-height: var(--sh-lh-snug);
    overflow-wrap: anywhere;
}

@media (min-width: 768px) {
    .sh-post-bg {
        font-size: var(--sh-fs-3xl);
    }
}

/* AI disclosure badge on a post. */
.sh-ai-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-inline-start: 6px;
    padding: 2px 7px;
    border-radius: var(--sh-radius-pill);
    background: var(--sh-gray-900);
    color: var(--sh-white);
    font-size: var(--sh-fs-2xs);
    font-weight: var(--sh-fw-bold);
}

.sh-ai-badge svg { width: 11px; height: 11px; }

/* ==========================================================================
   Story viewer
   Full-screen overlay stepping through the story rail.
   ========================================================================== */

.sh-sv {
    position: fixed;
    inset: 0;
    z-index: var(--sh-z-modal);
    display: none;
    align-items: center;
    justify-content: center;
    padding: 0;
}

.sh-sv.is-open {
    display: flex;
}

.sh-sv-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(8, 12, 24, 0.94);
}

.sh-sv-shell {
    position: relative;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}

.sh-sv-frame {
    position: relative;
    width: 100%;
    height: 100%;
    max-width: none;
    display: flex;
    flex-direction: column;
    background: var(--sh-gray-900);
    /* Deliberately NOT overflow:hidden — the desktop prev/next arrows sit
       outside the frame and would be clipped. The stage clips instead. */
}

/* -- Progress bars -------------------------------------------------------- */

.sh-sv-progress {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 3;
    display: flex;
    gap: 4px;
    padding: var(--sh-sp-3) var(--sh-sp-3) 0;
}

.sh-sv-bar {
    flex: 1 1 0;
    height: 3px;
    border-radius: var(--sh-radius-pill);
    background: rgba(255, 255, 255, 0.32);
    overflow: hidden;
}

.sh-sv-bar-fill {
    display: block;
    height: 100%;
    width: 0;
    border-radius: var(--sh-radius-pill);
    background: var(--sh-white);
}

.sh-sv-bar.is-done .sh-sv-bar-fill {
    width: 100%;
}

.sh-sv-bar.is-live .sh-sv-bar-fill {
    animation: sh-sv-fill linear forwards;
}

/* Pausing freezes the bar where it is. */
.sh-sv-frame.is-paused .sh-sv-bar.is-live .sh-sv-bar-fill {
    animation-play-state: paused;
}

@keyframes sh-sv-fill {
    from { width: 0; }
    to { width: 100%; }
}

/* -- Header ---------------------------------------------------------------- */

.sh-sv-head {
    position: absolute;
    top: var(--sh-sp-5);
    left: 0;
    right: 0;
    z-index: 3;
    display: flex;
    align-items: center;
    gap: var(--sh-sp-3);
    padding: var(--sh-sp-2) var(--sh-sp-3);
}

.sh-sv-name {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: var(--sh-fs-md);
    font-weight: var(--sh-fw-bold);
    color: var(--sh-white);
}

.sh-sv-name .sh-verified { color: var(--sh-white); }

.sh-sv-time {
    display: block;
    font-size: var(--sh-fs-xs);
    color: rgba(255, 255, 255, 0.75);
}

.sh-sv-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    color: var(--sh-white);
    flex-shrink: 0;
}

.sh-sv-icon:hover {
    background: rgba(255, 255, 255, 0.16);
    color: var(--sh-white);
}

.sh-sv-icon svg { width: 20px; height: 20px; }

/* -- Stage ------------------------------------------------------------------ */

.sh-sv-stage {
    position: relative;
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 0;
    overflow: hidden;
}

.sh-sv-media {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}

/* The sound toggle shows one glyph or the other. Both are in the
   markup and the class chooses, so the script never writes markup. */
.sh-sv-sound .sh-sv-sound-on,
.sh-sv-sound.is-on .sh-sv-sound-off {
    display: none;
}

.sh-sv-sound.is-on .sh-sv-sound-on {
    display: inline-flex;
}

/* A <video> needs real dimensions here. `max-*` caps an element and
   never grows one, and a video box defaults to 300x150 — so with the
   image rules alone a story clip sat as a small rectangle in the middle
   of the frame. Same trap the photo theatre hit with `<img>`. */
video.sh-sv-media {
    width: 100%;
    height: 100%;
}

.sh-sv-caption {
    position: absolute;
    left: var(--sh-sp-4);
    right: var(--sh-sp-4);
    bottom: var(--sh-sp-5);
    z-index: 2;
    margin: 0;
    padding: var(--sh-sp-3);
    border-radius: var(--sh-radius);
    background: rgba(8, 12, 24, 0.55);
    color: var(--sh-white);
    text-align: center;
    font-size: var(--sh-fs-md);
}

/* Invisible tap targets covering each half of the stage. */
.sh-sv-zone {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 35%;
    z-index: 1;
    background: transparent;
    border: 0;
    cursor: pointer;
}

.sh-sv-zone-prev { left: 0; }
.sh-sv-zone-next { right: 0; width: 65%; }
.sh-sv-zone:disabled { cursor: default; }

/* -- Footer ------------------------------------------------------------------ */

.sh-sv-foot {
    position: relative;
    z-index: 3;
    display: flex;
    align-items: center;
    gap: var(--sh-sp-2);
    padding: var(--sh-sp-3) var(--sh-sp-4) var(--sh-sp-5);
}

.sh-sv-reply {
    flex: 1 1 auto;
    min-width: 0;
}

.sh-sv-reply .sh-input {
    border-radius: var(--sh-radius-pill);
    background: rgba(255, 255, 255, 0.14);
    border-color: rgba(255, 255, 255, 0.35);
    color: var(--sh-white);
}

.sh-sv-reply .sh-input::placeholder {
    color: rgba(255, 255, 255, 0.7);
}

.sh-sv-views {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--sh-white);
    font-size: var(--sh-fs-sm);
    font-weight: var(--sh-fw-semibold);
}

.sh-sv-views svg { width: 16px; height: 16px; }

/* -- Desktop arrows ------------------------------------------------------------ */

.sh-sv-arrow {
    display: none;
}

/* ==========================================================================
   Story frame durations
   The bar animates in CSS, so each supported length needs its own class —
   the composer clamps `feed.story_duration` into this range.
   ========================================================================== */

.sh-sv-d3 .sh-sv-bar.is-live .sh-sv-bar-fill { animation-duration: 3s; }
.sh-sv-d4 .sh-sv-bar.is-live .sh-sv-bar-fill { animation-duration: 4s; }
.sh-sv-d5 .sh-sv-bar.is-live .sh-sv-bar-fill { animation-duration: 5s; }
.sh-sv-d6 .sh-sv-bar.is-live .sh-sv-bar-fill { animation-duration: 6s; }
.sh-sv-d7 .sh-sv-bar.is-live .sh-sv-bar-fill { animation-duration: 7s; }
.sh-sv-d8 .sh-sv-bar.is-live .sh-sv-bar-fill { animation-duration: 8s; }
.sh-sv-d9 .sh-sv-bar.is-live .sh-sv-bar-fill { animation-duration: 9s; }
.sh-sv-d10 .sh-sv-bar.is-live .sh-sv-bar-fill { animation-duration: 10s; }
.sh-sv-d11 .sh-sv-bar.is-live .sh-sv-bar-fill { animation-duration: 11s; }
.sh-sv-d12 .sh-sv-bar.is-live .sh-sv-bar-fill { animation-duration: 12s; }
.sh-sv-d13 .sh-sv-bar.is-live .sh-sv-bar-fill { animation-duration: 13s; }
.sh-sv-d14 .sh-sv-bar.is-live .sh-sv-bar-fill { animation-duration: 14s; }
.sh-sv-d15 .sh-sv-bar.is-live .sh-sv-bar-fill { animation-duration: 15s; }

@media (min-width: 768px) {
    .sh-sv {
        padding: var(--sh-sp-6);
    }

    .sh-sv-frame {
        width: min(440px, 100%);
        height: min(92vh, 860px);
        border-radius: var(--sh-radius-xl);
        box-shadow: var(--sh-shadow-lg);
    }

    .sh-sv-arrow {
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
        z-index: 4;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 44px;
        height: 44px;
        border-radius: 50%;
        background: var(--sh-surface);
        color: var(--sh-text);
        box-shadow: var(--sh-shadow-md);
    }

    .sh-sv-arrow svg { width: 22px; height: 22px; }

    .sh-sv-arrow-prev { left: calc(-1 * var(--sh-sp-12)); }
    .sh-sv-arrow-next { right: calc(-1 * var(--sh-sp-12)); }
}

/* ==========================================================================
   Photo theatre
   Phone: image on top, conversation below. Desktop: dark stage on the left,
   a fixed-width conversation panel on the right.
   ========================================================================== */

.sh-photo-overlay {
    position: fixed;
    inset: 0;
    z-index: var(--sh-z-modal);
    display: none;
    background: var(--sh-gray-900);
}

.sh-photo-overlay.is-open {
    display: block;
}

/* The fetched markup lands in a plain wrapper; without a height of its own
   the theatre's `height: 100%` resolves against auto and collapses. */
.sh-photo-overlay > * {
    height: 100%;
}

.sh-pt {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
    overflow-y: auto;
}

/* -- Stage ---------------------------------------------------------------- */

/* On a phone the stage hugs the photo. A `min-height` floor here padded
   every landscape shot with a band of backdrop above and below — 52vh is
   439px on a 844px screen, where a 4:3 photo only needs 293px, and that
   band reads as a border rather than as a stage. Desktop is different:
   there the stage is a real column with its own height. */
.sh-pt-stage {
    position: relative;
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--sh-media-backdrop);
    overflow: hidden;
}

.sh-pt-canvas {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    transition: transform var(--sh-dur) var(--sh-ease);
}

/* The image fills the stage and `contain` fits it inside — `max-width` /
   `max-height` only *cap* an <img>, they never grow one, so a photo
   smaller than the stage sat at its natural size in the middle of a black
   field. A 1200x900 photo on a 1560x1150 stage left 180px of backdrop
   down each side and 125px top and bottom, which read as a broken viewer
   rather than a letterbox. Whatever is left now is a real aspect
   difference. */
.sh-pt-img {
    width: 100%;
    /* Height follows the photo on a phone, capped so a tall portrait does
       not push the conversation off the screen entirely. */
    height: auto;
    max-height: 70vh;
    object-fit: contain;
}

/* A video on the stage sizes like the still it replaces. */
.sh-pt-video {
    width: 100%;
    height: auto;
    max-height: 70vh;
    object-fit: contain;
    display: block;
}

/* Stepped zoom. Discrete classes rather than an inline transform, so the
   scale values stay in the stylesheet. */
.sh-pt-z1 { transform: scale(1); }
.sh-pt-z2 { transform: scale(1.5); }
.sh-pt-z3 { transform: scale(2); }
.sh-pt-z4 { transform: scale(3); }

.sh-pt-z2,
.sh-pt-z3,
.sh-pt-z4 {
    cursor: grab;
}

.sh-pt-tools {
    position: absolute;
    top: var(--sh-sp-3);
    z-index: 3;
    display: flex;
    gap: var(--sh-sp-2);
}

.sh-pt-tools-start { left: var(--sh-sp-3); }
.sh-pt-tools-end { right: var(--sh-sp-3); }

/* Dark scrim, not a light one: these sit over the photo, which is often a
   bright sky at the top of the frame. */
.sh-pt-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: rgba(8, 12, 24, 0.55);
    color: var(--sh-white);
    flex-shrink: 0;
    backdrop-filter: blur(4px);
}

.sh-pt-icon:hover {
    background: rgba(8, 12, 24, 0.78);
    color: var(--sh-white);
}

.sh-pt-icon svg { width: 20px; height: 20px; }

.sh-pt-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 3;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: rgba(8, 12, 24, 0.55);
    color: var(--sh-white);
    backdrop-filter: blur(4px);
}

.sh-pt-nav:hover {
    background: rgba(8, 12, 24, 0.78);
    color: var(--sh-white);
}

.sh-pt-nav svg { width: 24px; height: 24px; }

.sh-pt-nav-prev { left: var(--sh-sp-3); }
.sh-pt-nav-next { right: var(--sh-sp-3); }

.sh-pt-count {
    position: absolute;
    bottom: var(--sh-sp-3);
    left: 50%;
    transform: translateX(-50%);
    z-index: 3;
    padding: 4px 12px;
    border-radius: var(--sh-radius-pill);
    background: rgba(8, 12, 24, 0.7);
    color: var(--sh-white);
    font-size: var(--sh-fs-xs);
    font-weight: var(--sh-fw-semibold);
}

/* -- Side panel ------------------------------------------------------------ */

.sh-pt-side {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    background: var(--sh-surface);
}

.sh-pt-comments {
    flex: 1 1 auto;
    padding: var(--sh-sp-2) var(--sh-sp-4);
    overflow-y: auto;
}

.sh-pt-compose {
    flex-shrink: 0;
    padding: var(--sh-sp-3) var(--sh-sp-4);
    border-top: 1px solid var(--sh-border);
    background: var(--sh-surface);
}

@media (min-width: 1024px) {
    .sh-pt {
        flex-direction: row;
        overflow: hidden;
    }

    .sh-pt-stage {
        flex: 1 1 auto;
        min-height: 0;
        height: 100%;
    }

    /* The stage is now a sized column, so the photo fills it and
       `contain` fits it inside. `max-width` / `max-height` only cap an
       <img> — they never grow one, which is why a photo smaller than the
       stage used to sit at its natural size in a field of backdrop. */
    .sh-pt-canvas {
        height: 100%;
    }

    .sh-pt-img,
    .sh-pt-video {
        height: 100%;
        max-height: none;
    }

    .sh-pt-side {
        flex: 0 0 var(--sh-photo-side-w, 396px);
        width: var(--sh-photo-side-w, 396px);
        height: 100%;
        overflow-y: auto;
        border-inline-start: 1px solid var(--sh-border);
    }
}

@media (min-width: 1440px) {
    .sh-pt-side {
        --sh-photo-side-w: 440px;
    }
}

/* ==========================================================================
   Comment tools — like, reply, nested replies
   ========================================================================== */

.sh-comment-tool {
    font: inherit;
    color: inherit;
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
}

.sh-comment-tool:hover {
    text-decoration: underline;
    color: var(--sh-text);
}

.sh-comment-tool.is-active {
    color: var(--sh-primary-600);
    font-weight: var(--sh-fw-bold);
}

/* Running like tally beside the tools; hidden while the count is zero. */
.sh-comment-likes {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 1px 7px;
    border-radius: var(--sh-radius-pill);
    background: var(--sh-surface-sunken);
    color: var(--sh-primary-600);
    font-size: var(--sh-fs-2xs);
    font-weight: var(--sh-fw-bold);
}

.sh-comment-likes svg {
    width: 11px;
    height: 11px;
}

/* Replies indent under their parent. */
.sh-comment-replies:not(:empty) {
    margin-top: var(--sh-sp-2);
    padding-inline-start: var(--sh-sp-4);
    border-inline-start: 2px solid var(--sh-border);
}

.sh-comment-reply {
    display: flex;
    align-items: flex-start;
    gap: var(--sh-sp-2);
    margin-top: var(--sh-sp-2);
    padding-inline-start: var(--sh-sp-4);
}

.sh-comment-reply .sh-textarea {
    min-height: 34px;
    padding-block: 6px;
    font-size: var(--sh-fs-sm);
}

/* ==========================================================================
   Header search — submit button and type-ahead panel
   ========================================================================== */

/* The magnifier is now a real submit control, not decoration. */
.sh-search-submit {
    position: absolute;
    left: 5px;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    color: var(--sh-text-subtle);
    cursor: pointer;
}

.sh-search-submit:hover {
    background: var(--sh-gray-150);
    color: var(--sh-text);
}

.sh-search-submit svg { width: 17px; height: 17px; }

.sh-suggest {
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + 8px);
    z-index: var(--sh-z-header);
    display: none;
    max-height: 70vh;
    overflow-y: auto;
    padding: var(--sh-sp-2);
    background: var(--sh-surface);
    border: 1px solid var(--sh-border);
    border-radius: var(--sh-radius);
    box-shadow: var(--sh-shadow-lg);
}

.sh-suggest.is-open {
    display: block;
}

.sh-suggest-label {
    margin: var(--sh-sp-2) var(--sh-sp-2) 4px;
    font-size: var(--sh-fs-2xs);
    font-weight: var(--sh-fw-bold);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--sh-text-subtle);
}

.sh-suggest-item {
    display: flex;
    align-items: center;
    gap: var(--sh-sp-3);
    padding: var(--sh-sp-2);
    border-radius: var(--sh-radius-xs);
    color: var(--sh-text);
}

.sh-suggest-item:hover,
.sh-suggest-item.is-active {
    background: var(--sh-surface-sunken);
    color: var(--sh-text);
}

.sh-suggest-glyph {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--sh-primary-50);
    color: var(--sh-primary-600);
    font-weight: var(--sh-fw-bold);
    flex-shrink: 0;
}

.sh-suggest-body {
    min-width: 0;
    flex: 1 1 auto;
}

.sh-suggest-title {
    display: block;
    font-size: var(--sh-fs-base);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text-strong);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sh-suggest-meta {
    display: block;
    font-size: var(--sh-fs-xs);
    color: var(--sh-text-muted);
}

.sh-suggest-all {
    display: block;
    margin-top: 4px;
    padding: var(--sh-sp-3) var(--sh-sp-2);
    border-top: 1px solid var(--sh-border);
    font-size: var(--sh-fs-sm);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-primary-600);
    text-align: center;
    border-radius: var(--sh-radius-xs);
}

.sh-suggest-all:hover,
.sh-suggest-all.is-active {
    background: var(--sh-primary-50);
}

.sh-suggest-empty {
    margin: 0;
    padding: var(--sh-sp-4);
    text-align: center;
    font-size: var(--sh-fs-sm);
    color: var(--sh-text-muted);
}

/* ==========================================================================
   Infinite scroll
   ========================================================================== */

.sh-stream {
    display: flex;
    flex-direction: column;
    gap: var(--sh-sp-4);
}

.sh-stream-more {
    position: relative;
    padding: var(--sh-sp-2) 0 var(--sh-sp-6);
}

/* While a page is in flight the manual link steps aside for the spinner. */
.sh-stream-more.is-loading [data-sh-stream-link] {
    visibility: hidden;
}

.sh-stream-spinner {
    display: none;
    position: absolute;
    left: 50%;
    top: var(--sh-sp-3);
    width: 26px;
    height: 26px;
    margin-inline-start: -13px;
    border-radius: 50%;
    border: 3px solid var(--sh-border);
    border-top-color: var(--sh-primary-600);
    animation: sh-spin 700ms linear infinite;
}

.sh-stream-more.is-loading .sh-stream-spinner {
    display: block;
}

@keyframes sh-spin {
    to { transform: rotate(360deg); }
}

.sh-stream-end {
    margin: 0;
    padding: var(--sh-sp-4) 0;
    text-align: center;
    font-size: var(--sh-fs-sm);
    color: var(--sh-text-subtle);
}

@media (min-width: 1024px) {
    .sh-stream {
        gap: var(--sh-sp-5);
    }
}

/* ==========================================================================
   Sponsored placements
   ========================================================================== */

.sh-ad-flag {
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text-muted);
}

.sh-ad-media {
    display: block;
    background: var(--sh-surface-sunken);
}

.sh-ad-media img {
    width: 100%;
    max-height: 340px;
    object-fit: cover;
}

.sh-ad-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sh-sp-3);
    padding: var(--sh-sp-3) var(--sh-sp-4);
    background: var(--sh-surface-alt);
    border-top: 1px solid var(--sh-border);
}

.sh-ad-foot-label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--sh-fs-sm);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text-strong);
}

/* ==========================================================================
   Connected accounts — Settings → Security

   A self-contained block: base rules first, then this feature's own media
   query, so nothing here can be beaten by a widened rule further up.
   ========================================================================== */

.sh-conn-row {
    flex-wrap: wrap;
    row-gap: var(--sh-sp-2);
}

/* In a wrapping flex row an item whose basis is wider than the space left
   moves to the next line instead of shrinking, so a long address pushed
   the whole text block below the logo while a short one stayed beside it.
   A zero basis makes it shrink, and the rows line up the same either way. */
.sh-conn-row > .sh-list-row-body {
    flex: 1 1 0;
}

/* The provider's own logo on a tile, matching the admin cards. A brand mark
   keeps its real colours, so the tile supplies the contrast. */
.sh-conn-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 38px;
    height: 38px;
    border-radius: var(--sh-radius-sm);
    border: 1px solid var(--sh-border);
    background: var(--sh-surface);
}

.sh-conn-mark svg {
    width: 20px;
    height: 20px;
}

/* Black marks vanish against a dark surface, so the tile goes white
   instead of the logo being recoloured. */
[data-sh-theme='dark'] .sh-conn-mark-apple,
[data-sh-theme='dark'] .sh-conn-mark-twitter,
[data-sh-theme='dark'] .sh-conn-mark-github {
    background: var(--sh-white);
}

/* On a phone the action drops under the row rather than squeezing the
   provider name into two characters, lining up under the text rather than
   the logo. The indent is padding, not margin: a `flex-basis: 100%` box
   plus an outside margin is wider than the row and overflows the card. */
.sh-conn-action {
    flex: 1 0 100%;
    padding-inline-start: calc(38px + var(--sh-sp-3));
}

/* The held-back badge is a label, not a full-width control. */
span.sh-conn-action {
    align-self: flex-start;
    width: fit-content;
    flex-basis: auto;
    padding-inline-start: 0;
    margin-inline-start: calc(38px + var(--sh-sp-3));
}

.sh-conn-add {
    margin-top: var(--sh-sp-3);
    padding-top: var(--sh-sp-3);
    border-top: 1px solid var(--sh-border);
}

.sh-conn-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sh-sp-2);
}

.sh-conn-buttons svg {
    width: 16px;
    height: 16px;
}

@media (min-width: 480px) {
    .sh-conn-row {
        flex-wrap: nowrap;
    }

    .sh-conn-action,
    span.sh-conn-action {
        flex: 0 0 auto;
        padding-inline-start: 0;
        margin-inline-start: 0;
    }
}

/* ==========================================================================
   Live video
   SocialHub does not broadcast; a live post embeds the stream the author
   is running on a platform that does. The badge is the honest part: it
   says "Live now" only while the author has not ended it.
   ========================================================================== */

.sh-live {
    display: flex;
    flex-direction: column;
    gap: var(--sh-sp-3);
    padding: 0 var(--sh-sp-4) var(--sh-sp-3);
}

.sh-live-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sh-sp-2);
}

.sh-live-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px var(--sh-sp-2);
    border-radius: var(--sh-radius-pill);
    background: var(--sh-surface-sunken);
    color: var(--sh-text-muted);
    font-size: var(--sh-fs-2xs);
    font-weight: var(--sh-fw-bold);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.sh-live-badge.is-on {
    background: var(--sh-danger-500);
    /* Fixed white, like every other badge that sits on a solid fill. */
    color: var(--sh-white);
}

.sh-live-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: currentColor;
}

/* Only while it is actually live — a pulsing dot on a finished stream
   would keep claiming something that has stopped. */
.sh-live-badge.is-on .sh-live-dot {
    animation: sh-live-pulse 1.6s ease-in-out infinite;
}

@keyframes sh-live-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.35; }
}

.sh-live-provider,
.sh-live-when {
    font-size: var(--sh-fs-xs);
    color: var(--sh-text-muted);
}

.sh-live-frame {
    position: relative;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: var(--sh-radius);
    background: var(--sh-media-backdrop);
}

.sh-live-frame iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

.sh-live-plain {
    display: flex;
    align-items: center;
    gap: var(--sh-sp-2);
    margin: 0;
    font-size: var(--sh-fs-sm);
}

.sh-live-plain svg {
    width: 16px;
    height: 16px;
    color: var(--sh-text-muted);
}

.sh-live-end {
    margin: 0;
}

@media (prefers-reduced-motion: reduce) {
    .sh-live-badge.is-on .sh-live-dot {
        animation: none;
    }
}

/* A browser broadcast, rather than an embedded third-party player. The
   <video> is fed by MediaSource, so it has no src of its own until the
   first segment lands. */
.sh-live-native video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    background: var(--sh-media-backdrop);
}

/* Says why nothing is playing yet, instead of a black rectangle. */
.sh-live-note {
    position: absolute;
    inset-inline: 0;
    inset-block-end: var(--sh-sp-3);
    margin: 0;
    padding: 0 var(--sh-sp-3);
    text-align: center;
    color: var(--sh-white);
    font-size: var(--sh-fs-sm);
    text-shadow: 0 1px 3px rgb(0 0 0 / 60%);
    pointer-events: none;
}
