From f58545aa62a4a37ab68c97b8e6329ad866753d6e Mon Sep 17 00:00:00 2001
From: nexalapp <108235158+nexalapp@users.noreply.github.com>
Date: Thu, 15 Oct 2026 14:46:19 -0600
Subject: [PATCH] Theme-Minimal: refresh for Stash v0.31 (0.3.0)
---
themes/Theme-Minimal/README.md | 28 ++++
themes/Theme-Minimal/Theme-Minimal.yml | 2 +-
themes/Theme-Minimal/_theme.css | 4 +-
themes/Theme-Minimal/inputs.css | 158 +++++++++++++++++-
themes/Theme-Minimal/modal.css | 25 +++
themes/Theme-Minimal/nav-bar.css | 220 +++++++++++++++++++++++++
themes/Theme-Minimal/player.css | 53 +++++-
themes/Theme-Minimal/scenes.css | 87 ++++++++--
themes/Theme-Minimal/settings.css | 10 ++
themes/Theme-Minimal/shared.css | 73 ++++++++
themes/Theme-Minimal/studio.css | 191 ++++++++++++++++++++-
11 files changed, 816 insertions(+), 35 deletions(-)
diff --git a/themes/Theme-Minimal/README.md b/themes/Theme-Minimal/README.md
index 5f76c9ab..4002bc2c 100644
--- a/themes/Theme-Minimal/README.md
+++ b/themes/Theme-Minimal/README.md
@@ -12,6 +12,22 @@ For intended experience:
## Screenshots
+### Version 0.3.0
+
+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 |
+|---|---|
+|  |  |
+
+| Performer | Studios |
+|---|---|
+|  |  |
+
+
+
+### Version 0.1
+
@@ -19,6 +35,18 @@ For intended experience:
## Changelog
+### Version 0.3.0 - 2026-10-03
+
+- Refresh for Stash v0.29+: the list toolbar (its old `.scene-list-toolbar` selector no longer matches), filter drawer and sticky pagination.
+- Toolbar controls share a 34px hit area; pagination is centred with the result count beside it; the duplicate bottom pagination is hidden.
+- Resolution and duration share one chip; studio logo chip top-left; card spacing and caption inset on one 12px rhythm; studio and tag logos on a soft 16:9 tile.
+- Card counts are plain icon + number, aligned with the title.
+- Hover lifts the card on a soft shadow; selection is a 2px light ring.
+- One light primary action per screen; secondary actions are quiet grey pills.
+- Menu shows words only; scene title at 34px; full-bleed performer portrait with a 40px name and a tight field list.
+- Filter drawer one step lighter than the page; its toggle no longer sits half off the edge.
+- Meta text greys lifted so small text passes WCAG AA.
+
### Version 0.2.7 - 2025-04-07
- Theme studio rating for real.
- Remove card hover.
diff --git a/themes/Theme-Minimal/Theme-Minimal.yml b/themes/Theme-Minimal/Theme-Minimal.yml
index 2cac4fef..3d009141 100644
--- a/themes/Theme-Minimal/Theme-Minimal.yml
+++ b/themes/Theme-Minimal/Theme-Minimal.yml
@@ -1,6 +1,6 @@
name: Theme - Minimal
description: Minimal Theme for Stash
-version: 0.2.8
+version: 0.3.0
url: https://discourse.stashapp.cc/t/minimal/1421
ui:
css:
diff --git a/themes/Theme-Minimal/_theme.css b/themes/Theme-Minimal/_theme.css
index d453d36a..25c3fe19 100644
--- a/themes/Theme-Minimal/_theme.css
+++ b/themes/Theme-Minimal/_theme.css
@@ -74,8 +74,8 @@
--primary-6: #3c393f;
--primary-7: #49474e;
--primary-8: #625f69;
- --primary-9: #6f6d78;
- --primary-10: #7c7a85;
+ --primary-9: #78767f; /* lifted from #6f6d78 */
+ --primary-10: #8a8892; /* lifted from #7c7a85: meta text passes AA on --primary-1 */
--primary-11: #b5b2bc;
--primary-12: #eeeef0;
--primary-a1: #00000000;
diff --git a/themes/Theme-Minimal/inputs.css b/themes/Theme-Minimal/inputs.css
index 08a1a181..95753c18 100644
--- a/themes/Theme-Minimal/inputs.css
+++ b/themes/Theme-Minimal/inputs.css
@@ -24,13 +24,16 @@
}
}
-.btn-primary {
- background-color: var(--primary-6);
+.btn-primary:not(.minimal) {
+ background-color: var(--primary-12);
border: 0;
- color: var(--primary-12);
+ border-radius: 10px;
+ color: var(--primary-1);
+ font-weight: 600;
&:hover {
- background-color: var(--primary-7);
+ background-color: var(--primary-11);
+ color: var(--primary-1);
}
&:disabled {
@@ -42,6 +45,7 @@
.btn-danger {
background-color: var(--danger-6);
border: 0;
+ border-radius: 10px;
color: var(--danger-12);
&:hover {
@@ -444,16 +448,77 @@ div.react-datepicker {
font-size: var(--text-xs);
}
+/* pagination centred with the count on the same row, at the right */
+.pagination-index-container {
+ display: grid;
+ grid-template-columns: 1fr auto 1fr;
+ align-items: center;
+ gap: 12px;
+ margin-top: 10px;
+ padding: 0 16px;
+
+ & > .pagination {
+ grid-column: 2;
+ margin: 0 !important;
+ }
+ & > .paginationIndex {
+ grid-column: 3;
+ justify-self: end;
+ margin: 0 !important;
+ }
+ & > .paginationIndex:only-child {
+ grid-column: 1 / -1;
+ justify-self: center;
+ }
+}
+@media (max-width: 575.98px) {
+ .pagination-index-container {
+ grid-template-columns: 1fr;
+ justify-items: center;
+ & > .pagination,
+ & > .paginationIndex {
+ grid-column: 1;
+ justify-self: center;
+ }
+ }
+}
+/* the floating copy at the bottom stays, on the page ground */
+.pagination-footer-container .pagination {
+ background-color: var(--primary-1);
+}
+
/* scene list toolbar and sidebar backgrounds */
+/* the filter drawer sits one step lighter than the page, with a hairline edge */
+.sidebar-pane .sidebar,
+.sidebar .sidebar-footer,
+.sidebar-toolbar {
+ background-color: var(--primary-2) !important;
+}
.sidebar-pane .sidebar {
- background-color: var(--primary-1) !important;
- border-right: var(--primary-1) !important;
+ border-right: 1px solid var(--white-a1) !important;
}
-.scene-list-toolbar.filtered-list-toolbar {
+.filtered-list-toolbar {
background-color: var(--primary-1) !important;
}
+/* every toolbar control shares a 34px hit area, so the bare row lines up */
+.filtered-list-toolbar {
+ gap: 8px;
+ .btn,
+ .form-control,
+ .page-size-selector select {
+ height: 34px;
+ border-radius: 10px;
+ }
+ .btn-group .btn {
+ border-radius: 8px !important;
+ }
+ .btn-secondary.active {
+ background-color: var(--primary-3) !important;
+ }
+}
+
.list-results-header {
background-color: var(--primary-1) !important;
}
@@ -512,3 +577,82 @@ input[type="range"]::-webkit-slider-thumb {
color: var(--primary-10);
}
}
+
+/* toolbar: bare text and icons at 13px; the sidebar toggle is a bare icon */
+.filtered-list-toolbar {
+ .btn,
+ .form-control,
+ select {
+ font-size: 13px;
+ }
+ .search-term-input .form-control {
+ background-color: transparent;
+ border: 0;
+ }
+}
+.sidebar-toggle-button-container .sidebar-toggle-button {
+ width: 34px;
+ height: 34px;
+ padding: 0;
+ border: 0 !important;
+ border-radius: 10px;
+ background-color: transparent !important;
+ color: var(--primary-11) !important;
+ opacity: 1;
+ margin-left: 0 !important; /* stock pulls it 15px left, half off the page */
+ &:hover {
+ background-color: var(--primary-3) !important;
+ }
+}
+
+/* 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(--primary-2) !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 */
+ }
+}
diff --git a/themes/Theme-Minimal/modal.css b/themes/Theme-Minimal/modal.css
index fe465f62..462968b9 100644
--- a/themes/Theme-Minimal/modal.css
+++ b/themes/Theme-Minimal/modal.css
@@ -11,3 +11,28 @@
background-color: var(--primary-2);
border-top: unset;
}
+
+/* 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(--primary-2) !important;
+ }
+ .modal-body {
+ flex: 1;
+ max-height: none !important; /* Stash caps it at a fixed height */
+ overflow-y: auto;
+ }
+ .modal-footer {
+ flex-wrap: nowrap;
+ }
+}
diff --git a/themes/Theme-Minimal/nav-bar.css b/themes/Theme-Minimal/nav-bar.css
index e98e1bae..a3c91640 100644
--- a/themes/Theme-Minimal/nav-bar.css
+++ b/themes/Theme-Minimal/nav-bar.css
@@ -38,6 +38,27 @@
.navbar-brand {
font-size: inherit;
+ .brand-link {
+ font-size: 17px;
+ font-weight: 600;
+ color: var(--primary-12);
+ }
+ }
+
+ /* desktop menu: words only, the active page lit */
+ @media (min-width: 1200px) {
+ .navbar-nav .nav-link > a.btn {
+ font-size: 13px;
+ font-weight: 500;
+ padding: 6px 12px !important;
+ border-radius: 10px;
+ .nav-menu-icon {
+ display: none !important; /* stock uses d-xl-inline, which is !important */
+ }
+ &.active {
+ background-color: var(--primary-3) !important;
+ }
+ }
}
.navbar-collapse {
@@ -63,3 +84,202 @@
color: var(--primary-11);
}
}
+
+/* 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(--primary-2) !important;
+ border-top: 1px solid var(--white-a2);
+ 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(--primary-12) !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(--primary-11);
+ }
+ .navbar-collapse > .navbar-nav > div > a.active {
+ color: var(--primary-12) !important;
+ background-color: var(--primary-4) !important;
+ }
+ .navbar-collapse > .navbar-nav > div > a.active svg {
+ color: var(--primary-12);
+ }
+ .navbar-collapse > .navbar-nav:not(:first-child) {
+ justify-content: center;
+ gap: 8px;
+ margin-top: 8px;
+ padding-top: 6px;
+ border-top: 1px solid var(--white-a2);
+ }
+ .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: rgb(120, 118, 127);
+}
+
+/* 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(--primary-12);
+ background: var(--primary-2) !important;
+ border: 1px solid var(--primary-6) !important;
+ border-radius: 8px !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(--primary-12) !important;
+ background: none !important;
+ border: 0 !important;
+ border-bottom: 1px solid var(--primary-6) !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(--primary-12) !important;
+ background: var(--primary-3) !important;
+ border: 1px solid var(--primary-6) !important;
+ border-radius: 6px !important;
+ box-shadow: none !important;
+ backdrop-filter: none !important;
+}
+.theme-plugin-menu .card-header,
+.theme-plugin-menu .card-body {
+ color: var(--primary-12) !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(--primary-11);
+}
+.theme-plugin-menu legend {
+ color: var(--primary-12) !important;
+}
+.theme-plugin-menu .checkbox-switch input + label::before {
+ color: var(--primary-11) !important;
+ background: color-mix(in srgb, var(--primary-11) 30%, transparent) !important;
+ border-color: transparent !important;
+}
+.theme-plugin-menu .checkbox-switch input:checked + label::before {
+ color: #fff !important;
+ background: var(--primary-11) !important;
+ border-color: var(--primary-11) !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;
+}
+
+/* Phones: the bar sits at the top, so the performer header no longer tucks
+ up under it */
+@media (max-width: 575.98px) {
+ .detail-header.full-width {
+ margin-top: 0 !important;
+ }
+}
diff --git a/themes/Theme-Minimal/player.css b/themes/Theme-Minimal/player.css
index 0adb228e..3d220545 100644
--- a/themes/Theme-Minimal/player.css
+++ b/themes/Theme-Minimal/player.css
@@ -1,5 +1,6 @@
-.scrubber-button:not(:hover) {
+.scrubber-button {
background-color: unset !important;
+ color: var(--primary-11) !important;
}
.scene-tabs {
@@ -16,6 +17,13 @@
min-width: unset !important;
}
+ .scene-header,
+ .scene-header .TruncatedText {
+ font-size: 34px !important;
+ font-weight: 500;
+ line-height: 1.1;
+ }
+
.scene-subheader {
span {
font-size: 0.8rem !important;
@@ -27,17 +35,18 @@
.nav {
margin-bottom: 24px;
margin-top: 32px;
- row-gap: 8px;
- column-gap: 8px;
+ row-gap: 6px;
+ column-gap: 2px;
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(6rem, 1fr));
+ display: flex;
+ flex-wrap: wrap;
.nav-link {
text-align: center;
color: var(--primary-11) !important;
background-color: unset;
- padding: 12px 1rem;
+ padding: 7px 10px;
+ font-size: var(--text-sm);
border: 0 !important;
border-radius: 8px !important;
line-height: 1;
@@ -50,7 +59,7 @@
}
&.active {
- background-color: var(--primary-2) !important;
+ background-color: var(--primary-3) !important;
color: var(--primary-12) !important;
font-weight: 600;
}
@@ -181,7 +190,8 @@
}
.scene-divider button {
- color: var(--primary-10);
+ background-color: unset !important;
+ color: var(--primary-10) !important;
}
.scene-player-container {
@@ -189,7 +199,7 @@
}
.video-js {
- border-radius: 8px;
+ border-radius: 12px;
overflow: hidden;
font-family: unset;
@@ -274,3 +284,28 @@
transition: none;
}
}
+
+/* big play button: a soft circle, the icon centred in it */
+.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(255, 255, 255, 0.14) !important;
+ backdrop-filter: blur(6px);
+}
+.video-js:hover .vjs-big-play-button {
+ background-color: rgba(255, 255, 255, 0.24) !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;
+}
+
diff --git a/themes/Theme-Minimal/scenes.css b/themes/Theme-Minimal/scenes.css
index ded10b9d..14eac91f 100644
--- a/themes/Theme-Minimal/scenes.css
+++ b/themes/Theme-Minimal/scenes.css
@@ -5,9 +5,18 @@
box-shadow: none;
border: none;
- margin: 8px;
+ margin: 6px; /* 12px between cards */
- border-radius: 10px;
+ border-radius: 12px;
+ transition: transform 0.2s cubic-bezier(0.2, 0.7, 0.2, 1), box-shadow 0.2s;
+
+ &.grid-card:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 14px 34px rgba(0, 0, 0, 0.55);
+ }
+ &.grid-card:has(.card-check:checked) {
+ box-shadow: 0 0 0 2px var(--primary-12);
+ }
a .card-section-title {
color: unset;
@@ -58,14 +67,35 @@
}
}
+ /* studio and tag logos sit in the same 16:9 box, so every card in a row
+ comes out the same height */
+ a.studio-card-header,
+ a.tag-card-header {
+ display: block;
+ position: relative;
+ aspect-ratio: 16 / 9;
+ height: auto;
+ border-radius: 12px;
+ background-color: var(--primary-2);
+
+ img {
+ position: absolute;
+ inset: 0;
+ width: 100% !important;
+ height: 100% !important;
+ max-height: none;
+ object-fit: contain;
+ padding: 10% 12%;
+ }
+ }
+
.scene-card-preview {
margin-bottom: 0;
}
.studio-overlay,
.rating-banner,
- .overlay-resolution,
- .overlay-duration {
+ .scene-specs-overlay {
height: auto;
background-color: var(--black-a7);
@@ -85,7 +115,8 @@
.studio-overlay {
--image-size: 4rem;
- right: 0;
+ left: 0;
+ right: auto;
top: 0;
height: unset;
@@ -127,6 +158,7 @@
}
.rating-banner {
+ display: none; /* the rating lives on the scene page */
transform: none;
left: 0;
top: 0;
@@ -185,14 +217,30 @@
}
}
+ /* resolution and duration share one chip, bottom right */
.scene-specs-overlay {
- left: 0;
+ left: auto;
right: 0;
bottom: 0;
+ padding: 4px 9px;
display: flex !important;
- justify-content: space-between;
align-items: center;
+ font-size: 11px;
+
+ span {
+ margin: 0 !important;
+ padding: 0 !important;
+ font-size: inherit !important;
+ font-weight: 600;
+ text-shadow: none;
+ }
+ .overlay-resolution + .overlay-duration::before {
+ content: "\00a0·\00a0";
+ }
+ .overlay-filesize {
+ display: none;
+ }
}
.preview-scrubber {
@@ -222,9 +270,11 @@
.card-section {
margin-bottom: 0;
- padding: 1rem 0.75rem 0 0.75rem;
+ padding: 12px 12px 6px;
.card-section-title {
- font-size: var(--text-base);
+ font-size: 17px;
+ font-weight: 500;
+ line-height: 1.25;
color: var(--primary-12);
}
@@ -257,14 +307,25 @@
display: flex;
flex-wrap: wrap;
justify-content: start;
- margin-top: 10px;
- margin-bottom: 10px;
+ gap: 22px;
+ margin: 4px 12px 10px;
+ /* plain icon + number, as in the designs: no button box, so the first
+ icon lines up with the title and nothing spills past the card */
.btn {
- padding-bottom: 3px;
- padding-top: 3px;
+ padding: 3px 0;
+ background-color: transparent !important;
color: var(--primary-11);
font-size: var(--text-xs);
+
+ &:hover,
+ &:focus {
+ background-color: transparent !important;
+ color: var(--primary-12);
+ }
+ svg {
+ margin-left: 0;
+ }
}
}
}
diff --git a/themes/Theme-Minimal/settings.css b/themes/Theme-Minimal/settings.css
index 588c41a1..c14ea4de 100644
--- a/themes/Theme-Minimal/settings.css
+++ b/themes/Theme-Minimal/settings.css
@@ -75,3 +75,13 @@
border-bottom: 0 !important;
}
}
+
+/* section titles at page size; settings stay card-less */
+#settings-container h1,
+#settings-container .setting-section > h1,
+#tasks-panel h1 {
+ font-size: 28px;
+ font-weight: 500;
+ line-height: 1;
+ margin: 24px 0 14px;
+}
diff --git a/themes/Theme-Minimal/shared.css b/themes/Theme-Minimal/shared.css
index fa3bcc67..f43457b2 100644
--- a/themes/Theme-Minimal/shared.css
+++ b/themes/Theme-Minimal/shared.css
@@ -122,3 +122,76 @@
.badge-pill {
padding: 0.25rem 0.6rem;
}
+
+/* ---------- review fixes ---------- */
+
+.btn-primary.btn.donate.minimal {
+ display: none;
+}
+
+/* card heart: the same size as the select checkbox, mirrored in the
+ opposite corner */
+.grid-card .favorite-button {
+ top: 11px !important;
+ right: 8px !important;
+ padding: 0 !important;
+ line-height: 1;
+}
+.grid-card .favorite-button svg {
+ width: 19px !important;
+ height: 19px !important;
+ font-size: 19px !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
+ rather than the cards plus the dots, every card in a row one height */
+.recommendation-row .slick-slider {
+ margin: 0 30px 30px;
+}
+.recommendation-row .slick-prev {
+ left: -28px;
+}
+.recommendation-row .slick-next {
+ right: -28px;
+}
+.recommendation-row .slick-dots {
+ position: absolute;
+ top: 100%;
+}
+.recommendation-row .slick-track {
+ display: flex !important;
+ margin-bottom: 0;
+}
+.recommendation-row .slick-arrow {
+ top: 0;
+ height: 100%;
+ transform: none;
+}
+.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);
+}
+
+/* scene page: two performers side by side in the details panel */
+.scene-performers .performer-card {
+ width: calc(50% - 10px) !important;
+ margin: 5px !important;
+}
+
+/* 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 / 332px, 1)) - 12px) !important;
+ max-width: none !important;
+}
diff --git a/themes/Theme-Minimal/studio.css b/themes/Theme-Minimal/studio.css
index 012268dc..152bf949 100644
--- a/themes/Theme-Minimal/studio.css
+++ b/themes/Theme-Minimal/studio.css
@@ -3,7 +3,7 @@
}
.detail-header {
- --performer-image-size: 15rem;
+ --performer-image-size: 18rem;
overflow: unset;
.background-image-container {
@@ -29,6 +29,7 @@
align-items: flex-start;
img {
max-width: var(--performer-image-size);
+ border-radius: 12px;
}
}
.row {
@@ -43,7 +44,7 @@
.detail-group {
display: flex;
column-gap: 0rem;
- row-gap: 1.5rem;
+ row-gap: 6px;
.detail-item {
.detail-item-title {
font-size: var(--text-xs);
@@ -59,7 +60,24 @@
}
.performer-name {
- font-size: var(--text-xl);
+ font-size: 40px;
+ font-weight: 500;
+ line-height: 1;
+ }
+
+ /* one light primary (Edit); the other actions are quiet grey pills */
+ .details-edit {
+ gap: 8px;
+ .btn {
+ margin: 0;
+ }
+ .btn-secondary {
+ background-color: var(--primary-3);
+ border-radius: 10px;
+ &:hover {
+ background-color: var(--primary-4);
+ }
+ }
}
}
}
@@ -142,3 +160,170 @@
}
}
}
+
+/* Performer header: the portrait fills the left edge and fades into the page */
+.detail-header:has(.performer-head) {
+ padding: 0 !important;
+ margin: -15px -15px 0 !important; /* flush with the window edge, under the nav */
+ width: auto !important;
+ max-width: none !important;
+ .detail-container {
+ max-width: none;
+ margin: 0;
+ padding: 0;
+ display: flex;
+ align-items: flex-start;
+ }
+ .detail-header-image {
+ position: relative;
+ flex: 0 0 420px;
+ width: 420px;
+ height: 400px;
+ margin: 0;
+ padding: 0;
+ overflow: hidden;
+
+ .btn-link {
+ display: block;
+ width: 100%;
+ height: 100%;
+ padding: 0;
+ }
+ img.performer {
+ width: 100%;
+ height: 100%;
+ max-width: none !important;
+ max-height: none;
+ object-fit: cover;
+ object-position: center top;
+ border-radius: 0 !important;
+ box-shadow: none;
+ }
+ &::after {
+ content: "";
+ position: absolute;
+ inset: 0;
+ pointer-events: none;
+ background: linear-gradient(90deg, transparent 55%, var(--primary-1));
+ }
+ }
+ .row {
+ flex: 1;
+ min-width: 0;
+ margin: 0;
+ padding: 24px 36px 0;
+ }
+ /* fields as a tight two-column list, as in the mockup */
+ .detail-group {
+ row-gap: 5px !important;
+ margin-top: 4px;
+ .detail-item {
+ font-size: 13px;
+ line-height: 1.4;
+ margin: 0 !important;
+ padding: 0 !important;
+ .detail-item-title {
+ width: 130px;
+ font-size: 13px !important;
+ font-weight: 500 !important;
+ color: var(--primary-10) !important;
+ }
+ .detail-item-value {
+ font-size: 13px !important;
+ }
+ }
+ }
+ .details-edit {
+ margin: 10px 0 0 !important;
+ padding: 0 !important;
+ }
+ /* stock nests the actions in a padded .col/.row; line them up with the fields */
+ .performer-head .col,
+ .performer-head .row {
+ padding: 0 !important;
+ margin: 0 !important;
+ }
+ .rating-stars {
+ margin: 6px 0 !important;
+ }
+}
+@media (max-width: 767.98px) {
+ .detail-header:has(.performer-head) {
+ .detail-container {
+ flex-direction: column;
+ }
+ .detail-header-image {
+ flex-basis: auto;
+ width: 100%;
+ height: 430px;
+ &::after {
+ background: linear-gradient(180deg, transparent 55%, var(--primary-1));
+ }
+ }
+ .row {
+ padding: 14px;
+ }
+ }
+}
+
+/* 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;
+}
+
+/* Phones: the full-bleed performer header is exactly the screen's width, not
+ its widest content's */
+@media (max-width: 767.98px) {
+ .detail-header:has(.performer-head) {
+ flex: none !important;
+ width: calc(100% + 30px) !important;
+ min-width: 0;
+ }
+ .detail-header:has(.performer-head) .detail-container {
+ max-width: 100%;
+ min-width: 0;
+ }
+}