/* Upload Society-specific overrides layered on top of the Friendbook theme */

/* dark.css's own .btn-outline default-state text color (#ff5a3c) — only the
   default state, hover/focus/active keep the theme's own colors. */
.btn-outline {
  color: #fcf7df;
  font-size: calc(12px + (14 - 12) * ((100vw - 320px) / (1920 - 320)));
}

.btn-solid {
  font-size: calc(11px + (14 - 12) * ((100vw - 320px) / (1920 - 320)));
}

/* dark.css sets .btn-solid/.btn-outline:hover's text color TWICE — once
   correctly (dark navy, readable) near where the rule is first declared,
   then a second time near the file's own "Dark css start" section, which
   sets it to plain white and wins the cascade since it comes later in the
   same file. That was fine back when the accent color was the old, darker
   #c51721 red, but white-on-#ff5a3c (this lighter coral) doesn't have
   enough contrast. Same root cause hits a few other bg:#ff5a3c elements
   scattered through the theme (also declared/overridden this exact way) —
   fixing every one of them here rather than hand-patching dark.css itself.
   (Used to also carry a text-shadow glow here, on the assumption it was
   needed for legibility — removed as part of a site-wide shadow cleanup
   for slower devices once the actual contrast ratio of #000 on #ff5a3c was
   checked: ~6.7:1, comfortably above the 4.5:1 AA threshold on its own, so
   the glow was never load-bearing.) */
.btn-solid,
.btn-outline:hover,
.tap-top,
.checkbox_animated input[type="checkbox"]:checked + label:before,
.theme-pagination .page-item.active .page-link,
.rtl-btn,
.setting-box .setting-contant .setting_buttons .setting_btn {
  color: #000;
}

/* Avatars are rectangles everywhere, not circles — dark.css hardcodes
   border-radius: 100% on avatar images in a few spots we don't otherwise
   have our own override for. Every other avatar spot lives in our own
   rules elsewhere in this file (or room.css) and just had the property
   removed directly instead of overridden here. */
.custom-dropdown .dropdown-menu .dropdown-content .friend-list .media img,
.blog-single-detail .blog-comment .comment-wrapper .comment-box .media img {
  border-radius: 0;
}

header .header-section .profile-btn .user-img {
  border-radius: 0;
}

.comment-load-more {
  margin-top: 15px;
}

.comment-replies-load-more {
  margin-left: calc(20px + (30 - 20) * ((100vw - 320px) / (1920 - 320)));
  color: #fff !important;
  position: relative;
  padding: 2px 15px;
  left: calc(var(--bs-gutter-x, 1.5rem) / 2);
  background-color: #051826 !important;
  text-decoration: none !important;
  border-color: #fff !important;
  transition: all 0.15s ease;
  overflow: hidden;
  position:relative;
}
.comment-replies-load-more:after {
  content: "v";
  position:absolute;
  right: -50px;
  transition: all 0.15s ease;
}
.comment-replies-load-more:hover:after {
  right: 10px;
}
.comment-replies-load-more:hover {
  background-color: #ff5a3c !important;
  color: #000 !important;
  border-color: #ff5a3c !important;
  padding-right: 25px !important;
}

.settings-subgroup-heading {
  width: 100%;
  margin: 4px 0 10px;
  opacity: 0.6;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* partials/video-thumb paints the real thumbnail as a background-image on its
   <a> (the <img> inside is just a hidden lazysizes placeholder) — that only
   shows up if the <a> actually has a size, which .people-list-item (built for
   circular 44x44 avatars) doesn't give it. This wrapper gives the history
   page's video rows a fixed-size box to paint into instead. */
.history-thumb {
  width: 64px;
  height: 40px;
  flex-shrink: 0;
  border-radius: 6px;
  overflow: hidden;
}

.history-thumb a.bg-size {
  width: 100%;
  height: 100%;
}

/* The theme's mobile fixed bottom bar (dark.css, max-width: 576px) only knows
   how to reposition its own stock 5 icons (home/add-friend/profile/message/
   notification) via `position: fixed; left: N%`. We added 2 more icons to
   that same row (friends-last-seen, active-users) that the theme has no
   rule for, so on mobile they were left behind in normal document flow at
   the top instead of joining the fixed bar. Home is shown separately in
   normal flow near the logo instead of joining this bar; upload/start-a-room
   are dropped from it entirely on mobile (reachable from the app-grid menu
   instead), so this re-spaces the remaining 6 evenly across the bar,
   profile-btn leading. Loads after dark.css, so equal-specificity selectors
   here win by cascade order without needing !important. */
@media (max-width: 576px) {
  html header .header-section .header-left .brand-logo {
    width: 160px;
  }
  html header .header-section .header-left .brand-logo img {
    width: 200px;
  }

  header .header-section .header-right .option-list .header-btn.guest-auth-btns a {
    padding-left: 5px;
    padding-right: 5px !important;
  }

  /* mobile-fix-menu is just the fixed mobile bar's background strip —
     mobile-only by design (desktop never shows it regardless), so it stays
     scoped to this media query. active-users/app-btn's own guest hiding
     moved below, unscoped, so it also applies on desktop. */
  header:has(.guest-auth-btns) .mobile-fix-menu {
    display: none !important;
  }

  /* dark.css (theme vendor CSS) unconditionally hides these badges below
     576px — undoes that so unread message/notification/friend-request
     counts still show on mobile (partials/header.ejs already hides a
     zero-count badge itself via .d-none, so this only restores badges that
     actually have something to show). */
  header .header-section .header-btn .count:not(.d-none) {
    display: inline-block !important;
  }

  /* Video watch page's title + favorite/flag button row (watch.ejs) — too
     cramped side-by-side on narrow screens, so stack them instead. */
  .video-watch-meta > .d-flex.align-items-center.justify-content-between {
    flex-direction: column;
    align-items: flex-start;
  }
  .video-watch-meta > .d-flex.align-items-center.justify-content-between > * {
    width: 100%;
    margin-bottom: 10px;
  }

  /* Channel topbar's message/friend/subscribe buttons (channel-view.ejs) —
     same problem, don't fit side-by-side on narrow screens. */
  .channel-topbar-actions {
    flex-direction: column;
    width: 100%;
  }
  .channel-topbar-actions > * {
    width: 100%;
    margin-bottom: 10px;
  }
  .channel-topbar-actions span {
    display: block;
  }
  .channel-topbar-actions form {
    width: 100%;
    display: block !important;
  }
  .channel-topbar-actions form .btn {
    width: 100%;
  }

  /* Comment header row (comment-item.ejs/video-comment-item.ejs) — username
     and date side-by-side don't fit on narrow screens. */
  .title:has(> .comment-user):has(> .comment-date) {
    flex-direction: column;
  }
  .title > .comment-user,
  .title > .comment-date {
    width: 100%;
  }
  .blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .title .comment-date {
    margin-left: 0;
  }

  .blog-comment > .d-flex > * {
    margin: 15px 0px 0px 0 !important
  }
  /* .comment-replies-list > .media covers a reply's own .media too — it
     sits one level deeper than a top-level comment's (inside .comment-
     replies-list, itself a child of .comment-box), so the plain
     ".comment-box > .media" selector alone never matched it. */
  .comment-box > .media > *,
  .comment-box .comment-replies-list > .media > *
  {
    margin: 0px 0px 5px 0 !important
  }
  .comment-box > .media, .comment-box .comment-replies-list > .media, .blog-comment > .d-flex
  {
    flex-direction: column;
  }

  /* Messages page (messages.ejs) — unlike the theme's original client-side
     Bootstrap-tab messenger, ours does a real page navigation per
     conversation, so there's no .tab-pane.active for dark.css's mobile
     "width: 0 unless a tab-pane is active" trick to ever un-collapse. Swap
     manually between list view and thread view based on whether a
     conversation is actually open (messanger-section.thread-open). */
  .messanger-section:not(.thread-open) .chat-content {
    display: none;
  }
  .messanger-section.thread-open .chat-users {
    display: none;
  }
  /* height: 100vh here (dark.css/thread-open override alike) ignored that
     the header above it still renders at its own real height even with
     some of its icon groups hidden on this page (rules below) — the
     .user-title margin-top: 60px this replaced was a visual patch for
     that same mismatch (nudging the title down to clear the header)
     without changing chat-content's actual total height, which is why
     the page still scrolled by whatever the header's real height was.
     Filling every level via flex instead of a guessed vh subtraction
     means nothing here needs to know the header's or user-title's actual
     pixel height at all — see the whole chain below. */
  html .messanger-section.thread-open .chat-content {
    width: 100%;
    height: 100%;
  }
  /* .chat-users (the conversation list) needs the exact same full-height
     treatment for the no-thread-open case — it's messanger-section's only
     visible child then (chat-content is display:none above), and without
     an explicit height it just shrinks to its own content and gets
     vertically centered by the vendor's align-items: center instead of
     filling the screen. */
  .messanger-section .chat-users {
    height: 100%;
    display: flex;
    flex-direction: column;
  }
  /* Vendor (dark.css) sets .user-header/.nav-tabs up with fixed vh-minus-N
     heights here too (height: 100vh on chat-users itself, ignoring the
     header entirely, then calc(100vh - 78px) on nav-tabs) — same
     disconnect as everywhere else in this file: nav-tabs' own height has
     no relation to chat-users' actual (correct, flex-filled) height, so
     the list either falls short of or overflows past its real container.
     Filling it via flex instead needs no number at all. */
  .messanger-section .chat-users .user-header {
    flex: 0 0 auto;
  }
  .messanger-section .chat-users .nav-tabs {
    flex: 1 1 auto;
    min-height: 0;
    height: auto;
  }
  /* height, not min-height — min-height lets long message content grow
     the page taller instead of capping it (the "still scrollable with
     many messages" bug), and gives flex-grow nothing extra to distribute
     into when content is short (the "not full height with few messages"
     bug) — flex-grow only fills space beyond children's own natural size,
     which only exists if the flex container's own size is fixed rather
     than itself just wrapping to fit content. */
  body:has(.messanger-section) {
    display: flex;
    flex-direction: column;
    height: 100dvh;
    overflow: hidden;
  }
  body:has(.messanger-section) header {
    flex: 0 0 auto;
  }
  body:has(.messanger-section) .messanger-section {
    flex: 1 1 auto;
    min-height: 0;
  }
  .messanger-section .chat-content .tab-box,
  .messanger-section .chat-content .tab-box .user-chat {
    height: 100%;
  }
  .messanger-section .chat-content .tab-box .user-chat {
    display: flex;
    flex-direction: column;
  }
  .messanger-section .chat-content .tab-box .user-chat .user-title {
    flex: 0 0 auto;
  }
  .messanger-section .chat-content .tab-box .user-chat .chat-history {
    flex: 1 1 auto;
    min-height: 0;
    height: auto;
  }

  /* The theme's fixed red bottom bar (dark.css, shown on mobile as a
     backdrop for the header icon row) sits on top of the message
     composer's send box here — hide it and the icons it's a backdrop for,
     only on the messages page. */
  body:has(.messanger-section) header .mobile-fix-menu {
    display: none;
  }
  body:has(.messanger-section) header .header-section .header-left > .btn-group {
    display: none;
  }
  body:has(.messanger-section) .option-list > li:not(.app-btn) {
    display: none;
  }

  header .header-section .header-btn.home-btn {
    position: static;
    margin-right: 10px;
  }

  /* 6 icons now (upload-btn dropped out, above) — evenly spaced at
     N * 100/(count+1) so the gaps before/after the row match the gaps
     between icons, profile-btn moved to lead the row. All fixed to the
     same 16px bottom offset — several of these got 16px explicitly below
     because the theme's own default (still in effect for the others) is
     15px, which misaligned them by 1px.

     `left: N%` alone positions each icon's LEFT EDGE at N%, not its
     center — visually drifting the whole row rightward by about half an
     icon's width (the icon svg itself is 16px, `.main-link` padding is
     stripped to 0 on mobile, so ~16px is the icon's full rendered width;
     half of that is 8px). A translateX(-50%) transform would center it
     properly, but transform on this SAME element also becomes the
     containing block for its dropdown-menu child, which the theme makes
     position: fixed; inset: 0 on mobile to fill the screen — that broke
     the dropdown, sizing it to the tiny icon instead of the viewport.
     margin-left doesn't affect containing blocks at all, so it centers
     the icon without that side effect. */
  header .header-section .header-btn.profile-btn {
    position: fixed;
    left: 14.29%;
    bottom: 16px;
    margin-left: -8px;
  }
  header .header-section .header-btn.add-friend {
    position: fixed;
    left: 28.57%;
    bottom: 16px;
    margin-left: -8px;
  }
  header .header-section .header-btn.friends-last-seen {
    position: fixed;
    left: 42.86%;
    bottom: 16px;
    margin-left: -8px;
  }
  header .header-section .header-btn.active-users {
    position: fixed;
    left: 57.14%;
    bottom: 16px;
    margin-left: -8px;
  }
  header .header-section .header-btn.message-btn {
    position: fixed;
    left: 71.43%;
    bottom: 16px;
    margin-left: -8px;
  }
  header .header-section .header-btn.notification-btn {
    position: fixed;
    left: 85.71%;
    bottom: 16px;
    margin-left: -8px;
  }

  /* Now that all 7 icons are `position: fixed` in the same bottom bar (above),
     any of them can end up underneath a sibling icon's open dropdown (the
     dropdown-content fills the screen on mobile) since header-left/
     header-right are separate flex containers with no shared stacking order.
     Bumping the currently-open one's own <li> above everything else fixes it
     regardless of which icon opened it. */
  header .header-section .header-btn:has(> .dropdown-menu.show) {
    z-index: 9999;
  }

  /* Plyr's control bar has no wrap/shrink handling of its own — play,
     current-time, mute, a 60-90px volume slider, settings, pip/airplay,
     and fullscreen all at fixed widths just overflow a narrow portrait
     screen with nowhere to go. Dropping the volume slider (still fully
     usable via the mute button, and this matches how YouTube's own mobile
     player has no volume slider either, relying on the device's hardware
     volume buttons) is what actually frees enough width to fit the rest. */
  .plyr__volume input[type=range] {
    display: none;
  }
}

/* active-users and the app-grid button aren't gated by login server-side
   (unlike guest-auth-btns, which only ever renders for a logged-out
   visitor) — hides both for guests on every screen size, not just mobile. */
header:has(.guest-auth-btns) .header-btn.custom-dropdown.dropdown-lg.active-users {
  display: none !important;
}
header:has(.guest-auth-btns) .header-btn.custom-dropdown.d-md-none.d-block.app-btn {
  display: none !important;
}

.warning-reason-preview {
  font-size: 11px;
  opacity: 0.7;
  max-width: 160px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.portfolio-section > .empty-state {
  margin-top: -15px;
}

.custom-dropdown .dropdown-menu .dropdown-content .friend-list .media .media-body > div {
  margin-bottom: unset;
}

.custom-dropdown .dropdown-menu .dropdown-content .friend-list .media img {
  object-fit: cover;
}

.table {
  color: #eee;
}

.form-control {
  color: #b7b7b7
}

.form-control:focus {
  color: #b7b7b7
}

.logo-sec {
  max-width: 150px;
}

.channel-warnings {
  margin-bottom: 16px;
}

.channel-warning-item {
  margin-bottom: 8px;
  font-size: 13px;
}

.channel-warning-date {
  margin-top: 4px;
  font-size: 11px;
  opacity: 0.7;
}

footer h1, footer h2, footer p {
  margin-bottom: 15px;
}

.nav-tabs .nav-link.active {
  border-color: #0b1a2c #0b1a2c #0b1a2c;
}

.nav-tabs {
  border-bottom: unset;
}

.nav-tabs .nav-link {
  border: 0 none;
}

header .header-section .profile-btn .media-body {
  margin-bottom: unset;
}

.channel-topbar-avatar .available-stats {
  position: absolute;
  right: 0;
  top: 0;
  width: 12px;
  height: 12px;
  border: 3px solid #0b1a2c;
  border-radius: 100%;
  cursor: default;
}

.channel-topbar-avatar .available-stats.online {
  background-color: #2bc60c;
}

.channel-topbar-avatar .available-stats.offline {
  background-color: #ff2f25;
}

.sidebar-panel .sidebar-icon > li + li a {
  margin-top: 10px;
}

.dropdown-footer {
  padding: 12px 15px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.page-center > .title-box + .portfolio-section {
  margin-top: 30px;
}

.video-watch-meta h1 {
  margin-bottom: 0;
  padding-right: 15px;
  font-size: calc(22px + (36 - 28) * ((100vw - 320px) / (1920 - 320)))
}

.video-watch-description {
  white-space: pre-line;
  opacity: 0.85;
  margin-bottom: 12px;
  margin-top: 5px;
}

.video-watch-description.collapsed {
  white-space: nowrap;
  overflow: hidden;
}

.video-description-toggle {
  cursor: pointer;
  color: inherit;
  opacity: 0.75;
  text-decoration: underline !important;
  white-space: nowrap;
}

.video-description-toggle:hover {
  opacity: 1;
}

.ih-15.feather {
  top: 3px;
}

.theme-form .form-control {
  border-color: rgba(100, 117, 137, 0.4);
}

.blog-single-detail .blog-comment .comment {
  color: unset;
  margin-bottom: 0px;
  margin-top: 0;
}

.blog-single-detail .blog-comment .comment + .d-flex.align-items-center {
  margin-top: -.8em;
  position: relative;
  top: .45em;
}

.video-watch-page .blog-comment .comment {
  margin-bottom: 0px;
  padding-bottom: 5px;
}

.channel-type-name {
  display: block;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin-bottom: 6px;
}

.channel-type-blurb p {
  margin: 0;
  font-size: calc(14px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
  opacity: 0.8;
}

.video-watch-page #favorite-btn {
  min-width: 120px;
}

.video-watch-page #flag-btn {
  min-width: 110px;
}

.video-watch-page .comment-wrapper:not(#video-comments-container) {
  margin-top: 15px;
}

.video-watch-page .plyr:not(:fullscreen) audio {
  max-height: 370px;
}

/* Self-hosted videos have no fixed aspect ratio (unlike YouTube's own iframe
   embed, which is always 16:9) — a portrait upload rendered at the player's
   full container width, with height following its own intrinsic ratio,
   could end up taller than a 1080p screen. A flat max-height (previously
   370px here) "fixes" that but stops being responsive itself — on a large
   screen it clamps normal 16:9 landscape videos down to a tiny fixed strip
   instead of scaling with the available width. Constraining the *wrapper*
   to a responsive 16:9 box instead means a real 16:9 video fills it exactly
   (no wasted space) while a portrait video's height is capped proportionally
   to whatever width it's actually rendered at, and letterboxes via
   object-fit instead of stretching. Scoped to :not(:fullscreen) so Plyr's
   own fullscreen sizing is untouched. */
.video-watch-page .plyr:not(:fullscreen) .plyr__video-wrapper {
  aspect-ratio: 16 / 9;
  height: auto;
}

.video-watch-page .plyr:not(:fullscreen) video {
  object-fit: contain;
}

#favorite-btn.active {
  background-color: #ff5a3c;
  border-color: #ff5a3c;
  color: #000;
}

#favorite-btn.active svg {
  fill: #000;
}

#flag-btn.active {
  background-color: #6c757d;
  border-color: #6c757d;
  color: #fff;
}

#flag-btn.active svg {
  fill: #fff;
}

#more-videos-container > .channel-sidebar-heading {
  padding-bottom: 20px;
}

#more-videos-container > div:first-child {
  padding: calc(var(--bs-gutter-x, 1.5rem) / 2) 0;
}

/* The heading is now nested inside the "all videos" button's flex wrapper
   (more-videos.ejs), so the `>` rule above no longer matches — this
   restores the spacing via a descendant selector instead. */
#more-videos-container .channel-sidebar-heading {
  margin-bottom: 20px;
}

#more-videos-container .channel-sidebar-heading + .btn {
  margin-bottom: 10px;
}

@media (max-width: 576px) {
  #more-videos-container > div:first-child {
    padding-left: 0;
    padding-right: 0;
  }
}

#more-videos-container .video-card-meta {
  padding: calc(var(--bs-gutter-x, 1.5rem) / 2.75) 0px;
}

#more-videos-container .portfolio-section {
  margin-top: 1px;
  padding: calc(var(--bs-gutter-x, 1.5rem) / 2);
}

.channel-page-content .comment-box {
  padding: calc(var(--bs-gutter-x, 1.5rem) / 2) 0;
}

.channel-page-content .poll-box,
.channel-page-content .featured-channels-box,
.channel-page-content .friends-box,
.channel-page-content .subscribers-box,
.channel-page-content .subscriptions-box,
.channel-page-content .recent-activity-box,
.channel-module-box .blog-comment {
  padding: calc(var(--bs-gutter-x, 1.5rem) / 2);
}

/* .blog-single-detail .blog-comment .comment-wrapper .comment-box .media img
   (dark.css) forces every <img> under .media to 60x60 circular-crop —
   meant for the avatar, but it also catches embedded images/GIFs posted
   inside the comment body (.comment-detail is a descendant of .media too).
   That selector is 5 classes + a type deep, so beating it needs !important
   rather than just higher specificity. */
.blog-single-detail .blog-comment .comment-wrapper .comment-box .media img {
  width: 100px;
  height: 100px;
}

/* Same offending selector, now also catching the small emoji "images"
   reaction badges render as (scripts.ejs's hydrateReactionEmojiSpans/
   renderCommentReactions — class="emojione", not a real posted image) —
   those need their own tiny, inline-with-text sizing instead of either the
   60x60 avatar crop or the 100x100 embedded-image override above. Adding
   .emojione gives this one more specificity than both, so it always wins
   regardless of viewport (dark.css's own 30x30 mobile variant included). */
.blog-single-detail .blog-comment .comment-wrapper .comment-box .media img.emojione {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  border-radius: 0;
  object-fit: contain;
}

/* Comments module placed in the narrow left sidebar column (.sidebarbox)
   instead of the wide main column — roughly a quarter of the page width
   even on a wide desktop viewport, so the site-wide mobile-portrait
   @media (max-width: 576px) rules above never kick in for it, despite
   the column itself being just as cramped as a real mobile screen (and
   the "wide desktop" avatar/font sizes below assume the full page width
   is actually available). Reuses that same mobile layout — avatar+
   reactions as one row, everything else stacked at 100% below it — plus
   smaller avatars and fixed (not viewport-fluid) type sizes so both
   actually fit a column this narrow instead of just being a scaled-down
   version of the wide layout. */
.sidebarbox .comment-box > .media,
.sidebarbox .comment-box .comment-replies-list > .media {
  flex-direction: column;
}
.sidebarbox .comment-box > .media > *,
.sidebarbox .comment-box .comment-replies-list > .media > * {
  margin: 0px 0px 5px 0 !important;
}
.sidebarbox .comment-avatar-col {
  flex-direction: row;
  align-items: flex-start;
  padding-bottom: 2.5px;
}
.sidebarbox .blog-single-detail .blog-comment .comment-wrapper .comment-box .media img {
  width: 50px !important;
  height: 50px !important;
}
.sidebarbox .blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .title .comment-user h6,
.sidebarbox .blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .title .comment-date h6,
.sidebarbox .blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .title .comment-user .h6,
.sidebarbox .blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .title .comment-date .h6 {
  font-size: 13px !important;
}
.sidebarbox .blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .comment-detail p {
  font-size: 13px !important;
}
.sidebarbox .comment-reaction-emoji,
.sidebarbox .video-reaction-emoji {
  font-size: 16px !important;
}
.sidebarbox .title:has(> .comment-user):has(> .comment-date) {
  flex-direction: column;
}
.sidebarbox .title > .comment-user,
.sidebarbox .title > .comment-date {
  width: 100%;
}

/* dark.css makes the mobile header dropdowns a full-screen overlay via
   `position: fixed; bottom: 0; height: 100vh`. On real Android Chrome (not
   desktop responsive-mode testing), 100vh includes the space behind the
   browser's dynamic address bar, so the box is taller than what's actually
   visible — and since it's anchored to the bottom, the top of the box
   (.dropdown-header, the first child) gets pushed off-screen above the
   visible area. `dvh` accounts for the real visible viewport instead. */
@media (max-width: 767px) {
  .header-btn.custom-dropdown .dropdown-menu {
    height: 100dvh;
  }
}

.comment-detail .comment-embed-img {
  height: auto !important;
  max-width: 320px;
  width: auto !important;
  display: block;
  object-fit: unset !important;
  border-radius: 4px !important;
  margin-bottom: 7.5px;
  margin-top: 7.5px;
  cursor: zoom-in;
}

@media (max-width: 576px) {
  .comment-detail .comment-embed-img {
    max-width: 100%;
  }
}

/* Same [img] embed, inside a message bubble instead of a comment — needs
   its own (higher-specificity) override since the vendor theme has its own
   `.message img { width: 18px; }` rule (assumes a small inline icon, not a
   full embedded photo) that would otherwise win: that selector is 9 classes
   deep, so this has to match/beat it, not just add .comment-embed-img on
   its own. */
.messanger-section .chat-content .tab-box .user-chat .chat-history .avenue-messenger .chat .messages-content .message .comment-embed-img {
  width: 220px !important;
  max-width: 100% !important;
  height: auto !important;
  display: block;
  object-fit: unset !important;
  border-radius: 6px !important;
  margin: 4px 0 !important;
  cursor: zoom-in;
}

/* Click-to-zoom lightbox for comment images (scripts.ejs) — a single
   overlay instance created/destroyed on demand, same pattern as the
   "add to playlist" popover elsewhere in this file. */
.comment-lightbox-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.85);
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: zoom-out;
}

.comment-lightbox-overlay img {
  max-width: 90vw;
  max-height: 90vh;
  object-fit: contain;
  cursor: default;
}

.comment-lightbox-close {
  position: absolute;
  top: 20px;
  right: 24px;
  background: none;
  border: none;
  color: #fff;
  font-size: 32px;
  line-height: 1;
  cursor: pointer;
  opacity: 0.8;
}

.comment-lightbox-close:hover {
  opacity: 1;
}

/* Inline video embeds inside a comment body ([youtube]/[scenesfeed] tags) —
   capped at 320x180 (16:9) but shrinks on narrower comment columns instead
   of overflowing. */
.comment-embed-video-wrap {
  width: 100%;
  max-width: 320px;
  aspect-ratio: 16 / 9;
  margin: 6px 0;
  margin-bottom: 15px;
  border-radius: 6px;
  overflow: hidden;
  background: #000;
}

/* Same fix as the narrow-portrait-mobile Plyr control bar (@media
   max-width: 576px, above) — this box is always ~320px regardless of
   viewport, so Plyr's fixed-width controls (play/time/mute/a 60-90px
   volume slider/settings/pip/fullscreen) overflow it on any screen size,
   not just small ones. Dropping the volume slider here too frees enough
   width for the rest to fit, same as on mobile. */
.comment-embed-video-wrap .plyr__volume input[type=range] {
  display: none;
}

.comment-embed-video-wrap iframe,
.comment-embed-video-wrap video {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

.comment-embed-video-wrap > .plyr:not(:fullscreen),
.comment-embed-video-wrap > .plyr:not(:fullscreen) video {
  max-height: 180px;
}

/* Self-hosted [video]/[scenesfeed] comment embeds — a clickable thumbnail
   straight to the watch page instead of an inline player (a busy thread
   embedding several of these no longer means several live <video>
   elements on the page). Same 320px/16:9 box as .comment-embed-video-wrap
   above, which still covers the (unrelated) [youtube] tag/iframe case. */
.comment-embed-video-thumb {
  display: block;
  width: 100%;
  max-width: 320px;
  aspect-ratio: 16 / 9;
  margin: 6px 0 15px;
  border-radius: 6px;
  overflow: hidden;
  background: #000;
  position: relative;
}
/* !important needed here — .blog-single-detail...media img (see the
   .emojione comment above) forces every plain <img> under .media to
   100x100 with higher selector specificity than this class-based rule
   alone can beat. */
.comment-embed-video-thumb img {
  width: 100% !important;
  height: 100% !important;
  object-fit: cover !important;
  display: block;
  transition: opacity 0.15s ease;
}
.comment-embed-video-thumb:hover img {
  opacity: 0.8;
}
.comment-embed-video-thumb-fallback {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
}
.comment-embed-video-thumb::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 40px;
  height: 40px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M8 5v14l11-7z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 55% center;
  background-size: 18px 18px;
  pointer-events: none;
}

.comment-embed-tools > button {
  margin-bottom: 5px;
}

.comment-gif-panel {
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 8px;
  padding: 10px;
}

.comment-gif-results {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  gap: 6px;
  margin-top: 10px;
  max-height: 260px;
  overflow-y: auto;
}

.comment-gif-result {
  width: 100%;
  height: 80px;
  object-fit: cover;
  border-radius: 4px;
  cursor: pointer;
}

.comment-gif-result:hover {
  outline: 2px solid #ff5a3c;
}

.comment-video-panel {
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 8px;
  padding: 10px;
}

.comment-video-results {
  margin-top: 10px;
  max-height: 260px;
  overflow-y: auto;
  background-color: #051826 !important;
  color: #fff;
}

.comment-video-result {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px;
  border-radius: 4px;
  cursor: pointer;
}

.comment-video-result span {
  color: #fff !important;
}

.comment-video-result:hover {
  background: rgba(255, 255, 255, 0.08);
}

.comment-video-result img {
  width: 64px;
  height: 36px;
  object-fit: cover;
  border-radius: 4px;
  flex-shrink: 0;
}

.comment-video-result span {
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* "Change featured" picker (channel-view.ejs) — its own copy of
   .comment-video-result's thumbnail+title row styling above, deliberately
   NOT sharing that class name: the comment composer's video-embed feature
   (scripts.ejs) delegates a click handler off `.comment-video-result`
   sitewide to insert a [video] shortcode into a comment textarea. Reusing
   the class here (as this used to) made THAT handler also match clicks on
   these results, which have no comment textarea to insert into at all —
   `.closest('form').querySelector('textarea[name="body"]')` came back null
   and threw. Same story for `.comment-video-results` on the outer list —
   the video-embed panel's own capture-phase scroll delegation also keys
   off that exact class. */
.change-featured-box {
  margin-top: 15px;
}

.change-featured-source {
  display: flex;
  gap: 16px;
  margin-bottom: 10px;
  font-size: 13px;
}

.change-featured-results {
  margin-top: 10px;
  margin-bottom: 10px;
  max-height: 260px;
  overflow-y: auto;
  background-color: #051826 !important;
  color: #fff;
}

.change-featured-result {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px;
  border-radius: 4px;
  cursor: pointer;
  border: 1px solid transparent;
}

.change-featured-result span {
  color: #fff !important;
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.change-featured-result:hover {
  background: rgba(255, 255, 255, 0.08);
}

.change-featured-result img {
  width: 64px;
  height: 36px;
  object-fit: cover;
  border-radius: 4px;
  flex-shrink: 0;
}

.change-featured-result.is-selected {
  border: 1px solid #fff;
}

.change-featured-autoplay {
  width: 100%;
  margin-bottom: 10px;
}

.feather {
  position: relative;
  top: 2px;
}

.blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .title .comment-user h6,
.blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .title .comment-date h6 {
  line-height: 18px;
}

.blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .title .comment-user h6,
.blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .title .comment-user .h6,
.blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .title .comment-date h6,
.blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .title .comment-date .h6 {
  font-size: calc(14px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
  font-weight: bold;
}

.blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .title {
  margin-bottom: 5px;
  padding-bottom: 0px;
}

.blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .title {
  border-bottom: 0 none;
}

.channel-page-content .blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .title .comment-date h6 {
  text-transform: lowercase;
}

.blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .title .comment-date svg {
  margin-right: 5px;
}

/* Comment-approval feature's pending-state label (comment-item.ejs/
   video-comment-item.ejs) — only ever rendered for the Content Creator
   owner viewing their own still-private Troll comments, right next to
   .comment-date. */
.comment-pending-approval {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 11px;
  color: #dc3545;
  white-space: nowrap;
}
.comment-pending-approval svg {
  width: 13px;
  height: 13px;
  top: 0;
}

.blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .comment-detail p {
  font-size: calc(14px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
  line-height: 26px;
}

/* Emoji reactions, stacked directly under the avatar — a shared column
   (not a sibling in .media's own row, which put reactions beside the
   avatar instead of under it) containing both the avatar link and the
   reaction row. Old SL had these here, under the avatar. */
.comment-avatar-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex-shrink: 0;
}

/* iPadOS Safari specifically keeps a tapped link's native focus ring
   visible (a rectangular glow hugging the link's box) until focus moves
   elsewhere — inconsistent-looking here since it only shows up whenever
   an avatar link happens to still hold focus from an earlier tap, not on
   every avatar. -webkit-tap-highlight-color (dark.css, on body) only
   suppresses the brief tap FLASH, not this lingering :focus outline — a
   separate thing entirely. :not(:focus-visible) keeps it removed only
   for a tap/click-triggered focus, so real keyboard (Tab) navigation
   still gets a visible outline. */
.comment-avatar-col a:focus:not(:focus-visible) {
  outline: none;
}

.comment-reactions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  margin-top: 6px;
  max-width: 70px;
}

/* Rendered even with zero reactions for a logged-in viewer (see
   comment-item.ejs's comment above this element) so their own first
   reaction has somewhere to live-append into — this class is what
   actually keeps that empty shell from taking up visible space
   (margin-top/gap) until it has something in it. Toggled server-side at
   render and client-side in renderCommentReactions (scripts.ejs) after
   every react/unreact, not via :empty — the badges container's source
   has whitespace text nodes around the (possibly zero) buttons, which
   :empty treats as content. */
.comment-reactions.is-empty {
  display: none;
}

/* A reply notification's link scrolls here and flags it briefly — see
   partials/comment-highlight-script.ejs. Fades out on its own via the
   transition rather than being yanked off after the JS timeout, so it
   doesn't feel like it just vanishes. */
.comment-highlight {
  animation: comment-highlight-flash 2.6s ease-out;
}
@keyframes comment-highlight-flash {
  0% { background-color: rgba(255, 196, 0, 0.35); }
  100% { background-color: transparent; }
}

.comment-reaction-badges,
.video-reaction-badges {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 4px;
}

.comment-reaction-btn,
.video-reaction-btn {
  background: none;
  border: 0;
  border-radius: 10px;
  padding: 5px 0px;
  opacity: 0.8;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  line-height: 1;
}

.comment-reaction-btn:hover,
.comment-reaction-btn.active,
.video-reaction-btn:hover,
.video-reaction-btn.active {
  opacity: 1;
  background: unset;
}

.comment-reaction-emoji,
.video-reaction-emoji {
  font-size: calc(18px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
}

.video-reaction-emoji img {
  width: auto;
  height: 24px;
}

.comment-reaction-count,
.video-reaction-count {
  font-size: calc(8px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
  opacity: 1;
  padding: 2px 5px;
  margin-top: 3px;
  background-color: rgba(255, 255, 255, .8) !important;
  color: #000 !important;
}

.emojionearea.emojionearea-inline > .emojionearea-editor {
  left: 0;
  height: auto;
  min-height: unset;
}

/* The inline "add a reaction" widget itself (comment-item.ejs's
   .comment-reaction-inline-input / video-reactions.ejs's
   .video-reaction-inline-input) — a real emojionearea instance per
   comment/video now (see scripts.ejs's initInlineReactionPickers), not a
   shared floating popup — opening the picker is a single click on the
   widget's own collapsed placeholder instead of one click on a separate
   custom "+" button plus a second click on the widget's own toggle.
   Sized down to roughly match the old "+" button's footprint rather than
   the plugin's own (much larger, meant for a real text composer) default
   sizing — only the collapsed-state wrapper, not its internals (unverified
   in this bundled version, and the expanded picker needs to lay out
   however the plugin's own CSS already positions it). Only one
   emojionearea usage on the whole site (this one), so no extra scoping
   needed to avoid colliding with anything else. */
.emojionearea.emojionearea-standalone {
  width: 30px;
  min-width: 0;
  min-height: unset;
  font-size: calc(12px + (14 - 12) * ((100vw - 320px) / (1920 - 320)));
}

.emojionearea.emojionearea-standalone .emojionearea-editor {
  min-height: unset;
  padding: 0;
  line-height: calc(21px + (14 - 12) * ((100vw - 320px) / (1920 - 320)));
}

.emojionearea.emojionearea-standalone .emojionearea-editor.has-placeholder {
  background-position: 14px 2px;
  background-image: none !important;
}

.emojionearea.emojionearea-standalone .emojionearea-editor.has-placeholder > img {
  opacity: .6 !important;
  transition: opacity .5s ease;
}
.emojionearea.emojionearea-standalone:hover .emojionearea-editor.has-placeholder > img {
  opacity: 1 !important;
}

.emojionearea.emojionearea-inline {
  height: auto;
  min-height: unset;
  border-radius: 5px;
  border: 1px solid #ff5a3c;
}

.emojionearea.emojionearea-standalone .emojionearea-button > div,
.emojionearea.emojionearea-standalone .emojionearea-editor::before {
  display: none;
}

/* The picker panel defaults to position:absolute relative to its own
   .emojionearea wrapper — fine for .comment-reactions (its ancestor
   .media-body needed no real scrolling of its own, see that selector's
   own overflow:visible), but .video-react-popover genuinely needs its
   own overflow-y:auto for the category-vote list, and toggling that
   ancestor's overflow as the picker opened/closed reset its scroll
   position, visibly jumping that content back to the top mid-interaction
   (confirmed directly). position:fixed here escapes ANY ancestor's
   overflow clipping unconditionally, so neither popover ever needs its
   own overflow touched at all — scripts.ejs's initInlineReactionPickers
   computes and sets real top/left from the widget's own screen position
   on every open ("picker.show"), since fixed positioning makes the
   library's own math (computed for its normal absolute-relative-to-
   wrapper case) land in the wrong place otherwise. */
.emojionearea-picker {
  position: fixed !important;
  /* The library's own .emojionearea-picker-position-top/-left/-right/
     -bottom variants use a negative margin (e.g. margin-top:-269px) to
     visually pull the picker toward its anchor while still sitting in
     normal flow — a trick that only makes sense under its normal
     position:absolute-in-flow case. Combined with position:fixed and a
     JS-computed top/left (see scripts.ejs's "picker.show" handler), that
     same margin shifts the panel by another ~270px on top of the correct
     coordinates, landing it off-screen — confirmed directly (inline style
     said top:573px, real rendered position was top:-301px). Neutralized
     since positioning is 100% manual now regardless of which variant. */
  margin: 0 !important;
}

.comment-actions > input.comment-reaction-inline-input {
  display: none;
}

/* The theme's own comment-avatar rule
   (.blog-single-detail .blog-comment .comment-wrapper .comment-box .media
   img — bundled vendor CSS) targets every <img> inside .media, not just
   the actual avatar — including every emojioneemoji sprite image the
   picker renders (both the collapsed placeholder and each button in the
   expanded grid), forcing them all into 60x60 circular avatars. Restores
   this library's own real default sizing (see its bundled scss) rather
   than inventing new values; !important to beat that rule's 6-class
   specificity, same reasoning as the .media-body override above. */
.emojionearea img.emojioneemoji {
  width: 2.1ex !important;
  height: 2ex !important;
  min-width: 20px !important;
  min-height: 20px !important;
  border-radius: 0 !important;
  object-fit: contain !important;
}

.emojionearea .emojionearea-editor .emojioneemoji {
  margin: -0.2ex 0.15em 0.2ex .25em;
}

.channel-page-body .emojionearea .emojionearea-editor .emojioneemoji {
  margin: -0.2ex 0.15em 0ex .3em;
}

/* comment-item.ejs's row: the inline reaction widget (see .emojionearea
   above) on the left, edit/delete grouped and pushed to the right. */
.comment-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.video-watch-page .comment-actions {
  justify-content: flex-start;
}

.comment-actions-right {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-right: auto;
}

/* Always-visible row below .video-card-views (watch.ejs) and its copy
   inside the "+ react to video" popup — unlike .comment-reactions, this
   sits on its own line rather than beside a narrow avatar column, so it's
   a plain horizontal row instead of a column capped at 70px. */
.video-reactions {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 8px;
  clear: both;
}

.messanger-section .chat-content .tab-box .user-chat .chat-history .avenue-messenger .chat .messages-content .message {
  font-size: calc(14px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
}

.messanger-section .chat-content .tab-box .user-chat .chat-history .avenue-messenger .chat .messages-content .message .timestamp {
  font-size: calc(12px + (14 - 12) * ((100vw - 320px) / (1920 - 320)));
}

.messanger-section .chat-users .nav-tabs h6,
.messanger-section .chat-users .nav-tabs .h6 {
  font-size: calc(14px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
}

.comment-reply-form.theme-form {
  margin-top: 15px;
  padding-left: calc(20px + (30 - 20) * ((100vw - 320px) / (1920 - 320)));
}

.comment-replies-list {
  padding-bottom: 15px;
}

.video-watch-page .comment-replies-list {
  padding-bottom: 0;
}
.video-watch-page .comment-box {
  padding-bottom: 15px;
}

.messanger-section .chat-content .tab-box .user-chat .chat-history .avenue-messenger .chat .message-box .message-submit {
  padding: 2px;
}

.messanger-section .chat-content .tab-box .user-chat .chat-history .avenue-messenger .chat .messages-content .message.message-personal {
  background: #391427;
  text-align: left;
}

.nav-tabs .nav-link {
  border-radius: 0;
}

.portfolio-section {
  background-color: #0b1a2c;
  margin-top: 16px;
  padding-right: 15px;
  padding-left: 15px;
  padding-bottom: 15px;
}

.setting-section .tab-section .nav-pills .nav-link.text-danger.active {
  color: #fff !important;
}

/* The dark theme build's own Bootstrap-reset rule hardcodes dark-gray text
   (#212529) directly alongside the dark navy background — fine for the
   theme's own components (they all set their own explicit light text color
   deeper in the cascade), but anything relying on plain inheritance (our own
   custom classes: .notification-list, .people-body, .channel-about, etc.)
   would render nearly invisible without this. */
body {
  color: #f4eed7;
  font-size: calc(14px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
}

/* Theme's own global link-color default (`* a`) — was the accent red for
   every plain link site-wide (channel/friend usernames, "uploaded by X",
   menu items, etc.) that doesn't have a more specific color rule of its own. */
* a {
  color: #e8e9db;
}

* a:hover {
  color: #dccdb6;
}

/* .dropdown-menu itself hardcodes #212529 (dark gray) directly against its
   own dark navy background — same class of bug as the body-level one above,
   just scoped to a more specific selector so the body override alone
   doesn't reach it. */
.dropdown-menu {
  color: #f4eed7;
}

/* Messenger conversation-list names — carried over as red by the earlier
   blue-to-red accent-color substitution, but this is a name label, not a
   themed accent/button, so it should read as regular light text like other
   titles instead. */
.messanger-section .chat-users .nav-tabs .list-media .media-body h5,
.messanger-section .chat-users .nav-tabs .list-media .media-body .h5 {
  color: #e8e9db;
}

/* The theme's .sidebar-panel is `position: sticky; height: max-content` —
   fine while it's short, but with no height cap it just keeps growing with
   its own content and has no independent scroll, so once the right-hand
   column gets much taller (e.g. an infinite-scroll video list), reaching the
   sidebar's own lower items means scrolling the whole page. Cap it to the
   viewport and let it scroll internally instead. */
header,
.sidebar-panel {
  background-color: #051826;
}

.sidebar-panel {
  max-height: calc(100vh - 130px);
  overflow-y: auto;
  padding-left: 10px;
  padding-right: 10px;
  min-width: 77px;
}

/* The theme positions the flyout tooltip with `position: absolute; left:
   60px`, anchored to its <li> — but any ancestor with overflow-y: auto also
   clips (and reveals a scrollbar for) horizontal overflow, so the flyout
   would get clipped/scrollbarred by .sidebar-panel's new scroll above.
   `position: fixed` escapes all ancestor scroll clipping entirely; the JS in
   scripts.ejs sets its left/top on hover since fixed positioning has no
   anchor to a static offset like "60px from my li" the way absolute did. */
.sidebar-panel .sidebar-icon .tooltip-cls {
  position: fixed;
  left: 0;
  top: 0;
  /* Theme's own rule transitions `all`, which animated left/top sliding in
     from (0,0) the first time JS set them on hover. Only the scale should
     animate — position is set once, instantly, right before it appears. */
  transition: transform 0.3s ease;
}

.sidebar-panel .sidebar-icon > li > a {
  width: unset;
}

/* The theme re-declares `transition: all 0.5s ease` again on the :hover
   rule specifically — higher specificity than the rule above, so it still
   won during the actual hover and re-introduced the top/left slide-in. */
.sidebar-panel .sidebar-icon > li:hover .tooltip-cls {
  transition: transform 0.3s ease;
}

h3 {
  text-transform: uppercase;
  margin-bottom: 15px;
}

.video-card {
  position: relative;
}

/* Small in-section heading (index.ejs's "latest videos" / the watched-
   videos column's own label) — lives inside .portfolio-section itself,
   above just its own column's cards, not a separate .title-box above the
   category tabs, so it needs its own (lighter) treatment rather than
   inheriting .title-box h3's styling. */
.portfolio-section-title {
  font-size: 15px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: #b4b6c5;
  margin-bottom: 12px;
}

/* #latest-videos-col and #watched-videos-col (index.ejs) each get their
   own capped-height, independently-scrolling box instead of growing the
   whole page — #latest-videos-col's own feed is effectively unbounded
   (infinite scroll), which used to mean the page just kept growing
   forever past wherever #watched-videos-col's much shorter content
   ended, leaving dead space below it. Both columns get the exact same
   treatment here so neither one behaves differently from the other.
   The heading (.portfolio-section-title) stays a normal flex child
   above the scrolling area rather than living inside it, so it's
   always visible instead of scrolling away with the videos — the
   scroll wrapper (#latest-videos-scroll/#watched-videos-scroll) is a
   flex: 1 child that fills whatever height the heading doesn't use,
   with min-height: 0 so it actually shrinks and scrolls instead of
   just growing the (capped) column past its own max-height. */
.portfolio-section #latest-videos-col,
.portfolio-section #watched-videos-col {
  max-height: calc(100vh - 30px);
  display: flex;
  flex-direction: column;
}

.portfolio-section #latest-videos-scroll,
.portfolio-section #watched-videos-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  /* overflow-x hidden below is load-bearing, not decorative — Bootstrap's
     .row uses negative left/right margins for its gutters, which a
     .container's own padding normally absorbs; a plain overflow:auto box
     like this one has no such padding, so that sliver of negative-margin
     overflow was showing up as a genuine (if tiny) horizontal scrollbar. */
  overflow-x: hidden;
  /* Same thin dark-track/orange-thumb treatment the theme already uses
     for its own scrollable panels (.setting-box, .chat-box, etc. —
     dark.css) rather than the default OS scrollbar, kept consistent
     with them instead of inventing a new look. Firefox has no
     ::-webkit-scrollbar-* support at all, hence the scrollbar-color
     fallback (same two colors, just via the standard property). */
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 90, 60, 0.5) rgba(255, 255, 255, 0.05);
}
.portfolio-section #latest-videos-scroll::-webkit-scrollbar,
.portfolio-section #watched-videos-scroll::-webkit-scrollbar {
  width: 3px;
}
.portfolio-section #latest-videos-scroll::-webkit-scrollbar-track,
.portfolio-section #watched-videos-scroll::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, 0.05);
  border-radius: 6px;
}
.portfolio-section #latest-videos-scroll::-webkit-scrollbar-thumb,
.portfolio-section #watched-videos-scroll::-webkit-scrollbar-thumb {
  background: rgba(255, 90, 60, 0.5);
  border-radius: 4px;
}
.portfolio-section #latest-videos-scroll::-webkit-scrollbar-thumb:hover,
.portfolio-section #watched-videos-scroll::-webkit-scrollbar-thumb:hover {
  background: #ff5a3c;
}


.video-card-meta {
  padding: 8px 2px 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.video-card-title {
  display: block;
  font-size: calc(14px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
  font-weight: 600;
  color: #e8e9db;
  line-height: calc(18px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
}

.video-card-title:hover,
.video-card-title:focus {
  color: #dccdb6;
}

/* position: relative lives on the thumbnail link itself (not a class on
   whatever wraps it) so the duration badge works the same regardless of
   which context video-thumb.ejs is rendered in — grid cards, sidebar
   lists, playlist rows, etc. */
.video-thumb-link {
  position: relative;
}

.video-thumb-duration {
  position: absolute;
  right: 6px;
  bottom: 6px;
  padding: 1px 5px;
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.75) !important;
  color: #fff !important;
  font-size: 11px;
  font-weight: 600;
  line-height: 16px;
}

.video-card-views {
  font-size: calc(11px + (14 - 12) * ((100vw - 320px) / (1920 - 320)));
  opacity: 0.65;
  line-height: calc(14px + (14 - 12) * ((100vw - 320px) / (1920 - 320)));
}

.video-card-uploader {
  display: flex;
  align-items: center;
  gap: 6px;
  color: #b4b6c5;
}

.video-card-uploader:hover,
.video-card-uploader:focus {
  color: #dccdb6;
}

.video-card-uploader-avatar {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}

.video-card-uploader span {
  font-size: calc(11px + (13 - 11) * ((100vw - 320px) / (1920 - 320)));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.video-card-category {
  align-self: flex-start;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  opacity: 0.6;
}

.add-to-playlist-trigger,
.video-react-trigger {
  background: none;
  border: 0;
  padding: 0;
  margin-left: 4px;
  color: inherit;
  opacity: 0.75;
  text-decoration: underline;
  cursor: pointer;
  font-size: inherit;
  width: auto;
  white-space: nowrap;
  margin: 2px 0;
}

/* Wraps both watch.ejs triggers (watch.ejs) so they float together as one
   unit instead of each floating independently (which stacked them in
   reverse DOM order). */
.video-card-views-triggers {
  float: right;
  display: inline-flex;
  align-items: center;
  position: relative;
  top: 2px;
}

.video-card-views-triggers > button {
  padding-right: 5px;
  padding-left: 5px;
}

.video-watch-page .video-card-views:before{
  margin-top: 5px;
}
.video-watch-page .video-card-views:after,
.video-watch-page .video-card-views:before{
  display: block;
  clear: both;
  content: "";
}

.add-to-playlist-trigger:hover,
.video-react-trigger:hover {
  opacity: 1;
}

/* Built/positioned on demand by scripts.ejs, appended straight to <body> —
   reuses .dropdown-menu purely for its look (see the JS comment). This is
   just the popover's own internal layout. */
.add-to-playlist-popover {
  width: 240px;
  max-height: 320px;
  overflow-y: auto;
  padding: 10px;
}

.add-to-playlist-header {
  font-size: 12px;
  text-transform: uppercase;
  opacity: 0.6;
  margin-bottom: 8px;
}

.add-to-playlist-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 10px;
}

.add-to-playlist-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 400;
  margin: 0;
  cursor: pointer;
}

.add-to-playlist-empty {
  font-size: 12px;
  opacity: 0.6;
  margin: 0;
}

.add-to-playlist-create {
  display: flex;
  gap: 6px;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  padding-top: 10px;
}

.add-to-playlist-create input {
  flex: 1;
  min-width: 0;
}

/* "+ react to video" popup (scripts.ejs, video-react-popup.ejs) — same
   on-demand dropdown-menu-look popover as .add-to-playlist-popover, just
   wider to comfortably fit the category vote list's longer rows. */
.video-react-popover {
  width: 300px;
  max-height: 400px;
  overflow-y: auto;
  padding: 10px;
}

.video-react-popup-header {
  font-size: 12px;
  text-transform: uppercase;
  opacity: 0.6;
  margin-bottom: 8px;
}

.video-react-popup-section {
  margin-bottom: 12px;
}

.video-react-popup-section:last-child {
  margin-bottom: 0;
}

.video-react-popup-label {
  font-size: 13px;
  font-weight: 500;
  margin-bottom: 6px;
}

.video-category-vote-locked-note {
  font-size: 12px;
  opacity: 0.7;
  margin: 0 0 8px;
}

.video-category-vote-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.video-category-vote-btn {
  width: 100%;
  background: rgba(255, 255, 255, 0.06);
  border: 0;
  border-radius: 6px;
  padding: 6px 8px;
  display: flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  font-size: 13px;
  opacity: 0.85;
}

.video-category-vote-btn:hover,
.video-category-vote-btn.active {
  opacity: 1;
  background: rgba(255, 255, 255, 0.16);
}

.video-category-vote-name {
  flex: 1;
  text-align: left;
  color: #fff;
}

.video-category-vote-current-badge {
  font-size: 10px;
  text-transform: uppercase;
  opacity: 0.6;
  color: #fff;
}

.video-category-vote-count {
  font-size: 11px;
  opacity: 0.7;
  color: #fff;
  min-width: 16px;
  text-align: right;
}

/* Video responses (partials/video-responses.ejs) — old YouTube-2008-style
   horizontal slider, one row, above comments. .video-response-card reuses
   .video-card's thumbnail aspect-ratio/meta styling as-is (just adds a
   fixed slider width + the remove button). */
.video-responses-section {
  margin-bottom: 24px;
}

.video-responses-slider {
  display: flex;
  gap: 12px;
  overflow-x: auto;
  padding-bottom: 8px;
}

.video-response-card {
  flex: 0 0 200px;
  width: 200px;
}

.video-response-remove-btn,
.playlist-remove-video-btn {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.6);
  border: 0;
  border-radius: 100%;
  color: #fff;
  cursor: pointer;
  z-index: 2;
}

.video-response-remove-btn > .feather {
  top: 0;
}

.playlist-remove-video-btn > .feather {
  top: 0;
}

.playlist-reorder-btns {
  position: absolute;
  top: 6px;
  left: 6px;
  display: flex;
  gap: 4px;
  z-index: 2;
}

.playlist-reorder-btn {
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.6);
  border: 0;
  border-radius: 100%;
  color: #fff;
  cursor: pointer;
}

.playlist-reorder-btn:disabled {
  opacity: 0.3;
  cursor: default;
}

.playlist-reorder-btn > .feather {
  top: 0;
}

.video-response-form {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}

.video-response-form select {
  flex: 1;
  max-width: 320px;
}

.empty-state {
  padding: 2rem 0;
  opacity: 0.7;
}

/* /playlists cards (views/playlists.ejs) — stacked-thumbnail look with a
   video-count badge, matching the reference (YouTube's own playlists
   grid), redone with this site's card conventions. */
.playlist-card-thumb {
  position: relative;
  display: block;
  padding-top: 56.25%;
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  border-radius: 8px;
  overflow: hidden;
}

.playlist-card-count {
  position: absolute;
  bottom: 8px;
  right: 8px;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  background: rgba(0, 0, 0, 0.75);
  border-radius: 4px;
  color: #fff;
  font-size: 12px;
}

.playlist-card-count .feather {
  top: 0;
}

.playlist-card-meta {
  padding: 8px 2px 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.playlist-card-title {
  font-size: 14px;
  font-weight: 600;
  color: #e8e9db;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.playlist-card-title:hover {
  color: #dccdb6;
}

.playlist-card-desc {
  font-size: 12px;
  opacity: 0.65;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.playlist-card-view-link {
  font-size: 12px;
  opacity: 0.7;
  text-decoration: underline;
}

.playlist-delete-form {
  margin-top: 6px;
}

.playlist-sort-select {
  width: auto;
}

/* Dismissible "new here?" tutorial banner (partials/tutorial-banner.ejs) —
   shared between the homepage and the channel page. On the channel page,
   channelCss.js generates per-owner color overrides scoped to
   .channel-page-content's descendants — !important here guarantees this
   banner always looks the same regardless of whichever channel it's shown
   on, rather than depending on it just happening to sit outside whatever
   channelCss.js currently targets. */
.tutorial-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  background-color: #0b1a2c !important;
  border: 1px solid rgba(255, 90, 60, 0.4);
  border-radius: 8px;
  padding: 14px 16px;
  margin-top: 15px;
  margin-bottom: 15px;
}

.tutorial-banner-text {
  font-size: 13px;
  opacity: 0.9;
  color: #e8e9db !important;
}

.tutorial-banner-text a {
  color: #ff5a3c !important;
  text-decoration: underline;
}

.tutorial-banner-close {
  flex-shrink: 0;
  background: none;
  border: none;
  color: #cfd3da !important;
  opacity: 0.7;
  padding: 4px;
  cursor: pointer;
}

.tutorial-banner-close:hover {
  opacity: 1;
}

/* Live Rooms — homepage's primary section (see services/liveRooms.js
   getLiveRoomsData()), rendered above the video grid with bigger cards
   since rooms, not videos, are the site's main focus now. */
.live-rooms-title-box {
  margin-top: 0;
  padding-top: 5px;
}

.live-rooms-title-box h3 {
  color: #ff5a3c;
}

.live-rooms-section {
  margin-bottom: 30px;
}

.live-rooms-empty {
  background-color: #0b1a2c;
  border-radius: 8px;
  padding: 40px 20px;
  text-align: center;
  opacity: 0.85;
}

.live-rooms-empty p {
  margin-bottom: 10px;
}

.live-rooms-empty form {
  margin-top: 15px;
}

.live-room-card {
  display: block;
  background-color: #0b1a2c;
  border-radius: 10px;
  overflow: hidden;
  text-decoration: none;
  transition: transform 0.2s ease;
}

.live-room-card:hover {
  transform: translateY(-3px);
}

.live-room-thumb {
  position: relative;
  width: 100%;
  padding-top: 56.25%;
  background-color: #06101d;
  background-image: url('/assets/images/video-placeholders/blanksf.png');
}

.live-room-badge {
  position: absolute;
  top: 12px;
  left: 12px;
  background-color: #ff5a3c;
  color: #000;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.5px;
  padding: 3px 8px;
  border-radius: 4px;
  text-transform: uppercase;
}

.live-room-meta {
  padding: 12px 14px 16px;
}

.live-room-title {
  font-size: 16px;
  font-weight: 700;
  color: #e8e9db;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.live-room-host {
  font-size: 12px;
  opacity: 0.65;
  margin-top: 2px;
}

.live-room-stats {
  display: flex;
  gap: 16px;
  margin-top: 10px;
  font-size: 12px;
  opacity: 0.8;
}

.live-room-stats span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.live-room-stats .feather {
  top: 0;
}

/* Same live-room concept as the homepage card, but horizontal — thumbnail
   left, info right — so it reads well spanning a channel page's full
   content-column width instead of being boxed into a grid cell. */
.channel-live-room {
  display: flex;
  align-items: stretch;
  border-radius: 10px;
  overflow: hidden;
  text-decoration: none;
  margin-bottom: 20px;
  transition: transform 0.2s ease;
}

.channel-live-room:hover {
  transform: translateY(-2px);
}

.channel-live-room-thumb {
  position: relative;
  flex: 0 0 280px;
  background-color: #06101d;
  background-image: url('/assets/images/video-placeholders/blanksf.png');
}

.channel-live-room-meta {
  flex: 1 1 auto;
  padding: 16px 20px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
}

.channel-live-room-title {
  font-size: 20px;
  font-weight: 700;
  color: #e8e9db;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.channel-live-room-meta .live-room-stats {
  margin-top: 12px;
  font-size: 13px;
}

@media (max-width: 767px) {
  .channel-live-room {
    flex-direction: column;
  }

  .channel-live-room-thumb {
    flex: none;
    width: 100%;
    padding-top: 42%;
  }
}

/* Used to be a fixed max-width: 640px, single-column layout — now sized by
   its col-lg-8 wrapper instead (see watch.ejs), to make room for the
   uploader-info/other-videos sidebar in col-lg-4. */

#video-comments-container {
  margin-top: 15px;
}

.plyr audio,
.plyr iframe,
.plyr video {
  display: block;
  height: 100%;
  width: 100%;
}

.channel-page-content .plyr:not(:fullscreen) audio {
  max-height: 442px;
}

/* Same responsive-aspect-ratio fix as .video-watch-page above — see that
   comment for why a flat max-height isn't responsive on a big screen. */
.channel-page-content .plyr:not(:fullscreen) .plyr__video-wrapper {
  aspect-ratio: 16 / 9;
  height: auto;
}

.channel-page-content .plyr:not(:fullscreen) video {
  object-fit: contain;
}

/* Watch page sidebar (partials/watch-sidebar.ejs) — uploader info, sub/
   friend actions, and their other videos, filling the col-lg-4 next to
   the player that used to just be empty space. */
.watch-page-row {
  margin-top: 15px;
  margin-bottom: 90px;
}

.watch-sidebar {
  background-color: #0b1a2c;
  border-radius: 8px;
  padding: 16px;
}

.watch-uploader-card {
  display: flex;
  align-items: center;
  gap: 12px;
}

.watch-uploader-avatar img {
  width: 100px;
  height: 100px;
  object-fit: cover;
  display: block;
}

.watch-uploader-info {
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.watch-uploader-name {
  color: #e8e9db;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.watch-uploader-name:hover {
  color: #dccdb6;
}

.watch-uploader-handle {
  font-size: calc(14px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
  opacity: 0.6;
}

.watch-uploader-type {
  font-size: calc(12px + (14 - 12) * ((100vw - 320px) / (1920 - 320)));
  text-transform: uppercase;
  letter-spacing: 0.04em;
  opacity: 0.5;
  margin-top: 2px;
}

.watch-uploader-all-videos {
  font-size: 13px;
  opacity: 0.75;
  margin-top: 4px;
}

.watch-uploader-all-videos:hover,
.watch-uploader-all-videos:focus {
  opacity: 1;
}

.watch-uploader-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 14px;
}

.watch-uploader-actions form {
  margin: 0;
}

/* Capped + independently-scrolling instead of growing the page, same
   pattern as the homepage's #latest-videos-col/#latest-videos-scroll
   (site.css's own comment on that pair explains the min-height:0/flex
   reasoning — identical here). 720px comfortably fits today's initial
   8-item page without a scrollbar; infinite-scrolled pages beyond that
   scroll internally instead of growing this section further. */
.watch-other-videos {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  max-height: 720px;
  display: flex;
  flex-direction: column;
}

.watch-other-videos-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 90, 60, 0.5) rgba(255, 255, 255, 0.05);
}
.watch-other-videos-scroll::-webkit-scrollbar {
  width: 3px;
}
.watch-other-videos-scroll::-webkit-scrollbar-track {
  background: rgba(255, 255, 255, 0.05);
  border-radius: 6px;
}
.watch-other-videos-scroll::-webkit-scrollbar-thumb {
  background: rgba(255, 90, 60, 0.5);
  border-radius: 4px;
}
.watch-other-videos-scroll::-webkit-scrollbar-thumb:hover {
  background: #ff5a3c;
}

.watch-other-video-item {
  display: flex;
  gap: 10px;
  padding: 8px 0;
}

.watch-other-video-item .bg-size {
  flex: 0 0 120px;
  width: 120px;
  height: 68px;
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: 6px;
}

.watch-other-video-meta {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  justify-content: center;
}

/* "You might also like" (partials/watch-recommendations.ejs) — same row
   shape as .watch-other-video-item, title weighted more prominently than
   the description snippet per explicit request. */
.watch-recommendations {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.watch-recommendation-item {
  display: flex;
  gap: 10px;
  padding: 8px 0;
}

.watch-recommendation-item .bg-size {
  flex: 0 0 120px;
  width: 120px;
  height: 68px;
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: 6px;
}

.watch-recommendation-meta {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  justify-content: center;
}

.watch-recommendation-title {
  font-size: calc(14px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
  font-weight: 600;
  color: #e8e9db;
}

.watch-recommendation-description {
  margin: 0;
  font-size: 12px;
  opacity: 0.65;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.watch-other-video-title {
  font-size: calc(14px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
  font-weight: 600;
  color: #e8e9db;
  text-decoration: none;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.watch-other-video-title:hover {
  color: #dccdb6;
}

.watch-other-video-views {
  font-size: 11px;
  opacity: 0.6;
}

/* Playlist queue widget — shown only when the current video was reached
   via a playlist link (?list=ID), first in .watch-sidebar (before
   .watch-uploader-card). Deliberately not a literal clone of YouTube's own
   up-next queue overlay (per request) — a plain scrollable list fits the
   existing sidebar better. */
.watch-playlist-queue {
  margin-bottom: 16px;
  padding-bottom: 16px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.watch-playlist-queue-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}

.watch-playlist-queue-title {
  font-weight: 600;
  color: #e8e9db;
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.watch-playlist-queue-title:hover {
  color: #dccdb6;
}

.watch-playlist-queue-position {
  font-size: 12px;
  opacity: 0.6;
  flex-shrink: 0;
  margin-left: 8px;
}

.watch-playlist-queue-list {
  max-height: 400px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.watch-playlist-queue-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px;
  border-radius: 6px;
  text-decoration: none;
}

.watch-playlist-queue-item:hover {
  background-color: rgba(255, 255, 255, 0.05);
}

.watch-playlist-queue-item.active {
  background-color: rgba(255, 255, 255, 0.1);
}

.watch-playlist-queue-num {
  flex: 0 0 16px;
  font-size: 11px;
  opacity: 0.5;
  text-align: center;
}

.watch-playlist-queue-thumb {
  flex: 0 0 64px;
  width: 64px;
  height: 36px;
  border-radius: 4px;
}

.watch-playlist-queue-item-title {
  font-size: 12px;
  color: #e8e9db;
  min-width: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

@media (max-width: 991px) {
  .watch-sidebar {
    margin-top: 20px;
  }
}

.video-player-wrap {
  position: relative;
  width: 100%;
  padding-top: 56.25%;
  background: #000;
  overflow: hidden;
}

.video-player-wrap iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.plyr-video-wrap {
  overflow: hidden;
}

.plyr-video-wrap > video {
  aspect-ratio: 16 / 9;
  height: auto;
  width: 100%;
}

/* Channel featured-video placeholder (partials/video-player.ejs's
   deferUntilClick) — same box as the real <video> above, but plain
   background-image + a play icon until actually clicked. */
.video-click-to-load {
  position: relative;
  aspect-ratio: 16 / 9;
  width: 100%;
  background-color: #000;
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  cursor: pointer;
}
.video-click-to-load::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 60px;
  height: 60px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M8 5v14l11-7z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 55% center;
  background-size: 26px 26px;
  pointer-events: none;
}

/* YouTube-style hover-to-pause — Plyr's own play-large button only ever
   shows a Play icon, and only while actually paused (see scripts.ejs for
   the click-to-pause/play wiring, which reuses Plyr's own clickToPlay for
   that). This is a separate button layered in the same spot, shown only
   while playing, so there's something to click there too. Tied to Plyr's
   own .plyr--hide-controls toggle (not :hover) so it shows/hides in sync
   with the real control bar on both mouse and touch — :hover alone gets
   stuck "on" after a tap on touch devices, since there's no hover-out
   event to clear it, which is why this never disappeared on mobile.
   Kept as its own class rather than reusing .plyr__control--overlaid,
   which would inherit Plyr's own ".plyr--playing hides this" rule and
   fight the rule below — same visual values as that button
   (background/border-radius/color/padding/opacity), just independent. */
.plyr__video-wrapper .custom-pause-overlay {
  display: none;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 3;
  align-items: center;
  justify-content: center;
  background: var(--plyr-color-main, #00b2ff);
  border: 0;
  border-radius: 100%;
  color: #fff;
  padding: 15px;
  opacity: 0.9;
  cursor: pointer;
}
.plyr--video.plyr--playing:not(.plyr--hide-controls) .custom-pause-overlay {
  display: flex;
}
.custom-pause-overlay:hover {
  opacity: 1;
}

.custom-pause-overlay > .feather {
  top: 0;
}

.video-watch-meta {
  padding-top: 12px;
  margin-bottom: 30px;
}

#featured-video-container .video-watch-meta {
  margin-bottom: 0px;
}

.video-watch-meta > h3 {
  margin-bottom: 0;
}

.empty-hint {
  padding: 12px 0px;
  opacity: 0.6;
  font-size: calc(10px + (12 - 10) * ((100vw - 320px) / (1920 - 320)));
}

.guest-auth-btns {
  display: flex;
  align-items: center;
  padding: 0 10px;
}

@media (max-width: 576px) {
  .guest-auth-btns {
    padding-right: 0;
  }
}

/* The theme's own style.css has a blanket rule zeroing out
   `.option-list .header-btn:last-child a` padding-right, assuming the last
   header button is always the profile dropdown. Our guest login/sign-up
   buttons became the new last-child, so restore their normal btn-sm padding
   here (same selector specificity, loaded after style.css). */
header .header-section .header-right .option-list .header-btn.guest-auth-btns a {
  padding-right: 20px;
}

.btn-solid.btn-danger {
  background-color: #dc3545;
  border-color: #dc3545;
  color: #fff;
}

.message-box button.message-submit {
  background: transparent;
  cursor: pointer;
}

.no-thread-selected {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  opacity: 0.6;
}

.notification-list,
.people-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.notification-list li,
.people-list li {
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.notification-list li a {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 6px;
}

.notification-list li a:hover {
  background-color: rgba(255, 90, 60, 0.06);
}

.notification-list img {
  width: 40px;
  height: 40px;
  object-fit: cover;
}

.notification-body h5 {
  margin-bottom: 3px;
  font-weight: 600;
}

.notification-body h5 span {
  font-weight: 700;
}

.notification-body h6 {
  opacity: 0.6;
  font-weight: 500;
}

.people-list-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 6px;
}

.people-list-item img {
  width: 44px;
  height: 44px;
  object-fit: cover;
}

.people-body {
  flex: 1;
  min-width: 0;
}

.people-body h6 {
  opacity: 0.6;
}

.people-list-stats {
  display: flex;
  gap: 12px;
  font-size: 13px;
  opacity: 0.7;
  margin-top: 2px;
}

.people-list-stats .people-list-online {
  color: #2ecc71;
  opacity: 1;
}

.people-list-about {
  font-size: 13px;
  opacity: 0.8;
  margin: 4px 0 0;
  max-width: 480px;
}

.people-body a,
.notification-list a,
.mini-people-list a {
  color: inherit;
  text-decoration: none;
}

.video-watch-meta a {
  color: inherit;
}

.video-card-views a {
  text-decoration: underline !important;
}

.people-body a:hover {
  text-decoration: underline;
}

.people-actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

.people-actions form {
  margin: 0;
}

/* On narrow screens the actions row (message/friend-request/unblock
   buttons) was squeezed into whatever space was left next to the avatar +
   name, since .people-list-item never wrapped and .people-actions kept
   flex-shrink: 0. Wrapping the row and letting actions take the full width
   below the avatar/name gives buttons room to actually be tappable. */
@media (max-width: 576px) {
  .people-list-item {
    flex-wrap: wrap;
  }

  .people-actions {
    flex-basis: 100%;
    width: 100%;
  }

  .people-actions form,
  .people-actions a,
  .people-actions .btn {
    flex: 1;
  }
}

.plain-settings-form fieldset {
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 8px;
  padding: 16px 20px;
  margin-bottom: 20px;
}

.plain-settings-form legend {
  width: auto;
  font-size: 15px;
  font-weight: 700;
  padding: 0;
}

/* Bare <input type="color"> has no .form-control class, so it rendered
   with the browser's own default chrome — a stark white-bordered square
   that didn't match any other field's dark background/border/radius on
   the page. Matches .form-control's own colors so it reads as part of
   the same form instead of a raw, unstyled browser widget. */
.plain-settings-form input[type="color"] {
  width: 100%;
  height: 38px;
  max-width: 38px;
  display: block;
  padding: 2px;
  background-color: #0b1a2c;
  border: 1px solid #ced4da;
  border-radius: 0.25rem;
}

.form-check-inline-group {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.btn-solid.btn-danger:hover,
.btn-solid.btn-danger:focus {
  background-color: #bb2d3b;
  border-color: #bb2d3b;
  color: #fff;
}

.theme-form, .theme-form .form-control {
  margin-bottom: 15px;
}

.theme-form textarea.form-control {
  min-height: 150px;
}

div.title-box {
  text-transform: uppercase;
  margin: 15px 0px;
}

.title-box-divider {
  margin: 0 6px;
  opacity: 0.35;
  font-weight: 400;
}

.title-box-link {
  font-size: 13px;
  font-weight: 500;
  text-transform: none;
  letter-spacing: normal;
  opacity: 0.75;
}

.title-box-divider, .title-box-link {
  position: relative;
  top: -1px;
}

.title-box-link:hover,
.title-box-link:focus {
  opacity: 1;
}

.messanger-section .chat-content .tab-box .user-chat .chat-history .avenue-messenger .chat .messages-content .message .timestamp {
  position: static;
  color: #fff;
  font-style: italic;
}

/* Channel view page */

.channel-topbar {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: 16px 0;
  margin-bottom: calc(var(--bs-gutter-x, 1.5rem) / 2);
}

.channel-topbar img {
  width: 100px;
  height: 100px;
  object-fit: cover;
}

.channel-topbar-avatar {
  position: relative;
  width: 100px;
  height: 100px;
  flex-shrink: 0;
}

.avatar-edit-btn {
  position: absolute;
  bottom: -2px;
  right: -2px;
  width: 24px;
  height: 24px;
  border-radius: 100%;
  background: #ff5a3c;
  color: #000;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  border: 2px solid var(--body-bg, #fff);
}

.avatar-edit-btn svg {
  width: 14px;
  height: 14px;
  top: -1px;
}

.avatar-edit-btn input[type="file"] {
  display: none;
}

.url-field-with-upload {
  position: relative;
}

/* .plain-settings-form prefix matches the vendor's `.theme-form.form-sm
   .form-control { padding: 8px 14px }` (dark.css) at equal specificity (3
   classes each) — without it, that shorthand padding rule wins regardless
   of site.css loading after dark.css, since 2 classes < 3. */
.plain-settings-form .url-field-with-upload .form-control {
  padding-right: 66px;
}

/* Small "clear/reset to default" button next to any free-typed text/number
   field on the channel settings page (views/channel.ejs) — .field-with-clear
   is the plain case (its own wrapper), while .url-field-with-upload fields
   already have a position:relative wrapper with an upload icon at right:0,
   so the clear button there sits just to its left instead. */
.field-with-clear {
  position: relative;
}

/* Same .plain-settings-form specificity fix as .url-field-with-upload
   .form-control above. */
.plain-settings-form .field-with-clear .form-control {
  padding-right: 30px;
}

.field-clear-btn {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: #647589;
  background: none;
  border: none;
  padding: 0;
  font-size: 18px;
  line-height: 1;
}

.field-clear-btn:hover {
  color: #ff5a3c;
}

.url-field-with-upload .field-clear-btn {
  right: 34px;
}

.inline-upload-btn {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: #647589;
}

.inline-upload-btn:hover {
  color: #ff5a3c;
}

.inline-upload-btn svg {
  width: 16px;
  height: 16px;
}

.inline-upload-btn input[type="file"] {
  display: none;
}

.channel-topbar-name h3 {
  margin: 0 0 1px 0;
}

.channel-topbar-name h6 {
  opacity: 1;
  margin: 0;
}

/* Homepage hero panel — the SEO tagline plus (when nothing's live) the
   "Upload a Video"/"Go Live" CTAs, in one centered card instead of bare
   text floating against the page background (see index.ejs). Same
   background/radius as .live-rooms-empty used for its own centered
   panel, just bigger padding since this is the homepage's actual hero now,
   not a small empty-state footnote. */
.homepage-hero {
  background-color: #0b1a2c;
  border-radius: 8px;
  padding: 36px 24px;
  text-align: center;
}

.homepage-hero-tagline {
  max-width: 640px;
  margin: 0 auto;
  font-size: calc(15px + (18 - 15) * ((100vw - 320px) / (1920 - 320)));
  font-weight: 500;
  opacity: 0.9;
}

/* Only actually needs the gap when the CTA row follows it — a live-rooms
   grid page has just the tagline alone in the panel. */
.homepage-hero-tagline:not(:last-child) {
  margin-bottom: 24px;
}

/* The "Go Live" button is a real <form method="POST"> (starting a room
   isn't a GET-able page), not a link, so it needs to sit inline like its
   sibling <a> rather than stack as its own block. */
.homepage-cta-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 16px;
}

.homepage-cta-form {
  display: inline-flex;
  margin: 0;
}

.homepage-cta-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 180px;
  justify-content: center;
}

.homepage-cta-row .feather {
  top: 0;
}

.channel-group-badge {
  display: inline-block;
  vertical-align: middle;
  background-color: #ff5a3c;
  color: #000;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  padding: 2px 8px 1px 8px;
  border-radius: 999px;
  margin-right: 6px;
  margin-top: 5px;
  position: relative;
  top: -2.5px;
  cursor: pointer;
}

/* Moderator/Admin badge (channel-view.ejs's channel-topbar-name only) —
   same badge shape, just a dark navy background instead of the group
   badges' orange. Also swaps to white text: the base rule's #000 would be
   unreadable against this much darker background. */
.channel-group-badge-moderator.channel-group-badge {
  background-color: #051826;
  color: #fff;
}

/* Same on-demand dropdown-menu-look popover as .add-to-playlist-popover —
   just a short static sentence instead of a fetched list, explaining what
   this badge means (see scripts.ejs's click handler). */
.channel-group-badge-tooltip {
  width: 240px;
  padding: 10px 12px;
  font-size: 13px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  line-height: 1.4;
}

.channel-group-badge-tiny {
  font-size: 8px;
  line-height: 16px;
  padding: 1px 6px 1px 6px;
  margin-right: 0;
  margin-bottom: -5px;
  text-align: center;
  max-width: 100px;
  display: inline-block;
  color: #000 !important;
  vertical-align: text-top;
}

.channel-group-badge-tiny.channel-group-badge {
  top: -5px;
}

.title:has(> .comment-user):has(> .comment-date) > * {
  margin-right: 10px;
  margin-left: 0 !important;
}
@media (max-width: 576px) {
  .title:has(> .comment-user):has(> .comment-date) > * {
    margin-bottom: 5px !important;
  }
  html .channel-preview-panel-inner {
    gap: 5px;
  }
  html .comment-avatar-col {
    flex-direction: row;
    align-items: flex-start;
    padding-bottom: 2.5px;
  }
  .comment-reactions {
    padding: 0 15px;
  }
  .comment-actions-right > button {
    max-width: 24px;
    overflow: hidden;
    text-indent: -17%;
    white-space: nowrap;
    min-height: 24px;
  }
  .comment-actions > button:not(.comment-vote-btn) {
    max-width: 25px;
    overflow: hidden;
    text-indent: -15%;
    white-space: nowrap;
    min-height: 24px;
  }
  .comment-actions > button.comment-vote-btn {
    min-height: 24px;
  }
  .emojionearea.emojionearea-inline {
    min-height: 24.19px !important;
  }
  .blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .title .comment-date > * {
    font-size: 12px !important;
    margin-top: -5px;
  }
  .mini-people-list li {
    width: 33.333333% !important;
    padding-left: 5px;
    padding-right: 5px;
  }
  .mini-people-list {
    gap: 10px 0px !important;
  }
  header .header-section .header-left .brand-logo + .btn-group {
    margin-left: -60px;
  }
  header .header-section .header-btn.app-btn {
    margin-right: 5px;
  }
  .channel-group-badge {
    width: 100%;
    text-align: center;
    margin-bottom: 5px;
  }
}

@media (min-width: 578px) {
  .comment-actions > button.comment-vote-btn {
    min-height: 25px;
  }
}

.channel-topbar-actions {
  margin-left: auto;
  display: flex;
  gap: 8px;
}

/* Was a column of centered, h4-sized stat blocks — huge and attention-
   grabbing for what's really just reference numbers. Old YouTube's own
   channel sidebar ("Channel Views: 5,598,816", "Subscribers: 76,167", one
   plain label:value line per row) is the model here — compact, left-
   aligned, no visual competition with the actual page content. */
.channel-stat-box {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 5px 0;
}

.channel-stat-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  font-size: calc(13px + (14 - 13) * ((100vw - 320px) / (1920 - 320)));
}

.channel-stat-value {
  font-weight: 700;
}

.channel-about {
  font-size: calc(14px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
  opacity: 0.85;
}

/* Vertical spacing between the row's stacked column wrappers (channel-
   type-blurb/channel-stat-box/about-box) at any width narrower than the
   two-per-row tablet range below — same spacing Bootstrap's own .row
   gutter already uses horizontally, just applied as margin-bottom since
   these stack vertically outside that range. */
.sidebarbox > .row > div {
  margin-bottom: calc(var(--bs-gutter-x, 1.5rem) / 2);
  padding: calc(var(--bs-gutter-x, 1.5rem) / 2);
}

.sidebarbox {
  padding: 0px calc(var(--bs-gutter-x, 1.5rem) / 2);
}

.sidebarbox > .row > div > .featured-channels-box,
.sidebarbox > .row > div > .poll-box,
.sidebarbox > .row > div > .friends-box,
.sidebarbox > .row > div > .subscribers-box,
.sidebarbox > .row > div > .subscriptions-box,
.sidebarbox > .row > div > .recent-activity-box,
.sidebarbox > .row > div > .blog-comment {
  background-color: unset !important;
  border: 0 none !important;
  padding: 0;
}

/* channel-type-blurb/channel-stat-box sit side by side (col-sm-6) only at
   this tablet range (see channel-view.ejs's row-eq-height) — the .row's
   own flex stretch already equalizes their column height, this just makes
   each box itself fill that stretched height instead of staying its own
   natural (shorter) size. aboutmediv drops to its own full-width row right
   after them, so it needs the top margin the row's own gap would otherwise
   have provided. */
@media (min-width: 577px) and (max-width: 991px) {
  /* Scoped to .row-eq-height (channel-view.ejs's own wrapper around these
     two boxes) — .channel-type-blurb also renders standalone on the
     separate channel-videos.ejs page (no .channel-stat-box there at all,
     no flex-row ancestor), where an unscoped height: 100% instead resolved
     against whatever ancestor actually has a real height, blowing the box
     up to fill it and pushing the rest of that page's content (search
     form, tabs, video grid) down past the fold. */
  .row-eq-height .channel-stat-box, .row-eq-height .channel-type-blurb {
    height: 100%;
  }
  .row-eq-height .channel-type-blurb {
    padding: 0;
  }
  #channel-type-box + .col-lg-12.col-sm-6 {
    border-left: 0 none !important
  }
}

.channel-about img {
  max-width: 100%;
}

.mini-people-list {
  list-style: none;
  display: flex;
  margin-left: calc(var(--bs-gutter-x, 1.5rem) / -2);
  margin-right: calc(var(--bs-gutter-x, 1.5rem) / -2);
  flex-wrap: wrap;
  justify-content: center;
  gap: calc(var(--bs-gutter-x, 1.5rem) / 2);
  padding: calc(var(--bs-gutter-x, 1.5rem) / 2);
}

.mini-people-list li {
  width: 70px;
  text-align: center;
}

@media (min-width: 991px) {
  .mini-people-list {
    gap: 10px 0px;
    padding: 0;
  }
  .mini-people-list li {
    width: 33.333333%;
  }

  /* Friends/Subscribers/Subscriptions were always a narrow-column-only
     box before channelSettings.module* made them placeable into the wide
     comments column too — 3-per-row (sized for that narrow column) looks
     sparse stretched across it, so use a denser grid there instead. 9
     items per row, not some arbitrary denser count, because each page of
     these lists is always exactly MINI_PEOPLE_PAGE_SIZE (routes/
     channel.js) = 9 — sizing for anything less than that still wraps a
     full page onto a second row that's mostly empty space, the same
     "big gaps" problem one size up. */
  .blog-single-detail .channel-module-box .mini-people-list li {
    width: 11.111111%;
  }

  /* .mini-people-list's default centers its items — fine for a handful
     of avatars filling a narrow sidebar, but a short list (say, 1 friend)
     centered across the full width of the wide comments column just
     reads as a tiny box floating in a sea of blank space either side of
     it. Left-aligned reads as the start of a normal list instead. */
  .blog-single-detail .channel-module-box .mini-people-list {
    justify-content: flex-start;
  }
}

.mini-people-list img {
  width: 70px;
  height: 70px;
  object-fit: cover;
}

.mini-people-list span {
  display: block;
  font-size: calc(10px + (12 - 10) * ((100vw - 320px) / (1920 - 320)));
  word-break: break-all;
  line-height: 16px;
  padding: calc(var(--bs-gutter-x, 1.5rem) / 4);
}

.mini-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin: 6px 0 4px;
}

.mini-pager-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 100%;
  background: rgba(255, 255, 255, 0.06);
  color: inherit !important;
}

.mini-pager-btn > .feather {
  top: 0;
}

.mini-pager-btn.disabled {
  opacity: 0.3;
  pointer-events: none;
}

.mini-pager-label {
  font-size: 11px;
  opacity: 0.7;
}

/* Featured channels — full-width, always exactly one row (unlike the
   sidebar's friends/subscribers/subscriptions lists, which wrap to 3 rows
   in their narrow column) — scrolls horizontally instead of wrapping. */
.mini-people-list--single-row {
  flex-wrap: nowrap;
  overflow-x: auto;
  justify-content: flex-start;
  padding-bottom: 4px;
}

.mini-people-list--single-row li {
  flex-shrink: 0;
  margin: 5px 10px;
}

.featured-channels-box {
  margin-bottom: 0;
}

#featured-channels-container .mini-people-list li {
  width: auto;
  max-width: 150px;
  overflow: hidden;
}
#featured-channels-container .mini-people-list li img {
  width: 100px;
  height: 100px;
}

/* Left-column placement: the box is too narrow for the single-row
   horizontal scroller, so one channel gets its own full-width row instead
   — avatar stays its normal size, just laid out beside the name rather
   than above it. */
.mini-people-list--stacked {
  flex-direction: column;
  justify-content: flex-start;
  padding: 0 calc(var(--bs-gutter-x, 1.5rem) / 2);
}
.mini-people-list--stacked li a {
  display: flex;
  align-items: center;
  text-align: left;
  gap: 10px;
  width: 100%;
  margin: 0 auto;
}
#featured-channels-container .mini-people-list--stacked li {
  width: 100% !important;
  max-width: none;
}
.mini-people-list--stacked li img {
  margin-bottom: 0;
  flex-shrink: 0;
}
.mini-people-list--stacked span {
  padding-top: 0;
}

/* Channel sidebar's "recent activity" module (partials/recent-activity.ejs)
   — old YouTube-2008-style "X uploaded/favorited a video" feed. Background/
   border comes from channelCss.js's themed selector group (.recent-activity-
   list joined that alongside .mini-people-list), this is just layout. */
/* display: flow-root (a modern clearfix) so this item's own height/border
   actually wraps the floated thumbnail below instead of collapsing around
   it — same reason any float-based layout needs one. */
.recent-activity-item {
  display: flow-root;
  padding: 5px 0;
}
.recent-activity-item:first-child {
  padding-top: 0;
}

.recent-activity-item:not(:last-child):not(:nth-last-child(2)) {
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

/* Floated left, same on every screen size now — text (.recent-activity-
   body) wraps beside it and continues full-width once it clears the
   thumbnail's height, instead of being confined to a fixed-height row
   or stacked full-width above it. */
.recent-activity-thumb {
  float: left;
  width: 70px;
  height: 44px;
  margin-right: 10px;
  overflow: hidden;
}

.recent-activity-thumb a.bg-size {
  width: 100%;
  height: 100%;
}

.recent-activity-body p {
  margin: 0;
  font-size: calc(12px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
  opacity: 0.6;
}

.recent-activity-body h6 {
  margin: 2px 0;
  font-size: calc(14px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.recent-activity-body h6 a {
  color: inherit;
}

.recent-activity-body p a {
  color: unset !important;
  text-decoration: underline !important;
}

.recent-activity-time {
  font-size: calc(10px + (12 - 11) * ((100vw - 320px) / (1920 - 320)));
  opacity: 0.5;
  text-align: right;
  display: block;
}

.featured-channels-edit-form .form-group {
  margin-bottom: 12px;
}

.featured-channels-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.featured-channel-chip {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px 4px 4px;
  border-radius: 100px;
  background: rgba(255, 255, 255, 0.08);
  font-size: 12px;
  margin-bottom: 10px;
}

.featured-channel-chip img {
  width: 22px;
  height: 22px;
  object-fit: cover;
}

.featured-channel-chip-remove {
  background: none;
  border: none;
  color: inherit;
  opacity: 0.6;
  cursor: pointer;
  line-height: 1;
  padding: 0 0 0 4px;
}

.featured-channel-chip-remove:hover {
  opacity: 1;
}

.featured-channels-search-wrap {
  position: relative;
  margin-bottom: 10px;
}

.featured-channels-search-results {
  position: absolute;
  z-index: 5;
  top: 100%;
  left: 0;
  right: 0;
  background: var(--body-bg, #fff);
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 8px;
  max-height: 220px;
  overflow-y: auto;
}

.featured-channels-search-results:empty {
  border: none;
}

.featured-channels-search-result {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  cursor: pointer;
  font-size: 13px;
  color: #000;
}

.featured-channels-search-result:hover {
  background: rgba(255, 90, 60, 0.08);
}

.featured-channels-search-result img {
  width: 24px;
  height: 24px;
  object-fit: cover;
}

.poll-box {
  padding: calc(var(--bs-gutter-x, 1.5rem) / 2);
  margin-bottom: 0;
}

.poll-box-owner-actions {
  display: flex;
  gap: 0px;
  margin-bottom: 10px;
}

.poll-question {
  font-weight: 700;
  margin-bottom: 10px;
}

.poll-edit-form .form-group {
  margin-bottom: 12px;
}

.poll-answers-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 10px;
}

.poll-answer-chip {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px;
  border-radius: 100px;
  background: rgba(255, 255, 255, 0.08);
  font-size: 12px;
}

.poll-answer-chip-remove {
  background: none;
  border: none;
  color: inherit;
  opacity: 0.6;
  cursor: pointer;
  line-height: 1;
  padding: 0 0 0 4px;
}

.poll-answer-chip-remove:hover {
  opacity: 1;
}

.poll-answer-add-wrap {
  display: flex;
  gap: 8px;
  margin-bottom: 10px;
}

.poll-answer-add-wrap .form-control {
  flex: 1;
}

.poll-vote-option {
  display: block;
  padding: 6px 0;
  font-size: 13px;
  cursor: pointer;
}

.theme-form label.poll-vote-option {
  margin-bottom: 0;
  padding: 0;
  font-size: calc(14px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
}

.poll-vote-form > button {
  margin-top: 15px;
}

.poll-vote-option input {
  margin-right: 8px;
}

/* Results view — the star-rating percentage-bar layout from the bought
   theme's single-reviews page (<h5>label</h5> + .progress/.progress-bar),
   repurposed for poll answers instead of star counts. */
.poll-results-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.poll-results-list li {
  margin-bottom: 10px;
}

.poll-results-list h5 {
  font-size: 13px;
  display: flex;
  justify-content: space-between;
  margin-bottom: 4px;
}

.poll-results-list .poll-option-pct {
  opacity: 0.7;
}

.poll-results-list li.poll-my-vote h5 {
  font-weight: 700;
}

.poll-total-votes {
  font-size: calc(14px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
  opacity: 0.6;
  margin: 8px 0 0;
}

.channel-sidebar-heading {
  font-size: calc(16px + (18 - 16) * ((100vw - 320px) / (1920 - 320)));
  font-weight: 700;
  text-transform: uppercase;
  margin: calc(var(--bs-gutter-x, 1.5rem) / 8) 0 calc(var(--bs-gutter-x, 1.5rem) / 2);
}

h4, .h4 {
  font-size: calc(16px + (18 - 16) * ((100vw - 320px) / (1920 - 320)));
}

header .header-section .header-left .brand-logo {
  width: 350px;
  padding-bottom: 0;
  padding-top: 0;
}

header .header-section .header-left .brand-logo img {
  filter: drop-shadow(0 0 20px rgba(255, 90, 60, 0.35));
  position: relative;
  left: -10px;
}

@media (min-width: 577px) {
  header .header-section .header-left .brand-logo + .btn-group {
    margin-left: -120px;
  }
}

.logo-sec img {
  filter: drop-shadow(0 0 20px rgba(255, 90, 60, 0.35));
}

/* dark.css pins header { position: fixed }, which breaks badly on iPad
   (content scrolls under/over it inconsistently with Safari's dynamic
   toolbar). Just keep it in normal document flow everywhere. dark.css's
   .page-body padding-top (100px/80px/62px across breakpoints) exists only
   to leave room under the old fixed header — zero it out now that the
   header takes up its own space in normal flow instead, or every page
   gets a big dead gap under the header. */
header {
  position: relative;
}

.page-body {
  padding-top: 15px;
  padding-bottom: 90px;
}

@media (min-width: 1017px) {
  .page-center {
    width: 100%;
  }
}

/* Channel view has no sidebar-panel (old SL didn't have one either) — let
   .page-center reclaim the width the theme normally reserves for it. */
.page-body.no-sidebar .page-center {
  width: 100%;
  padding-left: 0;
  padding-right: 0;
}

.page-body.custom-padding.channel-page-body {
  padding-left: 0;
  padding-right: 0;
  padding-top: 0;
  padding-bottom: 0;
}

/* Channel page's slim quick-jump bar (partials/channel-preview-panel) —
   sticky rather than truly fixed so it sits right under the (now static)
   header at the top of the page instead of covering it, but still pins to
   the viewport's top edge once scrolled past. No backdrop-filter (there
   used to be one) — `position: sticky` + `backdrop-filter` is a known
   WebKit trap: iPad Safari has to recomposite the blur on every layout
   change, and focusing a reply textarea's keyboard triggers exactly that,
   which was freezing the page for several seconds on every "Reply" tap on
   a channel page. Bumped the background opacity instead to keep roughly
   the same "floating over content" look without the GPU cost. */
.channel-preview-panel {
  position: sticky;
  top: 0;
  z-index: 2;
  background: rgba(11, 26, 44, 0.9);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.channel-preview-panel-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 8px 12px;
  flex-wrap: wrap;
}

.channel-preview-panel-inner .feather {
  top: 0;
}

.channel-preview-panel-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 14px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(255, 255, 255, 0.06);
  color: #e8e9db;
  font-size: calc(8px + (16 - 14) * ((100vw - 320px) / (1920 - 320)));
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.channel-preview-panel-btn:hover {
  background: rgba(255, 90, 60, 0.15);
  border-color: #ff5a3c;
  color: #fff;
}

.channel-preview-toggle-btn.active {
  background: #ff5a3c;
  border-color: #ff5a3c;
  color: #000;
}

/* So a jump-link doesn't land its target right under the sticky panel. */
#channel-videos-anchor,
#comments-container {
  scroll-margin-top: 56px;
}

/* Owner "preview as visitor" mode (toggled by .channel-preview-toggle-btn
   above) — hides every owner-only management affordance across the page
   (edit/settings buttons, empty poll/featured-channels boxes) so the owner
   can see their own channel exactly as a regular visitor would. The toggle
   button itself is never marked .owner-preview-hide, or there'd be no way
   to turn it back off. */
body.channel-preview-mode .owner-preview-hide {
  display: none !important;
}

body.channel-preview-mode #poll-box[data-has-content="false"],
body.channel-preview-mode #featured-channels-box[data-has-content="false"],
body.channel-preview-mode #channel-type-box[data-has-content="false"] {
  display: none !important;
}

.channel-main-box {
  max-width: 1200px;
  margin: 0 auto 0 auto;
}

@media (min-width: 992px) {
  .channel-main-box .row.row2-area > div:first-child,
  #channel-videos-anchor > div:first-child {
    padding-right: 0 !important;
  }
}

footer.footer-theme {
  padding-top: 60px;
  background-color: rgba(0,0,0,.7);
}

/* Bootstrap's .row defaults to align-items: stretch, forcing both
   row2-area columns to match whichever is taller — invisible before
   (comments, by far the tallest content on the page, was always paired
   with the wide column, itself always at least as tall as the sidebar),
   but now that channelSettings.module* lets comments (or any other box)
   land on either side, the shorter column stretches into a huge visible
   blank area under its own last box. Each column's height should only
   ever come from its own content. */
.row2-area {
  align-items: flex-start;
  margin-top: calc(var(--bs-gutter-x, 1.5rem) / 2);
  padding-bottom: 120px;
}

/* Comments narrows to roughly a phone's width whenever
   channelSettings.moduleComments places it in the left column instead of
   the wide one — same compact, stacked layout the theme already applies
   at real mobile widths (see the max-width: 576px comment rules above),
   just triggered by column placement here instead of viewport width, and
   scoped to the left column specifically so comments in the wide column
   are completely unaffected. The .blog-single-detail-prefixed mobile
   rules elsewhere don't need repeating here — the comments wrapper always
   carries that class now regardless of column (channel-view.ejs), so
   those already apply on their own. */
.row2-area > .col-xl-3.col-lg-4 [data-module="comments"] .title:has(> .comment-user):has(> .comment-date) {
  flex-direction: column;
}
.row2-area > .col-xl-3.col-lg-4 [data-module="comments"] .title > .comment-user,
.row2-area > .col-xl-3.col-lg-4 [data-module="comments"] .title > .comment-date {
  width: 100%;
}
.row2-area > .col-xl-3.col-lg-4 [data-module="comments"] .title:has(> .comment-user):has(> .comment-date) > * {
  margin-bottom: 5px !important;
}
.row2-area > .col-xl-3.col-lg-4 [data-module="comments"] .blog-comment > .d-flex > * {
  margin: 15px 0px 0px 0 !important;
}
.row2-area > .col-xl-3.col-lg-4 [data-module="comments"] .comment-box > .media > * {
  margin: 0px 0px 5px 0 !important;
}
.row2-area > .col-xl-3.col-lg-4 [data-module="comments"] .comment-box > .media,
.row2-area > .col-xl-3.col-lg-4 [data-module="comments"] .blog-comment > .d-flex {
  flex-direction: column;
}
.row2-area > .col-xl-3.col-lg-4 [data-module="comments"] .comment-avatar-col {
  flex-direction: row;
  align-items: flex-start;
  padding-bottom: 2.5px;
}
.row2-area > .col-xl-3.col-lg-4 [data-module="comments"] .comment-reactions {
  padding: 0 15px;
}
.row2-area > .col-xl-3.col-lg-4 [data-module="comments"] .comment-actions-right > button {
  max-width: 24px;
  overflow: hidden;
  text-indent: -17%;
  white-space: nowrap;
  min-height: 24px;
}
.row2-area > .col-xl-3.col-lg-4 [data-module="comments"] .emojionearea.emojionearea-inline {
  min-height: 24px !important;
}
.row2-area > .col-xl-3.col-lg-4 [data-module="comments"] .comment-detail .comment-embed-img {
  max-width: 100%;
}

/* Move-to-other-column arrows (partials/module-arrows.ejs) — owner-only,
   sits in each box's own heading row (.channel-sidebar-heading or the
   equivalent d-flex header a few boxes use their own heading markup for),
   aligned to that row's own end via the row's existing
   justify-content: space-between rather than anything in here. Shown on
   all screen sizes — even once the two columns stack into one on mobile,
   left/right still controls which box shows up first vs. last. */
.module-arrows {
  display: inline-flex;
  gap: 4px;
  margin-left: 8px;
  margin-right: 0px;
  position: relative;
}

.channel-sidebar-heading + button.btn, .module-arrows + button.btn , .module-arrows + button + button.btn, .module-arrow-btn + button.btn {
  position: relative;
  margin-left: 5px;
  padding: 2px 5px 1px 5px !important;
}
.module-arrow-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  margin-left: 0 !important;
  padding: 0;
  color: #000 !important;
  border: 1px solid #000;
  border-radius: 4px;
  background: #fff !important;
  color: inherit;
  cursor: pointer;
}
.module-arrows + .module-arrow-btn {
  margin-left: 4px !important;
}
.module-arrow-btn > svg {
  top: 0;
}
.module-arrow-btn:hover:not(:disabled) {
  background: rgba(255, 255, 255, 1);
  color: #000 !important;
}
.module-arrow-btn:disabled {
  opacity: 0.3;
  cursor: default;
  display: none;
}
/* Quick appearance popups (channel-view.ejs's #boxStyleEditModal etc.) —
   the main-box icon sits absolutely inside .channel-main-box's own
   top-right corner rather than a document-flow sibling, since it has no
   heading/toolbar row of its own to sit next to like the other four icons
   do. */
.channel-main-box {
  position: relative;
}
.channel-main-box > .main-box-style-edit-btn {
  position: absolute;
  top: 15px;
  right: 15px;
  z-index: 2;
  color:#000;
  background-color:#fff;
  border: 1px solid #000;
}
.quick-appearance-modal .quick-image-field {
  display: flex;
  align-items: center;
  gap: 8px;
}
.quick-appearance-modal .quick-image-current {
  opacity: 0.7;
  font-size: 13px;
  flex: 1;
}
.quick-appearance-modal .quick-image-upload-label, .quick-appearance-modal .quick-image-clear-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  padding: 0;
  height: 30px;
  cursor: pointer;
  color: #647589;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 4px;
  margin: 0;
}
.quick-appearance-modal .quick-image-upload-label:hover {
  color: #ff5a3c;
}
.quick-appearance-modal .quick-image-upload-label svg {
  width: 16px;
  height: 16px;
}
.modal-body.theme-form  label {
  font-size: calc(12px + (18 - 16) * ((100vw - 320px) / (1920 - 320)));
}
/* Wraps each of the 7 channel-page boxes channelSettings.module* can place
   into either column (channel-view.ejs) — gives every one of them the
   same minimum spacing regardless of which column it lands in or which
   other boxes end up next to it (a couple, like .featured-channels-box,
   already carry their own margin too; a slightly bigger gap there is
   harmless). Also the hook a later step's arrow-based AJAX reordering
   will target via [data-module] to move a box up/down within its column. */
.channel-module-box {
  margin-bottom: calc(var(--bs-gutter-x, 1.5rem) / 2);
}
.channel-module-box:last-child {
  margin-bottom: 0;
}

.sidebarbox > .channel-module-box {
  margin-bottom: 0;
}

.comment-date > *, .comment-user > * {
  display: inline-block;
}
.comment-user > h6 {
  font-weight: bold;
}

header .header-section .header-right .post-stats ul li h3 {
  margin-bottom: 0;
}

header .header-section .header-left .brand-logo {
  margin-right: 10px;
}

/* Video thumbnails: fixed 16:9 box (matches a 640x360 source), cropped via
   a centered `cover` background instead of the browser's native <img>
   scaling, which was cutting off the top/bottom on non-16:9 sources. */
.video-card .bg-size {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: inherit;
}

.video-card .bg-size:before {
  content: "";
  display: block;
  padding-top: 56.25%;
}

.theme-pagination > li {
  background-color: #fff;
  opacity: 1;
}

.theme-pagination {
  margin-top: 15px;
  margin-bottom: 15px;
}

[aria-label="moderator users pagination"] > .theme-pagination,
[aria-label="channels pagination"] > .theme-pagination,
[aria-label="channel videos pagination"] > .theme-pagination,
[aria-label="channel comments pagination"] > .theme-pagination {
  overflow-x: auto;
  width: 100%;
  -webkit-box-pack: center;
      -ms-flex-pack: center;
          justify-content: center;
}

.theme-pagination .page-item {
  padding: 0;
  margin: 0;
}

.theme-pagination .page-item .page-link {
  margin: 0;
  -webkit-transition: all 0.5s ease;
  transition: all 0.5s ease;
  width: auto;
  padding-left: 10px;
  padding-right: 10px;
}

.theme-pagination .page-item.active .page-link {
  border-radius: 0;
  color: #fff;
  background-color: #391427;
}

.theme-pagination .page-item > a {
  border-radius: 0;
}

.theme-pagination .page-item .page-link:hover,
.theme-pagination .page-item .page-link:focus {
  background-color: #391427;
  color: #fff;
  border-radius: 0;
}

/* Bootstrap's own .page-item:first-child/:last-child .page-link rules have
   higher specificity (3 classes/pseudo vs. our 2 classes + type selector),
   so they were still winning and rounding the end pagination items. */
.theme-pagination .page-item:first-child .page-link,
.theme-pagination .page-item:last-child .page-link {
  border-radius: 0;
}

/* Header dropdown menus (message/notification/profile) — twice as dark as
   the page navy, sampled from the logo's own hue. */
.dropdown-menu {
  background-color: #050d16;
}

.custom-dropdown .dropdown-menu:after {
  border-bottom-color: #050d16;
}

/* .nav-tabs (homepage/category tabs): the dark-theme conversion flipped the
   active tab's background from white to navy but left its text/border colors
   tuned for a white background, making the active tab unreadable. */
.nav-tabs .nav-link,
.nav-tabs .nav-link.active,
.nav-tabs .nav-item.show .nav-link {
  color: #e8e9db;
}

.nav-tabs .nav-link:hover,
.nav-tabs .nav-link:focus {
  color: #dccdb6;
}

/* On tablet/mobile the settings sidebar goes off-canvas and this is the only
   button that reveals it (views/settings.ejs), but it sits right at the top
   of the content column where the fixed header covers it. */
.setting-menu {
  margin-top: 60px;
}

html .theme-pagination .feather {
  top: 0;
}

.inner-comment {
  padding: 0px;
  background-color: transparent !important;
}

/* Replies get a denser treatment than top-level comments: ~5% smaller
   text throughout (username/date, body, badges — same responsive curve as
   the top-level rules, just scaled down rather than a flat override), a
   smaller avatar, and the same minimized icon-only action buttons the
   mobile breakpoint already uses elsewhere, applied here unconditionally
   since it's about density, not viewport width. Every one of these needs
   !important — the base .blog-single-detail...media... chains they're
   competing with run 5-8 classes deep (see the .emojione comment above),
   so plain specificity alone loses.
   The avatar rule is scoped to `> a > img` specifically (not a bare
   `.comment-avatar-col img`) — that container also holds the reaction
   emoji <img class="emojione">s (.comment-reactions lives inside it too),
   and a blanket `img` selector with !important was blowing THOSE up to
   70px as well, since !important beats the emojione rule's own higher
   (but non-important) specificity regardless of what either rule
   actually targets. */
.inner-comment .comment-avatar-col > a > img {
  width: 86px !important;
  height: 86px !important;
}

.inner-comment .title .comment-user h6,
.inner-comment .title .comment-user .h6,
.inner-comment .title .comment-date h6,
.inner-comment .title .comment-date .h6 {
  font-size: calc((14px + (16 - 14) * ((100vw - 320px) / (1920 - 320))) * 0.95) !important;
}

.inner-comment .comment-detail p {
  font-size: calc((14px + (16 - 14) * ((100vw - 320px) / (1920 - 320))) * 0.95) !important;
  line-height: calc((22px + (16 - 14) * ((100vw - 320px) / (1920 - 320))) * 0.95) !important;
}

.inner-comment .comment-actions > button:not(.comment-vote-btn) {
  max-width: 25px !important;
  overflow: hidden !important;
  text-indent: -15% !important;
  white-space: nowrap !important;
  min-height: 24px !important;
}

.inner-comment .comment-actions > button.comment-vote-btn {
  min-height: 24px !important;
}

@media (min-width: 578px) {
  .inner-comment .comment-actions > button.comment-vote-btn {
    min-height: 25px !important;
  }
}

.inner-comment .comment-actions-right > button {
  max-width: 24px !important;
  overflow: hidden !important;
  text-indent: -17% !important;
  white-space: nowrap !important;
  min-height: 24px !important;
}

.blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body {
  max-width: 100%;
  overflow: visible;
  padding-top: 5px;
}
.blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .comment-detail {
  max-width: 100%;
  overflow: auto;
}
.blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .comment-detail > p:last-child {
  margin-bottom: 0;
}
.blog-single-detail .blog-comment .comment-wrapper .comment-box .media .media-body .comment-detail {
  margin-bottom: 5px;
}

.custom-dropdown.profile-btn .dropdown-menu .dropdown-content .friend-list li {
  padding: 10px 5px;
}

.theme-form > .row > .form-group > .form-control {
  margin-bottom: 0;
}
.theme-form > .row > .form-group {
  margin-bottom: 15px !important;
}

/* Box-model for the channel banner strip — the actual image(s)/repeat/scale
   are user-customizable and generated per-channel (channelCss.js); this is
   just the fixed shape/fallback. */
.channel-banner {
  height: 200px;
  margin-bottom: 16px;
  border-radius: 0px;
}

/* Shared crossfade for a channel's secondary background/banner image
   (channelCss.js only emits the ::before/::after pair — and this animation
   reference — when both a primary and secondary image are set). A negative
   animation-delay on the second layer starts it half a cycle in-progress
   (rather than holding at its pre-animation opacity until a positive delay
   elapses), so the two layers are perfectly out of phase from paint one:
   full swap every 5s, smoothly crossfading rather than a hard cut. */
@keyframes channel-image-crossfade {
  0%, 100% { opacity: 1; }
  50% { opacity: 0; }
}

/* Channel type description / about me on the channel videos page
   (channel-videos.ejs) — collapsed by default so a long bio/description
   doesn't push the video grid down; expandable via the show more/less
   toggle rendered next to it. */
.collapsible-text {
  max-height: 100px;
  overflow: hidden;
}
.collapsible-text.expanded {
  max-height: none;
}
.collapsible-toggle {
  display: inline-block;
  margin-top: 6px;
  font-size: 12px;
  opacity: 0.8;
}

.progress-bar {
  color: #fff;
}

.sortable-header {
  color: inherit;
  text-decoration: none;
  white-space: nowrap;
}

.sortable-header:hover {
  text-decoration: underline;
}

.messanger-section .chat-content .tab-box .user-chat .chat-history .avenue-messenger .chat .message-box .message-input {
  color: #fff;
  padding-right: 0 !important;
  margin-right: 0 !important;
}
.messanger-section .chat-content .tab-box .user-chat .chat-history .avenue-messenger .chat .message-box .message-submit {
  right: 10px;
  bottom: 10px;
  height: 30px;
  width: 30px;
  top: unset;
  background-color: #051826;
  border: 1px solid #fff;
  color: #fff;
}

/* Image-upload button, left of .message-submit on the same row. Used to be
   hidden until the textarea was focused, but clicking it blurs the
   textarea first — display:none-on-blur was hiding the button out from
   under the click before it could register. Always visible instead. */
.messanger-section .chat-content .tab-box .user-chat .chat-history .avenue-messenger .chat .message-box .message-add-img-btn {
  display: flex;
  position: absolute;
  right: 45px;
  bottom: 10px;
  height: 30px;
  width: 30px;
  align-items: center;
  justify-content: center;
  padding: 0;
  background-color: #051826;
  border: 1px solid #fff;
  border-radius: 5px;
  color: #fff;
  cursor: pointer;
}
.message-add-img-btn > .ih-15.feather {
  top: 0;
}

.messanger-section .chat-content .tab-box .user-chat .chat-history .avenue-messenger .chat .message-box {
  height: auto;
  padding: 10px 80px 10px 10px;
}
/* No !important here (unlike the old focus-toggled rule this replaces) —
   JS (messages.ejs) sets the textarea's height directly via inline style
   on every expand/resize, and a plain inline style already beats a plain
   stylesheet rule regardless of specificity, so this is just the
   before-JS-runs/no-JS default. Targets .message-input (not just
   `textarea`) to match the vendor theme's own `.message-input { height:
   100% }` rule (dark.css) at equal specificity — a bare element-type
   selector has LOWER specificity than any class selector, so it lost to
   that vendor rule regardless of site.css loading after dark.css. */
.messanger-section .chat-content .tab-box .user-chat .chat-history .avenue-messenger .chat .message-box > textarea.message-input {
  height: 30px;
}

/* Drag-to-resize .message-box, same idea as the .chat-users sidebar
   resizer below — JS (messages.ejs) sets an explicit pixel height (100%
   doesn't work here: .message-box is display:flex/align-items:center from
   the vendor theme, so the textarea needs its own static height kept in
   sync with the container's, not a percentage) on load (twice the
   original single-line default, or whatever was last dragged) and reserves
   the same space from .messages-content via the --message-box-height
   custom property so the box doesn't cover the tail of the conversation.
   The resizer handle is always visible now (no more click-to-expand state
   to gate it behind) — dragging it is the only way left to resize. */
.messanger-section .chat-content .tab-box .user-chat .chat-history .avenue-messenger .chat .messages-content {
  height: calc(100% - var(--message-box-height, 80px));
}
.messanger-section .chat-content .tab-box .user-chat .chat-history .avenue-messenger .chat .message-box-resizer {
  display: block;
  position: absolute;
  top: -4px;
  left: 0;
  width: 100%;
  height: 8px;
  cursor: row-resize;
  z-index: 2;
}
.messanger-section .chat-content .tab-box .user-chat .chat-history .avenue-messenger .chat .message-box-resizer:hover,
.messanger-section .chat-content .tab-box .user-chat .chat-history .avenue-messenger .chat .message-box-resizer.is-resizing {
  background: rgba(255, 90, 60, 0.3);
}
@media (min-width: 577px) {
  /* Desktop only — mobile fills this via flex instead (see the
     max-width: 576px block above), since a fixed vh-minus-N number here
     would otherwise cascade onto mobile too (this selector isn't
     media-scoped by specificity, only by literally being inside this
     block) and silently win over the mobile flex-fill rules just by
     sitting later in the file, regardless of viewport. */
  .messanger-section .chat-users .nav-tabs {
    /* 155px = header + .chat-users .user-header — was 127px, too short for
       this site's actual (taller) header, so the list overflowed past its
       own container's bottom edge (overflow-y: visible on .chat-users)
       and inflated the whole page's scrollHeight even though every
       ancestor box measured fine on its own. */
    height: calc(100vh - 155px);
  }
}
.messanger-section .chat-users .nav-tabs {
    /* Bootstrap's .nav is display:flex, and each 100%-width .nav-item
       wraps onto its own line — with a fixed tall height and few
       conversations, the default align-content (stretch-like for a
       multi-line flex container) stretches each line to fill the leftover
       space instead of packing them at the top, leaving big gaps between
       conversations. flex-start packs them at the top instead. */
    align-content: flex-start;
}
.messanger-section .chat-users .nav-tabs .nav-item .nav-link {
    -webkit-transition: none;
    transition: none;
}
.messanger-section .chat-content .tab-box .user-chat .chat-history .avenue-messenger .chat .messages-content .message:last-child {
    margin-bottom: 160px;
}

/* Resizable/collapsible .chat-users sidebar — desktop only (matches
   Bootstrap's lg breakpoint at 991px). The theme's own .chat-content/
   .user-chat widths (style.css) are both a fixed `calc(100% - 400px)`/
   `calc(100% - 350px)`/`calc(100% - 300px)` at various breakpoints —
   leftover from its original 3-pane layout (chat-users | user-chat | a
   contact-details panel we don't use), which silently subtracted a
   phantom panel's width even after that third pane was dropped.
   Replacing both with a plain flex-fill removes that subtraction
   entirely and makes .chat-content automatically track .chat-users' REAL
   width (default, resized, or collapsed) with no calc()/media-query
   bookkeeping at all — site.css loads after style.css, so this overrides
   it at equal selector specificity via cascade order, even below the
   theme's own 1367px/1661px breakpoints. */
.chat-users-resizer,
.chat-users-collapse-toggle {
  display: none;
}
@media (min-width: 991px) {
  .messanger-section .chat-users {
    flex: 0 0 auto;
    position: relative;
    min-width: 76px;
    max-width: 600px;
  }
  .messanger-section .chat-content {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
  }
  .messanger-section .chat-content .tab-box .user-chat {
    width: 100%;
  }

  .chat-users-resizer {
    display: block;
    position: absolute;
    top: 0;
    right: -3px;
    width: 6px;
    height: 100%;
    cursor: col-resize;
    z-index: 5;
  }
  .chat-users-resizer:hover,
  .chat-users-resizer.is-resizing {
    background: rgba(255, 90, 60, 0.3);
  }

  .chat-users-collapse-toggle {
    display: block;
    position: absolute;
    top: 20px;
    right: 10px;
    z-index: 6;
    background: none;
    border: none;
    padding: 4px;
    opacity: 0.6;
    cursor: pointer;
  }
  .chat-users-collapse-toggle:hover {
    opacity: 1;
  }

  /* Collapsed: icon-only rail — hide everything but each contact's avatar. */
  .messanger-section .chat-users.is-collapsed {
    min-width: 0;
    padding-left: 5px;
  }
  .messanger-section .chat-users.is-collapsed .user-header h5,
  .messanger-section .chat-users.is-collapsed .user-header .search-bar,
  .messanger-section .chat-users.is-collapsed .nav-tabs .media-body,
  .messanger-section .chat-users.is-collapsed .nav-tabs .chat,
  .messanger-section .chat-users.is-collapsed .empty-hint {
    display: none;
  }
  .messanger-section .chat-users.is-collapsed .user-header {
    justify-content: center;
  }
  .messanger-section .chat-users.is-collapsed .nav-tabs .nav-link {
    justify-content: center;
    padding-left: 0;
    padding-right: 0;
  }

  .chat-users.is-collapsed .chat-users-collapse-toggle {
    -webkit-transform: scale(-1, -1);
    -moz-transform: scale(-1, -1);
    -o-transform: scale(-1, -1);
    transform: scale(-1, -1);
    left: 15px;
    right: unset;
  }

  .chat-users-collapse-toggle {
    color: #fff;
    top: 12.5px !important;
  }
  .chat-users-resizer {
    background-color: #1e303c !important;
    top: 10px;
    height: calc(100% - 10px);
  }

  .messanger-section .chat-users.is-collapsed .nav-tabs .list-media {
    margin-bottom: 0;
  }
}

@media (min-width: 577px) {
  /* Desktop only — see the nav-tabs comment above for why this can't be
     a plain unscoped rule: mobile fills both of these via flex instead
     (max-width: 576px block), and an unscoped calc(100vh - Npx) here
     would cascade onto mobile too just by sitting later in the file.
     Vendor theme (dark.css) sizes both of these off calc(100vh - 70px),
     assuming a shorter header than this site actually has — .chat-content
     and .chat-users (its sibling, the conversation sidebar) both ended up
     taller than the real available space, inflating the whole page's
     height even though nothing inside visibly looked wrong on its own.
     99px is this site's real header height; keeping both in sync since
     they're meant to fill the same vertical space side by side. */
  .messanger-section .chat-content,
  .messanger-section .chat-users {
    height: calc(100vh - 99px);
  }
}

@media (min-width: 577px) {
  /* Desktop only — same reason as the other two rules above: mobile
     fills this via flex instead (block below), and this would otherwise
     silently win on mobile too just by sitting later in the file.
     Vendor theme (dark.css) sets this to calc(100vh - 156px) — too tall,
     pushing the message-box below the fold on shorter viewports. */
  .messanger-section .chat-content .tab-box .user-chat .chat-history .avenue-messenger {
    height: calc(100vh - 185px);
  }
}

@media (max-width: 576px) {
  /* Was calc(100dvh - 137px), a guessed subtraction with the same problem
     as chat-content's above (see that comment) — .chat-history above this
     now fills exactly whatever real space is left via flex (dvh-aware at
     the body level already), so this just needs to fill .chat-history in
     turn, not recompute the viewport math itself. */
  .messanger-section .chat-content .tab-box .user-chat .chat-history .avenue-messenger {
    height: 100%;
  }
}

/* Messages-page avatars: rectangular like .channel-topbar-avatar, with the
   same online/offline status dot, instead of the vendor theme's circular
   .user-img (conversation list is 40x40, thread header is 45px). */
.messanger-section .chat-users .nav-tabs .list-media .story-img .user-img,
.messanger-section .chat-content .tab-box .user-chat .user-title .list-media .story-img .user-img {
  border-radius: 0;
}

.messanger-section .story-img .available-stats {
  position: absolute;
  right: 0;
  top: 0;
  width: 12px;
  height: 12px;
  border: 3px solid #0b1a2c;
  border-radius: 100%;
  cursor: default;
}

.messanger-section .story-img .available-stats.online {
  background-color: #2bc60c;
}

.messanger-section .story-img .available-stats.offline {
  background-color: #ff2f25;
}

/* Help & how-to wiki (views/help.ejs) — left nav + search, content column. */
.help-page {
  display: flex;
  align-items: flex-start;
  gap: 24px;
  margin-top: 15px;
}

.help-nav {
  flex: 0 0 240px;
  position: sticky;
  top: 15px;
  background-color: #0b1a2c;
  border-radius: 8px;
  padding: 14px;
}

.help-search {
  display: flex;
  align-items: center;
  gap: 8px;
  background-color: #06101d;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 6px;
  padding: 8px 10px;
  margin-bottom: 12px;
}

.help-search .feather {
  opacity: 0.6;
  flex-shrink: 0;
}

.help-search > .feather {
  top: 0;
}

.help-search input {
  background: none;
  border: none;
  outline: none;
  color: #e8e9db;
  width: 100%;
  font-size: 13px;
}

.help-nav-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.help-nav-list li {
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}

.help-nav-list li:first-child {
  border-top: none;
}

.help-nav-link {
  display: block;
  padding: 9px 4px;
  font-size: 13px;
  color: #cfd3da;
  text-decoration: none;
}

.help-nav-link:hover {
  color: #ff5a3c;
}

.help-content {
  flex: 1;
  min-width: 0;
  background-color: #0b1a2c;
  border-radius: 8px;
  padding: 10px 24px;
}

.help-section {
  padding: 20px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}

.help-section:first-child {
  border-top: none;
}

.help-section h4 {
  text-transform: uppercase;
  margin-bottom: 10px;
}

.help-section p {
  margin-bottom: 10px;
  opacity: 0.85;
  line-height: 1.6;
}

.help-section ul {
  margin: 0 0 10px;
  padding-left: 20px;
  opacity: 0.85;
  line-height: 1.6;
}

.help-section a {
  color: #ff5a3c;
}

.help-no-results {
  padding: 20px 0;
  opacity: 0.7;
}

@media (max-width: 991px) {
  .help-page {
    flex-direction: column;
  }

  .help-nav {
    position: static;
    width: 100%;
    flex-basis: auto;
  }
}

/* Static legal/about pages (views/privacy.ejs, terms.ejs, about.ejs) —
   single content column, same dark card look as .help-content. */
.legal-page {
  background-color: #0b1a2c;
  border-radius: 8px;
  padding: 20px 24px;
  margin-top: 15px;
  max-width: 820px;
}

.legal-page .legal-updated {
  opacity: 0.6;
  font-size: 13px;
  margin-bottom: 20px;
}

.legal-page h4 {
  text-transform: uppercase;
  margin: 24px 0 10px;
}

.legal-page h4:first-of-type {
  margin-top: 0;
}

.legal-page p {
  margin-bottom: 10px;
  opacity: 0.85;
  line-height: 1.6;
}

.legal-page ul {
  margin: 0 0 10px;
  padding-left: 20px;
  opacity: 0.85;
  line-height: 1.6;
  list-style-type: circle;
}

.legal-page a {
  color: #ff5a3c;
}

.contact-form {
  max-width: 480px;
  margin-top: 20px;
}

.contact-form .form-group {
  margin-bottom: 16px;
}

.contact-form label {
  opacity: 0.85;
  margin-bottom: 6px;
}

.contact-form .form-control {
  background-color: #06101d;
  border: 1px solid rgba(255, 255, 255, 0.1);
  color: #e8e9db;
}

.contact-form .form-control:focus {
  background-color: #06101d;
  color: #e8e9db;
  border-color: #ff5a3c;
  box-shadow: none;
}

.login-form .form-check-input {
  background-color: #fff;
}

.login-form a:not(.btn) {
  text-decoration: underline !important;
}

.login-form .btn-lg {
  padding-left: 10% !important;
  padding-right: 10% !important;
}

.error-section .error-content p {
  padding-top: 60px;
  text-transform: unset;
}

/* Homepage's video-category tabs (index.ejs) — Bootstrap's default
   .nav-tabs wraps onto extra lines once the category list doesn't fit a
   narrow viewport, pushing the video grid down unpredictably. Force a
   single scrollable row instead, same "wide content scrolls in its own
   container" pattern used elsewhere on the site. */
.tab-section .nav-tabs {
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
}

.tab-section .nav-tabs .nav-item {
  flex: 0 0 auto;
}

.messanger-section {
  margin-top: 0;
}

.sub-footer {
  padding-bottom: 120px;
}

/* script.js's mobile footer-accordion (<767px) does jQuery('.footer-content')
   .hide(), then only reveals a given block when its OWN .footer-title
   header is clicked. The SEO copy block shares the .footer-content class
   with the "quick links" column but has no .footer-title of its own to
   click, so on mobile it got hidden with no way to ever show it again.
   !important is required here since it has to beat an inline style
   (jQuery .hide() sets style="display: none" directly on the element). */
.footer-seo-content {
  display: block !important;
}

header .header-section .header-btn .main-link {
  padding: 0 15px 0 0px;
}
@media (max-width: 576px) {
    header .header-section .header-btn .main-link {
        padding: 0 10px 0 0px;
    }
}
@media (min-width: 991px) {
  .header-btn svg {
    height: 25px !important;
    width: 25px !important;
  }
  header .header-section .header-btn .main-link {
      padding: 0 30px 0 0px;
  }
}

.header-search-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  margin-left: 8px;
  padding: 0;
  border: none;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.1);
  color: #ffffff;
  cursor: pointer;
  flex-shrink: 0;
}
.header-search-btn:hover {
  background: rgba(255, 90, 60, 0.5);
}

.header-search-results {
  margin-top: 10px;
  max-height: 320px;
  overflow-y: auto;
}
.header-search-result {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px;
  border-radius: 4px;
  cursor: pointer;
  text-decoration: none;
  color: inherit;
}
.header-search-result:hover {
  background: rgba(255, 255, 255, 0.08);
  color: inherit;
}
.header-search-result img {
  width: 48px;
  height: 48px;
  object-fit: cover;
  border-radius: 4px;
  flex-shrink: 0;
}
.header-search-result.is-video img {
  width: 64px;
  height: 36px;
  border-radius: 4px;
}
.header-search-result span {
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.header-search-result span small {
  display: block;
  opacity: 0.65;
  font-size: 11px;
}

header .header-section .header-btn .count {
  right:unset;
}

.header-search-btn .feather {
  top: 0;
}

@media (min-width: 1200px) and (max-width: 1400px) {
  html .header-btn svg {
    height: 15px !important;
    width: 15px !important;
  }
  html header .header-section .header-btn .main-link {
      padding: 0 10px 0 10px;
  }
}

.oauth-divider {
  display: flex;
  align-items: center;
  text-align: center;
  margin: 20px 0;
  color: #8f8873;
  font-size: 13px;
}
.oauth-divider::before,
.oauth-divider::after {
  content: "";
  flex: 1;
  border-bottom: 1px solid rgba(255, 255, 255, 0.15);
}
.oauth-divider span {
  padding: 0 12px;
}
.oauth-buttons {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.oauth-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
}
.oauth-btn svg {
  flex-shrink: 0;
}

.login-section .login-form .login-discription {
  margin-bottom: 30px;
}

/* Shared "advanced settings" block (partials/video-advanced-fields.ejs) —
   plain <details>/<summary>, collapsed by default with no JS needed for
   that part; styled to look intentional rather than like an unstyled
   native disclosure widget. */
.video-advanced-settings {
  margin: 15px 0;
  padding: 12px 14px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 8px;
}

.video-advanced-settings > summary {
  cursor: pointer;
  font-weight: 600;
  list-style: none;
}

.video-advanced-settings > summary::-webkit-details-marker {
  display: none;
}

.video-advanced-settings > summary::before {
  content: "▸";
  display: inline-block;
  width: 1em;
  transition: transform 0.15s ease;
}

.video-advanced-settings[open] > summary::before {
  transform: rotate(90deg);
}

/* Same "styled native <details>" treatment as .video-advanced-settings
   above, for the channel settings page's collapsible module-weights panel
   (views/channel.ejs). Kept as its own class rather than sharing that one
   since the two live in unrelated forms — this one just happens to want
   an identical look. */
.module-weights-details {
  margin: 15px 0;
  padding: 12px 14px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 8px;
}

.module-weights-details > summary {
  cursor: pointer;
  font-weight: 600;
  list-style: none;
}

.module-weights-details > summary::-webkit-details-marker {
  display: none;
}

.module-weights-details > summary::before {
  content: "▸";
  display: inline-block;
  width: 1em;
  transition: transform 0.15s ease;
}

.module-weights-details[open] > summary::before {
  transform: rotate(90deg);
}

.module-weight-row {
  align-items: center;
  margin-bottom: 8px;
}

.module-weight-sublabel {
  font-size: 12px;
  opacity: 0.7;
  margin-bottom: 2px;
}

/* Rotating random-3-thumbnail slider (partials/video-thumb.ejs) — three
   stacked layers, only the .is-active one visible, cycled by a shared
   interval in scripts.ejs. No transition anywhere here on purpose — a
   plain opacity toggle with no transition is an instant/static swap,
   matching the explicit "no effects" requirement. */
.video-thumb-slide {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  opacity: 0;
}

.video-thumb-slide.is-active {
  opacity: 1;
}

/* Custom thumbnails manager (my-video-edit.ejs) */
.custom-thumbnails-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  gap: 8px;
}

.custom-thumbnail-item {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: 6px;
  overflow: hidden;
  background: #000;
}

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

.custom-thumbnail-remove {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.7);
  border: 0;
  border-radius: 100%;
  color: #fff;
  cursor: pointer;
  line-height: 1;
}

.custom-thumbnail-remove:hover {
  background: rgba(197, 23, 33, 0.85);
}

/* dark.css's own version of this rule uses a fixed px clamp — this uses
   the row gutter variable instead, so it scales with the rest of the
   channel page's spacing. */
.blog-single-detail .blog-comment .comment-wrapper .comment-box + .comment-box {
  margin-top: calc(var(--bs-gutter-x, 1.5rem) / 2);
}

.blog-single-detail .blog-comment .comment-wrapper .comment-box .media.inner-comment {
  padding: calc(var(--bs-gutter-x, 1.5rem) / 2);
}

.blog-single-detail .blog-comment .comment-wrapper .comment-box .media.inner-comment:not(:first-child) {
  margin-top: calc(var(--bs-gutter-x, 1.5rem) / 2);
}
