v1.8.14: branding — full color override (glass/glow/rgba/secondary), bg color+image control
This commit is contained in:
@@ -128,6 +128,8 @@ class BrandingUpdate(BaseModel):
|
|||||||
primary_color: str = None
|
primary_color: str = None
|
||||||
secondary_color: str = None
|
secondary_color: str = None
|
||||||
logo_size: str = None
|
logo_size: str = None
|
||||||
|
bg_color: str = None
|
||||||
|
bg_image: str = None
|
||||||
logo_url: str = None
|
logo_url: str = None
|
||||||
|
|
||||||
class ClaudeKeyUpdate(BaseModel):
|
class ClaudeKeyUpdate(BaseModel):
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+92
-18
@@ -557,6 +557,22 @@ a[role=button]:active {
|
|||||||
<input id="b-secondary-hex" class="flex-1 bg-surface-high border border-outline-variant rounded-xl px-4 py-3 text-sm font-mono outline-none focus:border-primary transition-colors" oninput="if(this.value.match(/^#[0-9a-fA-F]{6}$/)){document.getElementById('b-secondary').value=this.value;document.getElementById('preview-secondary').style.background=this.value}"/>
|
<input id="b-secondary-hex" class="flex-1 bg-surface-high border border-outline-variant rounded-xl px-4 py-3 text-sm font-mono outline-none focus:border-primary transition-colors" oninput="if(this.value.match(/^#[0-9a-fA-F]{6}$/)){document.getElementById('b-secondary').value=this.value;document.getElementById('preview-secondary').style.background=this.value}"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Background -->
|
||||||
|
<div>
|
||||||
|
<label class="text-xs text-on-surface-variant mb-2 block">Background Color</label>
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<input type="color" id="b-bg-color" class="w-12 h-12 rounded-xl border border-outline-variant cursor-pointer bg-transparent"
|
||||||
|
oninput="document.getElementById('b-bg-color-hex').value=this.value;document.body.style.background=this.value"/>
|
||||||
|
<input id="b-bg-color-hex" class="flex-1 bg-surface-high border border-outline-variant rounded-xl px-4 py-3 text-sm font-mono outline-none focus:border-primary transition-colors"
|
||||||
|
oninput="if(this.value.match(/^#[0-9a-fA-F]{6}$/)){document.getElementById('b-bg-color').value=this.value;document.body.style.background=this.value}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="text-xs text-on-surface-variant mb-2 block">Background Image URL <span class="text-[10px] opacity-50">(overrides color)</span></label>
|
||||||
|
<input id="b-bg-image" placeholder="https://example.com/bg.jpg"
|
||||||
|
class="w-full bg-surface-high border border-outline-variant rounded-xl px-4 py-3 text-sm outline-none focus:border-primary transition-colors"
|
||||||
|
oninput="if(this.value){document.body.style.backgroundImage='url('+this.value+')';document.body.style.backgroundSize='cover';}else{document.body.style.backgroundImage='';}" />
|
||||||
|
</div>
|
||||||
<div class="glass rounded-xl p-4">
|
<div class="glass rounded-xl p-4">
|
||||||
<p class="text-xs text-on-surface-variant mb-3">Preview</p>
|
<p class="text-xs text-on-surface-variant mb-3">Preview</p>
|
||||||
<div class="flex gap-3">
|
<div class="flex gap-3">
|
||||||
@@ -927,28 +943,83 @@ curl -X POST https://rag.afaqzaid.com/ingest-url \
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// -- Branding color override --------------------------------------------------
|
// -- Branding color override --------------------------------------------------
|
||||||
function applyBrandingColors(p, s) {
|
function applyBrandingColors(p, s, bg, bgImg) {
|
||||||
p = p || '#4edea3'; s = s || '#95d3ba';
|
p = p || '#4edea3';
|
||||||
const hr = (hex) => { const r=parseInt(hex.slice(1,3),16),g=parseInt(hex.slice(3,5),16),b=parseInt(hex.slice(5,7),16); return r+','+g+','+b; };
|
s = s || '#95d3ba';
|
||||||
const pr = hr(p), sr = hr(s);
|
bg = bg || '#0c1324';
|
||||||
|
const hr = (hex) => {
|
||||||
|
hex = hex.replace('#','');
|
||||||
|
if(hex.length === 3) hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];
|
||||||
|
return parseInt(hex.slice(0,2),16)+','+parseInt(hex.slice(2,4),16)+','+parseInt(hex.slice(4,6),16);
|
||||||
|
};
|
||||||
|
const pr = hr(p), sr = hr(s), bgr = hr(bg);
|
||||||
|
// Background
|
||||||
|
if(bgImg) { document.body.style.backgroundImage='url('+bgImg+')'; document.body.style.backgroundSize='cover'; document.body.style.backgroundPosition='center'; }
|
||||||
|
else { document.body.style.backgroundImage=''; document.body.style.background='radial-gradient(circle at 50% -20%,'+bg+' 0%,'+bg+' 100%)'; }
|
||||||
|
// Remove old style
|
||||||
const old = document.getElementById('_bco'); if(old) old.remove();
|
const old = document.getElementById('_bco'); if(old) old.remove();
|
||||||
const st = document.createElement('style'); st.id='_bco';
|
const st = document.createElement('style'); st.id='_bco';
|
||||||
st.textContent=
|
st.textContent = [
|
||||||
'.text-primary{color:'+p+'!important}.bg-primary{background-color:'+p+'!important}.border-primary{border-color:'+p+'!important}'+
|
// Primary color — text, bg, border
|
||||||
'.text-secondary{color:'+s+'!important}.bg-secondary{background-color:'+s+'!important}'+
|
'.text-primary{color:'+p+'!important}',
|
||||||
'.glass{border-color:rgba('+pr+',0.12)!important}'+
|
'.bg-primary{background-color:'+p+'!important}',
|
||||||
'.glass-hover:hover{background:rgba('+pr+',0.06)!important;border-color:rgba('+pr+',0.25)!important}'+
|
'.border-primary{border-color:'+p+'!important}',
|
||||||
'.glow{box-shadow:0 0 20px rgba('+pr+',0.15)!important}'+
|
'[class*="text-primary"]{color:'+p+'!important}',
|
||||||
'.glow-sm{box-shadow:0 0 10px rgba('+pr+',0.1)!important}'+
|
'[class*="bg-primary\\/"]{}',
|
||||||
'.glass.glow{box-shadow:inset 0 1px 0 rgba(255,255,255,0.06),0 0 20px rgba('+pr+',0.18),0 4px 24px rgba(0,0,0,0.15)!important}'+
|
// Secondary
|
||||||
'.upload-zone{border-color:rgba('+pr+',0.2)!important}'+
|
'.text-secondary{color:'+s+'!important}',
|
||||||
'.scrollbar::-webkit-scrollbar-thumb{background:rgba('+pr+',0.2)!important}';
|
'.bg-secondary{background-color:'+s+'!important}',
|
||||||
|
'.border-secondary{border-color:'+s+'!important}',
|
||||||
|
'.text-tertiary{color:'+s+'!important}',
|
||||||
|
// Hover/focus states
|
||||||
|
'.hover\\:text-primary:hover{color:'+p+'!important}',
|
||||||
|
'.hover\\:bg-primary\\/5:hover{background-color:rgba('+pr+',0.05)!important}',
|
||||||
|
'.focus\\:border-primary:focus{border-color:'+p+'!important}',
|
||||||
|
// Active nav
|
||||||
|
'.active.bg-primary\\/10{background-color:rgba('+pr+',0.1)!important}',
|
||||||
|
'.active.text-primary{color:'+p+'!important}',
|
||||||
|
'button.active{color:'+p+'!important}',
|
||||||
|
// Glass
|
||||||
|
'.glass{border-color:rgba('+pr+',0.12)!important}',
|
||||||
|
'.glass-hover:hover{background:rgba('+pr+',0.06)!important;border-color:rgba('+pr+',0.25)!important}',
|
||||||
|
// Glows
|
||||||
|
'.glow{box-shadow:0 0 20px rgba('+pr+',0.15)!important}',
|
||||||
|
'.glow-sm{box-shadow:0 0 10px rgba('+pr+',0.1)!important}',
|
||||||
|
'.glass.glow{box-shadow:inset 0 1px 0 rgba(255,255,255,0.06),0 0 20px rgba('+pr+',0.18),0 4px 24px rgba(0,0,0,0.15)!important}',
|
||||||
|
'.glass.glow-sm{box-shadow:inset 0 1px 0 rgba(255,255,255,0.06),0 0 10px rgba('+pr+',0.12)!important}',
|
||||||
|
// Spotlight card gradient
|
||||||
|
'.spotlight-card::before{background:radial-gradient(400px circle at var(--mx,50%) var(--my,50%),rgba('+pr+',0.06),transparent 60%)!important}',
|
||||||
|
// Alpha variants
|
||||||
|
'.bg-primary\\/15,.bg-primary\\/10,.bg-primary\\/5{background-color:rgba('+pr+',0.1)!important}',
|
||||||
|
'.border-primary\\/20{border-color:rgba('+pr+',0.2)!important}',
|
||||||
|
'.border-primary\\/30{border-color:rgba('+pr+',0.3)!important}',
|
||||||
|
// Upload zone
|
||||||
|
'.upload-zone{border-color:rgba('+pr+',0.2)!important}',
|
||||||
|
'.upload-zone.dragover{border-color:rgba('+pr+',0.6)!important}',
|
||||||
|
// Scrollbar
|
||||||
|
'.scrollbar::-webkit-scrollbar-thumb{background:rgba('+pr+',0.2)!important}',
|
||||||
|
// Input focus
|
||||||
|
'.inp:focus,.inp:focus-within{border-color:'+p+'!important;box-shadow:0 0 0 2px rgba('+pr+',0.1)!important}',
|
||||||
|
// Filter chips active
|
||||||
|
'.filter-chip.active{background:rgba('+pr+',0.12)!important;border-color:rgba('+pr+',0.4)!important;color:'+p+'!important}',
|
||||||
|
// Book card hover
|
||||||
|
'.book-card:hover{box-shadow:0 8px 24px rgba('+pr+',0.1)!important;border-color:rgba('+pr+',0.28)!important}',
|
||||||
|
// Nav active
|
||||||
|
'.nav-btn.active{background-color:rgba('+pr+',0.1)!important;color:'+p+'!important}',
|
||||||
|
// Sidebar border
|
||||||
|
'aside{border-color:rgba('+pr+',0.2)!important}',
|
||||||
|
// CTA button shimmer
|
||||||
|
'.cta-primary::before{background:linear-gradient(90deg,transparent,rgba('+pr+',0.1),transparent)!important}',
|
||||||
|
// Shadow glow on hover
|
||||||
|
'[class*="hover:shadow"]:hover{--tw-shadow-color:rgba('+pr+',0.4)!important}',
|
||||||
|
].join('\n');
|
||||||
document.head.appendChild(st);
|
document.head.appendChild(st);
|
||||||
document.documentElement.style.setProperty('--primary', p);
|
document.documentElement.style.setProperty('--primary', p);
|
||||||
document.documentElement.style.setProperty('--secondary', s);
|
document.documentElement.style.setProperty('--secondary', s);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ADMIN_KEY removed - JWT-only auth
|
// ADMIN_KEY removed - JWT-only auth
|
||||||
let JWT_TOKEN = localStorage.getItem('admin_jwt') || '';
|
let JWT_TOKEN = localStorage.getItem('admin_jwt') || '';
|
||||||
const RAG_KEY = 'zRf77E_brSEnA2BUi40uxLxT4uofAk661WMZb-cdv4M';
|
const RAG_KEY = 'zRf77E_brSEnA2BUi40uxLxT4uofAk661WMZb-cdv4M';
|
||||||
@@ -1542,13 +1613,16 @@ async function loadBranding() {
|
|||||||
document.getElementById('b-site-name').value = d.site_name||'';
|
document.getElementById('b-site-name').value = d.site_name||'';
|
||||||
document.getElementById('b-subtitle').value = d.site_subtitle||'';
|
document.getElementById('b-subtitle').value = d.site_subtitle||'';
|
||||||
document.getElementById('b-logo').value = d.logo_url||'';
|
document.getElementById('b-logo').value = d.logo_url||'';
|
||||||
|
document.getElementById('b-bg-color').value = d.bg_color||'#0c1324';
|
||||||
|
document.getElementById('b-bg-color-hex').value = d.bg_color||'#0c1324';
|
||||||
|
document.getElementById('b-bg-image').value = d.bg_image||'';
|
||||||
document.getElementById('b-primary').value = d.primary_color||'#4edea3';
|
document.getElementById('b-primary').value = d.primary_color||'#4edea3';
|
||||||
document.getElementById('b-primary-hex').value = d.primary_color||'#4edea3';
|
document.getElementById('b-primary-hex').value = d.primary_color||'#4edea3';
|
||||||
document.getElementById('b-secondary').value = d.secondary_color||'#95d3ba';
|
document.getElementById('b-secondary').value = d.secondary_color||'#95d3ba';
|
||||||
document.getElementById('b-secondary-hex').value = d.secondary_color||'#95d3ba';
|
document.getElementById('b-secondary-hex').value = d.secondary_color||'#95d3ba';
|
||||||
document.getElementById('preview-primary').style.background = d.primary_color||'#4edea3';
|
document.getElementById('preview-primary').style.background = d.primary_color||'#4edea3';
|
||||||
document.getElementById('preview-secondary').style.background = d.secondary_color||'#95d3ba';
|
document.getElementById('preview-secondary').style.background = d.secondary_color||'#95d3ba';
|
||||||
applyBrandingColors(d.primary_color, d.secondary_color);
|
applyBrandingColors(d.primary_color,d.secondary_color,d.bg_color,d.bg_image);
|
||||||
// Logo
|
// Logo
|
||||||
if(d.logo_url) document.getElementById('b-logo').value = d.logo_url;
|
if(d.logo_url) document.getElementById('b-logo').value = d.logo_url;
|
||||||
if(d.logo_size) document.getElementById('b-logo-size').value = d.logo_size;
|
if(d.logo_size) document.getElementById('b-logo-size').value = d.logo_size;
|
||||||
@@ -1564,12 +1638,12 @@ async function loadBranding() {
|
|||||||
|
|
||||||
async function saveBranding() {
|
async function saveBranding() {
|
||||||
try {
|
try {
|
||||||
const r = await fetch('/admin/branding', {method:'POST', headers:{'Content-Type':'application/json','Authorization':'Bearer '+JWT_TOKEN}, body:JSON.stringify({site_name:document.getElementById('b-site-name').value, site_subtitle:document.getElementById('b-subtitle').value, logo_url:document.getElementById('b-logo').value, logo_size:document.getElementById('b-logo-size')?.value||'40', primary_color:document.getElementById('b-primary-hex').value, secondary_color:document.getElementById('b-secondary-hex').value})});
|
const r = await fetch('/admin/branding', {method:'POST', headers:{'Content-Type':'application/json','Authorization':'Bearer '+JWT_TOKEN}, body:JSON.stringify({site_name:document.getElementById('b-site-name').value, site_subtitle:document.getElementById('b-subtitle').value, logo_url:document.getElementById('b-logo').value, logo_size:document.getElementById('b-logo-size')?.value||'40', primary_color:document.getElementById('b-primary-hex').value, secondary_color:document.getElementById('b-secondary-hex').value, bg_color:document.getElementById('b-bg-color-hex')?.value||'#0c1324', bg_image:document.getElementById('b-bg-image')?.value||''})});
|
||||||
if (r.ok) {
|
if (r.ok) {
|
||||||
toast('Branding saved!','success');
|
toast('Branding saved!','success');
|
||||||
const p=document.getElementById('b-primary-hex')?.value;
|
const p=document.getElementById('b-primary-hex')?.value;
|
||||||
const s=document.getElementById('b-secondary-hex')?.value;
|
const s=document.getElementById('b-secondary-hex')?.value;
|
||||||
if(p||s) applyBrandingColors(p,s);
|
applyBrandingColors(p,s,document.getElementById("b-bg-color")?.value,document.getElementById("b-bg-image")?.value);
|
||||||
} else { alert('Save failed'); }
|
} else { alert('Save failed'); }
|
||||||
} catch(e) { alert('Error: '+e.message); }
|
} catch(e) { alert('Error: '+e.message); }
|
||||||
}
|
}
|
||||||
|
|||||||
+71
-16
@@ -371,23 +371,78 @@ let currentUser = null;
|
|||||||
|
|
||||||
// ── Branding ──────────────────────────────────────────────────────────────────
|
// ── Branding ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
function applyBrandingColors(p, s) {
|
// -- Branding color override --------------------------------------------------
|
||||||
p = p || '#4edea3'; s = s || '#95d3ba';
|
function applyBrandingColors(p, s, bg, bgImg) {
|
||||||
const hr = (hex) => { const r=parseInt(hex.slice(1,3),16),g=parseInt(hex.slice(3,5),16),b=parseInt(hex.slice(5,7),16); return r+','+g+','+b; };
|
p = p || '#4edea3';
|
||||||
const pr = hr(p), sr = hr(s);
|
s = s || '#95d3ba';
|
||||||
|
bg = bg || '#0c1324';
|
||||||
|
const hr = (hex) => {
|
||||||
|
hex = hex.replace('#','');
|
||||||
|
if(hex.length === 3) hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];
|
||||||
|
return parseInt(hex.slice(0,2),16)+','+parseInt(hex.slice(2,4),16)+','+parseInt(hex.slice(4,6),16);
|
||||||
|
};
|
||||||
|
const pr = hr(p), sr = hr(s), bgr = hr(bg);
|
||||||
|
// Background
|
||||||
|
if(bgImg) { document.body.style.backgroundImage='url('+bgImg+')'; document.body.style.backgroundSize='cover'; document.body.style.backgroundPosition='center'; }
|
||||||
|
else { document.body.style.backgroundImage=''; document.body.style.background='radial-gradient(circle at 50% -20%,'+bg+' 0%,'+bg+' 100%)'; }
|
||||||
|
// Remove old style
|
||||||
const old = document.getElementById('_bco'); if(old) old.remove();
|
const old = document.getElementById('_bco'); if(old) old.remove();
|
||||||
const st = document.createElement('style'); st.id='_bco';
|
const st = document.createElement('style'); st.id='_bco';
|
||||||
st.textContent=
|
st.textContent = [
|
||||||
'.text-primary{color:'+p+'!important}.bg-primary{background-color:'+p+'!important}.border-primary{border-color:'+p+'!important}'+
|
// Primary color — text, bg, border
|
||||||
'.text-secondary{color:'+s+'!important}.bg-secondary{background-color:'+s+'!important}'+
|
'.text-primary{color:'+p+'!important}',
|
||||||
'.glass{border-color:rgba('+pr+',0.12)!important}'+
|
'.bg-primary{background-color:'+p+'!important}',
|
||||||
'.glass-hover:hover{background:rgba('+pr+',0.06)!important;border-color:rgba('+pr+',0.25)!important}'+
|
'.border-primary{border-color:'+p+'!important}',
|
||||||
'.glow{box-shadow:0 0 20px rgba('+pr+',0.15)!important}'+
|
'[class*="text-primary"]{color:'+p+'!important}',
|
||||||
'.glow-sm{box-shadow:0 0 10px rgba('+pr+',0.1)!important}'+
|
'[class*="bg-primary\/"]{}',
|
||||||
'.glass.glow{box-shadow:inset 0 1px 0 rgba(255,255,255,0.06),0 0 20px rgba('+pr+',0.18),0 4px 24px rgba(0,0,0,0.15)!important}'+
|
// Secondary
|
||||||
'.upload-zone{border-color:rgba('+pr+',0.2)!important}'+
|
'.text-secondary{color:'+s+'!important}',
|
||||||
'.upload-zone:hover{border-color:rgba('+pr+',0.4)!important}'+
|
'.bg-secondary{background-color:'+s+'!important}',
|
||||||
'.scrollbar::-webkit-scrollbar-thumb{background:rgba('+pr+',0.2)!important}';
|
'.border-secondary{border-color:'+s+'!important}',
|
||||||
|
'.text-tertiary{color:'+s+'!important}',
|
||||||
|
// Hover/focus states
|
||||||
|
'.hover\:text-primary:hover{color:'+p+'!important}',
|
||||||
|
'.hover\:bg-primary\/5:hover{background-color:rgba('+pr+',0.05)!important}',
|
||||||
|
'.focus\:border-primary:focus{border-color:'+p+'!important}',
|
||||||
|
// Active nav
|
||||||
|
'.active.bg-primary\/10{background-color:rgba('+pr+',0.1)!important}',
|
||||||
|
'.active.text-primary{color:'+p+'!important}',
|
||||||
|
'button.active{color:'+p+'!important}',
|
||||||
|
// Glass
|
||||||
|
'.glass{border-color:rgba('+pr+',0.12)!important}',
|
||||||
|
'.glass-hover:hover{background:rgba('+pr+',0.06)!important;border-color:rgba('+pr+',0.25)!important}',
|
||||||
|
// Glows
|
||||||
|
'.glow{box-shadow:0 0 20px rgba('+pr+',0.15)!important}',
|
||||||
|
'.glow-sm{box-shadow:0 0 10px rgba('+pr+',0.1)!important}',
|
||||||
|
'.glass.glow{box-shadow:inset 0 1px 0 rgba(255,255,255,0.06),0 0 20px rgba('+pr+',0.18),0 4px 24px rgba(0,0,0,0.15)!important}',
|
||||||
|
'.glass.glow-sm{box-shadow:inset 0 1px 0 rgba(255,255,255,0.06),0 0 10px rgba('+pr+',0.12)!important}',
|
||||||
|
// Spotlight card gradient
|
||||||
|
'.spotlight-card::before{background:radial-gradient(400px circle at var(--mx,50%) var(--my,50%),rgba('+pr+',0.06),transparent 60%)!important}',
|
||||||
|
// Alpha variants
|
||||||
|
'.bg-primary\/15,.bg-primary\/10,.bg-primary\/5{background-color:rgba('+pr+',0.1)!important}',
|
||||||
|
'.border-primary\/20{border-color:rgba('+pr+',0.2)!important}',
|
||||||
|
'.border-primary\/30{border-color:rgba('+pr+',0.3)!important}',
|
||||||
|
// Upload zone
|
||||||
|
'.upload-zone{border-color:rgba('+pr+',0.2)!important}',
|
||||||
|
'.upload-zone.dragover{border-color:rgba('+pr+',0.6)!important}',
|
||||||
|
// Scrollbar
|
||||||
|
'.scrollbar::-webkit-scrollbar-thumb{background:rgba('+pr+',0.2)!important}',
|
||||||
|
// Input focus
|
||||||
|
'.inp:focus,.inp:focus-within{border-color:'+p+'!important;box-shadow:0 0 0 2px rgba('+pr+',0.1)!important}',
|
||||||
|
// Filter chips active
|
||||||
|
'.filter-chip.active{background:rgba('+pr+',0.12)!important;border-color:rgba('+pr+',0.4)!important;color:'+p+'!important}',
|
||||||
|
// Book card hover
|
||||||
|
'.book-card:hover{box-shadow:0 8px 24px rgba('+pr+',0.1)!important;border-color:rgba('+pr+',0.28)!important}',
|
||||||
|
// Nav active
|
||||||
|
'.nav-btn.active{background-color:rgba('+pr+',0.1)!important;color:'+p+'!important}',
|
||||||
|
// Sidebar border
|
||||||
|
'aside{border-color:rgba('+pr+',0.2)!important}',
|
||||||
|
// CTA button shimmer
|
||||||
|
'.cta-primary::before{background:linear-gradient(90deg,transparent,rgba('+pr+',0.1),transparent)!important}',
|
||||||
|
// Shadow glow on hover
|
||||||
|
'[class*="hover:shadow"]:hover{--tw-shadow-color:rgba('+pr+',0.4)!important}',
|
||||||
|
].join('
|
||||||
|
');
|
||||||
document.head.appendChild(st);
|
document.head.appendChild(st);
|
||||||
document.documentElement.style.setProperty('--primary', p);
|
document.documentElement.style.setProperty('--primary', p);
|
||||||
document.documentElement.style.setProperty('--secondary', s);
|
document.documentElement.style.setProperty('--secondary', s);
|
||||||
@@ -395,7 +450,7 @@ function applyBrandingColors(p, s) {
|
|||||||
fetch('/branding').then(r=>r.json()).then(b=>{
|
fetch('/branding').then(r=>r.json()).then(b=>{
|
||||||
if(b.site_name){document.title=b.site_name;const bn=document.getElementById('brand-name');if(bn)bn.textContent=b.site_name;}
|
if(b.site_name){document.title=b.site_name;const bn=document.getElementById('brand-name');if(bn)bn.textContent=b.site_name;}
|
||||||
if(b.site_subtitle){const bs=document.getElementById('brand-sub');if(bs)bs.textContent=b.site_subtitle;}
|
if(b.site_subtitle){const bs=document.getElementById('brand-sub');if(bs)bs.textContent=b.site_subtitle;}
|
||||||
if(b.primary_color||b.secondary_color){applyBrandingColors(b.primary_color,b.secondary_color);}
|
applyBrandingColors(b.primary_color,b.secondary_color,b.bg_color,b.bg_image);
|
||||||
if(b.logo_url){
|
if(b.logo_url){
|
||||||
const logo=document.getElementById('brand-logo');
|
const logo=document.getElementById('brand-logo');
|
||||||
if(logo){logo.src=b.logo_url;logo.style.height=(b.logo_size||'40')+'px';logo.classList.remove('hidden');}
|
if(logo){logo.src=b.logo_url;logo.style.height=(b.logo_size||'40')+'px';logo.classList.remove('hidden');}
|
||||||
|
|||||||
+71
-16
@@ -651,30 +651,85 @@ async function toggleFav(bookId, btn, e) {
|
|||||||
|
|
||||||
// ── Branding ───────────────────────────────────────────────────────────────
|
// ── Branding ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
function applyBrandingColors(p, s) {
|
// -- Branding color override --------------------------------------------------
|
||||||
p = p || '#4edea3'; s = s || '#95d3ba';
|
function applyBrandingColors(p, s, bg, bgImg) {
|
||||||
const hr = (hex) => { const r=parseInt(hex.slice(1,3),16),g=parseInt(hex.slice(3,5),16),b=parseInt(hex.slice(5,7),16); return r+','+g+','+b; };
|
p = p || '#4edea3';
|
||||||
const pr = hr(p), sr = hr(s);
|
s = s || '#95d3ba';
|
||||||
|
bg = bg || '#0c1324';
|
||||||
|
const hr = (hex) => {
|
||||||
|
hex = hex.replace('#','');
|
||||||
|
if(hex.length === 3) hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];
|
||||||
|
return parseInt(hex.slice(0,2),16)+','+parseInt(hex.slice(2,4),16)+','+parseInt(hex.slice(4,6),16);
|
||||||
|
};
|
||||||
|
const pr = hr(p), sr = hr(s), bgr = hr(bg);
|
||||||
|
// Background
|
||||||
|
if(bgImg) { document.body.style.backgroundImage='url('+bgImg+')'; document.body.style.backgroundSize='cover'; document.body.style.backgroundPosition='center'; }
|
||||||
|
else { document.body.style.backgroundImage=''; document.body.style.background='radial-gradient(circle at 50% -20%,'+bg+' 0%,'+bg+' 100%)'; }
|
||||||
|
// Remove old style
|
||||||
const old = document.getElementById('_bco'); if(old) old.remove();
|
const old = document.getElementById('_bco'); if(old) old.remove();
|
||||||
const st = document.createElement('style'); st.id='_bco';
|
const st = document.createElement('style'); st.id='_bco';
|
||||||
st.textContent=
|
st.textContent = [
|
||||||
'.text-primary{color:'+p+'!important}.bg-primary{background-color:'+p+'!important}.border-primary{border-color:'+p+'!important}'+
|
// Primary color — text, bg, border
|
||||||
'.text-secondary{color:'+s+'!important}.bg-secondary{background-color:'+s+'!important}'+
|
'.text-primary{color:'+p+'!important}',
|
||||||
'.glass{border-color:rgba('+pr+',0.12)!important}'+
|
'.bg-primary{background-color:'+p+'!important}',
|
||||||
'.glass-hover:hover{background:rgba('+pr+',0.06)!important;border-color:rgba('+pr+',0.25)!important}'+
|
'.border-primary{border-color:'+p+'!important}',
|
||||||
'.glow{box-shadow:0 0 20px rgba('+pr+',0.15)!important}'+
|
'[class*="text-primary"]{color:'+p+'!important}',
|
||||||
'.glow-sm{box-shadow:0 0 10px rgba('+pr+',0.1)!important}'+
|
'[class*="bg-primary\/"]{}',
|
||||||
'.glass.glow{box-shadow:inset 0 1px 0 rgba(255,255,255,0.06),0 0 20px rgba('+pr+',0.18),0 4px 24px rgba(0,0,0,0.15)!important}'+
|
// Secondary
|
||||||
'.upload-zone{border-color:rgba('+pr+',0.2)!important}'+
|
'.text-secondary{color:'+s+'!important}',
|
||||||
'.upload-zone:hover{border-color:rgba('+pr+',0.4)!important}'+
|
'.bg-secondary{background-color:'+s+'!important}',
|
||||||
'.scrollbar::-webkit-scrollbar-thumb{background:rgba('+pr+',0.2)!important}';
|
'.border-secondary{border-color:'+s+'!important}',
|
||||||
|
'.text-tertiary{color:'+s+'!important}',
|
||||||
|
// Hover/focus states
|
||||||
|
'.hover\:text-primary:hover{color:'+p+'!important}',
|
||||||
|
'.hover\:bg-primary\/5:hover{background-color:rgba('+pr+',0.05)!important}',
|
||||||
|
'.focus\:border-primary:focus{border-color:'+p+'!important}',
|
||||||
|
// Active nav
|
||||||
|
'.active.bg-primary\/10{background-color:rgba('+pr+',0.1)!important}',
|
||||||
|
'.active.text-primary{color:'+p+'!important}',
|
||||||
|
'button.active{color:'+p+'!important}',
|
||||||
|
// Glass
|
||||||
|
'.glass{border-color:rgba('+pr+',0.12)!important}',
|
||||||
|
'.glass-hover:hover{background:rgba('+pr+',0.06)!important;border-color:rgba('+pr+',0.25)!important}',
|
||||||
|
// Glows
|
||||||
|
'.glow{box-shadow:0 0 20px rgba('+pr+',0.15)!important}',
|
||||||
|
'.glow-sm{box-shadow:0 0 10px rgba('+pr+',0.1)!important}',
|
||||||
|
'.glass.glow{box-shadow:inset 0 1px 0 rgba(255,255,255,0.06),0 0 20px rgba('+pr+',0.18),0 4px 24px rgba(0,0,0,0.15)!important}',
|
||||||
|
'.glass.glow-sm{box-shadow:inset 0 1px 0 rgba(255,255,255,0.06),0 0 10px rgba('+pr+',0.12)!important}',
|
||||||
|
// Spotlight card gradient
|
||||||
|
'.spotlight-card::before{background:radial-gradient(400px circle at var(--mx,50%) var(--my,50%),rgba('+pr+',0.06),transparent 60%)!important}',
|
||||||
|
// Alpha variants
|
||||||
|
'.bg-primary\/15,.bg-primary\/10,.bg-primary\/5{background-color:rgba('+pr+',0.1)!important}',
|
||||||
|
'.border-primary\/20{border-color:rgba('+pr+',0.2)!important}',
|
||||||
|
'.border-primary\/30{border-color:rgba('+pr+',0.3)!important}',
|
||||||
|
// Upload zone
|
||||||
|
'.upload-zone{border-color:rgba('+pr+',0.2)!important}',
|
||||||
|
'.upload-zone.dragover{border-color:rgba('+pr+',0.6)!important}',
|
||||||
|
// Scrollbar
|
||||||
|
'.scrollbar::-webkit-scrollbar-thumb{background:rgba('+pr+',0.2)!important}',
|
||||||
|
// Input focus
|
||||||
|
'.inp:focus,.inp:focus-within{border-color:'+p+'!important;box-shadow:0 0 0 2px rgba('+pr+',0.1)!important}',
|
||||||
|
// Filter chips active
|
||||||
|
'.filter-chip.active{background:rgba('+pr+',0.12)!important;border-color:rgba('+pr+',0.4)!important;color:'+p+'!important}',
|
||||||
|
// Book card hover
|
||||||
|
'.book-card:hover{box-shadow:0 8px 24px rgba('+pr+',0.1)!important;border-color:rgba('+pr+',0.28)!important}',
|
||||||
|
// Nav active
|
||||||
|
'.nav-btn.active{background-color:rgba('+pr+',0.1)!important;color:'+p+'!important}',
|
||||||
|
// Sidebar border
|
||||||
|
'aside{border-color:rgba('+pr+',0.2)!important}',
|
||||||
|
// CTA button shimmer
|
||||||
|
'.cta-primary::before{background:linear-gradient(90deg,transparent,rgba('+pr+',0.1),transparent)!important}',
|
||||||
|
// Shadow glow on hover
|
||||||
|
'[class*="hover:shadow"]:hover{--tw-shadow-color:rgba('+pr+',0.4)!important}',
|
||||||
|
].join('
|
||||||
|
');
|
||||||
document.head.appendChild(st);
|
document.head.appendChild(st);
|
||||||
document.documentElement.style.setProperty('--primary', p);
|
document.documentElement.style.setProperty('--primary', p);
|
||||||
document.documentElement.style.setProperty('--secondary', s);
|
document.documentElement.style.setProperty('--secondary', s);
|
||||||
}
|
}
|
||||||
fetch('/branding').then(r=>r.json()).then(b=>{
|
fetch('/branding').then(r=>r.json()).then(b=>{
|
||||||
if(b.site_name){const bn=document.getElementById('brand-name');if(bn)bn.textContent=b.site_name;}
|
if(b.site_name){const bn=document.getElementById('brand-name');if(bn)bn.textContent=b.site_name;}
|
||||||
if(b.primary_color||b.secondary_color){applyBrandingColors(b.primary_color,b.secondary_color);}
|
applyBrandingColors(b.primary_color,b.secondary_color,b.bg_color,b.bg_image);
|
||||||
}).catch(()=>{});
|
}).catch(()=>{});
|
||||||
|
|
||||||
// ── Auth Nav ───────────────────────────────────────────────────────────────
|
// ── Auth Nav ───────────────────────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user