source: Klonkt/src/views/pages/hub-home.ejs@ 4c5169f

main
Last change on this file since 4c5169f was 4c5169f, checked in by roboburr <roboburr@…>, 3 months ago

hub: overview is a headerless landing with hero image

The hub overview now starts directly with the hero — no masthead/profile-header/
view-switcher/bottom-tab (those belong to a PrutFolio and appear on /user/
pages). Hero supports a background image (setting hub_hero_image, configurable
in Admin) with a dark overlay; otherwise gradient. Roster avatars use each
artist's accent color.

  • shell.ejs: chrome gated on bodyClass 'on-hub'.
  • hub.js: artists.accent + hub.heroImage from settings.
  • admin-settings: hub_hero_image field.

Co-Authored-By: Claude <noreply@…>

  • Property mode set to 100644
File size: 7.4 KB
Line 
1<div class="hub">
2
3 <%# ── HERO (label) — de pagina begint hier, geen header erboven ────── %>
4 <header class="hub-hero<%= hub.heroImage ? ' has-img' : '' %>"<% if (hub.heroImage) { %> style="--hero-img:url('<%= hub.heroImage %>')"<% } %>>
5 <div class="hub-hero-inner container">
6 <h1 class="hub-hero-title"><%= hub.title %></h1>
7 <% if (hub.tagline) { %>
8 <p class="hub-hero-tag"><%= hub.tagline %></p>
9 <% } %>
10 <% if (hub.intro) { %>
11 <p class="hub-hero-desc"><%= hub.intro %></p>
12 <% } %>
13 </div>
14 </header>
15
16 <div class="container hub-body">
17
18 <%# ── ARTIESTEN-ROSTER ─────────────────────────────────────────── %>
19 <% if (artists && artists.length) { %>
20 <section class="hub-sec">
21 <h2 class="hub-sec-title">Artiesten</h2>
22 <div class="roster">
23 <% artists.forEach(function(a){ %>
24 <a class="roster-card" href="/user/<%= a.slug %>">
25 <span class="roster-avatar"<% if (a.profile_photo) { %> style="background-image:url('<%= a.profile_photo %>')"<% } else { %> style="background:<%= a.accent || 'var(--accent)' %>;color:#fff"<% } %>>
26 <% if (!a.profile_photo) { %><%= (a.title || a.slug).charAt(0).toUpperCase() %><% } %>
27 </span>
28 <span class="roster-name"><%= a.title %></span>
29 <% if (a.tagline) { %><span class="roster-tag"><%= a.tagline %></span><% } %>
30 <span class="roster-count"><%= a.post_count %> post<%= a.post_count === 1 ? '' : 's' %></span>
31 </a>
32 <% }); %>
33 </div>
34 </section>
35 <% } %>
36
37 <%# ── LAATSTE POSTS ────────────────────────────────────────────── %>
38 <% if (posts && posts.length) { %>
39 <section class="hub-sec">
40 <h2 class="hub-sec-title">Laatste posts van users</h2>
41 <div class="hub-feed">
42 <% posts.forEach(function(p){ %>
43 <a class="feed-item" href="/user/<%= p.site_slug %>/<%= p.slug %>">
44 <% if (p.cover_image_url) { %>
45 <span class="feed-cover" style="background-image:url('<%= p.cover_image_url %>')"></span>
46 <% } %>
47 <span class="feed-body">
48 <span class="feed-meta"><%= p.site_title %> · <%= formatDate(p.published_at || p.created_at) %></span>
49 <span class="feed-title"><%= p.title %></span>
50 <% if (p.excerpt) { %><span class="feed-excerpt"><%= p.excerpt %></span><% } %>
51 </span>
52 <span class="feed-arrow" aria-hidden="true">→</span>
53 </a>
54 <% }); %>
55 </div>
56 </section>
57 <% } %>
58
59 </div>
60</div>
61
62<style>
63.hub { width: 100%; }
64
65/* ── Hero ─────────────────────────────────────────────────────────── */
66.hub-hero {
67 display: flex; align-items: center; justify-content: center;
68 min-height: clamp(340px, 58vh, 560px);
69 text-align: center;
70 background:
71 radial-gradient(130% 130% at 50% -10%, color-mix(in srgb, var(--accent) 26%, var(--paper)) 0%, var(--paper) 62%);
72 border-bottom: 1px solid var(--rule);
73}
74.hub-hero.has-img {
75 background:
76 linear-gradient(180deg, rgba(0,0,0,.45) 0%, rgba(0,0,0,.55) 100%),
77 var(--hero-img) center / cover no-repeat;
78 border-bottom: 0;
79 color: #fff;
80}
81.hub-hero-inner { padding: 3.5rem 1rem; }
82.hub-hero-title {
83 font-family: var(--font-display, serif);
84 font-size: clamp(2.6rem, 7vw, 4.4rem);
85 line-height: 1.02; margin: 0; letter-spacing: -0.015em;
86}
87.hub-hero-tag {
88 margin: 0.7rem 0 0; font-size: 1.05rem; font-weight: 600;
89 text-transform: uppercase; letter-spacing: 0.1em;
90 color: var(--accent);
91}
92.hub-hero.has-img .hub-hero-tag { color: #fff; opacity: 0.92; }
93.hub-hero-desc {
94 margin: 1.1rem auto 0; max-width: 48ch;
95 font-size: 1.1rem; line-height: 1.55; color: var(--ink-muted);
96}
97.hub-hero.has-img .hub-hero-desc { color: rgba(255,255,255,.9); }
98
99.hub-body { padding-bottom: 4.5rem; }
100.hub-sec { margin-top: 3rem; }
101.hub-sec-title {
102 font-family: var(--font-display, serif);
103 font-size: 1.5rem; margin: 0 0 1.2rem;
104 display: flex; align-items: center; gap: 0.75rem;
105}
106.hub-sec-title::after { content: ''; flex: 1; height: 1px; background: var(--rule); }
107
108/* ── Roster (artiesten) ───────────────────────────────────────────── */
109.roster {
110 display: grid;
111 grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
112 gap: 1rem;
113}
114.roster-card {
115 display: flex; flex-direction: column; align-items: center; text-align: center;
116 gap: 0.4rem; padding: 1.6rem 1rem 1.3rem;
117 border: 1px solid var(--rule); border-radius: 16px;
118 background: var(--paper-2); color: var(--ink); text-decoration: none;
119 transition: border-color 140ms, transform 140ms, box-shadow 140ms;
120}
121.roster-card:hover {
122 border-color: var(--accent); transform: translateY(-3px);
123 box-shadow: 0 10px 28px -14px color-mix(in srgb, var(--accent) 55%, transparent);
124}
125.roster-avatar {
126 width: 88px; height: 88px; border-radius: 50%; margin-bottom: 0.45rem;
127 background-size: cover; background-position: center;
128 display: inline-flex; align-items: center; justify-content: center;
129 font-family: var(--font-display, serif); font-size: 2.1rem; font-weight: 700; color: #fff;
130 box-shadow: inset 0 0 0 2px rgba(255,255,255,.18);
131}
132.roster-name { font-weight: 700; font-size: 1.1rem; }
133.roster-tag { color: var(--ink-muted); font-size: 0.82rem; }
134.roster-count {
135 margin-top: 0.35rem; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em;
136 color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent);
137 padding: 0.15rem 0.6rem; border-radius: 99px;
138}
139
140/* ── Feed (laatste posts) ─────────────────────────────────────────── */
141.hub-feed { display: flex; flex-direction: column; gap: 0.6rem; }
142.feed-item {
143 display: flex; align-items: center; gap: 1rem;
144 padding: 0.9rem 1rem; border: 1px solid var(--rule); border-radius: 12px;
145 background: var(--paper-2); color: var(--ink); text-decoration: none;
146 transition: border-color 140ms, background 140ms;
147}
148.feed-item:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 5%, var(--paper-2)); }
149.feed-cover {
150 width: 64px; height: 64px; border-radius: 8px; flex-shrink: 0;
151 background-size: cover; background-position: center; background-color: var(--paper);
152}
153.feed-body { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; flex: 1; }
154.feed-meta { font-size: 0.76rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--accent); }
155.feed-title { font-weight: 600; font-size: 1.05rem; line-height: 1.25; }
156.feed-excerpt {
157 color: var(--ink-muted); font-size: 0.88rem; line-height: 1.4;
158 display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden;
159}
160.feed-arrow { color: var(--ink-muted); font-size: 1.2rem; flex-shrink: 0; transition: transform 140ms, color 140ms; }
161.feed-item:hover .feed-arrow { color: var(--accent); transform: translateX(3px); }
162
163@media (max-width: 560px) {
164 .hub-hero-inner { padding: 2.5rem 1rem; }
165 .feed-cover { width: 52px; height: 52px; }
166 .feed-arrow { display: none; }
167}
168</style>
Note: See TracBrowser for help on using the repository browser.