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 | +|---|---| +| ![Scenes](https://raw.githubusercontent.com/nexalapp/CommunityScripts/43c9691b1c39e40be1e918faa9a0a75183ba956a/Theme-Minimal/desktop-scenes.jpg) | ![Scene](https://raw.githubusercontent.com/nexalapp/CommunityScripts/43c9691b1c39e40be1e918faa9a0a75183ba956a/Theme-Minimal/desktop-scene.jpg) | + +| Performer | Studios | +|---|---| +| ![Performer](https://raw.githubusercontent.com/nexalapp/CommunityScripts/43c9691b1c39e40be1e918faa9a0a75183ba956a/Theme-Minimal/desktop-performer.jpg) | ![Studios](https://raw.githubusercontent.com/nexalapp/CommunityScripts/43c9691b1c39e40be1e918faa9a0a75183ba956a/Theme-Minimal/desktop-studios.jpg) | + +Scenes on a phone A scene on a phone + +### Version 0.1 + stash--minimal-theme-v0 1--performers stash--minimal-theme-v0 1--tags stash--minimal-theme-v0 1--settings @@ -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; + } +}