Initial commit
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
@@ -0,0 +1,35 @@
|
||||
/* Address autocomplete dropdown (public + portal). */
|
||||
.address-ac-wrap {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.address-ac-list {
|
||||
position: absolute;
|
||||
z-index: 40;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: calc(100% + 2px);
|
||||
margin: 0;
|
||||
padding: 4px 0;
|
||||
list-style: none;
|
||||
max-height: 240px;
|
||||
overflow-y: auto;
|
||||
background: #fff;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);
|
||||
}
|
||||
|
||||
.address-ac-item {
|
||||
padding: 8px 12px;
|
||||
font-size: 13px;
|
||||
line-height: 1.35;
|
||||
color: #111827;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.address-ac-item:hover,
|
||||
.address-ac-item:focus {
|
||||
background: #f3f4f6;
|
||||
outline: none;
|
||||
}
|
||||
@@ -0,0 +1,728 @@
|
||||
:root {
|
||||
--monica-primary: #00626c;
|
||||
--monica-primary-light: #008898;
|
||||
--monica-ink: #212121;
|
||||
--monica-muted: #6b7280;
|
||||
--monica-surface: #f4f7f7;
|
||||
--monica-border: #d9e3e4;
|
||||
--monica-ok: #1a7f4b;
|
||||
--monica-warn: #b45309;
|
||||
--monica-danger: #b91c1c;
|
||||
--portal-sidebar: 240px;
|
||||
--exit-dark: #080808;
|
||||
--exit-teal: #00626c;
|
||||
--exit-teal-bright: #008898;
|
||||
}
|
||||
|
||||
/* Portal shell */
|
||||
body.portal {
|
||||
margin: 0;
|
||||
background: var(--monica-surface);
|
||||
font-family: "Work Sans", sans-serif;
|
||||
color: var(--monica-ink);
|
||||
}
|
||||
.portal-shell { display: flex; min-height: 100vh; }
|
||||
.portal-sidebar {
|
||||
width: var(--portal-sidebar);
|
||||
background: #080808;
|
||||
color: #cbd5e1;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.portal-brand {
|
||||
padding: 16px 18px;
|
||||
border-bottom: 1px solid rgba(255,255,255,0.08);
|
||||
font-family: Poppins, sans-serif;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.portal-brand img {
|
||||
height: 36px;
|
||||
width: auto;
|
||||
display: block;
|
||||
}
|
||||
.portal-brand span { color: #7dd3da; font-size: 12px; letter-spacing: 0.04em; }
|
||||
.portal-nav { padding: 12px 0; flex: 1; }
|
||||
.portal-nav a {
|
||||
display: block;
|
||||
padding: 10px 18px;
|
||||
color: #94a3b8;
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
border-left: 3px solid transparent;
|
||||
}
|
||||
.portal-nav a:hover { color: #fff; background: rgba(255,255,255,0.04); }
|
||||
.portal-nav a.active { color: #fff; background: rgba(0,98,108,0.28); border-left-color: #00a0ab; }
|
||||
.portal-nav .nav-section {
|
||||
font-size: 10px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
color: #64748b;
|
||||
padding: 16px 18px 6px;
|
||||
}
|
||||
.portal-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
|
||||
.portal-topbar {
|
||||
background: #fff;
|
||||
border-bottom: 1px solid var(--monica-border);
|
||||
padding: 14px 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
}
|
||||
.portal-topbar h1 { margin: 0; font-size: 20px; font-family: Poppins, sans-serif; font-weight: 600; }
|
||||
.portal-content { padding: 24px; flex: 1; }
|
||||
.portal-user { font-size: 13px; color: var(--monica-muted); }
|
||||
.portal-user strong { color: var(--monica-ink); }
|
||||
|
||||
/* Portal widgets */
|
||||
.stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 16px; margin-bottom: 24px; }
|
||||
.analytics-overview {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(140px, 1fr) 4fr;
|
||||
gap: 16px;
|
||||
margin-bottom: 24px;
|
||||
align-items: stretch;
|
||||
}
|
||||
.analytics-overview .stat-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
.analytics-overview .panel { margin-bottom: 0; }
|
||||
@media (max-width: 800px) {
|
||||
.analytics-overview { grid-template-columns: 1fr; }
|
||||
}
|
||||
.stat-card {
|
||||
background: #fff;
|
||||
border: 1px solid var(--monica-border);
|
||||
padding: 18px;
|
||||
}
|
||||
.stat-card .label { font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--monica-muted); }
|
||||
.stat-card .value { font-size: 28px; font-weight: 700; font-family: Poppins, sans-serif; margin-top: 4px; }
|
||||
.stat-card .delta { font-size: 12px; margin-top: 4px; color: var(--monica-ok); }
|
||||
|
||||
.panel {
|
||||
background: #fff;
|
||||
border: 1px solid var(--monica-border);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.panel-h {
|
||||
padding: 14px 18px;
|
||||
border-bottom: 1px solid var(--monica-border);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
}
|
||||
.panel-h h2 { margin: 0; font-size: 15px; font-family: Poppins, sans-serif; font-weight: 600; }
|
||||
.panel-b { padding: 18px; }
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
padding: 9px 18px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
font-family: "Work Sans", sans-serif;
|
||||
}
|
||||
.btn-primary { background: var(--monica-primary); color: #fff; }
|
||||
.btn-primary:hover { background: #004e56; color: #fff; text-decoration: none; }
|
||||
.btn-ghost { background: transparent; border: 1px solid var(--monica-border); color: var(--monica-ink); }
|
||||
.btn-sm { padding: 6px 12px; font-size: 12px; }
|
||||
|
||||
.table { width: 100%; border-collapse: collapse; font-size: 14px; }
|
||||
.table th {
|
||||
text-align: left;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.06em;
|
||||
color: var(--monica-muted);
|
||||
padding: 10px 12px;
|
||||
border-bottom: 1px solid var(--monica-border);
|
||||
font-weight: 600;
|
||||
}
|
||||
.table td { padding: 12px; border-bottom: 1px solid var(--monica-border); vertical-align: middle; }
|
||||
.table tr:hover td { background: #f8fafc; }
|
||||
.table a { color: var(--monica-primary); text-decoration: none; font-weight: 500; }
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
border-radius: 2px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
.badge-new { background: #d0eef0; color: #00626c; }
|
||||
.badge-contacted { background: #fef3c7; color: #92400e; }
|
||||
.badge-won { background: #d1fae5; color: #065f46; }
|
||||
.badge-lost { background: #fee2e2; color: #991b1b; }
|
||||
.badge-sent { background: #d0eef0; color: #00626c; }
|
||||
.badge-scheduled { background: #ede9fe; color: #5b21b6; }
|
||||
.badge-delivered { background: #d1fae5; color: #065f46; }
|
||||
.badge-opened { background: #dbeafe; color: #1e40af; }
|
||||
.badge-clicked { background: #ede9fe; color: #5b21b6; }
|
||||
.badge-failed { background: #fee2e2; color: #991b1b; }
|
||||
.badge-optin { background: #d1fae5; color: #065f46; }
|
||||
.badge-optout { background: #f3f4f6; color: #4b5563; }
|
||||
.badge-draft { background: #f3f4f6; color: #4b5563; }
|
||||
.badge-completed { background: #d1fae5; color: #065f46; }
|
||||
.badge-cancelled { background: #f3f4f6; color: #4b5563; }
|
||||
.badge-sending { background: #d0eef0; color: #00626c; }
|
||||
.badge-queued { background: #ede9fe; color: #5b21b6; }
|
||||
.badge-bounced { background: #fee2e2; color: #991b1b; }
|
||||
.badge-published { background: #d1fae5; color: #065f46; }
|
||||
.badge-publishing { background: #d0eef0; color: #00626c; }
|
||||
|
||||
.form-grid { display: grid; gap: 16px; }
|
||||
.form-grid.cols-2 { grid-template-columns: 1fr 1fr; }
|
||||
@media (max-width: 700px) { .form-grid.cols-2 { grid-template-columns: 1fr; } }
|
||||
.field label { display: block; font-size: 12px; font-weight: 600; margin-bottom: 6px; color: #374151; }
|
||||
.field input, .field select, .field textarea {
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid var(--monica-border);
|
||||
font: inherit;
|
||||
background: #fff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.field textarea { min-height: 100px; resize: vertical; }
|
||||
.field .hint { font-size: 12px; color: var(--monica-muted); margin-top: 4px; }
|
||||
|
||||
.channel-tabs { display: flex; gap: 0; border-bottom: 1px solid var(--monica-border); margin-bottom: 18px; }
|
||||
.channel-tabs a {
|
||||
padding: 10px 16px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: var(--monica-muted);
|
||||
text-decoration: none;
|
||||
border-bottom: 2px solid transparent;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
.channel-tabs a.active { color: var(--monica-primary); border-bottom-color: var(--monica-primary); }
|
||||
|
||||
.chart-placeholder {
|
||||
height: 220px;
|
||||
background: linear-gradient(180deg, #e8f4f5 0%, #fff 100%);
|
||||
border: 1px dashed #a8d8dc;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
gap: 12px;
|
||||
padding: 24px 16px 12px;
|
||||
}
|
||||
.chart-placeholder > .bar {
|
||||
flex: 1;
|
||||
background: var(--monica-primary);
|
||||
opacity: 0.75;
|
||||
border-radius: 2px 2px 0 0;
|
||||
min-height: 8px;
|
||||
}
|
||||
.chart-placeholder .chart-bar-col {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
justify-content: flex-end;
|
||||
min-width: 0;
|
||||
height: 100%;
|
||||
}
|
||||
.chart-placeholder .chart-bar-col .bar {
|
||||
width: 100%;
|
||||
background: var(--monica-primary);
|
||||
opacity: 0.75;
|
||||
border-radius: 2px 2px 0 0;
|
||||
min-height: 8px;
|
||||
transition: height 0.25s ease;
|
||||
}
|
||||
.chart-placeholder .chart-bar-meta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
margin-top: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
.chart-placeholder .chart-bar-value {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #0f172a;
|
||||
line-height: 1.2;
|
||||
}
|
||||
.chart-placeholder .chart-bar-label {
|
||||
font-size: 11px;
|
||||
color: var(--monica-muted);
|
||||
line-height: 1.2;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.consent-pills { display: flex; gap: 6px; flex-wrap: wrap; }
|
||||
.preview-pane {
|
||||
background: #f8fafc;
|
||||
border: 1px solid var(--monica-border);
|
||||
padding: 16px;
|
||||
font-size: 14px;
|
||||
min-height: 160px;
|
||||
}
|
||||
.calendar-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
gap: 4px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.calendar-grid .dow { text-align: center; color: var(--monica-muted); font-weight: 600; padding: 6px; }
|
||||
.calendar-grid .day {
|
||||
aspect-ratio: 1;
|
||||
border: 1px solid var(--monica-border);
|
||||
background: #fff;
|
||||
padding: 6px;
|
||||
position: relative;
|
||||
}
|
||||
.calendar-grid .day.has-post { background: #e8f4f5; }
|
||||
.calendar-grid .day .dot {
|
||||
width: 6px; height: 6px; border-radius: 50%;
|
||||
background: var(--monica-primary);
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.login-wrap {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(160deg, #080808, #00626c 60%, #e8f4f5 60%);
|
||||
padding: 24px;
|
||||
}
|
||||
.login-card {
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
padding: 36px 32px;
|
||||
border: 1px solid var(--monica-border);
|
||||
}
|
||||
.login-card h1 { font-family: Poppins, sans-serif; font-size: 22px; margin: 0 0 6px; }
|
||||
.login-card .sub { color: var(--monica-muted); font-size: 14px; margin-bottom: 24px; }
|
||||
|
||||
.split { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
|
||||
@media (max-width: 900px) {
|
||||
.portal-shell { flex-direction: column; }
|
||||
.portal-sidebar { width: 100%; }
|
||||
.portal-nav { display: flex; flex-wrap: wrap; padding: 8px; }
|
||||
.portal-nav .nav-section { display: none; }
|
||||
.portal-nav a { border-left: none; border-bottom: 2px solid transparent; padding: 8px 12px; }
|
||||
.portal-nav a.active { border-bottom-color: #00a0ab; }
|
||||
.split { grid-template-columns: 1fr; }
|
||||
}
|
||||
|
||||
/* Public brand — EXIT Realty logo from exitrealtywheaton.com */
|
||||
.page .rd-navbar-brand {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.page .rd-navbar-brand img {
|
||||
display: block !important;
|
||||
height: 44px;
|
||||
width: auto;
|
||||
max-width: 160px;
|
||||
}
|
||||
.page .rd-navbar-brand::before,
|
||||
.page .rd-navbar-brand::after { content: none !important; display: none !important; }
|
||||
.page .rd-navbar-brand .brand-site {
|
||||
font-family: Poppins, sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 13px;
|
||||
letter-spacing: 0.04em;
|
||||
color: #00626c;
|
||||
text-decoration: none;
|
||||
line-height: 1.2;
|
||||
}
|
||||
.page .rd-navbar-brand .brand-site span {
|
||||
display: block;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
/* Shared extras */
|
||||
.muted { color: var(--monica-muted); font-size: 12px; }
|
||||
.text-warn { color: var(--monica-warn); font-size: 12px; }
|
||||
.hint-block { font-size: 13px; color: var(--monica-muted); margin: 12px 0 0; }
|
||||
.plain-list { margin: 0 0 12px; padding-left: 18px; }
|
||||
.plain-list li { margin-bottom: 6px; }
|
||||
.check-row { display: flex; align-items: center; gap: 8px; font-size: 14px; }
|
||||
.check-row.account-pick { align-items: flex-start; }
|
||||
.account-pick-copy {
|
||||
min-width: 0;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
}
|
||||
.account-pick-copy strong { display: block; font-weight: 600; }
|
||||
.account-rename {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.account-rename input[type="text"] {
|
||||
flex: 1;
|
||||
min-width: 160px;
|
||||
max-width: 100%;
|
||||
padding: 8px 10px;
|
||||
border: 1px solid var(--monica-border);
|
||||
font: inherit;
|
||||
background: #fff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.row-warn td { background: #fffbeb; }
|
||||
.auth-alert {
|
||||
background: #fff7ed;
|
||||
border: 1px solid #fdba74;
|
||||
color: #9a3412;
|
||||
padding: 12px 16px;
|
||||
margin-bottom: 16px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.auth-alert a { color: #9a3412; font-weight: 600; }
|
||||
|
||||
/* Social accounts */
|
||||
.connect-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
@media (max-width: 900px) {
|
||||
.connect-grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
.connect-card {
|
||||
display: flex; gap: 14px; align-items: flex-start; text-align: left;
|
||||
padding: 14px; border: 1px solid var(--monica-border); background: #fff;
|
||||
cursor: pointer; font: inherit; width: 100%;
|
||||
}
|
||||
.connect-card:hover { border-color: var(--monica-primary); }
|
||||
.connect-card.is-active { border-color: var(--monica-primary); box-shadow: inset 0 0 0 1px var(--monica-primary); }
|
||||
.connect-card p { margin: 4px 0 0; font-size: 13px; color: var(--monica-muted); }
|
||||
.connect-form-panel {
|
||||
margin-top: 16px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid var(--monica-border);
|
||||
}
|
||||
.connect-steps {
|
||||
margin: 0 0 16px;
|
||||
padding-left: 18px;
|
||||
font-size: 13px;
|
||||
color: var(--monica-muted);
|
||||
}
|
||||
.connect-steps li { margin-bottom: 8px; }
|
||||
.connect-steps a { color: var(--monica-primary); }
|
||||
.platform-icon {
|
||||
width: 40px; height: 40px; border-radius: 8px; display: flex; align-items: center;
|
||||
justify-content: center; color: #fff; font-weight: 700; flex-shrink: 0; font-size: 14px;
|
||||
}
|
||||
.platform-icon.meta { background: #1877f2; }
|
||||
.platform-icon.ig { background: linear-gradient(45deg, #f58529, #dd2a7b, #8134af); font-size: 12px; }
|
||||
.platform-icon.li { background: #0a66c2; }
|
||||
.platform-pill {
|
||||
display: inline-block; padding: 2px 8px; font-size: 11px; font-weight: 600;
|
||||
color: #fff; border-radius: 2px;
|
||||
}
|
||||
.platform-pill.meta { background: #1877f2; }
|
||||
.platform-pill.ig { background: #dd2a7b; }
|
||||
.platform-pill.li { background: #0a66c2; }
|
||||
|
||||
/* Import wizard */
|
||||
.steps {
|
||||
display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 20px;
|
||||
}
|
||||
.step {
|
||||
display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--monica-muted);
|
||||
padding: 8px 12px; background: #fff; border: 1px solid var(--monica-border);
|
||||
}
|
||||
.step span {
|
||||
width: 22px; height: 22px; border-radius: 50%; background: #e5e7eb; color: #374151;
|
||||
display: inline-flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 700;
|
||||
}
|
||||
.step.active { border-color: var(--monica-primary); color: var(--monica-ink); }
|
||||
.step.active span { background: var(--monica-primary); color: #fff; }
|
||||
.dropzone {
|
||||
border: 2px dashed var(--monica-border); padding: 32px; text-align: center; background: #f8fafc;
|
||||
}
|
||||
|
||||
/* Designer shared layout */
|
||||
.designer-layout {
|
||||
display: grid; grid-template-columns: minmax(280px, 380px) 1fr; gap: 20px; align-items: start;
|
||||
}
|
||||
.designer-layout.with-ai {
|
||||
grid-template-columns: minmax(260px, 340px) minmax(240px, 320px) 1fr;
|
||||
}
|
||||
@media (max-width: 1200px) {
|
||||
.designer-layout.with-ai { grid-template-columns: 1fr 1fr; }
|
||||
.designer-layout.with-ai .designer-preview-col { grid-column: 1 / -1; }
|
||||
}
|
||||
@media (max-width: 960px) {
|
||||
.designer-layout,
|
||||
.designer-layout.with-ai { grid-template-columns: 1fr; }
|
||||
}
|
||||
|
||||
/* PCM Integrations embedded designer */
|
||||
.pcm-iframe-wrap {
|
||||
padding: 0 !important;
|
||||
min-height: 70vh;
|
||||
background: #f8fafc;
|
||||
}
|
||||
.pcm-iframe-wrap iframe {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: min(80vh, 900px);
|
||||
border: 0;
|
||||
background: #fff;
|
||||
}
|
||||
.pcm-designer .table tr.is-active td {
|
||||
background: #e8f4f5;
|
||||
}
|
||||
|
||||
/* Size picker */
|
||||
.size-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
|
||||
.size-option {
|
||||
border: 1px solid var(--monica-border); background: #fff; padding: 10px 12px;
|
||||
text-align: left; cursor: pointer; font: inherit; color: inherit;
|
||||
}
|
||||
.size-option:hover { border-color: var(--monica-primary); }
|
||||
.size-option.active {
|
||||
border-color: var(--monica-primary); background: #e8f4f5;
|
||||
box-shadow: inset 3px 0 0 var(--monica-primary);
|
||||
}
|
||||
.size-option .sz-name { font-weight: 700; font-size: 13px; font-family: Poppins, sans-serif; }
|
||||
.size-option .sz-meta { font-size: 11px; color: var(--monica-muted); margin-top: 2px; }
|
||||
.size-option .sz-badge {
|
||||
display: inline-block; margin-top: 6px; font-size: 10px; font-weight: 600;
|
||||
text-transform: uppercase; letter-spacing: 0.04em; color: var(--monica-primary);
|
||||
}
|
||||
|
||||
/* Media library */
|
||||
.media-library { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
|
||||
.media-tile {
|
||||
position: relative; aspect-ratio: 4 / 3; border: 2px solid transparent;
|
||||
background-size: cover; background-position: center; background-color: #e5e7eb;
|
||||
cursor: pointer; padding: 0; overflow: hidden;
|
||||
}
|
||||
.media-tile.active { border-color: var(--monica-primary); }
|
||||
.media-tile .media-label {
|
||||
position: absolute; left: 0; right: 0; bottom: 0; padding: 4px 6px;
|
||||
background: rgba(15, 23, 42, 0.72); color: #fff; font-size: 10px;
|
||||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
||||
}
|
||||
.media-tile.upload-tile {
|
||||
border: 2px dashed var(--monica-border); background: #f8fafc;
|
||||
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
||||
gap: 4px; color: var(--monica-muted); font-size: 11px; font-weight: 600;
|
||||
}
|
||||
.media-tile.upload-tile:hover { border-color: var(--monica-primary); color: var(--monica-primary); }
|
||||
.media-tile.upload-tile span { font-size: 22px; line-height: 1; color: var(--monica-primary); }
|
||||
.dropzone.compact { padding: 16px; font-size: 13px; cursor: pointer; }
|
||||
.dropzone.compact:hover { border-color: var(--monica-primary); }
|
||||
.library-hint { font-size: 12px; color: var(--monica-muted); margin: 8px 0 0; }
|
||||
|
||||
/* AI chat assist */
|
||||
.ai-chat {
|
||||
display: flex; flex-direction: column; height: min(640px, 75vh);
|
||||
background: #fff; border: 1px solid var(--monica-border);
|
||||
}
|
||||
.ai-chat-h {
|
||||
padding: 12px 14px; border-bottom: 1px solid var(--monica-border);
|
||||
display: flex; align-items: center; justify-content: space-between; gap: 8px;
|
||||
}
|
||||
.ai-chat-h h2 { margin: 0; font-size: 15px; font-family: Poppins, sans-serif; font-weight: 600; }
|
||||
.ai-pill {
|
||||
font-size: 10px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
|
||||
background: #e8f4f5; color: var(--monica-primary); padding: 3px 8px;
|
||||
}
|
||||
.ai-chat-messages {
|
||||
flex: 1; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 12px;
|
||||
background: linear-gradient(180deg, #f8fafc 0%, #fff 40%);
|
||||
}
|
||||
.ai-msg { max-width: 92%; font-size: 13px; line-height: 1.45; }
|
||||
.ai-msg.bot { align-self: flex-start; }
|
||||
.ai-msg.user { align-self: flex-end; }
|
||||
.ai-msg .bubble {
|
||||
padding: 10px 12px; border: 1px solid var(--monica-border); background: #fff;
|
||||
}
|
||||
.ai-msg.user .bubble {
|
||||
background: var(--monica-primary); color: #fff; border-color: var(--monica-primary);
|
||||
}
|
||||
.ai-msg .who {
|
||||
font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
|
||||
color: var(--monica-muted); margin-bottom: 4px;
|
||||
}
|
||||
.ai-msg.user .who { text-align: right; color: var(--monica-primary); }
|
||||
.ai-draft {
|
||||
margin-top: 8px; padding: 10px; background: #f8fafc; border: 1px dashed #a8d8dc;
|
||||
white-space: pre-wrap; font-size: 12px; color: var(--monica-ink);
|
||||
}
|
||||
.ai-msg-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
|
||||
.ai-chat-prompts {
|
||||
padding: 8px 12px; border-top: 1px solid var(--monica-border);
|
||||
display: flex; flex-wrap: wrap; gap: 6px; background: #fafbfc;
|
||||
}
|
||||
.chip {
|
||||
border: 1px solid var(--monica-border); background: #fff; font: inherit;
|
||||
font-size: 11px; font-weight: 600; padding: 5px 10px; cursor: pointer; color: var(--monica-ink);
|
||||
}
|
||||
.chip:hover { border-color: var(--monica-primary); color: var(--monica-primary); }
|
||||
.ai-chat-input {
|
||||
border-top: 1px solid var(--monica-border); padding: 10px 12px;
|
||||
display: flex; gap: 8px; align-items: flex-end;
|
||||
}
|
||||
.ai-chat-input textarea {
|
||||
flex: 1; min-height: 44px; max-height: 100px; resize: vertical;
|
||||
border: 1px solid var(--monica-border); padding: 8px 10px; font: inherit; font-size: 13px;
|
||||
}
|
||||
.ai-chat-input .btn { flex-shrink: 0; }
|
||||
|
||||
/* Postcard */
|
||||
.postcard {
|
||||
width: 100%; max-width: 420px; aspect-ratio: 6 / 4; position: relative; overflow: hidden;
|
||||
background: #111; box-shadow: 0 12px 40px rgba(15, 23, 42, 0.25); color: #fff;
|
||||
transition: max-width 0.2s, aspect-ratio 0.2s;
|
||||
}
|
||||
.postcard.size-4x6 { max-width: 420px; aspect-ratio: 6 / 4; }
|
||||
.postcard.size-6x9 { max-width: 480px; aspect-ratio: 9 / 6; }
|
||||
.postcard.size-6x11 { max-width: 520px; aspect-ratio: 11 / 6; }
|
||||
.postcard.size-square { max-width: 400px; aspect-ratio: 1 / 1; }
|
||||
.postcard-media {
|
||||
position: absolute; inset: 0; background-size: cover; background-position: center;
|
||||
}
|
||||
.postcard-overlay { position: absolute; inset: 0; pointer-events: none; }
|
||||
.postcard-overlay.ov-dark { background: linear-gradient(transparent 35%, rgba(0,0,0,.75)); }
|
||||
.postcard-overlay.ov-light { background: linear-gradient(transparent 50%, rgba(255,255,255,.92)); }
|
||||
.postcard-overlay.ov-none { background: none; }
|
||||
.postcard-overlay.ov-light ~ .postcard-copy,
|
||||
.ov-light + .postcard-copy { color: #111; }
|
||||
.postcard-copy {
|
||||
position: absolute; left: 20px; right: 20px; bottom: 18px; z-index: 2;
|
||||
}
|
||||
.postcard-headline {
|
||||
font-family: Poppins, sans-serif; font-weight: 700; font-size: 28px; letter-spacing: 0.04em;
|
||||
border-left: 4px solid #00626c; padding-left: 10px; line-height: 1.1;
|
||||
}
|
||||
.postcard-sub { margin-top: 8px; font-size: 14px; opacity: 0.95; }
|
||||
.postcard-back { background: #fafafa; color: #212121; }
|
||||
.postcard-back-grid { display: grid; grid-template-columns: 1.2fr 1fr; height: 100%; }
|
||||
.postcard-back-msg { padding: 16px; display: flex; flex-direction: column; gap: 10px; border-right: 1px dashed #cbd5e1; }
|
||||
.postcard-back-body { font-size: 12px; white-space: pre-wrap; flex: 1; line-height: 1.45; }
|
||||
.postcard-agent { font-size: 11px; font-weight: 600; color: #00626c; }
|
||||
.postcard-qr {
|
||||
width: 48px; height: 48px; background: #111; color: #fff; font-size: 10px;
|
||||
display: flex; align-items: center; justify-content: center; letter-spacing: 0.05em;
|
||||
}
|
||||
.postcard-back-mail { padding: 12px; position: relative; }
|
||||
.stamp {
|
||||
width: 44px; height: 52px; border: 2px dashed #94a3b8; float: right;
|
||||
font-size: 9px; color: #94a3b8; display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.addr-block {
|
||||
margin-top: 48px; font-size: 12px; line-height: 1.4;
|
||||
border-bottom: 1px solid #e2e8f0; padding-bottom: 8px;
|
||||
}
|
||||
|
||||
/* Social live preview */
|
||||
.platform-toggles { display: flex; flex-wrap: wrap; gap: 8px; }
|
||||
.toggle-pill {
|
||||
border: 1px solid var(--monica-border); padding: 8px 12px; font-size: 13px;
|
||||
background: #fff; display: inline-flex; align-items: center; gap: 6px;
|
||||
}
|
||||
.toggle-pill.warn { border-color: #fdba74; background: #fff7ed; }
|
||||
.social-phone {
|
||||
width: 100%; max-width: 360px; background: #fff; border: 1px solid #d1d5db;
|
||||
box-shadow: 0 8px 30px rgba(15,23,42,.12); overflow: hidden; font-size: 14px;
|
||||
}
|
||||
.social-phone.ig { max-width: 340px; }
|
||||
.soc-header {
|
||||
display: flex; align-items: center; gap: 10px; padding: 12px 14px; position: relative;
|
||||
}
|
||||
.soc-avatar {
|
||||
width: 40px; height: 40px; background: #00626c; color: #fff; display: flex;
|
||||
align-items: center; justify-content: center; font-weight: 700; font-size: 13px; flex-shrink: 0;
|
||||
}
|
||||
.soc-avatar.round { border-radius: 50%; background: linear-gradient(45deg, #f58529, #dd2a7b); }
|
||||
.soc-avatar.sq { border-radius: 4px; background: #0a66c2; }
|
||||
.soc-name { font-weight: 700; font-size: 13px; }
|
||||
.soc-meta { font-size: 11px; color: #6b7280; }
|
||||
.soc-more { margin-left: auto; color: #6b7280; }
|
||||
.soc-caption { padding: 0 14px 12px; white-space: pre-wrap; line-height: 1.4; font-size: 13px; }
|
||||
.soc-image {
|
||||
height: 200px; background-size: cover; background-position: center; background-color: #e5e7eb;
|
||||
}
|
||||
.soc-image.square { height: 340px; }
|
||||
.soc-actions {
|
||||
padding: 10px 14px; border-top: 1px solid #e5e7eb; font-size: 12px; color: #4b5563; font-weight: 600;
|
||||
}
|
||||
.ig-act { font-size: 18px; border-top: none; padding-top: 8px; }
|
||||
|
||||
|
||||
|
||||
/* Portal logout button in topbar */
|
||||
.portal-user form { display: inline; margin: 0; }
|
||||
.portal-user button.linkish {
|
||||
background: none; border: 0; padding: 0; color: var(--monica-primary);
|
||||
font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; text-decoration: underline;
|
||||
}
|
||||
.portal-flash { list-style: none; margin: 0 0 16px; padding: 0; }
|
||||
.portal-flash li {
|
||||
padding: 10px 14px; background: #e8f4f5; border-left: 3px solid var(--monica-primary);
|
||||
margin-bottom: 8px; font-size: 14px;
|
||||
}
|
||||
.portal-flash li.error { background: #fee2e2; border-left-color: #b91c1c; }
|
||||
.toolbar { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; justify-content: space-between; margin-bottom: 16px; }
|
||||
.toolbar-filters { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
|
||||
.toolbar-filters input, .toolbar-filters select {
|
||||
padding: 8px 10px; border: 1px solid var(--monica-border); font: inherit; font-size: 13px; background: #fff;
|
||||
}
|
||||
.empty-state { padding: 24px; color: var(--monica-muted); font-size: 14px; }
|
||||
|
||||
.utm-panel {
|
||||
margin-top: 4px;
|
||||
padding-top: 4px;
|
||||
}
|
||||
.utm-url {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
line-height: 1.45;
|
||||
word-break: break-all;
|
||||
background: #f8fafc;
|
||||
border: 1px solid var(--monica-border);
|
||||
padding: 8px 10px;
|
||||
color: #0f172a;
|
||||
}
|
||||
.utm-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.utm-qr {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 12px;
|
||||
}
|
||||
.utm-qr canvas {
|
||||
display: block;
|
||||
border: 1px solid var(--monica-border);
|
||||
background: #fff;
|
||||
}
|
||||
.utm-qr-actions { min-width: 160px; }
|
||||
.utm-qr-actions .btn { margin: 0 8px 8px 0; }
|
||||
#preview-body a { color: var(--monica-primary); }
|
||||
@@ -0,0 +1,211 @@
|
||||
:root {
|
||||
--bg: #1a2332;
|
||||
--bg-2: #243044;
|
||||
--ink: #f3efe6;
|
||||
--muted: #b7c0ce;
|
||||
--accent: #c4a574;
|
||||
--accent-2: #7ea08a;
|
||||
--danger: #c97b7b;
|
||||
--radius: 2px;
|
||||
--font-display: "Fraunces", Georgia, serif;
|
||||
--font-body: "Source Sans 3", system-ui, sans-serif;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
html, body { margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: var(--font-body);
|
||||
color: var(--ink);
|
||||
background:
|
||||
radial-gradient(1200px 600px at 10% -10%, #2c3d55 0%, transparent 55%),
|
||||
radial-gradient(900px 500px at 100% 0%, #3a2f28 0%, transparent 45%),
|
||||
var(--bg);
|
||||
min-height: 100vh;
|
||||
line-height: 1.5;
|
||||
}
|
||||
a { color: var(--accent); text-decoration: none; }
|
||||
a:hover { text-decoration: underline; }
|
||||
.site-header, .site-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 1rem 1.5rem;
|
||||
gap: 1rem;
|
||||
}
|
||||
.site-header nav { display: flex; gap: 1rem; flex-wrap: wrap; }
|
||||
.brand {
|
||||
font-family: var(--font-display);
|
||||
font-size: 1.4rem;
|
||||
color: var(--ink);
|
||||
font-weight: 700;
|
||||
}
|
||||
main { padding: 1.5rem; max-width: 1100px; margin: 0 auto; }
|
||||
.hero {
|
||||
min-height: 70vh;
|
||||
display: grid;
|
||||
align-content: end;
|
||||
gap: 0.75rem;
|
||||
padding: 2rem 0 3rem;
|
||||
}
|
||||
.hero h1 {
|
||||
font-family: var(--font-display);
|
||||
font-size: clamp(2.4rem, 6vw, 4.2rem);
|
||||
margin: 0;
|
||||
max-width: 14ch;
|
||||
line-height: 1.05;
|
||||
}
|
||||
.hero p { max-width: 42ch; color: var(--muted); font-size: 1.1rem; }
|
||||
.btn {
|
||||
display: inline-block;
|
||||
background: var(--accent);
|
||||
color: #1a2332;
|
||||
padding: 0.7rem 1.2rem;
|
||||
border: 0;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
.btn.secondary { background: transparent; color: var(--ink); border: 1px solid var(--muted); }
|
||||
.flash { list-style: none; padding: 0 1.5rem; }
|
||||
.flash li { background: var(--bg-2); padding: 0.6rem 0.9rem; margin: 0.4rem 0; }
|
||||
.form-grid { display: grid; gap: 0.8rem; max-width: 32rem; }
|
||||
.form-grid label { display: grid; gap: 0.3rem; color: var(--muted); }
|
||||
.form-grid input, .form-grid textarea, .form-grid select {
|
||||
background: var(--bg-2);
|
||||
border: 1px solid #3a4a63;
|
||||
color: var(--ink);
|
||||
padding: 0.6rem 0.7rem;
|
||||
font: inherit;
|
||||
}
|
||||
.portal-shell { display: grid; grid-template-columns: 220px 1fr; gap: 1.5rem; min-height: 70vh; }
|
||||
.portal-nav {
|
||||
background: rgba(36, 48, 68, 0.85);
|
||||
padding: 1rem;
|
||||
display: grid;
|
||||
gap: 0.55rem;
|
||||
align-content: start;
|
||||
}
|
||||
.portal-nav a { color: var(--ink); }
|
||||
.portal-logout { margin: 0; }
|
||||
.portal-logout button {
|
||||
background: none;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
color: var(--ink);
|
||||
font: inherit;
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
}
|
||||
.portal-logout button:hover { text-decoration: underline; }
|
||||
.brand-mini { font-family: var(--font-display); margin: 0 0 0.5rem; color: var(--accent); }
|
||||
.stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 0.8rem; }
|
||||
.stat {
|
||||
background: rgba(36, 48, 68, 0.9);
|
||||
padding: 1rem;
|
||||
}
|
||||
.stat strong { display: block; font-size: 1.6rem; font-family: var(--font-display); }
|
||||
.table { width: 100%; border-collapse: collapse; }
|
||||
.table th, .table td { text-align: left; padding: 0.55rem 0.4rem; border-bottom: 1px solid #33455f; }
|
||||
.holding {
|
||||
min-height: 80vh;
|
||||
display: grid;
|
||||
align-content: center;
|
||||
gap: 1rem;
|
||||
max-width: 36rem;
|
||||
}
|
||||
.holding h1 { font-family: var(--font-display); font-size: clamp(2rem, 5vw, 3rem); margin: 0; }
|
||||
.muted { color: var(--muted); }
|
||||
.error { color: var(--danger); }
|
||||
|
||||
.visually-hidden {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.site-footer {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.footer-meta { display: grid; gap: 0.25rem; }
|
||||
.footer-meta p { margin: 0; color: var(--muted); }
|
||||
.footer-links { margin: 0; }
|
||||
.footer-link-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
color: var(--muted);
|
||||
font: inherit;
|
||||
font-size: 0.9rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
.footer-link-btn:hover {
|
||||
color: var(--accent);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.cookie-consent-banner {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1100;
|
||||
padding: 1rem;
|
||||
background: rgba(26, 35, 50, 0.97);
|
||||
border-top: 1px solid rgba(196, 165, 116, 0.35);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
.cookie-consent-content {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
}
|
||||
.cookie-consent-text {
|
||||
flex: 1 1 420px;
|
||||
color: var(--muted);
|
||||
font-size: 0.95rem;
|
||||
margin: 0;
|
||||
}
|
||||
.cookie-consent-text-short { display: none; }
|
||||
.cookie-consent-actions {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.cookie-consent-banner {
|
||||
padding: 0.625rem 0.75rem;
|
||||
padding-bottom: max(0.625rem, env(safe-area-inset-bottom));
|
||||
}
|
||||
.cookie-consent-content {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 0.625rem;
|
||||
}
|
||||
.cookie-consent-text-short { display: inline; }
|
||||
.cookie-consent-text-full { display: none; }
|
||||
.cookie-consent-text {
|
||||
flex: none;
|
||||
font-size: 0.8125rem;
|
||||
line-height: 1.35;
|
||||
}
|
||||
.cookie-consent-actions { width: 100%; }
|
||||
.cookie-consent-actions .btn {
|
||||
flex: 1;
|
||||
padding: 0.5rem 0.75rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
.portal-shell { grid-template-columns: 1fr; }
|
||||
}
|
||||
@@ -0,0 +1,373 @@
|
||||
/* EXIT Realty / MKDRealtor public brand overrides on Real Estate theme */
|
||||
|
||||
:root {
|
||||
--monica-primary: #00626c;
|
||||
--monica-primary-light: #008898;
|
||||
--monica-ink: #212121;
|
||||
--monica-muted: #6b7280;
|
||||
--monica-surface: #f4f7f7;
|
||||
--monica-border: #d9e3e4;
|
||||
}
|
||||
|
||||
.footer-brand-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.footer-brand-row img {
|
||||
height: 40px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.about-subtitle {
|
||||
font-size: 18px;
|
||||
color: var(--monica-muted);
|
||||
}
|
||||
|
||||
.page .button-primary,
|
||||
.page .button-primary:focus,
|
||||
.page .button-primary:active,
|
||||
.cookie-consent-banner .button-primary,
|
||||
.cookie-consent-banner .button-primary:focus,
|
||||
.cookie-consent-banner .button-primary:active {
|
||||
background-color: var(--monica-primary) !important;
|
||||
border-color: var(--monica-primary) !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
.page .button-primary:hover,
|
||||
.cookie-consent-banner .button-primary:hover {
|
||||
background-color: var(--monica-primary-light) !important;
|
||||
border-color: var(--monica-primary-light) !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
/* Theme default blue (#0045b6) → EXIT Realty teal on public chrome */
|
||||
html .page .text-primary {
|
||||
color: var(--monica-primary) !important;
|
||||
}
|
||||
.page .breadcrumbs-custom-path a,
|
||||
.page a.link-default {
|
||||
color: var(--monica-primary);
|
||||
}
|
||||
.page a.link-default:hover {
|
||||
color: var(--monica-primary-light);
|
||||
}
|
||||
|
||||
.page .button-gray-bordered:hover,
|
||||
.page .button-gray-bordered:active,
|
||||
.page .button-default:hover,
|
||||
.page .button-default:active,
|
||||
.page .button-accent-outline:hover,
|
||||
.page .button-accent-outline:active,
|
||||
.page .button-primary-outline:hover,
|
||||
.page .button-primary-outline:active,
|
||||
.page .button-primary-white:hover,
|
||||
.page .button-primary-white:active,
|
||||
.page .button.button-primary-lighten,
|
||||
.page .button.button-primary-lighten:focus {
|
||||
background-color: var(--monica-primary) !important;
|
||||
border-color: var(--monica-primary) !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
.page .button.button-primary-lighten:hover,
|
||||
.page .button.button-primary-lighten:active {
|
||||
background-color: var(--monica-ink) !important;
|
||||
border-color: var(--monica-ink) !important;
|
||||
}
|
||||
.page .button-accent-outline,
|
||||
.page .button-accent-outline:focus {
|
||||
border-color: var(--monica-primary) !important;
|
||||
}
|
||||
.page .button-video:hover {
|
||||
color: var(--monica-primary) !important;
|
||||
}
|
||||
.page .btn-primary,
|
||||
.page .btn-primary:active,
|
||||
.page .btn-primary:focus {
|
||||
background: var(--monica-primary) !important;
|
||||
border-color: var(--monica-primary) !important;
|
||||
}
|
||||
.page .box-chloe__icon,
|
||||
.page .box-light-icon,
|
||||
.page .box-minimal-icon .box-chloe__icon {
|
||||
color: var(--monica-primary);
|
||||
}
|
||||
|
||||
/* Mobile drawer active/hover — theme uses #0045b6 */
|
||||
.rd-navbar-fixed .rd-nav-item:hover .rd-nav-link,
|
||||
.rd-navbar-fixed .rd-nav-item.focus .rd-nav-link,
|
||||
.rd-navbar-fixed .rd-nav-item.active .rd-nav-link,
|
||||
.rd-navbar-fixed .rd-nav-item.opened .rd-nav-link {
|
||||
background: var(--monica-primary) !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
/* Scroll-to-top (injected outside .page) */
|
||||
.ui-to-top {
|
||||
background: var(--monica-primary) !important;
|
||||
color: #fff !important;
|
||||
box-shadow: 0 6px 16px rgba(0, 98, 108, 0.35);
|
||||
}
|
||||
.ui-to-top:hover,
|
||||
.ui-to-top:focus {
|
||||
background: var(--monica-primary-light) !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
/* Django flash messages */
|
||||
.flash {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 12px 0 0;
|
||||
}
|
||||
.flash li {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto 8px;
|
||||
padding: 12px 16px;
|
||||
background: #e8f4f5;
|
||||
border-left: 3px solid #00626c;
|
||||
color: #0d4a52;
|
||||
font-size: 14px;
|
||||
}
|
||||
.flash li.error,
|
||||
.flash li.danger {
|
||||
background: #fee2e2;
|
||||
border-left-color: #b91c1c;
|
||||
color: #991b1b;
|
||||
}
|
||||
|
||||
/* Form field errors */
|
||||
.form-wrap .errorlist {
|
||||
list-style: none;
|
||||
margin: 6px 0 0;
|
||||
padding: 0;
|
||||
color: #b91c1c;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* Cookie consent — match public EXIT Realty teal brand */
|
||||
.cookie-consent-banner {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 11000;
|
||||
padding: 1rem 1.25rem;
|
||||
background: rgba(17, 24, 28, 0.96);
|
||||
border-top: 2px solid var(--monica-primary);
|
||||
box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.28);
|
||||
font-family: "Work Sans", sans-serif;
|
||||
}
|
||||
.cookie-consent-content {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
}
|
||||
.cookie-consent-text {
|
||||
flex: 1 1 420px;
|
||||
color: #d7dee3;
|
||||
font-size: 0.9375rem;
|
||||
line-height: 1.45;
|
||||
margin: 0;
|
||||
font-family: "Work Sans", sans-serif;
|
||||
font-weight: 400;
|
||||
}
|
||||
.cookie-consent-text-short {
|
||||
display: none;
|
||||
}
|
||||
.cookie-consent-actions {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.cookie-consent-banner .button {
|
||||
min-width: 10rem;
|
||||
padding-left: 1.5rem;
|
||||
padding-right: 1.5rem;
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
font-family: "Work Sans", sans-serif;
|
||||
font-weight: 500;
|
||||
}
|
||||
.visually-hidden {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
.footer-link-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
color: #7dd3da;
|
||||
font: inherit;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
.footer-link-btn:hover {
|
||||
text-decoration: underline;
|
||||
color: #a8e8ed;
|
||||
}
|
||||
|
||||
.cookie-consent-link {
|
||||
color: #7dd3da;
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
.cookie-consent-link:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.legal-prose {
|
||||
max-width: 42rem;
|
||||
}
|
||||
.legal-prose .legal-lead {
|
||||
font-size: 1.05rem;
|
||||
color: var(--monica-ink);
|
||||
margin-bottom: 1.75rem;
|
||||
}
|
||||
.legal-prose h2 {
|
||||
font-size: 1.35rem;
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 0.75rem;
|
||||
text-transform: none;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
.legal-prose p {
|
||||
margin-bottom: 1rem;
|
||||
color: #4b5563;
|
||||
line-height: 1.65;
|
||||
}
|
||||
.legal-prose .legal-updated {
|
||||
margin-top: 2.5rem;
|
||||
font-size: 0.875rem;
|
||||
color: var(--monica-muted);
|
||||
}
|
||||
|
||||
/* Contact form — breathe on narrow viewports */
|
||||
@media (max-width: 767.98px) {
|
||||
.contact-form-section > .container {
|
||||
padding-left: 1.5rem;
|
||||
padding-right: 1.5rem;
|
||||
}
|
||||
.contact-form-section .section-lg {
|
||||
padding-top: 2.5rem;
|
||||
padding-bottom: 2.5rem;
|
||||
}
|
||||
.contact-form-section h3 {
|
||||
margin-bottom: 1.25rem;
|
||||
padding-right: 0.25rem;
|
||||
}
|
||||
.contact-message-form .form-wrap {
|
||||
margin-bottom: 0.35rem;
|
||||
}
|
||||
.contact-message-form .form-label-outside {
|
||||
margin-bottom: 0.35rem;
|
||||
}
|
||||
.contact-message-form .row-10 {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
.contact-message-form .row-10 > [class*="col-"] {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-aside-copy {
|
||||
text-align: right;
|
||||
}
|
||||
.footer-aside-copy .rights {
|
||||
margin: 0;
|
||||
}
|
||||
.footer-made-by {
|
||||
margin: 6px 0 0;
|
||||
font-size: 13px;
|
||||
color: #9ca3af;
|
||||
font-family: "Work Sans", sans-serif;
|
||||
}
|
||||
.footer-made-by a {
|
||||
color: #d1d5db;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.footer-made-by a:hover {
|
||||
color: #fff;
|
||||
}
|
||||
.footer-minimal .footer-made-by {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.footer-minimal-inner {
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.pref-check {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
font-size: 15px;
|
||||
color: var(--monica-ink);
|
||||
cursor: pointer;
|
||||
}
|
||||
.pref-check input {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.cookie-consent-banner {
|
||||
padding: 0.625rem 0.75rem;
|
||||
padding-bottom: max(0.625rem, env(safe-area-inset-bottom));
|
||||
}
|
||||
.cookie-consent-content {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 0.625rem;
|
||||
}
|
||||
.cookie-consent-text-short {
|
||||
display: inline;
|
||||
}
|
||||
.cookie-consent-text-full {
|
||||
display: none;
|
||||
}
|
||||
.cookie-consent-text {
|
||||
flex: none;
|
||||
font-size: 0.8125rem;
|
||||
line-height: 1.35;
|
||||
}
|
||||
.cookie-consent-actions {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* Keep hero slide-2 heading visually aligned with slide-1 h1 (SEO: one h1). */
|
||||
.swiper-slider-minimal .jumbotron-classic-content h1.font-weight-bold,
|
||||
.swiper-slider-minimal .jumbotron-classic-content h2.font-weight-bold {
|
||||
font-size: 2.5rem;
|
||||
line-height: 1.15;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.swiper-slider-minimal .jumbotron-classic-content h1.font-weight-bold,
|
||||
.swiper-slider-minimal .jumbotron-classic-content h2.font-weight-bold {
|
||||
font-size: 3.5rem;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
.swiper-slider-minimal .jumbotron-classic-content h1.font-weight-bold,
|
||||
.swiper-slider-minimal .jumbotron-classic-content h2.font-weight-bold {
|
||||
font-size: 4.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 270 KiB |
|
After Width: | Height: | Size: 434 KiB |
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>
|
||||
<json>
|
||||
<![CDATA[
|
||||
{
|
||||
"fontFamily": "lg",
|
||||
"majorVersion": 1,
|
||||
"minorVersion": 0,
|
||||
"fontURL": "https://github.com/sachinchoolur/lightGallery",
|
||||
"copyright": "sachin",
|
||||
"license": "MLT",
|
||||
"licenseURL": "http://opensource.org/licenses/MIT",
|
||||
"version": "Version 1.0",
|
||||
"fontId": "lg",
|
||||
"psName": "lg",
|
||||
"subFamily": "Regular",
|
||||
"fullName": "lg",
|
||||
"description": "Font generated by IcoMoon."
|
||||
}
|
||||
]]>
|
||||
</json>
|
||||
</metadata>
|
||||
<defs>
|
||||
<font id="lg" horiz-adv-x="1024">
|
||||
<font-face units-per-em="1024" ascent="960" descent="-64" />
|
||||
<missing-glyph horiz-adv-x="1024" />
|
||||
<glyph unicode=" " horiz-adv-x="512" d="" />
|
||||
<glyph unicode="" glyph-name="pause_circle_outline" data-tags="pause_circle_outline" d="M554 256.667v340h86v-340h-86zM512 84.667q140 0 241 101t101 241-101 241-241 101-241-101-101-241 101-241 241-101zM512 852.667q176 0 301-125t125-301-125-301-301-125-301 125-125 301 125 301 301 125zM384 256.667v340h86v-340h-86z" />
|
||||
<glyph unicode="" glyph-name="play_circle_outline" data-tags="play_circle_outline" d="M512 84.667q140 0 241 101t101 241-101 241-241 101-241-101-101-241 101-241 241-101zM512 852.667q176 0 301-125t125-301-125-301-301-125-301 125-125 301 125 301 301 125zM426 234.667v384l256-192z" />
|
||||
<glyph unicode="" glyph-name="stack-2" data-tags="stack-2" d="M384 853.334h426.667q53 0 90.5-37.5t37.5-90.5v-426.667q0-53-37.5-90.5t-90.5-37.5h-426.667q-53 0-90.5 37.5t-37.5 90.5v426.667q0 53 37.5 90.5t90.5 37.5zM170.667 675.334v-547.333q0-17.667 12.5-30.167t30.167-12.5h547.333q-13.333-37.667-46.333-61.5t-74.333-23.833h-426.667q-53 0-90.5 37.5t-37.5 90.5v426.667q0 41.333 23.833 74.333t61.5 46.333zM810.667 768h-426.667q-17.667 0-30.167-12.5t-12.5-30.167v-426.667q0-17.667 12.5-30.167t30.167-12.5h426.667q17.667 0 30.167 12.5t12.5 30.167v426.667q0 17.667-12.5 30.167t-30.167 12.5z" />
|
||||
<glyph unicode="" glyph-name="clear" data-tags="clear" d="M810 664.667l-238-238 238-238-60-60-238 238-238-238-60 60 238 238-238 238 60 60 238-238 238 238z" />
|
||||
<glyph unicode="" glyph-name="arrow-left" data-tags="arrow-left" d="M426.667 768q17.667 0 30.167-12.5t12.5-30.167q0-18-12.667-30.333l-225.667-225.667h665q17.667 0 30.167-12.5t12.5-30.167-12.5-30.167-30.167-12.5h-665l225.667-225.667q12.667-12.333 12.667-30.333 0-17.667-12.5-30.167t-30.167-12.5q-18 0-30.333 12.333l-298.667 298.667q-12.333 13-12.333 30.333t12.333 30.333l298.667 298.667q12.667 12.333 30.333 12.333z" />
|
||||
<glyph unicode="" glyph-name="arrow-right" data-tags="arrow-right" d="M597.333 768q18 0 30.333-12.333l298.667-298.667q12.333-12.333 12.333-30.333t-12.333-30.333l-298.667-298.667q-12.333-12.333-30.333-12.333-18.333 0-30.5 12.167t-12.167 30.5q0 18 12.333 30.333l226 225.667h-665q-17.667 0-30.167 12.5t-12.5 30.167 12.5 30.167 30.167 12.5h665l-226 225.667q-12.333 12.333-12.333 30.333 0 18.333 12.167 30.5t30.5 12.167z" />
|
||||
<glyph unicode="" glyph-name="vertical_align_bottom" data-tags="vertical_align_bottom" d="M170 128.667h684v-86h-684v86zM682 384.667l-170-172-170 172h128v426h84v-426h128z" />
|
||||
<glyph unicode="" glyph-name="apps" data-tags="apps" d="M682 84.667v172h172v-172h-172zM682 340.667v172h172v-172h-172zM426 596.667v172h172v-172h-172zM682 768.667h172v-172h-172v172zM426 340.667v172h172v-172h-172zM170 340.667v172h172v-172h-172zM170 84.667v172h172v-172h-172zM426 84.667v172h172v-172h-172zM170 596.667v172h172v-172h-172z" />
|
||||
<glyph unicode="" glyph-name="fullscreen" data-tags="fullscreen" d="M598 724.667h212v-212h-84v128h-128v84zM726 212.667v128h84v-212h-212v84h128zM214 512.667v212h212v-84h-128v-128h-84zM298 340.667v-128h128v-84h-212v212h84z" />
|
||||
<glyph unicode="" glyph-name="fullscreen_exit" data-tags="fullscreen_exit" d="M682 596.667h128v-84h-212v212h84v-128zM598 128.667v212h212v-84h-128v-128h-84zM342 596.667v128h84v-212h-212v84h128zM214 256.667v84h212v-212h-84v128h-128z" />
|
||||
<glyph unicode="" glyph-name="zoom_in" data-tags="zoom_in" d="M512 512.667h-86v-86h-42v86h-86v42h86v86h42v-86h86v-42zM406 340.667q80 0 136 56t56 136-56 136-136 56-136-56-56-136 56-136 136-56zM662 340.667l212-212-64-64-212 212v34l-12 12q-76-66-180-66-116 0-197 80t-81 196 81 197 197 81 196-81 80-197q0-104-66-180l12-12h34z" />
|
||||
<glyph unicode="" glyph-name="zoom_out" data-tags="zoom_out" d="M298 554.667h214v-42h-214v42zM406 340.667q80 0 136 56t56 136-56 136-136 56-136-56-56-136 56-136 136-56zM662 340.667l212-212-64-64-212 212v34l-12 12q-76-66-180-66-116 0-197 80t-81 196 81 197 197 81 196-81 80-197q0-104-66-180l12-12h34z" />
|
||||
<glyph unicode="" glyph-name="share" data-tags="share" d="M768 252.667c68 0 124-56 124-124s-56-126-124-126-124 58-124 126c0 10 0 20 2 28l-302 176c-24-22-54-34-88-34-70 0-128 58-128 128s58 128 128 128c34 0 64-12 88-34l300 174c-2 10-4 20-4 30 0 70 58 128 128 128s128-58 128-128-58-128-128-128c-34 0-64 14-88 36l-300-176c2-10 4-20 4-30s-2-20-4-30l304-176c22 20 52 32 84 32z" />
|
||||
<glyph unicode="" glyph-name="facebook-with-circle" data-tags="facebook-with-circle" d="M512 952.32c-271.462 0-491.52-220.058-491.52-491.52s220.058-491.52 491.52-491.52 491.52 220.058 491.52 491.52-220.058 491.52-491.52 491.52zM628.429 612.659h-73.882c-8.755 0-18.483-11.52-18.483-26.829v-53.35h92.416l-13.978-76.083h-78.438v-228.403h-87.194v228.403h-79.104v76.083h79.104v44.749c0 64.205 44.544 116.378 105.677 116.378h73.882v-80.947z" />
|
||||
<glyph unicode="" glyph-name="google-with-circle" data-tags="google+-with-circle" d="M512 952.32c-271.462 0-491.52-220.058-491.52-491.52s220.058-491.52 491.52-491.52 491.52 220.058 491.52 491.52-220.058 491.52-491.52 491.52zM483.686 249.805c-30.874-15.002-64.102-16.589-76.954-16.589-2.458 0-3.84 0-3.84 0s-1.178 0-2.765 0c-20.070 0-119.962 4.608-119.962 95.59 0 89.395 108.8 96.41 142.131 96.41h0.87c-19.251 25.702-15.258 51.61-15.258 51.61-1.69-0.102-4.147-0.205-7.168-0.205-12.544 0-36.762 1.997-57.549 15.411-25.498 16.384-38.4 44.288-38.4 82.893 0 109.107 119.142 113.51 120.32 113.613h118.989v-2.611c0-13.312-23.91-15.923-40.192-18.125-5.53-0.819-16.64-1.894-19.763-3.482 30.157-16.128 35.021-41.421 35.021-79.104 0-42.906-16.794-65.587-34.611-81.51-11.059-9.882-19.712-17.613-19.712-28.006 0-10.189 11.878-20.582 25.702-32.717 22.579-19.917 53.555-47.002 53.555-92.723 0-47.258-20.326-81.050-60.416-100.454zM742.4 460.8h-76.8v-76.8h-51.2v76.8h-76.8v51.2h76.8v76.8h51.2v-76.8h76.8v-51.2zM421.018 401.92c-2.662 0-5.325-0.102-8.038-0.307-22.733-1.69-43.725-10.189-58.88-24.013-15.053-13.619-22.733-30.822-21.658-48.179 2.304-36.403 41.37-57.702 88.832-54.323 46.694 3.379 77.824 30.31 75.571 66.714-2.15 34.202-31.898 60.109-75.827 60.109zM465.766 599.808c-12.39 43.52-32.358 56.422-63.386 56.422-3.328 0-6.707-0.512-9.933-1.382-13.466-3.84-24.166-15.053-30.106-31.744-6.093-16.896-6.451-34.509-1.229-54.579 9.472-35.891 34.97-61.901 60.672-61.901 3.379 0 6.758 0.41 9.933 1.382 28.109 7.885 45.722 50.79 34.048 91.802z" />
|
||||
<glyph unicode="" glyph-name="pinterest-with-circle" data-tags="pinterest-with-circle" d="M512 952.32c-271.462 0-491.52-220.058-491.52-491.52s220.058-491.52 491.52-491.52 491.52 220.058 491.52 491.52-220.058 491.52-491.52 491.52zM545.638 344.32c-31.539 2.406-44.749 18.022-69.427 32.973-13.568-71.219-30.157-139.52-79.309-175.206-15.206 107.725 22.221 188.518 39.629 274.381-29.645 49.92 3.533 150.323 66.099 125.645 76.954-30.515-66.662-185.6 29.747-205.005 100.659-20.173 141.773 174.694 79.36 237.978-90.214 91.494-262.502 2.099-241.306-128.87 5.12-32 38.246-41.728 13.21-85.914-57.702 12.8-74.957 58.317-72.704 118.989 3.533 99.328 89.242 168.909 175.155 178.483 108.698 12.083 210.688-39.885 224.819-142.182 15.821-115.405-49.101-240.282-165.274-231.27z" />
|
||||
<glyph unicode="" glyph-name="twitter-with-circle" data-tags="twitter-with-circle" d="M512 952.32c-271.462 0-491.52-220.058-491.52-491.52s220.058-491.52 491.52-491.52 491.52 220.058 491.52 491.52-220.058 491.52-491.52 491.52zM711.936 549.683c0.205-4.198 0.256-8.397 0.256-12.493 0-128-97.331-275.507-275.405-275.507-54.682 0-105.574 15.974-148.378 43.52 7.526-0.922 15.258-1.28 23.091-1.28 45.363 0 87.091 15.411 120.218 41.421-42.342 0.819-78.080 28.774-90.419 67.174 5.888-1.075 11.93-1.69 18.176-1.69 8.806 0 17.408 1.178 25.498 3.379-44.288 8.909-77.67 48.026-77.67 94.925v1.178c13.056-7.219 28.006-11.622 43.878-12.134-26.010 17.408-43.059 47.002-43.059 80.64 0 17.715 4.762 34.406 13.107 48.691 47.77-58.573 119.040-97.075 199.526-101.222-1.69 7.117-2.509 14.49-2.509 22.118 0 53.402 43.315 96.819 96.819 96.819 27.802 0 52.992-11.776 70.656-30.618 22.067 4.403 42.752 12.39 61.44 23.501-7.219-22.579-22.528-41.574-42.547-53.606 19.61 2.406 38.246 7.578 55.603 15.309-12.954-19.405-29.389-36.506-48.282-50.125z" />
|
||||
</font></defs></svg>
|
||||
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 647 KiB |
|
After Width: | Height: | Size: 455 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 163 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 244 KiB |
|
After Width: | Height: | Size: 412 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
* Address autocomplete via Django /api/address-suggest/ (Nominatim proxy).
|
||||
* Never calls Nominatim from the browser.
|
||||
*
|
||||
* Markup: wrap fields in [data-address-autocomplete][data-suggest-url="..."].
|
||||
* Mark inputs with data-ac="line1|line2|city|state|zip|country".
|
||||
* The line1 input is the typeahead trigger.
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var DEBOUNCE_MS = 280;
|
||||
var MIN_CHARS = 3;
|
||||
|
||||
function debounce(fn, wait) {
|
||||
var t;
|
||||
return function () {
|
||||
var ctx = this;
|
||||
var args = arguments;
|
||||
clearTimeout(t);
|
||||
t = setTimeout(function () {
|
||||
fn.apply(ctx, args);
|
||||
}, wait);
|
||||
};
|
||||
}
|
||||
|
||||
function field(root, key) {
|
||||
return root.querySelector('[data-ac="' + key + '"]');
|
||||
}
|
||||
|
||||
function ensureList(root) {
|
||||
var list = root.querySelector(".address-ac-list");
|
||||
if (list) {
|
||||
return list;
|
||||
}
|
||||
list = document.createElement("ul");
|
||||
list.className = "address-ac-list";
|
||||
list.hidden = true;
|
||||
list.setAttribute("role", "listbox");
|
||||
var line1 = field(root, "line1");
|
||||
var wrap = line1 && line1.closest(".form-wrap, .field");
|
||||
(wrap || root).appendChild(list);
|
||||
if (wrap) {
|
||||
wrap.classList.add("address-ac-wrap");
|
||||
} else {
|
||||
root.classList.add("address-ac-wrap");
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
function hide(list) {
|
||||
list.hidden = true;
|
||||
list.innerHTML = "";
|
||||
}
|
||||
|
||||
function fill(root, item) {
|
||||
var map = {
|
||||
line1: item.line1 || "",
|
||||
line2: item.line2 || "",
|
||||
city: item.city || "",
|
||||
state: item.state || "",
|
||||
zip: item.zip || "",
|
||||
country: item.country || "US",
|
||||
};
|
||||
Object.keys(map).forEach(function (key) {
|
||||
var el = field(root, key);
|
||||
if (el) {
|
||||
el.value = map[key];
|
||||
el.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
el.dispatchEvent(new Event("change", { bubbles: true }));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function render(root, list, results) {
|
||||
list.innerHTML = "";
|
||||
if (!results.length) {
|
||||
hide(list);
|
||||
return;
|
||||
}
|
||||
results.forEach(function (item, index) {
|
||||
var li = document.createElement("li");
|
||||
li.className = "address-ac-item";
|
||||
li.setAttribute("role", "option");
|
||||
li.setAttribute("tabindex", "-1");
|
||||
li.dataset.index = String(index);
|
||||
li.textContent = item.label || item.line1 || "Address";
|
||||
li.addEventListener("mousedown", function (ev) {
|
||||
ev.preventDefault();
|
||||
fill(root, item);
|
||||
hide(list);
|
||||
});
|
||||
list.appendChild(li);
|
||||
});
|
||||
list.hidden = false;
|
||||
}
|
||||
|
||||
function bind(root) {
|
||||
var url = root.getAttribute("data-suggest-url");
|
||||
var input = field(root, "line1");
|
||||
if (!url || !input) {
|
||||
return;
|
||||
}
|
||||
var list = ensureList(root);
|
||||
input.setAttribute("autocomplete", "off");
|
||||
input.setAttribute("aria-autocomplete", "list");
|
||||
|
||||
var fetchSuggest = debounce(function () {
|
||||
var q = (input.value || "").trim();
|
||||
if (q.length < MIN_CHARS) {
|
||||
hide(list);
|
||||
return;
|
||||
}
|
||||
var req = url + (url.indexOf("?") >= 0 ? "&" : "?") + "q=" + encodeURIComponent(q) + "&limit=5";
|
||||
fetch(req, { headers: { Accept: "application/json" }, credentials: "same-origin" })
|
||||
.then(function (res) {
|
||||
return res.json();
|
||||
})
|
||||
.then(function (data) {
|
||||
render(root, list, (data && data.results) || []);
|
||||
})
|
||||
.catch(function () {
|
||||
hide(list);
|
||||
});
|
||||
}, DEBOUNCE_MS);
|
||||
|
||||
input.addEventListener("input", fetchSuggest);
|
||||
input.addEventListener("keydown", function (ev) {
|
||||
if (ev.key === "Escape") {
|
||||
hide(list);
|
||||
}
|
||||
});
|
||||
document.addEventListener("click", function (ev) {
|
||||
if (!root.contains(ev.target)) {
|
||||
hide(list);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
document.querySelectorAll("[data-address-autocomplete]").forEach(bind);
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,301 @@
|
||||
/**
|
||||
* Campaign UTM link helper (composer + report).
|
||||
* utm_source from data-utm-source (brand slug), utm_medium=email|sms|postcard,
|
||||
* utm_campaign=slug(name). Short URLs come from the portal JSON endpoint.
|
||||
*/
|
||||
(function (global) {
|
||||
"use strict";
|
||||
|
||||
var SLUG_MAX = 80;
|
||||
var SHORTEN_WAIT_MS = 400;
|
||||
var SHORT_URL_RE =
|
||||
/https?:\/\/(?:(?:www\.)?(?:beta\.)?piha\.li|(?:127\.0\.0\.1|localhost):\d+)\/[a-z0-9]{4,8}/i;
|
||||
|
||||
function slug(name) {
|
||||
var s = String(name || "")
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, "-")
|
||||
.replace(/^-+|-+$/g, "");
|
||||
return (s || "campaign").slice(0, SLUG_MAX);
|
||||
}
|
||||
|
||||
function sourceFrom(panel) {
|
||||
return slug((panel && panel.getAttribute("data-utm-source")) || "campaign");
|
||||
}
|
||||
|
||||
function utmUrlRe(source) {
|
||||
return new RegExp(
|
||||
"https?:\\/\\/[^\\s<>\"]+utm_source=" + source + "[^\\s<>\"]*",
|
||||
"i"
|
||||
);
|
||||
}
|
||||
|
||||
function buildUrl(base, medium, name, source) {
|
||||
var root = String(base || "").replace(/\/+$/, "");
|
||||
var ch = String(medium || "email").toLowerCase();
|
||||
if (ch !== "email" && ch !== "sms" && ch !== "postcard") ch = "email";
|
||||
var q =
|
||||
"utm_source=" +
|
||||
encodeURIComponent(source || "campaign") +
|
||||
"&utm_medium=" +
|
||||
encodeURIComponent(ch) +
|
||||
"&utm_campaign=" +
|
||||
encodeURIComponent(slug(name));
|
||||
return root + "/?" + q;
|
||||
}
|
||||
|
||||
function replaceTextUrl(text, url, source) {
|
||||
var raw = String(text || "");
|
||||
var utmRe = utmUrlRe(source || "campaign");
|
||||
if (utmRe.test(raw)) {
|
||||
return raw.replace(utmRe, url);
|
||||
}
|
||||
if (SHORT_URL_RE.test(raw)) {
|
||||
return raw.replace(SHORT_URL_RE, url);
|
||||
}
|
||||
var trimmed = raw.replace(/\s+$/, "");
|
||||
return trimmed ? trimmed + "\n\n" + url : url;
|
||||
}
|
||||
|
||||
function linkify(text) {
|
||||
var esc = String(text || "").replace(/[&<>"']/g, function (c) {
|
||||
return (
|
||||
{ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[
|
||||
c
|
||||
] || c
|
||||
);
|
||||
});
|
||||
return esc.replace(
|
||||
/(https?:\/\/[^\s]+)/g,
|
||||
'<a href="$1" rel="noopener noreferrer">$1</a>'
|
||||
);
|
||||
}
|
||||
|
||||
function ensureQuillLink(quill, url, label, source) {
|
||||
if (!quill || !quill.root) return;
|
||||
var src = source || "campaign";
|
||||
var existing = quill.root.querySelectorAll(
|
||||
'a[data-campaign-utm], a[href*="utm_source=' +
|
||||
src +
|
||||
'"], a[href*="piha.li/"]'
|
||||
);
|
||||
if (existing.length) {
|
||||
existing.forEach(function (a) {
|
||||
a.setAttribute("href", url);
|
||||
a.setAttribute("data-campaign-utm", "1");
|
||||
});
|
||||
return;
|
||||
}
|
||||
var labelText = label || "Website";
|
||||
var start = Math.max(0, quill.getLength() - 1);
|
||||
quill.insertText(start, "\n" + labelText, "silent");
|
||||
quill.formatText(start + 1, labelText.length, "link", url, "silent");
|
||||
var links = quill.root.querySelectorAll("a");
|
||||
var last = links[links.length - 1];
|
||||
if (last) last.setAttribute("data-campaign-utm", "1");
|
||||
}
|
||||
|
||||
function renderQr(canvas, url) {
|
||||
if (!canvas || !url || typeof QRCode === "undefined") return Promise.resolve();
|
||||
return QRCode.toCanvas(canvas, url, {
|
||||
width: 192,
|
||||
margin: 1,
|
||||
color: { dark: "#00626c", light: "#ffffff" },
|
||||
});
|
||||
}
|
||||
|
||||
function flash(el, okText, errText, ok) {
|
||||
if (!el) return;
|
||||
el.textContent = ok ? okText : errText;
|
||||
el.hidden = false;
|
||||
window.setTimeout(function () {
|
||||
el.hidden = true;
|
||||
}, 2200);
|
||||
}
|
||||
|
||||
function copyText(text) {
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
return navigator.clipboard.writeText(text);
|
||||
}
|
||||
return Promise.reject(new Error("clipboard unavailable"));
|
||||
}
|
||||
|
||||
function copyCanvas(canvas) {
|
||||
if (!canvas || !canvas.toBlob) {
|
||||
return Promise.reject(new Error("canvas unavailable"));
|
||||
}
|
||||
return new Promise(function (resolve, reject) {
|
||||
canvas.toBlob(function (blob) {
|
||||
if (!blob) {
|
||||
reject(new Error("qr blob failed"));
|
||||
return;
|
||||
}
|
||||
if (
|
||||
!navigator.clipboard ||
|
||||
!navigator.clipboard.write ||
|
||||
typeof ClipboardItem === "undefined"
|
||||
) {
|
||||
reject(new Error("image clipboard unavailable"));
|
||||
return;
|
||||
}
|
||||
navigator.clipboard
|
||||
.write([new ClipboardItem({ "image/png": blob })])
|
||||
.then(resolve, reject);
|
||||
}, "image/png");
|
||||
});
|
||||
}
|
||||
|
||||
function downloadCanvas(canvas, filename) {
|
||||
if (!canvas) return;
|
||||
var a = document.createElement("a");
|
||||
a.href = canvas.toDataURL("image/png");
|
||||
a.download = filename || "campaign-qr.png";
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
}
|
||||
|
||||
function bindPanel(panel, opts) {
|
||||
if (!panel) return;
|
||||
opts = opts || {};
|
||||
var urlEl = panel.querySelector("[data-utm-url]");
|
||||
var canvas = panel.querySelector("[data-utm-qr]");
|
||||
var qrWrap = panel.querySelector("[data-utm-qr-wrap]");
|
||||
var smsHint = panel.querySelector("[data-utm-sms-hint]");
|
||||
var emailHint = panel.querySelector("[data-utm-email-hint]");
|
||||
var postcardHint = panel.querySelector("[data-utm-postcard-hint]");
|
||||
var statusEl = panel.querySelector("[data-utm-status]");
|
||||
var base = panel.getAttribute("data-base-url") || "";
|
||||
var source = sourceFrom(panel);
|
||||
var label = panel.getAttribute("data-link-label") || "Website";
|
||||
var live = panel.getAttribute("data-live") === "1";
|
||||
var shortenUrl = panel.getAttribute("data-shorten-url") || "";
|
||||
var csrf = (opts.csrfToken || panel.getAttribute("data-csrf") || "").trim();
|
||||
var shortenTimer = null;
|
||||
var shortenSeq = 0;
|
||||
|
||||
function medium() {
|
||||
if (typeof opts.getMedium === "function") return opts.getMedium();
|
||||
return panel.getAttribute("data-medium") || "email";
|
||||
}
|
||||
|
||||
function name() {
|
||||
if (typeof opts.getName === "function") return opts.getName();
|
||||
return panel.getAttribute("data-campaign-name") || "";
|
||||
}
|
||||
|
||||
function campaignId() {
|
||||
return (
|
||||
(typeof opts.getCampaignId === "function" && opts.getCampaignId()) ||
|
||||
panel.getAttribute("data-campaign-id") ||
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
function paint(url, inject) {
|
||||
var ch = medium();
|
||||
if (urlEl) urlEl.textContent = url;
|
||||
if (qrWrap) qrWrap.hidden = ch !== "postcard";
|
||||
if (smsHint) smsHint.hidden = ch !== "sms";
|
||||
if (emailHint) emailHint.hidden = ch !== "email";
|
||||
if (postcardHint) postcardHint.hidden = ch !== "postcard";
|
||||
if (ch === "postcard" && canvas) {
|
||||
renderQr(canvas, url).catch(function () {});
|
||||
}
|
||||
if (inject && typeof opts.onUrlChange === "function") {
|
||||
opts.onUrlChange(url, ch, label);
|
||||
}
|
||||
}
|
||||
|
||||
function apply() {
|
||||
var ch = medium();
|
||||
var longUrl = buildUrl(base, ch, name(), source);
|
||||
if (!shortenUrl) {
|
||||
paint(longUrl, true);
|
||||
return longUrl;
|
||||
}
|
||||
paint(longUrl, false);
|
||||
var seq = ++shortenSeq;
|
||||
window.clearTimeout(shortenTimer);
|
||||
shortenTimer = window.setTimeout(function () {
|
||||
fetch(shortenUrl, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
"X-CSRFToken": csrf,
|
||||
},
|
||||
credentials: "same-origin",
|
||||
body: JSON.stringify({
|
||||
name: name(),
|
||||
medium: ch,
|
||||
campaign_id: campaignId(),
|
||||
}),
|
||||
})
|
||||
.then(function (r) {
|
||||
return r.ok ? r.json() : Promise.reject();
|
||||
})
|
||||
.then(function (data) {
|
||||
if (seq !== shortenSeq) return;
|
||||
paint((data && data.display_url) || longUrl, true);
|
||||
})
|
||||
.catch(function () {
|
||||
if (seq !== shortenSeq) return;
|
||||
paint(longUrl, true);
|
||||
});
|
||||
}, SHORTEN_WAIT_MS);
|
||||
return longUrl;
|
||||
}
|
||||
|
||||
panel.querySelectorAll("[data-utm-copy-url]").forEach(function (btn) {
|
||||
btn.addEventListener("click", function () {
|
||||
var url = (urlEl && urlEl.textContent) || "";
|
||||
copyText(url).then(
|
||||
function () {
|
||||
flash(statusEl, "Link copied.", "Could not copy.", true);
|
||||
},
|
||||
function () {
|
||||
flash(statusEl, "", "Could not copy link.", false);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
panel.querySelectorAll("[data-utm-copy-qr]").forEach(function (btn) {
|
||||
btn.addEventListener("click", function () {
|
||||
copyCanvas(canvas).then(
|
||||
function () {
|
||||
flash(statusEl, "QR image copied.", "Could not copy QR.", true);
|
||||
},
|
||||
function () {
|
||||
flash(statusEl, "", "Copy failed — use Download PNG.", false);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
panel.querySelectorAll("[data-utm-download-qr]").forEach(function (btn) {
|
||||
btn.addEventListener("click", function () {
|
||||
downloadCanvas(canvas, "qr-" + slug(name()) + ".png");
|
||||
flash(statusEl, "QR downloaded.", "", true);
|
||||
});
|
||||
});
|
||||
|
||||
if (live) {
|
||||
var nameField = document.getElementById("id_name");
|
||||
if (nameField) nameField.addEventListener("input", apply);
|
||||
}
|
||||
|
||||
panel._utmApply = apply;
|
||||
apply();
|
||||
return { apply: apply, buildUrl: buildUrl };
|
||||
}
|
||||
|
||||
global.CampaignUtm = {
|
||||
slug: slug,
|
||||
buildUrl: buildUrl,
|
||||
replaceTextUrl: replaceTextUrl,
|
||||
linkify: linkify,
|
||||
ensureQuillLink: ensureQuillLink,
|
||||
bindPanel: bindPanel,
|
||||
};
|
||||
})(window);
|
||||
@@ -0,0 +1,161 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var NOTICE_KEY = 'aiml_analytics_notice';
|
||||
var LEGACY_CONSENT_KEY = 'aiml_analytics_consent';
|
||||
var LEGACY_DISABLED_KEY = 'tianji.disabled';
|
||||
var configEl = document.getElementById('tianji-config');
|
||||
if (!configEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
var trackerUrl = configEl.dataset.trackerUrl;
|
||||
var websiteId = configEl.dataset.websiteId;
|
||||
var userId = configEl.dataset.userId || '';
|
||||
|
||||
function getStorageItem(key) {
|
||||
try {
|
||||
return localStorage.getItem(key);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function setStorageItem(key, value) {
|
||||
try {
|
||||
localStorage.setItem(key, value);
|
||||
} catch (e) {
|
||||
/* ignore storage errors */
|
||||
}
|
||||
}
|
||||
|
||||
function removeStorageItem(key) {
|
||||
try {
|
||||
localStorage.removeItem(key);
|
||||
} catch (e) {
|
||||
/* ignore storage errors */
|
||||
}
|
||||
}
|
||||
|
||||
function showBanner() {
|
||||
var banner = document.getElementById('cookie-consent-banner');
|
||||
if (banner) {
|
||||
banner.removeAttribute('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
function hideBanner() {
|
||||
var banner = document.getElementById('cookie-consent-banner');
|
||||
if (banner) {
|
||||
banner.setAttribute('hidden', '');
|
||||
}
|
||||
}
|
||||
|
||||
function trackEvent(name, data) {
|
||||
if (window.tianji && typeof window.tianji.track === 'function') {
|
||||
window.tianji.track(name, data || {});
|
||||
}
|
||||
}
|
||||
|
||||
function identifyUser() {
|
||||
if (!userId || !window.tianji || typeof window.tianji.identify !== 'function') {
|
||||
return;
|
||||
}
|
||||
window.tianji.identify({ userId: userId });
|
||||
}
|
||||
|
||||
function loadTracker() {
|
||||
if (document.querySelector('script[data-tianji-loaded="true"]')) {
|
||||
identifyUser();
|
||||
return;
|
||||
}
|
||||
|
||||
var script = document.createElement('script');
|
||||
script.async = true;
|
||||
script.defer = true;
|
||||
script.src = trackerUrl;
|
||||
script.setAttribute('data-website-id', websiteId);
|
||||
script.setAttribute('data-do-not-track', 'true');
|
||||
script.setAttribute('data-tianji-loaded', 'true');
|
||||
|
||||
script.onload = function () {
|
||||
identifyUser();
|
||||
document.dispatchEvent(new CustomEvent('tianji:ready'));
|
||||
};
|
||||
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
function migrateLegacyConsent() {
|
||||
var legacyConsent = getStorageItem(LEGACY_CONSENT_KEY);
|
||||
var legacyDisabled = getStorageItem(LEGACY_DISABLED_KEY);
|
||||
|
||||
if (legacyConsent === 'accepted') {
|
||||
setStorageItem(NOTICE_KEY, 'acknowledged');
|
||||
removeStorageItem(LEGACY_CONSENT_KEY);
|
||||
removeStorageItem(LEGACY_DISABLED_KEY);
|
||||
return 'migrated_acknowledged';
|
||||
}
|
||||
|
||||
if (legacyConsent === 'declined' || legacyDisabled === '1') {
|
||||
removeStorageItem(LEGACY_CONSENT_KEY);
|
||||
removeStorageItem(LEGACY_DISABLED_KEY);
|
||||
return 'migrated_declined';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function acknowledgeNotice() {
|
||||
setStorageItem(NOTICE_KEY, 'acknowledged');
|
||||
hideBanner();
|
||||
window.aimlTrackWhenReady('notice_acknowledged');
|
||||
}
|
||||
|
||||
function bindBannerControls() {
|
||||
var acknowledgeBtn = document.getElementById('cookie-consent-acknowledge');
|
||||
var manageLinks = document.querySelectorAll('[data-open-cookie-preferences]');
|
||||
|
||||
if (acknowledgeBtn) {
|
||||
acknowledgeBtn.addEventListener('click', acknowledgeNotice);
|
||||
}
|
||||
manageLinks.forEach(function (link) {
|
||||
link.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
showBanner();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
window.aimlTrack = function (name, data) {
|
||||
trackEvent(name, data);
|
||||
};
|
||||
|
||||
window.aimlTrackWhenReady = function (name, data) {
|
||||
if (window.tianji && typeof window.tianji.track === 'function') {
|
||||
trackEvent(name, data);
|
||||
return;
|
||||
}
|
||||
document.addEventListener('tianji:ready', function handler() {
|
||||
document.removeEventListener('tianji:ready', handler);
|
||||
trackEvent(name, data);
|
||||
});
|
||||
};
|
||||
|
||||
function initNotice() {
|
||||
bindBannerControls();
|
||||
loadTracker();
|
||||
|
||||
var migration = migrateLegacyConsent();
|
||||
var notice = getStorageItem(NOTICE_KEY);
|
||||
|
||||
if (notice === 'acknowledged' || migration === 'migrated_acknowledged') {
|
||||
hideBanner();
|
||||
return;
|
||||
}
|
||||
|
||||
showBanner();
|
||||
}
|
||||
|
||||
initNotice();
|
||||
})();
|
||||