Compare commits
No commits in common. 'main' and 'master' have entirely different histories.
12 changed files with 32 additions and 874 deletions
@ -1,549 +0,0 @@ |
|||||||
/* ===== OTB shared theme system ===== */ |
|
||||||
|
|
||||||
:root{ |
|
||||||
--otb-bg-main:#050b19; |
|
||||||
--otb-bg-grad-1:#1f2a57; |
|
||||||
--otb-bg-grad-2:#08111f; |
|
||||||
--otb-bg-grad-3:#143c2d; |
|
||||||
--otb-panel:#0b1330; |
|
||||||
--otb-text:#f1f5ff; |
|
||||||
--otb-muted:#c5cde4; |
|
||||||
--otb-link:#9fd2ff; |
|
||||||
--otb-accent:#62f0cf; |
|
||||||
--otb-border:rgba(255,255,255,0.08); |
|
||||||
--otb-shadow:0 16px 40px rgba(0,0,0,0.28); |
|
||||||
} |
|
||||||
|
|
||||||
html[data-theme="light"]{ |
|
||||||
--otb-bg-main:#eef3fb; |
|
||||||
--otb-bg-grad-1:#f7f9fd; |
|
||||||
--otb-bg-grad-2:#edf3fb; |
|
||||||
--otb-bg-grad-3:#e7f2ec; |
|
||||||
--otb-panel:#ffffff; |
|
||||||
--otb-text:#172033; |
|
||||||
--otb-muted:#55627c; |
|
||||||
--otb-link:#0b63ce; |
|
||||||
--otb-accent:#0e8f73; |
|
||||||
--otb-border:rgba(18,32,60,0.10); |
|
||||||
--otb-shadow:0 10px 28px rgba(16,24,40,0.08); |
|
||||||
} |
|
||||||
|
|
||||||
html, body{ |
|
||||||
background: |
|
||||||
linear-gradient(90deg, var(--otb-bg-grad-1) 0%, var(--otb-bg-grad-2) 48%, var(--otb-bg-grad-3) 100%), |
|
||||||
var(--otb-bg-main) !important; |
|
||||||
color:var(--otb-text) !important; |
|
||||||
} |
|
||||||
|
|
||||||
a{ color:var(--otb-link); } |
|
||||||
|
|
||||||
.site-header{ background:transparent; } |
|
||||||
|
|
||||||
.site-brand strong, |
|
||||||
.site-navlinks > a, |
|
||||||
.dropdown-toggle, |
|
||||||
.site-title strong, |
|
||||||
.site-title span{ |
|
||||||
color:var(--otb-text) !important; |
|
||||||
} |
|
||||||
|
|
||||||
.site-title span, |
|
||||||
.small, |
|
||||||
.lead, |
|
||||||
.sub, |
|
||||||
.portal-sub, |
|
||||||
.portal-note, |
|
||||||
.muted{ |
|
||||||
color:var(--otb-muted) !important; |
|
||||||
} |
|
||||||
|
|
||||||
.card, |
|
||||||
.heroCard, |
|
||||||
.sideCard, |
|
||||||
.feature, |
|
||||||
.portal-card, |
|
||||||
.detail-card, |
|
||||||
.pay-card, |
|
||||||
.snapshot-wrap, |
|
||||||
.note, |
|
||||||
.tableWrap{ |
|
||||||
background:var(--otb-panel) !important; |
|
||||||
border:1px solid var(--otb-border) !important; |
|
||||||
color:var(--otb-text) !important; |
|
||||||
box-shadow:var(--otb-shadow); |
|
||||||
} |
|
||||||
|
|
||||||
.dropdown-menu{ |
|
||||||
background:var(--otb-panel) !important; |
|
||||||
border:1px solid var(--otb-border) !important; |
|
||||||
box-shadow:var(--otb-shadow); |
|
||||||
} |
|
||||||
|
|
||||||
.dropdown-menu a{ |
|
||||||
color:var(--otb-text) !important; |
|
||||||
} |
|
||||||
|
|
||||||
input, |
|
||||||
select, |
|
||||||
textarea{ |
|
||||||
background:rgba(255,255,255,0.06) !important; |
|
||||||
color:var(--otb-text) !important; |
|
||||||
border:1px solid var(--otb-border) !important; |
|
||||||
} |
|
||||||
|
|
||||||
html[data-theme="light"] input, |
|
||||||
html[data-theme="light"] select, |
|
||||||
html[data-theme="light"] textarea{ |
|
||||||
background:#f6f8fc !important; |
|
||||||
} |
|
||||||
|
|
||||||
::placeholder{ |
|
||||||
color:var(--otb-muted); |
|
||||||
opacity:0.85; |
|
||||||
} |
|
||||||
|
|
||||||
.btn, |
|
||||||
.portal-btn{ |
|
||||||
border:1px solid var(--otb-border) !important; |
|
||||||
} |
|
||||||
|
|
||||||
.otb-statusbar{ |
|
||||||
background:#0b1326 !important; |
|
||||||
border-top:1px solid rgba(255,255,255,0.06); |
|
||||||
} |
|
||||||
|
|
||||||
.otb-statusbar-inner{ |
|
||||||
max-width:1200px; |
|
||||||
margin:0 auto; |
|
||||||
padding:10px 18px; |
|
||||||
color:#f3f7ff; |
|
||||||
display:flex; |
|
||||||
justify-content:center; |
|
||||||
align-items:center; |
|
||||||
gap:10px; |
|
||||||
flex-wrap:wrap; |
|
||||||
font-size:13px; |
|
||||||
line-height:1.4; |
|
||||||
} |
|
||||||
|
|
||||||
.otb-statusbar strong{ color:#f8fbff; } |
|
||||||
|
|
||||||
.otb-statusbar a{ |
|
||||||
color:#62f0cf !important; |
|
||||||
text-decoration:none; |
|
||||||
} |
|
||||||
|
|
||||||
.otb-dot{ |
|
||||||
width:4px; |
|
||||||
height:4px; |
|
||||||
border-radius:50%; |
|
||||||
background:rgba(255,255,255,0.25); |
|
||||||
display:inline-block; |
|
||||||
} |
|
||||||
|
|
||||||
html[data-theme="light"] .otb-statusbar{ |
|
||||||
background:#edf2fb !important; |
|
||||||
border-top:1px solid rgba(18,32,60,0.08); |
|
||||||
} |
|
||||||
|
|
||||||
html[data-theme="light"] .otb-statusbar-inner{ |
|
||||||
color:#23314a; |
|
||||||
} |
|
||||||
|
|
||||||
html[data-theme="light"] .otb-statusbar strong{ |
|
||||||
color:#16233a; |
|
||||||
} |
|
||||||
|
|
||||||
html[data-theme="light"] .otb-dot{ |
|
||||||
background:rgba(23,32,51,0.22); |
|
||||||
} |
|
||||||
|
|
||||||
.portal-shell, |
|
||||||
.portal-wrap{ |
|
||||||
max-width:1200px; |
|
||||||
margin:0 auto; |
|
||||||
padding:32px 20px 72px; |
|
||||||
} |
|
||||||
|
|
||||||
.portal-card{ |
|
||||||
max-width:760px; |
|
||||||
margin:0 auto; |
|
||||||
} |
|
||||||
|
|
||||||
@media (max-width: 1100px){ |
|
||||||
.site-container, |
|
||||||
.container{ |
|
||||||
padding-left:16px !important; |
|
||||||
padding-right:16px !important; |
|
||||||
} |
|
||||||
|
|
||||||
.site-nav{ |
|
||||||
display:flex; |
|
||||||
flex-direction:column; |
|
||||||
align-items:flex-start; |
|
||||||
gap:14px; |
|
||||||
} |
|
||||||
|
|
||||||
.site-nav-right{ |
|
||||||
width:100%; |
|
||||||
display:flex; |
|
||||||
flex-direction:column; |
|
||||||
align-items:flex-start; |
|
||||||
gap:12px; |
|
||||||
} |
|
||||||
|
|
||||||
.site-navlinks{ |
|
||||||
width:100%; |
|
||||||
display:flex; |
|
||||||
flex-wrap:wrap; |
|
||||||
gap:10px 16px; |
|
||||||
align-items:center; |
|
||||||
} |
|
||||||
|
|
||||||
.dropdown-menu{ |
|
||||||
min-width:220px; |
|
||||||
} |
|
||||||
|
|
||||||
.portal-shell, |
|
||||||
.portal-wrap{ |
|
||||||
padding:24px 16px 64px; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@media (max-width: 640px){ |
|
||||||
.site-brand img{ |
|
||||||
width:48px; |
|
||||||
height:48px; |
|
||||||
} |
|
||||||
|
|
||||||
.site-title strong{ |
|
||||||
font-size:20px; |
|
||||||
} |
|
||||||
|
|
||||||
.site-title span{ |
|
||||||
font-size:13px; |
|
||||||
} |
|
||||||
|
|
||||||
.site-navlinks{ |
|
||||||
gap:8px 14px; |
|
||||||
} |
|
||||||
|
|
||||||
.otb-statusbar-inner{ |
|
||||||
font-size:12px; |
|
||||||
gap:8px; |
|
||||||
padding:10px 12px; |
|
||||||
} |
|
||||||
|
|
||||||
.portal-card{ |
|
||||||
max-width:100%; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ===== OTB hamburger nav ===== */ |
|
||||||
.otb-menu-toggle{ |
|
||||||
display:none !important; |
|
||||||
margin-left:auto; |
|
||||||
width:46px; |
|
||||||
height:42px; |
|
||||||
border:1px solid var(--otb-border); |
|
||||||
background:rgba(255,255,255,0.04); |
|
||||||
border-radius:12px; |
|
||||||
padding:0; |
|
||||||
align-items:center; |
|
||||||
justify-content:center; |
|
||||||
flex-direction:column; |
|
||||||
gap:5px; |
|
||||||
cursor:pointer; |
|
||||||
} |
|
||||||
|
|
||||||
.otb-menu-toggle span{ |
|
||||||
display:block; |
|
||||||
width:20px; |
|
||||||
height:2px; |
|
||||||
background:var(--otb-text); |
|
||||||
border-radius:2px; |
|
||||||
transition:transform 0.2s ease, opacity 0.2s ease; |
|
||||||
} |
|
||||||
|
|
||||||
.site-nav-right{ |
|
||||||
display:flex; |
|
||||||
align-items:center; |
|
||||||
gap:16px; |
|
||||||
} |
|
||||||
|
|
||||||
@media (max-width: 1100px){ |
|
||||||
.otb-menu-toggle{ |
|
||||||
display:flex !important; |
|
||||||
} |
|
||||||
|
|
||||||
.site-nav{ |
|
||||||
display:flex; |
|
||||||
align-items:center; |
|
||||||
justify-content:space-between; |
|
||||||
gap:14px; |
|
||||||
flex-wrap:wrap; |
|
||||||
} |
|
||||||
|
|
||||||
.site-brand{ |
|
||||||
min-width:0; |
|
||||||
flex:1 1 auto; |
|
||||||
} |
|
||||||
|
|
||||||
.site-nav-right{ |
|
||||||
display:none; |
|
||||||
width:100%; |
|
||||||
flex-direction:column; |
|
||||||
align-items:flex-start; |
|
||||||
gap:14px; |
|
||||||
padding-top:10px; |
|
||||||
} |
|
||||||
|
|
||||||
.site-nav-right.otb-nav-open{ |
|
||||||
display:flex; |
|
||||||
} |
|
||||||
|
|
||||||
.site-navlinks{ |
|
||||||
width:100%; |
|
||||||
display:flex; |
|
||||||
flex-direction:column; |
|
||||||
align-items:flex-start; |
|
||||||
gap:10px; |
|
||||||
} |
|
||||||
|
|
||||||
.site-navlinks > a, |
|
||||||
.dropdown{ |
|
||||||
width:100%; |
|
||||||
} |
|
||||||
|
|
||||||
.dropdown-toggle{ |
|
||||||
display:inline-flex; |
|
||||||
width:100%; |
|
||||||
justify-content:flex-start; |
|
||||||
} |
|
||||||
|
|
||||||
.dropdown-menu{ |
|
||||||
position:static !important; |
|
||||||
display:none; |
|
||||||
min-width:0; |
|
||||||
width:100%; |
|
||||||
margin-top:8px; |
|
||||||
} |
|
||||||
|
|
||||||
.dropdown:hover .dropdown-menu, |
|
||||||
.dropdown:focus-within .dropdown-menu{ |
|
||||||
display:block; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ===== stronger mobile nav override ===== */ |
|
||||||
@media (max-width: 1100px){ |
|
||||||
.otb-menu-toggle{ |
|
||||||
display:flex !important; |
|
||||||
} |
|
||||||
|
|
||||||
.site-nav{ |
|
||||||
display:flex !important; |
|
||||||
align-items:center !important; |
|
||||||
justify-content:space-between !important; |
|
||||||
gap:14px !important; |
|
||||||
flex-wrap:wrap !important; |
|
||||||
} |
|
||||||
|
|
||||||
.site-nav-right{ |
|
||||||
display:none !important; |
|
||||||
width:100% !important; |
|
||||||
flex-direction:column !important; |
|
||||||
align-items:flex-start !important; |
|
||||||
gap:14px !important; |
|
||||||
padding-top:10px !important; |
|
||||||
} |
|
||||||
|
|
||||||
.site-nav-right.otb-nav-open{ |
|
||||||
display:flex !important; |
|
||||||
} |
|
||||||
|
|
||||||
.site-navlinks{ |
|
||||||
width:100% !important; |
|
||||||
display:flex !important; |
|
||||||
flex-direction:column !important; |
|
||||||
align-items:flex-start !important; |
|
||||||
gap:10px !important; |
|
||||||
} |
|
||||||
|
|
||||||
.site-navlinks > a, |
|
||||||
.dropdown{ |
|
||||||
width:100% !important; |
|
||||||
} |
|
||||||
|
|
||||||
.dropdown-toggle{ |
|
||||||
width:100% !important; |
|
||||||
justify-content:flex-start !important; |
|
||||||
} |
|
||||||
|
|
||||||
.dropdown-menu{ |
|
||||||
position:static !important; |
|
||||||
min-width:0 !important; |
|
||||||
width:100% !important; |
|
||||||
margin-top:8px !important; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/* ===== desktop nav force ===== */ |
|
||||||
@media (min-width: 1101px){ |
|
||||||
.otb-menu-toggle{ |
|
||||||
display:none !important; |
|
||||||
} |
|
||||||
|
|
||||||
.site-nav-right{ |
|
||||||
display:flex !important; |
|
||||||
width:auto !important; |
|
||||||
flex-direction:row !important; |
|
||||||
align-items:center !important; |
|
||||||
gap:16px !important; |
|
||||||
padding-top:0 !important; |
|
||||||
} |
|
||||||
|
|
||||||
.site-navlinks{ |
|
||||||
display:flex !important; |
|
||||||
flex-direction:row !important; |
|
||||||
align-items:center !important; |
|
||||||
width:auto !important; |
|
||||||
gap:16px !important; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* ===== OTB hamburger hard fix ===== */ |
|
||||||
.otb-menu-toggle{ |
|
||||||
display:none !important; |
|
||||||
appearance:none !important; |
|
||||||
-webkit-appearance:none !important; |
|
||||||
background:transparent !important; |
|
||||||
border:0 !important; |
|
||||||
box-shadow:none !important; |
|
||||||
outline:none !important; |
|
||||||
padding:0 !important; |
|
||||||
margin:0 0 0 auto !important; |
|
||||||
width:46px !important; |
|
||||||
height:42px !important; |
|
||||||
align-items:center !important; |
|
||||||
justify-content:center !important; |
|
||||||
flex-direction:column !important; |
|
||||||
gap:5px !important; |
|
||||||
cursor:pointer !important; |
|
||||||
} |
|
||||||
|
|
||||||
.otb-menu-toggle::before, |
|
||||||
.otb-menu-toggle::after{ |
|
||||||
content:none !important; |
|
||||||
display:none !important; |
|
||||||
} |
|
||||||
|
|
||||||
.otb-menu-toggle span{ |
|
||||||
display:block !important; |
|
||||||
width:20px !important; |
|
||||||
height:2px !important; |
|
||||||
min-height:2px !important; |
|
||||||
max-height:2px !important; |
|
||||||
background:var(--otb-text) !important; |
|
||||||
border-radius:2px !important; |
|
||||||
margin:0 !important; |
|
||||||
padding:0 !important; |
|
||||||
} |
|
||||||
|
|
||||||
@media (min-width: 1101px){ |
|
||||||
.otb-menu-toggle{ |
|
||||||
display:none !important; |
|
||||||
visibility:hidden !important; |
|
||||||
pointer-events:none !important; |
|
||||||
width:0 !important; |
|
||||||
height:0 !important; |
|
||||||
overflow:hidden !important; |
|
||||||
} |
|
||||||
|
|
||||||
.site-nav-right{ |
|
||||||
display:flex !important; |
|
||||||
width:auto !important; |
|
||||||
flex-direction:row !important; |
|
||||||
align-items:center !important; |
|
||||||
gap:16px !important; |
|
||||||
padding-top:0 !important; |
|
||||||
} |
|
||||||
|
|
||||||
.site-navlinks{ |
|
||||||
display:flex !important; |
|
||||||
flex-direction:row !important; |
|
||||||
align-items:center !important; |
|
||||||
width:auto !important; |
|
||||||
gap:16px !important; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@media (max-width: 1100px){ |
|
||||||
.otb-menu-toggle{ |
|
||||||
display:flex !important; |
|
||||||
visibility:visible !important; |
|
||||||
pointer-events:auto !important; |
|
||||||
width:46px !important; |
|
||||||
height:42px !important; |
|
||||||
overflow:visible !important; |
|
||||||
border:1px solid var(--otb-border) !important; |
|
||||||
background:rgba(255,255,255,0.04) !important; |
|
||||||
border-radius:12px !important; |
|
||||||
} |
|
||||||
|
|
||||||
.site-nav{ |
|
||||||
display:flex !important; |
|
||||||
align-items:center !important; |
|
||||||
justify-content:space-between !important; |
|
||||||
gap:14px !important; |
|
||||||
flex-wrap:wrap !important; |
|
||||||
} |
|
||||||
|
|
||||||
.site-brand{ |
|
||||||
min-width:0 !important; |
|
||||||
flex:1 1 auto !important; |
|
||||||
} |
|
||||||
|
|
||||||
.site-nav-right{ |
|
||||||
display:none !important; |
|
||||||
width:100% !important; |
|
||||||
flex-direction:column !important; |
|
||||||
align-items:flex-start !important; |
|
||||||
gap:14px !important; |
|
||||||
padding-top:10px !important; |
|
||||||
} |
|
||||||
|
|
||||||
.site-nav-right.otb-nav-open{ |
|
||||||
display:flex !important; |
|
||||||
} |
|
||||||
|
|
||||||
.site-navlinks{ |
|
||||||
width:100% !important; |
|
||||||
display:flex !important; |
|
||||||
flex-direction:column !important; |
|
||||||
align-items:flex-start !important; |
|
||||||
gap:10px !important; |
|
||||||
} |
|
||||||
|
|
||||||
.site-navlinks > a, |
|
||||||
.dropdown{ |
|
||||||
width:100% !important; |
|
||||||
} |
|
||||||
|
|
||||||
.dropdown-toggle{ |
|
||||||
width:100% !important; |
|
||||||
justify-content:flex-start !important; |
|
||||||
} |
|
||||||
|
|
||||||
.dropdown-menu{ |
|
||||||
position:static !important; |
|
||||||
min-width:0 !important; |
|
||||||
width:100% !important; |
|
||||||
margin-top:8px !important; |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,54 +0,0 @@ |
|||||||
(function () { |
|
||||||
const root = document.documentElement; |
|
||||||
const KEY = "otb-theme"; |
|
||||||
|
|
||||||
function applyTheme(theme) { |
|
||||||
const resolved = theme === "light" ? "light" : "dark"; |
|
||||||
root.setAttribute("data-theme", resolved); |
|
||||||
document.body.classList.toggle("otb-dark", resolved === "dark"); |
|
||||||
document.body.classList.toggle("otb-light", resolved === "light"); |
|
||||||
|
|
||||||
const toggle = document.getElementById("otbThemeToggle") || document.getElementById("themeToggle"); |
|
||||||
if (toggle) toggle.checked = resolved === "light"; |
|
||||||
} |
|
||||||
|
|
||||||
function savedTheme() { |
|
||||||
try { |
|
||||||
return localStorage.getItem(KEY) || "dark"; |
|
||||||
} catch (e) { |
|
||||||
return "dark"; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
function saveTheme(theme) { |
|
||||||
try { |
|
||||||
localStorage.setItem(KEY, theme); |
|
||||||
} catch (e) {} |
|
||||||
} |
|
||||||
|
|
||||||
function setupMenu() { |
|
||||||
const btn = document.getElementById("otbMenuToggle"); |
|
||||||
const nav = document.getElementById("otbNavWrap"); |
|
||||||
if (!btn || !nav) return; |
|
||||||
|
|
||||||
btn.addEventListener("click", function () { |
|
||||||
const open = nav.classList.toggle("otb-nav-open"); |
|
||||||
btn.setAttribute("aria-expanded", open ? "true" : "false"); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function () { |
|
||||||
applyTheme(savedTheme()); |
|
||||||
|
|
||||||
const toggle = document.getElementById("otbThemeToggle") || document.getElementById("themeToggle"); |
|
||||||
if (toggle) { |
|
||||||
toggle.addEventListener("change", function () { |
|
||||||
const next = toggle.checked ? "light" : "dark"; |
|
||||||
saveTheme(next); |
|
||||||
applyTheme(next); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
setupMenu(); |
|
||||||
}); |
|
||||||
})(); |
|
||||||
@ -1,51 +0,0 @@ |
|||||||
#!/bin/bash |
|
||||||
set -e |
|
||||||
SITE_DIR="/var/www/outsidethebox.top" |
|
||||||
cd "$SITE_DIR" || exit 1 |
|
||||||
|
|
||||||
STAMP="$(date +%Y%m%d-%H%M%S)" |
|
||||||
BKDIR="backups/shared-brand-$STAMP" |
|
||||||
mkdir -p "$BKDIR" |
|
||||||
cp -av index.html pricing.html terms.html contact.html assets/style.css "$BKDIR"/ |
|
||||||
|
|
||||||
HEADER="$(cat /home/def/otb-shared-brand/header.html)" |
|
||||||
FOOTER="$(cat /home/def/otb-shared-brand/footer.html | sed 's|__OTB_BRAND_JS__|/assets/brand.js|g')" |
|
||||||
BRANDCSS="$(cat /home/def/otb-shared-brand/brand.css)" |
|
||||||
|
|
||||||
cp -av /home/def/otb-shared-brand/brand.js assets/brand.js |
|
||||||
|
|
||||||
python3 - <<PY2 |
|
||||||
from pathlib import Path |
|
||||||
import re |
|
||||||
|
|
||||||
header = '''$HEADER''' |
|
||||||
footer = '''$FOOTER''' |
|
||||||
brandcss = '''$BRANDCSS''' |
|
||||||
|
|
||||||
for name in ["index.html", "pricing.html", "terms.html", "contact.html"]: |
|
||||||
p = Path(name) |
|
||||||
text = p.read_text(encoding="utf-8") |
|
||||||
|
|
||||||
if '<header class="site-header">' in text: |
|
||||||
text = re.sub(r'<header class="site-header">.*?</header>', header, text, count=1, flags=re.S) |
|
||||||
elif '<header class="header">' in text: |
|
||||||
text = re.sub(r'<header class="header">.*?</header>', header, text, count=1, flags=re.S) |
|
||||||
else: |
|
||||||
text = text.replace('<body>', '<body>\n' + header, 1) |
|
||||||
|
|
||||||
if '<div class="otb-statusbar">' in text: |
|
||||||
text = re.sub(r'<div class="otb-statusbar">.*?</script>', footer, text, count=1, flags=re.S) |
|
||||||
else: |
|
||||||
text = text.replace('</body>', footer + '\n</body>', 1) |
|
||||||
|
|
||||||
p.write_text(text, encoding="utf-8") |
|
||||||
|
|
||||||
cssp = Path("assets/style.css") |
|
||||||
css = cssp.read_text(encoding="utf-8") |
|
||||||
if "/* ===== OTB shared branding ===== */" in css: |
|
||||||
css = re.sub(r'/\* ===== OTB shared branding ===== \*/.*', brandcss, css, flags=re.S) |
|
||||||
else: |
|
||||||
css += "\n\n" + brandcss |
|
||||||
cssp.write_text(css, encoding="utf-8") |
|
||||||
print("mintme deploy complete") |
|
||||||
PY2 |
|
||||||
@ -1,66 +0,0 @@ |
|||||||
#!/bin/bash |
|
||||||
set -e |
|
||||||
APP_DIR="/home/def/monitor" |
|
||||||
cd "$APP_DIR" || exit 1 |
|
||||||
|
|
||||||
STAMP="$(date +%Y%m%d-%H%M%S)" |
|
||||||
BKDIR="backups/shared-brand-$STAMP" |
|
||||||
mkdir -p "$BKDIR" |
|
||||||
cp -av frontend/index.html frontend/styles.css "$BKDIR"/ || true |
|
||||||
|
|
||||||
HEADER="$(cat /home/def/otb-shared-brand/header.html)" |
|
||||||
FOOTER="$(cat /home/def/otb-shared-brand/footer.html | sed 's|__OTB_BRAND_JS__|/brand.js|g')" |
|
||||||
BRANDCSS="$(cat /home/def/otb-shared-brand/brand.css)" |
|
||||||
|
|
||||||
cp -av /home/def/otb-shared-brand/brand.js frontend/brand.js |
|
||||||
|
|
||||||
cat > frontend/index.html <<HTML |
|
||||||
<!doctype html> |
|
||||||
<html lang="en" data-theme="dark"> |
|
||||||
<head> |
|
||||||
<meta charset="utf-8" /> |
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" /> |
|
||||||
<title>Monitor</title> |
|
||||||
<link rel="stylesheet" href="/styles.css" /> |
|
||||||
</head> |
|
||||||
<body> |
|
||||||
$HEADER |
|
||||||
|
|
||||||
<div class="wrap"> |
|
||||||
<header class="top"> |
|
||||||
<div> |
|
||||||
<div class="title">Monitor</div> |
|
||||||
<div class="sub">7-day snapshot • rotating refresh</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="top-right"> |
|
||||||
<div class="status-pill" id="status">Loading…</div> |
|
||||||
<div class="cycle" id="cycle"></div> |
|
||||||
</div> |
|
||||||
</header> |
|
||||||
|
|
||||||
<div class="card"> |
|
||||||
<div id="root"></div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
$FOOTER |
|
||||||
</body> |
|
||||||
</html> |
|
||||||
HTML |
|
||||||
|
|
||||||
python3 - <<PY2 |
|
||||||
from pathlib import Path |
|
||||||
import re |
|
||||||
p = Path("frontend/styles.css") |
|
||||||
css = p.read_text(encoding="utf-8") |
|
||||||
brandcss = '''$BRANDCSS''' |
|
||||||
if "/* ===== OTB shared branding ===== */" in css: |
|
||||||
css = re.sub(r'/\* ===== OTB shared branding ===== \*/.*', brandcss, css, flags=re.S) |
|
||||||
else: |
|
||||||
css = brandcss + "\n\n" + css |
|
||||||
p.write_text(css, encoding="utf-8") |
|
||||||
print("monitor branding css updated") |
|
||||||
PY2 |
|
||||||
|
|
||||||
/home/def/monitor/deploy-monitor.sh |
|
||||||
@ -1,48 +0,0 @@ |
|||||||
#!/bin/bash |
|
||||||
set -e |
|
||||||
APP_DIR="/opt/otb_tracker" |
|
||||||
cd "$APP_DIR" || exit 1 |
|
||||||
|
|
||||||
STAMP="$(date +%Y%m%d-%H%M%S)" |
|
||||||
BKDIR="backups/shared-brand-$STAMP" |
|
||||||
mkdir -p "$BKDIR" |
|
||||||
cp -av backend/app.py "$BKDIR"/ |
|
||||||
|
|
||||||
HEADER="$(cat /home/def/otb-shared-brand/header.html)" |
|
||||||
FOOTER="$(cat /home/def/otb-shared-brand/footer.html | sed 's|__OTB_BRAND_JS__|/static/brand.js|g')" |
|
||||||
BRANDCSS="$(cat /home/def/otb-shared-brand/brand.css)" |
|
||||||
BRANDJS="$(cat /home/def/otb-shared-brand/brand.js)" |
|
||||||
|
|
||||||
mkdir -p static |
|
||||||
printf '%s |
|
||||||
' "$BRANDJS" > static/brand.js |
|
||||||
|
|
||||||
python3 - <<PY2 |
|
||||||
from pathlib import Path |
|
||||||
import re |
|
||||||
|
|
||||||
app = Path("backend/app.py") |
|
||||||
text = app.read_text(encoding="utf-8") |
|
||||||
|
|
||||||
header = '''$HEADER''' |
|
||||||
footer = '''$FOOTER''' |
|
||||||
brandcss = '''$BRANDCSS''' |
|
||||||
|
|
||||||
style_block = f"<style>\n{brandcss}\n</style>" |
|
||||||
|
|
||||||
text = re.sub(r'<style>\s*/\* ===== OTB shared branding ===== \*/.*?</style>', '', text, flags=re.S) |
|
||||||
|
|
||||||
if header not in text: |
|
||||||
text = text.replace("<body>", "<body>\n" + header) |
|
||||||
|
|
||||||
if footer not in text: |
|
||||||
text = text.replace("</body>", footer + "\n</body>") |
|
||||||
|
|
||||||
if style_block not in text: |
|
||||||
text = text.replace("</head>", style_block + "\n</head>") |
|
||||||
|
|
||||||
app.write_text(text, encoding="utf-8") |
|
||||||
print("otb-tracker branding injected") |
|
||||||
PY2 |
|
||||||
|
|
||||||
sudo systemctl restart otb-tracker.service || true |
|
||||||
@ -1,42 +0,0 @@ |
|||||||
#!/bin/bash |
|
||||||
set -e |
|
||||||
APP_DIR="/home/def/otb_billing" |
|
||||||
cd "$APP_DIR" || exit 1 |
|
||||||
|
|
||||||
STAMP="$(date +%Y%m%d-%H%M%S)" |
|
||||||
BKDIR="backups/shared-brand-$STAMP" |
|
||||||
mkdir -p "$BKDIR" |
|
||||||
cp -av templates/includes/site_nav.html static/css/style.css templates/portal_*.html "$BKDIR"/ |
|
||||||
|
|
||||||
cp -av /home/def/otb-shared-brand/header.html templates/includes/site_nav.html |
|
||||||
cp -av /home/def/otb-shared-brand/brand.js static/brand.js |
|
||||||
|
|
||||||
FOOTER="$(cat /home/def/otb-shared-brand/footer.html | sed 's|__OTB_BRAND_JS__|/static/brand.js|g')" |
|
||||||
BRANDCSS="$(cat /home/def/otb-shared-brand/brand.css)" |
|
||||||
|
|
||||||
python3 - <<PY2 |
|
||||||
from pathlib import Path |
|
||||||
import re |
|
||||||
|
|
||||||
footer = '''$FOOTER''' |
|
||||||
brandcss = '''$BRANDCSS''' |
|
||||||
|
|
||||||
for p in Path("templates").glob("portal_*.html"): |
|
||||||
text = p.read_text(encoding="utf-8") |
|
||||||
if '<div class="otb-statusbar">' in text: |
|
||||||
text = re.sub(r'<div class="otb-statusbar">.*?</script>', footer, text, count=1, flags=re.S) |
|
||||||
else: |
|
||||||
text = text.replace('{% include "footer.html" %}', footer + '\n\n {% include "footer.html" %}') |
|
||||||
p.write_text(text, encoding="utf-8") |
|
||||||
|
|
||||||
cssp = Path("static/css/style.css") |
|
||||||
css = cssp.read_text(encoding="utf-8") |
|
||||||
if "/* ===== OTB shared branding ===== */" in css: |
|
||||||
css = re.sub(r'/\* ===== OTB shared branding ===== \*/.*', brandcss, css, flags=re.S) |
|
||||||
else: |
|
||||||
css += "\n\n" + brandcss |
|
||||||
cssp.write_text(css, encoding="utf-8") |
|
||||||
print("portal deploy complete") |
|
||||||
PY2 |
|
||||||
|
|
||||||
sudo systemctl restart otb_billing.service |
|
||||||
@ -1,2 +0,0 @@ |
|||||||
{% include "includes/otb_statusbar.html" %} |
|
||||||
<script src="/static/brand.js" defer></script> |
|
||||||
@ -1,42 +0,0 @@ |
|||||||
<header class="site-header"> |
|
||||||
<div class="site-container"> |
|
||||||
<div class="site-nav"> |
|
||||||
<a class="site-brand" href="https://outsidethebox.top"> |
|
||||||
<img src="https://outsidethebox.top/assets/favicon.png" alt="outsidethebox.top logo" /> |
|
||||||
<div class="site-title"> |
|
||||||
<strong>outsidethebox.top</strong> |
|
||||||
<span>Managed hosting • no client server logins</span> |
|
||||||
</div> |
|
||||||
</a> |
|
||||||
|
|
||||||
<button class="otb-menu-toggle" id="otbMenuToggle" aria-label="Toggle menu" aria-expanded="false" aria-controls="otbNavWrap"> |
|
||||||
<span></span> |
|
||||||
<span></span> |
|
||||||
<span></span> |
|
||||||
</button> |
|
||||||
|
|
||||||
<div class="site-nav-right" id="otbNavWrap"> |
|
||||||
<nav class="site-navlinks"> |
|
||||||
<a href="https://outsidethebox.top">Home</a> |
|
||||||
<a href="https://outsidethebox.top/pricing.html">Pricing</a> |
|
||||||
<a href="https://outsidethebox.top/terms.html">ToS</a> |
|
||||||
<a href="https://outsidethebox.top/contact.html">Contact</a> |
|
||||||
<div class="dropdown"> |
|
||||||
<a href="#" class="dropdown-toggle">Services</a> |
|
||||||
<div class="dropdown-menu"> |
|
||||||
<a href="https://follow-me.outsidethebox.top">Follow-me Tracker</a> |
|
||||||
<a href="https://monitor.outsidethebox.top">Oracle</a> |
|
||||||
<a href="https://video.outsidethebox.top">Video</a> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<a href="https://otb-billing.outsidethebox.top/portal">Portal</a> |
|
||||||
</nav> |
|
||||||
|
|
||||||
<label class="otb-theme-switch" title="Toggle light / dark mode"> |
|
||||||
<input type="checkbox" id="otbThemeToggle" aria-label="Toggle theme" /> |
|
||||||
<span class="otb-theme-slider"></span> |
|
||||||
</label> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</header> |
|
||||||
@ -0,0 +1,30 @@ |
|||||||
|
<header class="site-header"> |
||||||
|
<div class="site-container"> |
||||||
|
<div class="site-nav"> |
||||||
|
<a class="site-brand" href="https://outsidethebox.top"> |
||||||
|
<img src="https://outsidethebox.top/assets/favicon.png" /> |
||||||
|
<div class="site-title"> |
||||||
|
<strong>outsidethebox.top</strong> |
||||||
|
<span>Managed hosting • no client server logins</span> |
||||||
|
</div> |
||||||
|
</a> |
||||||
|
|
||||||
|
<nav class="site-navlinks"> |
||||||
|
<a href="https://outsidethebox.top">Home</a> |
||||||
|
<a href="https://outsidethebox.top/pricing.html">Pricing</a> |
||||||
|
<a href="https://outsidethebox.top/terms.html">ToS</a> |
||||||
|
<a href="https://outsidethebox.top/contact.html">Contact</a> |
||||||
|
|
||||||
|
<div class="dropdown"> |
||||||
|
<a href="#" class="dropdown-toggle">Services</a> |
||||||
|
<div class="dropdown-menu"> |
||||||
|
<a href="https://follow-me.outsidethebox.top">Follow-me Tracker</a> |
||||||
|
<a href="https://monitor.outsidethebox.top">Oracle</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<a href="https://otb-billing.outsidethebox.top/portal">Portal</a> |
||||||
|
</nav> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</header> |
||||||
Loading…
Reference in new issue