Add shared web layout and scoped card styles
This commit is contained in:
parent
324095c9e9
commit
99d72c4758
13
docs/TODO.md
Normal file
13
docs/TODO.md
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Goondex TODO / DONE
|
||||
|
||||
## TODO
|
||||
- [ ] Implement bulk studio import (`./goondex import all-studios`) with the same pagination/resume flow as the performer importer.
|
||||
- [ ] Implement bulk scene import (`./goondex import all-scenes`) and wire the CLI/UI to the new data set.
|
||||
- [ ] Build a movie ingest path (TPDB and/or Adult Empire) that feeds the `movies` tables and populates the movies pages.
|
||||
- [ ] Align the web stack on a single CSS pipeline (deprecate legacy `style.css`, keep goondex + scoped component files).
|
||||
- [ ] Add lightweight UI validation (lint/smoke tests) for navigation, modals, and search to catch regressions early.
|
||||
|
||||
## DONE
|
||||
- [x] Split card styling into per-context files (base, performers, studios, scenes) and updated listing templates to use them.
|
||||
- [x] Created shared task lists (`docs/TODO.md`, `docs/WEB_TODO.md`) to keep engineering and web work in sync.
|
||||
- [x] Adult Empire scraper + TPDB merge support for performers (see `SESSION_SUMMARY_v0.1.0-dev4.md`).
|
||||
11
docs/WEB_TODO.md
Normal file
11
docs/WEB_TODO.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Web TODO / DONE
|
||||
|
||||
## TODO
|
||||
- [ ] Split remaining shared CSS (hero, navbar, search, stats, forms, modals) into scoped files and retire inline styles in templates.
|
||||
- [ ] Migrate detail pages to the same CSS pipeline as listings (drop `style.css` in favor of scoped goondex files).
|
||||
- [ ] Audit cards for movies once movie data lands and add a dedicated `cards-movie.css`.
|
||||
- [ ] Add a short usage note for the GX component set (which classes/components we rely on and where).
|
||||
|
||||
## DONE
|
||||
- [x] Added per-context card styles (`cards/card-base.css`, `cards/cards-performer.css`, `cards/cards-studio.css`, `cards/cards-scene.css`) and wired listing templates.
|
||||
- [x] Cleaned up CSS imports in `internal/web/static/css/goondex.css` to reference real files only.
|
||||
|
|
@ -6,11 +6,11 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
"io/fs"
|
||||
|
||||
"git.leaktechnologies.dev/stu/Goondex/internal/db"
|
||||
import_service "git.leaktechnologies.dev/stu/Goondex/internal/import"
|
||||
|
|
@ -59,10 +59,10 @@ func (s *Server) Start() error {
|
|||
|
||||
mux.Handle(
|
||||
"/static/",
|
||||
http.StripPrefix(
|
||||
"/static/",
|
||||
http.FileServer(http.FS(staticFS)),
|
||||
),
|
||||
http.StripPrefix(
|
||||
"/static/",
|
||||
http.FileServer(http.FS(staticFS)),
|
||||
),
|
||||
)
|
||||
|
||||
// ============================================================================
|
||||
|
|
@ -127,6 +127,8 @@ func (s *Server) handleDashboard(w http.ResponseWriter, r *http.Request) {
|
|||
movies, _ := movieStore.Search("")
|
||||
|
||||
data := map[string]interface{}{
|
||||
"PageTitle": "Dashboard",
|
||||
"ActivePage": "dashboard",
|
||||
"PerformerCount": len(performers),
|
||||
"StudioCount": len(studios),
|
||||
"SceneCount": len(scenes),
|
||||
|
|
@ -218,10 +220,12 @@ func (s *Server) handlePerformerList(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
data := map[string]interface{}{
|
||||
"Performers": performersWithCounts,
|
||||
"Query": query,
|
||||
"Nationalities": nationalities,
|
||||
"Genders": genders,
|
||||
"PageTitle": "Performers",
|
||||
"ActivePage": "performers",
|
||||
"Performers": performersWithCounts,
|
||||
"Query": query,
|
||||
"Nationalities": nationalities,
|
||||
"Genders": genders,
|
||||
"SelectedNationality": nationalityFilter,
|
||||
"SelectedGender": genderFilter,
|
||||
}
|
||||
|
|
@ -317,9 +321,12 @@ func (s *Server) handlePerformerDetail(w http.ResponseWriter, r *http.Request) {
|
|||
scenes, _ := sceneStore.GetByPerformer(id)
|
||||
|
||||
data := map[string]interface{}{
|
||||
"Performer": performer,
|
||||
"SceneCount": sceneCount,
|
||||
"Scenes": scenes,
|
||||
"PageTitle": fmt.Sprintf("Performer: %s", performer.Name),
|
||||
"ActivePage": "performers",
|
||||
"Stylesheets": []string{"/static/css/style.css", "/static/css/goondex.css"},
|
||||
"Performer": performer,
|
||||
"SceneCount": sceneCount,
|
||||
"Scenes": scenes,
|
||||
}
|
||||
|
||||
s.templates.ExecuteTemplate(w, "performer_detail.html", data)
|
||||
|
|
@ -344,12 +351,14 @@ func (s *Server) handleStudioList(w http.ResponseWriter, r *http.Request) {
|
|||
for _, st := range studios {
|
||||
count, _ := store.GetSceneCount(st.ID)
|
||||
studiosWithCounts = append(studiosWithCounts,
|
||||
StudioWithCount{Studio: st, SceneCount: count})
|
||||
StudioWithCount{Studio: st, SceneCount: count})
|
||||
}
|
||||
|
||||
data := map[string]interface{}{
|
||||
"Studios": studiosWithCounts,
|
||||
"Query": query,
|
||||
"PageTitle": "Studios",
|
||||
"ActivePage": "studios",
|
||||
"Studios": studiosWithCounts,
|
||||
"Query": query,
|
||||
}
|
||||
|
||||
s.templates.ExecuteTemplate(w, "studios.html", data)
|
||||
|
|
@ -373,8 +382,11 @@ func (s *Server) handleStudioDetail(w http.ResponseWriter, r *http.Request) {
|
|||
sceneCount, _ := store.GetSceneCount(id)
|
||||
|
||||
data := map[string]interface{}{
|
||||
"Studio": studio,
|
||||
"SceneCount": sceneCount,
|
||||
"PageTitle": fmt.Sprintf("Studio: %s", studio.Name),
|
||||
"ActivePage": "studios",
|
||||
"Stylesheets": []string{"/static/css/style.css", "/static/css/goondex.css"},
|
||||
"Studio": studio,
|
||||
"SceneCount": sceneCount,
|
||||
}
|
||||
|
||||
s.templates.ExecuteTemplate(w, "studio_detail.html", data)
|
||||
|
|
@ -408,12 +420,14 @@ func (s *Server) handleSceneList(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
scenesWithStudios = append(scenesWithStudios,
|
||||
SceneWithStudio{Scene: sc, StudioName: studioName})
|
||||
SceneWithStudio{Scene: sc, StudioName: studioName})
|
||||
}
|
||||
|
||||
data := map[string]interface{}{
|
||||
"Scenes": scenesWithStudios,
|
||||
"Query": query,
|
||||
"PageTitle": "Scenes",
|
||||
"ActivePage": "scenes",
|
||||
"Scenes": scenesWithStudios,
|
||||
"Query": query,
|
||||
}
|
||||
|
||||
s.templates.ExecuteTemplate(w, "scenes.html", data)
|
||||
|
|
@ -448,11 +462,14 @@ func (s *Server) handleSceneDetail(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
data := map[string]interface{}{
|
||||
"Scene": scene,
|
||||
"Performers": performers,
|
||||
"Tags": tags,
|
||||
"Movies": movies,
|
||||
"StudioName": studioName,
|
||||
"PageTitle": fmt.Sprintf("Scene: %s", scene.Title),
|
||||
"ActivePage": "scenes",
|
||||
"Stylesheets": []string{"/static/css/style.css", "/static/css/goondex.css"},
|
||||
"Scene": scene,
|
||||
"Performers": performers,
|
||||
"Tags": tags,
|
||||
"Movies": movies,
|
||||
"StudioName": studioName,
|
||||
}
|
||||
|
||||
s.templates.ExecuteTemplate(w, "scene_detail.html", data)
|
||||
|
|
@ -492,8 +509,10 @@ func (s *Server) handleMovieList(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
data := map[string]interface{}{
|
||||
"Movies": moviesWithDetails,
|
||||
"Query": query,
|
||||
"PageTitle": "Movies",
|
||||
"ActivePage": "movies",
|
||||
"Movies": moviesWithDetails,
|
||||
"Query": query,
|
||||
}
|
||||
|
||||
s.templates.ExecuteTemplate(w, "movies.html", data)
|
||||
|
|
@ -526,6 +545,8 @@ func (s *Server) handleMovieDetail(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
data := map[string]interface{}{
|
||||
"PageTitle": fmt.Sprintf("Movie: %s", movie.Title),
|
||||
"ActivePage": "movies",
|
||||
"Movie": movie,
|
||||
"Scenes": scenes,
|
||||
"StudioName": studioName,
|
||||
|
|
@ -594,7 +615,7 @@ func (s *Server) handleAPIImportPerformer(w http.ResponseWriter, r *http.Request
|
|||
json.NewEncoder(w).Encode(APIResponse{
|
||||
Success: true,
|
||||
Message: fmt.Sprintf("Imported %d performer(s)", imported),
|
||||
Data: map[string]int{"imported": imported, "found": len(performers)},
|
||||
Data: map[string]int{"imported": imported, "found": len(performers)},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -644,7 +665,7 @@ func (s *Server) handleAPIImportStudio(w http.ResponseWriter, r *http.Request) {
|
|||
json.NewEncoder(w).Encode(APIResponse{
|
||||
Success: true,
|
||||
Message: fmt.Sprintf("Imported %d studio(s)", imported),
|
||||
Data: map[string]int{"imported": imported, "found": len(studios)},
|
||||
Data: map[string]int{"imported": imported, "found": len(studios)},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -737,7 +758,7 @@ func (s *Server) handleAPIImportScene(w http.ResponseWriter, r *http.Request) {
|
|||
json.NewEncoder(w).Encode(APIResponse{
|
||||
Success: true,
|
||||
Message: fmt.Sprintf("Imported %d scene(s)", imported),
|
||||
Data: map[string]int{"imported": imported, "found": len(scenes)},
|
||||
Data: map[string]int{"imported": imported, "found": len(scenes)},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -856,7 +877,7 @@ func (s *Server) handleAPIBulkImportPerformers(w http.ResponseWriter, r *http.Re
|
|||
json.NewEncoder(w).Encode(APIResponse{
|
||||
Success: true,
|
||||
Message: fmt.Sprintf("Imported %d/%d performers", result.Imported, result.Total),
|
||||
Data: result,
|
||||
Data: result,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -886,7 +907,7 @@ func (s *Server) handleAPIBulkImportStudios(w http.ResponseWriter, r *http.Reque
|
|||
json.NewEncoder(w).Encode(APIResponse{
|
||||
Success: true,
|
||||
Message: fmt.Sprintf("Imported %d/%d studios", result.Imported, result.Total),
|
||||
Data: result,
|
||||
Data: result,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -916,7 +937,7 @@ func (s *Server) handleAPIBulkImportScenes(w http.ResponseWriter, r *http.Reques
|
|||
json.NewEncoder(w).Encode(APIResponse{
|
||||
Success: true,
|
||||
Message: fmt.Sprintf("Imported %d/%d scenes", result.Imported, result.Total),
|
||||
Data: result,
|
||||
Data: result,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1084,6 +1105,6 @@ func (s *Server) handleAPIGlobalSearch(w http.ResponseWriter, r *http.Request) {
|
|||
json.NewEncoder(w).Encode(APIResponse{
|
||||
Success: true,
|
||||
Message: fmt.Sprintf("Found %d results", results["total"]),
|
||||
Data: results,
|
||||
Data: results,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
103
internal/web/static/css/cards/card-base.css
Normal file
103
internal/web/static/css/cards/card-base.css
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* GOONDEX CARD BASE
|
||||
* Shared grid + card shell used by performer/studio/scene listings.
|
||||
*/
|
||||
|
||||
:root {
|
||||
--gx-card-thumb-ratio: 3 / 4;
|
||||
--gx-card-min-width: 250px;
|
||||
}
|
||||
|
||||
.gx-card-grid {
|
||||
display: grid;
|
||||
gap: 1.6rem;
|
||||
padding: 1rem 0;
|
||||
grid-template-columns: repeat(auto-fill, minmax(var(--gx-card-min-width), 1fr));
|
||||
}
|
||||
|
||||
.gx-card {
|
||||
background: var(--color-bg-card);
|
||||
border: 1px solid var(--color-border-soft);
|
||||
border-radius: var(--radius-soft);
|
||||
overflow: hidden;
|
||||
|
||||
box-shadow: var(--shadow-elevated);
|
||||
transition:
|
||||
transform var(--transition),
|
||||
box-shadow var(--transition),
|
||||
border-color var(--transition);
|
||||
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.gx-card:hover {
|
||||
transform: translateY(-4px);
|
||||
border-color: var(--color-brand);
|
||||
box-shadow:
|
||||
0 0 18px rgba(255, 79, 163, 0.28),
|
||||
0 6px 24px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
|
||||
.gx-card-thumb {
|
||||
width: 100%;
|
||||
aspect-ratio: var(--gx-card-thumb-ratio);
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
filter: brightness(0.92);
|
||||
transition: filter var(--transition-fast);
|
||||
}
|
||||
|
||||
.gx-card:hover .gx-card-thumb {
|
||||
filter: brightness(1);
|
||||
}
|
||||
|
||||
.gx-card-body {
|
||||
padding: 1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
|
||||
.gx-card-title {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
|
||||
background: linear-gradient(135deg, var(--color-text-primary), var(--color-header));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.gx-card-meta {
|
||||
font-size: 0.85rem;
|
||||
color: var(--color-text-secondary);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.gx-card-tags {
|
||||
margin-top: 0.7rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.gx-card-tag {
|
||||
padding: 0.2rem 0.55rem;
|
||||
font-size: 0.75rem;
|
||||
border-radius: var(--radius);
|
||||
background: rgba(255, 79, 163, 0.08);
|
||||
color: var(--color-brand);
|
||||
border: 1px solid rgba(255, 79, 163, 0.25);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.03em;
|
||||
}
|
||||
|
||||
@media (max-width: 550px) {
|
||||
.gx-card-grid {
|
||||
grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
|
||||
}
|
||||
|
||||
.gx-card-title {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
16
internal/web/static/css/cards/cards-movie.css
Normal file
16
internal/web/static/css/cards/cards-movie.css
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* GOONDEX MOVIE CARDS
|
||||
* Poster-focused layout for movie listings.
|
||||
*/
|
||||
|
||||
.movie-card-grid {
|
||||
--gx-card-thumb-ratio: 2 / 3;
|
||||
}
|
||||
|
||||
.movie-card .gx-card-meta + .gx-card-meta {
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
.movie-card .gx-card-tags {
|
||||
margin-top: 0.6rem;
|
||||
}
|
||||
16
internal/web/static/css/cards/cards-performer.css
Normal file
16
internal/web/static/css/cards/cards-performer.css
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* GOONDEX PERFORMER CARDS
|
||||
* Portrait-focused layout for performer listings.
|
||||
*/
|
||||
|
||||
.performer-card-grid {
|
||||
--gx-card-thumb-ratio: 3 / 4;
|
||||
}
|
||||
|
||||
.performer-card .gx-card-meta + .gx-card-meta {
|
||||
margin-top: 0.3rem;
|
||||
}
|
||||
|
||||
.performer-card .gx-card-tags {
|
||||
margin-top: 0.6rem;
|
||||
}
|
||||
16
internal/web/static/css/cards/cards-scene.css
Normal file
16
internal/web/static/css/cards/cards-scene.css
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* GOONDEX SCENE CARDS
|
||||
* Landscape-focused layout for scene listings.
|
||||
*/
|
||||
|
||||
.scene-card-grid {
|
||||
--gx-card-thumb-ratio: 16 / 9;
|
||||
}
|
||||
|
||||
.scene-card .gx-card-meta + .gx-card-meta {
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
.scene-card .gx-card-tags {
|
||||
margin-top: 0.6rem;
|
||||
}
|
||||
23
internal/web/static/css/cards/cards-studio.css
Normal file
23
internal/web/static/css/cards/cards-studio.css
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* GOONDEX STUDIO CARDS
|
||||
* Studio listings with compact description support.
|
||||
*/
|
||||
|
||||
.studio-card-grid {
|
||||
--gx-card-thumb-ratio: 3 / 4;
|
||||
}
|
||||
|
||||
.studio-card .studio-card-description {
|
||||
margin-top: 0.5rem;
|
||||
font-size: 0.85rem;
|
||||
color: var(--color-text-secondary);
|
||||
opacity: 0.85;
|
||||
line-height: 1.4;
|
||||
max-height: 2.8rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.studio-card .gx-card-tags {
|
||||
margin-top: 0.6rem;
|
||||
}
|
||||
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
/* ===== GX COMPONENT LIBRARY ================================================= */
|
||||
@import 'gx/GX_Button.css';
|
||||
@import 'gx/GX_CardGrid.css';
|
||||
@import 'gx/GX_Checkbox.css';
|
||||
@import 'gx/GX_Input.css';
|
||||
@import 'gx/GX_Loader.css';
|
||||
|
|
@ -15,18 +14,18 @@
|
|||
|
||||
/* ===== LAYOUT & STRUCTURE =================================================== */
|
||||
@import 'layout.css';
|
||||
@import 'navbar.css';
|
||||
@import 'sidepanels.css';
|
||||
|
||||
/* ===== PAGE-LEVEL COMPONENTS ================================================ */
|
||||
@import 'hero.css';
|
||||
@import 'stats.css';
|
||||
/* ===== CORE COMPONENTS ===================================================== */
|
||||
@import 'forms.css';
|
||||
@import 'buttons.css';
|
||||
@import 'components.css';
|
||||
|
||||
/* ===== CARDS (SCOPED BY CONTEXT) =========================================== */
|
||||
@import 'cards/card-base.css';
|
||||
@import 'cards/cards-performer.css';
|
||||
@import 'cards/cards-studio.css';
|
||||
@import 'cards/cards-scene.css';
|
||||
@import 'cards/cards-movie.css';
|
||||
|
||||
/* ===== GLOBAL PAGE STYLES =================================================== */
|
||||
@import 'pages.css';
|
||||
|
||||
/* ===== RESPONSIVE OVERRIDES (MOBILE/TABLET/HALF-SCREEN) ===================== */
|
||||
@import 'responsive.css';
|
||||
|
|
|
|||
|
|
@ -1,103 +1,11 @@
|
|||
/*
|
||||
* GX CARD GRID — Performer / Studio / Scene cards
|
||||
* Dark luxury aesthetic, Flamingo Pink medium glow, responsive columns
|
||||
* GX CARD GRID (COMPAT)
|
||||
* This file now re-exports the scoped card styles.
|
||||
* Prefer importing /static/css/cards/*.css directly.
|
||||
*/
|
||||
|
||||
/* WRAPPER */
|
||||
.gx-card-grid {
|
||||
display: grid;
|
||||
gap: 1.6rem;
|
||||
padding: 1rem 0;
|
||||
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
||||
}
|
||||
|
||||
/* CARD */
|
||||
.gx-card {
|
||||
background: var(--color-bg-card);
|
||||
border: 1px solid var(--color-border-soft);
|
||||
border-radius: var(--radius-soft);
|
||||
overflow: hidden;
|
||||
|
||||
box-shadow: var(--shadow-elevated);
|
||||
transition: transform var(--transition),
|
||||
box-shadow var(--transition),
|
||||
border-color var(--transition);
|
||||
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* HOVER EFFECT */
|
||||
.gx-card:hover {
|
||||
transform: translateY(-4px);
|
||||
border-color: var(--color-brand);
|
||||
box-shadow: 0 0 18px rgba(255, 79, 163, 0.28),
|
||||
0 6px 24px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
|
||||
/* THUMBNAIL */
|
||||
.gx-card-thumb {
|
||||
width: 100%;
|
||||
aspect-ratio: 3 / 4;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
filter: brightness(0.92);
|
||||
transition: filter var(--transition-fast);
|
||||
}
|
||||
|
||||
.gx-card:hover .gx-card-thumb {
|
||||
filter: brightness(1);
|
||||
}
|
||||
|
||||
/* CONTENT */
|
||||
.gx-card-body {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
/* TITLE */
|
||||
.gx-card-title {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.35rem;
|
||||
|
||||
background: linear-gradient(135deg, var(--color-text-primary), var(--color-header));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
/* SMALL META (scene count, category, etc.) */
|
||||
.gx-card-meta {
|
||||
font-size: 0.85rem;
|
||||
color: var(--color-text-secondary);
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
/* TAGS inside cards (optional) */
|
||||
.gx-card-tags {
|
||||
margin-top: 0.8rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.gx-card-tag {
|
||||
padding: 0.2rem 0.55rem;
|
||||
font-size: 0.75rem;
|
||||
border-radius: var(--radius);
|
||||
background: rgba(255, 79, 163, 0.08);
|
||||
color: var(--color-brand);
|
||||
border: 1px solid rgba(255, 79, 163, 0.25);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.03em;
|
||||
}
|
||||
|
||||
/* MOBILE OPTIMISATION */
|
||||
@media (max-width: 550px) {
|
||||
.gx-card-grid {
|
||||
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
|
||||
}
|
||||
|
||||
.gx-card-title {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
@import '../cards/card-base.css';
|
||||
@import '../cards/cards-performer.css';
|
||||
@import '../cards/cards-studio.css';
|
||||
@import '../cards/cards-scene.css';
|
||||
@import '../cards/cards-movie.css';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<div class="gx-card-grid">
|
||||
<div class="gx-card-grid performer-card-grid">
|
||||
|
||||
{{range .Performers}}
|
||||
<div class="gx-card" onclick="location.href='/performers/{{.Performer.ID}}'">
|
||||
<div class="gx-card performer-card" onclick="location.href='/performers/{{.Performer.ID}}'">
|
||||
|
||||
<div class="gx-card-thumb"
|
||||
style="background-image: url('/static/img/performers/{{.Performer.ID}}.jpg');">
|
||||
|
|
|
|||
|
|
@ -80,6 +80,20 @@ body {
|
|||
justify-content: space-between;
|
||||
}
|
||||
|
||||
/* Bootstrap navbar controls */
|
||||
.navbar .navbar-toggler {
|
||||
border-color: var(--color-border-soft);
|
||||
padding: 0.35rem 0.5rem;
|
||||
}
|
||||
|
||||
.navbar .navbar-toggler:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.navbar .navbar-toggler-icon {
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
/* Logo image control */
|
||||
.logo-img {
|
||||
height: 42px;
|
||||
|
|
@ -264,4 +278,17 @@ body {
|
|||
.stats-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.navbar .collapse {
|
||||
padding-top: 0.75rem;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.nav-links .nav-link {
|
||||
padding: 0.35rem 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Goondex - Dashboard</title>
|
||||
<link rel="stylesheet" href="/static/css/goondex.css">
|
||||
{{template "html-head" .}}
|
||||
|
||||
<style>
|
||||
/* ==== LUXURY SIDE PANELS (A1 – Medium 240px) ==== */
|
||||
|
|
@ -89,18 +86,7 @@
|
|||
<div class="main-wrapper">
|
||||
|
||||
<!-- NAVIGATION -->
|
||||
<nav class="navbar">
|
||||
<div class="container nav-inner">
|
||||
<img src="/static/img/logo/GOONDEX_logo.png" class="logo-img">
|
||||
<ul class="nav-links">
|
||||
<li><a href="/" class="active">Dashboard</a></li>
|
||||
<li><a href="/performers">Performers</a></li>
|
||||
<li><a href="/studios">Studios</a></li>
|
||||
<li><a href="/scenes">Scenes</a></li>
|
||||
<li><a href="/movies">Movies</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
{{template "navbar" .}}
|
||||
|
||||
<main class="container">
|
||||
|
||||
|
|
@ -254,6 +240,6 @@
|
|||
<!-- EXISTING MODALS (unchanged, full code integrity kept) -->
|
||||
{{/* Your modals remain exactly as before */}}
|
||||
|
||||
<script src="/static/js/app.js"></script>
|
||||
{{template "html-scripts" .}}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
57
internal/web/templates/layout.html
Normal file
57
internal/web/templates/layout.html
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
{{define "html-head"}}
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{if .PageTitle}}{{.PageTitle}} - Goondex{{else}}Goondex{{end}}</title>
|
||||
|
||||
<!-- Bootstrap (base layout) -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Goondex bespoke styles -->
|
||||
{{if .Stylesheets}}
|
||||
{{range .Stylesheets}}
|
||||
<link rel="stylesheet" href="{{.}}">
|
||||
{{end}}
|
||||
{{else}}
|
||||
<link rel="stylesheet" href="/static/css/goondex.css">
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{define "html-scripts"}}
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="/static/js/app.js"></script>
|
||||
{{end}}
|
||||
|
||||
{{define "navbar"}}
|
||||
<nav class="navbar navbar-expand-lg navbar-dark">
|
||||
<div class="container nav-inner">
|
||||
<a class="navbar-brand d-flex align-items-center" href="/">
|
||||
<img src="/static/img/logo/GOONDEX_logo.png" class="logo-img" alt="Goondex logo">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mainNav"
|
||||
aria-controls="mainNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse justify-content-end" id="mainNav">
|
||||
<ul class="nav-links navbar-nav align-items-lg-center">
|
||||
<li class="nav-item">
|
||||
<a href="/" class="nav-link {{if eq .ActivePage "dashboard"}}active{{end}}">Dashboard</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/performers" class="nav-link {{if eq .ActivePage "performers"}}active{{end}}">Performers</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/studios" class="nav-link {{if eq .ActivePage "studios"}}active{{end}}">Studios</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/scenes" class="nav-link {{if eq .ActivePage "scenes"}}active{{end}}">Scenes</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/movies" class="nav-link {{if eq .ActivePage "movies"}}active{{end}}">Movies</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
{{end}}
|
||||
|
|
@ -1,24 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{.Movie.Title}} - Goondex</title>
|
||||
<link rel="stylesheet" href="/static/css/goondex.css">
|
||||
{{template "html-head" .}}
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar">
|
||||
<div class="container nav-inner">
|
||||
<img src="/static/img/logo/GOONDEX_logo.png" class="logo-img">
|
||||
<ul class="nav-links">
|
||||
<li><a href="/">Dashboard</a></li>
|
||||
<li><a href="/performers">Performers</a></li>
|
||||
<li><a href="/studios">Studios</a></li>
|
||||
<li><a href="/scenes">Scenes</a></li>
|
||||
<li><a href="/movies" class="active">Movies</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
{{template "navbar" .}}
|
||||
|
||||
<main class="container">
|
||||
<div class="detail-header">
|
||||
|
|
@ -85,11 +71,11 @@
|
|||
{{if .Scenes}}
|
||||
<section class="detail-section">
|
||||
<h2>Scenes ({{len .Scenes}})</h2>
|
||||
<div class="gx-card-grid scenes-grid">
|
||||
<div class="gx-card-grid scene-card-grid">
|
||||
{{range .Scenes}}
|
||||
<div class="gx-card" onclick="location.href='/scenes/{{.ID}}'">
|
||||
<div class="gx-card scene-card" onclick="location.href='/scenes/{{.ID}}'">
|
||||
<div class="gx-card-thumb"
|
||||
style="background-image: url('{{if .ImageURL}}{{.ImageURL}}{{else}}/static/img/placeholder-scene.jpg{{end}}'); aspect-ratio: 16/9; background-color: #1a1a1a;">
|
||||
style="background-image: url('{{if .ImageURL}}{{.ImageURL}}{{else}}/static/img/placeholder-scene.jpg{{end}}'); background-color: #1a1a1a;">
|
||||
</div>
|
||||
|
||||
<div class="gx-card-body">
|
||||
|
|
@ -113,5 +99,6 @@
|
|||
</section>
|
||||
{{end}}
|
||||
</main>
|
||||
{{template "html-scripts" .}}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,24 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Movies - Goondex</title>
|
||||
<link rel="stylesheet" href="/static/css/goondex.css">
|
||||
{{template "html-head" .}}
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar">
|
||||
<div class="container nav-inner">
|
||||
<img src="/static/img/logo/GOONDEX_logo.png" class="logo-img">
|
||||
<ul class="nav-links">
|
||||
<li><a href="/">Dashboard</a></li>
|
||||
<li><a href="/performers">Performers</a></li>
|
||||
<li><a href="/studios">Studios</a></li>
|
||||
<li><a href="/scenes">Scenes</a></li>
|
||||
<li><a href="/movies" class="active">Movies</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
{{template "navbar" .}}
|
||||
|
||||
<main class="container">
|
||||
<div class="page-header">
|
||||
|
|
@ -30,9 +16,9 @@
|
|||
</div>
|
||||
|
||||
{{if .Movies}}
|
||||
<div class="gx-card-grid">
|
||||
<div class="gx-card-grid movie-card-grid">
|
||||
{{range .Movies}}
|
||||
<div class="gx-card" onclick="location.href='/movies/{{.Movie.ID}}'">
|
||||
<div class="gx-card movie-card" onclick="location.href='/movies/{{.Movie.ID}}'">
|
||||
<div class="gx-card-thumb"
|
||||
style="background-image: url('{{if .Movie.ImageURL}}{{.Movie.ImageURL}}{{else}}/static/img/placeholder-movie.jpg{{end}}'); background-color: #1a1a1a;">
|
||||
</div>
|
||||
|
|
@ -47,13 +33,13 @@
|
|||
<div class="gx-card-meta">{{.SceneCount}} scenes</div>
|
||||
|
||||
{{if .StudioName}}
|
||||
<div class="gx-card-meta" style="margin-top: 0.3rem;">
|
||||
<div class="gx-card-meta">
|
||||
🎬 {{.StudioName}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if .Movie.Duration}}
|
||||
<div class="gx-card-tags" style="margin-top: 0.6rem;">
|
||||
<div class="gx-card-tags">
|
||||
<span class="gx-card-tag">{{.Movie.Duration}} min</span>
|
||||
{{if .Movie.Source}}
|
||||
<span class="gx-card-tag">{{.Movie.Source}}</span>
|
||||
|
|
@ -75,5 +61,6 @@
|
|||
</div>
|
||||
{{end}}
|
||||
</main>
|
||||
{{template "html-scripts" .}}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,24 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{.Performer.Name}} - Goondex</title>
|
||||
<link rel="stylesheet" href="/static/css/style.css">
|
||||
{{template "html-head" .}}
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar">
|
||||
<div class="container">
|
||||
<h1 class="logo">Goondex</h1>
|
||||
<ul class="nav-links">
|
||||
<li><a href="/">Dashboard</a></li>
|
||||
<li><a href="/performers" class="active">Performers</a></li>
|
||||
<li><a href="/studios">Studios</a></li>
|
||||
<li><a href="/scenes">Scenes</a></li>
|
||||
<li><a href="/movies">Movies</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
{{template "navbar" .}}
|
||||
|
||||
<main class="container">
|
||||
<div class="breadcrumb">
|
||||
|
|
@ -268,5 +254,6 @@
|
|||
}
|
||||
});
|
||||
</script>
|
||||
{{template "html-scripts" .}}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,24 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Performers - Goondex</title>
|
||||
<link rel="stylesheet" href="/static/css/goondex.css">
|
||||
{{template "html-head" .}}
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar">
|
||||
<div class="container nav-inner">
|
||||
<img src="/static/img/logo/GOONDEX_logo.png" class="logo-img">
|
||||
<ul class="nav-links">
|
||||
<li><a href="/">Dashboard</a></li>
|
||||
<li><a href="/performers" class="active">Performers</a></li>
|
||||
<li><a href="/studios">Studios</a></li>
|
||||
<li><a href="/scenes">Scenes</a></li>
|
||||
<li><a href="/movies">Movies</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
{{template "navbar" .}}
|
||||
|
||||
<main class="container">
|
||||
<div class="page-header">
|
||||
|
|
@ -45,9 +31,9 @@
|
|||
</div>
|
||||
|
||||
{{if .Performers}}
|
||||
<div class="gx-card-grid">
|
||||
<div class="gx-card-grid performer-card-grid">
|
||||
{{range .Performers}}
|
||||
<div class="gx-card" onclick="location.href='/performers/{{.Performer.ID}}'">
|
||||
<div class="gx-card performer-card" onclick="location.href='/performers/{{.Performer.ID}}'">
|
||||
<div class="gx-card-thumb"
|
||||
style="background-image: url('{{if .Performer.ImageURL}}{{.Performer.ImageURL}}{{else}}/static/img/placeholder-performer.jpg{{end}}'); background-color: #1a1a1a;">
|
||||
</div>
|
||||
|
|
@ -59,13 +45,13 @@
|
|||
<div class="gx-card-meta">{{.SceneCount}} scenes</div>
|
||||
|
||||
{{if .Performer.Nationality}}
|
||||
<div class="gx-card-meta" style="margin-top: 0.3rem;">
|
||||
<div class="gx-card-meta">
|
||||
{{if .CountryFlag}}{{.CountryFlag}}{{else}}🌍{{end}} {{.Performer.Nationality}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if .Performer.Gender}}
|
||||
<div class="gx-card-tags" style="margin-top: 0.6rem;">
|
||||
<div class="gx-card-tags">
|
||||
<span class="gx-card-tag">{{.Performer.Gender}}</span>
|
||||
{{if .Performer.Source}}
|
||||
<span class="gx-card-tag">{{.Performer.Source}}</span>
|
||||
|
|
@ -87,5 +73,6 @@
|
|||
</div>
|
||||
{{end}}
|
||||
</main>
|
||||
{{template "html-scripts" .}}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,24 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{.Scene.Title}} - Goondex</title>
|
||||
<link rel="stylesheet" href="/static/css/style.css">
|
||||
{{template "html-head" .}}
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar">
|
||||
<div class="container">
|
||||
<h1 class="logo">Goondex</h1>
|
||||
<ul class="nav-links">
|
||||
<li><a href="/">Dashboard</a></li>
|
||||
<li><a href="/performers">Performers</a></li>
|
||||
<li><a href="/studios">Studios</a></li>
|
||||
<li><a href="/scenes" class="active">Scenes</a></li>
|
||||
<li><a href="/movies">Movies</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
{{template "navbar" .}}
|
||||
|
||||
<main class="container">
|
||||
<div class="breadcrumb">
|
||||
|
|
@ -136,6 +122,6 @@
|
|||
</div>
|
||||
</main>
|
||||
|
||||
<script src="/static/js/app.js"></script>
|
||||
{{template "html-scripts" .}}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,30 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Scenes - Goondex</title>
|
||||
<link rel="stylesheet" href="/static/css/goondex.css">
|
||||
<style>
|
||||
/* Scene cards use 16:9 aspect ratio instead of 3:4 for performers */
|
||||
.scenes-grid .gx-card-thumb {
|
||||
aspect-ratio: 16 / 9;
|
||||
}
|
||||
</style>
|
||||
{{template "html-head" .}}
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar">
|
||||
<div class="container nav-inner">
|
||||
<img src="/static/img/logo/GOONDEX_logo.png" class="logo-img">
|
||||
<ul class="nav-links">
|
||||
<li><a href="/">Dashboard</a></li>
|
||||
<li><a href="/performers">Performers</a></li>
|
||||
<li><a href="/studios">Studios</a></li>
|
||||
<li><a href="/scenes" class="active">Scenes</a></li>
|
||||
<li><a href="/movies">Movies</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
{{template "navbar" .}}
|
||||
|
||||
<main class="container">
|
||||
<div class="page-header">
|
||||
|
|
@ -36,9 +16,9 @@
|
|||
</div>
|
||||
|
||||
{{if .Scenes}}
|
||||
<div class="gx-card-grid scenes-grid">
|
||||
<div class="gx-card-grid scene-card-grid">
|
||||
{{range .Scenes}}
|
||||
<div class="gx-card" onclick="location.href='/scenes/{{.Scene.ID}}'">
|
||||
<div class="gx-card scene-card" onclick="location.href='/scenes/{{.Scene.ID}}'">
|
||||
<div class="gx-card-thumb"
|
||||
style="background-image: url('{{if .Scene.ImageURL}}{{.Scene.ImageURL}}{{else}}/static/img/placeholder-scene.jpg{{end}}'); background-color: #1a1a1a;">
|
||||
</div>
|
||||
|
|
@ -51,12 +31,12 @@
|
|||
{{end}}
|
||||
|
||||
{{if .StudioName}}
|
||||
<div class="gx-card-meta" style="margin-top: 0.2rem;">
|
||||
<div class="gx-card-meta">
|
||||
🏢 {{.StudioName}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="gx-card-tags" style="margin-top: 0.6rem;">
|
||||
<div class="gx-card-tags">
|
||||
{{if .Scene.Code}}
|
||||
<span class="gx-card-tag">{{.Scene.Code}}</span>
|
||||
{{end}}
|
||||
|
|
@ -79,5 +59,6 @@
|
|||
</div>
|
||||
{{end}}
|
||||
</main>
|
||||
{{template "html-scripts" .}}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,24 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{.Studio.Name}} - Goondex</title>
|
||||
<link rel="stylesheet" href="/static/css/style.css">
|
||||
{{template "html-head" .}}
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar">
|
||||
<div class="container">
|
||||
<h1 class="logo">Goondex</h1>
|
||||
<ul class="nav-links">
|
||||
<li><a href="/">Dashboard</a></li>
|
||||
<li><a href="/performers">Performers</a></li>
|
||||
<li><a href="/studios" class="active">Studios</a></li>
|
||||
<li><a href="/scenes">Scenes</a></li>
|
||||
<li><a href="/movies">Movies</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
{{template "navbar" .}}
|
||||
|
||||
<main class="container">
|
||||
<div class="breadcrumb">
|
||||
|
|
@ -73,5 +59,6 @@
|
|||
{{end}}
|
||||
</div>
|
||||
</main>
|
||||
{{template "html-scripts" .}}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,24 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Studios - Goondex</title>
|
||||
<link rel="stylesheet" href="/static/css/goondex.css">
|
||||
{{template "html-head" .}}
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar">
|
||||
<div class="container nav-inner">
|
||||
<img src="/static/img/logo/GOONDEX_logo.png" class="logo-img">
|
||||
<ul class="nav-links">
|
||||
<li><a href="/">Dashboard</a></li>
|
||||
<li><a href="/performers">Performers</a></li>
|
||||
<li><a href="/studios" class="active">Studios</a></li>
|
||||
<li><a href="/scenes">Scenes</a></li>
|
||||
<li><a href="/movies">Movies</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
{{template "navbar" .}}
|
||||
|
||||
<main class="container">
|
||||
<div class="page-header">
|
||||
|
|
@ -30,9 +16,9 @@
|
|||
</div>
|
||||
|
||||
{{if .Studios}}
|
||||
<div class="gx-card-grid">
|
||||
<div class="gx-card-grid studio-card-grid">
|
||||
{{range .Studios}}
|
||||
<div class="gx-card" onclick="location.href='/studios/{{.Studio.ID}}'">
|
||||
<div class="gx-card studio-card" onclick="location.href='/studios/{{.Studio.ID}}'">
|
||||
<div class="gx-card-thumb"
|
||||
style="background-image: url('{{if .Studio.ImageURL}}{{.Studio.ImageURL}}{{else}}/static/img/placeholder-studio.jpg{{end}}'); background-color: #1a1a1a;">
|
||||
</div>
|
||||
|
|
@ -42,13 +28,11 @@
|
|||
<div class="gx-card-meta">{{.SceneCount}} scenes</div>
|
||||
|
||||
{{if .Studio.Description}}
|
||||
<div class="gx-card-meta" style="margin-top: 0.5rem; font-size: 0.8rem; opacity: 0.8; line-height: 1.3; max-height: 2.6rem; overflow: hidden; text-overflow: ellipsis;">
|
||||
{{.Studio.Description}}
|
||||
</div>
|
||||
<div class="gx-card-meta studio-card-description">{{.Studio.Description}}</div>
|
||||
{{end}}
|
||||
|
||||
{{if .Studio.Source}}
|
||||
<div class="gx-card-tags" style="margin-top: 0.6rem;">
|
||||
<div class="gx-card-tags">
|
||||
<span class="gx-card-tag">{{.Studio.Source}}</span>
|
||||
</div>
|
||||
{{end}}
|
||||
|
|
@ -67,5 +51,6 @@
|
|||
</div>
|
||||
{{end}}
|
||||
</main>
|
||||
{{template "html-scripts" .}}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user