diff --git a/AGENTS.md b/AGENTS.md index eb37412..e07e1d8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -34,6 +34,9 @@ The Nginx configurations on the web server can be found at `/etc/nginx/nginx.con ## AI Workflow +### Theme Work +Blackprint is the built-in default implemented by `/style.css`, `/template.html`, and `/template_mobile.html`; Classic is the retained packaged theme under `/themes`. Before creating or reworking themes, read `/themes/AGENTS.md` and treat the current five-section cascade in `/style.css` as the canonical component, responsive, accessibility, and cross-theme contract. + ### Updating the Wiki Whenever you make a change, you should always check if the change is worth mentioning in the wiki by looking through the pages and checking whether or not the topic of your change is mentioned. diff --git a/api/settings/index.php b/api/settings/index.php index b0b7568..ad821e4 100644 --- a/api/settings/index.php +++ b/api/settings/index.php @@ -243,7 +243,6 @@ function is_truthy_setting($value) { $colorFields = ['bg', 'fg', 'border', 'subtle', 'links']; $themeColorFields = [ 'classic' => $colorFields, - 'ambercrt' => ['links'], ]; $errors = []; diff --git a/js/settings.js b/js/settings.js index 6c3a0fe..f46319f 100644 --- a/js/settings.js +++ b/js/settings.js @@ -11,7 +11,6 @@ const COLOR_PREFS_KEY = 'colorPrefs'; const COLOR_FIELDS = ['bg', 'fg', 'border', 'subtle', 'links']; const THEME_COLOR_FIELDS = { classic: COLOR_FIELDS, - ambercrt: ['links'], }; const COLOR_DEFAULTS = { bg: '#000000', @@ -22,9 +21,6 @@ const COLOR_DEFAULTS = { }; const THEME_COLOR_DEFAULTS = { classic: COLOR_DEFAULTS, - ambercrt: { - links: '#FFB84D', - }, }; const MOBILE_VIEW_COOKIE = 'mobile_friendly_view'; const MOBILE_VIEW_DOMAIN = '.fridge.dev'; @@ -455,10 +451,7 @@ function normalizeTheme(theme) { const normalized = theme.trim().toLowerCase(); if (normalized === '' || normalized === 'default') return 'default'; if (normalized === 'blackprint') return 'default'; - if (normalized === 'crt') return 'ambercrt'; - if (normalized === 'liminal') return 'default'; if (normalized === 'custom') return 'classic'; - if (normalized === 'newsprint') return 'whiteprint'; if (/^[a-z0-9_-]+$/.test(normalized)) return normalized; return 'default'; } @@ -1531,16 +1524,14 @@ function initSettingsPage() { colorSection.style.display = fields.length ? '' : 'none'; const heading = colorSection.querySelector('h3'); if (heading) { - heading.textContent = normalizedTheme === 'ambercrt' ? 'CRT phosphor' : 'color scheme'; + heading.textContent = 'color scheme'; } const allowed = new Set(fields); colorInputs.forEach(inp => { const row = inp.closest('.color-row'); if (row) row.style.display = allowed.has(inp.dataset.colorKey) ? '' : 'none'; const label = row ? row.querySelector('span') : null; - if (label && normalizedTheme === 'ambercrt' && inp.dataset.colorKey === 'links') { - label.textContent = 'main'; - } else if (label && inp.dataset.colorKey === 'links') { + if (label && inp.dataset.colorKey === 'links') { label.textContent = 'links'; } }); @@ -2059,6 +2050,9 @@ function initSettingsPage() { saveLocalThemePref(currentTheme); setThemeCookie(currentTheme); applyThemeSelection(currentTheme); + if (currentTheme === 'classic') { + resetColorsToDefault(); + } }); } diff --git a/lib/render.php b/lib/render.php index bda5811..fcc5384 100644 --- a/lib/render.php +++ b/lib/render.php @@ -263,21 +263,9 @@ function fridg3_normalize_theme_id($theme) { if ($theme === 'blackprint') { return 'default'; } - if ($theme === 'crt') { - return 'ambercrt'; - } - if ($theme === 'liminal') { - return 'default'; - } - if ($theme === 'syswave') { - return 'default'; - } if ($theme === 'custom') { return 'classic'; } - if ($theme === 'newsprint') { - return 'whiteprint'; - } if (preg_match('/^[a-z0-9_-]+$/', $theme)) { return $theme; } @@ -343,6 +331,10 @@ function fridg3_list_themes($startDir) { $name = trim((string)($meta['name'] ?? '')); $description = trim((string)($meta['description'] ?? '')); + $base = strtolower(trim((string)($meta['base'] ?? ''))); + if ($base !== '' && $base !== 'blackprint') { + continue; + } $html = fridg3_normalize_theme_asset_path($meta['html'] ?? ''); $css = fridg3_normalize_theme_asset_path($meta['css'] ?? ''); $thumbnail = fridg3_normalize_theme_asset_path($meta['thumbnail'] ?? ''); @@ -373,6 +365,7 @@ function fridg3_list_themes($startDir) { 'id' => $id, 'name' => $name, 'description' => $description, + 'base' => $base, 'thumbnail' => $thumbnail, 'html' => $html, 'css' => $css, @@ -385,6 +378,8 @@ function fridg3_list_themes($startDir) { } uasort($themes, function($a, $b) { + // Blackprint is prepended by the themes API; packaged themes follow + // it with Whiteprint and Classic pinned ahead of future themes. $priority = ['whiteprint' => 0, 'classic' => 1]; $aPriority = $priority[$a['id']] ?? 10; $bPriority = $priority[$b['id']] ?? 10; @@ -736,6 +731,11 @@ function apply_preferred_theme_stylesheet($template, $startDir) { ); } + $template = fridg3_apply_body_theme_class($template, $theme['id'] . '-theme'); + if (($theme['base'] ?? '') === 'blackprint') { + $template = fridg3_apply_body_theme_class($template, 'blackprint-theme'); + } + $href = htmlspecialchars($theme['cssHref'], ENT_QUOTES, 'UTF-8'); if (strpos($template, 'href="' . $href . '"') !== false || strpos($template, "href='" . $href . "'") !== false) { return fridg3_replace_logged_in_discord_footer_button( diff --git a/main.js b/main.js index fd3a62a..50aba58 100644 --- a/main.js +++ b/main.js @@ -3372,7 +3372,6 @@ function setupSpaForms() { document.querySelectorAll('form').forEach(form => { if (form.dataset.searchWaitBound === '1') return; const isSearchForm = form.id === 'search' - || form.id === 'littlehelps-search' || form.getAttribute('role') === 'search' || !!form.querySelector('input[type="search"], input[name="q"]'); if (!isSearchForm) return; diff --git a/style.css b/style.css index 1c95955..8db5df7 100644 --- a/style.css +++ b/style.css @@ -517,6 +517,8 @@ body { display: flex; flex-direction: column; overflow-y: auto; /* allow sidebar content to scroll if taller than viewport */ + user-select: none; + -webkit-user-select: none; opacity: 1; transform: translateX(0); transition: @@ -529,6 +531,11 @@ body { box-shadow 0.16s ease; } +#sidebar img, +#sidebar a { + -webkit-user-drag: none; +} + body.sidebar-is-hidden #sidebar { width: 0 !important; min-width: 0 !important; @@ -6295,33 +6302,6 @@ html.access-high-contrast body { color: var(--fg) !important; } -html.access-high-contrast body.whiteprint-theme, -html.access-high-contrast body.bubblegum-theme, -html.access-high-contrast body.cottagecore-theme, -html.access-high-contrast body.littlehelps-theme { - --bg: #ffffff !important; - --fg: #000000 !important; - --border: #000000 !important; - --subtle: #333333 !important; - --links: #003cff !important; - color: var(--fg) !important; -} - -html.access-high-contrast body.whiteprint-theme, -html.access-high-contrast body.bubblegum-theme, -html.access-high-contrast body.cottagecore-theme, -html.access-high-contrast body.littlehelps-theme, -html.access-high-contrast body.whiteprint-theme #sidebar, -html.access-high-contrast body.bubblegum-theme #sidebar, -html.access-high-contrast body.cottagecore-theme #sidebar, -html.access-high-contrast body.littlehelps-theme #sidebar, -html.access-high-contrast body.whiteprint-theme #content-layout, -html.access-high-contrast body.bubblegum-theme #content-layout, -html.access-high-contrast body.cottagecore-theme #content-layout, -html.access-high-contrast body.littlehelps-theme #content-layout { - background: #ffffff !important; -} - html.access-high-contrast a, html.access-high-contrast button, html.access-high-contrast input, @@ -8208,6 +8188,7 @@ pre code.hljs { .theme-picker-description, .theme-picker-option-description { + font-family: "MainRegular", var(--emoji-font), monospace; font-size: 12px; line-height: 1.25; color: var(--subtle); diff --git a/template.html b/template.html index 83ab936..3637113 100644 --- a/template.html +++ b/template.html @@ -9,7 +9,7 @@ - + diff --git a/template_mobile.html b/template_mobile.html index 4cdfa63..57a3cfb 100644 --- a/template_mobile.html +++ b/template_mobile.html @@ -9,7 +9,7 @@ - + diff --git a/themes/AGENTS.md b/themes/AGENTS.md index 2e2f3e6..8252c73 100644 --- a/themes/AGENTS.md +++ b/themes/AGENTS.md @@ -1,288 +1,191 @@ -# Theme Creation Instructions +# Theme Development Instructions -this directory contains selectable website themes for fridge.dev. +This directory contains selectable themes for fridge.dev. Blackprint is the built-in default and is implemented by `/template.html`, `/template_mobile.html`, and the Blackprint layer near the end of `/style.css`. It is not a JSON theme package. Classic is the retained selectable reference theme in `/themes/classic.json` and `/themes/lib/classic/`. -if a user says something like "using this AGENTS.md, create an x based theme", you should be able to make the whole theme from this file plus the existing examples. do the work directly unless the request is dangerously unclear. +Treat `/style.css` as the source of truth. Read it before creating or substantially changing a theme. It contains the complete shared component system, accessibility behavior, responsive rules, Blackprint implementation, and final cross-theme invariants. Do not copy deleted themes or assume an older selector inventory is still accurate. -## Mental Model +## Theme Package Contract -a theme has two parts: +A selectable theme has: -- metadata json in `/themes` -- assets in `/themes/lib` +- `/themes/{theme-id}.json` +- `/themes/lib/{theme-id}/{template}.html` +- `/themes/lib/{theme-id}/{stylesheet}.css` +- `/themes/thumbnails/{theme-id}.svg` (normally a 4:3 preview) -the metadata file is what makes the theme appear in `/settings`. the filename, minus `.json`, becomes the saved theme id. +Theme IDs use lowercase `a-z`, `0-9`, `_`, and `-`. The JSON filename without `.json` is the saved theme ID. -example: +Required metadata: ```json { - "name": "Frutiger Aero", - "html": "frutiger-aero-template.html", - "css": "frutiger-aero.css" + "name": "Theme Name", + "description": "short picker description", + "thumbnail": "thumbnails/theme-id.svg", + "html": "theme-id/theme-id.html", + "css": "theme-id/theme-id.css" } ``` -this means: +An optional `"base": "blackprint"` field makes the renderer add both the package's `{theme-id}-theme` body class and `blackprint-theme`. Use it for a deliberate Blackprint derivative so the package inherits the current Blackprint layout and component coverage instead of copying that layer. `blackprint` is currently the only supported base value. -- settings label: `Frutiger Aero` -- saved id: `example_theme` if the file is `/themes/example_theme.json` -- desktop template: `/themes/lib/frutiger-aero/frutiger-aero-template.html` -- theme stylesheet: `/themes/lib/frutiger-aero/frutiger-aero.css` +`thumbnail` is relative to `/themes`; `html` and `css` are relative to `/themes/lib`. Asset paths may contain only letters, numbers, `.`, `_`, `-`, and `/`. Never use absolute paths, `..`, empty segments, query strings, or shell-like filenames. -## Files To Create +The renderer discovers valid JSON files dynamically. Blackprint is exposed as `default`; packaged themes receive a `{theme-id}-theme` body class. Missing, malformed, unsupported-base, or unsafe packages are ignored. Desktop may use the package HTML; mobile always uses `/template_mobile.html` and only appends the selected theme CSS. -for a new theme, create: +## Base Stylesheet Map -- `/themes/{theme-id}.json` -- `/themes/lib/{theme-id}/{theme-id-or-theme-name}.html` -- `/themes/lib/{theme-id}/{theme-id-or-theme-name}.css` +`/style.css` is intentionally ordered into five cascade sections: -keep ids lowercase with `a-z`, `0-9`, `_`, and `-`. avoid spaces in filenames. +1. Foundations: design variables, selection, loading UI, local fonts, emoji fallback, ASCII/resource typography, global text and element behavior. +2. Site shell: page wrapper, sidebar, title and title animations, navigation, content layout, notifications, mini-player, footer, sliders, and scrollbars. +3. Shared controls: checkboxes, settings panels, theme/title/Fruity Dance pickers, forms, popups, prompts, media corruption effects, tables, Markdown/BBCode surfaces, pagination, toolbars, and common responsive rules. +4. Page features: route-specific feed, journal, account, chat, gallery, upload, admin, notification, music, and tool interfaces. +5. Theme layers: the full Blackprint skin, Blackprint mobile coverage, application-specific cleanup, and final rules that intentionally apply across every theme. -## Required JSON Rules +Rules remain in cascade order because later responsive, theme, and coverage rules intentionally override earlier component defaults. A theme stylesheet is appended after the shared stylesheet, but inline mobile rules can still require scoped `!important` overrides. -theme json must be valid JSON and must include: +## Design Variables -- `name`: human-readable label shown in `/settings` -- `description`: short supporting text shown in the on-site theme picker -- `thumbnail`: 4:3 preview image path relative to `/themes`, usually `thumbnails/{theme-id}.svg` -- `html`: relative path inside `/themes/lib` -- `css`: relative path inside `/themes/lib` +Set the core variables at the start of a theme stylesheet: -do not put paths like `/themes/lib/foo.css` in the json. use paths relative to `/themes/lib`, such as `aero/aero.css`. -do not put paths like `/themes/thumbnails/foo.svg` in the json. use paths relative to `/themes`, such as `thumbnails/aero.svg`. +```css +:root { + --bg: #000000; + --fg: #eeeeee; + --border: #3c7895; + --subtle: #917daa; + --links: #415fad; + --chat-own-fg: #ffffff; +} +``` -allowed asset path characters are letters, numbers, `.`, `_`, `-`, and `/`. never use `..`, absolute paths, empty path segments, or weird shell-ish filenames. +The shared stylesheet also derives or consumes: -## Template Requirements +- `--hero-ascii-muted` and `--hero-ascii-1` through `--hero-ascii-7` +- `--hero-ascii-opacity` +- `--resource-ascii`, `--resource-label`, `--time-ascii`, `--time-label` +- `--emoji-font` +- `--selection-bg`, `--selection-fg` +- `--scrollbar-track`, `--scrollbar-thumb`, `--scrollbar-thumb-hover`, `--scrollbar-thumb-border` +- `--chat-own-bg` in the shared chat layer -start from `/template.html` unless the user asks for a radical layout. copy it into `/themes/lib/{theme-id}`, then adapt it. +Prefer overriding variables over duplicating component rules. Add direct component overrides where the theme changes shape, spacing, typography, imagery, or layout. Classic alone currently exposes account-synced custom values for `bg`, `fg`, `border`, `subtle`, and `links`; adding color controls for another theme requires coordinated changes in `/js/settings.js` and `/api/settings/index.php`. -the template must preserve these placeholders: +Available shared fonts are `MainRegular`, `MainBold`, `MainItalic`, `MainBoldItalic`, `IBM_VGA`, `Title`, and the `var(--emoji-font)` fallback stack. Preserve the emoji fallback in custom font families. -- `{title}` -- `{description}` -- `{content}` -- `{user_greeting}` - -the template should preserve these scripts/styles unless there is a very good reason: - -- Font Awesome CDN link -- Highlight.js CDN CSS and JS -- `/main.js` -- favicon and manifest links +## Templates And Runtime Contracts -the template should include a stylesheet link to `/style.css`; the renderer appends the selected theme CSS later, so the theme CSS can override base styling. +Start desktop work from `/template.html` unless the requested design needs a different layout. Preserve: -## Layout Freedom +- `{title}`, `{description}`, `{content}`, and `{user_greeting}` +- the content mount IDs `#container`, `#content`, `#content-layout`, and `#content-main` +- sidebar/navigation access, including home, account, and settings +- title markup with `#title` and per-character `.title-letter` spans +- mini-player IDs and the persistent `#mini-player-audio` element +- sidebar/footer/notification hooks used by `/js/sidebar-player.js` +- Font Awesome, Highlight.js, favicon, manifest, `/style.css`, and shared script includes -themes are allowed to change the website layout. this is not just a color-skin system. +The site uses SPA content replacement while leaving the shell and audio element mounted. Do not duplicate IDs, replace the shared audio element during navigation, or remove runtime hooks without updating and verifying the JavaScript. -you may: +Themes may radically rearrange the desktop shell, but content and navigation must remain usable. Avoid adding padding directly to `#content-main` when a decorative wrapper or `#content-layout::before` can add breathing room without reducing the page's usable width. -- move the menu -- redesign the sidebar -- make the layout top-nav, bottom-nav, split-panel, dashboard-like, etc. -- add decorative wrappers or background elements -- change spacing, borders, visual density, typography, and component shape +## Components To Cover -but you must keep: +At minimum, inspect the current declarations in `/style.css` for every component the theme visibly changes: -- a visible content display area containing `{content}` -- a usable menu/navigation of some sort -- account/settings/home navigation available somewhere -- the mini-player markup unless the theme intentionally restyles it -- IDs/classes that `main.js` depends on, unless you also verify and update the JS safely +- shell: `body`, `.paper-grain`, `#page-wrapper`, `#sidebar`, `#header`, `#title`, `.title-letter`, `#tab`, `#container`, `#content`, `#content-layout`, `#content-main` +- navigation/status: active tabs, sidebar notifications, active chat, maintenance/developer indicators, tooltips, notification toasts +- footer: `#sidebar-footer`, `#footer-text`, `#footer-buttons`, `#footer-button` +- player: `#mini-player`, `#mini-player-main`, art wrapper/image/download, metadata/title/artist, play/mute/close controls, seek/volume sliders, track list, `.mini-track` hover/active states, live-stream states +- forms: text inputs, textareas, selects/dropdowns, buttons, radios, checkboxes, color inputs, file controls, field help, disabled/error/success states +- pickers/popups: theme picker, title-animation picker, Fruity Dance controls, site popup/prompt/dialog surfaces +- content: headings, links, lists, blockquotes, code/pre, Markdown/BBCode, spoilers, tables, embedded media, pager controls, posts/cards +- route features: feed/journal editors and cards, accounts/settings/admin, chat and reply UI, gallery/upload, notifications, music albums, tools, logs, wiki/formatting pages +- ASCII/resource displays: homepage hero, server time/resources, labels, scaling containers -translation: go wild aesthetically, but do not strand users on a pretty page with no content or nav. that would be deeply goofy. +Use the stylesheet's actual selectors rather than inventing parallel markup. Search for a route or component name before adding overrides. -## Mobile Behavior +## Title And Motion -mobile view uses `/template_mobile.html`, not the theme HTML file. this is easy to forget and then the theme looks half-baked on `m.fridge.dev`, so treat mobile CSS as required theme work, not a nice extra. +The shared title uses clipped per-letter backgrounds and runtime-selectable wobble, bounce, rubberhose, bubble, slot-machine, moonwalk, and heartbeat animations. Mobile Safari requires gradients on the individual `.title-letter` elements. Keep transform-safe overflow and padding intact unless the replacement is verified with every animation. -when mobile-friendly view is active: +Do not override the shared title's `font-family` in packaged theme styles. Themes may change the title's colour, gradient, decoration, and surrounding panel, but `#title`, `.title-letter`, `.mobile-collapsed-title`, and its letters must retain the shared title typeface. Classic is the existing legacy exception because its original title treatment is part of that preserved theme. -- only the theme CSS is applied -- the theme HTML is ignored -- write mobile overrides under `body.mobile-template` +Respect both `@media (prefers-reduced-motion: reduce)` and `html.access-reduced-motion`. Theme animation is decorative and must be suppressible. The global reduced-motion rule forces animation and transition durations down to 1ms; do not defeat it with later theme rules. -this means every theme CSS must include mobile-specific polish if the theme changes core layout, backgrounds, nav buttons, content spacing, cards, forms, the mini-player, or footer controls. almost every real theme changes at least one of these, so most themes should have a substantial `body.mobile-template` section. +## Mobile Requirements -important: `/template_mobile.html` contains inline styles with strong defaults. these include black backgrounds for nav buttons, player/footer blocks, and `#content-main`. if you do not override these with `body.mobile-template ... !important`, light themes will get random black panels and dark themes may get default-looking controls. +Mobile uses `/template_mobile.html`, ignores theme HTML, and appends theme CSS. Scope mobile work under `body.mobile-template`. The template contains strong inline layout defaults, so targeted `!important` is sometimes necessary. -important mobile selectors that often need theme overrides: +Verify at least: -- `body.mobile-template` -- `body.mobile-template #sidebar` -- `body.mobile-template .mobile-collapsed-header` -- `body.mobile-template .mobile-collapsed-brand` -- `body.mobile-template .mobile-collapsed-subtitle` -- `body.mobile-template .mobile-collapsed-title` -- `body.mobile-template #show-sidebar` -- `body.mobile-template .mobile-nav-grid` -- `body.mobile-template .mobile-nav-grid a.mobile-nav-link > #tab.mobile-nav-button` -- `body.mobile-template .mobile-nav-grid a.mobile-nav-link > #tab.mobile-nav-button:hover` -- `body.mobile-template .mobile-nav-grid a.mobile-nav-link > #tab.mobile-nav-button.active` -- `body.mobile-template .mobile-nav-grid a.mobile-nav-link > #tab.mobile-nav-button.active:hover` -- `body.mobile-template #footer-buttons` -- `body.mobile-template #footer-buttons > a.mobile-footer-link > #footer-button.mobile-footer-button` -- `body.mobile-template #footer-buttons > a.mobile-footer-link > #footer-button.mobile-footer-button:hover` -- `body.mobile-template #footer-buttons > a.mobile-footer-link > #footer-button.mobile-footer-button.active` -- `body.mobile-template #footer-buttons > a.mobile-footer-link > #footer-button.mobile-footer-button.active:hover` -- `body.mobile-template #content` -- `body.mobile-template #content-layout` -- `body.mobile-template #content-main` -- `body.mobile-template #mini-player` -- `body.mobile-template #mini-player-tracks` -- `body.mobile-template #mini-player-art-wrapper` -- `body.mobile-template #mini-player-art` -- `body.mobile-template #mini-player-download` -- `body.mobile-template #mini-player-play` -- `body.mobile-template #mini-player-controls span` -- `body.mobile-template #mini-player-seek` -- `body.mobile-template #mini-player-volume` -- `body.mobile-template .mini-track` -- `body.mobile-template .mini-track:hover` -- `body.mobile-template .mini-track.active` -- `body.mobile-template #sidebar-footer` -- `body.mobile-template input` -- `body.mobile-template textarea` -- `body.mobile-template .dropdown` -- `body.mobile-template .text-input` -- `body.mobile-template .bbcode-dropdown` -- `body.mobile-template .bbcode-btn` +- page background, collapsed header, brand/title, menu button, unread badge, backdrop, and expanded menu panel +- `body.mobile-template #sidebar` preserves the shared safe gutter (`width: calc(100% - 16px)`), uses `min-width: 0`, `max-width: none`, border-box sizing, and never overflows the viewport +- nav and footer buttons in normal, hover, active, and active-hover states with explicit readable foregrounds +- content/layout/main backgrounds and spacing; light themes must replace default dark panels +- complete mini-player and track-list styling +- inputs, textareas, dropdowns, BBCode controls, radios, checkboxes, and color/file controls +- narrow content, long words, code blocks, tables, ASCII art, and media without horizontal page overflow -mobile CSS may need `!important` because `template_mobile.html` has inline mobile-specific styles. use it where necessary, not everywhere like a maniac. +Do not reintroduce a separate collapsed branded header: the current mobile template uses the fixed menu control and expanded sidebar title. Preserve the shared open/close transforms, backdrop behavior, document scroll locking, and reduced-motion overrides. -minimum mobile checklist for every theme: - -- theme the page background -- theme the collapsed header and menu button -- theme the expanded menu panel, and force `body.mobile-template #sidebar` back to `width: 100% !important; min-width: 0 !important; max-width: none !important;` so desktop sidebar widths do not make the opened mobile menu skinny -- theme mobile nav buttons, including hover, active, and active-hover states; every state must explicitly set readable text/icon colors -- theme footer buttons, including hover, active, and active-hover states; every state must explicitly set readable text/icon colors -- theme the mini-player, track list, album art, download overlay, play/mute controls, title text, sliders, track rows, hover states, and active track states -- theme `#content-layout` and `#content-main`; especially remove the mobile template's default black `#content-main` background when making a light theme -- theme inputs, dropdowns, textareas, BBCode controls, radios, checkboxes, and color inputs if the theme is light or uses non-default colors -- keep spacing tight enough for small screens without horizontal scrolling - -## CSS Strategy - -theme CSS is appended after the base stylesheet. normally do not `@import url('/style.css')` in theme CSS, because that can reload base styles after mobile styles and break mobile theming. - -set the core color variables early: +## Accessibility And Shared Invariants -```css -:root { - --bg: #000000; - --fg: #eeeeee; - --border: #3c7895; - --subtle: #917daa; - --links: #415fad; -} -``` +Themes must maintain readable contrast, distinct links, visible focus/hover/active states, usable target sizes, and unclipped content. Decorative backgrounds need opaque-enough content surfaces. -then override components directly. - -common components: - -- `body` -- `#page-wrapper` -- `#sidebar` -- `#header` -- `#title` -- `#tab` -- `#container` -- `#content` -- `#content-layout` -- `#content-main` -- `#post` -- `#search` -- `#search-box` -- `#search-button` -- `#footer-buttons` -- `#footer-button` -- `#mini-player` -- `#mini-player-tracks` -- `#mini-player-art-wrapper` -- `#mini-player-art` -- `#mini-player-download` -- `#mini-player-play` -- `#mini-player-controls span` -- `#mini-player-seek` -- `#mini-player-volume` -- `.mini-track`, `.mini-track:hover`, `.mini-track.active` -- form inputs, buttons, `.dropdown`, `.radio`, `.checkbox` - -when styling menus, do not only set the background on hover/active states. set the foreground color too. this includes `#tab:hover`, `#tab.active`, `#footer-button:hover`, `#footer-button.active`, mobile nav buttons, mobile footer buttons, and pseudo-elements like `#tab::before` if the theme uses them. invisible active menu text is a tiny little css jump scare and it is your job to prevent it. - -## Content Spacing - -be careful with padding on `#content-main`: it reduces usable width for page content. if the user asks for more breathing room without shrinking content, prefer outer margins, pseudo-elements, or background wrappers. - -good pattern: +The shared accessibility layer supplies high contrast through the core variables. If a future light theme needs a light high-contrast mode, add an explicit theme-scoped override rather than a generic name list. -```css -#content-layout { - position: relative; - isolation: isolate; -} +The final rules in `/style.css` are intentional cross-theme contracts: -#content-layout::before { - content: ""; - position: absolute; - inset: -20px; - z-index: -1; - pointer-events: none; -} -``` +- sidebar mini-player, track list, and footer remain shadow-free +- mini-player close controls retain their compact pinned geometry +- mobile title letters retain independent gradient painting and transform-safe spacing +- mobile Always Playing title setting stays hidden +- the mobile menu toggle remains square +- chat controls and quoted replies remain flat and readable +- the sidebar suppresses text selection and native image/link dragging while controls remain interactive -this makes the visual panel larger without stealing content width. +Do not casually override these rules in a theme. -## Accessibility And Usability +## CSS Practices -keep themes readable: - -- preserve strong text/background contrast -- make links visually distinct -- make focus/hover states visible -- keep buttons and controls large enough to click -- avoid hiding overflow in ways that cut off content -- check long words, ASCII art, forms, and post cards - -if a theme uses very decorative backgrounds, make content panels opaque enough to read. +- Do not `@import /style.css`; the renderer already loads it. +- Scope theme-specific rules to the theme body class added by the renderer. +- Set both foreground and background for hover/active states, including pseudo-elements. +- Reuse shared variables and component markup. +- Use `!important` only to beat known inline/mobile or final shared declarations. +- Keep asset URLs rooted under the theme package when practical. +- Avoid broad selectors that leak into editor previews, popups, or mobile unintentionally. +- Preserve reduced motion, high contrast, keyboard focus, and touch behavior. ## Validation -after creating or changing a theme: +After creating or changing a theme: -1. validate json: +1. Validate metadata: ```bash -php -r 'json_decode(file_get_contents("themes/{theme-id}.json"), true); echo json_last_error_msg(), "\n";' +php -r '$v=json_decode(file_get_contents("themes/{theme-id}.json"), true); echo json_last_error_msg(), "\n";' ``` -2. check the theme loader sees it: +2. Verify discovery: ```bash -php -r 'require "lib/render.php"; echo json_encode(array_values(array_map(fn($t)=>["id"=>$t["id"],"name"=>$t["name"]], fridg3_list_themes(__DIR__))), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES), "\n";' +php -r 'require "lib/render.php"; echo json_encode(array_values(array_map(fn($t) => ["id" => $t["id"], "name" => $t["name"]], fridg3_list_themes(__DIR__))), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES), "\n";' ``` -3. check whitespace: - -```bash -git diff --check -- themes/{theme-id}.json themes/lib/{theme-id}/{theme}.html themes/lib/{theme-id}/{theme}.css -``` - -4. if PHP render helper changed, run: +3. Lint and check whitespace: ```bash php -l lib/render.php +git diff --check -- themes/{theme-id}.json themes/lib/{theme-id} themes/thumbnails/{theme-id}.svg ``` -do not start a dev server for this repo. assume one is already running if preview is needed. +4. Test desktop and mobile, normal and reduced motion, keyboard focus, long content, forms, mini-player states, and the routes whose components the theme overrides. + +Do not start a development server; assume one is already running if preview is needed. ## Documentation -if you change how themes work, update the wiki. if you only add a normal theme, wiki changes usually are not needed. +Update `/wiki/Frontend-and-Templates.md`, `/wiki/Routing-and-Rendering.md`, `/wiki/Data-Contracts.md`, and `/wiki/API-Reference.md` when the package contract, renderer, settings behavior, color support, or shared theme architecture changes. A normal new theme usually needs only a concise catalog mention if its behavior is noteworthy. diff --git a/themes/aero.json b/themes/aero.json index 3e7eb9b..f11d018 100644 --- a/themes/aero.json +++ b/themes/aero.json @@ -1,7 +1,8 @@ { "name": "aero", - "description": "blackprint structure under polished blue Aero glass", + "description": "a bright Frutiger Aero world of glass, blue skies, and green hills", "thumbnail": "thumbnails/aero.svg", "html": "aero/aero.html", - "css": "aero/aero.css" + "css": "aero/aero.css", + "base": "blackprint" } diff --git a/themes/ambercrt.json b/themes/ambercrt.json deleted file mode 100644 index 1a8a4fc..0000000 --- a/themes/ambercrt.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "CRT", - "description": "dark scanline terminal with one adjustable phosphor colour", - "thumbnail": "thumbnails/crt.svg", - "html": "ambercrt/ambercrt.html", - "css": "ambercrt/ambercrt.css" -} diff --git a/themes/arcade.json b/themes/arcade.json deleted file mode 100644 index cf8ddf9..0000000 --- a/themes/arcade.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "arcade", - "description": "neon cabinet colours with teal, blue, violet, and magenta", - "thumbnail": "thumbnails/arcade.svg", - "html": "arcade/arcade.html", - "css": "arcade/arcade.css" -} diff --git a/themes/base16.json b/themes/base16.json new file mode 100644 index 0000000..6ebce2b --- /dev/null +++ b/themes/base16.json @@ -0,0 +1,8 @@ +{ + "name": "base16", + "description": "Base16 Default Dark with strictly flat, textureless components", + "thumbnail": "thumbnails/base16.svg", + "html": "whiteprint/whiteprint.html", + "css": "base16/base16.css", + "base": "blackprint" +} diff --git a/themes/bubblegum.json b/themes/bubblegum.json deleted file mode 100644 index 1830d20..0000000 --- a/themes/bubblegum.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "bubblegum", - "description": "soft pastel whiteprint with candy pink and mint accents", - "thumbnail": "thumbnails/bubblegum.svg", - "html": "bubblegum/bubblegum.html", - "css": "bubblegum/bubblegum.css" -} diff --git a/themes/catpuccin.json b/themes/catpuccin.json new file mode 100644 index 0000000..3f45a77 --- /dev/null +++ b/themes/catpuccin.json @@ -0,0 +1 @@ +{"name":"catpuccin","description":"soft Catppuccin-inspired lavender, mauve, and mocha","thumbnail":"thumbnails/catpuccin.svg","html":"whiteprint/whiteprint.html","css":"catpuccin/catpuccin.css","base":"blackprint"} diff --git a/themes/cottagecore.json b/themes/cottagecore.json deleted file mode 100644 index d17ea9b..0000000 --- a/themes/cottagecore.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "cottagecore", - "description": "warm garden paper, stitched controls, and rose tones", - "thumbnail": "thumbnails/cottagecore.svg", - "html": "cottagecore/cottagecore.html", - "css": "cottagecore/cottagecore.css" -} diff --git a/themes/gothic.json b/themes/gothic.json deleted file mode 100644 index 6f3fa98..0000000 --- a/themes/gothic.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "gothic", - "description": "dark stone panels, iron buttons, and antique gold glow", - "thumbnail": "thumbnails/gothic.svg", - "html": "gothic/gothic.html", - "css": "gothic/gothic.css" -} diff --git a/themes/lib/aero/aero.css b/themes/lib/aero/aero.css index 7c6e6aa..607fccc 100644 --- a/themes/lib/aero/aero.css +++ b/themes/lib/aero/aero.css @@ -1,524 +1,913 @@ @font-face { - font-family: "AeroTahoma"; - src: url("/themes/lib/aero/tahoma.ttf") format("truetype"); - font-weight: 400; + font-family: "Aero Tahoma"; + src: url('/themes/lib/aero/tahoma.ttf') format('truetype'); font-style: normal; + font-weight: normal; font-display: swap; } -:root { - --bg: #07141f; - --fg: #edfaff; - --border: #58c8e2; - --subtle: #9dccd8; - --links: #82f0d8; - --chat-own-fg: #052b35; - --hero-ascii-muted: #7faab7; - --hero-ascii-1: #776490; - --hero-ascii-2: #7c7ba3; - --hero-ascii-3: #7795b4; - --hero-ascii-4: #70adbf; - --hero-ascii-5: #69c7c5; - --hero-ascii-6: #73dfca; - --hero-ascii-7: #82f0d8; - --hero-ascii-opacity: 0.96; - --aero-glass: rgba(10, 30, 42, 0.66); - --aero-glass-strong: rgba(8, 24, 34, 0.82); - --aero-shine: rgba(237, 250, 255, 0.24); - --aero-blue: #58c8e2; - --aero-teal: #82f0d8; - --aero-purple: #776490; -} - -body { - background: - radial-gradient(ellipse at 22% 4%, rgba(150, 236, 255, 0.34), transparent 34%), - radial-gradient(ellipse at 86% 84%, rgba(130, 240, 216, 0.2), transparent 32%), - linear-gradient(135deg, rgba(119, 100, 144, 0.18), rgba(88, 200, 226, 0.1)), - linear-gradient(180deg, #081524 0%, #0b2f43 46%, #082b36 68%, #06151d 100%); - background-attachment: fixed; - color: var(--fg); - font-family: "AeroTahoma", Tahoma, "MainRegular", var(--emoji-font), sans-serif; +:root, +body.aero-theme { + --bg: #dff4ff; + --fg: #18354a; + --border: #4d91c7; + --subtle: #52758a; + --links: #0876be; + --chat-own-bg: #1688d0; + --chat-own-fg: #ffffff; + --hero-ascii-muted: #78afd2; + --hero-ascii-1: #126fc0; + --hero-ascii-2: #0789cf; + --hero-ascii-3: #00a8dc; + --hero-ascii-4: #29baba; + --hero-ascii-5: #58bd7c; + --hero-ascii-6: #78bd48; + --hero-ascii-7: #a3ce42; + --selection-bg: #168bd1; + --selection-fg: #ffffff; + --scrollbar-track: #d6effb; + --scrollbar-thumb: #65acd5; + --scrollbar-thumb-hover: #2c8dc8; + --scrollbar-thumb-border: #eefaff; +} + +body.aero-theme, +body.aero-theme :is( + #subtitle, + #tab, + #footer-text, + #footer-button, + #user-greeting, + #content-main, + #content-footer, + h1, h2, h3, h4, h5, h6, + p, li, label, summary, legend, + input, textarea, select, button, + .text-input, + .dropdown, + .bbcode-dropdown, + .bbcode-btn, + .grid-caption, + .grid-subcaption, + .mini-track, + .tooltip, + .site-notification-toast, + .site-popup-dialog +) { + font-family: "Aero Tahoma", Tahoma, Verdana, var(--emoji-font), sans-serif !important; +} + +body.aero-theme :is(#ascii, #ascii-time, .usage-ascii, .ascii-scale-inner) { + font-family: "IBM_VGA", var(--emoji-font), monospace !important; +} + +body.aero-theme :is(pre, code, pre *, code *) { + font-family: "MainRegular", var(--emoji-font), monospace !important; +} + +body.aero-theme, +body.aero-theme.mobile-template { + background: #78bde0 !important; + color: var(--fg) !important; + isolation: isolate; } -body::before { - content: ""; - position: fixed; - inset: 0; - z-index: -3; - pointer-events: none; - background: - linear-gradient(110deg, transparent 0 17%, rgba(255, 255, 255, 0.16) 17% 19%, transparent 19% 100%), - linear-gradient(152deg, transparent 0 68%, rgba(130, 240, 216, 0.12) 68% 70%, transparent 70% 100%), - repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.035) 0 1px, transparent 1px 28px); +body.aero-theme .paper-grain { + opacity: 1; + inset: -12px; + z-index: -1; + background: url('/themes/lib/aero/background.jpg') center / cover no-repeat fixed; + filter: blur(6px) saturate(1.08); + transform: scale(1.02); } -.aero-sky, -.aero-waterline { - position: fixed; - left: 0; - right: 0; - pointer-events: none; -} +body.aero-theme #page-wrapper, +body.aero-theme #container { background: transparent !important; } -.aero-sky { - top: 0; - height: 44vh; - z-index: -2; - background: - linear-gradient(180deg, rgba(186, 246, 255, 0.24), transparent 62%), - radial-gradient(ellipse at 42% 0%, rgba(255, 255, 255, 0.22), transparent 46%); +body.aero-theme #sidebar, +body.aero-theme.mobile-template #sidebar { + background: linear-gradient(180deg, rgba(238,250,255,.9), rgba(177,224,244,.82)) !important; + border: 1px solid rgba(255,255,255,.9) !important; + border-right-color: #438cb9 !important; + box-shadow: inset -1px 0 rgba(255,255,255,.65), 6px 0 20px rgba(17,74,112,.25) !important; + backdrop-filter: blur(14px) saturate(1.25); } -.aero-waterline { - bottom: 0; - height: 36vh; - z-index: -1; - background: - linear-gradient(180deg, transparent 0%, rgba(130, 240, 216, 0.16) 28%, rgba(10, 56, 58, 0.26) 100%), - repeating-radial-gradient(ellipse at 50% 100%, rgba(160, 255, 242, 0.16) 0 2px, transparent 3px 18px); - opacity: 0.88; +body.aero-theme #header { + margin: 10px !important; + padding: 13px 10px !important; + border: 1px solid #4c98c9 !important; + border-radius: 12px !important; + background: linear-gradient(180deg, rgba(255,255,255,.9), rgba(120,202,240,.58)) !important; + box-shadow: inset 0 1px #fff, 0 2px 5px rgba(30,91,126,.18) !important; } -#page-wrapper, -#container { - background: transparent; +body.aero-theme #title, +body.aero-theme #title .title-letter, +body.aero-theme .mobile-collapsed-title, +body.aero-theme .mobile-collapsed-title .title-letter { + background-image: linear-gradient(0deg, #0879c4, #21a6dc 44%, #74c546 48%, #1483cc 55%, #0879c4) !important; + filter: drop-shadow(0 1px rgba(255,255,255,.9)); } -#sidebar { - width: 282px; - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.18), transparent 22%), - linear-gradient(180deg, rgba(18, 68, 89, 0.7), rgba(4, 22, 31, 0.82)), - var(--aero-glass); - border-right: 1px solid rgba(163, 239, 255, 0.48); - box-shadow: - inset -1px 0 0 rgba(255, 255, 255, 0.18), - 12px 0 36px rgba(0, 8, 18, 0.34); - backdrop-filter: blur(18px) saturate(1.35); +body.aero-theme #sidebar > a { margin-left: 10px; margin-right: 10px; } + +body.aero-theme :is(#tab, #footer-button, .mobile-nav-button, .mobile-footer-button, #show-sidebar) { + background: linear-gradient(180deg, #ffffff 0%, #dff4fd 47%, #acd8ee 50%, #d9f1fb 100%) !important; + color: #174967 !important; + border: 1px solid #4a94c2 !important; + border-radius: 7px !important; + box-shadow: inset 0 1px #fff, 0 1px 2px rgba(24,77,108,.2) !important; + text-shadow: 0 1px #fff; } -#header { - position: relative; - margin: 12px; - padding: 14px 12px 16px; - text-align: center; - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.22), transparent 42%), - linear-gradient(135deg, rgba(119, 100, 144, 0.32), rgba(88, 200, 226, 0.26)), - rgba(8, 34, 48, 0.72); - border: 1px solid rgba(178, 244, 255, 0.46); - border-radius: 8px; - box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.26), - 0 10px 24px rgba(0, 8, 18, 0.24); -} - -#title, -.mobile-collapsed-title { - background-image: linear-gradient(0deg, #dffbff, #82f0d8 48%, #776490); - background-clip: text; - -webkit-background-clip: text; - color: transparent; - -webkit-text-fill-color: transparent; - font-family: "MainBold", "AeroTahoma", Tahoma, var(--emoji-font), sans-serif; - text-shadow: none; -} - -#subtitle, -#footer-text, -#user-greeting, -#content-footer, -#post-date, -#post-date-feed, -#post-description, -#post-username, -.usage-label { - color: var(--subtle); -} - -a, -#hide-sidebar, -#show-sidebar { - color: var(--links); -} - -#sidebar > a { - display: block; - margin: 0 12px 8px; -} - -#tab, -#footer-button, -.theme-picker-button, -.theme-picker-option { - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.18), transparent 42%), - linear-gradient(90deg, rgba(119, 100, 144, 0.22), rgba(88, 200, 226, 0.18)), - rgba(7, 36, 51, 0.66) !important; - border: 1px solid rgba(163, 239, 255, 0.48) !important; - border-radius: 8px !important; - color: var(--fg) !important; - box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.24), - 0 5px 14px rgba(0, 8, 18, 0.2) !important; +body.aero-theme #tab { + text-transform: lowercase !important; } -#tab::before { - content: ">> "; - color: var(--links); +body.aero-theme :is(#tab, #footer-button, .mobile-nav-button, .mobile-footer-button, #show-sidebar):hover, +body.aero-theme :is(#tab, #footer-button, .mobile-nav-button, .mobile-footer-button).active { + background: linear-gradient(180deg, #fbfff2, #cbed9e 48%, #79c641 51%, #b9e687) !important; + color: #174d20 !important; + border-color: #4d9c35 !important; + box-shadow: inset 0 1px #fff, 0 0 7px rgba(96,190,57,.55) !important; } -#tab:hover, -#tab.active, -#footer-button:hover, -#footer-button.active, -.theme-picker-option:hover, -.theme-picker-option.selected { - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.42), rgba(255, 255, 255, 0.08) 44%), - linear-gradient(90deg, #776490, #58c8e2 54%, #82f0d8) !important; - border-color: rgba(224, 255, 255, 0.82) !important; - color: #031923 !important; - box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.48), - 0 8px 18px rgba(88, 200, 226, 0.26) !important; - transform: translateY(-1px); +body.aero-theme #tab::before { + content: none !important; } -#tab:hover::before, -#tab.active::before { - color: #031923; +body.aero-theme #footer-button::before { color: #1d8dcc !important; } + +body.aero-theme #content-layout, +body.aero-theme.mobile-template #content-layout, +body.aero-theme.mobile-template #content-main { + background: linear-gradient(135deg, rgba(255,255,255,.94), rgba(226,246,255,.9)) !important; + color: var(--fg) !important; + border: 1px solid rgba(255,255,255,.95) !important; + border-radius: 16px !important; + outline: 1px solid #4b98c9; + box-shadow: inset 0 1px rgba(255,255,255,.95), 0 10px 30px rgba(17,70,105,.28) !important; + backdrop-filter: blur(12px) saturate(1.15); } -#content { - padding: 34px; +body.aero-theme :is(#post, .feed-post, .journal-post, .form-card, .grid-item, .notification-item, .music-album, .gallery-item, .chat-admin-card, .account-admin-card, .site-popup-dialog, .image-modal-content, .feed-reply-notice, .bbcode-editor, #bbcode-preview, table, details, .settings-section) { + background: linear-gradient(180deg, rgba(255,255,255,.94), rgba(211,239,250,.86)) !important; + background-image: linear-gradient(180deg, rgba(255,255,255,.94), rgba(211,239,250,.86)) !important; + color: var(--fg) !important; + border: 1px solid #69a9ce !important; + border-radius: 10px !important; + box-shadow: inset 0 1px #fff, 0 3px 8px rgba(27,86,119,.14) !important; } -#content-layout { - max-width: 940px; - min-height: calc(100% - 2px); - padding: 24px 30px; - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.18), transparent 28%), - linear-gradient(145deg, rgba(119, 100, 144, 0.13), rgba(88, 200, 226, 0.1)), - rgba(6, 27, 39, 0.7); - border: 1px solid rgba(163, 239, 255, 0.48); - border-radius: 10px; - box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.24), - 0 18px 46px rgba(0, 8, 18, 0.34); - backdrop-filter: blur(18px) saturate(1.32); -} - -#content-main > *:first-child { - margin-top: 0; -} - -#post, -.account-admin-card, -.usage-card, -.form-card, -.grid-item, -pre code.hljs, -#mini-player, -#mini-player-tracks, -#sidebar-footer, -.site-popup-dialog, -#bbcode-preview { - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.14), transparent 34%), - rgba(8, 31, 44, 0.72); - color: var(--fg); - border: 1px solid rgba(163, 239, 255, 0.42); - border-radius: 8px; - box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.18), - 0 10px 24px rgba(0, 8, 18, 0.24); - backdrop-filter: blur(12px) saturate(1.2); +body.aero-theme :is(#post, .feed-post, .journal-post, .grid-item, .music-album, .gallery-item, .account-admin-card):hover { + background: linear-gradient(180deg, #fff, #d8f3ff) !important; + border-color: #268ac4 !important; } -#post { - padding: 14px 16px; +body.aero-theme :is(input, textarea, select, .text-input, .dropdown, .bbcode-dropdown, #bbcode-textbox, #search-box) { + background: linear-gradient(180deg, #fff, #effaff) !important; + color: #17384c !important; + border: 1px solid #5d9fc7 !important; + border-radius: 6px !important; + box-shadow: inset 0 1px 3px rgba(30,84,116,.14) !important; } -#post:hover, -.account-admin-card:hover, -.usage-card:hover { - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.18), transparent 34%), - rgba(12, 44, 60, 0.78); -} - -#post-content, -#post-title, -.form-card, -.form-card p, -.form-field label, -.checkbox-label span, -.radio-label span, -.color-row, -.color-row span, -.feed-reply-body, -.feed-reply-meta, -.guestbook-post-actions, -#content-main, -#content-main h1, -#content-main h2, -#content-main h3, -#content-main h4, -#content-main p, -#content-main li { - color: var(--fg); -} - -input, -textarea, -.dropdown, -.text-input, -.bbcode-dropdown, -.bbcode-btn, -#bbcode-textbox, -.color-input { - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.11), rgba(0, 0, 0, 0.08)), - rgba(3, 20, 30, 0.8); - color: var(--fg); - border: 1px solid rgba(163, 239, 255, 0.44); - border-radius: 7px; -} - -input:hover, -input:focus, -textarea:hover, -textarea:focus, -.dropdown:hover, -.dropdown:focus, -.text-input:hover, -.text-input:focus, -.bbcode-dropdown:hover, -.bbcode-dropdown:focus, -.bbcode-btn:hover, -.bbcode-btn:focus, -#bbcode-textbox:focus { - border-color: rgba(130, 240, 216, 0.88); - box-shadow: 0 0 0 2px rgba(130, 240, 216, 0.16); +body.aero-theme :is(input, textarea, select, .text-input, .dropdown, .bbcode-dropdown, #bbcode-textbox, #search-box):focus { + background: #fff !important; + border-color: #158ed1 !important; + box-shadow: 0 0 0 3px rgba(22,142,209,.22), inset 0 1px 2px rgba(30,84,116,.1) !important; outline: none; } -button, -#search-button, -#form-button, -#lastfm-link-button, -#settings-save, -#color-reset, -.danger-button, -.site-popup-button { - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.24), rgba(255, 255, 255, 0.04) 45%), - linear-gradient(90deg, #776490, #58c8e2 58%, #82f0d8); - color: #031923; - border: 1px solid rgba(224, 255, 255, 0.74); - border-radius: 8px; - box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.46), - 0 8px 18px rgba(0, 8, 18, 0.24); -} - -button:hover, -#search-button:hover, -#form-button:hover, -#lastfm-link-button:hover, -#settings-save:hover, -#color-reset:hover, -.site-popup-button:hover { - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0.08) 44%), - linear-gradient(90deg, #8b73a8, #6fd8ef 58%, #a1ffe9); - color: #031923; -} +body.aero-theme :is(select, .dropdown, .bbcode-dropdown) option { background: #effaff; color: var(--fg); } -.danger-button { - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0.04)), - #8c2d3d; - color: #fff7f7; +body.aero-theme :is(button, #search-button, #form-button, #two-buttons, .bbcode-btn, input[type="submit"], input[type="button"], #settings-save, #color-reset) { + background: linear-gradient(180deg, #fbfff7, #d9f2bb 48%, #79c445 51%, #a9db77) !important; + color: #174c21 !important; + border: 1px solid #4c9538 !important; + border-radius: 7px !important; + box-shadow: inset 0 1px #fff, 0 1px 3px rgba(38,100,33,.22) !important; + text-shadow: 0 1px rgba(255,255,255,.8); } -.checkbox, -.radio { - background: rgba(3, 20, 30, 0.82); - border: 1px solid rgba(163, 239, 255, 0.44); +body.aero-theme :is(button, #search-button, #form-button, #two-buttons, .bbcode-btn, input[type="submit"], input[type="button"], #settings-save, #color-reset):hover { + background: linear-gradient(180deg, #fff, #eaffd3 48%, #8ed458 51%, #c5ed9d) !important; + color: #103d18 !important; } -.checkbox:checked { - background-color: var(--links); +body.aero-theme :is(.danger-button, .grid-delete-button, #admin-account-delete-form button) { + background: linear-gradient(180deg, #ffeded, #f09595 48%, #d84e4e 51%, #ed7777) !important; + color: #641313 !important; + border-color: #ba4141 !important; } -.radio { - border-radius: 50%; +body.aero-theme #search { + padding: 7px; + border: 1px solid #79b5d5; + border-radius: 10px; + background: rgba(189,229,247,.62) !important; } -.radio:checked { - background: radial-gradient(circle, var(--links) 0 42%, rgba(3, 20, 30, 0.82) 46%); +body.aero-theme :is(#mini-player, #mini-player-tracks, #sidebar-footer), +body.aero-theme.mobile-template :is(#mini-player, #mini-player-tracks, #sidebar-footer) { + background: linear-gradient(180deg, rgba(255,255,255,.88), rgba(175,221,241,.88)) !important; + color: var(--fg) !important; + border: 1px solid #5599c1 !important; + border-radius: 10px !important; + box-shadow: inset 0 1px #fff !important; +} + +body.aero-theme #mini-player-art-wrapper, +body.aero-theme .grid-image { border-radius: 7px; overflow: hidden; } +body.aero-theme :is(#mini-player-title-inner, .mini-track.active) { color: #0876be !important; } +body.aero-theme .mini-track { background: rgba(255,255,255,.4) !important; border-radius: 5px !important; } +body.aero-theme .mini-track:hover, +body.aero-theme .mini-track.active { background: rgba(188,235,166,.75) !important; color: #20582b !important; } +body.aero-theme #mini-player-close { background: transparent !important; border: 0 !important; box-shadow: none !important; color: #28698f !important; } +body.aero-theme :is(#mini-player-seek, #mini-player-volume) { accent-color: #68bb3f; } + +body.aero-theme :is(pre, code, blockquote) { background: rgba(212,239,250,.7) !important; color: #17384c; border-color: #79afd0 !important; } +body.aero-theme :is(#homepage-hero-ascii, #homepage-hero-ascii pre, #ascii, #ascii-time, #usage-grid, #usage-grid .usage-card, .usage-ascii, .usage-label) { background: transparent !important; border: 0 !important; box-shadow: none !important; } +body.aero-theme a { color: var(--links); } +body.aero-theme .tooltip, +body.aero-theme :is(.site-notification-toast, .chat-context-menu) { background: linear-gradient(180deg, #fff, #dff3fc) !important; color: var(--fg) !important; border-color: #4e98c4 !important; border-radius: 7px !important; } +body.aero-theme :is(.site-popup-overlay, .image-modal, .mobile-menu-backdrop) { background: rgba(22,68,94,.5) !important; backdrop-filter: blur(4px); } +body.aero-theme :is(.chat-message:not(.chat-message-own), .chat-reply-reference, .chat-reply-compose) { background: #e5f6fc !important; color: var(--fg) !important; border-color: #7eb5d2 !important; border-radius: 10px !important; } +body.aero-theme .chat-message-own { background: linear-gradient(180deg, #30a3df, #1179bb) !important; color: #fff !important; } + +/* Aero editor: compact Windows 7 toolbar chrome above a clean writing pane. */ +body.aero-theme .bbcode-editor, +body.aero-theme .feed-thread-page .bbcode-editor, +body.aero-theme .feed-markdown-editor { + overflow: hidden; + background: rgba(226, 245, 253, .92) !important; + background-image: none !important; + border: 1px solid #438fbd !important; + border-radius: 11px !important; + box-shadow: inset 0 1px #fff, 0 4px 12px rgba(23, 79, 112, .18) !important; +} + +body.aero-theme .bbcode-toolbar, +body.aero-theme .feed-thread-page .bbcode-toolbar, +body.aero-theme .feed-markdown-toolbar { + min-width: 0; + padding: 7px !important; + gap: 5px !important; + overflow: visible; + background: linear-gradient(180deg, rgba(255,255,255,.98), rgba(180,224,244,.94)) !important; + background-image: linear-gradient(180deg, rgba(255,255,255,.98), rgba(180,224,244,.94)) !important; + border: 0 !important; + border-bottom: 1px solid #438fbd !important; + border-radius: 10px 10px 0 0 !important; + box-shadow: inset 0 1px #fff !important; +} + +body.aero-theme .feed-markdown-formatting { + gap: 3px; + padding: 1px 2px 4px 1px; + scrollbar-color: #4f9dca transparent; +} + +body.aero-theme .feed-markdown-actions { + gap: 3px; + margin-left: 2px; + padding-left: 7px; + border-left-color: rgba(55, 132, 176, .45); +} + +body.aero-theme .bbcode-btn, +body.aero-theme .feed-thread-page .bbcode-btn, +body.aero-theme .feed-markdown-editor .bbcode-btn, +body.aero-theme .journal-markdown-editor .bbcode-btn { + display: inline-flex; + width: 34px; + min-width: 34px; + height: 32px; + padding: 0 !important; + align-items: center; + justify-content: center; + background: linear-gradient(180deg, #fff 0%, #dff4fd 47%, #acd8ee 50%, #d9f1fb 100%) !important; + background-image: linear-gradient(180deg, #fff 0%, #dff4fd 47%, #acd8ee 50%, #d9f1fb 100%) !important; + color: #15597e !important; + border: 1px solid #4b94bf !important; + border-radius: 6px !important; + box-shadow: inset 0 1px #fff, 0 1px 2px rgba(24, 77, 108, .16) !important; + text-shadow: 0 1px #fff; +} + +body.aero-theme .bbcode-btn:hover, +body.aero-theme .bbcode-btn:focus-visible { + background: linear-gradient(180deg, #fff, #e7f8ff 47%, #8dcae8 50%, #c9ecfa) !important; + color: #064f78 !important; + border-color: #147db7 !important; + box-shadow: 0 0 0 2px rgba(22, 142, 209, .18), inset 0 1px #fff !important; + outline: none; } -input[type="range"] { - accent-color: var(--links); +body.aero-theme .bbcode-btn:active, +body.aero-theme .bbcode-btn[aria-pressed="true"] { + background: linear-gradient(180deg, #83bddb, #d9f1fb) !important; + box-shadow: inset 0 2px 3px rgba(28, 84, 116, .24) !important; + transform: none; +} + +body.aero-theme .bbcode-btn:disabled, +body.aero-theme .bbcode-btn.disabled { + opacity: .48; + filter: grayscale(.35); +} + +body.aero-theme .bbcode-dropdown, +body.aero-theme .feed-thread-page .bbcode-dropdown { + width: auto; + min-width: 72px; + height: 32px; + padding: 4px 24px 4px 8px !important; + background: linear-gradient(180deg, #fff, #d9eff9) !important; + color: #174967 !important; + border: 1px solid #4b94bf !important; + border-radius: 6px !important; + box-shadow: inset 0 1px #fff !important; +} + +body.aero-theme #bbcode-textbox, +body.aero-theme .feed-thread-page #bbcode-textbox, +body.aero-theme .feed-markdown-editor #bbcode-textbox, +body.aero-theme .markdown-highlight-layer, +body.aero-theme #bbcode-preview, +body.aero-theme .feed-markdown-preview { + margin: 0 !important; + background: rgba(250, 254, 255, .96) !important; + background-image: none !important; + color: #18384b !important; + border: 0 !important; + border-radius: 0 0 10px 10px !important; + box-shadow: inset 0 2px 4px rgba(32, 93, 127, .1) !important; + caret-color: #0876be; +} + +body.aero-theme #bbcode-textbox::placeholder, +body.aero-theme .markdown-highlight-input::placeholder { + color: #718d9d !important; + opacity: 1; +} + +body.aero-theme #bbcode-textbox:focus { + background: #fff !important; + box-shadow: inset 0 0 0 2px rgba(22, 142, 209, .16) !important; + outline: none; } -#mini-player, -#mini-player-tracks { - color: var(--fg); +body.aero-theme .markdown-highlight-input { + background: transparent !important; + border: 0 !important; + border-radius: 0 0 10px 10px !important; + box-shadow: none !important; } -#mini-player-art-wrapper, -#mini-player-art { - border-radius: 6px; - background: rgba(3, 20, 30, 0.88); - border-color: rgba(163, 239, 255, 0.36); +body.aero-theme .markdown-highlight-input:focus { + background: transparent !important; + outline: none; } -#mini-player-download, -#mini-player-play, -#mini-player-controls span { - color: var(--links); +body.aero-theme :is(.bbcode-voice-recorder, .chat-voice-recorder) { + background: linear-gradient(180deg, #f8fdff, #d8eff9) !important; + color: var(--fg) !important; + border: 0 !important; + border-top: 1px solid #6ca8c9 !important; } -#mini-player-download:hover, -#mini-player-play:hover, -#mini-player-controls span:hover, -.mini-track:hover, -.mini-track.active { - background: rgba(130, 240, 216, 0.18); - color: var(--fg); +/* Compact Winamp-inspired player skin inside the bright Aero shell. */ +body.aero-theme #mini-player, +body.aero-theme.mobile-template #mini-player { + position: relative; + padding: 22px 7px 7px !important; + background: + linear-gradient(90deg, rgba(255,255,255,.08) 1px, transparent 1px) 0 0 / 3px 3px, + linear-gradient(180deg, #3c4656, #1a202a) !important; + color: #d9e2e8 !important; + border: 2px solid !important; + border-color: #eef3f7 #111720 #111720 #eef3f7 !important; + border-radius: 2px !important; + box-shadow: inset 1px 1px #778393, inset -1px -1px #080b10 !important; + font-family: "Aero Tahoma", Tahoma, sans-serif !important; +} + +body.aero-theme #mini-player::before { + content: "FRIDGEAMP"; + position: absolute; + top: 4px; + left: 7px; + color: #f1f4f6; + font-family: "Aero Tahoma", Tahoma, sans-serif; + font-size: 9px; + font-weight: bold; + line-height: 12px; + letter-spacing: 1.3px; + text-shadow: 1px 1px #06090d; +} + +body.aero-theme #mini-player::after { + content: ""; + position: absolute; + top: 7px; + right: 27px; + left: 78px; + height: 3px; + border-top: 1px solid #8996a6; + border-bottom: 1px solid #10151d; +} + +body.aero-theme #mini-player-main { gap: 6px !important; } + +body.aero-theme #mini-player-art-wrapper { + width: 42px !important; + height: 42px !important; + flex: 0 0 42px !important; + margin: 0 !important; + background: #050806 !important; + border: 2px solid !important; + border-color: #080b10 #778393 #778393 #080b10 !important; + border-radius: 0 !important; + box-shadow: none !important; +} + +body.aero-theme #mini-player-art { border-radius: 0 !important; } + +body.aero-theme #mini-player-download { + background: rgba(5, 8, 6, .78) !important; + color: #8eff54 !important; + border-radius: 0 !important; +} + +body.aero-theme #mini-player-meta { + gap: 3px !important; + min-width: 0; +} + +body.aero-theme #mini-player-title, +body.aero-theme #mini-player-artist { + min-width: 0; + padding: 2px 5px !important; + box-sizing: border-box; + overflow: hidden; + background: #07100a !important; + border: 1px solid !important; + border-color: #050806 #5b6875 #5b6875 #050806 !important; + border-radius: 0 !important; + color: #8eff54 !important; + font-family: "Aero Tahoma", Tahoma, sans-serif !important; + font-size: 10px !important; + line-height: 13px !important; + text-shadow: 0 0 4px rgba(106,255,66,.5) !important; +} + +body.aero-theme #mini-player-title-inner, +body.aero-theme #mini-player-title-inner.scrolling, +body.aero-theme #mini-player-artist { + color: #8eff54 !important; + font-family: inherit !important; +} + +body.aero-theme #mini-player-artist { color: #5fcf42 !important; } +body.aero-theme #mini-player-row { gap: 4px !important; align-items: center !important; } + +body.aero-theme :is(#mini-player-play, #mini-player-mute) { + display: inline-flex; + width: 20px !important; + min-width: 20px !important; + height: 18px !important; + align-items: center; + justify-content: center; + box-sizing: border-box; + background: linear-gradient(180deg, #d8dde1, #788493) !important; + color: #10161e !important; + border: 1px solid !important; + border-color: #f5f7f8 #303945 #303945 #f5f7f8 !important; + border-radius: 0 !important; + box-shadow: inset 1px 1px rgba(255,255,255,.45) !important; + font-size: 9px !important; + text-shadow: none !important; +} + +body.aero-theme :is(#mini-player-play, #mini-player-mute):hover { + background: linear-gradient(180deg, #f0f3f5, #91a0b0) !important; + color: #005ba0 !important; +} + +body.aero-theme :is(#mini-player-play, #mini-player-mute):active { + border-color: #303945 #f5f7f8 #f5f7f8 #303945 !important; + background: #768291 !important; +} + +body.aero-theme #mini-player-volume-wrapper { gap: 3px !important; } + +body.aero-theme :is(#mini-player-seek, #mini-player-volume) { + height: 10px !important; + padding: 0 !important; + background: #080d13 !important; + border: 1px solid !important; + border-color: #05070a #66717d #66717d #05070a !important; + border-radius: 0 !important; + box-shadow: none !important; + accent-color: #168ed1; +} + +body.aero-theme :is(#mini-player-seek, #mini-player-volume)::-webkit-slider-runnable-track { + height: 4px; + background: linear-gradient(90deg, #0879c4, #61d8ff) !important; + border: 0 !important; + border-radius: 0 !important; +} + +body.aero-theme :is(#mini-player-seek, #mini-player-volume)::-webkit-slider-thumb { + width: 7px !important; + height: 10px !important; + margin-top: -3px !important; + background: linear-gradient(90deg, #e2e6e9, #788492) !important; + border: 1px solid #222b35 !important; + border-radius: 0 !important; + box-shadow: none !important; +} + +body.aero-theme :is(#mini-player-seek, #mini-player-volume)::-moz-range-track { + height: 4px; + background: linear-gradient(90deg, #0879c4, #61d8ff) !important; + border: 0 !important; + border-radius: 0 !important; +} + +body.aero-theme :is(#mini-player-seek, #mini-player-volume)::-moz-range-thumb { + width: 7px !important; + height: 10px !important; + background: linear-gradient(90deg, #e2e6e9, #788492) !important; + border: 1px solid #222b35 !important; + border-radius: 0 !important; + box-shadow: none !important; +} + +body.aero-theme #mini-player-close { + top: 3px !important; + right: 5px !important; + width: 15px !important; + height: 14px !important; + min-width: 15px !important; + background: linear-gradient(180deg, #d8dde1, #788493) !important; + color: #751414 !important; + border: 1px solid !important; + border-color: #f5f7f8 #303945 #303945 #f5f7f8 !important; + border-radius: 0 !important; + box-shadow: none !important; + font-size: 9px !important; +} + +body.aero-theme #mini-player-tracks, +body.aero-theme.mobile-template #mini-player-tracks { + padding: 3px !important; + background: #080d13 !important; + background-image: none !important; + color: #8eff54 !important; + border: 2px solid !important; + border-color: #080b10 #75808e #75808e #080b10 !important; + border-radius: 0 !important; + box-shadow: none !important; + font-family: "Aero Tahoma", Tahoma, sans-serif !important; +} + +body.aero-theme .mini-track { + padding: 4px 5px !important; + background: #080d13 !important; + color: #76df4e !important; + border: 0 !important; + border-radius: 0 !important; + font-family: inherit !important; + font-size: 10px !important; +} + +body.aero-theme .mini-track:hover, +body.aero-theme .mini-track.active { + background: #1d4f78 !important; + color: #fff !important; +} + +body.aero-theme.mobile-template :is(.mobile-collapsed-header, #show-sidebar) { + background: linear-gradient(180deg, rgba(255,255,255,.95), rgba(158,216,242,.92)) !important; + color: #155779 !important; + border-color: #408dbb !important; +} +body.aero-theme.mobile-template #sidebar { + width: calc(100% - 16px) !important; + max-width: none !important; + min-width: 0 !important; + box-sizing: border-box !important; } +body.aero-theme.mobile-template #content { background: transparent !important; color: var(--fg) !important; } -#mini-player-title-inner, -.mini-track { - color: var(--fg); +@media (max-width: 600px) { + body.aero-theme .bbcode-toolbar, + body.aero-theme .feed-markdown-toolbar { padding: 6px !important; gap: 3px !important; } + body.aero-theme .bbcode-btn, + body.aero-theme .feed-markdown-editor .bbcode-btn { width: 31px; min-width: 31px; height: 30px; } + body.aero-theme .feed-markdown-actions { padding-left: 5px; } + body.aero-theme.mobile-template #mini-player { padding-top: 22px !important; } + body.aero-theme.mobile-template #mini-player-art-wrapper { width: 38px !important; height: 38px !important; flex-basis: 38px !important; } } -.tooltip { - background: rgba(4, 25, 36, 0.94); - color: var(--fg); - border-color: rgba(163, 239, 255, 0.48); - box-shadow: 0 10px 24px rgba(0, 8, 18, 0.38); +/* Calm Aero palette: misty blue glass and soft sage instead of saturated cyan + and lime, while retaining enough separation for controls and content. */ +body.aero-theme { + --bg: #dce9ee; + --fg: #29434e; + --border: #7899a7; + --subtle: #667d86; + --links: #3f7892; + --chat-own-bg: #5d8799; + --hero-ascii-muted: #8ba8b4; + --hero-ascii-1: #537f98; + --hero-ascii-2: #598ba1; + --hero-ascii-3: #6096a5; + --hero-ascii-4: #6c9f9d; + --hero-ascii-5: #78a58d; + --hero-ascii-6: #86aa7d; + --hero-ascii-7: #94ae75; + --selection-bg: #648da0; + --scrollbar-track: #d9e6eb; + --scrollbar-thumb: #8aa7b3; + --scrollbar-thumb-hover: #668c9d; } -.theme-picker-menu { - background: rgba(5, 24, 35, 0.95); - border-color: rgba(163, 239, 255, 0.48); -} +body.aero-theme, +body.aero-theme.mobile-template { background-color: #91b9c8 !important; } -.theme-picker-description, -.theme-picker-option-description { - color: var(--subtle); +body.aero-theme #sidebar, +body.aero-theme.mobile-template #sidebar { + background: linear-gradient(180deg, rgba(239,247,249,.9), rgba(200,221,228,.86)) !important; + border-right-color: #7699a8 !important; + box-shadow: inset -1px 0 rgba(255,255,255,.7), 6px 0 18px rgba(42,72,84,.18) !important; } -.theme-picker-option:hover .theme-picker-option-title, -.theme-picker-option:hover .theme-picker-option-description, -.theme-picker-option.selected .theme-picker-option-title, -.theme-picker-option.selected .theme-picker-option-description { - color: #031923 !important; +body.aero-theme #header { + background: linear-gradient(180deg, rgba(255,255,255,.88), rgba(193,220,230,.68)) !important; + border-color: #7d9faa !important; } -.chat-view { - --chat-bg: rgba(7, 28, 40, 0.72); - --chat-fg: #edfaff; - --chat-border: rgba(163, 239, 255, 0.42); - --chat-muted: #9dccd8; - --chat-own-bg: #82f0d8; - --chat-own-fg: #052b35; - --chat-other-bg: rgba(28, 65, 80, 0.84); - --chat-other-fg: #edfaff; +body.aero-theme #title, +body.aero-theme #title .title-letter, +body.aero-theme .mobile-collapsed-title, +body.aero-theme .mobile-collapsed-title .title-letter { + background-image: linear-gradient(0deg, #547f97, #6997a8 44%, #87a979 49%, #6991a0 56%, #547f97) !important; } - -body.mobile-template { - background: - radial-gradient(ellipse at 22% 4%, rgba(150, 236, 255, 0.32), transparent 34%), - radial-gradient(ellipse at 86% 84%, rgba(130, 240, 216, 0.18), transparent 32%), - linear-gradient(180deg, #081524 0%, #0b2f43 46%, #082b36 68%, #06151d 100%) !important; - color: var(--fg) !important; +body.aero-theme :is(#tab, #footer-button, .mobile-nav-button, .mobile-footer-button, #show-sidebar) { + background: linear-gradient(180deg, #f8fbfc, #d9e8ed 52%, #c2d8e0) !important; + color: #355868 !important; + border-color: #7899a7 !important; } -body.mobile-template #sidebar { - width: 100% !important; - min-width: 0 !important; - max-width: none !important; - height: auto !important; - min-height: 0 !important; - box-sizing: border-box !important; +body.aero-theme :is(#tab, #footer-button, .mobile-nav-button, .mobile-footer-button, #show-sidebar):hover, +body.aero-theme :is(#tab, #footer-button, .mobile-nav-button, .mobile-footer-button).active { + background: linear-gradient(180deg, #f7faf3, #dce8d4 52%, #c1d4b8) !important; + color: #3f6045 !important; + border-color: #7f9e79 !important; + box-shadow: inset 0 1px #fff, 0 0 5px rgba(105,143,98,.24) !important; } -body.mobile-template #sidebar, -body.mobile-template .mobile-collapsed-header, -body.mobile-template #content-layout, -body.mobile-template #content-main, -body.mobile-template #mini-player, -body.mobile-template #mini-player-tracks, -body.mobile-template #sidebar-footer { - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.16), transparent 28%), - rgba(6, 27, 39, 0.82) !important; - color: var(--fg) !important; - border-color: rgba(163, 239, 255, 0.48) !important; - border-radius: 10px !important; - box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.2), - 0 12px 26px rgba(0, 8, 18, 0.28) !important; +body.aero-theme #content-layout, +body.aero-theme.mobile-template #content-layout, +body.aero-theme.mobile-template #content-main { + background: linear-gradient(135deg, rgba(249,251,250,.94), rgba(223,235,239,.92)) !important; + outline-color: #7899a7; + box-shadow: inset 0 1px rgba(255,255,255,.94), 0 9px 24px rgba(42,72,84,.2) !important; } -body.mobile-template #content { - padding: 12px 10px 16px !important; +body.aero-theme :is(#post, .feed-post, .journal-post, .form-card, .grid-item, .notification-item, .music-album, .gallery-item, .chat-admin-card, .account-admin-card, .site-popup-dialog, .image-modal-content, .feed-reply-notice, .bbcode-editor, #bbcode-preview, table, details, .settings-section) { + background: linear-gradient(180deg, rgba(250,252,251,.94), rgba(218,232,236,.9)) !important; + border-color: #8aa5af !important; } -body.mobile-template #content-layout { - padding: 16px !important; +body.aero-theme :is(#post, .feed-post, .journal-post, .grid-item, .music-album, .gallery-item, .account-admin-card):hover { + background: linear-gradient(180deg, #fbfcfb, #e1edf0) !important; + border-color: #6e929f !important; } -body.mobile-template .mobile-nav-grid a.mobile-nav-link > #tab.mobile-nav-button, -body.mobile-template #footer-buttons > a.mobile-footer-link > #footer-button.mobile-footer-button, -body.mobile-template #show-sidebar, -body.mobile-template .mobile-collapsed-header #show-sidebar { - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.18), transparent 42%), - linear-gradient(90deg, rgba(119, 100, 144, 0.22), rgba(88, 200, 226, 0.18)), - rgba(7, 36, 51, 0.76) !important; +body.aero-theme :is(input, textarea, select, .text-input, .dropdown, .bbcode-dropdown, #bbcode-textbox, #search-box) { + background: linear-gradient(180deg, #fafcfb, #edf3f4) !important; + color: var(--fg) !important; + border-color: #819faa !important; +} + +body.aero-theme :is(input, textarea, select, .text-input, .dropdown, .bbcode-dropdown, #bbcode-textbox, #search-box):focus { + border-color: #648da0 !important; + box-shadow: 0 0 0 3px rgba(100,141,160,.16), inset 0 1px 2px rgba(48,75,86,.08) !important; +} + +body.aero-theme :is(button:not(#mini-player-close):not(.bbcode-btn):not(.danger-button):not(.grid-delete-button), #search-button, #form-button, #two-buttons, input[type="submit"], input[type="button"], #settings-save, #color-reset) { + background: linear-gradient(180deg, #f8faf6, #dce8d5 52%, #bfd2b7) !important; + color: #3c5c42 !important; + border-color: #7d9c77 !important; + box-shadow: inset 0 1px #fff, 0 1px 2px rgba(57,87,53,.14) !important; +} + +body.aero-theme :is(button:not(#mini-player-close):not(.bbcode-btn):not(.danger-button):not(.grid-delete-button), #search-button, #form-button, #two-buttons, input[type="submit"], input[type="button"], #settings-save, #color-reset):hover { + background: linear-gradient(180deg, #fff, #e6efe1 52%, #cbdcc4) !important; + color: #34533a !important; +} + +body.aero-theme .bbcode-toolbar, +body.aero-theme .feed-markdown-toolbar { + background: linear-gradient(180deg, rgba(250,252,252,.98), rgba(202,222,229,.96)) !important; + border-bottom-color: #7899a7 !important; +} + +body.aero-theme .bbcode-btn, +body.aero-theme .feed-thread-page .bbcode-btn, +body.aero-theme .feed-markdown-editor .bbcode-btn, +body.aero-theme .journal-markdown-editor .bbcode-btn { + background: linear-gradient(180deg, #fafcfc, #dce9ed 52%, #c4d9e0) !important; + color: #416779 !important; + border-color: #7b9ba8 !important; +} + +body.aero-theme .bbcode-btn:hover, +body.aero-theme .bbcode-btn:focus-visible { + background: linear-gradient(180deg, #fff, #e5eff2 52%, #d0e1e6) !important; + color: #345f73 !important; + border-color: #648da0 !important; +} + +body.aero-theme :is(.checkbox, .radio), +body.aero-theme.mobile-template :is(.checkbox, .radio) { + width: 16px; + height: 16px; + padding: 0 !important; + appearance: none; + -webkit-appearance: none; + background: linear-gradient(180deg, #fbfcfb, #dfe9ec) !important; + border: 1px solid #718f9b !important; + box-shadow: inset 0 1px #fff, 0 1px 2px rgba(48,75,86,.12) !important; +} + +body.aero-theme .checkbox, +body.aero-theme.mobile-template .checkbox { border-radius: 3px !important; } + +body.aero-theme .checkbox:checked, +body.aero-theme.mobile-template .checkbox:checked { + background-color: #789d75 !important; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.2 8.1 6.5 11l6.3-7' fill='none' stroke='%23fff' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") !important; + background-position: center !important; + background-size: 14px 14px !important; + background-repeat: no-repeat !important; + border-color: #668861 !important; + box-shadow: inset 0 1px rgba(255,255,255,.3), 0 1px 2px rgba(48,75,52,.16) !important; +} + +body.aero-theme .radio, +body.aero-theme.mobile-template .radio { border-radius: 50% !important; } + +body.aero-theme .radio:checked, +body.aero-theme.mobile-template .radio:checked { + background: radial-gradient(circle, #6f966c 0 38%, #f7faf8 42% 58%, #dfe9ec 62%) !important; + border-color: #668861 !important; + box-shadow: inset 0 1px #fff, 0 1px 2px rgba(48,75,52,.16) !important; +} + +/* Keep the retro player dark, but replace its neon display and electric-blue + accents with softer phosphor and slate tones. */ +body.aero-theme #mini-player-title, +body.aero-theme #mini-player-artist, +body.aero-theme #mini-player-title-inner, +body.aero-theme #mini-player-title-inner.scrolling { + color: #b4cea4 !important; + text-shadow: 0 0 3px rgba(180,206,164,.3) !important; +} +body.aero-theme #mini-player-artist { color: #91ad84 !important; } +body.aero-theme #mini-player-download, +body.aero-theme #mini-player-tracks, +body.aero-theme .mini-track { color: #abc99a !important; } +body.aero-theme :is(#mini-player-seek, #mini-player-volume)::-webkit-slider-runnable-track { background: linear-gradient(90deg, #527e94, #8ab2c1) !important; } +body.aero-theme :is(#mini-player-seek, #mini-player-volume)::-moz-range-track { background: linear-gradient(90deg, #527e94, #8ab2c1) !important; } +body.aero-theme .mini-track:hover, +body.aero-theme .mini-track.active { background: #3e6074 !important; color: #f4f7f5 !important; } + +/* Complete mobile shell coverage, including the high-specificity player rules + embedded by the shared mobile template. */ +body.aero-theme.mobile-template #sidebar { + width: calc(100% - 16px) !important; + min-width: 0 !important; + max-width: none !important; + padding-bottom: 10px !important; + box-sizing: border-box !important; + border: 1px solid rgba(255,255,255,.82) !important; + border-right-color: #7899a7 !important; + border-radius: 13px !important; +} +body.aero-theme.mobile-template .mobile-nav-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + gap: 7px !important; + padding: 8px 10px 0 !important; +} +body.aero-theme.mobile-template .mobile-nav-grid a.mobile-nav-link > #tab.mobile-nav-button { + min-width: 0 !important; + min-height: 40px !important; + background: linear-gradient(180deg, #f8fbfc, #d9e8ed 52%, #c2d8e0) !important; + color: #355868 !important; + border: 1px solid #7899a7 !important; + border-radius: 7px !important; +} +body.aero-theme.mobile-template .mobile-nav-grid a.mobile-nav-link > #tab.mobile-nav-button:hover, +body.aero-theme.mobile-template .mobile-nav-grid a.mobile-nav-link > #tab.mobile-nav-button.active { + background: linear-gradient(180deg, #f7faf3, #dce8d4 52%, #c1d4b8) !important; + color: #3f6045 !important; + border-color: #7f9e79 !important; +} +body.aero-theme.mobile-template #content { padding: 10px !important; } +body.aero-theme.mobile-template #content-layout { + padding: 0 !important; + background: transparent !important; + border: 0 !important; + outline: 0 !important; + box-shadow: none !important; +} +body.aero-theme.mobile-template #content-main { + min-width: 0 !important; + padding: 16px 14px !important; + background: linear-gradient(135deg, rgba(249,251,250,.96), rgba(223,235,239,.94)) !important; + border: 1px solid rgba(255,255,255,.9) !important; + border-radius: 12px !important; + outline: 1px solid #7899a7 !important; + box-shadow: 0 7px 20px rgba(42,72,84,.16) !important; + overflow-x: hidden !important; +} +body.aero-theme.mobile-template #sidebar #mini-player { + margin: 8px 10px 0 !important; + padding: 22px 7px 7px !important; + width: auto !important; + background: linear-gradient(180deg, #3c4656, #1a202a) !important; + border: 2px solid !important; + border-color: #eef3f7 #111720 #111720 #eef3f7 !important; + border-radius: 2px !important; +} +body.aero-theme.mobile-template #sidebar #mini-player-main { + grid-template-columns: 46px minmax(0, 1fr) !important; + gap: 7px !important; +} +body.aero-theme.mobile-template #sidebar #mini-player-art-wrapper { width: 46px !important; height: 46px !important; } +body.aero-theme.mobile-template #sidebar #mini-player-title-inner { color: #b4cea4 !important; font-family: "Aero Tahoma", Tahoma, sans-serif !important; } +body.aero-theme.mobile-template #sidebar #mini-player-artist { color: #91ad84 !important; } +body.aero-theme.mobile-template #sidebar #mini-player-play { background: linear-gradient(180deg, #d8dde1, #788493) !important; color: #10161e !important; border: 1px solid #303945 !important; } +body.aero-theme.mobile-template #sidebar #mini-player-close { background: linear-gradient(180deg, #d8dde1, #788493) !important; color: #751414 !important; border: 1px solid #303945 !important; } +body.aero-theme.mobile-template #sidebar #mini-player-tracks { + margin: 8px 10px 0 !important; + background: #080d13 !important; + color: #abc99a !important; + border: 2px solid #65717d !important; + border-radius: 0 !important; +} +body.aero-theme.mobile-template #sidebar #sidebar-footer { + margin: 8px 10px 0 !important; + background: rgba(239,247,249,.9) !important; color: var(--fg) !important; - border-color: rgba(163, 239, 255, 0.48) !important; + border: 1px solid #7899a7 !important; border-radius: 8px !important; } - -body.mobile-template .mobile-nav-grid a.mobile-nav-link > #tab.mobile-nav-button:hover, -body.mobile-template .mobile-nav-grid a.mobile-nav-link > #tab.mobile-nav-button.active, -body.mobile-template .mobile-nav-grid a.mobile-nav-link > #tab.mobile-nav-button.active:hover, -body.mobile-template #footer-buttons > a.mobile-footer-link > #footer-button.mobile-footer-button:hover, -body.mobile-template #footer-buttons > a.mobile-footer-link > #footer-button.mobile-footer-button.active, -body.mobile-template #footer-buttons > a.mobile-footer-link > #footer-button.mobile-footer-button.active:hover, -body.mobile-template #show-sidebar:hover, -body.mobile-template .mobile-collapsed-header #show-sidebar:hover { - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.42), rgba(255, 255, 255, 0.08) 44%), - linear-gradient(90deg, #776490, #58c8e2 54%, #82f0d8) !important; - color: #031923 !important; - border-color: rgba(224, 255, 255, 0.82) !important; -} - -body.mobile-template input, -body.mobile-template textarea, -body.mobile-template .dropdown, -body.mobile-template .text-input, -body.mobile-template .bbcode-dropdown, -body.mobile-template .bbcode-btn, -body.mobile-template #bbcode-textbox, -body.mobile-template #bbcode-preview, -body.mobile-template .checkbox, -body.mobile-template .radio, -body.mobile-template .color-input { - background: rgba(3, 20, 30, 0.86) !important; +body.aero-theme.mobile-template :is(#post, .feed-post, .journal-post, .notification-item, .music-album, .gallery-item, .form-card, .grid-item, .chat-admin-card, .account-admin-card, .settings-section, details, table) { + background: linear-gradient(180deg, rgba(250,252,251,.96), rgba(218,232,236,.94)) !important; color: var(--fg) !important; - border-color: rgba(163, 239, 255, 0.44) !important; + border: 1px solid #8aa5af !important; + border-radius: 9px !important; + box-shadow: inset 0 1px #fff, 0 2px 6px rgba(42,72,84,.12) !important; +} +body.aero-theme.mobile-template :is(#post, .feed-post, .journal-post, .grid-item, .music-album, .gallery-item, .account-admin-card):hover { + background: linear-gradient(180deg, #fbfcfb, #e1edf0) !important; + border-color: #6e929f !important; +} +body.aero-theme.mobile-template #footer-buttons > a.mobile-footer-link > #footer-button.mobile-footer-button { + background: linear-gradient(180deg, #f8fbfc, #d9e8ed 52%, #c2d8e0) !important; + color: #355868 !important; + border: 1px solid #7899a7 !important; + border-radius: 7px !important; +} +body.aero-theme.mobile-template #footer-buttons > a.mobile-footer-link > #footer-button.mobile-footer-button:hover, +body.aero-theme.mobile-template #footer-buttons > a.mobile-footer-link > #footer-button.mobile-footer-button.active { + background: linear-gradient(180deg, #f7faf3, #dce8d4 52%, #c1d4b8) !important; + color: #3f6045 !important; + border-color: #7f9e79 !important; +} +body.aero-theme.mobile-template :is(#post-content, #post-title, #post-header, .grid-caption, .form-card, .settings-section) { color: var(--fg) !important; } +body.aero-theme.mobile-template :is(#post-description, #post-date, #post-date-feed, #post-username, .grid-subcaption) { color: var(--subtle) !important; } +body.aero-theme.mobile-template :is(input, textarea, select, .text-input, .dropdown, .bbcode-dropdown, #bbcode-textbox) { max-width: 100% !important; box-sizing: border-box !important; } +body.aero-theme.mobile-template :is(table, pre, code, img, video, iframe) { max-width: 100% !important; } +body.aero-theme.mobile-template :is(pre, table) { overflow-x: auto !important; } + +html.access-high-contrast body.aero-theme { + --bg: #ffffff !important; + --fg: #000000 !important; + --border: #003f68 !important; + --subtle: #243842 !important; + --links: #004f88 !important; +} + +@media (prefers-reduced-motion: reduce) { + body.aero-theme .paper-grain { background-attachment: scroll; } } -body.aero-theme .content-pagination .guestbook-page-btn { border-radius: 7px; } diff --git a/themes/lib/aero/aero.html b/themes/lib/aero/aero.html index 59116af..8101cc3 100644 --- a/themes/lib/aero/aero.html +++ b/themes/lib/aero/aero.html @@ -5,112 +5,28 @@