Files
bitvid/css/style.css
T

1995 lines
42 KiB
CSS

:root {
/*
Core palette tokens used across the application.
--color-page keeps the primary content surface neutral while --color-surface
powers the dark shells (sidebar, dialogs, cards).
*/
--color-page: #ffffff;
--color-surface: #0f172a;
--color-bg: var(--color-surface);
--color-card: #1e293b;
--color-card-private: #3b1d74;
--color-primary: #fe0032;
--color-secondary: #ff93a5;
--color-card-critical: #3f0b13;
--color-text: #f8fafc;
--color-text-strong: #0f172a;
--color-muted: #94a3b8;
--shadow-sm: 0 0.0625rem 0.125rem 0 rgb(0 0 0 / 0.05);
--shadow-md: 0 0.25rem 0.375rem -0.0625rem rgb(0 0 0 / 0.1);
--shadow-lg: 0 0.625rem 0.9375rem -0.1875rem rgb(0 0 0 / 0.1);
--modal-motion-duration: 160ms;
--scrollbar-width: 0.5rem;
--scrollbar-track: rgba(255, 255, 255, 0.1);
--scrollbar-thumb: rgba(255, 255, 255, 0.3);
--scrollbar-thumb-hover: rgba(255, 255, 255, 0.4);
/* Sidebar stack must remain below modal overlays. */
--z-sidebar-overlay: 10;
--z-sidebar: 20;
--z-modal-root: 100;
--z-modal-overlay: 110;
--z-modal-content: 120;
--z-modal-player: 130;
--sidebar-width-expanded: 16rem;
--sidebar-width-collapsed: 4rem;
--sidebar-width: var(--sidebar-width-expanded);
--sidebar-control-size: 2.75rem;
--sidebar-content-gap: 1rem;
}
html {
font-size: 100%;
}
@media (min-width: 1024px) {
html {
font-size: 75%;
}
}
/* Global scrollbar styling */
* {
scrollbar-width: thin;
scrollbar-color: var(--scrollbar-thumb) transparent;
}
*::-webkit-scrollbar {
width: var(--scrollbar-width);
height: var(--scrollbar-width);
}
*::-webkit-scrollbar-track {
background: var(--scrollbar-track);
}
*::-webkit-scrollbar-thumb {
background: var(--scrollbar-thumb);
border-radius: 0.25rem;
}
*::-webkit-scrollbar-thumb:hover {
background: var(--scrollbar-thumb-hover);
}
/* Core Styles */
body {
font-family: system-ui, -apple-system, sans-serif;
background-color: var(--color-page);
color: var(--color-text-strong);
line-height: 1.5;
margin: 0;
padding: 0;
overflow-x: hidden; /* Disable horizontal scrolling */
}
#app {
/*
Keep the primary content surface aligned with the page background so the
sidebar styling does not bleed into the video grid.
*/
background-color: var(--color-page);
color: inherit;
}
header {
margin-bottom: 2rem;
padding: 1rem 0;
display: flex;
justify-content: flex-start;
}
header img {
height: 6rem;
width: auto;
max-width: none;
}
.container {
max-width: 92.5rem;
margin: 0 auto;
padding: 1rem;
}
/* Video Grids */
#videoList {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
gap: 2rem;
padding: 1.5rem 0;
}
/* Subscriptions grid: same pattern as #videoList */
#subscriptionsVideoList {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
gap: 2rem;
padding: 1.5rem 0;
}
/* Now also match for channelVideoList (channel profile) */
#channelVideoList {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
gap: 2rem;
padding: 1.5rem 0;
}
/* Dedicated watch-history layout stacks cards vertically */
.watch-history-grid {
display: flex;
flex-direction: column;
gap: 1.5rem;
width: 100%;
padding: 1.5rem 0;
}
/* Profile modal uses the same vertical stack but without outer padding */
.watch-history-grid.watch-history-grid--modal {
padding: 0;
gap: 1.25rem;
}
@media (max-width: 640px) {
.watch-history-grid {
gap: 1.25rem;
}
.watch-history-grid.watch-history-grid--modal {
gap: 1.125rem;
}
}
/* Video Cards */
.video-card {
background-color: var(--color-card);
border-radius: 0.75rem;
overflow: hidden;
transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: var(--shadow-md);
}
.video-card.video-card--owner-private {
background-color: var(--color-card-private) !important;
box-shadow: 0 0 0 0.125rem rgba(168, 85, 247, 0.55), var(--shadow-md);
}
.video-card.video-card--owner-private:hover {
box-shadow: 0 0 0 0.125rem rgba(192, 132, 252, 0.65), var(--shadow-lg);
}
.video-card[data-owner-is-viewer="false"][data-url-health-state="offline"][data-stream-health-state="unhealthy"] {
display: none;
}
.video-card[data-owner-is-viewer="true"][data-url-health-state="offline"][data-stream-health-state="unhealthy"] {
background-color: var(--color-card-critical);
box-shadow: 0 0 0 0.0625rem rgba(239, 68, 68, 0.35), var(--shadow-md);
}
.video-card[data-owner-is-viewer="true"][data-url-health-state="offline"][data-stream-health-state="unhealthy"]:hover {
box-shadow: 0 0 0 0.0625rem rgba(239, 68, 68, 0.45), var(--shadow-lg);
}
.video-card--enter {
opacity: 0;
animation: video-card-fade-in 220ms ease-out forwards;
}
/* Watch history cards */
.watch-history-card {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
align-items: stretch;
background-color: var(--color-card);
border-radius: 0.75rem;
padding: 1rem 1.25rem;
border: 0.0625rem solid transparent;
box-shadow: var(--shadow-md);
transition: box-shadow 0.2s ease, transform 0.2s ease;
}
.watch-history-card:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
}
.watch-history-card--private {
border-color: rgba(234, 179, 8, 0.75);
}
.watch-history-card__primary {
display: flex;
gap: 1rem;
flex: 1 1 18rem;
min-width: 0;
}
.watch-history-card__thumbnail {
display: block;
flex: 0 0 14rem;
max-width: 14rem;
text-decoration: none;
}
.watch-history-card__thumbnailInner {
width: 100%;
height: 100%;
border-radius: 0.5rem;
overflow: hidden;
background-color: #0f172a;
}
.watch-history-card__thumbnailInner img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.watch-history-card__details {
display: flex;
flex-direction: column;
justify-content: center;
gap: 0.5rem;
min-width: 0;
}
.watch-history-card__title {
margin: 0;
font-size: 1.125rem;
font-weight: 600;
color: #ffffff;
line-height: 1.4;
cursor: pointer;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.watch-history-card__title:hover,
.watch-history-card__title:focus {
color: #60a5fa;
}
.watch-history-card__created {
margin: 0;
font-size: 0.875rem;
color: #9ca3af;
}
.watch-history-card__meta {
display: flex;
flex-direction: column;
justify-content: space-between;
gap: 1rem;
flex: 0 0 16rem;
min-width: 14rem;
}
.watch-history-card__watched {
margin: 0;
font-size: 0.875rem;
color: #d1d5db;
}
.watch-history-card__creator {
display: flex;
align-items: center;
gap: 0.75rem;
}
.watch-history-card__creatorAvatar {
width: 2.5rem;
height: 2.5rem;
border-radius: 9999px;
border: 0;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
background-color: #1f2937;
cursor: pointer;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.watch-history-card__creatorAvatar:hover,
.watch-history-card__creatorAvatar:focus {
box-shadow: 0 0 0 0.125rem rgba(59, 130, 246, 0.5);
outline: none;
}
.watch-history-card__creatorAvatar img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 9999px;
}
.watch-history-card__creatorName {
background: none;
border: none;
padding: 0;
margin: 0;
font-size: 0.95rem;
font-weight: 500;
color: #e5e7eb;
text-align: left;
cursor: pointer;
}
.watch-history-card__creatorName:hover,
.watch-history-card__creatorName:focus {
color: #60a5fa;
outline: none;
}
.watch-history-card__actions {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
align-items: center;
}
.watch-history-card__action {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.5rem 1rem;
border-radius: 9999px;
font-size: 0.875rem;
font-weight: 500;
border: 0.0625rem solid transparent;
background-color: #1f2937;
color: #e5e7eb;
cursor: pointer;
text-decoration: none;
transition: background-color 0.2s ease, color 0.2s ease,
border-color 0.2s ease, box-shadow 0.2s ease;
}
.watch-history-card__action:hover,
.watch-history-card__action:focus {
background-color: #111827;
color: #ffffff;
border-color: #374151;
outline: none;
}
.watch-history-card__action--primary {
background-color: #2563eb;
color: #ffffff;
}
.watch-history-card__action--primary:hover,
.watch-history-card__action--primary:focus {
background-color: #1d4ed8;
border-color: #1d4ed8;
}
.watch-history-card__action--danger {
background-color: #7f1d1d;
color: #ffffff;
}
.watch-history-card__action--danger:hover,
.watch-history-card__action--danger:focus {
background-color: #991b1b;
border-color: #991b1b;
}
@media (max-width: 1024px) {
.watch-history-card__meta {
flex: 1 1 18rem;
}
}
@media (max-width: 768px) {
.watch-history-card {
gap: 1.25rem;
padding: 1rem;
}
.watch-history-card__thumbnail {
flex-basis: 11rem;
max-width: 11rem;
}
}
@media (max-width: 640px) {
.watch-history-card {
flex-direction: column;
}
.watch-history-card__primary,
.watch-history-card__meta {
flex: 1 1 auto;
min-width: 0;
}
.watch-history-card__thumbnail {
width: 100%;
max-width: 100%;
}
.watch-history-card__meta {
gap: 0.75rem;
}
}
@keyframes video-card-fade-in {
from {
opacity: 0;
transform: translateY(0.5rem);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/*
Thumbnails start transparent and fade in the first time they finish loading.
`data-thumbnail-loaded` is cleared by js/index.js once the animation completes
so re-rendering the same element later does not replay the transition and cause
a distracting flash.
*/
[data-video-thumbnail][data-thumbnail-loaded="true"] {
animation: video-thumbnail-fade-in 220ms ease-out forwards;
}
@keyframes video-thumbnail-fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/*
Generic fade-in utility for chrome elements (sidebar, header controls, etc.).
js/index.js listens for the `interface-fade-in` animation finishing and removes
the temporary classes so that once an element has gracefully appeared it stays
opaque even if the DOM is re-used or re-parented later.
*/
.fade-in {
opacity: 0;
animation: interface-fade-in 280ms ease-out forwards;
animation-delay: var(--fade-in-delay, 0ms);
}
.fade-in-delay-100 {
--fade-in-delay: 100ms;
}
.fade-in-delay-200 {
--fade-in-delay: 200ms;
}
.fade-in-delay-300 {
--fade-in-delay: 300ms;
}
.fade-in-delay-400 {
--fade-in-delay: 400ms;
}
@keyframes interface-fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@media (prefers-reduced-motion: reduce) {
.video-card--enter,
.fade-in {
opacity: 1;
animation: none;
}
[data-video-thumbnail][data-thumbnail-loaded="true"] {
animation: none;
opacity: 1;
}
}
.video-card:hover {
transform: translateY(-0.25rem);
box-shadow: var(--shadow-lg);
}
.video-card .thumbnail-container {
position: relative;
padding-top: 56.25%;
background-color: #0f172a;
}
.video-card img.thumbnail {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
.video-card .details {
padding: 1.25rem;
}
.video-card h3 {
font-size: 1.125rem;
font-weight: 600;
color: var(--color-text);
margin-bottom: 0.75rem;
}
/* Ensure modal portals always sit above the sidebar stack */
#modalContainer {
position: fixed;
inset: 0;
z-index: var(--z-modal-root);
pointer-events: none;
isolation: isolate;
}
#modalContainer > * {
pointer-events: auto;
}
#modalContainer > [id$="Modal"]:not(#playerModal) {
z-index: var(--z-modal-root);
}
#modalContainer > [id$="Modal"]:not(#playerModal) > .absolute {
z-index: var(--z-modal-overlay);
}
#modalContainer > [id$="Modal"]:not(#playerModal) .modal-container,
#modalContainer > [id$="Modal"]:not(#playerModal) .modal-content {
z-index: var(--z-modal-content);
}
#modalContainer > #playerModal {
z-index: var(--z-modal-player);
}
#modalContainer > #playerModal .player-modal__container,
#modalContainer > #playerModal .player-modal__content {
z-index: var(--z-modal-content);
}
/* Modal Player */
#playerModal {
position: fixed;
inset: 0;
z-index: var(--z-modal-player);
display: none;
flex-direction: column;
align-items: stretch;
justify-content: stretch;
width: 100vw;
height: 100vh;
background-color: #0f172a;
color: #e2e8f0;
overflow-x: hidden;
overflow-y: auto;
overscroll-behavior: contain;
-webkit-overflow-scrolling: touch;
}
#nostrFormModal,
#profileModal,
#uploadModal {
backdrop-filter: blur(0.625rem);
-webkit-backdrop-filter: blur(0.625rem); /* For Safari */
}
/* --------------------------------------------------------------------------
Profile modal account pane
--------------------------------------------------------------------------
The modal previously mixed Tailwind-style utility classes with our global
stylesheet. Those utilities are not always present in the production build,
so important layout rules (borders, gaps, flex behaviour) were getting
dropped. This block consolidates the account tab styling in one predictable
place so future tweaks only require CSS updates here instead of scattered
inline class lists.
--------------------------------------------------------------------------- */
#profileModal .profile-pane {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
/*
Ensure the global `.hidden` helper keeps working for the tab panes. Our
profile-pane declaration above sets a `display` value with higher
specificity than `.hidden`, so we explicitly restore the hidden state when
both classes are present.
*/
#profileModal .profile-pane.hidden {
display: none;
}
#profileModal .profile-switcher {
display: flex;
flex-direction: column;
gap: 1.5rem;
padding: clamp(1.25rem, 2vw, 1.5rem);
border-radius: 1.25rem;
border: 0.0625rem solid rgba(148, 163, 184, 0.28);
background: linear-gradient(145deg, rgba(15, 23, 42, 0.94), rgba(15, 23, 42, 0.72));
box-shadow: 0 1.75rem 3.5rem rgba(8, 11, 30, 0.45);
}
#profileModal .profile-switcher__header {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
#profileModal .profile-switcher__intro {
display: flex;
flex-direction: column;
gap: 0.35rem;
}
#profileModal .profile-switcher__title {
margin: 0;
font-size: 1rem;
font-weight: 600;
color: var(--color-text);
}
#profileModal .profile-switcher__subtitle {
margin: 0;
font-size: 0.875rem;
color: var(--color-muted);
}
#profileModal .profile-switcher__badge {
align-self: flex-start;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.35rem 0.85rem;
font-size: 0.625rem;
font-weight: 600;
letter-spacing: 0.18em;
text-transform: uppercase;
border-radius: 9999px;
background: rgba(59, 130, 246, 0.18);
color: rgba(191, 219, 254, 0.95);
border: 0.0625rem solid rgba(96, 165, 250, 0.25);
}
#profileModal .profile-card {
position: relative;
display: flex;
flex-direction: column;
gap: 0.85rem;
padding: 1rem;
border-radius: 1rem;
border: 0.0625rem solid rgba(148, 163, 184, 0.24);
background: rgba(15, 23, 42, 0.72);
box-shadow: inset 0 1px 0 rgba(148, 163, 184, 0.08);
color: var(--color-text);
cursor: pointer;
transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
outline: none;
}
#profileModal .profile-card:hover {
border-color: rgba(148, 163, 184, 0.45);
}
#profileModal .profile-card:focus-visible {
border-color: rgba(96, 165, 250, 0.6);
box-shadow: 0 0 0 0.1875rem rgba(37, 99, 235, 0.25);
}
#profileModal .profile-card--active {
border-color: rgba(59, 130, 246, 0.55);
background: linear-gradient(160deg, rgba(37, 99, 235, 0.22), rgba(15, 23, 42, 0.78));
box-shadow: 0 1.35rem 2.8rem rgba(37, 99, 235, 0.22);
}
#profileModal .profile-card__avatar {
flex: 0 0 auto;
width: 3rem;
height: 3rem;
display: grid;
place-items: center;
border-radius: 9999px;
overflow: hidden;
border: 0.1875rem solid rgba(148, 163, 184, 0.3);
background: rgba(15, 23, 42, 0.95);
}
#profileModal .profile-card__avatar img {
width: 100%;
height: 100%;
border-radius: inherit;
object-fit: cover;
}
#profileModal .profile-card--active .profile-card__avatar {
border-color: rgba(96, 165, 250, 0.7);
box-shadow: 0 0 0 0.1875rem rgba(59, 130, 246, 0.18);
}
#profileModal .profile-card__meta {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
#profileModal .profile-card__topline {
display: flex;
flex-direction: column;
gap: 0.35rem;
align-items: flex-start;
}
#profileModal .profile-card__label {
font-size: 0.7rem;
font-weight: 600;
letter-spacing: 0.2em;
text-transform: uppercase;
color: rgba(191, 219, 254, 0.9);
}
#profileModal .profile-card__action {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.3rem 0.8rem;
border-radius: 9999px;
border: 0.0625rem solid rgba(59, 130, 246, 0.4);
background: rgba(59, 130, 246, 0.14);
color: rgba(191, 219, 254, 0.95);
font-size: 0.65rem;
font-weight: 600;
letter-spacing: 0.18em;
text-transform: uppercase;
text-decoration: none;
transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}
#profileModal .profile-card__action:hover,
#profileModal .profile-card__action:focus-visible {
background: rgba(59, 130, 246, 0.24);
border-color: rgba(59, 130, 246, 0.6);
color: #ffffff;
}
#profileModal .profile-card__name {
font-size: 0.95rem;
font-weight: 600;
color: var(--color-text);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#profileModal .profile-card__npub {
font-size: 0.75rem;
font-family: "JetBrains Mono", "Fira Code", ui-monospace, SFMono-Regular, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
color: rgba(148, 163, 184, 0.85);
word-break: break-all;
}
#profileModal .profile-switcher__list {
display: flex;
flex-direction: column;
gap: 1rem;
}
#profileModal .profile-switcher__add {
display: flex;
align-items: center;
gap: 1rem;
padding: 1rem;
border-radius: 1rem;
border: 0.125rem dashed rgba(148, 163, 184, 0.35);
background: rgba(15, 23, 42, 0.55);
color: rgba(226, 232, 240, 0.85);
text-align: left;
cursor: pointer;
transition: border-color 0.2s ease, background 0.2s ease, color 0.2s ease;
}
#profileModal .profile-switcher__add:hover,
#profileModal .profile-switcher__add:focus-visible {
border-color: rgba(96, 165, 250, 0.65);
background: rgba(59, 130, 246, 0.18);
color: #ffffff;
outline: none;
}
#profileModal .profile-switcher__addAvatar {
flex: 0 0 auto;
width: 3rem;
height: 3rem;
display: grid;
place-items: center;
border-radius: 9999px;
border: 0.125rem dashed currentColor;
color: inherit;
background: rgba(15, 23, 42, 0.75);
}
#profileModal .profile-switcher__addAvatar svg {
width: 1.25rem;
height: 1.25rem;
}
#profileModal .profile-switcher__addCopy {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
#profileModal .profile-switcher__addTitle {
font-size: 0.9rem;
font-weight: 600;
color: inherit;
}
#profileModal .profile-switcher__addHint {
font-size: 0.75rem;
color: rgba(148, 163, 184, 0.85);
}
#profileModal .profile-switcher__helper {
margin: 0;
font-size: 0.75rem;
color: rgba(148, 163, 184, 0.7);
}
@media (min-width: 640px) {
#profileModal .profile-switcher__header {
flex-direction: row;
align-items: center;
justify-content: space-between;
}
#profileModal .profile-card {
flex-direction: row;
align-items: center;
}
#profileModal .profile-card__topline {
flex-direction: row;
justify-content: space-between;
align-items: center;
gap: 0.75rem;
}
}
/* If you ever want to show it, add ".flex" class dynamically */
#playerModal.flex {
display: flex;
}
#playerModal .player-modal__container {
flex: 1;
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
min-height: 100vh;
padding: 0;
margin: 0;
}
#playerModal .player-modal__content {
position: relative;
flex: 1;
display: flex;
flex-direction: column;
width: 100%;
min-height: 100%;
max-width: none;
background-color: #0f172a;
overflow: visible;
box-shadow: none;
animation: fadeIn var(--modal-motion-duration) ease-out;
}
#playerModal .player-modal__video {
width: 100%;
position: sticky;
top: 0;
z-index: 51;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
padding: clamp(0.75rem, 3.5vw, 2.5rem);
background-color: var(--color-bg);
border-bottom: 0.0625rem solid rgba(148, 163, 184, 0.18);
}
#playerModal .player-modal__video video {
width: 100%;
aspect-ratio: 16 / 9;
background-color: #000;
border-radius: 0.75rem;
display: block;
box-shadow: 0 1.125rem 2.75rem rgba(8, 11, 30, 0.55);
max-height: min(80vh, calc(100vw * 9 / 16));
object-fit: contain;
}
#playerModal .player-modal__info {
flex: 0 0 auto;
padding: clamp(1.5rem, 3vw, 2.5rem);
padding-bottom: clamp(2.5rem, 6vw, 4rem);
background-color: var(--color-bg);
border-top: 0.0625rem solid rgba(148, 163, 184, 0.16);
box-shadow: inset 0 1px 0 rgba(15, 23, 42, 0.35);
}
.modal-meta {
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.modal-view-count {
display: inline-flex;
align-items: center;
gap: 0.25rem;
font-size: 0.875rem;
line-height: 1.25rem;
color: #9ca3af;
white-space: nowrap;
}
.view-count-text {
white-space: nowrap;
color: #6b7280;
}
html.modal-open {
overflow: hidden;
}
body.modal-open {
overflow: hidden;
}
html.modal-open,
body.modal-open {
height: 100%;
}
body.modal-open #app {
overflow: hidden;
}
body.modal-open #sidebar,
body.modal-open #sidebarOverlay {
pointer-events: none;
opacity: 0;
visibility: hidden;
}
body.modal-open #sidebar {
z-index: var(--z-sidebar-overlay);
}
body.modal-open #sidebarOverlay {
z-index: calc(var(--z-sidebar-overlay) - 1);
}
#sidebar.is-modal-hidden,
#sidebarOverlay.is-modal-hidden {
pointer-events: none;
opacity: 0;
visibility: hidden;
}
/* Modal Content Container */
.modal-content {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
background-color: #0f172a;
animation: fadeIn var(--modal-motion-duration) ease-out;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(1.25rem);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@media (prefers-reduced-motion: reduce) {
.modal-content {
animation-duration: 1ms;
}
}
/* Modal Video */
#modalVideo {
width: 100%;
aspect-ratio: 16/9;
background-color: black;
}
/* Responsive Adjustments */
@media (min-width: 768px) {
.modal-content {
max-width: 64rem;
max-height: calc(100vh - 4rem); /* Account for padding */
border-radius: 0.5rem;
overflow: visible;
}
#playerModal .player-modal__content {
max-width: none;
border-radius: 0;
}
}
#modalNav.modal-nav,
.modal-nav {
background-color: var(--color-bg);
border-bottom: 0.0625rem solid rgba(148, 163, 184, 0.25);
box-shadow: 0 0.75rem 2rem rgba(8, 11, 30, 0.45);
}
.modal-nav .flex {
position: relative;
gap: 0.75rem;
}
.modal-nav .icon-button {
background-color: rgba(30, 41, 59, 0.85);
border: 0.0625rem solid rgba(148, 163, 184, 0.4);
color: #f8fafc;
box-shadow: none;
}
.modal-nav .icon-button:hover {
background-color: rgba(51, 65, 85, 0.95);
border-color: rgba(148, 163, 184, 0.55);
}
.modal-nav .icon-button:focus-visible {
outline: none;
box-shadow: 0 0 0 0.1875rem rgba(148, 163, 184, 0.45);
}
#modalNav {
position: sticky;
top: 0;
z-index: 60;
}
.modal-actions {
margin-left: auto;
display: flex;
align-items: center;
justify-content: flex-end;
gap: 0.5rem;
flex-wrap: nowrap;
}
.zap-popover {
position: absolute;
top: calc(100% + 0.5rem);
right: 0;
z-index: 80;
width: max-content;
}
.zap-popover__content {
width: 18rem;
max-width: calc(100vw - 2rem);
background: rgba(11, 17, 32, 0.96);
color: #e5e7eb;
border: 1px solid rgba(148, 163, 184, 0.35);
box-shadow: 0 22px 48px -18px rgba(8, 14, 28, 0.7);
-webkit-backdrop-filter: blur(12px);
backdrop-filter: blur(12px);
}
.modal-actions__overflow {
position: relative;
overflow: visible;
}
[data-more-menu="true"] {
z-index: 70;
}
/* Mobile-specific styles */
@media (max-width: 767px) {
#playerModal {
padding: 0;
}
.modal-content {
border-radius: 0;
}
}
/* Progress Bars */
.progress-bar {
width: 100%;
height: 0.5rem;
background-color: rgb(255 255 255 / 0.1);
border-radius: 9999px;
overflow: hidden;
}
.progress-bar-fill {
height: 100%;
background-color: var(--color-primary);
transition: width 0.3s ease-out;
}
/* Forms & Inputs */
input,
textarea {
width: 100%;
padding: 0.75rem;
background-color: var(--color-bg);
border: 0.0625rem solid rgb(255 255 255 / 0.1);
border-radius: 0.5rem;
color: var(--color-text);
transition: border-color 0.2s;
}
input:focus,
textarea:focus {
outline: none;
border-color: var(--color-primary);
ring: 0.125rem var(--color-primary);
}
/* -------------------------------------------
COMMENTED OUT the 'button:not(.icon-button)'
global rule that overrides your circles
--------------------------------------------
button:not(.icon-button) {
padding: 0.75rem 1.5rem;
background-color: var(--color-primary);
color: white;
border-radius: 0.5rem;
font-weight: 500;
transition: all 0.2s;
}
button:not(.icon-button):hover {
background-color: var(--color-secondary);
transform: translateY(-0.0625rem);
}
button:not(.icon-button):focus {
outline: none;
ring: 0.125rem var(--color-primary);
}
*/
/* Utility Classes */
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.hidden {
display: none;
}
/* Notifications */
#notificationPortal {
position: fixed;
top: calc(env(safe-area-inset-top, 0px) + 1.5rem);
left: 50%;
transform: translateX(-50%);
z-index: 400; /* Keep notifications above the highest modal overlays */
width: min(90vw, 32rem);
display: flex;
flex-direction: column;
gap: 0.75rem;
pointer-events: none;
}
#notificationPortal > * {
width: 100%;
margin-bottom: 0;
pointer-events: auto;
border-radius: 0.75rem;
box-shadow: 0 1.25rem 3rem rgba(15, 23, 42, 0.3);
}
/* Base styling without a forced display */
#errorContainer,
#successContainer {
border-radius: 0.5rem;
padding: 1rem;
margin-bottom: 1rem;
align-items: center; /* Keep the rest of your styling */
}
/* When not hidden, display as flex */
#errorContainer:not(.hidden),
#successContainer:not(.hidden) {
display: flex;
}
.status-spinner--inline {
animation: spin 1s linear infinite;
border: 0.125rem solid rgba(96, 165, 250, 0.35);
border-radius: 9999px;
border-top-color: #60a5fa;
display: inline-block;
height: 1rem;
width: 1rem;
}
.sidebar-loading-wrapper {
display: flex;
justify-content: center;
align-items: center;
padding: 3rem 0;
width: 100%;
grid-column: 1 / -1;
}
.sidebar-loading-indicator {
display: inline-flex;
align-items: center;
gap: 0.75rem;
color: #6b7280;
font-size: 0.875rem;
font-weight: 500;
letter-spacing: 0.01em;
}
.sidebar-loading-text {
white-space: nowrap;
}
.status-banner {
align-items: center;
background-color: rgba(31, 41, 55, 0.9);
border-radius: 0.5rem;
color: #e5e7eb;
display: flex;
gap: 0.75rem;
margin-bottom: 1rem;
padding: 1rem;
}
.status-banner .status-spinner {
animation: spin 1s linear infinite;
border: 0.125rem solid rgba(229, 231, 235, 0.35);
border-radius: 9999px;
border-top-color: #f9fafb;
height: 1.25rem;
width: 1.25rem;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
/* Responsive Design */
@media (max-width: 640px) {
#videoList {
grid-template-columns: 1fr;
gap: 1rem;
}
.container {
padding: 0.75rem;
}
}
footer {
border-top: 0.0625rem solid rgba(255, 255, 255, 0.1);
margin-top: 4rem;
padding-top: 2rem;
}
footer a {
text-decoration: none;
}
footer a:hover {
text-decoration: underline;
}
/* Disclaimer Modal Styles */
#disclaimerModal {
position: fixed;
inset: 0;
background-color: rgb(0 0 0 / 0.9);
z-index: var(--z-modal-root);
/* remove display: none; */
display: flex;
flex-direction: column;
overflow-y: auto;
overscroll-behavior: contain;
}
#disclaimerModal > .absolute {
z-index: var(--z-modal-overlay);
}
#disclaimerModal .modal-container,
#disclaimerModal .modal-content {
z-index: var(--z-modal-content);
}
#disclaimerModal.hidden {
display: none !important;
}
#disclaimerModal .modal-content {
width: min(60rem, calc(100% - 2rem));
max-height: min(90vh, 51.25rem);
display: flex;
flex-direction: column;
background-color: var(--color-bg);
box-shadow: 0 1.5625rem 3.125rem -0.75rem rgb(0 0 0 / 0.45);
}
#disclaimerModal .modal-header {
min-height: 1.5rem;
}
#disclaimerModal .modal-body {
padding: 1.5rem;
flex: 1;
overflow-y: auto;
}
#disclaimerModal .modal-footer {
padding: 1.25rem 1.5rem 1.75rem;
background-color: #1a2234;
border-top: 0.0625rem solid rgba(255, 255, 255, 0.1);
}
/* Responsive Adjustments for Disclaimer Modal */
@media (min-width: 768px) {
#disclaimerModal {
padding: 2rem;
align-items: center;
justify-content: center;
}
#disclaimerModal .modal-body {
padding: 2rem 2.5rem 1.5rem;
max-height: calc(90vh - 5rem);
}
#disclaimerModal .modal-footer {
padding: 1.5rem 2.5rem 2rem;
}
}
/* Mobile-specific styles for Disclaimer Modal */
@media (max-width: 767px) {
#disclaimerModal {
padding: 0;
}
#disclaimerModal .modal-content {
min-height: 100vh;
border-radius: 0;
max-height: none;
width: 100%;
}
#disclaimerModal .modal-body {
padding: 1.5rem 1.5rem 1rem;
max-height: none;
}
#disclaimerModal .modal-footer {
padding: 1rem 1.5rem 2rem;
}
}
/* Override default button styles for back button */
.back-button {
background: rgba(15, 23, 42, 0.75) !important;
padding: 0 !important;
color: rgb(226 232 240) !important;
transform: none !important;
border: 0.0625rem solid rgba(148, 163, 184, 0.4) !important;
box-shadow: none;
}
.back-button:hover {
background: rgba(51, 65, 85, 0.95) !important;
color: white !important;
border-color: rgba(148, 163, 184, 0.55) !important;
}
/* Modal Container */
.modal-container {
padding: 0;
}
@media (min-width: 768px) {
.modal-container {
padding: 2rem;
}
}
/* Video info cards */
.player-modal__info .bg-gray-800\/50 {
background-color: rgb(31 41 55 / 0.5);
backdrop-filter: blur(0.25rem);
}
/* Circular Icon Buttons */
.icon-button {
display: inline-flex;
align-items: center;
justify-content: center;
width: 2.5rem; /* 40px */
height: 2.5rem; /* 40px */
line-height: 0;
background-color: #3f3f46; /* Gray 700 */
color: #fff;
border: none;
border-radius: 9999px;
cursor: pointer;
transition: background-color 0.2s, box-shadow 0.2s;
}
.icon-button:hover {
background-color: #52525b; /* Gray 600 */
}
.icon-button:focus,
.icon-button:active {
outline: none;
box-shadow: 0 0 0 0.1875rem rgba(220, 38, 38, 0.6);
}
.icon-image {
width: 1.25rem; /* 20px */
height: 1.25rem; /* 20px */
pointer-events: none;
}
/* Ratio 16:9 Container */
.ratio-16-9 {
position: relative;
width: 100%;
padding-top: 56.25%;
background-color: #1e293b;
}
.ratio-16-9 > img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
/* Sidebar default states */
#sidebarContainer {
position: relative;
overflow: visible;
}
#sidebar {
position: fixed;
top: 0;
left: 0;
width: var(--sidebar-width);
min-width: var(--sidebar-width);
height: 100vh;
height: 100dvh;
background-color: transparent;
color: var(--color-text);
overflow-x: visible;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
overscroll-behavior: contain;
scrollbar-gutter: stable both-edges;
transition: width 200ms ease, transform 0.3s ease, box-shadow 0.3s ease;
/* Keep below modal stacks so dialogs overlay the drawer. */
z-index: var(--z-sidebar);
box-shadow: none;
}
#sidebar .sidebar__inner {
display: flex;
flex-direction: column;
height: 100%;
padding: 1.5rem 1.25rem 1.75rem;
position: relative;
width: 100%;
/*
Allow the gradient panel shadow to breathe outside the rail while a nested
scroll container handles overflow.
*/
overflow: visible;
}
/*
The scroll wrapper keeps nav + footer together while leaving overflow
visible so the gradient card shadow is never clipped.
*/
.sidebar-scroll {
display: flex;
flex-direction: column;
gap: 1.5rem;
width: 100%;
height: 100%;
min-height: 0;
flex: 1 1 auto;
overflow: visible;
}
.sidebar-panel {
background: linear-gradient(
160deg,
rgba(30, 41, 59, 0.92) 0%,
rgba(15, 23, 42, 0.92) 100%
);
border: 1px solid rgba(148, 163, 184, 0.18);
border-radius: 1rem;
box-shadow: 0 1.25rem 2.5rem rgba(15, 23, 42, 0.35);
padding: 1.25rem 1rem;
width: 100%;
box-sizing: border-box;
display: flex;
flex-direction: column;
gap: 1.25rem;
}
.sidebar-panel--primary {
flex: 1 1 auto;
min-height: 0;
}
.sidebar-panel__header {
display: none;
justify-content: flex-end;
margin-bottom: 1rem;
}
.sidebar-collapse-toggle {
display: none;
align-items: center;
justify-content: center;
width: var(--sidebar-control-size);
height: var(--sidebar-control-size);
border-radius: 9999px;
border: 1px solid rgba(148, 163, 184, 0.2);
background: rgba(148, 163, 184, 0.08);
color: inherit;
cursor: pointer;
transition: background 180ms ease, color 180ms ease, border-color 180ms ease;
flex-shrink: 0;
box-sizing: border-box;
}
.sidebar-collapse-toggle:hover {
background: rgba(148, 163, 184, 0.18);
border-color: rgba(148, 163, 184, 0.35);
color: #f8fafc;
}
.sidebar-collapse-toggle:focus-visible {
outline: 0.125rem solid var(--color-secondary);
outline-offset: 0.25rem;
}
.sidebar-collapse-toggle__icon {
width: 1.125rem;
height: 1.125rem;
transition: transform 200ms ease;
}
.sidebar-nav {
display: flex;
flex-direction: column;
gap: 0.25rem;
opacity: 1;
transition: opacity 160ms ease;
width: 100%;
}
.sidebar-nav-link {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.625rem 0.875rem;
min-height: var(--sidebar-control-size);
border-radius: 0.875rem;
font-size: 0.95rem;
font-weight: 600;
color: rgba(226, 232, 240, 0.94);
text-decoration: none;
transition: background 160ms ease, color 160ms ease, transform 160ms ease;
width: 100%;
box-sizing: border-box;
}
.sidebar-nav-link:hover {
background: rgba(148, 163, 184, 0.18);
color: #f8fafc;
}
.sidebar-nav-link:focus-visible {
outline: 0.125rem solid var(--color-secondary);
outline-offset: 0.25rem;
}
.sidebar-nav-link--sub {
font-size: 0.85rem;
font-weight: 500;
color: rgba(226, 232, 240, 0.82);
padding-block: 0.55rem;
}
.sidebar-icon {
/* Lock icon sizing so the glyphs remain steady during collapse/expand. */
width: 1.5rem;
height: 1.5rem;
min-width: 1.5rem;
min-height: 1.5rem;
flex-shrink: 0;
display: block;
}
.sidebar-footer {
display: flex;
flex-direction: column;
gap: 0.75rem;
margin-top: auto;
position: relative;
z-index: 2;
}
.sidebar-dropup-trigger {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
width: 100%;
padding: 0.75rem 0.875rem;
min-height: var(--sidebar-control-size);
border-radius: 0.875rem;
border: 1px solid rgba(148, 163, 184, 0.18);
background: rgba(30, 41, 59, 0.85);
color: rgba(226, 232, 240, 0.9);
font-size: 0.9rem;
font-weight: 600;
cursor: pointer;
transition: background 160ms ease, border-color 160ms ease, color 160ms ease;
box-sizing: border-box;
flex-shrink: 0;
}
.sidebar-dropup-trigger:hover {
background: rgba(51, 65, 85, 0.95);
border-color: rgba(148, 163, 184, 0.32);
color: #f8fafc;
}
.sidebar-dropup-trigger:focus-visible {
outline: 0.125rem solid var(--color-secondary);
outline-offset: 0.25rem;
}
.sidebar-dropup-trigger__glyph {
width: 1.25rem;
height: 1.25rem;
opacity: 0.9;
}
.sidebar-dropup-trigger__chevron {
width: 1.125rem;
height: 1.125rem;
transition: transform 180ms ease;
}
.sidebar-dropup-trigger__chevron.is-rotated,
.sidebar-dropup-trigger[aria-expanded="true"] .sidebar-dropup-trigger__chevron {
transform: rotate(180deg);
}
.sidebar-dropup-panel {
background: rgba(15, 23, 42, 0.88);
border: 1px solid rgba(148, 163, 184, 0.18);
border-radius: 0.875rem;
box-shadow: 0 1.5rem 3rem rgba(15, 23, 42, 0.4);
padding: 0.75rem 0.5rem;
position: absolute;
left: 0;
right: 0;
bottom: calc(100% + 0.75rem);
opacity: 0;
visibility: hidden;
pointer-events: none;
transform: translateY(0.5rem);
transition: opacity 160ms ease, transform 160ms ease, visibility 160ms ease;
z-index: 5;
}
.sidebar-dropup-panel[data-state="expanded"] {
opacity: 1;
visibility: visible;
pointer-events: auto;
transform: translateY(0);
}
.sidebar-dropup-panel__inner {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
#sidebar[data-footer-state="expanded"] .sidebar-nav {
opacity: 0;
pointer-events: none;
}
#sidebar[data-footer-state="collapsed"] .sidebar-nav {
opacity: 1;
}
#sidebar.sidebar-open {
box-shadow: 0 0.75rem 1.5rem rgba(15, 23, 42, 0.45);
}
#sidebarOverlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(15, 23, 42, 0.55);
opacity: 0;
pointer-events: none;
transition: opacity 0.3s ease;
/* Sits above page chrome but below modals and the sidebar itself. */
z-index: var(--z-sidebar-overlay);
}
body.sidebar-open #sidebarOverlay {
opacity: 1;
pointer-events: auto;
}
/* Mobile (max-width: 767px): Hide sidebar by default */
@media (max-width: 767px) {
#sidebar {
transform: translate3d(-100%, 0, 0);
width: min(var(--sidebar-width-expanded), calc(100vw - 3rem));
}
/* When the sidebar-open class is added, slide the sidebar in */
#sidebar.sidebar-open {
transform: translate3d(0, 0, 0);
}
body.sidebar-open {
overflow: hidden;
}
}
/* Desktop (min-width: 768px): Always show the sidebar */
@media (min-width: 768px) {
.sidebar-panel__header {
display: flex;
}
.sidebar-collapse-toggle {
display: inline-flex;
}
#sidebar {
transform: translateX(0) !important;
width: var(--sidebar-width);
overflow: visible;
}
#sidebar.sidebar-open {
box-shadow: none;
}
#sidebarOverlay {
display: none;
}
#app {
box-sizing: border-box;
transition: margin-left 200ms ease, width 200ms ease, max-width 200ms ease;
}
#app[data-sidebar-state="collapsed"] {
margin-left: calc(var(--sidebar-width-collapsed) + var(--sidebar-content-gap));
width: calc(100vw - var(--sidebar-width-collapsed) - var(--sidebar-content-gap));
max-width: calc(100vw - var(--sidebar-width-collapsed) - var(--sidebar-content-gap));
}
#app[data-sidebar-state="expanded"] {
margin-left: calc(var(--sidebar-width-expanded) + var(--sidebar-content-gap));
width: calc(100vw - var(--sidebar-width-expanded) - var(--sidebar-content-gap));
max-width: calc(100vw - var(--sidebar-width-expanded) - var(--sidebar-content-gap));
}
body.sidebar-collapsed,
#sidebar.sidebar-collapsed {
--sidebar-width: var(--sidebar-width-collapsed);
}
body.sidebar-expanded,
#sidebar.sidebar-expanded {
--sidebar-width: var(--sidebar-width-expanded);
}
body.sidebar-collapsed #sidebar .sidebar-nav-link,
#sidebar.sidebar-collapsed .sidebar-nav-link {
/*
Keep icons centered in the collapsed rail without resizing them.
*/
justify-content: center;
width: var(--sidebar-control-size);
padding: 0;
margin-inline: auto;
border-radius: 9999px;
}
body.sidebar-expanded #sidebar .sidebar-nav-link,
#sidebar.sidebar-expanded .sidebar-nav-link {
justify-content: flex-start;
}
body.sidebar-collapsed #sidebar .sidebar-text,
#sidebar.sidebar-collapsed .sidebar-text {
display: none;
}
body.sidebar-collapsed #sidebar .sidebar__inner,
#sidebar.sidebar-collapsed .sidebar__inner {
/*
Keep enough breathing room for the panel shadow while widening the
interior track so var(--sidebar-control-size) controls stay perfectly
round.
*/
padding-inline: 0.25rem;
}
body.sidebar-collapsed #sidebar .sidebar-panel,
#sidebar.sidebar-collapsed .sidebar-panel {
/*
Mirror the outer adjustment so the gradient card retains its rounded
edges without squeezing the icon rail or clipping the control diameter.
*/
padding-inline: 0.375rem;
}
body.sidebar-collapsed #sidebar .sidebar-panel__header,
#sidebar.sidebar-collapsed .sidebar-panel__header {
justify-content: center;
}
body.sidebar-collapsed #sidebar .sidebar-collapse-toggle,
#sidebar.sidebar-collapsed .sidebar-collapse-toggle {
margin-inline: auto;
}
#sidebar .sidebar-toggle-icon--rotated {
transform: rotate(180deg);
}
body.sidebar-collapsed #sidebar .sidebar-toggle-icon--rotated,
#sidebar.sidebar-collapsed .sidebar-toggle-icon--rotated {
transform: rotate(0deg);
}
body.sidebar-collapsed #sidebar .sidebar-dropup-trigger {
/*
Align the "More" control with the centered icon rail while keeping its
padding consistent so the glyph does not scale between states.
*/
justify-content: center;
width: var(--sidebar-control-size);
height: var(--sidebar-control-size);
padding: 0;
margin-inline: auto;
border-radius: 9999px;
}
body.sidebar-collapsed #sidebar .sidebar-dropup-trigger .sidebar-text,
#sidebar.sidebar-collapsed .sidebar-dropup-trigger .sidebar-text {
display: none;
}
body.sidebar-collapsed #sidebar .sidebar-dropup-trigger__chevron {
display: none;
}
body.sidebar-collapsed #sidebar .sidebar-dropup-trigger__glyph,
#sidebar.sidebar-collapsed .sidebar-dropup-trigger__glyph {
margin: 0;
}
}
.edit-field-button {
align-items: center;
background-color: #1f2937;
border-radius: 0.5rem;
color: #e2e8f0;
display: inline-flex;
font-size: 0.75rem;
font-weight: 600;
justify-content: center;
padding: 0.5rem 0.85rem;
transition: background-color 0.2s ease, color 0.2s ease, transform 0.2s ease;
}
.edit-field-button:hover,
.edit-field-button:focus {
background-color: #334155;
color: #f8fafc;
transform: translateY(-0.0625rem);
}
.locked-input {
background-color: rgba(31, 41, 55, 0.75) !important;
border-color: rgba(55, 65, 81, 0.9) !important;
color: #94a3b8 !important;
cursor: default;
}
.locked-input:focus {
outline: none;
box-shadow: none;
}