:root{
  --bg: #272727;
  --card-bg: #1f1f1f;
  --card-bg-hover: #232323;
  --text: #f2f2f2;
  --text-muted: #9a9a9a;
  --eyebrow: #6f6f6f;
  --accent: #ea3323;
  --border: #383838;
  --max-width: 1280px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: 'Figtree', 'Helvetica Neue', Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }

header.site-header {
  position: relative;
  background: var(--bg);
  padding: 28px 20px;
  text-align: center;
  border-bottom: 1px solid var(--border);
  overflow: hidden;
}

header.site-header.no-border {
  border-bottom: none;
}

header.site-header.has-search {
  text-align: left;
  padding-left: 0;
  padding-right: 0;
}

.site-header-inner {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
}

header.site-header.has-search .logo {
  flex-shrink: 0;
}

.header-search-wrap {
  position: relative;
  z-index: 2;
  flex: 1;
  max-width: 480px;
  display: flex;
  align-items: center;
  background: #1f1f1f;
  border: 1px solid transparent;
  border-radius: 30px;
  padding: 6px;
  transform-origin: right center;
  transition: background 0.2s ease, border-color 0.2s ease, transform 0.3s ease-in;
}

.header-search-wrap:hover {
  background: #131411;
  transform: scale(1.05);
  transition: background 0.2s ease, border-color 0.2s ease, transform 0.3s ease-out;
}

.header-search-input {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: none;
  color: var(--text);
  padding: 12px 10px 12px 20px;
  font-family: 'Figtree', 'Helvetica Neue', Arial, sans-serif;
  font-size: 16px;
  font-weight: 400;
}

.header-search-input::placeholder {
  color: #b8b8b8;
  font-weight: 400;
}

.header-search-input:focus {
  outline: none;
}

.header-search-btn {
  flex-shrink: 0;
  height: 44px;
  padding: 0 22px;
  border-radius: 30px;
  background: #ea3323;
  color: #fff;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  font-family: 'Figtree', 'Helvetica Neue', Arial, sans-serif;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  transition: transform 0.2s ease, background 0.2s ease;
}

.header-search-btn i {
  position: relative;
  font-size: 15px;
  transition: transform 0.2s ease, color 0.2s ease;
}

.header-search-icon-wrap {
  position: relative;
  width: 22px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.search-line-shape {
  height: 2px;
  border-radius: 2px;
  background: #646464;
}

.search-line {
  position: absolute;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.search-line-1 {
  width: 13px;
  top: 1px;
  left: -6px;
}

.search-line-dot-bottom {
  position: absolute;
  bottom: 2px;
  left: -6px;
  display: flex;
  align-items: center;
  gap: 3px;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.search-line-4 {
  width: 6px;
}

.search-line-dot {
  position: absolute;
  bottom: 8px;
  left: -6px;
  display: flex;
  flex-direction: row-reverse;
  align-items: center;
  gap: 3px;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.search-line-3 {
  width: 8px;
}

.search-dot {
  width: 2px;
  height: 2px;
  border-radius: 50%;
  background: #646464;
}

.header-search-wrap:hover .header-search-btn {
  transform: scale(1.05);
  background: #232323;
}

@keyframes search-lines-scan {
  0%, 100% { transform: translateX(0); opacity: 0.35; }
  50% { transform: translateX(3px); opacity: 1; }
}

.header-search-wrap:hover .search-line-1,
.header-search-wrap:hover .search-line-dot-bottom,
.header-search-wrap:hover .search-line-dot {
  animation: search-lines-scan 2s ease-in-out infinite;
}

.header-search-wrap:hover .search-line-dot-bottom {
  animation-delay: 0.24s;
}

.header-search-wrap:hover .search-line-dot {
  animation-delay: 0.12s;
}

@keyframes search-icon-scan {
  0%, 100% { transform: scale(1.1) translateX(-2px); }
  50% { transform: scale(1.1) translateX(2px); }
}

.header-search-wrap:hover .header-search-btn i {
  color: #ea3323;
  animation: search-icon-scan 2s ease-in-out infinite;
}

.header-search-btn:active {
  transform: scale(0.96);
}

.search-highlight {
  background: var(--accent);
  color: #fff;
  padding: 0 3px;
  border-radius: 3px;
}

.mobile-search-trigger {
  display: none;
}

.mobile-search-flyout {
  display: contents;
}

header.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: url('/assets/footer-bg.jpg');
  background-size: cover;
  background-position: center;
  opacity: 0.22;
  -webkit-mask-image:
    radial-gradient(circle at 8% 30%, black 0%, transparent 56%),
    radial-gradient(circle at 36% 75%, black 0%, transparent 53%),
    radial-gradient(circle at 64% 25%, black 0%, transparent 59%),
    radial-gradient(circle at 92% 70%, black 0%, transparent 53%);
  mask-image:
    radial-gradient(circle at 8% 30%, black 0%, transparent 56%),
    radial-gradient(circle at 36% 75%, black 0%, transparent 53%),
    radial-gradient(circle at 64% 25%, black 0%, transparent 59%),
    radial-gradient(circle at 92% 70%, black 0%, transparent 53%);
  pointer-events: none;
  z-index: 0;
}

header.site-header .logo {
  position: relative;
  z-index: 1;
}

header.site-header .logo-img {
  width: 221px;
  height: auto;
  display: block;
}

.trending-heading {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 30px 20px 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 20px;
}

.trending-title-group {
  display: flex;
  align-items: center;
  gap: 14px;
}

.trending-title-group i {
  color: #fff;
  font-size: 14px;
}

.trending-heading h1 {
  color: var(--text-muted);
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin: 0;
}

.custom-select {
  position: relative;
}

.custom-select-trigger {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  background: var(--card-bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 20px;
  font-family: 'Figtree', 'Helvetica Neue', Arial, sans-serif;
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  cursor: pointer;
  transition: border-color 0.2s ease;
}

.custom-select-trigger:hover,
.custom-select.is-open .custom-select-trigger {
  border-color: var(--accent);
}

.custom-select-trigger i {
  font-size: 11px;
  color: var(--text-muted);
  transition: transform 0.2s ease;
}

.custom-select.is-open .custom-select-trigger i {
  transform: rotate(180deg);
}

.custom-select-options {
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 10;
  min-width: 180px;
  margin: 0;
  padding: 6px;
  list-style: none;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.45);
}

.custom-select-option {
  padding: 10px 14px;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease;
}

.custom-select-option:hover,
.custom-select-option:focus {
  background: var(--accent);
  color: #ffffff;
  transform: scale(1.03);
  outline: none;
}

.custom-select-option.is-selected {
  color: var(--accent);
}

.custom-select-option.is-selected:hover {
  color: #ffffff;
}

.filter-bar {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 24px 32px 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px 32px;
}

.filter-bar-left {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 16px 32px;
}

.filter-bar-right {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 16px 32px;
}

.mobile-always-visible-row {
  display: none;
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 20px 20px 0;
  align-items: center;
  justify-content: space-between;
}

.mobile-filters-flyout {
  display: none;
}

.mobile-filters-flyout .filter-bar-group {
  padding: 0 20px;
  margin-bottom: 24px;
}

.mobile-filters-flyout .filter-bar-group:has(#orderByFilterMobile) {
  margin-bottom: 8px;
}

.mobile-filters-flyout .custom-select {
  flex: 1;
}

.mobile-filters-flyout .custom-select-trigger {
  width: 100%;
}

.filter-bar-group {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--text-muted);
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  white-space: nowrap;
}

.filter-bar-group > i {
  font-size: 14px;
  color: var(--text-muted);
}

.text-white {
  color: #fff;
}

.filter-dots {
  display: flex;
  align-items: center;
  color: var(--text-muted);
  opacity: 0.3;
}

.filter-trending-link {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: 22px;
  color: var(--text-muted);
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.2s ease;
}

.filter-trending-link:hover {
  color: var(--accent);
}

.filter-trending-link i {
  color: #fff;
}

.filter-trending-link:hover i {
  color: var(--accent);
}

@media (max-width: 900px) {
  .filter-dots {
    display: none;
  }
}

.search-no-results {
  display: none;
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 60px 20px 40px;
  text-align: center;
  color: var(--text);
  font-size: 20px;
}

.search-no-results i {
  color: #ea3323;
  margin-right: 10px;
}

.trending-list {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 10px 20px 80px;
  display: flex;
  flex-direction: column;
  gap: 28px;
}

.trending-row.video-card {
  position: relative;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 28px;
  background: var(--card-bg);
  border-radius: 24px;
  padding: 0 28px 0 0;
  overflow: visible;
}

.trending-row .card-link.trending-link {
  display: flex;
  align-items: center;
  gap: 28px;
  flex: 1;
  min-width: 0;
}

.trending-row .thumb-wrap.trending-thumb {
  flex-shrink: 0;
  width: 280px;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 24px 0 0 24px;
}

.trending-row .trending-info {
  flex: 1;
  min-width: 0;
}

.trending-row .trending-info h2 {
  font-size: 22px;
  font-weight: 700;
  margin: 0 0 10px;
}

.trending-row .trending-info .excerpt {
  font-size: 15px;
  color: var(--text-muted);
  margin: 0;
  line-height: 1.5;
}

.trending-row .trending-actions {
  flex-shrink: 0;
  display: flex;
  gap: 12px;
}

.trending-row .trending-actions .watch-now-btn {
  flex: 0 0 auto;
  white-space: nowrap;
}

/* Rank badge: numbered circle, #1-13. Flame accent on #1, desktop only. */
.trending-rank {
  position: absolute;
  left: -22px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.rank-circle {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 22.1px;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4);
  position: relative;
  z-index: 1;
}

.trending-rank.is-top {
  top: 42%;
}

.flame-stage {
  position: relative;
  width: 37.7px;
  height: 49.4px;
  margin-bottom: -10px;
}

.flame-frame {
  position: absolute;
  top: 0;
  left: 0;
  width: 37.7px;
  height: 49.4px;
  opacity: 0;
  filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.4));
  animation: frameCycle 0.88s steps(1, end) infinite;
}

.frame-a { animation-delay: 0s; }
.frame-b { animation-delay: 0.22s; }
.frame-c { animation-delay: 0.44s; }
.frame-d { animation-delay: 0.66s; }

@keyframes frameCycle {
  0%   { opacity: 1; }
  25%  { opacity: 0; }
  100% { opacity: 0; }
}

@media (max-width: 900px) {
  .trending-heading {
    padding: 16px 20px 16px;
    gap: 10px;
  }

  .trending-title-group {
    gap: 6px;
  }

  .trending-heading .filter-bar-group {
    gap: 6px;
  }

  .trending-row.video-card {
    padding: 0 14px 0 0;
    gap: 12px;
  }

  .trending-row .card-link.trending-link {
    gap: 12px;
  }

  .trending-row .thumb-wrap.trending-thumb {
    width: 96px;
    border-radius: 12px 0 0 12px;
  }

  .trending-row .play-icon {
    display: none;
  }

  .trending-row .trending-info h2 {
    font-size: 15px;
    margin: 0 0 3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .trending-row .trending-info .excerpt {
    font-size: 12.5px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* Watch Now is redundant once the whole row is the tap target - the
     duration becomes small inline text instead of its own chip. */
  .trending-row .trending-actions {
    display: block;
  }

  .trending-row .trending-actions .watch-now-btn {
    display: none;
  }

  .trending-rank {
    left: -8px;
  }

  .rank-circle {
    width: 28px;
    height: 28px;
    font-size: 15.6px;
  }

  .flame-stage {
    display: none;
  }

  .trending-list {
    gap: 14px;
  }
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.video-grid {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 28px 20px 40px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}

.video-card[data-batch]:not([data-batch="0"]) {
  display: none;
}

.video-card[data-batch].is-visible {
  display: flex;
}

.load-more-wrap {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 20px 150px;
  text-align: center;
}

#loadMoreBtn {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: #000;
  color: #fff;
  border: none;
  padding-left: 70px;
  padding-right: 70px;
  font-size: 15.9px;
  transition: color 0.3s ease, transform 0.15s ease;
}

#loadMoreBtn::before {
  content: "";
  position: absolute;
  inset: 0;
  background: #1d1d1d;
  transform: translateX(-100%);
  transition: transform 0.35s cubic-bezier(0.65, 0, 0.35, 1);
  z-index: 0;
}

#loadMoreBtn i,
#loadMoreBtn span {
  position: relative;
  z-index: 1;
  transition: transform 0.35s ease, color 0.3s ease;
}

#loadMoreBtn:hover::before {
  transform: translateX(0);
}

#loadMoreBtn:hover i {
  color: #ea3323;
}

#loadMoreBtn:active {
  transform: scale(0.96);
}

@media (max-width: 900px) {
  .video-grid { grid-template-columns: repeat(2, 1fr); gap: 16px; }
}
@media (max-width: 480px) {
  .video-grid { grid-template-columns: 1fr; }
  #loadMoreBtn { padding-left: 30px; padding-right: 30px; width: 100%; }
  header.site-header .logo-img { width: 160px; }
}

.video-card {
  background: var(--card-bg);
  border-radius: 24px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: background 0.2s ease;
}

.video-card:hover { background: var(--card-bg-hover); }

.video-card .thumb-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: #111;
}

.video-card .thumb-loader {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #111;
}

.video-card .thumb-spinner {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 4px solid rgba(255, 255, 255, 0.15);
  border-top-color: #ea3323;
  animation: thumbSpin 0.9s linear infinite;
}

@keyframes thumbSpin {
  to { transform: rotate(360deg); }
}

.video-card .thumb-wrap img {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.35s ease;
}

.video-card:hover .thumb-wrap img { transform: scale(1.04); }

.video-card .play-icon {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 72px;
  height: 72px;
  pointer-events: none;
  z-index: 2;
}

.video-card .play-icon .anim-play-btn {
  display: block;
  width: 100%;
  height: 100%;
}

/* Desktop only - the base 72px size above stays as-is for mobile. */
@media (min-width: 901px) {
  .video-card .play-icon {
    width: 83px;
    height: 83px;
  }
}

/* Shared animated play-button component (used by the card thumbnail
   icon above, and by the hero player button further down). REST state:
   each shape starts small/rotated and invisible. transform-box: fill-box
   makes each shape scale/rotate around its own center rather than the
   SVG's top-left corner. */
.anim-play-btn .layer {
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
}

.anim-play-btn .outer-circle { transform: scale(0.3); }
.anim-play-btn .inner-circle { transform: scale(0.3); }
.anim-play-btn .play-arrow   { transform: scale(0.3); }

/* Transitions on the REST rule control the circles' closing animation
   (hover -> rest): inner circle, then outer circle. The arrow doesn't
   use a transition (see the keyframes below) since it animates
   differently opening vs closing, not just a reversal of the same path. */
.anim-play-btn .outer-circle,
.anim-play-btn .inner-circle {
  transition-property: transform, opacity;
  transition-duration: 0.3s;
  transition-timing-function: ease-in;
}
.anim-play-btn .inner-circle  { transition-delay: 0.08s; }
.anim-play-btn .outer-circle  { transition-delay: 0.16s; }

/* HOVER state: full size / final position, revealed by hovering the
   card itself. The player-frame no longer participates in this - its
   play button auto-reveals on load instead (below) and stays static
   afterward, no hover interaction. Transitions here control the
   opening animation (rest -> hover): outer circle, then inner circle. */
.video-card:hover .anim-play-btn .outer-circle {
  opacity: 1;
  transform: scale(1);
  transition-duration: 0.35s;
  transition-timing-function: cubic-bezier(0.34, 1.2, 0.64, 1);
  transition-delay: 0s;
}

.video-card:hover .anim-play-btn .inner-circle {
  opacity: 1;
  transform: scale(1);
  transition-duration: 0.35s;
  transition-timing-function: cubic-bezier(0.34, 1.2, 0.64, 1);
  transition-delay: 0.12s;
}

/* Arrow: a real keyframe animation instead of a transition, because
   opening and closing now travel to two DIFFERENT sizes rather than
   being mirror images of each other - opening zooms in from big
   (1.4 -> 0.85), closing shrinks away small (0.85 -> 0.3), matching
   how the circles shrink small on close. A plain transition can only
   have one "rest" value, which can't express that, so JS toggles
   .is-open / .is-closing on the card / player-frame to trigger these.
   Order on close: arrow first, then inner circle (0.08s), then outer
   circle (0.16s) - each starting slightly before the previous finishes. */
@keyframes fadeInBadge {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes fadeToPartialOpacity {
  from { opacity: 1; }
  to   { opacity: 0.75; }
}

@keyframes circleScaleIn {
  from { opacity: 0; transform: scale(0.3); }
  to   { opacity: 1; transform: scale(1); }
}

@keyframes playArrowReveal {
  from { opacity: 0; transform: scale(1.4); }
  to   { opacity: 1; transform: scale(0.85); }
}

@keyframes playArrowRetract {
  from { opacity: 1; transform: scale(0.85); }
  to   { opacity: 0; transform: scale(0.3); }
}

.video-card.is-open .anim-play-btn .play-arrow {
  animation: playArrowReveal 0.3s ease-out forwards;
  animation-delay: 0.3s;
}

.video-card.is-closing .anim-play-btn .play-arrow {
  animation: playArrowRetract 0.3s ease-in forwards;
  animation-delay: 0s;
}

.video-card .card-body {
  padding: 22px 20px 24px;
  flex: 1;
  display: flex;
  flex-direction: column;
}

.video-card h2, .video-card h3 {
  font-size: 17px;
  line-height: 1.3;
  margin: 0 0 8px;
  font-weight: 700;
}

.video-card p.excerpt {
  font-size: 15px;
  font-weight: 400;
  line-height: 1.5;
  color: var(--text-muted);
  margin: 0 0 14px;
  flex: 1;
}

.video-grid .video-card p.excerpt {
  margin: 0 0 20px;
}

.video-card .card-actions {
  display: flex;
  gap: 10px;
}

.video-card .watch-now-btn {
  position: relative;
  overflow: hidden;
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: rgba(255, 255, 255, 0.08);
  color: var(--text);
  padding: 14px 18px;
  border-radius: 8px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 1px;
  font-weight: 700;
  transition: color 0.3s ease, transform 0.15s ease;
}

.video-card .watch-now-btn::before {
  content: "";
  position: absolute;
  inset: 0;
  background: #131411;
  transform: translateX(-100%);
  transition: transform 0.35s cubic-bezier(0.65, 0, 0.35, 1);
  z-index: 0;
}

.video-card .watch-now-btn i,
.video-card .watch-now-btn span {
  position: relative;
  z-index: 1;
}

.video-card .watch-now-btn i {
  transition: transform 0.35s ease;
}

.video-card:hover .watch-now-btn::before {
  transform: translateX(0);
}

.video-card:hover .watch-now-btn {
  color: #fff;
}

.video-card:hover .video-card-badge {
  color: #fff;
}

.video-card:hover .watch-now-btn i {
  color: #ea3323;
  transform: translateX(2px);
}

.video-card:active .watch-now-btn {
  transform: scale(0.96);
}

.video-card .video-card-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: rgba(0, 0, 0, 0.4);
  color: var(--text-muted);
  padding: 14px 30px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 1px;
  white-space: nowrap;
  transition: color 0.3s ease;
}

.video-card .video-card-badge i {
  font-size: 12px;
}

.video-card .card-link { display: contents; }

.hero {
  position: relative;
  width: 100%;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 128px 20px 0;
  overflow: hidden;
}

.hero-bg {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center top;
  z-index: 0;
}

.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(0,0,0,0.15) 0%,
    rgba(0,0,0,0.08) 35%,
    rgba(39,39,39,0.2) 48%,
    rgba(39,39,39,0.4) 62%,
    rgba(39,39,39,0.6) 76%,
    rgba(39,39,39,0.82) 89%,
    rgba(39,39,39,1) 100%
  );
  z-index: 1;
}

.player-frame {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 1100px;
  aspect-ratio: 16 / 9;
  border-radius: 24px;
  overflow: hidden;
  box-shadow: 0 30px 80px rgba(0,0,0,0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transform: translateY(-90px);
}

.player-frame.is-playing {
  box-shadow: none;
}

.player-duration-badge {
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: rgba(0, 0, 0, 0.4);
  color: #fff;
  padding: 10px 18px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(10px);
  /* Mobile overrides this delay separately below - this base value only
     applies everywhere else. */
  animation: fadeInBadge 2.4s ease forwards;
  animation-delay: 0.8s;
}

.player-subcategory-badge {
  position: absolute;
  top: 20px;
  right: 20px;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: rgba(0, 0, 0, 0.4);
  color: #fff;
  padding: 10px 18px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 600;
  text-transform: capitalize;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(10px);
  /* Mobile overrides this delay separately below - this base value only
     applies everywhere else. */
  animation: fadeInBadge 2.4s ease forwards;
  animation-delay: 1.2s;
}

.player-duration-badge i,
.player-subcategory-badge i {
  font-size: 12px;
}

.player-frame .play-button {
  position: relative;
  z-index: 2;
  width: 132px;
  height: 132px;
}

.player-frame .play-button .anim-play-btn {
  display: block;
  width: 100%;
  height: 100%;
}

/* Desktop/all-other-breakpoints hover-grow: the intro reveal below is
   completely unchanged/untouched from before this existed - the hover
   effect uses the independent CSS "scale" property instead of
   "transform" specifically so it can never contaminate the reveal.
   transform and scale are separate, composable properties in modern
   CSS (confirmed directly, not assumed) - the browser multiplies them
   together for final rendering, so a plain transition on "scale" here
   layers on top of whatever the reveal's "transform" animation is
   doing, rather than the two fighting over the same property the way
   two "transform"-based animations chained on one element do (that
   was the actual cause of the reveal breaking in an earlier version of
   this: the hover-reverse animation was winning control of "transform"
   during the reveal's own active window, since simultaneously-active
   animations on the same property always have the later-listed one
   win for the entire overlap, not just once the first one finishes).

   The reveal delays below (button 0.5s/0.62s/0.8s, matching duration
   badge 0.8s and subcategory badge 1.2s - see .player-duration-badge/
   .player-subcategory-badge) are now deliberately identical to
   mobile's own reveal timing further down this file - the two used to
   differ, unified on request so the reveal feels the same regardless
   of breakpoint. Mobile's fade-to-75%-opacity finale afterward is
   untouched and still mobile-only.

   Because "scale" never conflicts with anything, plain transition-delay
   staggering works correctly here with no special handling needed -
   outer leads on hover-in (0s/0.08s/0.16s = outer/inner/arrow), arrow
   leads on hover-off (mirrored: 0s/0.08s/0.16s = arrow/inner/outer),
   both directions complete in 0.36s total, comfortably under 1.4s. */
@media (min-width: 901px) {
  .player-frame .play-button .anim-play-btn .outer-circle {
    animation: circleScaleIn 0.35s cubic-bezier(0.34, 1.2, 0.64, 1) 0.5s forwards;
    scale: 1;
    transition: scale 0.2s ease-out 0.16s;
  }

  .player-frame .play-button .anim-play-btn .inner-circle {
    animation: circleScaleIn 0.35s cubic-bezier(0.34, 1.2, 0.64, 1) 0.62s forwards;
    scale: 1;
    transition: scale 0.2s ease-out 0.08s;
  }

  .player-frame .play-button .anim-play-btn .play-arrow {
    animation: playArrowReveal 0.3s ease-out 0.8s forwards;
    scale: 1;
    transition: scale 0.2s ease-out;
  }

  .player-frame:hover .play-button .anim-play-btn .outer-circle {
    scale: 1.15;
    transition-delay: 0s;
  }

  .player-frame:hover .play-button .anim-play-btn .inner-circle {
    scale: 1.15;
    transition-delay: 0.08s;
  }

  .player-frame:hover .play-button .anim-play-btn .play-arrow {
    scale: 1.15;
    transition-delay: 0.16s;
  }
}

/* Mobile: no hover exists to reveal the button (tapping is all there
   is), so instead of the desktop hover-in/hover-out interaction, it
   auto-reveals on page load - same circle-then-arrow choreography as
   the desktop auto-reveal above, just starting later per the mobile
   sequence (button, then duration badge, then subcategory badge) - and
   then settles down to partial opacity after lingering fully visible
   for a bit. The whole .player-frame stays clickable throughout,
   exactly as it already is; this only changes how the button becomes
   visible, not how playback starts. */
@media (max-width: 900px) {
  .player-frame .play-button {
    width: 92px;
    height: 92px;
  }

  .player-frame .play-button .anim-play-btn .outer-circle {
    animation: circleScaleIn 0.35s cubic-bezier(0.34, 1.2, 0.64, 1) forwards;
    animation-delay: 0.5s;
  }

  .player-frame .play-button .anim-play-btn .inner-circle {
    animation: circleScaleIn 0.35s cubic-bezier(0.34, 1.2, 0.64, 1) forwards;
    animation-delay: 0.62s;
  }

  .player-frame .play-button .anim-play-btn .play-arrow {
    animation: playArrowReveal 0.3s ease-out forwards;
    animation-delay: 0.8s;
  }

  /* Reveal finishes at 1.1s (0.8s arrow delay + its 0.3s duration).
     Waiting the same 2.5s pause the original design used before dimming
     puts this fade's start at 3.6s; still a 2s fade for a slow, gradual
     dim rather than a quick snap. */
  .player-frame .play-button {
    animation: fadeToPartialOpacity 2s ease forwards;
    animation-delay: 3.6s;
  }
}

.player-frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  z-index: 3;
}

.video-info {
  max-width: 910px;
  margin: -50px auto 0;
  padding: 0 20px 80px;
  text-align: left;
  position: relative;
  z-index: 2;
}

.video-info h1 {
  font-size: 38px;
  line-height: 1.2;
  margin: 0 0 20px;
  font-weight: 800;
}

.video-info .description {
  font-size: 20px;
  font-weight: 400;
  line-height: 1.7;
  color: #d6d6d6;
  margin: 0 0 42px;
}

.video-info .actions {
  display: flex;
  gap: 24px 14px;
  flex-wrap: wrap;
}

.video-info .actions .btn {
  min-height: 52px;
}

.btn {
  display: inline-block;
  padding: 16px 35px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 1px;
  font-weight: 700;
  border-radius: 8px;
  cursor: pointer;
}

.btn-outline {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: rgba(255, 255, 255, 0.08);
  color: var(--text);
  border: none;
  transition: color 0.3s ease, transform 0.15s ease;
}

.btn-outline:not(.btn-platform)::before {
  content: "";
  position: absolute;
  inset: 0;
  background: #131411;
  transform: translateX(-100%);
  transition: transform 0.35s cubic-bezier(0.65, 0, 0.35, 1);
  z-index: 0;
}

.btn-outline i,
.btn-outline span {
  position: relative;
  z-index: 1;
}

.btn-outline i {
  font-size: 15.96px;
}

.btn-outline:not(.btn-platform):hover::before {
  transform: translateX(0);
}

.btn-outline:not(.btn-platform):hover {
  color: #fff;
}

.btn-outline:not(.btn-platform):hover i {
  color: var(--accent);
}

.btn-outline:not(.btn-platform):active {
  transform: scale(0.96);
}

.btn-platform {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-left: auto;
  background: var(--platform-color, var(--accent));
  border-color: var(--platform-color, var(--accent));
  color: #fff;
  transition: filter 0.2s ease;
}

.btn-platform i {
  font-size: 22.34px;
  color: #fff;
}

.btn-platform:hover {
  filter: brightness(0.88);
}

/* Vimeo button override: black button, brand-cyan text/icon */
.btn-platform:has(.fa-vimeo-v) {
  background: #000000;
  border-color: #000000;
  color: #17D5FF;
}

.btn-platform:has(.fa-vimeo-v) i {
  color: #17D5FF;
}

.related-section {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0px 20px 80px;
  border-top: 1px solid var(--border);
}

.related-section h2.section-label {
  text-align: center;
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-muted);
  margin: 40px 0 38px;
}

.related-section h2.section-label::before,
.related-section h2.section-label::after {
  font: var(--fa-font-solid);
  color: var(--text-muted);
  font-size: 1.1em;
  vertical-align: middle;
}

.related-section h2.section-label::before {
  content: "\f72f";
  margin-right: 20px;
}

.related-section h2.section-label::after {
  content: "\f4e3";
  margin-left: 20px;
}

.related-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}

.related-grid .card-actions {
  margin-top: 14px;
}

/* Scroll-triggered reveal - starts hidden/shifted down, animates into
   place once the IntersectionObserver in assets/site.js adds
   .is-visible as the card scrolls into the viewport. Each card animates
   independently as it individually comes into view, not all at once.
   0.1s base delay before the first card starts, then a left-to-right
   stagger - card 2 at 0.25s, card 3 at 0.45s - each subsequent card
   starting later than the previous one, for a rolling left-to-right
   feel. */
.related-grid .video-card {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity 0.6s ease, transform 0.6s ease;
  transition-delay: 0.1s;
}

.related-grid .video-card:nth-child(2) { transition-delay: 0.25s; }
.related-grid .video-card:nth-child(3) { transition-delay: 0.45s; }

.related-grid .video-card.is-visible {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .related-grid .video-card {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

@media (max-width: 900px) {
  .related-grid { grid-template-columns: repeat(2, 1fr); gap: 16px; }
  .video-info {
    margin: -70px auto 0;
    padding: 0 24px 40px;
  }
  .video-info h1 { font-size: 26px; margin: 0 0 14px; }
  .video-info .description {
    font-size: 17px;
    font-weight: 600;
    line-height: 1.8;
    margin: 0 0 32px;
  }
  .video-info .actions { flex-direction: column; }
  .video-info .actions .btn { width: 100%; justify-content: center; }
  .btn-platform { margin-left: 0; }
  .player-frame { transform: translateY(-100px); }
  .related-section { padding: 0px 20px 30px; }
  .footer-content { padding: 10px 30px; }
  .player-subcategory-badge {
    top: 14px;
    right: 14px;
    padding: 8px 14px;
  }
  .player-duration-badge {
    top: 14px;
    left: 14px;
    padding: 8px 14px;
  }
}

@media (max-width: 480px) {
  .related-grid { grid-template-columns: 1fr; }
  .video-info h1 { font-size: 22px; }
  .video-info .description { font-size: 16px; }
}

.site-footer {
  position: relative;
  min-height: 620px;
  overflow: hidden;
  background: #6e6e6e;
}

/* Pixel dissolve transition. The canvas draws at a fixed 900px working
   height - unchanged from before, so the effect's own proportions
   (solid top / dissolve zone / flat bottom) are untouched. .site-footer
   is shorter than that and clips via overflow: hidden, so only the top
   portion (the solid blend + the tall dissolve zone) is visible; most of
   the flat gray floor below the dissolve zone gets cropped off rather
   than shown in full. */
.pixel-transition {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 900px;
  z-index: 0;
  overflow: hidden;
}

.pixel-transition canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.footer-content {
  position: relative;
  z-index: 1;
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 20px 60px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 30px;
}

.footer-message p {
  font-family: 'Silkscreen', 'Figtree', 'Helvetica Neue', Arial, sans-serif;
  font-size: 12px;
  font-weight: 400;
  color: var(--text);
  margin: 0;
  text-align: center;
  white-space: nowrap;
}

.footer-logo-img {
  width: 55px;
  height: auto;
  display: block;
}

@media (max-width: 700px) {
  .site-footer {
    min-height: 360px;
  }

  .pixel-transition {
    height: 500px;
  }

  .footer-content {
    padding: 40px 30px;
  }
}

@media (max-width: 480px) {
  .footer-message p {
    white-space: normal;
  }
}

/* Mobile search/filter flyout - deliberately placed at the very end of
   this file. These rules override earlier base rules (.filter-bar,
   .mobile-always-visible-row, .mobile-filters-flyout) that share the same
   specificity; putting this block last guarantees it wins the cascade at
   this breakpoint regardless of where those base rules are defined above. */
@media (max-width: 700px) {
  .mobile-search-trigger {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    flex-shrink: 0;
    border-radius: 50%;
    background: #1f1f1f;
    border: 1px solid var(--border);
    color: var(--text);
    padding: 0;
    position: relative;
    overflow: hidden;
    cursor: pointer;
    transition: background 0.2s ease, color 0.2s ease;
  }

  .mobile-search-trigger svg {
    width: 39px;
    height: 28.6px;
    stroke: currentColor;
    stroke-width: 4px;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: none;
    display: block;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }

  .mobile-search-trigger svg path {
    transition: stroke-dasharray 0.5s ease, stroke-dashoffset 0.5s ease;
    stroke-dasharray: 26px 100px;
    stroke-dashoffset: 126px;
    transform: translateZ(0);
  }

  .mobile-search-trigger svg path:nth-child(2) {
    transition-duration: 0.4s;
    transition-timing-function: ease-in;
    stroke-dashoffset: 100px;
    stroke-dasharray: 26px 74px;
  }

  .mobile-search-trigger svg path:nth-child(3) {
    stroke-dashoffset: 133px;
    stroke-dasharray: 26px 107px;
  }

  .mobile-search-trigger.is-open svg path {
    stroke-dashoffset: 57px;
  }

  .mobile-search-trigger.is-open svg path:nth-child(1),
  .mobile-search-trigger.is-open svg path:nth-child(3) {
    transition-delay: 0.15s;
    transition-timing-function: cubic-bezier(0.2, 0.4, 0.2, 1.1);
  }

  .mobile-search-trigger.is-open svg path:nth-child(2) {
    transition-duration: 0.4s;
    stroke-dashoffset: 2px;
    stroke-dasharray: 1px 100px;
  }

  .mobile-search-trigger.is-open svg path:nth-child(3) {
    stroke-dashoffset: 58px;
  }

  .mobile-search-trigger.is-open {
    background: var(--accent);
    color: #fff;
  }

  .mobile-search-flyout {
    display: block;
    width: 100%;
    background: var(--bg);
    padding: 0 20px;
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.35s ease;
  }

  .mobile-search-flyout.is-open {
    max-height: 140px;
    padding-bottom: 8px;
  }

  .mobile-search-flyout .header-search-wrap {
    max-width: 100%;
    width: 100%;
    margin-top: 24px;
    margin-bottom: 24px;
  }

  .mobile-search-flyout .header-search-wrap:hover {
    transform: none;
  }

  .mobile-search-flyout .header-search-wrap:hover .header-search-btn {
    transform: none;
  }

  .mobile-always-visible-row {
    display: flex;
  }

  .mobile-filters-flyout {
    display: block;
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.35s ease, overflow 0s linear;
  }

  .mobile-filters-flyout.is-open {
    max-height: 220px;
    overflow: visible;
    transition: max-height 0.35s ease, overflow 0s linear 0.35s;
  }

  .mobile-filters-flyout .custom-select-options {
    left: 0;
    right: 0;
    transform: none;
  }

  .mobile-filters-flyout .custom-select-trigger {
    justify-content: space-between;
  }

  .filter-bar {
    display: none;
  }

  .mobile-search-flyout .header-search-btn span:last-child {
    display: none;
  }

  .mobile-search-flyout .header-search-btn {
    padding: 0 16px;
    gap: 0;
  }

  header.site-header.has-search {
    padding: 20px 8px;
  }

  .site-header-inner {
    padding: 0 8px;
    gap: 0;
  }

  header.site-header .logo-img {
    width: 120px;
  }
}

/* ==========================================================================
   HOSTED VIDEO INTERIOR PAGE
   --------------------------------------------------------------------------
   Applies only to videos with video_source = 'hosted'. Embedded YouTube /
   Vimeo pages use the .hero + .video-info layout above and are untouched.

   Nothing here introduces a new colour, breakpoint or radius - it reuses the
   :root variables, the three existing breakpoints (900/700/480), and the
   .player-frame / .play-button / badge components already defined above.
   ========================================================================== */

.hosted-page {
  max-width: var(--max-width);
  margin: 0 auto;
  /* 20px sides matches .related-section, so the hero columns and the card
     grid below line up on the same edges. */
  padding: 40px 20px 64px;
}

/* Two columns: player left, title/excerpt/CTA right.
   minmax(0, ...) on both tracks stops a long unbroken title from forcing its
   column wider than its share - the standard CSS Grid overflow trap. */
.hosted-hero {
  display: grid;
  /* 1.86 : 1 gives the player ~65% of the row and the text ~35%.
     Was 1.25 : 1 (~55/45). minmax(0, ...) on both tracks stops a long
     unbroken title forcing its column wider than its share. */
  grid-template-columns: minmax(0, 1.86fr) minmax(0, 1fr);
  gap: 48px;
  align-items: start;
}

.hosted-player {
  min-width: 0;
}

/* --------------------------------------------------------------------------
   The frame keeps its .player-frame class on purpose. That's what gives the
   hosted page the play button's auto-reveal on load, its 1.15 hover scale on
   desktop, the mobile dim-to-0.75 sequence, and both badge positions with
   their staggered fadeInBadge timing - all for free, no duplicated rules.

   .hosted-frame cancels only the parts of .player-frame that exist to place
   it inside the old full-bleed .hero.
   -------------------------------------------------------------------------- */
.player-frame.hosted-frame {
  /* Mirrors the value .gbp sets on itself. The play button is a SIBLING of
     .gbp, not a descendant, so it can't inherit the variable from there -
     without this the calc() that re-centres it silently fails and the button
     drops to the bottom of the frame. Keep both in sync (58px at <=900px). */
  --gbp-bar-h: 76px;

  /* .player-frame is a centring flexbox, which would sit the play button
     BESIDE the player rather than over it. Block + absolute button instead. */
  display: block;
  /* The player sets its own ratio from the video's real dimensions, so a
     fixed 16/9 here would letterbox anything that isn't 16:9. */
  aspect-ratio: auto;
  max-width: none;
  margin: 0;
  /* translateY(-90px) exists to pull the player up into the hero. In this
     two-column layout it would just yank it out of the grid. */
  transform: none;
  /* Match the player's own corner radius rather than the hero box's 24px. */
  border-radius: 12px;

  /* .player-frame carries a large drop shadow that .is-playing then removes,
     so on the embed page it fades out as the video starts. On the hosted
     layout that read as a glitch - a shadow on load that vanished on play -
     so it's off here from the start, in both states. Embed pages keep it. */
  box-shadow: none;
}

/* The player ships its own centre play button; the site's animated one
   replaces it here. The control bar's play button is untouched. */
.hosted-frame .gbp__bigplay {
  display: none;
}

/* .player-frame .play-button is position:relative, centred by the flexbox
   we just turned off - so it needs real centring now. Its 132px/92px sizes
   still come from the rules above. */
.hosted-frame .play-button {
  position: absolute;
  /* The frame now contains the video AND the control bar beneath it, so a
     flat 50% would sit the button low - centred on the pair rather than on
     the picture. Lifting it by half the bar height re-centres it on the
     video itself. */
  /* --gbp-bar-actual is measured and published by player.js. The declared
     --gbp-bar-h is only a min-height, so it's wrong whenever the bar wraps
     (phones) - it's kept here purely as a pre-script fallback. */
  top: calc(50% - (var(--gbp-bar-actual, var(--gbp-bar-h)) / 2));
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  line-height: 0;
}

/* This one is a <button> rather than the embed page's <div>, so it's
   keyboard-reachable and needs a visible focus ring. */
.hosted-frame .play-button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 6px;
  border-radius: 50%;
}

/* Once playback starts the poster is gone and the controls own the frame.
   Mirrors what resetPlayer() does inline on the embed page. */
.hosted-frame.is-playing .play-button,
.hosted-frame.is-playing .player-duration-badge,
.hosted-frame.is-playing .player-subcategory-badge {
  display: none;
}

/* --- Info column --------------------------------------------------------- */

.hosted-info {
  min-width: 0;
  padding-top: 4px;   /* optically aligns cap-height with the player's top */
}

.hosted-info h1 {
  /* Centred on the existing 38px hero size, allowed to grow on wide desktops
     to match the mockup and shrink gracefully in between. */
  font-size: clamp(30px, 2.7vw, 46px);
  font-weight: 800;
  line-height: 1.12;
  letter-spacing: -0.01em;
  color: var(--text);
  margin: 0 0 20px;
}

.hosted-info .hosted-excerpt {
  font-size: 20px;
  font-weight: 400;
  line-height: 1.6;
  color: #d6d6d6;        /* same dimmer body colour as .video-info p */
  margin: 0 0 34px;
  max-width: 60ch;       /* keeps line length readable on wide screens */
}

.hosted-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

/* No .hosted-divider rule needed: .related-section already carries
   border-top: 1px solid var(--border), which is the divider in the mockup.
   No width modifier needed either - .related-section is already
   var(--max-width), the same width as .hosted-page above. */

/* --- Mobile (existing 900px breakpoint) ---------------------------------- */

@media (max-width: 900px) {
  .hosted-page {
    padding: 20px 20px 40px;
  }

  .hosted-hero {
    grid-template-columns: minmax(0, 1fr);
    gap: 24px;
  }

  /* The mobile rule above sets .player-frame to translateY(-100px); cancel
     that here too, since the base .hosted-frame rule only covers -90px. */
  .player-frame.hosted-frame {
    transform: none;
    --gbp-bar-h: 66px;   /* matches .gbp's mobile value - see note above */
  }

  .hosted-info {
    padding-top: 0;
  }

  .hosted-info h1 {
    font-size: 26px;      /* matches the existing mobile hero size */
    margin: 0 0 14px;
  }

  .hosted-info .hosted-excerpt {
    font-size: 17px;
    font-weight: 600;     /* existing mobile treatment for body copy */
    line-height: 1.8;
    margin: 0 0 26px;
  }

  .hosted-actions .btn {
    width: 100%;
    justify-content: center;
  }
}

/* --- Small phones (existing 480px breakpoint) ---------------------------- */

@media (max-width: 480px) {
  .hosted-info h1 {
    font-size: 22px;      /* matches the existing ≤480px hero size */
  }

  .hosted-info .hosted-excerpt {
    font-size: 16px;
  }
}


/* ==========================================================================
   SELF-HOSTED VIDEO PLAYER
   --------------------------------------------------------------------------
   Formerly assets/player.css (an older copy of that file was still sitting
   in assets/ unused; it has been deleted). Only used on hosted video pages,
   but it costs ~9KB on every page in exchange for having exactly one
   stylesheet to get right.

   Scoped entirely under .gbp - none of these rules can touch anything else
   on the site.
   ========================================================================== */

.gbp {
  /* ---- Mockup-matched values. Tweak here, not in the rules below. ---- */
  --gbp-stage:        #131313;                    /* video letterbox area   */
  --gbp-bar:          #373737;                    /* control bar strip      */
  --gbp-track:        #262626;                    /* progress: unplayed, at rest */
  --gbp-stripe-a:     #5c5c5c;                    /* loading stripe, light  */
  --gbp-stripe-b:     #4b4b4b;                    /* loading stripe, dark   */
  --gbp-stripe-alpha: 0.5;                        /* stripe layer opacity   */
  --gbp-played:       #151515;                    /* progress: played       */
  --gbp-buffered:     #464646;                    /* progress: buffered     */
  --gbp-handle:       #929292;                    /* scrubber handle        */

  /* ---- CONTRAST NOTE ------------------------------------------------------
     Four of these fall below WCAG 1.4.11, which asks 3:1 for UI conveying
     state (4.5:1 for text). Measured against the current bar (#373737):

        track vs bar        2.55:1   needs 3.0
        handle vs track     1.50:1   needs 3.0   <- the serious one
        time text vs bar    4.23:1   needs 4.5
        focus ring vs bar   2.83:1   needs 3.0

     The handle is the one that matters in practice: at 1.50:1 the scrubber
     grip is very close to invisible against the track, which is a problem
     for anyone, not just for an audit.

     Smallest set of changes that would pass, keeping the same look:
        --gbp-track:  #808080     (from #747474)
        --gbp-handle: #e1e1e1     (from #929292)
        --gbp-time:   #a0a0a0     (from #9a9a9a)
        --gbp-accent: #f0432f     (focus ring only, from the brand red)
  ---------------------------------------------------------------------- */
  --gbp-icon:         #b4b3b3;                    /* control glyphs         */
  --gbp-icon-hover:   #f2f2f2;
  --gbp-time:         #9a9a9a;
  --gbp-accent:       var(--accent, #ea3323);     /* focus rings, hover     */
  --gbp-radius:       12px;                       /* outer frame corners    */
  --gbp-bar-h:        76px;   /* 40px track + 18px above and below */
  --gbp-track-h:      40px;                       /* progress bar height    */
  --gbp-handle-w:     16px;                       /* scrubber handle width  */
  --gbp-handle-dots:  #7b7b7b;                    /* grip dots on the handle */
  --gbp-handle-dot-r: 1.5px;                      /* dot radius             */
  --gbp-handle-dot-g: 7px;                        /* gap between dot centres */

  /* SWAP FOR BRAND-RED PROGRESS: change --gbp-played to var(--accent,#ea3323) */

  position: relative;
  width: 100%;
  background: var(--gbp-stage);
  border-radius: var(--gbp-radius);
  overflow: hidden;
  font-family: 'Figtree', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  -webkit-tap-highlight-color: transparent;
  isolation: isolate;
}

/* --- Stage: fluid 16:9, never a fixed pixel height ----------------------- */

.gbp__stage {
  position: relative;
  width: 100%;
  /* Defaults to 16:9, then gets overwritten with the video's real ratio.
     Set --gbp-ratio inline (the 'ratio' option of render_player() in
     includes/layout.php) to skip the
     correction entirely and avoid any layout shift. */
  aspect-ratio: var(--gbp-ratio, 16 / 9);
  background: var(--gbp-stage);
  overflow: hidden;
  transition: aspect-ratio .2s ease;
}

.gbp__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  object-fit: contain;
  background: var(--gbp-stage);
}

/* Poster is our own element, not the native poster attribute — the native
   one disappears the instant playback starts and can't be faded. */
.gbp__poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 2;
  transition: opacity .45s ease;
}

.gbp.is-started .gbp__poster { opacity: 0; pointer-events: none; }

/* --- Big centre play button (mockup: ringed circle, light arrow) --------- */

.gbp__bigplay {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 132px;
  height: 132px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  z-index: 4;
  transition: opacity .3s ease, transform .3s cubic-bezier(.4, 0, .2, 1);
}

.gbp__bigplay svg { width: 100%; height: 100%; display: block; }
.gbp__bigplay .gbp-ring  { fill: none; stroke: #3f3e3e; stroke-width: 34; }
.gbp__bigplay .gbp-disc  { fill: #2d2d2c; }
.gbp__bigplay .gbp-arrow { fill: #b4b3b3; transition: fill .2s ease; }

.gbp__bigplay:hover { transform: translate(-50%, -50%) scale(1.06); }
.gbp__bigplay:hover .gbp-arrow { fill: #f2f2f2; }

.gbp.is-started .gbp__bigplay {
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, -50%) scale(.7);
}

/* --- Control bar --------------------------------------------------------- */

/* Sits directly under the video as a normal block, flush against it - not
   absolutely positioned over the picture. Always visible, never animates
   away. The old overlay auto-hid after a few seconds of playback, which
   works with a mouse (move it and the bar returns) but is genuinely
   confusing on phones and tablets: no hover means every interaction starts
   with a blind tap just to make the controls reappear. */
.gbp__bar {
  position: relative;
  min-height: var(--gbp-bar-h);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 14px;
  background: var(--gbp-bar);
  z-index: 6;
}

/* --- Buttons ------------------------------------------------------------- */

.gbp__btn {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Sized from the track, not a fixed number, so the hover box lines up
     exactly with the top and bottom of the progress bar beside it. At a
     hard-coded 36px against a 40px track it sat 2px short at each end - a
     small gap, but visible once you notice it. Tying it to the variable
     means changing --gbp-track-h keeps them in step automatically. */
  width: var(--gbp-track-h);
  height: var(--gbp-track-h);
  padding: 0;
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--gbp-icon);
  cursor: pointer;
  transition: color .18s ease, background .18s ease;
}

.gbp__btn svg { width: 19px; height: 19px; fill: currentColor; }
.gbp__btn:hover { color: var(--gbp-icon-hover); background: rgba(255,255,255,.07); }

/* Hosted player only. Scoped under .hosted-frame rather than applied to
   .gbp__btn globally, so the player keeps its neutral hover if it's ever
   embedded anywhere else on the site. */
.hosted-frame .gbp__btn:hover {
  background: #151515;
  color: var(--accent, #ea3323);
}

/* Visible keyboard focus. Do not remove — this is the single most commonly
   stripped accessibility feature when a player gets reskinned. */
.gbp__btn:focus-visible,
.gbp__progress:focus-visible,
.gbp__volume:focus-visible {
  outline: 2px solid var(--gbp-accent);
  outline-offset: 2px;
}

.gbp__btn[aria-pressed="true"] { color: var(--gbp-accent); }

/* Icon state swapping — one button, two glyphs.
   Uses data attributes, NOT ids: several players can share a page (the
   related-videos grid), and duplicate ids would break both the CSS and
   any future querySelector against them. */
.gbp__btn svg[data-ico]           { display: none; }
.gbp__btn svg[data-ico="play"],
.gbp__btn svg[data-ico="vol"],
.gbp__btn svg[data-ico="fs"]      { display: block; }

.gbp.is-playing .gbp__btn svg[data-ico="play"]   { display: none; }
.gbp.is-playing .gbp__btn svg[data-ico="pause"]  { display: block; }
.gbp.is-muted   .gbp__btn svg[data-ico="vol"]    { display: none; }
.gbp.is-muted   .gbp__btn svg[data-ico="mute"]   { display: block; }
.gbp.is-fs      .gbp__btn svg[data-ico="fs"]     { display: none; }
.gbp.is-fs      .gbp__btn svg[data-ico="fsexit"] { display: block; }

/* --- Progress bar (the mockup's signature element) ----------------------- */

.gbp__progress {
  position: relative;
  flex: 1 1 auto;
  min-width: 120px;   /* never let the buttons squeeze the scrubber away */
  height: calc(var(--gbp-track-h) + 10px);  /* hit area > visual track */
  display: flex;
  align-items: center;
  cursor: pointer;
  touch-action: none;
  border-radius: 6px;
}

.gbp__track {
  position: relative;
  width: 100%;
  height: var(--gbp-track-h);
  background: var(--gbp-track);
  border-radius: 5px;
  overflow: hidden;
}

/* --- Loading stripes -------------------------------------------------------
   The classic barber-pole progress animation: a 45° gradient tiled at
   40x40px, with background-position swept one whole tile per cycle so it
   loops seamlessly.

   Gated on .is-started, so the track is flat #262626 on page load and only
   starts moving once the viewer actually presses play.

   Drawn on a ::before layer rather than the track's own background, so its
   opacity can be dialled down without fading .gbp__buffered and .gbp__played
   with it - opacity on .gbp__track would apply to the whole subtree.
   ::before also paints before its positioned siblings in DOM order, which is
   what keeps the buffered and played bars on top of the stripes.

   .gbp__buffered paints on top of this, so the stripes are progressively
   covered as the video loads - that's the intended behaviour, not a bug.
   The animation keeps running underneath; it costs essentially nothing
   since only background-position changes, which the compositor handles.

   prefers-reduced-motion is already handled by the blanket rule further
   down: those users get the stripes as a static pattern, no movement.
-------------------------------------------------------------------------- */

.gbp.is-started .gbp__track::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: var(--gbp-stripe-alpha);
  background-color: var(--gbp-stripe-b);
  background-image: linear-gradient(
    45deg,
    var(--gbp-stripe-a) 25%,
    transparent          25%,
    transparent          50%,
    var(--gbp-stripe-a)  50%,
    var(--gbp-stripe-a)  75%,
    transparent          75%,
    transparent
  );
  background-size: 40px 40px;
  animation: gbp-stripes 2s linear infinite;
}

@keyframes gbp-stripes {
  from { background-position: 40px 0; }
  to   { background-position: 0 0; }
}

.gbp__buffered,
.gbp__played {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  border-radius: 4px;
  width: 0;
}

.gbp__buffered { background: var(--gbp-buffered); }
.gbp__played   { background: var(--gbp-played); }

/* Sits in .gbp__progress, NOT inside .gbp__track — the track is
   overflow:hidden to clip the fills, which would slice the handle in half
   at 0% and 100%. A wider handle makes that clipping obvious, so it lives
   one level up. */
.gbp__handle {
  position: absolute;
  top: 50%;
  left: 0;
  width: var(--gbp-handle-w);
  height: calc(var(--gbp-track-h) + 0px);
  margin-left: calc(var(--gbp-handle-w) / -2);
  background: var(--gbp-handle);
  border-radius: 3px;
  transform: translateY(-50%);
  pointer-events: none;
  z-index: 3;
  box-shadow: 0 0 0 1px rgba(0,0,0,.35);
}

/* Grip dots - the same mark as Font Awesome's ellipsis-vertical, drawn in
   CSS rather than as a glyph. One dot as the pseudo-element, the other two
   as box-shadow copies offset above and below: no icon font to load, no
   line-height guesswork inside a 16px box, and it can't break if Font
   Awesome fails to arrive. */
.gbp__handle::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: calc(var(--gbp-handle-dot-r) * 2);
  height: calc(var(--gbp-handle-dot-r) * 2);
  margin: calc(var(--gbp-handle-dot-r) * -1) 0 0 calc(var(--gbp-handle-dot-r) * -1);
  border-radius: 50%;
  background: var(--gbp-handle-dots);
  box-shadow:
    0 calc(var(--gbp-handle-dot-g) * -1) 0 var(--gbp-handle-dots),
    0 var(--gbp-handle-dot-g)            0 var(--gbp-handle-dots);
  pointer-events: none;
}

/* Scrub preview time, follows the cursor above the track */
.gbp__scrubtip {
  position: absolute;
  bottom: calc(100% + 8px);
  transform: translateX(-50%);
  padding: 4px 8px;
  background: #000;
  color: #f2f2f2;
  font-size: 12px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  border-radius: 4px;
  pointer-events: none;
  opacity: 0;
  transition: opacity .15s ease;
  white-space: nowrap;
}
.gbp__progress:hover .gbp__scrubtip,
.gbp.is-scrubbing .gbp__scrubtip { opacity: 1; }

/* --- Time readout (mockup: right of the bar, letter-spaced, muted) ------- */

.gbp__time {
  flex: 0 0 auto;
  color: var(--gbp-time);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .08em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  user-select: none;
}

/* --- Volume slider (desktop only; mobile uses hardware buttons) ---------- */

.gbp__volwrap { display: flex; align-items: center; flex: 0 0 auto; }

.gbp__volume {
  width: 0;
  opacity: 0;
  height: 22px;
  margin: 0;
  padding: 0;
  background: none;
  cursor: pointer;
  transition: width .22s ease, opacity .22s ease, margin .22s ease;
  -webkit-appearance: none;
  appearance: none;
}

.gbp__volwrap:hover .gbp__volume,
.gbp__volwrap:focus-within .gbp__volume {
  width: 72px;
  opacity: 1;
  margin-left: 6px;
}

.gbp__volume::-webkit-slider-runnable-track {
  height: 4px; background: var(--gbp-track); border-radius: 2px;
}
.gbp__volume::-moz-range-track {
  height: 4px; background: var(--gbp-track); border-radius: 2px;
}
.gbp__volume::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 12px; height: 12px; margin-top: -4px;
  background: var(--gbp-handle); border-radius: 50%; border: 0;
}
.gbp__volume::-moz-range-thumb {
  width: 12px; height: 12px;
  background: var(--gbp-handle); border-radius: 50%; border: 0;
}

/* --- Settings menu (playback speed + quality if multiple sources) -------- */

.gbp__menuwrap { position: relative; flex: 0 0 auto; }

.gbp__menu {
  position: absolute;
  right: 0;
  bottom: calc(100% + 10px);
  min-width: 150px;
  padding: 6px;
  background: var(--card-bg, #1f1f1f);
  border: 1px solid var(--border, #383838);
  border-radius: 8px;
  list-style: none;
  margin: 0;
  display: none;
  z-index: 10;
  box-shadow: 0 10px 30px rgba(0,0,0,.5);
}
.gbp__menu[data-open="true"] { display: block; }

.gbp__menu li { margin: 0; }

.gbp__menuitem {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  border-radius: 5px;
  background: none;
  color: var(--text, #f2f2f2);
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}
.gbp__menuitem:hover { background: var(--card-bg-hover, #232323); }
.gbp__menuitem:focus-visible { outline: 2px solid var(--gbp-accent); outline-offset: -2px; }
.gbp__menuitem[aria-checked="true"]::after { content: '✓'; color: var(--gbp-accent); }

.gbp__menulabel {
  padding: 6px 10px 4px;
  color: var(--eyebrow, #6f6f6f);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
}

/* --- Captions ------------------------------------------------------------ */

/* Captions live inside the stage, so they measure from the bottom of the
   video itself now that the bar no longer overlaps it. */
.gbp__captions {
  position: absolute;
  left: 5%;
  right: 5%;
  bottom: 20px;
  z-index: 5;
  text-align: center;
  pointer-events: none;
}

.gbp__captions span {
  display: inline-block;
  padding: 4px 10px;
  background: rgba(0, 0, 0, .78);
  color: #fff;
  font-size: clamp(15px, 2.4vw, 21px);
  font-weight: 500;
  line-height: 1.4;
  border-radius: 4px;
}
.gbp__captions:empty { display: none; }

/* --- Buffering spinner --------------------------------------------------- */

.gbp__spinner {
  position: absolute;
  left: 50%; top: 50%;
  width: 44px; height: 44px;
  margin: -22px 0 0 -22px;
  border: 3px solid rgba(255,255,255,.18);
  border-top-color: var(--gbp-accent);
  border-radius: 50%;
  z-index: 5;
  display: none;
  animation: gbp-spin .8s linear infinite;
}
.gbp.is-waiting .gbp__spinner { display: block; }
@keyframes gbp-spin { to { transform: rotate(360deg); } }

/* --- Error state --------------------------------------------------------- */

.gbp__error {
  position: absolute;
  inset: 0;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 24px;
  background: var(--gbp-stage);
  color: var(--text, #f2f2f2);
  text-align: center;
  z-index: 8;
}
.gbp.is-error .gbp__error { display: flex; }
.gbp__error strong { font-size: 16px; font-weight: 700; }
.gbp__error span   { font-size: 14px; color: var(--text-muted, #9a9a9a); }

/* --- Screen-reader-only live region -------------------------------------- */

.gbp__sr {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* --- Fullscreen ---------------------------------------------------------- */

/* In fullscreen the bar still sits below the video rather than over it, so
   the stage takes whatever height is left rather than the full viewport. */
.gbp:fullscreen {
  border-radius: 0;
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--gbp-stage);
}
.gbp:fullscreen .gbp__stage {
  flex: 1 1 auto;
  min-height: 0;
  height: auto;
  aspect-ratio: auto;
}
.gbp:fullscreen .gbp__bar { flex: 0 0 auto; }

.gbp:-webkit-full-screen {
  border-radius: 0;
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
}
.gbp:-webkit-full-screen .gbp__stage {
  flex: 1 1 auto;
  min-height: 0;
  aspect-ratio: auto;
}

/* --- Responsive ---------------------------------------------------------- */

@media (max-width: 900px) {
  .gbp {
    --gbp-bar-h: 66px;      /* 34px track + 16px above and below */
    --gbp-radius: 10px;
    --gbp-track-h: 34px;
    --gbp-handle-w: 15px;
  }
  .gbp__bigplay { width: 92px; height: 92px; }
  .gbp__bar { gap: 6px; padding: 0 10px; }
  .gbp__time { font-size: 11px; letter-spacing: .06em; }
  /* track/handle sizes now come from the variables above */
}

/* Phones: the bar becomes two rows - a full-width scrubber on top, buttons
   and clock beneath. In one row, five 44px touch targets plus the time
   readout left the progress bar about 17px wide on a 390px screen, which is
   impossible to scrub. Uses the site's existing 700px breakpoint. */
@media (max-width: 700px) {
  .gbp__bar {
    flex-wrap: wrap;
    padding: 10px 12px;
    gap: 4px;
    row-gap: 8px;
  }

  .gbp__progress {
    order: -1;          /* above the buttons rather than between them */
    flex: 1 0 100%;     /* its own full-width row */
    min-width: 0;
  }

  .gbp__time {
    margin-left: auto;  /* pushes the clock to the far right of row two */
  }
}

@media (max-width: 480px) {
  .gbp__time { font-size: 10px; }
  .gbp__btn svg { width: 17px; height: 17px; }
}

/* WCAG 2.5.5 — 44px minimum touch targets on coarse pointers.
   Deliberately overrides the track-height sizing above: 40px would be under
   the minimum, and there's no hover box to align with on a touch device. */
@media (hover: none) and (pointer: coarse) {
  .gbp__btn { width: 44px; height: 44px; }
  .gbp__progress { height: 44px; }

  /* Hardware buttons own volume on touch devices, and a hover-to-expand
     slider can't work without hover. Keyed to pointer type, NOT viewport
     width — a desktop browser in a narrow window still has a mouse and
     still needs this control. */
  .gbp__volwrap { display: none; }
}

/* --- Reduced motion ------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  .gbp *,
  .gbp *::before,
  .gbp *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* --- Forced colors / Windows high contrast ------------------------------- */

@media (forced-colors: active) {
  .gbp__btn { forced-color-adjust: none; color: ButtonText; }
  .gbp__track  { background: ButtonFace; border: 1px solid ButtonText; }
  .gbp__played { background: Highlight; }
  .gbp__handle { background: ButtonText; }
  .gbp__handle::after { background: ButtonFace; box-shadow: none; }
}

/* ==========================================================================
   ADMIN (13admin*.php)
   --------------------------------------------------------------------------
   Formerly four separate <style> blocks, one per admin page. Every rule is
   scoped under the body class admin_page_start() sets - .admin, plus
   .admin-login / .admin-dashboard / .admin-edit / .admin-analytics - so none
   of it can reach the public site. Admin buttons are .admin-btn rather than
   .btn so they never pick up the public .btn / .btn-outline animations.
   ========================================================================== */

/* --- Shared ----------------------------------------------------------- */

.admin .wrap {
  max-width: 1100px;
  margin: 0 auto;
  padding: 32px 20px 80px;
}

.admin .topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 28px;
  gap: 16px;
  flex-wrap: wrap;
}

.admin .topbar-left {
  display: flex;
  align-items: center;
  gap: 14px;
}

.admin .dashboard-logo {
  height: 42.56px;
  width: auto;
  display: block;
}

.admin h1 {
  font-size: 22px;
  font-weight: 400;
  margin: 0;
}

.admin .actions-row {
  display: flex;
  gap: 12px;
  align-items: center;
}

.admin-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 10px 20px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  text-decoration: none;
  cursor: pointer;
  border: none;
  font-family: inherit;
}

.admin-btn-primary { background: #ea3323; color: #fff; }
.admin-btn-primary:hover { filter: brightness(0.92); }
.admin-btn-outline { background: transparent; color: #f2f2f2; border: 1px solid #383838; }
.admin-btn-outline:hover { background: rgba(255, 255, 255, 0.06); }
.admin-btn-outline.is-active { background: #ea3323; border-color: #ea3323; }
.admin-btn:disabled { opacity: 0.3; cursor: default; pointer-events: none; }
.admin-btn-danger { background: rgba(234, 51, 35, 0.14); color: #ff8a80; border: 1px solid rgba(234, 51, 35, 0.4); }
.admin-btn-danger:hover { background: rgba(234, 51, 35, 0.24); }
.admin-btn-sm { padding: 7px 14px; font-size: 12px; }
.admin-btn-icon { padding: 8px; width: 32px; height: 32px; justify-content: center; }

.admin .message {
  padding: 12px 16px;
  border-radius: 8px;
  font-size: 14px;
  margin-bottom: 20px;
}

.admin .message-success {
  background: rgba(80, 200, 120, 0.12);
  border: 1px solid rgba(80, 200, 120, 0.35);
  color: #8fe0a8;
}

.admin .message-error {
  background: rgba(234, 51, 35, 0.12);
  border: 1px solid rgba(234, 51, 35, 0.4);
  color: #ff8a80;
}

/* --- Login ------------------------------------------------------------ */

body.admin-login {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

.admin-login .admin-box {
  width: 100%;
  max-width: 380px;
  background: #1f1f1f;
  border: 1px solid #383838;
  border-radius: 16px;
  padding: 36px 32px;
}

.admin-login h1 {
  font-size: 20px;
  font-weight: 700;
  margin: 0 0 6px;
}

.admin-login .sub {
  color: #9a9a9a;
  font-size: 14px;
  margin: 0 0 24px;
  line-height: 1.5;
}

.admin-login label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 6px;
}

.admin-login input {
  width: 100%;
  padding: 12px 14px;
  margin-bottom: 18px;
  background: #272727;
  border: 1px solid #383838;
  border-radius: 8px;
  color: #f2f2f2;
  font-size: 14px;
  font-family: inherit;
}

.admin-login input:focus {
  outline: none;
  border-color: #ea3323;
}

.admin-login button {
  width: 100%;
  padding: 13px;
  background: #ea3323;
  color: #fff;
  border: none;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  cursor: pointer;
  font-family: inherit;
}

.admin-login button:hover { filter: brightness(0.92); }

.admin-login .error {
  background: rgba(234, 51, 35, 0.12);
  border: 1px solid rgba(234, 51, 35, 0.4);
  color: #ff8a80;
  padding: 12px 14px;
  border-radius: 8px;
  font-size: 13px;
  margin-bottom: 18px;
  line-height: 1.4;
}

.admin-login .hint {
  font-size: 12px;
  color: #6f6f6f;
  margin-top: 18px;
  line-height: 1.5;
}

/* --- Dashboard -------------------------------------------------------- */

.admin .ga4-strip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  margin-bottom: 28px;
  padding: 24px 28px;
  background: #1f1f1f;
  border: 1px solid #383838;
  border-radius: 12px;
}

.admin .ga4-strip-stats {
  display: flex;
  align-items: center;
  gap: 40px;
  flex-wrap: wrap;
}

.admin .ga4-stat {
  display: flex;
  align-items: center;
  gap: 10px;
}

.admin .ga4-stat-number {
  font-size: 16px;
  font-weight: 800;
  line-height: 1;
}

.admin .ga4-stat-active .ga4-stat-number { color: #fff; }
.admin .ga4-stat-active .ga4-stat-icon { color: #fff; font-size: 14px; }

.admin .ga4-stat-label {
  font-size: 13px;
  color: #9a9a9a;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  white-space: nowrap;
}

.admin-dashboard table {
  width: 100%;
  border-collapse: collapse;
  background: #1f1f1f;
  border: 1px solid #383838;
  border-radius: 12px;
  overflow: hidden;
}

.admin-dashboard th,
.admin-dashboard td {
  text-align: left;
  padding: 14px 16px;
  border-bottom: 1px solid #383838;
  font-size: 14px;
  vertical-align: middle;
}

.admin-dashboard th {
  color: #9a9a9a;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  font-weight: 700;
}

.admin-dashboard tr:last-child td { border-bottom: none; }
.admin-dashboard tbody tr { cursor: pointer; transition: background 0.15s ease; }
.admin-dashboard tbody tr:hover { background: rgba(255, 255, 255, 0.03); }

.admin .thumb {
  width: 83px;
  height: 47px;
  object-fit: cover;
  border-radius: 4px;
  background: #272727;
  display: block;
}

.admin .title-cell { font-weight: 600; margin-bottom: 6px; }
.admin .slug-cell { color: #6f6f6f; font-size: 12px; }
.admin .subcategory-cell { color: #9a9a9a; }

.admin .badge {
  display: inline-block;
  padding: 3px 8px;
  border-radius: 20px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.admin .badge-scheduled { background: rgba(234, 179, 8, 0.15); color: #eab308; }
.admin .badge-expired { background: rgba(154, 154, 154, 0.15); color: #9a9a9a; }
.admin .badge-external { background: rgba(23, 213, 255, 0.15); color: #17D5FF; }
.admin .badge-sponsored { background: rgba(234, 51, 35, 0.15); color: #ea3323; }
.admin .badge-plain { color: #6f6f6f; font-size: 11px; }

.admin .row-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}

.admin .empty-state {
  text-align: center;
  padding: 60px 20px;
  color: #9a9a9a;
}

.admin form.inline { display: inline; }

.admin .pagination-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 20px;
  gap: 16px;
}

.admin .pagination-status {
  color: #9a9a9a;
  font-size: 13px;
}

/* --- Add / edit form -------------------------------------------------- */

.admin-edit .wrap { max-width: 720px; }

.admin-edit .topbar {
  margin-bottom: 24px;
  gap: 0;
  flex-wrap: nowrap;
}

.admin-edit h1 { font-size: 26px; font-weight: 700; }
.admin-edit a.back { color: #9a9a9a; font-size: 15px; }
.admin-edit a.back:hover { color: #f2f2f2; }

.admin-edit form {
  background: #1f1f1f;
  border: 1px solid #383838;
  border-radius: 12px;
  padding: 28px;
}

.admin-edit .field { margin-bottom: 20px; }
.admin-edit .field-row { display: flex; gap: 16px; }
.admin-edit .field-row .field { flex: 1; }

.admin-edit label {
  display: block;
  font-size: 15px;
  font-weight: 600;
  margin-bottom: 6px;
}

.admin-edit .label-note { color: #6f6f6f; font-weight: 400; }

.admin-edit .hint {
  font-size: 14px;
  color: #6f6f6f;
  margin-top: 6px;
  line-height: 1.4;
}

.admin-edit input[type="text"],
.admin-edit textarea {
  width: 100%;
  padding: 11px 14px;
  background: #272727;
  border: 1px solid #383838;
  border-radius: 8px;
  color: #f2f2f2;
  font-size: 17px;
  font-family: inherit;
}

.admin-edit textarea { resize: vertical; min-height: 70px; }

.admin-edit input:focus,
.admin-edit textarea:focus {
  outline: none;
  border-color: #ea3323;
}

.admin-edit .admin-btn {
  display: inline-block;
  padding: 12px 24px;
  font-size: 15px;
}

.admin-edit .errors {
  background: rgba(234, 51, 35, 0.12);
  border: 1px solid rgba(234, 51, 35, 0.4);
  color: #ff8a80;
  padding: 14px 16px;
  border-radius: 8px;
  font-size: 15px;
  margin-bottom: 20px;
  line-height: 1.6;
}

.admin-edit .errors ul { margin: 0; padding-left: 18px; }

.admin-edit .type-toggle { display: flex; gap: 10px; }

.admin-edit .type-option {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px;
  background: #272727;
  border: 1px solid #383838;
  border-radius: 8px;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.admin-edit .type-option input { position: absolute; opacity: 0; pointer-events: none; }
.admin-edit .type-option:has(input:checked) { border-color: #ea3323; background: rgba(234, 51, 35, 0.1); }

/* Content Type and Video Source toggles show/hide field groups via classes
   on the form. Hidden fields are also disabled by the page's script so they
   can't block submit. Wrap a .field-row in the toggled div rather than
   putting the class on the row - display:block would clobber its flex. */
.admin-edit .link-only-field,
.admin-edit .hosted-only-field { display: none; }
.admin-edit #adminForm.type-link .video-only-field,
.admin-edit #adminForm.source-hosted .embed-only-field { display: none; }
.admin-edit #adminForm.type-link .link-only-field,
.admin-edit #adminForm.source-hosted .hosted-only-field { display: block; }

/* --- Analytics -------------------------------------------------------- */

.admin-analytics .message {
  background: rgba(234, 51, 35, 0.14);
  color: #ff8a80;
  border: 1px solid rgba(234, 51, 35, 0.4);
}

.admin .active-now-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #4ade80;
  margin-right: 6px;
  animation: pulse-dot 2s ease-in-out infinite;
}

@keyframes pulse-dot { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }

.admin .range-toggle { display: flex; gap: 8px; margin-bottom: 24px; }

.admin .summary-row,
.admin .panels-row { display: flex; gap: 16px; margin-bottom: 24px; flex-wrap: wrap; }

.admin .summary-card,
.admin .panel {
  flex: 1;
  min-width: 180px;
  background: #1f1f1f;
  border: 1px solid #383838;
  border-radius: 12px;
  padding: 20px 24px;
}

.admin .panel { min-width: 280px; }

.admin .summary-card-number { font-size: 30px; font-weight: 800; line-height: 1.1; }
.admin .summary-card-active .summary-card-number { color: #ea3323; }
.admin .summary-card-label { font-size: 13px; color: #9a9a9a; margin-top: 6px; }

.admin .panel h2 { font-size: 15px; font-weight: 700; margin: 0 0 16px; }
.admin .panel table { width: 100%; border-collapse: collapse; font-size: 14px; }
.admin .panel td { padding: 8px 0; border-bottom: 1px solid #333; }
.admin .panel td:last-child { text-align: right; color: #9a9a9a; white-space: nowrap; padding-left: 12px; }
.admin .panel tr:last-child td { border-bottom: none; }

.admin .device-usage-section { margin-bottom: 24px; }
.admin .device-usage-label { font-size: 15px; font-weight: 700; margin: 0 0 12px; }

.admin .device-usage-bar {
  display: flex;
  width: 100%;
  height: 64px;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid #383838;
}

.admin .device-usage-segment {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  font-weight: 600;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  padding: 0 8px;
}

.admin .empty-note { color: #9a9a9a; font-size: 14px; }
