/* ==========================================================================
   SocialHub — Components
   Shared vocabulary for every surface (public, user panel, admin).
   The admin shell re-maps --sh-primary-* so these pick up its scheme free.
   ========================================================================== */

/* ==========================================================================
   Card
   ========================================================================== */

.sh-card {
    background: var(--sh-surface);
    border: 1px solid var(--sh-border);
    border-radius: var(--sh-radius-lg);
    box-shadow: var(--sh-shadow-sm);
    overflow: hidden;
}

.sh-card-flat {
    box-shadow: none;
}

.sh-card-pad {
    padding: var(--sh-sp-4);
}

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

.sh-card-head-plain {
    border-bottom: 0;
    padding-bottom: 0;
}

.sh-card-title {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: var(--sh-fs-lg);
    font-weight: var(--sh-fw-bold);
    color: var(--sh-text-strong);
    margin: 0;
}

/* An <x-icon> carries no width of its own, so without this it inflates to
   fill the heading and pushes the label onto its own line. */
.sh-card-title > svg {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
}

.sh-card-sub {
    font-size: var(--sh-fs-xs);
    color: var(--sh-text-muted);
    margin: 2px 0 0;
}

.sh-card-body {
    padding: var(--sh-sp-4);
}

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

/* "See All" style link that sits opposite a card title */
.sh-card-link {
    font-size: var(--sh-fs-sm);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-primary-600);
    white-space: nowrap;
}

/* ==========================================================================
   Buttons
   ========================================================================== */

.sh-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sh-sp-2);
    padding: 0 var(--sh-sp-4);
    height: 40px;
    border-radius: var(--sh-radius-sm);
    font-size: var(--sh-fs-base);
    font-weight: var(--sh-fw-semibold);
    line-height: 1;
    white-space: nowrap;
    border: 1px solid transparent;
    cursor: pointer;
    transition: background var(--sh-dur-fast) var(--sh-ease),
        color var(--sh-dur-fast) var(--sh-ease),
        border-color var(--sh-dur-fast) var(--sh-ease),
        box-shadow var(--sh-dur-fast) var(--sh-ease),
        transform var(--sh-dur-fast) var(--sh-ease);
}

.sh-btn:active {
    transform: translateY(1px);
}

.sh-btn:disabled,
.sh-btn.is-disabled {
    opacity: 0.55;
    cursor: not-allowed;
    transform: none;
}

.sh-btn svg {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
}

/* -- Variants ------------------------------------------------------------ */

.sh-btn-primary {
    background: var(--sh-primary-600);
    color: var(--sh-text-inverse);
}

.sh-btn-primary:hover {
    background: var(--sh-primary-700);
    color: var(--sh-text-inverse);
}

.sh-btn-gradient {
    background: var(--sh-brand-gradient);
    color: var(--sh-text-inverse);
    border: 0;
}

.sh-btn-gradient:hover {
    color: var(--sh-text-inverse);
    filter: brightness(1.06);
}

.sh-btn-secondary {
    background: var(--sh-primary-50);
    color: var(--sh-primary-700);
}

.sh-btn-secondary:hover {
    background: var(--sh-primary-100);
    color: var(--sh-primary-800);
}

.sh-btn-outline {
    background: var(--sh-surface);
    color: var(--sh-text);
    border-color: var(--sh-border-strong);
}

.sh-btn-outline:hover {
    background: var(--sh-surface-alt);
    border-color: var(--sh-gray-400);
    color: var(--sh-text);
}

.sh-btn-outline-primary {
    background: var(--sh-surface);
    color: var(--sh-primary-600);
    border-color: var(--sh-primary-600);
}

.sh-btn-outline-primary:hover {
    background: var(--sh-primary-50);
    color: var(--sh-primary-700);
}

.sh-btn-ghost {
    background: transparent;
    color: var(--sh-text-muted);
}

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

.sh-btn-success {
    background: var(--sh-success-500);
    color: var(--sh-text-inverse);
}

.sh-btn-success:hover {
    background: var(--sh-success-600);
    color: var(--sh-text-inverse);
}

.sh-btn-danger {
    background: var(--sh-danger-500);
    color: var(--sh-text-inverse);
}

.sh-btn-danger:hover {
    background: var(--sh-danger-600);
    color: var(--sh-text-inverse);
}

.sh-btn-danger-soft {
    background: var(--sh-danger-50);
    color: var(--sh-danger-600);
    border-color: var(--sh-danger-100);
}

.sh-btn-danger-soft:hover {
    background: var(--sh-danger-100);
    color: var(--sh-danger-700);
}

/* -- Sizes --------------------------------------------------------------- */

.sh-btn-xs {
    height: 28px;
    padding: 0 var(--sh-sp-2);
    font-size: var(--sh-fs-xs);
    border-radius: var(--sh-radius-xs);
}

.sh-btn-xs svg { width: 14px; height: 14px; }

.sh-btn-sm {
    height: 34px;
    padding: 0 var(--sh-sp-3);
    font-size: var(--sh-fs-sm);
}

.sh-btn-sm svg { width: 16px; height: 16px; }

.sh-btn-lg {
    height: 48px;
    padding: 0 var(--sh-sp-6);
    font-size: var(--sh-fs-md);
    border-radius: var(--sh-radius);
}

.sh-btn-block {
    width: 100%;
}

.sh-btn-pill {
    border-radius: var(--sh-radius-pill);
}

/* Square icon-only button */
.sh-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: var(--sh-radius-sm);
    color: var(--sh-text-muted);
    background: transparent;
    border: 1px solid transparent;
    flex-shrink: 0;
    transition: background var(--sh-dur-fast) var(--sh-ease),
        color var(--sh-dur-fast) var(--sh-ease);
}

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

.sh-icon-btn svg { width: 19px; height: 19px; }

.sh-icon-btn-sm {
    width: 32px;
    height: 32px;
}

.sh-icon-btn-sm svg { width: 16px; height: 16px; }

.sh-icon-btn-bordered {
    border-color: var(--sh-border);
    background: var(--sh-surface);
}

.sh-icon-btn-soft {
    background: var(--sh-surface-sunken);
}

/* Circular floating action button (mobile tab bar centre) */
.sh-fab {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: var(--sh-primary-600);
    color: var(--sh-text-inverse);
    box-shadow: 0 6px 18px rgba(29, 106, 240, 0.4);
}

.sh-fab svg { width: 26px; height: 26px; }

/* ==========================================================================
   Avatar
   ========================================================================== */

.sh-avatar {
    position: relative;
    display: inline-block;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    overflow: hidden;
    flex-shrink: 0;
    background: var(--sh-surface-sunken);
}

.sh-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* An avatar carrying a presence dot crops the photo itself instead of
   clipping its children.
   `overflow: hidden` is what rounds the picture, and it also clipped the
   dot — which sits in the *corner* of a box the rounding has already cut
   away, so the dot was invisible on every page that drew one. The markup
   had been there from the start and never showed a pixel. */
.sh-avatar:has(.sh-presence) {
    overflow: visible;
}

.sh-avatar:has(.sh-presence) > img {
    border-radius: inherit;
}

.sh-avatar-xs { width: 24px; height: 24px; }
.sh-avatar-sm { width: 32px; height: 32px; }
.sh-avatar-md { width: 44px; height: 44px; }
.sh-avatar-lg { width: 56px; height: 56px; }
.sh-avatar-xl { width: 80px; height: 80px; }
.sh-avatar-2xl { width: 112px; height: 112px; }

.sh-avatar-square {
    border-radius: var(--sh-radius-sm);
}

.sh-avatar-ring {
    box-shadow: 0 0 0 2px var(--sh-surface), 0 0 0 4px var(--sh-primary-500);
}

/* Gradient story ring — wraps the avatar, not the image */
.sh-avatar-story {
    padding: 2.5px;
    border-radius: 50%;
    background: var(--sh-brand-gradient);
    display: inline-block;
    line-height: 0;
}

.sh-avatar-story .sh-avatar {
    box-shadow: 0 0 0 2.5px var(--sh-surface);
}

.sh-avatar-story-seen {
    background: var(--sh-gray-300);
}

/* Presence dot. The state classes are named in
   `config('socialhub.presence.states')` — add a state there and its
   class has to exist here, or the dot falls back to the grey below. */
.sh-presence {
    position: absolute;
    /* Inset by a proportion, not pinned to the corner: the corner of a
       circular avatar is empty space, so `right: 0` left the dot
       floating diagonally off the photo. 5% puts its centre on the
       circle's edge at every avatar size. Logical, so it mirrors in
       RTL with the rest of the layout. */
    inset-inline-end: 5%;
    bottom: 5%;
    width: 11px;
    height: 11px;
    border-radius: 50%;
    border: 2px solid var(--sh-surface);
    background: var(--sh-gray-400);
}

.sh-presence-online { background: var(--sh-success-500); }
.sh-presence-away { background: var(--sh-warning-500); }
.sh-presence-offline { background: var(--sh-danger-500); }

/* Riding in a line of text ("Online now") rather than pinned to the
   corner of an avatar, so it drops the absolute position and the ring
   that separates it from a photo. */
.sh-presence-inline {
    position: static;
    display: inline-block;
    width: 8px;
    height: 8px;
    border: 0;
}

/* The words beside an inline dot. They used to be painted green by the
   container, which was only ever correct while "Online" was the one
   state that could be rendered. */
.sh-presence-status-online { color: var(--sh-success-600); }
.sh-presence-status-away { color: var(--sh-warning-600); }
.sh-presence-status-offline { color: var(--sh-text-muted); }

/* Overlapping avatar pile ("+12K members") */
.sh-avatar-stack {
    display: inline-flex;
    align-items: center;
}

.sh-avatar-stack .sh-avatar {
    border: 2px solid var(--sh-surface);
    margin-inline-start: -8px;
}

.sh-avatar-stack .sh-avatar:first-child {
    margin-inline-start: 0;
}

.sh-avatar-stack-count {
    margin-inline-start: var(--sh-sp-2);
    font-size: var(--sh-fs-xs);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-primary-600);
    background: var(--sh-primary-50);
    border-radius: var(--sh-radius-pill);
    padding: 2px 8px;
}

/* ==========================================================================
   Badge / pill / chip
   ========================================================================== */

.sh-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 9px;
    border-radius: var(--sh-radius-pill);
    font-size: var(--sh-fs-xs);
    font-weight: var(--sh-fw-semibold);
    line-height: 1.4;
    white-space: nowrap;
}

.sh-badge-primary { background: var(--sh-primary-50); color: var(--sh-primary-700); }
.sh-badge-violet { background: var(--sh-violet-50); color: var(--sh-violet-700); }
.sh-badge-pink { background: var(--sh-pink-50); color: var(--sh-pink-600); }
.sh-badge-success { background: var(--sh-success-50); color: var(--sh-success-700); }
.sh-badge-warning { background: var(--sh-warning-50); color: var(--sh-warning-700); }
.sh-badge-danger { background: var(--sh-danger-50); color: var(--sh-danger-700); }
.sh-badge-neutral { background: var(--sh-gray-100); color: var(--sh-gray-600); }
.sh-badge-solid { background: var(--sh-primary-600); color: var(--sh-text-inverse); }
.sh-badge-square { border-radius: var(--sh-radius-xs); }

/* Small red count bubble on nav icons */
.sh-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: var(--sh-radius-pill);
    background: var(--sh-danger-500);
    color: var(--sh-text-inverse);
    font-size: var(--sh-fs-2xs);
    font-weight: var(--sh-fw-bold);
    line-height: 1;
}

.sh-count-float {
    position: absolute;
    top: -3px;
    right: -5px;
    border: 2px solid var(--sh-surface);
    height: 20px;
    min-width: 20px;
}

/* Filter chips — the scrolling "All / Trending / People" rails */
.sh-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 36px;
    padding: 0 var(--sh-sp-4);
    border-radius: var(--sh-radius-pill);
    background: var(--sh-surface-sunken);
    color: var(--sh-text-muted);
    font-size: var(--sh-fs-sm);
    font-weight: var(--sh-fw-semibold);
    white-space: nowrap;
    border: 1px solid transparent;
    transition: background var(--sh-dur-fast) var(--sh-ease),
        color var(--sh-dur-fast) var(--sh-ease);
}

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

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

.sh-chip.is-active,
.sh-chip-active {
    background: var(--sh-primary-600);
    color: var(--sh-text-inverse);
}

.sh-chip.is-active:hover {
    background: var(--sh-primary-700);
    color: var(--sh-text-inverse);
}

.sh-chip-outline {
    background: var(--sh-surface);
    border-color: var(--sh-border);
}

/* Hashtag pill */
.sh-tag {
    display: inline-flex;
    align-items: center;
    padding: 5px 10px;
    border-radius: var(--sh-radius-xs);
    background: var(--sh-primary-50);
    color: var(--sh-primary-700);
    font-size: var(--sh-fs-xs);
    font-weight: var(--sh-fw-medium);
}

.sh-tag:hover {
    background: var(--sh-primary-100);
    color: var(--sh-primary-800);
}

/* Verified tick */
.sh-verified {
    display: inline-flex;
    color: var(--sh-primary-600);
    flex-shrink: 0;
}

.sh-verified svg { width: 15px; height: 15px; }

/* ==========================================================================
   Tabs — underline style
   ========================================================================== */

.sh-tabs {
    display: flex;
    gap: var(--sh-sp-1);
    border-bottom: 1px solid var(--sh-border);
    overflow-x: auto;
    scrollbar-width: none;
}

.sh-tabs::-webkit-scrollbar { display: none; }

.sh-tab {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: var(--sh-sp-3) var(--sh-sp-4);
    font-size: var(--sh-fs-base);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text-muted);
    white-space: nowrap;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    transition: color var(--sh-dur-fast) var(--sh-ease),
        border-color var(--sh-dur-fast) var(--sh-ease);
}

.sh-tab:hover {
    color: var(--sh-text);
}

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

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

/* Segmented control (Monthly / Yearly) */
.sh-segment {
    display: inline-flex;
    padding: 4px;
    border-radius: var(--sh-radius-pill);
    background: var(--sh-surface-sunken);
    gap: 2px;
}

.sh-segment-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 38px;
    padding: 0 var(--sh-sp-5);
    border-radius: var(--sh-radius-pill);
    font-size: var(--sh-fs-base);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text-muted);
    white-space: nowrap;
}

.sh-segment-item.is-active {
    background: var(--sh-primary-600);
    color: var(--sh-text-inverse);
    box-shadow: var(--sh-shadow-sm);
}

/* ==========================================================================
   Forms
   ========================================================================== */

.sh-field {
    display: block;
    margin-bottom: var(--sh-sp-4);
}

/* Heading sits ABOVE the control — never a floating label. */
.sh-label {
    display: block;
    margin-bottom: 6px;
    font-size: var(--sh-fs-sm);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text);
}

.sh-label-req::after {
    content: " *";
    color: var(--sh-danger-500);
}

.sh-input,
.sh-select,
.sh-textarea {
    display: block;
    width: 100%;
    min-height: 44px;
    padding: 0 var(--sh-sp-3);
    background: var(--sh-surface);
    border: 1px solid var(--sh-border-strong);
    border-radius: var(--sh-radius-sm);
    font-size: var(--sh-fs-base);
    color: var(--sh-text);
    transition: border-color var(--sh-dur-fast) var(--sh-ease),
        box-shadow var(--sh-dur-fast) var(--sh-ease);
}

.sh-textarea {
    padding: var(--sh-sp-3);
    min-height: 96px;
    resize: vertical;
    line-height: var(--sh-lh-normal);
}

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

.sh-input:focus,
.sh-select:focus,
.sh-textarea:focus {
    outline: none;
    border-color: var(--sh-primary-500);
    box-shadow: var(--sh-shadow-focus);
}

.sh-input:disabled,
.sh-select:disabled,
.sh-textarea:disabled {
    background: var(--sh-surface-sunken);
    color: var(--sh-text-subtle);
    cursor: not-allowed;
}

.sh-select {
    appearance: none;
    padding-inline-end: var(--sh-sp-8);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right var(--sh-sp-3) center;
}

/* Borderless select used as an inline control, e.g. the feed sort dropdown. */
.sh-select-bare {
    min-height: 34px;
    height: 34px;
    padding-inline-start: var(--sh-sp-2);
    padding-inline-end: var(--sh-sp-6);
    border-color: transparent;
    background-color: transparent;
    font-size: var(--sh-fs-sm);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text);
    background-position: right var(--sh-sp-2) center;
}

.sh-select-bare:hover {
    background-color: var(--sh-surface-sunken);
}

.sh-input-error {
    border-color: var(--sh-danger-500);
}

.sh-input-error:focus {
    box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.15);
}

.sh-help {
    margin-top: 5px;
    font-size: var(--sh-fs-xs);
    color: var(--sh-text-muted);
}

.sh-error {
    margin-top: 5px;
    font-size: var(--sh-fs-xs);
    color: var(--sh-danger-600);
    font-weight: var(--sh-fw-medium);
}

/* Input with a leading and/or trailing icon */
.sh-input-group {
    position: relative;
}

.sh-input-group .sh-input {
    padding-inline-start: 42px;
}

.sh-input-group-icon {
    position: absolute;
    left: var(--sh-sp-3);
    top: 50%;
    transform: translateY(-50%);
    color: var(--sh-text-subtle);
    pointer-events: none;
    display: flex;
}

.sh-input-group-icon svg { width: 18px; height: 18px; }

.sh-input-group-action {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
}

.sh-input-group-has-action .sh-input {
    padding-inline-end: 44px;
}

/* Search box — rounded, sunken, appears in every header */
.sh-search {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
}

/* White with a visible edge by default: the sunken grey is within a shade of
   --sh-page-bg, so a transparent-bordered field vanishes anywhere it sits
   directly on the page rather than inside a white card. */
.sh-search .sh-input {
    height: 40px;
    min-height: 40px;
    padding-inline-start: 40px;
    background: var(--sh-surface);
    border-color: var(--sh-border-strong);
    border-radius: var(--sh-radius-pill);
}

.sh-search .sh-input:focus {
    background: var(--sh-surface);
    border-color: var(--sh-primary-500);
}

/* In a header the field sits on white, so the classic sunken pill reads
   correctly there and keeps the app chrome looking right. */
.sh-header-search .sh-search .sh-input,
.sh-ad-header-search .sh-search .sh-input {
    background: var(--sh-surface-sunken);
    border-color: transparent;
}

.sh-header-search .sh-search .sh-input:focus,
.sh-ad-header-search .sh-search .sh-input:focus {
    background: var(--sh-surface);
    border-color: var(--sh-primary-500);
}

.sh-search-icon {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--sh-text-subtle);
    pointer-events: none;
    display: flex;
}

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

/* Checkbox / radio */
.sh-check {
    display: inline-flex;
    align-items: flex-start;
    gap: var(--sh-sp-2);
    cursor: pointer;
    font-size: var(--sh-fs-base);
    line-height: 1.45;
}

.sh-check input[type="checkbox"],
.sh-check input[type="radio"] {
    width: 18px;
    height: 18px;
    margin: 1px 0 0;
    accent-color: var(--sh-primary-600);
    cursor: pointer;
    flex-shrink: 0;
}

/* A checkbox used outside the .sh-check wrapper, where the row does its own
   layout. Same look, no opinion about what sits beside it. */
.sh-checkbox {
    width: 18px;
    height: 18px;
    margin: 0;
    accent-color: var(--sh-primary-600);
    cursor: pointer;
    flex-shrink: 0;
}

.sh-checkbox:disabled {
    cursor: not-allowed;
}

/* Toggle switch */
.sh-switch {
    position: relative;
    display: inline-block;
    width: 44px;
    height: 24px;
    flex-shrink: 0;
}

.sh-switch input {
    opacity: 0;
    width: 0;
    height: 0;
}

.sh-switch-track {
    position: absolute;
    inset: 0;
    background: var(--sh-gray-300);
    border-radius: var(--sh-radius-pill);
    cursor: pointer;
    transition: background var(--sh-dur) var(--sh-ease);
}

.sh-switch-track::before {
    content: "";
    position: absolute;
    left: 3px;
    top: 3px;
    width: 18px;
    height: 18px;
    background: var(--sh-white);
    border-radius: 50%;
    box-shadow: var(--sh-shadow-sm);
    transition: transform var(--sh-dur) var(--sh-ease);
}

.sh-switch input:checked + .sh-switch-track {
    background: var(--sh-success-500);
}

.sh-switch input:checked + .sh-switch-track::before {
    transform: translateX(20px);
}

.sh-switch input:focus-visible + .sh-switch-track {
    box-shadow: var(--sh-shadow-focus);
}

/* A labelled switch row, as used all through Settings */
.sh-switch-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sh-sp-4);
    padding: var(--sh-sp-3) 0;
}

.sh-switch-row + .sh-switch-row {
    border-top: 1px solid var(--sh-border);
}

/* ==========================================================================
   Dropdown menu
   ========================================================================== */

.sh-dropdown {
    position: relative;
}

.sh-dropdown-menu {
    position: absolute;
    right: 0;
    top: calc(100% + 8px);
    min-width: 200px;
    padding: 6px;
    background: var(--sh-surface);
    border: 1px solid var(--sh-border);
    border-radius: var(--sh-radius);
    box-shadow: var(--sh-shadow-lg);
    z-index: var(--sh-z-sticky);
    display: none;
}

.sh-dropdown.is-open .sh-dropdown-menu {
    display: block;
}

.sh-dropdown-menu-left {
    right: auto;
    left: 0;
}

.sh-dropdown-item {
    display: flex;
    align-items: center;
    gap: var(--sh-sp-3);
    width: 100%;
    padding: var(--sh-sp-2) var(--sh-sp-3);
    border-radius: var(--sh-radius-xs);
    font-size: var(--sh-fs-base);
    font-weight: var(--sh-fw-medium);
    color: var(--sh-text);
    text-align: start;
}

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

.sh-dropdown-item svg {
    width: 17px;
    height: 17px;
    color: var(--sh-text-muted);
    flex-shrink: 0;
}

.sh-dropdown-item-danger {
    color: var(--sh-danger-600);
}

.sh-dropdown-item-danger svg {
    color: var(--sh-danger-500);
}

.sh-dropdown-divider {
    height: 1px;
    background: var(--sh-border);
    margin: 5px 0;
}

.sh-dropdown-head {
    padding: var(--sh-sp-3);
    border-bottom: 1px solid var(--sh-border);
    margin-bottom: 5px;
}

/* ==========================================================================
   Modal
   ========================================================================== */

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

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

.sh-modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(15, 23, 42, 0.55);
    backdrop-filter: blur(2px);
}

/* Phones get a bottom sheet; from tablet it becomes a centred dialog. */
.sh-modal-dialog {
    position: relative;
    width: 100%;
    max-height: 92vh;
    display: flex;
    flex-direction: column;
    background: var(--sh-surface);
    border-radius: var(--sh-radius-xl) var(--sh-radius-xl) 0 0;
    box-shadow: var(--sh-shadow-lg);
    overflow: hidden;
    animation: sh-sheet-up var(--sh-dur) var(--sh-ease);
}

@keyframes sh-sheet-up {
    from { transform: translateY(24px); opacity: 0; }
    to { transform: translateY(0); opacity: 1; }
}

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

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

.sh-modal-foot {
    display: flex;
    gap: var(--sh-sp-2);
    justify-content: flex-end;
    padding: var(--sh-sp-4);
    border-top: 1px solid var(--sh-border);
    flex-shrink: 0;
}

/* ==========================================================================
   Table (admin lists)
   ========================================================================== */

.sh-table-wrap {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.sh-table {
    width: 100%;
    min-width: 720px;
    border-collapse: collapse;
    font-size: var(--sh-fs-base);
}

.sh-table thead th {
    padding: var(--sh-sp-3) var(--sh-sp-3);
    text-align: start;
    font-size: var(--sh-fs-xs);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text-muted);
    background: var(--sh-surface-alt);
    border-bottom: 1px solid var(--sh-border);
    white-space: nowrap;
}

.sh-table tbody td {
    padding: var(--sh-sp-3);
    border-bottom: 1px solid var(--sh-border);
    vertical-align: middle;
    color: var(--sh-text);
}

.sh-table tbody tr:last-child td {
    border-bottom: 0;
}

.sh-table tbody tr:hover {
    background: var(--sh-surface-alt);
}

.sh-table-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    justify-content: flex-end;
}

.sh-table-nowrap {
    white-space: nowrap;
}

/* User cell: avatar + name/handle stack, reused in most admin tables */
.sh-table-user {
    display: flex;
    align-items: center;
    gap: var(--sh-sp-3);
    min-width: 0;
}

.sh-table-user-name {
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text-strong);
    line-height: 1.3;
}

.sh-table-user-meta {
    font-size: var(--sh-fs-xs);
    color: var(--sh-text-muted);
    line-height: 1.3;
}

/* ==========================================================================
   Stat card (the coloured-icon KPI tile on every admin index)
   ========================================================================== */

.sh-stat {
    display: flex;
    align-items: flex-start;
    gap: var(--sh-sp-3);
    padding: var(--sh-sp-4);
    background: var(--sh-surface);
    border: 1px solid var(--sh-border);
    border-radius: var(--sh-radius-lg);
    box-shadow: var(--sh-shadow-sm);
}

.sh-stat-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 46px;
    height: 46px;
    border-radius: var(--sh-radius);
    flex-shrink: 0;
}

.sh-stat-icon svg {
    width: 22px;
    height: 22px;
}

.sh-stat-icon-primary { background: var(--sh-primary-50); color: var(--sh-primary-600); }
.sh-stat-icon-violet { background: var(--sh-violet-50); color: var(--sh-violet-600); }
.sh-stat-icon-pink { background: var(--sh-pink-50); color: var(--sh-pink-600); }
.sh-stat-icon-success { background: var(--sh-success-50); color: var(--sh-success-600); }
.sh-stat-icon-warning { background: var(--sh-warning-50); color: var(--sh-warning-600); }
.sh-stat-icon-danger { background: var(--sh-danger-50); color: var(--sh-danger-600); }
.sh-stat-icon-info { background: var(--sh-info-50); color: var(--sh-info-600); }

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

.sh-stat-label {
    font-size: var(--sh-fs-sm);
    color: var(--sh-text-muted);
    font-weight: var(--sh-fw-medium);
    line-height: 1.3;
}

.sh-stat-value {
    font-size: var(--sh-fs-2xl);
    font-weight: var(--sh-fw-extrabold);
    color: var(--sh-text-strong);
    line-height: 1.2;
    margin-top: 2px;
    letter-spacing: -0.02em;
}

.sh-stat-delta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 2px 4px;
    margin-top: 4px;
    font-size: var(--sh-fs-xs);
    font-weight: var(--sh-fw-semibold);
}

.sh-stat-delta svg { width: 13px; height: 13px; flex-shrink: 0; }
.sh-stat-delta-up { color: var(--sh-success-600); }
.sh-stat-delta-down { color: var(--sh-danger-600); }

/* In a narrow 2-up tile the caption drops to its own line rather than
   breaking one word per line. */
.sh-stat-delta-note {
    color: var(--sh-text-subtle);
    font-weight: var(--sh-fw-normal);
    white-space: nowrap;
}

/* ==========================================================================
   List row (sidebar widgets: suggested groups, online friends, trending…)
   ========================================================================== */

.sh-list-row {
    display: flex;
    align-items: center;
    gap: var(--sh-sp-3);
    padding: var(--sh-sp-2) 0;
    min-width: 0;
    /* Wraps only when the text column would otherwise be squeezed past
       readability. In a 220px rail a thumbnail, a title and a Join button
       left the title 87px — narrower than the word "Photography" — so it
       broke mid-word. The button drops to its own line there and nothing
       changes on the rows that already had room. */
    flex-wrap: wrap;
}

.sh-list-row-body {
    /* The basis is what decides when the row wraps: below this the
       siblings go to the next line rather than starving the text. */
    flex: 1 1 110px;
    min-width: 0;
}

.sh-list-row-title {
    /* These are spans, and `display` is not implied — left inline the
       title and both meta lines ran together as one paragraph
       ("Sunburn Music Festival 2026 Fri, Oct 23 · 6:00 PM Hyderabad"). */
    display: block;
    font-size: var(--sh-fs-base);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text-strong);
    line-height: 1.35;
    /* `break-word`, never `anywhere`. Both stop a long unbroken string
       overflowing, but `anywhere` also drops the element's min-content
       width to one character — so in a rail this title was starved by the
       thumbnail and the button beside it and broke mid-word
       ("Photograp / hy Walk"). `break-word` only breaks a word that
       genuinely cannot fit on a line of its own. */
    overflow-wrap: break-word;
}

/* A compact date, for an event row that would otherwise spend a line
   on it and 56px on a cover photo that says nothing at that size. */
.sh-datechip {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    border-radius: var(--sh-radius-sm);
    background: var(--sh-primary-50);
    color: var(--sh-primary-700);
    line-height: 1.1;
}

.sh-datechip-month {
    font-size: var(--sh-fs-2xs);
    font-weight: var(--sh-fw-bold);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.sh-datechip-day {
    font-size: var(--sh-fs-base);
    font-weight: var(--sh-fw-bold);
}

/* A widget row whose action sits outside the row link. The link is the
   row, so it takes the space and the button stays at the end. */
.sh-widget-row-action {
    display: flex;
    align-items: center;
    gap: var(--sh-sp-2);
}

.sh-widget-row-action > .sh-widget-rowlink {
    flex: 1 1 0;
}

.sh-list-row-meta {
    display: block;
    font-size: var(--sh-fs-xs);
    color: var(--sh-text-muted);
    line-height: 1.35;
    overflow-wrap: break-word;
}

.sh-list-divided > .sh-list-row + .sh-list-row {
    border-top: 1px solid var(--sh-border);
}

/* Numbered rank (trending lists) */
.sh-rank {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: var(--sh-radius-xs);
    background: var(--sh-surface-sunken);
    color: var(--sh-text-muted);
    font-size: var(--sh-fs-xs);
    font-weight: var(--sh-fw-bold);
    flex-shrink: 0;
}

/* ==========================================================================
   Misc
   ========================================================================== */

/* Page heading block above content */
.sh-page-head {
    margin-bottom: var(--sh-sp-4);
}

.sh-page-title {
    font-size: var(--sh-fs-3xl);
    font-weight: var(--sh-fw-extrabold);
    letter-spacing: -0.025em;
    color: var(--sh-text-strong);
    margin: 0;
}

.sh-page-sub {
    margin: 4px 0 0;
    font-size: var(--sh-fs-md);
    color: var(--sh-text-muted);
}

.sh-page-head-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sh-sp-3);
    flex-wrap: wrap;
}

/* Two or more buttons on the right of a page heading. */
.sh-page-head-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sh-sp-2);
}

/* Section heading inside a column ("Trending Hashtags" + See All) */
.sh-section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sh-sp-3);
    margin-bottom: var(--sh-sp-3);
}

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

/* Empty state */
.sh-empty {
    padding: var(--sh-sp-10) var(--sh-sp-4);
    text-align: center;
}

.sh-empty-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 64px;
    height: 64px;
    border-radius: 50%;
    background: var(--sh-surface-sunken);
    color: var(--sh-text-subtle);
    margin-bottom: var(--sh-sp-3);
}

.sh-empty-icon svg { width: 28px; height: 28px; }

.sh-empty-title {
    font-size: var(--sh-fs-lg);
    font-weight: var(--sh-fw-bold);
    color: var(--sh-text-strong);
}

.sh-empty-text {
    margin-top: 4px;
    font-size: var(--sh-fs-base);
    color: var(--sh-text-muted);
}

/* Pagination */
.sh-pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    flex-wrap: wrap;
}

.sh-page-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 34px;
    height: 34px;
    padding: 0 8px;
    border-radius: var(--sh-radius-xs);
    font-size: var(--sh-fs-sm);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text-muted);
    border: 1px solid var(--sh-border);
    background: var(--sh-surface);
}

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

.sh-page-link.is-active {
    background: var(--sh-primary-600);
    border-color: var(--sh-primary-600);
    color: var(--sh-text-inverse);
}

.sh-page-link.is-disabled {
    opacity: 0.45;
    pointer-events: none;
}

/* Progress bar */
.sh-progress {
    height: 7px;
    border-radius: var(--sh-radius-pill);
    background: var(--sh-surface-sunken);
    overflow: hidden;
}

.sh-progress-bar {
    height: 100%;
    border-radius: var(--sh-radius-pill);
    background: var(--sh-primary-600);
    transition: width var(--sh-dur-slow) var(--sh-ease);
}

.sh-progress-bar-gradient { background: var(--sh-brand-gradient); }
.sh-progress-bar-success { background: var(--sh-success-500); }
.sh-progress-bar-warning { background: var(--sh-warning-500); }

/* ==========================================================================
   Stepped width scale
   Bars, meters and completion rings need a data-driven width, and inline
   styles are not allowed here. Blade rounds the percentage to the nearest 5
   and picks a class: .sh-w-0 … .sh-w-100.
   ========================================================================== */

.sh-w-0 { width: 0; }
.sh-w-5 { width: 5%; }
.sh-w-10 { width: 10%; }
.sh-w-15 { width: 15%; }
.sh-w-20 { width: 20%; }
.sh-w-25 { width: 25%; }
.sh-w-30 { width: 30%; }
.sh-w-35 { width: 35%; }
.sh-w-40 { width: 40%; }
.sh-w-45 { width: 45%; }
.sh-w-50 { width: 50%; }
.sh-w-55 { width: 55%; }
.sh-w-60 { width: 60%; }
.sh-w-65 { width: 65%; }
.sh-w-70 { width: 70%; }
.sh-w-75 { width: 75%; }
.sh-w-80 { width: 80%; }
.sh-w-85 { width: 85%; }
.sh-w-90 { width: 90%; }
.sh-w-95 { width: 95%; }
.sh-w-100 { width: 100%; }

/* Alert / callout */
.sh-alert {
    display: flex;
    align-items: flex-start;
    gap: var(--sh-sp-3);
    padding: var(--sh-sp-3) var(--sh-sp-4);
    border-radius: var(--sh-radius);
    font-size: var(--sh-fs-base);
    border: 1px solid transparent;
}

.sh-alert svg {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    margin-top: 1px;
}

.sh-alert-info { background: var(--sh-info-50); color: var(--sh-info-600); border-color: var(--sh-info-100); }
.sh-alert-success { background: var(--sh-success-50); color: var(--sh-success-700); border-color: var(--sh-success-100); }
.sh-alert-warning { background: var(--sh-warning-50); color: var(--sh-warning-700); border-color: var(--sh-warning-100); }
.sh-alert-danger { background: var(--sh-danger-50); color: var(--sh-danger-700); border-color: var(--sh-danger-100); }

/* Media thumbnail with a rounded frame.
   Usually a <span> inside a link, so it needs an explicit block display for
   the width/height on the size modifiers to take effect. */
.sh-thumb {
    display: block;
    border-radius: var(--sh-radius-sm);
    overflow: hidden;
    background: var(--sh-surface-sunken);
    flex-shrink: 0;
}

.sh-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.sh-thumb-sm { width: 44px; height: 44px; }
.sh-thumb-md { width: 56px; height: 56px; }
.sh-thumb-lg { width: 80px; height: 60px; }

/* Ratio boxes for cover art / reels.
   `display: block` is load-bearing: this class is often carried by a <span>
   inside a link, and on an inline box the padding-top trick collapses to
   nothing — the element renders zero-height and the image disappears. */
.sh-ratio {
    display: block;
    position: relative;
    width: 100%;
    overflow: hidden;
    background: var(--sh-surface-sunken);
}

.sh-ratio > img,
.sh-ratio > video,
.sh-ratio > .sh-ratio-fill {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.sh-ratio-16x9 { padding-top: 56.25%; }
.sh-ratio-4x3 { padding-top: 75%; }
.sh-ratio-1x1 { padding-top: 100%; }
.sh-ratio-4x5 { padding-top: 125%; }
.sh-ratio-9x16 { padding-top: 177.78%; }

/* Skeleton shimmer for async panels */
.sh-skeleton {
    background: linear-gradient(90deg, var(--sh-gray-100) 25%, var(--sh-gray-150) 37%, var(--sh-gray-100) 63%);
    background-size: 400% 100%;
    animation: sh-shimmer 1.4s ease infinite;
    border-radius: var(--sh-radius-xs);
}

@keyframes sh-shimmer {
    0% { background-position: 100% 50%; }
    100% { background-position: 0 50%; }
}

/* Toast */
.sh-toast-host {
    position: fixed;
    left: 50%;
    bottom: calc(var(--sh-tabbar-h) + 16px);
    transform: translateX(-50%);
    z-index: var(--sh-z-toast);
    display: flex;
    flex-direction: column;
    gap: var(--sh-sp-2);
    width: calc(100% - 32px);
    max-width: 420px;
    pointer-events: none;
}

.sh-toast {
    display: flex;
    align-items: center;
    gap: var(--sh-sp-3);
    padding: var(--sh-sp-3) var(--sh-sp-4);
    border-radius: var(--sh-radius);
    background: var(--sh-gray-900);
    color: var(--sh-text-inverse);
    font-size: var(--sh-fs-base);
    font-weight: var(--sh-fw-medium);
    box-shadow: var(--sh-shadow-lg);
    pointer-events: auto;
    animation: sh-sheet-up var(--sh-dur) var(--sh-ease);
}

.sh-toast svg { width: 18px; height: 18px; flex-shrink: 0; }
.sh-toast-success svg { color: var(--sh-success-500); }
.sh-toast-danger svg { color: var(--sh-danger-500); }

/* ==========================================================================
   Responsive
   ========================================================================== */

/* ==========================================================================
   Two-factor authentication card — Settings → Security, admin and member

   Shared, because `<x-two-factor-card>` renders on both surfaces and the
   member panel does not load the admin stylesheet.
   ========================================================================== */

/* A second action on a form screen is a sibling form, not a nested one.
   Lives here rather than in the admin sheet because both surfaces use it. */
.sh-hidden-form {
    display: none;
}

.sh-tfa-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sh-sp-3);
}

.sh-tfa-state {
    display: flex;
    align-items: flex-start;
    gap: var(--sh-sp-2);
    margin: 0 0 var(--sh-sp-3);
    font-size: var(--sh-fs-sm);
    color: var(--sh-text-muted);
}

/* An icon has no width of its own inside a container that never sizes svg. */
.sh-tfa-state svg {
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    margin-top: 1px;
}

.sh-tfa-secret {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    letter-spacing: 0.08em;
}

/* Shown once. Wraps instead of scrolling sideways on a phone. */
.sh-tfa-codes {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sh-sp-2);
    margin: 0 0 var(--sh-sp-4);
    padding: var(--sh-sp-3);
    list-style: none;
    border: 1px dashed var(--sh-border-strong);
    border-radius: var(--sh-radius-sm);
    background: var(--sh-surface-sunken);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: var(--sh-fs-sm);
    overflow-wrap: anywhere;
}

.sh-tfa-start,
.sh-tfa-confirm {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--sh-sp-3);
}

@media (min-width: 480px) {
    .sh-tfa-codes {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    .sh-tfa-start,
    .sh-tfa-confirm {
        flex-direction: row;
        align-items: flex-end;
    }

    .sh-tfa-start .sh-field,
    .sh-tfa-confirm .sh-field {
        flex: 0 1 260px;
    }
}

@media (min-width: 768px) {
    .sh-card-pad,
    .sh-card-head,
    .sh-card-body {
        padding: var(--sh-sp-5);
    }

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

    .sh-modal {
        align-items: center;
        padding: var(--sh-sp-6);
    }

    .sh-modal-dialog {
        max-width: 560px;
        max-height: 86vh;
        border-radius: var(--sh-radius-xl);
    }

    .sh-modal-dialog-lg { max-width: 760px; }
    .sh-modal-dialog-sm { max-width: 420px; }

    .sh-toast-host {
        left: auto;
        right: 24px;
        bottom: 24px;
        transform: none;
    }
}

@media (min-width: 1024px) {
    .sh-page-title {
        font-size: var(--sh-fs-4xl);
    }
}

/* ==========================================================================
   Dropdowns inside cards
   .sh-card clips its overflow to round its corners, which also amputates any
   menu that opens past the card edge. Un-clip only while a menu is open, and
   only on the card that owns it.
   ========================================================================== */

.sh-card:has(.sh-dropdown.is-open) {
    overflow: visible;
}

/* The cover art keeps its own rounding, so dropping the card's clip above
   cannot square off the top corners. */
.sh-card > :first-child.sh-prof-cover,
.sh-card > :first-child.sh-ratio,
.sh-card > :first-child img {
    border-top-left-radius: inherit;
    border-top-right-radius: inherit;
    overflow: hidden;
}

/* ==========================================================================
   File inputs
   Styled globally on the element so every upload control picks this up, with
   no extra class on the markup. The browser default ("Choose files / No file
   chosen") is the one control that ignores the rest of the design system.
   ========================================================================== */

input[type="file"] {
    display: block;
    width: 100%;
    min-height: 46px;
    padding: 7px;
    background: var(--sh-surface);
    /* Dashed reads as a drop target rather than a text field. */
    border: 1px dashed var(--sh-border-strong);
    border-radius: var(--sh-radius-sm);
    font-family: inherit;
    font-size: var(--sh-fs-sm);
    color: var(--sh-text-muted);
    cursor: pointer;
    transition: border-color var(--sh-dur-fast) var(--sh-ease),
        background var(--sh-dur-fast) var(--sh-ease);
}

input[type="file"]:hover {
    border-color: var(--sh-primary-400);
    background: var(--sh-primary-50);
}

input[type="file"]:focus-visible {
    outline: none;
    border-color: var(--sh-primary-500);
    border-style: solid;
    box-shadow: var(--sh-shadow-focus);
}

input[type="file"]:disabled {
    background: var(--sh-surface-sunken);
    border-color: var(--sh-border);
    cursor: not-allowed;
}

/* The picker button itself, matched to .sh-btn-secondary. */
input[type="file"]::file-selector-button {
    height: 30px;
    margin-inline-end: var(--sh-sp-3);
    padding: 0 var(--sh-sp-4);
    border: 0;
    border-radius: var(--sh-radius-xs);
    background: var(--sh-primary-600);
    color: var(--sh-text-inverse);
    font-family: inherit;
    font-size: var(--sh-fs-sm);
    font-weight: var(--sh-fw-semibold);
    line-height: 1;
    cursor: pointer;
    transition: background var(--sh-dur-fast) var(--sh-ease);
}

input[type="file"]:hover::file-selector-button {
    background: var(--sh-primary-700);
}

input[type="file"]:disabled::file-selector-button {
    background: var(--sh-gray-300);
    cursor: not-allowed;
}

/* Safari and older Chromium use the vendor-prefixed pseudo-element. */
input[type="file"]::-webkit-file-upload-button {
    height: 30px;
    margin-inline-end: var(--sh-sp-3);
    padding: 0 var(--sh-sp-4);
    border: 0;
    border-radius: var(--sh-radius-xs);
    background: var(--sh-primary-600);
    color: var(--sh-text-inverse);
    font-family: inherit;
    font-size: var(--sh-fs-sm);
    font-weight: var(--sh-fw-semibold);
    line-height: 1;
    cursor: pointer;
}

/* ==========================================================================
   Sponsored CTA colours
   The admin's campaign picker swaps these on its preview button and the
   live ad wears the same class, so what an advertiser is shown is what
   gets published. They live here, not in sh-admin-content.css, because
   the member panel never loads that file — the colour was chosen, stored,
   validated and then ignored on every real ad.
   ========================================================================== */

.sh-ac-cta-primary {
    background: var(--sh-primary-600);
    color: var(--sh-text-inverse);
}

.sh-ac-cta-success {
    background: var(--sh-success-600);
    color: var(--sh-text-inverse);
}

.sh-ac-cta-danger {
    background: var(--sh-danger-600);
    color: var(--sh-text-inverse);
}

.sh-ac-cta-dark {
    background: var(--sh-gray-900);
    color: var(--sh-text-inverse);
}

/* ==========================================================================
   Widgets
   Blocks placed by Admin → Widgets. They land in rails (~270px), in the
   feed column (~720px) and in the public footer, so everything here is
   sized to the narrowest of those and simply has more room elsewhere.
   Lives in components, not a surface file: the same block renders on the
   public site and inside the member panel.
   ========================================================================== */

.sh-widget {
    margin-bottom: var(--sh-sp-4);
}

.sh-widget-body {
    padding-top: var(--sh-sp-3);
}

/* -- Rows ------------------------------------------------------------------ */

/* A widget adapts to the column it lands in, not to the window.
   The same card sits in a 268px rail, a 400px one when the second
   sidebar is switched off, a profile sidebar and the footer — a media
   query cannot tell those apart, and sizing for the narrowest left the
   widest looking half empty. */
.sh-widget {
    container-type: inline-size;
    container-name: shwidget;
}

.sh-widget-list {
    display: flex;
    flex-direction: column;
    gap: var(--sh-sp-1);
    margin: 0;
    padding: 0;
    list-style: none;
}

.sh-widget-row {
    min-width: 0;
}

/* The anchor wraps the whole row, so it has to be a flex box — left
   inline it collapsed into a run of blue text with the avatar floating
   in the middle of it. */
.sh-widget-rowlink {
    display: flex;
    align-items: center;
    gap: var(--sh-sp-2);
    padding: var(--sh-sp-2);
    border-radius: var(--sh-radius-sm);
    color: var(--sh-text);
    text-decoration: none;
    min-width: 0;
}

.sh-widget-rowlink:hover {
    background: var(--sh-surface-sunken);
    color: var(--sh-text-strong);
}

.sh-widget-rowbody {
    display: flex;
    flex-direction: column;
    min-width: 0;
    gap: 1px;
}

.sh-widget-rowtitle {
    font-size: var(--sh-fs-sm);
    font-weight: var(--sh-fw-semibold);
    color: var(--sh-text-strong);
    line-height: 1.3;
    /* Never `anywhere`: it would starve this column the same way. */
    overflow-wrap: break-word;
}

.sh-widget-rowmeta {
    font-size: var(--sh-fs-xs);
    color: var(--sh-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}


/* A reel still is a 9:16 tile, not a full-bleed photograph — without a
   size the browser drew it at its natural height and one thumbnail
   filled the whole card. */
.sh-widget-thumb {
    display: block;
    flex-shrink: 0;
    width: 40px;
    aspect-ratio: 9 / 16;
    overflow: hidden;
    border-radius: var(--sh-radius-xs);
    background: var(--sh-surface-sunken);
}

.sh-widget-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.sh-widget-rank {
    flex-shrink: 0;
    width: 18px;
    font-size: var(--sh-fs-xs);
    font-weight: var(--sh-fw-bold);
    color: var(--sh-text-subtle);
    text-align: center;
    font-variant-numeric: tabular-nums;
}

/* -- Categories ------------------------------------------------------------ */

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

.sh-widget-chipcount {
    margin-inline-start: 5px;
    font-size: var(--sh-fs-2xs);
    color: var(--sh-text-subtle);
}

/* -- Social ---------------------------------------------------------------- */

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

.sh-widget-socialbtn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border: 1px solid var(--sh-border);
    border-radius: var(--sh-radius-sm);
    color: var(--sh-text-muted);
}

.sh-widget-socialbtn:hover {
    border-color: var(--sh-border-strong);
    background: var(--sh-surface-sunken);
    color: var(--sh-text-strong);
}

.sh-widget-socialbtn svg {
    width: 18px;
    height: 18px;
}

/* -- Newsletter and custom HTML -------------------------------------------- */

.sh-widget-text {
    margin: 0 0 var(--sh-sp-3);
    font-size: var(--sh-fs-sm);
    color: var(--sh-text-muted);
    line-height: var(--sh-lh-snug);
}

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

.sh-widget-html {
    font-size: var(--sh-fs-sm);
    color: var(--sh-text);
    line-height: var(--sh-lh-relaxed);
    overflow-wrap: break-word;
}

.sh-widget-html :is(p, ul, ol) {
    margin: 0 0 var(--sh-sp-2);
}

.sh-widget-html :last-child {
    margin-bottom: 0;
}

.sh-widget-html img {
    max-width: 100%;
    height: auto;
    border-radius: var(--sh-radius-sm);
}

/* -- A roomy column ------------------------------------------------------- */

/* Everything grows together. Enlarging only the thumbnail made it
   worse: a 9:16 still at 64px is 114px tall, so the row got taller
   while the two lines of text beside it stayed the same and the gap
   above and below them grew. */
@container shwidget (min-width: 330px) {
    .sh-widget-rowlink {
        gap: var(--sh-sp-3);
        padding: var(--sh-sp-2) var(--sh-sp-3);
    }

    .sh-widget-thumb {
        width: 52px;
    }

    .sh-widget-rowtitle {
        font-size: var(--sh-fs-base);
    }

    .sh-widget-rowmeta {
        font-size: var(--sh-fs-sm);
    }

    .sh-widget-rowlink .sh-avatar {
        width: 44px;
        height: 44px;
    }

    /* Chips and social tiles have room to breathe too. */
    .sh-widget-chips {
        gap: var(--sh-sp-2);
    }
}

/* A wider column can afford a larger reel still. */
@media (min-width: 1024px) {
    .sh-feed .sh-widget-thumb {
        width: 48px;
    }
}

/* ==========================================================================
   Social link tiles
   A row of small round links to other platforms. Used on a CMS page's
   "Elsewhere" card. They lived in the public footer's stylesheet and were
   painted for a dark slab, so they were already wrong on a light card —
   and vanished entirely when the footer stopped being dark.
   ========================================================================== */

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

.sh-social-link {
    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-muted);
}

.sh-social-link:hover {
    background: var(--sh-primary-600);
    color: var(--sh-text-inverse);
}

.sh-social-link svg {
    width: 17px;
    height: 17px;
}
