/*
 * Styles for the Valorous Dashboard
 *
 * The design is inspired by Apple’s Liquid Glass aesthetic, a
 * translucent material that reflects and refracts its surroundings.
 * Cards, navigation and overlays use a semi‑transparent backdrop
 * combined with subtle borders and drop shadows to create depth.  A
 * colorful gradient background sets the stage for the glass panels
 * without distracting from the content.
 */

:root {
    /* After Dark palette inspired by iOS 26: deep blacks and ultraviolet hues */
    --bg-gradient-start: #020306;
    --bg-gradient-end: #310061;
    --accent-color: #a36be2;
    --text-color: #eae6f9;
    --glass-bg: rgba(30, 0, 50, 0.35);
    --glass-border: rgba(200, 150, 255, 0.25);
    --glass-shadow: rgba(0, 0, 0, 0.5);
    --transition-speed: 0.4s;
    /* Audio reactivity level.  Updated by JavaScript based on music amplitude. */
    --audio-level: 0;

    /* Low frequency amplitude for bass‑reactive glow walls.  This value is
       updated by the audio analyser in main.js.  It ranges from 0 to 1
       and should be used sparingly as it can spike quickly with bass hits. */
    --bass-level: 0;

    /* Define primary and secondary text colours for convenience.  Some
       components (e.g. location and user cards) reference these
       variables.  If not defined they fallback to inherit, leading to
       unintended colours. */
    --text-primary: var(--text-color);
    --text-secondary: rgba(234, 230, 249, 0.7);

    /* Base brightness of the background.  This variable is animated in
       effects.js to gently oscillate between darker and lighter values,
       giving the backdrop a living, ambient feel reminiscent of Windows 11.
       It combines with --audio-level in the filter below to react to
       music peaks without overpowering the subtle breathing motion. */
    --ambient-brightness: 0.8;
}

html, body {
    margin: 0;
    padding: 0;
    font-family: 'Inter', sans-serif;
    color: var(--text-color);
    height: 100%;
    overflow: hidden;
}

#background {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    /*
     * Composite Windows 11‑style backdrop consisting of several radial gradients
     * layered over a shifting linear gradient. The radial gradients create
     * soft ambient blobs reminiscent of the Task Manager/File Explorer
     * background, while the base gradient animates slowly to add life. The
     * background-position variables (--bg-parallax-x/y) nudge the entire
     * backdrop for subtle parallax without revealing edges.
     */
    background:
        radial-gradient(circle at 25% 25%, rgba(62, 81, 181, 0.45), transparent 70%),
        radial-gradient(circle at 75% 70%, rgba(122, 70, 210, 0.35), transparent 70%),
        radial-gradient(circle at 85% 15%, rgba(0, 122, 204, 0.25), transparent 70%),
        linear-gradient(135deg, var(--bg-gradient-start) 0%, var(--bg-gradient-end) 100%);
    /* Use a large background-size so the moving linear gradient has space to
       animate across the screen; radial layers default to cover */
    background-size: 400% 400%, 400% 400%, 400% 400%, 400% 400%;
    /* Parallax offsets applied via CSS variables set in effects.js */
    background-position: calc(50% + var(--bg-parallax-x, 0px)) calc(50% + var(--bg-parallax-y, 0px));
    animation: gradientShift 20s ease infinite;
    z-index: -2;

    /* React to audio by brightening/dimming the background as the music plays
       and combine with a slowly oscillating ambient brightness.  The
       --ambient-brightness variable is updated in effects.js via a
       requestAnimationFrame loop, creating a subtle breathing effect. */
    filter: brightness(calc(var(--ambient-brightness) + var(--audio-level) * 0.6));
}

/*
 * Glow walls: soft, blurred bands at the top and bottom of the page that
 * react to bass frequencies.  They are positioned behind the UI but above
 * the gradient background and are driven by the --bass-level variable.  A
 * stronger bass level increases the opacity of the glow, making it pulse
 * with the beat.  The blur radius and gradient create a diffused, neon
 * effect reminiscent of a glow spilling onto the glass panels.
 */
.glow-wall {
    position: fixed;
    left: 0;
    width: 100%;
    height: 22vh;
    pointer-events: none;
    z-index: -1;
    /* Use the accent colour for the glow but fade to transparent towards
       the centre.  The radial gradient produces a smooth falloff. */
    background: radial-gradient(ellipse at center, rgba(163, 107, 226, 0.7), rgba(163, 107, 226, 0.0) 70%);
    /* Blur softens the edges, making the glow appear as a diffused band */
    filter: blur(40px);
    /* The opacity is controlled by the bass level.  Clamp ensures it never
       exceeds 1; values beyond 0.5 create a strong glow during heavy bass. */
    opacity: calc(min(var(--bass-level) * 2, 1));
    transition: opacity 0.15s ease;
}

#top-glow {
    top: 0;
    transform: translateY(-40%);
}

#bottom-glow {
    /* Hide the bottom glow wall.  Only the top glow remains active. */
    display: none;
}

/*
 * Full-screen effects canvas used by the ambient particle system. It is fixed
 * positioned and sits just above the gradient background and below the rest
 * of the UI. Pointer events are disabled so it never intercepts clicks.
 */
#effects-canvas {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: -1;
    pointer-events: none;
}

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

.centered {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
}

.login-logo {
  display: block;
  margin: 0 auto 16px;   /* center + space below */
  max-width: 120px;      /* or whatever fits */
  height: auto;
  /* if you want a bit of a glow under audio reactivity, you could mirror the glass-card shadow: */
  /* box-shadow: 0 0 10px rgba(163, 107, 226, calc(var(--audio-level) * 0.6)); */
}

/* Remember me checkbox styling */
.remember-option {
    margin: 8px 0;
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
}
.remember-option label {
    cursor: pointer;
}

/* Verification screen styles */
#verify-screen .login-card {
    text-align: center;
}
#verify-screen input {
    margin-bottom: 12px;
}

/* 1. Frosted-glass overlay */
#frosted-overlay {
  position: fixed; top:0; left:0; width:100%; height:100%;
  pointer-events: none;
  /* blur everything behind this element */
  backdrop-filter: blur(20px) saturate(1.2);
  -webkit-backdrop-filter: blur(20px) saturate(1.2);
  background: rgba(255,255,255,0.03); /* subtle whitish tint */
  z-index: -1; /* sits above #background (−2) but below effects-canvas & UI */
  animation: frostedPulse 15s ease-in-out infinite;
}

@keyframes frostedPulse {
  0%,100% { backdrop-filter: blur(18px) saturate(1.1); }
  50%    { backdrop-filter: blur(24px) saturate(1.3); }
}

/* 2. Logo watermark (hidden until login) */
#logo-watermark {
  position: fixed; top:50%; left:50%;
  transform: translate(-50%,-50%);
  width: 80vmin; height: 80vmin;
  background: url('Valor_Varient2_Blank.png') no-repeat center/contain;
  opacity: 0; /* start invisible */
  filter: blur(2px);
  pointer-events: none;
  z-index: -1;
  transition: opacity 1s ease;
  animation: watermarkPulse 20s ease-in-out infinite;
}

#logo-watermark.visible {
  opacity: 0.04; /* very faint imprint */
}

@keyframes watermarkPulse {
  0%,100% { transform: translate(-50%,-50%) scale(1); }
  50%     { transform: translate(-50%,-50%) scale(1.02); }
}

/*
 * Hide an element completely from the layout.  Using only `visibility: hidden` and
 * `opacity: 0` leaves the element in the document flow, which can cause full‑screen
 * containers like the login panel to continue taking up space and push other
 * content offscreen.  Adding `display: none` collapses the element entirely.
 */
.hidden {
    display: none;
    visibility: hidden;
    opacity: 0;
    pointer-events: none;
}

/* Glass card base styling */
.glass-card {
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
    border-radius: 16px;
    padding: 20px;
    /* Base shadow plus an audio‑reactive neon glow.  The second shadow
       intensifies with the current audio level. */
    box-shadow: 0 4px 30px var(--glass-shadow), 0 0 20px 4px rgba(163, 107, 226, calc(var(--audio-level) * 0.8));
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    transition: var(--transition-speed), box-shadow var(--transition-speed), border var(--transition-speed);
}

.glass-card:hover {
    background: rgba(50, 0, 70, 0.45);
    box-shadow: 0 8px 40px var(--glass-shadow);
}

/* Login card specific styling */
.login-card {
    width: 360px;
    text-align: center;
}

.app-title {
    font-size: 2rem;
    margin-bottom: 10px;
}

.subtitle {
    margin-bottom: 20px;
    color: rgba(255, 255, 255, 0.8);
}

input[type="text"], input[type="password"], input[type="number"] {
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    padding: 12px 14px;
    margin-bottom: 14px;
    border: 1px solid var(--glass-border);
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-color);
    outline: none;
    font-size: 1rem;
    transition: border var(--transition-speed), background var(--transition-speed);
}

input[type="text"]:focus {
    border-color: var(--accent-color);
    background: rgba(255, 255, 255, 0.12);
}

/*
 * Base styling for all buttons across the site.  Buttons now follow the
 * frosted‑glass aesthetic rather than a solid accent colour.  They use a
 * semi‑transparent background combined with a subtle border and blur to
 * blend into the glass panels.  The accent colour still shines through
 * via opacity, providing continuity with the rest of the UI.  Hovering
 * slightly brightens the background and lifts the button.
 */
button {
    background: rgba(163, 107, 226, 0.25);
    color: var(--text-color);
    border: 1px solid var(--glass-border);
    padding: 10px 20px;
    border-radius: 12px;
    cursor: pointer;
    font-weight: 600;
    font-size: 1rem;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    box-shadow: 0 2px 8px var(--glass-shadow), 0 0 6px 1px rgba(163, 107, 226, calc(var(--audio-level) * 0.5));
    transition: background var(--transition-speed), transform var(--transition-speed), box-shadow var(--transition-speed);
    outline: none;
}

/* Smooth transitions for pages */
.page {
    /* Disable slide and fade transitions between pages.  Pages are either visible or hidden via the
       .hidden class. */
    opacity: 1;
    transform: none;
    transition: none;
}

/* Enhanced card animations */
.stat-card, .avatar-card {
    transition: transform var(--transition-speed) ease, background var(--transition-speed) ease, box-shadow var(--transition-speed) ease;
}
.stat-card:hover, .avatar-card:hover {
    transform: translateY(-4px) scale(1.02);
}

/* Modal fade in/out */
.modal {
    animation: fadeInModal var(--transition-speed) ease forwards;
}
@keyframes fadeInModal {
    from { opacity: 0; }
    to   { opacity: 1; }
}

button:hover {
    background: rgba(163, 107, 226, 0.35);
    transform: translateY(-2px);
    box-shadow: 0 4px 12px var(--glass-shadow), 0 0 8px 2px rgba(163, 107, 226, 0.7);
}

.error {
    margin-top: 8px;
    color: #ff7b7b;
    font-size: 0.9rem;
}

/* Success messages share the same font size as error messages but use
   the accent colour defined for small messages.  When a license or
   reset action succeeds, the corresponding element receives this
   class to indicate success. */
.success {
    margin-top: 8px;
    color: #8bd7bd;
    font-size: 0.9rem;
}

.nav-bar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 24px;
    margin: 16px;
}

.nav-title {
    font-size: 1.4rem;
    font-weight: 600;
}

.nav-links {
    list-style: none;
    display: flex;
    gap: 24px;
    margin: 0;
    padding: 0;
}

.nav-links li a {
    text-decoration: none;
    color: var(--text-color);
    font-weight: 500;
    position: relative;
    padding: 4px 0;
    transition: color var(--transition-speed);
}

.nav-links li a.active,
.nav-links li a:hover {
    color: var(--accent-color);
}

.nav-links li a.active::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: -6px;
    width: 100%;
    height: 2px;
    background: var(--accent-color);
    border-radius: 1px;
}

/* Hide admin nav item until authorised */
#nav-admin {
    display: none;
}

/* Hide admin-only nav items by default; JS will show them when authorised */
#nav-sessions {
    display: none;
}
#nav-licenses {
    display: none;
}

.logout-btn {
    margin-left: 16px;
}

/* Modal styles for avatar details */
.modal {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.6);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--transition-speed);
}
.modal:not(.hidden) {
    opacity: 1;
    pointer-events: auto;
}
.modal-content {
    max-width: 600px;
    max-height: 80vh;
    overflow-y: auto;
    position: relative;
}
.modal-close {
    position: absolute;
    top: 4px;
    right: 8px;
    background: transparent;
    border: none;
    color: var(--text-color);
    font-size: 1.5rem;
    cursor: pointer;
}

/* Fade-out animation for login screen */
.fade-out {
    animation: fadeOut 0.5s forwards;
}

@keyframes fadeOut {
    from { opacity: 1; }
    to { opacity: 0; }
}

.page {
    padding: 20px 40px;
    overflow-y: auto;
    height: calc(100vh - 80px);
}

.stats-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 24px;
}

.stat-card {
    flex: 1 1 300px;
}

ul {
    list-style: none;
    padding: 0;
    margin: 0;
}

li {
    margin-bottom: 8px;
}

.avatars-grid {
    display: grid;
    gap: 24px;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    margin-top: 16px;
}

.avatar-card {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    /* prepare for animation */
    opacity: 0;
    animation: fadeInUp 0.6s ease forwards;
}

.avatar-card img {
    width: 100%;
    height: 180px;
    object-fit: cover;
    border-top-left-radius: 16px;
    border-top-right-radius: 16px;
}

.avatar-info {
    padding: 12px 16px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.avatar-name {
    font-weight: 600;
    font-size: 1.1rem;
    color: var(--text-color);
}

.avatar-author {
    font-size: 0.9rem;
    color: rgba(255, 255, 255, 0.7);
}

.small-message {
    margin-top: 8px;
    font-size: 0.9rem;
    color: #8bd7bd;
}

.license-form {
    margin-bottom: 24px;
}

.search-bar {
    display: flex;
    gap: 12px;
    margin-bottom: 20px;
}

.pagination {
    display: flex;
    justify-content: center;
    gap: 8px;
    margin-top: 20px;
}

.pagination button {
    background: var(--glass-bg);
    color: var(--text-color);
    border: 1px solid var(--glass-border);
    backdrop-filter: blur(10px);
    padding: 6px 12px;
    border-radius: 8px;
    min-width: 40px;
}

.pagination button.active {
    /* Active pagination buttons adopt a stronger frosted accent tint rather than
       a fully opaque colour to stay consistent with other glass buttons. */
    background: rgba(163, 107, 226, 0.35);
    border-color: rgba(163, 107, 226, 0.45);
    color: var(--text-color);
}

@media (max-width: 640px) {
    .nav-links {
        display: none;
    }
    .nav-right {
        flex: 1;
        justify-content: flex-end;
        display: flex;
    }
    .nav-bar {
        flex-wrap: wrap;
        gap: 12px;
    }
    .page {
        padding: 20px;
    }
}

/* Keyframes for fading items up when they appear */
@keyframes fadeInUp {
    from {
        opacity: 0;
        transform: translateY(12px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Toast notification container */
#toast-container {
    position: fixed;
    bottom: 20px;
    right: 20px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    z-index: 10000;
}

/* Individual toast styling */
.toast {
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
    color: var(--text-color);
    padding: 12px 16px;
    border-radius: 12px;
    box-shadow: 0 4px 20px var(--glass-shadow);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    animation: toastFade 4s forwards;
    min-width: 220px;
    font-size: 0.9rem;
}

@keyframes toastFade {
    0% {
        opacity: 0;
        transform: translateY(10px);
    }
    10% {
        opacity: 1;
        transform: translateY(0);
    }
    90% {
        opacity: 1;
        transform: translateY(0);
    }
    100% {
        opacity: 0;
        transform: translateY(10px);
    }
}

/* ==========================================================================
   Live statistics update animation
   When a global statistic value changes the corresponding list item is given
   the ``stat-updated`` class.  This triggers a brief neon glow animation
   that draws the user's eye to the updated value without being overly
   distracting.
   ========================================================================== */
.stat-updated {
    animation: stat-update-glow 1.2s ease-in-out;
}

@keyframes stat-update-glow {
    0% {
        color: #00ffea;
        filter: brightness(1.1);
    }
    50% {
        color: #ffffff;
        filter: brightness(1.5);
    }
    100% {
        color: #00ffea;
        filter: brightness(1.1);
    }
}

/* ==========================================================================
   Page and modal transition animations
   These classes and keyframes create smooth fade/slide transitions when
   navigating between pages and opening modals.  The animations are
   inspired by the fluid iOS interface and provide a polished, modern feel.
   ========================================================================= */

/* Base transition for all pages */
.page {
    transition: opacity 0.4s ease, transform 0.4s ease;
}

/* Entering pages start from lower opacity and slight downward shift */
.page-enter {
    animation: pageEnter 0.4s ease forwards;
}

/* Leaving pages fade out and slide up */
.page-leave {
    animation: pageLeave 0.4s ease forwards;
}

@keyframes pageEnter {
    from {
        opacity: 0;
        transform: translateY(20px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes pageLeave {
    from {
        opacity: 1;
        transform: translateY(0);
    }
    to {
        opacity: 0;
        transform: translateY(-20px);
    }
}

/* Modal fade and scale effect */
.modal:not(.hidden) .modal-content {
    animation: modalFadeIn 0.4s ease forwards;
}

@keyframes modalFadeIn {
    from {
        opacity: 0;
        transform: scale(0.95);
    }
    to {
        opacity: 1;
        transform: scale(1);
    }
}

/* ==========================================================================
   Changelogs page styles

   The changelog page displays a list of update entries in a timeline.  Each
   entry is rendered as a glass card with a clickable header that toggles
   the visibility of its details.  Nested lists within the content are
   indented using additional margin and use alternate bullet styles to
   differentiate levels.  Headings and paragraphs inside the changelog
   content inherit the overall typography but adjust spacing for clarity.
   ========================================================================= */

/* Container for all changelog entries */
.changelogs-list {
    display: flex;
    flex-direction: column;
    gap: 16px;
    margin: 16px;
    overflow-y: auto;
    max-height: calc(100vh - 200px);
    /* Provide a subtle fade at the bottom to hint at scrollable content */
    mask-image: linear-gradient(to bottom, rgba(0,0,0,1) 90%, rgba(0,0,0,0));
}

/* Each changelog entry extends the glass card style.  We remove default
   padding because the header and content define their own spacing. */
.changelog-card {
    padding: 0;
    overflow: hidden;
    cursor: default;
    /* Animate cards in when the changelogs page is shown.  Each card
       starts slightly below and fully transparent, then slides up and
       fades into view.  The delay is controlled via the custom
       property --changelog-delay set in JavaScript for sequential
       staggering. */
    opacity: 0;
    transform: translateY(10px);
    animation: changelogCardEnter 0.5s ease forwards;
    animation-delay: var(--changelog-delay, 0s);
    /* Smooth hover effect; cards lift slightly and brighten when hovered. */
    transition: transform var(--transition-speed), background var(--transition-speed), box-shadow var(--transition-speed);
}

.changelog-card:hover {
    transform: translateY(-3px) scale(1.02);
    background: rgba(255, 255, 255, 0.02);
    box-shadow: 0 4px 16px var(--glass-shadow), 0 0 10px 2px rgba(163, 107, 226, 0.6);
}

/* Keyframes for changelog card entrance.  Mirrors the page transitions
   elsewhere on the site by fading and sliding from below. */
@keyframes changelogCardEnter {
    from {
        opacity: 0;
        transform: translateY(10px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Header of a changelog entry.  Displays the title and an arrow indicator.
   The arrow rotates when the card is open. */
.changelog-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 16px;
    user-select: none;
    cursor: pointer;
    border-bottom: 1px solid rgba(200, 150, 255, 0.25);
    transition: background var(--transition-speed), color var(--transition-speed);
    transition-property: background, color, transform;
}

.changelog-header:hover {
    background: rgba(255, 255, 255, 0.05);
}

.changelog-header:active {
    transform: scale(0.98);
}

.changelog-card:hover .changelog-header {
    background: rgba(255, 255, 255, 0.03);
}

.changelog-title {
    font-weight: 600;
    font-size: 1.05rem;
    flex: 1;
}

.changelog-arrow {
    margin-left: 12px;
    transition: transform 0.3s ease;
    font-size: 1rem;
}

.changelog-card.open .changelog-arrow {
    transform: rotate(90deg);
}

/* Content area for a changelog entry.  Hidden by default and revealed
   when the card has the open class.  The padding matches the header. */
.changelog-content {
    /* Content is hidden by default via max-height and opacity.
       It expands smoothly when the card gains the "open" class. */
    padding: 16px;
    line-height: 1.5;
    overflow: hidden;
    max-height: 0;
    opacity: 0;
    transition: max-height 0.4s ease, opacity 0.4s ease;
}

.changelog-card.open .changelog-content {
    opacity: 1;
    /* max-height is set dynamically via JavaScript when toggled */
}

/* Typography tweaks inside changelog content */
.changelog-content h3,
.changelog-content h4 {
    margin-top: 0;
    margin-bottom: 0.5rem;
    font-weight: 600;
}

.changelog-content p {
    margin: 0.5rem 0;
}

.changelog-content ul {
    margin: 0.5rem 0 0.5rem 1.25rem;
    padding: 0;
    list-style: disc;
}

/* Nested lists use alternate bullet styles to indicate depth */
.changelog-content ul ul {
    list-style: circle;
    margin-left: 1.25rem;
}

/* Card appearance animation for login and welcome screens */
.login-card {
    animation: cardFadeIn 0.6s ease forwards;
}

@keyframes cardFadeIn {
    from {
        opacity: 0;
        transform: translateY(20px) scale(0.95);
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

/* ==========================================================================
   Loading overlay and progress bar styles
   This overlay is displayed after a successful login/continue to visualise
   the application initialisation process.  It presents a glassy card
   containing the provided Loading.gif, a status message and a progress
   bar with animated fill.  The bar uses a moving gradient and glow to
   echo the existing ambient effects.
   ========================================================================== */

#loading-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2000;
    background: rgba(0, 0, 0, 0.6);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    opacity: 1;
    transition: opacity var(--transition-speed) ease;
}

#loading-overlay.hidden {
    display: none;
    opacity: 0;
    pointer-events: none;
}

.loading-container {
    width: 380px;
    padding: 30px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 18px;
}

.loading-gif {
    width: 120px;
    height: 120px;
    object-fit: contain;
}

.loading-text {
    font-size: 1.1rem;
    text-align: center;
    color: var(--text-color);
}

.progress-bar {
    width: 100%;
    height: 14px;
    background: rgba(255, 255, 255, 0.1);
    border: 1px solid var(--glass-border);
    border-radius: 10px;
    overflow: hidden;
    position: relative;
}

.progress-fill {
    height: 100%;
    width: 0%;
    background: linear-gradient(90deg, var(--accent-color), #6b3dd6, var(--accent-color));
    background-size: 200% 100%;
    animation: progressGlide 4s linear infinite;
    box-shadow: 0 0 12px 4px rgba(163, 107, 226, 0.6);
    transition: width 1s ease-in-out;
}

@keyframes progressGlide {
    0% { background-position: 0% 50%; }
    100% { background-position: 200% 50%; }
}

/* Fade-out animation for the loading overlay */
#loading-overlay.fade-out {
    animation: fadeOutOverlay 0.6s forwards;
}

@keyframes fadeOutOverlay {
    from { opacity: 1; }
    to   { opacity: 0; }
}

/* ==========================================================================
   Dashboard loader styles
   This small overlay appears on the dashboard while data is fetching.
   ========================================================================== */

.dashboard-loader {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 1500;
    padding: 24px;
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
    border-radius: 14px;
    box-shadow: 0 4px 20px var(--glass-shadow), 0 0 12px 4px rgba(163, 107, 226, 0.6);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    display: flex;
    align-items: center;
    justify-content: center;
}

.dashboard-loader.hidden {
    display: none;
}

.dashboard-loading-gif {
    width: 80px;
    height: 80px;
    object-fit: contain;
}

/* ==========================================================================
   Management page styles
   The management page displays active locations, license management tools,
   and a Discord user lookup.  These styles build on the glass aesthetic.
   ========================================================================== */

.management-sections {
    display: flex;
    flex-wrap: wrap;
    gap: 24px;
    margin-top: 20px;
}

.admin-section {
    flex: 1 1 420px;
    padding: 16px;
}

.locations-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    margin-top: 12px;
}

.location-card {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    border-radius: 12px;
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
    box-shadow: 0 2px 10px var(--glass-shadow), 0 0 8px 2px rgba(163, 107, 226, 0.4);
    cursor: pointer;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.location-card:hover {
    transform: translateY(-3px);
    box-shadow: 0 4px 14px var(--glass-shadow), 0 0 12px 3px rgba(163, 107, 226, 0.6);
}

.location-avatar {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    object-fit: cover;
}

.location-details {
    display: flex;
    flex-direction: column;
}

.location-username {
    font-weight: 600;
    font-size: 1rem;
    color: var(--text-primary);
}

.location-world-name {
    font-size: 0.9rem;
    color: var(--text-secondary);
}

.location-world-meta {
    font-size: 0.7rem;
    color: var(--text-secondary);
    line-height: 1.2;
}

.location-world-thumb {
    width: 60px;
    height: 60px;
    border-radius: 8px;
    object-fit: cover;
    margin-left: auto;
}

/* ==========================================================================
   Changelog management styles (admin)

   Forms and lists for creating, editing and deleting changelog entries in
   the management page.  Inputs and text areas follow the glass theme and
   align with the other management tools.  List items lay out the title and
   controls in a clean horizontal row.
   ========================================================================= */

.changelog-create-form input,
.changelog-create-form textarea {
    width: 100%;
    margin-bottom: 8px;
    border: 1px solid var(--glass-border);
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.05);
    color: var(--text-color);
    padding: 10px 12px;
    box-sizing: border-box;
    font-size: 0.9rem;
}

.changelog-create-form textarea {
    resize: vertical;
}

.changelog-create-form button {
    margin-top: 4px;
}

.changelog-admin-list {
    margin-top: 12px;
}

.changelog-admin-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 8px 0;
    border-bottom: 1px solid rgba(200, 150, 255, 0.15);
}

.changelog-admin-item .changelog-admin-title {
    flex: 1;
    font-weight: 500;
    font-size: 0.95rem;
}

.changelog-admin-item button {
    margin-left: 8px;
    font-size: 0.8rem;
    padding: 4px 8px;
}

.lookup-form {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
}

.lookup-form input {
    flex: 1 1 auto;
    padding: 8px 12px;
    border-radius: 8px;
    border: 1px solid var(--glass-border);
    background: var(--glass-bg);
    color: var(--text-primary);
    outline: none;
}

.lookup-form input::placeholder {
    color: var(--text-secondary);
}

.lookup-form button {
    padding: 8px 16px;
    border-radius: 8px;
    border: 1px solid var(--glass-border);
    background: rgba(163, 107, 226, 0.25);
    color: var(--text-color);
    cursor: pointer;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    transition: background var(--transition-speed), box-shadow var(--transition-speed);
}

.lookup-form button:hover {
    background: rgba(163, 107, 226, 0.35);
    box-shadow: 0 3px 10px var(--glass-shadow), 0 0 6px 1px rgba(163, 107, 226, 0.6);
}

.user-result {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.user-card {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 16px;
    border-radius: 12px;
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
    box-shadow: 0 2px 10px var(--glass-shadow), 0 0 8px 2px rgba(163, 107, 226, 0.4);
    max-width: 420px;
}

.user-card-header {
    display: flex;
    align-items: center;
    gap: 12px;
}

.user-avatar {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    object-fit: cover;
}

.user-basic-info {
    display: flex;
    flex-direction: column;
}

.user-name {
    font-size: 1.3rem;
    font-weight: 600;
    color: var(--text-primary);
}

.user-id {
    font-size: 0.9rem;
    color: var(--text-secondary);
}

.user-extra-info {
    padding: 12px;
    border-radius: 8px;
    background: rgba(255, 255, 255, 0.05);
    color: var(--text-secondary);
    font-size: 0.9rem;
    word-break: break-all;
}

/*
 * Action panel for admin user operations.  Appears below the user card in
 * the management lookup section and provides controls for modifying a
 * user's license or resetting their lockouts.  Inputs and buttons here
 * follow the glass aesthetic consistent with the rest of the UI.
 */
.user-actions {
    margin-top: 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-width: 420px;
}
.user-actions input {
    padding: 8px 12px;
    border-radius: 8px;
    border: 1px solid var(--glass-border);
    background: var(--glass-bg);
    color: var(--text-primary);
    outline: none;
    width: 100%;
    box-sizing: border-box;
}
.user-actions input::placeholder {
    color: var(--text-secondary);
}
.user-actions button {
    align-self: flex-start;
    padding: 6px 14px;
    font-size: 0.9rem;
}

/* License management and generic form styles */
.license-form {
    margin-bottom: 16px;
}

.license-form h4 {
    margin-bottom: 8px;
    font-size: 1rem;
    font-weight: 500;
    color: var(--text-primary);
}

.form-group {
    display: flex;
    flex-direction: column;
    margin-bottom: 8px;
}

.form-group input {
    padding: 8px 12px;
    border-radius: 8px;
    border: 1px solid var(--glass-border);
    background: var(--glass-bg);
    color: var(--text-primary);
    outline: none;
}

.form-group input::placeholder {
    color: var(--text-secondary);
}

.license-form button {
    padding: 8px 16px;
    border-radius: 8px;
    border: 1px solid var(--glass-border);
    background: rgba(163, 107, 226, 0.25);
    color: var(--text-color);
    cursor: pointer;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    transition: background var(--transition-speed), box-shadow var(--transition-speed);
}

.license-form button:hover {
    background: rgba(163, 107, 226, 0.35);
    box-shadow: 0 3px 10px var(--glass-shadow), 0 0 6px 1px rgba(163, 107, 226, 0.6);
}

/* ==========================================================================
   Media player styles
   A collapsible music player docked to the bottom of the screen.  It holds
   the current track artwork, title, artist and playback controls.  The
   player uses the glass aesthetic and slides into view when hovered or
   expanded via JavaScript.  When collapsed it hides most of its content
   leaving only a small tab visible.
   ========================================================================== */

.media-player {
    position: fixed;
    left: 0;
    bottom: 0;
    width: 100%;
    /* Height of full player: adjust as needed */
    height: 100px;
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
    border-top-left-radius: 16px;
    border-top-right-radius: 16px;
    box-shadow: 0 -4px 20px var(--glass-shadow), 0 0 12px 4px rgba(163, 107, 226, calc(var(--audio-level) * 0.8));
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    display: flex;
    flex-direction: column;
    transition: transform 0.3s ease;
    z-index: 500; /* above other overlay elements but below modals */
    pointer-events: auto;
}

/* When collapsed the player is mostly hidden off screen; only the tab is visible */
.media-player.collapsed {
    transform: translateY(calc(100% - 20px));
}

/* Tab/handle area that the user hovers over to reveal the player */
.media-tab {
    width: 100%;
    height: 20px;
    cursor: pointer;
    position: relative;
}
/* Draw a small horizontal bar on the tab to indicate handle */
.media-tab::before {
    content: '';
    position: absolute;
    top: 6px;
    left: 50%;
    transform: translateX(-50%);
    width: 60px;
    height: 4px;
    border-radius: 2px;
    background: rgba(255, 255, 255, 0.3);
}

.media-content {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 0 16px;
}

.media-thumbnail {
    width: 60px;
    height: 60px;
    border-radius: 12px;
    object-fit: cover;
    flex-shrink: 0;
}

.media-info {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 4px;
    overflow: hidden;
}

.media-title {
    font-size: 1rem;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.media-artist {
    font-size: 0.8rem;
    color: var(--text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.media-controls {
    display: flex;
    gap: 8px;
}

.media-btn {
    width: 44px;
    height: 36px;
    border-radius: 8px;
    border: 1px solid var(--glass-border);
    background: var(--glass-bg);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    color: var(--text-color);
    font-size: 1.1rem;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    box-shadow: 0 2px 8px var(--glass-shadow), 0 0 6px 1px rgba(163, 107, 226, calc(var(--audio-level) * 0.6));
    transition: background 0.2s ease, box-shadow 0.2s ease;
}

.media-btn:hover {
    background: rgba(50, 0, 70, 0.45);
    box-shadow: 0 4px 10px var(--glass-shadow), 0 0 8px 2px rgba(163, 107, 226, 0.8);
}

/* --------------------------------------------------------------------
   Conversion utilities styling
   -------------------------------------------------------------------- */
.conversion-flex {
    display: flex;
    flex-wrap: wrap;
    gap: 32px;
    margin-top: 16px;
}

.conversion-form {
    flex: 1 1 60%;
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding: 20px;
}

.conversion-status {
    flex: 1 1 40%;
    max-height: 600px;
    overflow-y: auto;
    padding: 20px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.form-group {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

/* Custom select styling for dropdowns */
.select-input {
    /* Unified styling for all dropdowns in the conversion UI.  The
       appearance properties remove default OS styling and allow full
       customisation. */
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    padding: 8px 12px;
    border-radius: 8px;
    border: 1px solid var(--glass-border);
    /* Use a dark frosted base similar to other glass elements */
    background: rgba(50, 0, 70, 0.45);
    backdrop-filter: blur(8px);
    color: var(--text-color);
    outline: none;
    font-size: 0.9rem;
    transition: background 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
    cursor: pointer;
}

.select-input:hover {
    /* Lighten the background slightly on hover */
    background: rgba(50, 0, 70, 0.55);
}

.select-input:focus {
    /* Highlight the border and add a subtle glow when focused */
    border-color: var(--accent-color);
    background: rgba(50, 0, 70, 0.55);
    box-shadow: 0 0 0 2px rgba(163, 107, 226, 0.4);
}

/* File upload styling */
.file-upload {
    display: flex;
    align-items: center;
    gap: 10px;
    position: relative;
}

.file-upload-label {
    padding: 10px 18px;
    border-radius: 8px;
    cursor: pointer;
    background: rgba(255, 255, 255, 0.15);
    border: 1px solid var(--glass-border);
    color: var(--text-color);
    transition: background 0.2s ease, border-color 0.2s ease;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 120px;
}

.file-upload-label:hover {
    background: rgba(255, 255, 255, 0.2);
    border-color: var(--accent-color);
}

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

.file-name {
    font-size: 0.85rem;
    color: var(--text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 200px;
}

/* Convert button */
.convert-btn {
    padding: 10px 20px;
    border-radius: 8px;
    border: none;
    font-size: 1rem;
    cursor: pointer;
    background: rgba(255, 255, 255, 0.1);
    color: var(--text-color);
    transition: background 0.2s ease;
}

.convert-btn:hover:not([disabled]) {
    background: rgba(255, 255, 255, 0.15);
}

.convert-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Status list */
.status-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    font-size: 0.9rem;
}

.status-item {
    padding: 6px 8px;
    border-radius: 6px;
    background: rgba(255, 255, 255, 0.05);
}

.status-link {
    color: var(--accent-color);
    text-decoration: underline;
    margin-left: 4px;
}