Add _device_serial() to read disk serials from /sys/class/block/{name}/device/serial and /sys/block/{name}/device/serial when lsblk cannot expose them in Docker containers. Update raid_status() to use sysfs fallback before defaulting to "—" for missing serials. Add .raid-disks 2-column grid with 6px gap, .raid-disk 7px/9px padding, .raid-disk small 1px top margin, and .raid-smart 85% opacity. Add mobile
Add format_transfer_rate() to convert mdstat rates (e.g., 133628K/sec) into readable values like "130.5 MB/s" using 1024-based units. Add format_remaining_time() to convert mdstat durations (e.g., 450.1min) into compact German format like "7 Std. 30 Min." with day/hour/minute components. Update raid_status() to parse member devices directly from array_line in /proc/mdstat to avoid cross
Add scan_datastore_storage() to walk DATASTORE_PATH and categorize media by directory structure (movies/series/anime/kdrama/downloads/other) with size/file counts. Add raid_status() to parse /proc/mdstat and mdadm --detail for RAID level, active/failed devices, and recovery progress. Add /api/datastore endpoint with 15-minute cache for storage scans and live RAID updates. Install mdadm/util-linux/
Add addMissingSections() function to inject "Filme ohne Deutsch"/"Movies without German" heading before #missingMovies table and "Serien ohne Deutsch"/"Series without German" before first .missing-series element. Style .missing-section-heading with 9px border-radius, uppercase 12px/800 text, 10px/13px padding, and glowing dot indicator. Apply blue gradient/border for .movies section
Replace single downloads table with two-section layout: "Aktive Downloads" for downloading items and "Weitere Queue-Einträge" for queued/paused items. Inject dual-table HTML structure with section headers showing item counts. Update renderDownloads() to distribute rows by status into activeDownloadsBody/otherDownloadsBody with fallback empty states. Add .download-table grid layout, .download-section styling
Add DOMContentLoaded script to dynamically inject shortcut icon link element with media-mark.svg if not already present. Update dashboard hero eyebrow text from "MEDIA CONTROL CENTER" to "MEDIA MAX" for consistent branding.
Update project name from "Radarr Language Dashboard v2" to "Media Max" in README.md, docker-compose.yml service/container names, app.py logger name and service definition, manifest.json name/short_name/description, and templates/index.html title and header elements. Update docker exec command example in README to use new container name.
Add .missing-table wrapper with 10px padding and style nested table with 100% width, 8px bottom margin, border, 10px border-radius, and overflow:hidden. Set thead th with 38px height, 12px horizontal padding, #2d3540 background, and right borders (except last-child). Set .missing-series summary min-height to 42px with flex center alignment. Add duplicate style block at end
Add syncDashboardMissingCounter() function to update #dashboardMissing with count of visible missing items (movies + non-hidden episodes excluding season-zero-hidden). Call on page load and after #showSeasonZero change with setTimeout(0) to reflect filtered totals in dashboard widget.
Add updateMissingHeading() function to toggle #missingMovies heading between 'Media'/'Medien' based on document.documentElement.lang. Call on page load and after #languageToggle click with setTimeout(0) to ensure DOM updates. Add .missing-table styles with table-layout:fixed and transform:none/animation:none on tbody tr to disable row animations and hover effects.
Add showSeasonZero checkbox in settings panel with toggle styling (42x23px switch, green when active). Implement applySeasonZeroPreference() to filter S00E episodes via .season-zero-hidden class and hide empty series with .season-zero-empty. Update missing count in nav badge and stats to exclude hidden season zero episodes. Add dynamic hint text toggle between "eingeblendet"/"ausgeblendet". Remove season zero exclusion from is_german_review_candidate() in app.py to
Add .view#radarr.active with 12px row-gap and style .toolbar with 0/10px padding, transparent background/border, and no shadow. Style toolbar inputs/selects with rgba(42,46,54,.82) background, #454d59 border, and #303640 focus state for improved visual integration.
Add .view#sonarr with 4px bottom padding and transparent #seriesList background. Style .series-category containers with 18px bottom margin, 13px border-radius, gradient backgrounds, and 10px/28px shadow. Add category headings with 13px/16px padding, bottom border, gradient background, and 3px left accent border. Style nested .series with 8px/10px margins, 9px border-radius, reduced shadows, and hover state
Set explicit 34px height on .view#radarr>.toolbar (margin-bottom:0) and .view#radarr>.stats (align-self:stretch, align-items:stretch) with .stat children using flexbox center alignment for consistent desktop row height. Restore auto height and initial alignment in mobile breakpoint to preserve responsive wrapping behavior.
Replace static #radarr grid with .view#radarr that displays:none by default and shows grid layout when .active class is applied. Update mobile breakpoint to use .view#radarr.active selector for responsive block layout, enabling dynamic tab switching without page reloads.
Rename CSS selector from #movies to #radarr in both desktop grid layout and mobile responsive breakpoint to align with service-specific naming convention used throughout the application.
Add #movies grid container with toolbar in column 1, stats in column 2 (nowrap, aligned center), and table spanning both columns. Collapse to single-column block layout on mobile (<760px) to maintain responsive behavior.
Decrease toolbar vertical padding from 10px to 1px, reduce border-radius from 10px to 8px, adjust box-shadow from 0 10px 28px to 0 8px 20px, and decrease gap from 9px to 8px. Set explicit input/select height to 30px with 5px/9px padding for consistent compact sizing.
Replace Simple Icons URLs with Iconify API endpoints for SABnzbd (mdi:download-box), Seerr (mdi:movie-search), Prowlarr (mdi:radar), Easynews (mdi:cloud-download), Bazarr (mdi:subtitles), and Lingarr (mdi:forum) while preserving original brand colors via color query parameters. Keep Simple Icons for Radarr, Sonarr, Jellyfin, qBittorrent, and LibreTranslate.
Add tag fetching from Sonarr API and category_for() function to classify series based on normalized tags (anime, kdrama, standard). Parse tag labels/names into normalized strings removing non-alphanumeric characters for matching. Add category and category_label fields to series groups.
Update index route to build series_categories list grouping series by category key (anime/Anime, kdrama/K-Dramen, standard/Standard) and pass
Add header-nav class to mainNav and move it before headerActions in header. Add dynamic stylesheet hiding .head-title/.head-sub, styling .header-nav with flex layout, 4px gap, 22px left margin, transparent background, and 8px/11px button padding. Add responsive breakpoints at 850px (scrollable nav with hidden scrollbar, max-width calc(100vw - 250px)) and 560px (icon-only buttons
Add SERVICE_DEFINITIONS list with Radarr, Sonarr, SABnzbd, Jellyfin, Seerr, Prowlarr, Easynews as Indexer, qBittorrent, Bazarr, Lingarr, LibreTranslate, Sonarr-Prowlarr Proxy, Radarr-Prowlarr Proxy, and Dashboard. Add check_service() to perform HTTP/API health checks with configurable timeout. Add refresh_services() to run checks in parallel using service_check_executor ThreadPoolExecutor with 16 workers.
Update media_row() to combine embedded subtitle_languages from ffprobe with external subtitle files detected via external_subtitle_languages(). Apply unique_langs() to deduplicate language codes when local_path is available, ensuring both .mkv internal subs and external .srt/.ass files appear in the subtitle language list.
Add download-nav-count specific styles with yellow background (#f4c430), darker text (#17191d), lighter border (#ffd95a), and glowing box-shadow for visual prominence matching dashboard disk icon color scheme.
Add download-nav-count span to downloads nav button with hidden class and downloadNavCount id. Update renderDownloads() to extract active_count from data, update badge text content, and toggle hidden class based on count. Add fetchDownloads() call on page load to populate initial badge state.
Add EXTERNAL_SUBTITLE_EXTENSIONS set with common subtitle formats (.srt, .ass, .ssa, .vtt, .sub, .idx, .sup). Add external_subtitle_files() to glob subtitle files matching media stem and external_subtitle_languages() to parse language codes from filenames (de/deu/ger/german/deutsch, en/eng/english, fr/fra/fre/french/französisch, es/spa/spanish/spanisch, it/ita/italian/italienisch).
Update run_ffprobe() to merge external subtitle
Add scan_executor ThreadPoolExecutor with 4 workers for parallel file scanning. Import as_completed from concurrent.futures to process scan results. Replace sequential scan_one() loop with parallel futures submission and result collection using as_completed().
Update /api/rescan endpoint to accept "all" source parameter for scanning both Radarr and Sonarr simultaneously. Fix cache deletion
Change disk-name from flex to grid layout with 2-column template (20px icon + flexible content). Update ::before icon to span both rows using grid-row:1/span 2 with zero margin. Add grid-template-rows auto/auto with conditional single row when disk-path is missing. Style disk-path in column 2 row 2 with nowrap and hide when empty. Set min-width:92px and line-height:1.1 for consistent sizing.
Add dashboard_stats dictionary to index() route calculating movie/episode totals, available files, missing items, and downloading counts. Pass stats to template for dashboard insights display.
Add dashboard-insights CSS grid with 4 insight cards showing media availability (movies/episodes), monitoring status, and live updates. Each card has color-coded icon with
Add manifest.json with app metadata, theme colors, and icon configuration for installable PWA. Add service worker (sw.js) with shell caching strategy for offline support - caches static assets on install, cleans old caches on activate, and implements network-first fetch with cache fallback for non-API requests.
Update index.html with PWA meta tags (theme-color, mobile
Remove duplicate display:flex declaration from .dashboard-view base class (already inherited from .view.active). Add .view.dashboard-view:not(.active) display:none rule to ensure dashboard view is properly hidden when inactive, preventing layout issues with flex-direction:column on non-active views.
Add ::before pseudo-elements with inline-grid centering to meter and disk-name elements. Style CPU meter with blue circular icon (◔), RAM meter with purple stacked icon (▤), and disk labels with yellow bar icon (▰). Each icon has matching semi-transparent background and colored text. Update dashboard view display to flex and align icon containers.
Add German comment explaining that Filme and Serien share the same host storage (/nesflix) and are made visible in the container via media mounts. Update mount_paths list to replace "Daten" label with "Medien" and combine Filme/Serien paths under single "Medien" label. Add dashboard-view CSS class with flex layout, min-height constraints, and increased disk-list gap for improved vertical
Add system_metrics() function to read CPU usage from /proc/stat with delta calculation, memory stats from /proc/meminfo, and disk usage for System/Daten/Filme/Serien mounts with device deduplication. Add /api/system endpoint returning metrics JSON with error handling.
Add dashboard view as default tab with hero section, 4-card overview grid showing movie/series/missing/download counts, system
Add is_german_review_candidate() helper function to filter media that exists locally or is currently being downloaded, excluding season 0 (specials) episodes. Apply filter to missing_german_movies and missing_german_series lists to show only actionable items. Update tab description text from "Kein deutsches Audio und keine deutschen Untertitel" to "Vorhanden oder wird gerade geladen · Staffel
Replace hardcoded color values with CSS custom properties (--bg, --panel, --line, --text, --muted, --yellow, --blue) defined in :root. Add color-scheme:dark for better dark mode support. Minify all CSS into single line to reduce file size. Maintain existing layout, spacing, and visual design while improving code organization and enabling easier theme customization.
Add parse_size_bytes() and format_bytes() helper functions to convert and format file sizes. Calculate total remaining bytes from queue and include active_count, history_count, remaining_bytes, and formatted remaining in downloads API response. Update error responses to include new fields.
Add media-mark.svg favicon with gradient background, golden lines, and green checkmark. Replace text logo with inline
Add new navigation tab showing count of movies and episodes without German tracks. Implement has_german_track() helper to check for German audio or subtitles. Filter movies and series to create missing_german_movies and missing_german_series lists passed to template. Add dedicated view section with tables for movies and series lacking German content, including empty state message. Update navigation translation logic
Add audio-preferred CSS class with blue background, border, and shadow to visually distinguish items matching user's preferred audio language. Implement highlightPreferences() function to scan audio badges in movies and series tables and apply styling when content matches stored preference. Call highlightPreferences() on page load and after saving preferences.
Add German/English language switching with DE/EN toggle button in header. Add settings modal with gear icon button for configuring preferred audio and subtitle languages. Store language and filter preferences in localStorage and auto-apply on page load. Add data-de/data-en attributes to translatable elements and translate table headers, filter placeholders, and navigation labels. Include modal backdrop with
Remove duplicate header z-index:100 declaration and consolidate all z-index and positioning overrides into single style block. Maintain sticky positioning hierarchy with header at z-index:100, series summaries at z-index:30 (top:64px), and season dividers at z-index:29 (top:110px).
Set background-attachment:fixed on body gradient to prevent it from scrolling with content. Add min-height:100vh to body and min-height:100% to html to ensure gradient covers full viewport. Add min-height:calc(100vh - 64px) to main to maintain full-height layout accounting for header.
Update series summary sticky top position from 0 to 64px and add z-index:30 to prevent overlap with fixed header. Update season divider sticky top position to 110px with z-index:29 to stack below series summaries but above content.
Add radial gradient background with accent colors, refined header with backdrop blur and shadow, improved navigation with active state indicator line, enhanced toolbar with focus states and transitions, refined table styling with gradient headers and hover animations, and add rescan button hover lift effect. Include responsive breakpoints for mobile layout adjustments.
Add smooth expand animation with cubic-bezier easing when opening series details. Add rotating chevron indicator (⌄) to series summary that changes color and rotates 180° when expanded. Animation includes fade-in, translateY, and scaleY transform from top center origin.
Set overflow:visible on #seriesList and .series elements to prevent sticky positioning from being clipped. This ensures series summaries remain visible at the top when scrolling through long episode lists.
Add CSS animations for row entries, download pulse effects, and progress bar shimmer. Implement sticky positioning for series summaries and season dividers with backdrop blur effects. Add hover transitions for navigation buttons and badges. Include intersection observer to highlight currently scrolled series with visual indicator. Add prefers-reduced-motion media query for accessibility.
Add visual separators between seasons in series episode tables. Extract season number from episode data and insert divider rows with "Staffel N" labels when season changes. Style dividers with dark background and subtle borders to improve readability of long episode lists.