From bd5a18c75a8211c65fb1b916ea6baf7d9c61312e Mon Sep 17 00:00:00 2001 From: nexalapp <108235158+nexalapp@users.noreply.github.com> Date: Thu, 15 Oct 2026 09:38:21 -0600 Subject: [PATCH] Theme-RoundedYellow: refresh for Stash v0.31 (2.0) Near-black ground, charcoal cards with 20px corners and one warm yellow for everything active. Palette in variables, two radii, yellow-filled primary buttons, the stock blue gone, and styling for the newer parts of Stash, including phone layouts and the Theme Switch menu. Co-Authored-By: Claude Opus 5.5 (1M context) --- themes/Theme-RoundedYellow/README.md | 18 +- .../Theme-RoundedYellow.css | 1357 +++++++++++++++-- .../Theme-RoundedYellow.yml | 2 +- 3 files changed, 1257 insertions(+), 120 deletions(-) diff --git a/themes/Theme-RoundedYellow/README.md b/themes/Theme-RoundedYellow/README.md index b035ce43..53968696 100644 --- a/themes/Theme-RoundedYellow/README.md +++ b/themes/Theme-RoundedYellow/README.md @@ -2,8 +2,18 @@ https://discourse.stashapp.cc/t/rounded-yellow/1431 -A theme with yellow accent colour and rounded corners. +A near-black theme with charcoal cards, large rounded corners and one warm yellow for everything active. Version 2.0 refreshes the theme for Stash v0.31: two radii (6px for controls, 20px for cards, panels, menus and dialogs), the active page in yellow with a yellow underline, yellow-filled primary buttons with dark text, covers that fade into the card above a translucent footer band, bordered toolbar boxes with a yellow-filled active view, yellow toggles and a yellow Settings nav block, and styling for the newer parts of Stash (filter sidebar, selection toolbar, performer header, settings, dialogs). The stock blue no longer shows through. -## Preview -![2024-01-03_14-37-11_blur](https://github.com/Written2001/CommunityScripts/assets/121555133/96932001-4b46-4e97-b4de-5e7cb61608fb) -![2024-01-03_14-37-01_blur](https://github.com/Written2001/CommunityScripts/assets/121555133/e999ae6b-5e53-418c-a561-00c658afba3e) +## Screenshots + +Taken on Stash v0.31.1 with demo content: fictional titles and names, blurred openly licensed photos (credits on the [screenshots branch](https://github.com/nexalapp/CommunityScripts/tree/screenshots)). + +| Scenes | Scene | +|---|---| +| ![Scenes](https://raw.githubusercontent.com/nexalapp/CommunityScripts/02544a82449ea6fc01ca6302f8488ff699a7f8cf/Theme-RoundedYellow/desktop-scenes.jpg) | ![Scene](https://raw.githubusercontent.com/nexalapp/CommunityScripts/02544a82449ea6fc01ca6302f8488ff699a7f8cf/Theme-RoundedYellow/desktop-scene.jpg) | + +| Performer | Studios | +|---|---| +| ![Performer](https://raw.githubusercontent.com/nexalapp/CommunityScripts/02544a82449ea6fc01ca6302f8488ff699a7f8cf/Theme-RoundedYellow/desktop-performer.jpg) | ![Studios](https://raw.githubusercontent.com/nexalapp/CommunityScripts/02544a82449ea6fc01ca6302f8488ff699a7f8cf/Theme-RoundedYellow/desktop-studios.jpg) | + +Scenes on a phone A scene on a phone diff --git a/themes/Theme-RoundedYellow/Theme-RoundedYellow.css b/themes/Theme-RoundedYellow/Theme-RoundedYellow.css index 7a5760f2..81d5c922 100644 --- a/themes/Theme-RoundedYellow/Theme-RoundedYellow.css +++ b/themes/Theme-RoundedYellow/Theme-RoundedYellow.css @@ -1,183 +1,1310 @@ +/* +Rounded Yellow, refreshed for Stash v0.31. +Near-black ground, charcoal cards with large rounded corners, and one warm +yellow for everything active. +*/ + :root { - --bgcol: #101118; - --searchbgcol: #1b1c28; - --btnbordercol: #202b33; - --secbtncol: #171822; - --btnaccentcol: #cfad0b; - --cardbgcol: #1f282c; - --navbarcol: #212529; + --ry-bg: #13141c; /* page, nav */ + --ry-bar: #1b1f24; /* sidebar, menus on phones */ + --ry-card: #1b1f24; /* cards, toolbar boxes, menus */ + --ry-raised: #262a31; /* secondary buttons, hover */ + --ry-line: rgba(255, 255, 255, 0.08); /* every hairline */ + --ry-text: #f3f2ee; + --ry-text-2: #b5b3ad; + --ry-text-3: #8c8a84; + --ry-yellow: #d9a800; /* fills, rings, toggles */ + --ry-yellow-text: #f2c230; /* yellow text, AA on the dark ground */ + --ry-ink: #1a1400; /* text on a yellow fill */ + --ry-danger: #d9363e; + --ry-radius: 6px; /* controls and buttons */ + --ry-radius-sm: 4px; + --ry-radius-card: 20px; /* cards, panels, menus, dialogs */ } body { - background-color: var(--bgcol); + color: var(--ry-text); + background-color: var(--ry-bg); } -.bg-secondary { - background-color: var(--searchbgcol) !important; +.bg-dark { + background-color: var(--ry-bg) !important; } -.pagination .btn:first-child { - border-left: 1px solid var(--btnbordercol); -} -.pagination .btn:last-child { - border-right: 1px solid var(--btnbordercol); +.card { + background-color: var(--ry-card); + border: 1px solid var(--ry-line); + border-radius: var(--ry-radius-card); + box-shadow: none; } -.btn-secondary { - border-color: var(--btnbordercol); - background-color: var(--bgcol); +.bg-secondary { + background-color: var(--ry-card) !important; } -.btn-secondary:disabled { - border-color: var(--btnbordercol); - background-color: var(--secbtncol); +.text-white { + color: var(--ry-text) !important; } -.btn-secondary:not(:disabled):not(.disabled):active, -.btn-secondary:not(:disabled):not(.disabled).active, -.show > .btn-secondary.dropdown-toggle { - background-color: var(--secbtncol); - border: 1px solid var(--btnbordercol); - color: var(--btnaccentcol); - border-bottom: 3px solid var(--btnaccentcol); +.border-secondary { + border-color: var(--ry-line) !important; } -.card { - background-color: var(--cardbgcol); - border-radius: 30px; +.btn-secondary { + color: var(--ry-text); + background-color: var(--ry-card); + border-color: var(--ry-line); } -.progress-indicator { - background-color: var(--btnaccentcol); +.btn-secondary:hover { + color: var(--ry-text); + background-color: var(--ry-raised); + border-color: var(--ry-line); } -.bg-dark { - background-color: var(--navbarcol) !important; +a { + color: var(--ry-text-2); } -.btn.active:not(.disabled), -.btn.active.minimal:not(.disabled) { - background-color: transparent; - color: var(--btnaccentcol); - border-bottom: 3px solid var(--btnaccentcol); +.btn.active { + background-color: var(--ry-raised); + color: var(--ry-yellow-text); } +/* Primary actions: yellow fill with dark text; Delete filled red */ .btn-primary { - background-color: var(--btnaccentcol); - border-color: var(--btnaccentcol); + color: var(--ry-ink); + background-color: var(--ry-yellow); + border-color: var(--ry-yellow); +} + +.btn-primary:hover, +.btn-primary:focus { + color: var(--ry-ink); + background-color: var(--ry-yellow-text); + border-color: var(--ry-yellow-text); } -.btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active, +.btn-primary:not(:disabled):not(.disabled):active, .show > .btn-primary.dropdown-toggle { + color: var(--ry-ink); + background-color: var(--ry-yellow-text); + border-color: var(--ry-yellow-text); +} + +.btn-danger { + color: #fff; + background-color: var(--ry-danger); + border-color: var(--ry-danger); +} + +.nav-tabs { + border-bottom: 1px solid var(--ry-line); +} + +.nav-tabs .nav-link { + outline: 0; + color: var(--ry-text-2); + border: 0; + border-radius: var(--ry-radius-sm) var(--ry-radius-sm) 0 0; +} + +.nav-tabs .nav-link.active, +.nav-tabs .nav-link.active:hover { + color: var(--ry-text); background-color: transparent; - border-color: var(--btnaccentcol); + border-bottom: 2px solid var(--ry-yellow); + outline: 0; } -.btn-primary:not(:disabled):not(.disabled):active:focus, -.btn-primary:not(:disabled):not(.disabled).active:focus, -.show > .btn-primary.dropdown-toggle:focus { - box-shadow: 0 0 0 0; +.btn-primary.btn.donate.minimal { + display: none; } -.btn-primary:focus, -.btn-primary.focus { - background-color: var(--btnaccentcol); - border-color: var(--btnaccentcol); - box-shadow: 0 0 0 0; +.btn-primary.btn.help-button.minimal { + display: none; } -.btn-primary:hover { - color: #fff; - background-color: var(--btnaccentcol); - border-color: var(--btnaccentcol); +.changelog { + display: none; } -div.react-select__menu, -div.dropdown-menu { - background-color: var(--bgcol); - color: #f5f8fa; - z-index: 1600; +.input-control, +.input-control:focus, +.form-control, +.form-control:focus { + color: var(--ry-text); + background-color: var(--ry-card); + border-color: var(--ry-line); } -.modal-header, -.modal-body, -.modal-footer { - background-color: var(--bgcol); - color: #f5f8fa; +#performer-page .image-container .performer { + background-color: rgba(0, 0, 0, 0.45); + box-shadow: 0 0 2px rgba(0, 0, 0, 0.35); } -.edit-filter-dialog .criterion-list .card .filter-item-header:focus { - border-color: var(--btnaccentcol); - border-radius: calc(0.375rem - 1px); - box-shadow: inset 0 0 0 0.1rem var(--btnaccentcol); - outline: 0; +/* Settings: the active item on a yellow block */ +.nav-pills .nav-link { + color: var(--ry-text-2); + border-radius: var(--ry-radius-sm); } -.nav-tabs .nav-link.active { - border-bottom: 2px solid; - color: var(--btnaccentcol); +.nav-pills .nav-link.active, +.nav-pills .show > .nav-link { + color: var(--ry-ink); + background-color: var(--ry-yellow); } -.nav-tabs .nav-link.active:hover { - border-bottom-color: var(--btnaccentcol); - cursor: default; +input[type="range"], +input[type="checkbox"] { + accent-color: var(--ry-yellow); } -.job-table.card { - background-color: var(--bgcol); - height: 10em; - margin-bottom: 30px; - overflow-y: auto; - padding: 0.5rem 15px; +input[type="range"]::-moz-range-track { + background: hsla(0, 0%, 100%, 0.25); +} + +input[type="range"]::-moz-range-thumb { + background: var(--ry-text); +} + +div.react-select__control { + background-color: var(--ry-card); + color: var(--ry-text); + border-color: var(--ry-line); + cursor: pointer; +} + +div.react-select__menu { + background-color: var(--ry-card); +} + +.scene-wall-item-text-container { + background: radial-gradient( + farthest-corner at 50% 50%, + rgba(50, 50, 50, 0.5) 50%, + #323232 100% + ); + color: var(--ry-text); +} + +.btn-link { + font-weight: 500; + color: var(--ry-yellow-text); + text-decoration: none; +} + +/* Top nav: plain labels, the active page in yellow with a yellow underline */ +button.minimal.brand-link.d-none.d-md-inline-block.btn.btn-primary { + color: var(--ry-text); + font-weight: 600; + border: 0; +} + +a.minimal { + font-weight: 500; + color: var(--ry-text); +} + +a:hover { + color: var(--ry-text); +} + +option { + background-color: var(--ry-card); +} + +.scrubber-tags-background { + background-color: var(--ry-raised); +} + +/* Top-right icons: neutral, not the stock blue (or the old green logout) */ +.navbar-buttons .btn.minimal, +.btn-primary.btn.settings-button.minimal, +.btn-primary.btn.logout-button.minimal { + color: var(--ry-text-2); + background-color: transparent; + border-color: transparent; +} + +.scrubber-viewport { + background-color: var(--ry-bar); +} + +/* ---------- Stash v0.29+ refresh ---------- */ + +.navbar { + border-bottom: 1px solid var(--ry-line); +} +.navbar-collapse > .navbar-nav > div > a { + display: flex !important; + flex-direction: row !important; /* stock stacks icon over label */ + align-items: center; + height: 32px; + padding: 0 12px !important; + border-radius: var(--ry-radius); + font-size: 13px; +} +.navbar-collapse > .navbar-nav > div > a.active { + color: var(--ry-yellow-text) !important; + background-color: transparent !important; +} +@media (min-width: 1200px) { + .navbar-collapse > .navbar-nav > div > a { + position: relative; + } + .navbar-collapse > .navbar-nav > div > a.active::after { + content: ""; + position: absolute; + left: 12px; + right: 12px; + bottom: var(--ry-nav-underline, -9px); /* on the bar's bottom edge */ + height: 2px; + background-color: var(--ry-yellow); + } +} +@media (min-width: 1200px) { + .navbar-collapse > .navbar-nav > div > a svg { + display: none !important; /* words only on desktop */ + } +} +.top-nav a[href$="/new"] .btn { + color: var(--ry-ink); + background-color: var(--ry-yellow); + border: 1px solid var(--ry-yellow); + font-weight: 600; +} + +/* List toolbar: dark bordered 34px boxes, light glyphs, yellow-filled active view */ +.filtered-list-toolbar { + background-color: transparent !important; + gap: 8px; +} +.filtered-list-toolbar .btn-group, +.filtered-list-toolbar .sort-by-select { + height: 34px; + background-color: var(--ry-card); + border: 1px solid var(--ry-line); + border-radius: var(--ry-radius); + padding: 2px; + gap: 2px; + align-items: center; +} +.filtered-list-toolbar .btn-group .btn-group { + border: 0; + padding: 0; + height: auto; + background: none; +} +.filtered-list-toolbar .btn-group .btn, +.filtered-list-toolbar .sort-by-select .btn { + height: 28px !important; /* the saved-filter button sits one group deeper */ + padding: 0 9px; + color: var(--ry-text); + border: 0 !important; + border-radius: var(--ry-radius-sm) !important; + background: none !important; + box-shadow: none !important; +} +.filtered-list-toolbar .btn-group .btn:hover { + background-color: var(--ry-raised) !important; +} +.filtered-list-toolbar .btn-group .btn.active { + color: var(--ry-ink) !important; + background-color: var(--ry-yellow) !important; +} +.filtered-list-toolbar .btn-group .btn-danger { + color: #fff !important; + background-color: var(--ry-danger) !important; +} +.filtered-list-toolbar .search-term-input .form-control, +.filtered-list-toolbar .page-size-selector select { + height: 34px; + background-color: var(--ry-card) !important; + border: 1px solid var(--ry-line) !important; + border-radius: var(--ry-radius) !important; +} +.filtered-list-toolbar .page-size-selector select { + color: var(--ry-text); +} +.filtered-list-toolbar.has-selection .selected-items-info span { + color: var(--ry-yellow-text); + font-weight: 600; +} +.item-list-container .filtered-list-toolbar.has-selection { + background-color: var(--ry-bg) !important; + border-bottom: 1px solid var(--ry-line); +} +.sidebar-toggle-button-container .sidebar-toggle-button { + width: 34px; + height: 34px; + padding: 0; + margin-left: 0 !important; /* stock hangs it half off the page */ + color: var(--ry-text); + background-color: var(--ry-card) !important; + border: 1px solid var(--ry-line) !important; + border-radius: var(--ry-radius) !important; + opacity: 1; +} +.sidebar-pane .sidebar, +.sidebar .sidebar-footer, +.sidebar-toolbar { + background-color: var(--ry-bar) !important; +} +.sidebar-pane .sidebar { + border-right: 1px solid var(--ry-line); +} +.zoom-slider { + accent-color: var(--ry-yellow); +} +/* Size slider: yellow track, white thumb (stock is blue) */ +input[type="range"].zoom-slider::-webkit-slider-runnable-track { + height: 4px; + border-radius: 2px; + background: var(--ry-yellow); +} +input[type="range"].zoom-slider::-webkit-slider-thumb { + -webkit-appearance: none; + width: 14px; + height: 14px; + margin-top: -5px; + border: 0; + border-radius: 50%; + background: var(--ry-text) !important; +} +.zoom-slider::-moz-range-track { + height: 4px; + background: var(--ry-yellow) !important; +} +.zoom-slider::-moz-range-thumb { + border: 0; + background: var(--ry-text); +} + +/* Pagination centred, with the result count on the same row; the floating + bottom pagination stays */ +.pagination-index-container { + display: grid; + grid-template-columns: 1fr auto 1fr; + align-items: center; + gap: 12px; + margin-top: 10px; +} +.pagination-index-container > .pagination { + grid-column: 2; + margin: 0 !important; +} +.pagination-index-container > .paginationIndex { + grid-column: 3; + justify-self: end; + margin: 0 !important; + font-size: 13px; + color: var(--ry-text-2); +} +.pagination-index-container > .paginationIndex:only-child { + grid-column: 1 / -1; + justify-self: center; +} +.pagination.btn-group { + background-color: var(--ry-card); + border: 1px solid var(--ry-line); + border-radius: var(--ry-radius); + padding: 2px; + gap: 2px; +} +.pagination .btn, +.pagination .btn:first-child, +.pagination .btn:last-child { + color: var(--ry-text-2); + border: 0 !important; + border-radius: var(--ry-radius-sm) !important; + background: none; +} +.pagination .btn:hover { + color: var(--ry-text); + background-color: var(--ry-raised); +} +.pagination .btn.active, +.pagination .btn:disabled { + color: var(--ry-text); +} +@media (max-width: 575.98px) { + .pagination-index-container { + grid-template-columns: 1fr; + justify-items: center; + } + .pagination-index-container > .pagination, + .pagination-index-container > .paginationIndex { + grid-column: 1; + justify-self: center; + } } -.progress-bar { +/* Cards: hover lifts 2px with a yellow hairline; selection is a 2px yellow + ring; the cover fades into the card above a translucent footer band */ +.grid-card { + overflow: hidden; + border-color: transparent; display: flex; flex-direction: column; - justify-content: center; + padding: 0; + transition: transform 0.2s cubic-bezier(0.2, 0.7, 0.2, 1), box-shadow 0.2s, border-color 0.2s; +} +.grid-card:hover { + transform: translateY(-2px); + border-color: rgba(217, 168, 0, 0.6); + box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5); +} +.grid-card:has(.card-check:checked) { + border-color: var(--ry-yellow); + box-shadow: 0 0 0 1px var(--ry-yellow); +} +.grid-card .thumbnail-section { + position: relative; overflow: hidden; + flex: none; /* never squeezed by the text below it */ +} +.scene-card .thumbnail-section::after, +.gallery-card .thumbnail-section::after, +.group-card .thumbnail-section::after { + content: ""; + position: absolute; + inset: 0; + pointer-events: none; + background: linear-gradient(180deg, transparent 45%, var(--ry-card)); +} +.grid-card .scene-specs-overlay, +.grid-card .studio-overlay, +.grid-card .favorite-button, +.grid-card .card-check { + z-index: 2; +} +.grid-card .card-section { + padding: 12px 14px 12px !important; /* keeps the text off the footer band */ +} +.grid-card .card-section-title { + color: var(--ry-text); + font-size: 16px !important; + font-weight: 500 !important; +} +.scene-card__date, +.performer-card__age { + color: var(--ry-text-3) !important; + font-size: 13px; +} +.scene-card__details { + margin-bottom: 0 !important; +} +.scene-card__description, +.TruncatedText.scene-card__description { + color: var(--ry-text-2); + font-size: 13px; +} +.grid-card .card-popovers { + margin: auto 0 0 !important; + padding: 10px 14px !important; + background-color: rgba(255, 255, 255, 0.03); + border-top: 1px solid var(--ry-line); + justify-content: center !important; + gap: 24px; +} +.grid-card hr { + display: none; +} +.grid-card .card-popovers .btn { + color: var(--ry-text); + border: 0 !important; + background: none !important; + box-shadow: none !important; + padding: 0 !important; +} +.grid-card .card-popovers .btn:hover { + color: var(--ry-yellow-text); +} +.scene-card .scene-specs-overlay { + font-size: 12px !important; + font-weight: 700; color: #fff; - text-align: center; - white-space: nowrap; - background-color: var(--btnaccentcol); - transition: width 0.6s ease; +} +.scene-card .scene-specs-overlay span { + margin: 0 !important; + padding: 0 !important; +} +.scene-card .scene-specs-overlay .overlay-resolution + .overlay-duration::before { + content: "\00a0"; +} +.scene-card .extra-scene-info, +.scene-card .overlay-filesize { + display: none !important; +} +/* Rating ribbon off the cards; the rating stays on the scene page */ +.grid-card .rating-banner { + display: none; +} +.performer-card .performer-card-image { + width: 100% !important; + height: auto !important; + min-width: 0 !important; + max-width: none !important; + max-height: none !important; + aspect-ratio: 2 / 3; + object-fit: cover; + object-position: top; +} +.studio-card .studio-card-header, +.tag-card .tag-card-header { + display: block !important; + position: relative; + aspect-ratio: 16 / 9; + height: auto !important; +} +.studio-card .studio-card-image, +.tag-card .tag-card-image { + position: absolute; + inset: 0; + width: 100% !important; + height: 100% !important; + max-height: none !important; + object-fit: contain; + padding: 10% 12%; } -.grid-card .progress-bar { - background-color: rgba(115, 133, 159, 0.5); - bottom: 5px; +/* Studio chip top-left on the cover */ +.scene-card .studio-overlay { + top: 8px !important; + left: 8px !important; + right: auto !important; + max-width: 60%; + height: auto !important; + padding: 3px 7px; + border-radius: var(--ry-radius-sm); + background-color: rgba(0, 0, 0, 0.55); + opacity: 1; + line-height: 0; +} +.scene-card .studio-overlay a { display: block; - height: 5px; - position: absolute; - width: 100%; + height: auto !important; +} +.scene-card .studio-overlay .image-thumbnail { + height: 18px !important; + max-height: 18px !important; + width: auto; + max-width: 100% !important; + object-fit: contain; } -.grid-card .progress-indicator { - background-color: var(--btnaccentcol); - height: 5px; +/* Card heart: the same size as the select checkbox, mirrored in the + opposite corner */ +.grid-card .favorite-button { + top: 10px !important; + right: 8px !important; + padding: 0 !important; + line-height: 1; +} +.grid-card .favorite-button svg { + width: 17px !important; + height: 17px !important; + font-size: 17px !important; + margin: 0 !important; +} + +/* Home carousels: slides pulled in so the arrows sit inside the page (stock + pushes the next arrow off a phone screen), arrows centred on the cards (not + the cards plus the dots below), every card in a row as tall as the tallest */ +.recommendation-row .slick-slider { + margin: 0 30px; +} +.recommendation-row .slick-prev { + left: -28px; +} +.recommendation-row .slick-next { + right: -28px; +} +.recommendation-row .slick-slider { + margin-bottom: 30px; +} +.recommendation-row .slick-dots { + position: absolute; /* out of the flow, so the slider is exactly the cards' height */ + top: 100%; +} +.recommendation-row .slick-track { + margin-bottom: 0; +} +.recommendation-row .slick-arrow { + top: 0; + height: 100%; + transform: none; + color: var(--ry-yellow-text); +} +.recommendation-row .slick-track { + display: flex !important; +} +.recommendation-row .slick-slide { + height: auto !important; +} +.recommendation-row .slick-slide > div { + height: 100%; +} +.recommendation-row .slick-slide .grid-card { + width: 320px !important; /* studios too, not just scenes and performers */ + height: calc(100% - 10px); + margin-top: 5px; + margin-bottom: 5px; } -.hover-scrubber .hover-scrubber-indicator .hover-scrubber-indicator-marker { - background-color: var(--btnaccentcol); - bottom: 0; - height: 5px; +/* Detail pages: white titles, grey labels */ +.detail-header { + background-color: var(--ry-bg) !important; + border-bottom: 1px solid var(--ry-line); +} +/* Performer page: full-bleed portrait fading into the header */ +.detail-header:has(.performer-head) { + padding: 0 !important; + margin: 0 !important; + width: auto !important; + max-width: none !important; +} +.detail-header:has(.performer-head) .detail-container { + max-width: none; + margin: 0; + padding: 0; + display: flex; + align-items: flex-start; +} +.detail-header:has(.performer-head) .detail-header-image { + position: relative; + flex: 0 0 420px; + width: 420px; + height: 400px; + margin: 0; + padding: 0; + overflow: hidden; +} +.detail-header:has(.performer-head) .detail-header-image .btn-link { + display: block; + width: 100%; + height: 100%; + padding: 0; + border: 0 !important; +} +.detail-header:has(.performer-head) img.performer { + width: 100%; + height: 100%; + max-width: none !important; + max-height: none; + object-fit: cover; + object-position: center top; + border: 0 !important; + border-radius: 0 !important; +} +.detail-header:has(.performer-head) .detail-header-image::after { + content: ""; position: absolute; + inset: 0; + pointer-events: none; + background: linear-gradient(90deg, transparent 55%, var(--ry-bg)); +} +.detail-header:has(.performer-head) > .detail-container > .row { + flex: 1; + min-width: 0; + margin: 0; + padding: 24px 36px 0; +} +.detail-header:has(.performer-head) .performer-head .col, +.detail-header:has(.performer-head) .performer-head .row { + padding: 0 !important; + margin: 0 !important; +} +.detail-header .detail-item { + font-size: 13px; + line-height: 1.4; + margin: 0 !important; + padding: 0 !important; +} +.detail-header .detail-group { + row-gap: 5px; +} +.detail-header .detail-item-title { + width: 130px; +} +@media (max-width: 767.98px) { + .detail-header:has(.performer-head) .detail-container { + flex-direction: column; + } + .detail-header:has(.performer-head) .detail-header-image { + flex-basis: auto; + width: 100%; + height: 430px; + } + .detail-header:has(.performer-head) .detail-header-image::after { + background: linear-gradient(180deg, transparent 55%, var(--ry-bg)); + } + .detail-header:has(.performer-head) > .detail-container > .row { + padding: 14px; + } +} +.detail-header .performer-name, +.detail-header .studio-name, +.detail-header h2 { + color: var(--ry-text); + font-size: 40px; + font-weight: 500; +} +.detail-header .detail-item-title { + color: var(--ry-text-3); +} +.detail-header .detail-item-value { + color: var(--ry-text); +} +.details-edit { + gap: 8px; +} +.details-edit .btn { + margin: 0 !important; +} +.details-edit .btn-secondary { + color: var(--ry-text); + background-color: var(--ry-raised); + border-color: var(--ry-raised); +} +.details-edit .btn-primary, +.details-edit .edit { + color: var(--ry-ink); + background-color: var(--ry-yellow); + border-color: var(--ry-yellow); +} + +/* Scene page */ +.scene-tabs .scene-header, +.scene-tabs .scene-header .TruncatedText { + color: var(--ry-text); + font-size: 32px !important; + font-weight: 500; + line-height: 1.15; +} +/* Scene details: white labels and headings, yellow links, grey paragraphs */ +.scene-tabs .tab-content h6 { + color: var(--ry-text); + font-size: 13px; +} +.scene-tabs .tab-content h6 a { + color: var(--ry-yellow-text); +} +.scene-tabs .tab-content p.pre { + color: var(--ry-text-2); + font-size: 13px; +} +.tag-item.badge-secondary { + color: var(--ry-text); + background-color: var(--ry-raised); + border: 1px solid var(--ry-line); +} +.nav-tabs .badge, +.badge-pill.badge-secondary { + color: var(--ry-text); + background-color: var(--ry-raised); +} +.tag-item.badge-secondary a { + color: inherit; +} +.video-js .vjs-play-progress, +.video-js .vjs-volume-level { + background-color: var(--ry-yellow); +} +.video-js .vjs-big-play-button { + width: 72px !important; + height: 72px !important; + margin-left: -36px !important; + margin-top: -36px !important; + font-size: 36px !important; + line-height: 72px !important; + border: 0 !important; + border-radius: 50% !important; + background-color: rgba(40, 40, 40, 0.85) !important; +} +.video-js:hover .vjs-big-play-button { + color: var(--ry-ink) !important; + background-color: var(--ry-yellow) !important; +} +.video-js .vjs-big-play-button .vjs-icon-placeholder::before { + font-size: 36px !important; + line-height: 72px !important; + width: 100% !important; + height: 100% !important; + text-indent: 3px; +} +.scrubber-button { + color: var(--ry-yellow-text) !important; + background-color: var(--ry-card) !important; + border: 1px solid var(--ry-line) !important; +} +/* Two performers side by side in the details panel */ +.scene-performers .performer-card { + width: calc(50% - 10px) !important; + margin: 5px !important; +} + +/* Settings: white headings, yellow toggles */ +#settings-container h1, +#tasks-panel h1, +.setting-section h1 { + color: var(--ry-text); + font-size: 28px; + font-weight: 500; +} +.setting-section .setting h3, +.setting-section > h2 { + color: var(--ry-text); +} +.custom-switch .custom-control-input:checked ~ .custom-control-label::before { + background-color: var(--ry-yellow); + border-color: var(--ry-yellow); } +/* Dialogs and menus on the card tone */ +.modal-content, +.dropdown-menu { + background-color: var(--ry-card); + border: 1px solid var(--ry-line); + border-radius: var(--ry-radius-card); +} +.dropdown-menu { + padding: 6px; + box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5); +} +.dropdown-item { + border-radius: var(--ry-radius); +} +.modal-header { + border-bottom: 1px solid var(--ry-line); + color: var(--ry-text); +} +.modal-footer { + border-top: 1px solid var(--ry-line); +} +.modal-footer .btn-primary { + color: var(--ry-ink); + background-color: var(--ry-yellow); + border-color: var(--ry-yellow); +} +.dropdown-item { + color: var(--ry-text); +} +.dropdown-item:hover, +.dropdown-item.active { + color: var(--ry-text); + background-color: var(--ry-raised); +} + +/* Theme Switch menu: its sections are spaced apart, so keep the full outline + that Bootstrap's accordion style strips from all but the last */ +.theme-plugin-menu .accordion > .card { + border-bottom: 1px solid var(--ry-line) !important; + border-radius: var(--ry-radius) !important; +} + +/* Empty lists */ +.item-list-container .sidebar-pane-content:not(:has(.grid-card, .table-list, .scene-wall, .wall, .tagger-container, .card)) > .pagination-index-container::after { + content: "Nothing here yet"; + grid-column: 1 / -1; + margin-top: 18vh; + text-align: center; + font-size: 26px; + font-weight: 500; + color: var(--ry-text-2); +} + +/* Task queue and job cards: off the stock blue-grey */ #tasks-panel .tasks-panel-queue { - background-color: var(--bgcol); - margin-top: -1rem; - padding-bottom: 0.25rem; - padding-top: 1rem; - position: sticky; - top: 3rem; - z-index: 2; + background-color: var(--ry-bg) !important; +} +.job-table.card { + background-color: var(--ry-card) !important; + border: 1px solid var(--ry-line); +} +/* Settings buttons are secondary; the scene-page panel toggle keeps the theme */ +#settings-container .btn-primary { + color: var(--ry-text); + background-color: var(--ry-raised); + border-color: var(--ry-raised); +} +.scene-divider .btn { + color: var(--ry-text-2); + background: none; + border: 0; } -#scene-edit-details .edit-buttons-container { - background-color: var(--bgcol); - position: sticky; - top: 0; - z-index: 3; +/* Home carousels: whole cards only. The number of cards that fits at about + 320px, sized to fill the row exactly, so none is cut off at the edge */ +.recommendation-row .slick-list { + container-type: inline-size; +} +.recommendation-row .slick-slide .grid-card { + width: calc(100cqw / max(1, round(100cqw / 330px, 1)) - 10px) !important; + max-width: none !important; +} + +/* Detail-page tab bars: Stash pads them below, which lifts the active + underline off the bar's line */ +.nav-tabs { + padding-bottom: 0 !important; +} + +/* The slim header Stash pins when a detail page scrolls slides down only as + the full header's bottom edge passes under the top bar, instead of + appearing as soon as the page moves. It follows the scroll position, so + scrolling back up reverses it; browsers without scroll-driven animations + show it as Stash does. */ +@supports (animation-timeline: view()) { + .main { + timeline-scope: --detail-header; + } + .detail-header:not(.sticky) { + view-timeline: --detail-header block; + } + .detail-header.sticky { + animation: detail-header-sticky-in linear both; + animation-timeline: --detail-header; + animation-range: exit calc(100% - 130px) exit calc(100% - 50px); + } + @keyframes detail-header-sticky-in { + from { + transform: translateY(-100%); + opacity: 0; + visibility: hidden; + } + to { + transform: none; + opacity: 1; + visibility: visible; + } + } +} + +/* Filter sidebar on small screens. Stash slides it over the page below 768px, + covering the button that closes it. Phones get a full-screen sheet whose + "Show N results" button is the way out; small tablets get the desktop + layout, the content pushed aside to a single column. */ +@media (max-width: 575.98px) { + .sidebar-pane:not(.hide-sidebar) { + z-index: 1020; /* above the performer header, which is its own layer */ + } + .sidebar-pane:not(.hide-sidebar) > .sidebar { + position: fixed !important; + top: 0 !important; + left: 0 !important; + right: 0 !important; + bottom: auto !important; + width: 100% !important; + max-width: none !important; + height: calc(100dvh - 46px) !important; /* down to the bottom bar */ + max-height: none !important; + flex: none !important; + margin: 0 !important; + padding: 12px 15px 0 !important; + display: flex !important; + flex-direction: column; + z-index: 1020; + background-color: var(--ry-bar) !important; + } + .sidebar-pane:not(.hide-sidebar) > .sidebar .sidebar-footer { + margin-top: auto; + bottom: 0; + left: 0 !important; + width: 100% !important; + padding: 12px 0 15px !important; + background: none !important; + border-top: 0 !important; + } + .sidebar-pane:not(.hide-sidebar) > .sidebar .sidebar-footer .btn { + width: 100%; + height: 44px; + } +} +@media (min-width: 576px) and (max-width: 767.98px) { + .sidebar-pane:not(.hide-sidebar) > .sidebar-pane-content { + margin-left: 235px; + } + .sidebar-pane:not(.hide-sidebar) .sidebar-toggle-button-container { + left: 257px; + } + .sidebar-pane:not(.hide-sidebar) .grid-card { + width: calc(100% - 30px) !important; /* one column beside the filters */ + } +} + +/* Detail fields on phones: the label above its value, so long values like a + Stash ID get the full width; an ID that still doesn't fit ends in an + ellipsis (the link opens the full ID) */ +@media (max-width: 575.98px) { + .detail-header .detail-item { + display: block !important; + } + .detail-header .detail-item-title { + display: block; + width: auto !important; + margin-bottom: 1px; + } + .detail-header > .detail-container > .row { + align-self: stretch; + max-width: 100%; + } + .detail-header .performer-head, + .detail-header .detail-group { + min-width: 0; + max-width: 100%; + } +} +.stash-id-pill { + display: inline-flex !important; + max-width: 100%; + min-width: 0; +} +.stash-id-pill span { + flex: none; +} +.stash-id-pill a { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.detail-item-value.stash-ids, +.detail-item-value.stash-ids ul, +.detail-item-value.stash-ids li { + display: block; + max-width: 100%; + min-width: 0; + margin: 0; +} +.detail-item-value.stash-ids { + overflow: hidden; +} + +/* Dialog panels on the dialog's own colour, not Stash's slate */ +.modal-content { + background-color: var(--ry-card) !important; +} +.modal-header, +.modal-body, +.modal-footer { + background: transparent !important; +} + +/* Phones: dialogs (Edit filter and the rest) fill the screen down to the + bottom bar; the body scrolls and the buttons stay at the foot */ +@media (max-width: 575.98px) { + .modal-dialog { + max-width: none !important; + width: 100% !important; + margin: 0 !important; + height: calc(100dvh - 46px); + } + .modal-content { + height: 100%; + border-radius: 0 !important; + border: 0 !important; + background-color: var(--ry-card) !important; + } + .modal-body { + flex: 1; + max-height: none !important; /* Stash caps it at a fixed height */ + overflow-y: auto; + } + .modal-footer { + flex-wrap: nowrap; + } +} + +/* Phone and tablet menu (the ☰ button): an even grid of tiles, small icon + above its label, the current page on a soft tile, utility icons in a row + beneath a hairline (stock crams large icons beside the words) */ +@media (max-width: 1199.98px) { + .navbar-collapse.show, + .navbar-collapse.collapsing { + background-color: var(--ry-bar) !important; + border-top: 1px solid var(--ry-line); + padding: 10px 24px 6px !important; + margin: 0 -14px; /* edge to edge across the bar's padding */ + } + .navbar-collapse > .navbar-nav:first-child { + display: grid !important; + grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); /* 3 across on phones */ + gap: 6px; + } + .navbar-collapse > .navbar-nav:first-child > div { + max-width: none !important; + flex: none !important; + width: auto !important; + padding: 0 !important; + } + .navbar-collapse > .navbar-nav > div > a { + display: flex !important; + flex-direction: column !important; + align-items: center !important; + justify-content: center !important; + gap: 6px; + height: 64px !important; + padding: 6px !important; + color: var(--ry-text) !important; + background: none !important; + border: 0 !important; + border-radius: 8px !important; + box-shadow: none !important; + font-size: 12px; + font-weight: 600; + text-transform: none; + } + .navbar-collapse > .navbar-nav > div > a svg { + display: block !important; + width: 20px !important; + height: 20px !important; + font-size: 20px !important; + margin: 0 !important; + color: var(--ry-text-2); + } + .navbar-collapse > .navbar-nav > div > a.active { + color: var(--ry-yellow-text) !important; + background-color: var(--ry-raised) !important; + } + .navbar-collapse > .navbar-nav > div > a.active svg { + color: var(--ry-yellow-text); + } + .navbar-collapse > .navbar-nav:not(:first-child) { + justify-content: center; + gap: 8px; + margin-top: 8px; + padding-top: 6px; + border-top: 1px solid var(--ry-line); + } + .navbar-collapse .nav-utility svg { + width: 18px !important; + height: 18px !important; + } +} + +/* Phones: the list toolbar on two rows. The space for the filter button is + kept on the first row only (search stretches beside it, then the + saved-filter and filter buttons); the rest slims down to share row two. */ +@media (max-width: 575.98px) { + .filtered-list-toolbar { + margin-left: 0 !important; + margin-right: 0 !important; /* stock keeps 40px each side */ + justify-content: flex-start !important; + gap: 8px 6px !important; + } + .filtered-list-toolbar > .search-term-input { + margin-left: 40px !important; + flex: 1 1 0 !important; + min-width: 0 !important; + width: auto !important; + } + .filtered-list-toolbar > .search-term-input .form-control { + width: 100% !important; + min-width: 0 !important; + } + .filtered-list-toolbar .sort-by-select .btn { + padding: 0 6px !important; + } + .filtered-list-toolbar > .page-size-selector, + .filtered-list-toolbar > .page-size-selector select { + width: 56px !important; + min-width: 0 !important; + } + .filtered-list-toolbar .btn-group:not(.pagination) .btn { + padding: 0 6px !important; + } + .filtered-list-toolbar > .btn-group:last-of-type { + margin-left: auto; /* the view buttons close the second row on the right */ + } + /* row 1: search + the filter buttons; a zero-height break; row 2: the rest */ + .filtered-list-toolbar > * { + order: 3; + } + .filtered-list-toolbar > .search-term-input, + .filtered-list-toolbar > .search-term-input + .btn-group { + order: 1; + } + .filtered-list-toolbar::after { + content: ""; + order: 2; + flex-basis: 100%; + height: 0; + } +} + +/* The phone menu button wears the same colour as the nav icons beside it */ +.top-nav .nav-menu-toggle, +.top-nav .nav-menu-toggle:hover, +.top-nav .nav-menu-toggle:focus { + color: var(--ry-text-2); +} + +/* Theme Switch menu: solid, on the theme's menu colours (stock leaves its + sections on Bootstrap's slate, and see-through over the cards) */ +.theme-plugin-menu.dropdown-menu { + padding: 6px !important; + color: var(--ry-text); + background: var(--ry-card) !important; + border: 1px solid var(--ry-line) !important; + border-radius: var(--ry-radius-card) !important; + box-shadow: 0 16px 40px rgba(0, 0, 0, 0.45) !important; +} +.theme-plugin-menu .accordion { + max-width: none !important; +} +.theme-plugin-menu .modal-header { + margin: 0 0 6px; + padding: 6px 8px 10px !important; + color: var(--ry-text) !important; + background: none !important; + border: 0 !important; + border-bottom: 1px solid var(--ry-line) !important; + border-radius: 0 !important; + font-size: 14px; + font-weight: 600; + text-shadow: none; +} +.theme-plugin-menu .accordion > .card { + margin: 0 0 4px !important; + color: var(--ry-text) !important; + background: rgba(255, 255, 255, 0.04) !important; + border: 1px solid var(--ry-line) !important; + border-radius: var(--ry-radius) !important; + box-shadow: none !important; + backdrop-filter: none !important; +} +.theme-plugin-menu .card-header, +.theme-plugin-menu .card-body { + color: var(--ry-text) !important; + background: none !important; + border: 0 !important; + text-shadow: none; +} +.theme-plugin-menu .card-header { + cursor: pointer; +} +.theme-plugin-menu .card-header svg { + color: var(--ry-text-2); +} +.theme-plugin-menu legend { + color: var(--ry-text) !important; +} +.theme-plugin-menu .checkbox-switch input + label::before { + color: var(--ry-text-2) !important; + background: color-mix(in srgb, var(--ry-text-2) 30%, transparent) !important; + border-color: transparent !important; +} +.theme-plugin-menu .checkbox-switch input:checked + label::before { + color: #fff !important; + background: var(--ry-yellow) !important; + border-color: var(--ry-yellow) !important; +} +/* A blurred bar turns everything drawn inside it see-through, the open + menu included: while the menu is open the bar drops its blur */ +.top-nav:has(.theme-plugin-menu.show) { + backdrop-filter: none !important; + -webkit-backdrop-filter: none !important; } diff --git a/themes/Theme-RoundedYellow/Theme-RoundedYellow.yml b/themes/Theme-RoundedYellow/Theme-RoundedYellow.yml index 660a84e3..48b347e9 100644 --- a/themes/Theme-RoundedYellow/Theme-RoundedYellow.yml +++ b/themes/Theme-RoundedYellow/Theme-RoundedYellow.yml @@ -1,6 +1,6 @@ name: Theme - Rounded Yellow description: Theme with rounded corners and yellow accents -version: 1.0 +version: 2.0 url: https://discourse.stashapp.cc/t/rounded-yellow/1431 ui: css: