2980 lines
62 KiB
CSS
2980 lines
62 KiB
CSS
/* =========================================================================
|
||
* Shopify Sync Dashboard — Lime-olive palette
|
||
* primary brand #95BE45 hsl(80, 48%, 51%) — vibrant olive/lime
|
||
* sidebar #6E8E27 → #7DA02C (darker derivatives, keeps white text legible)
|
||
* sidebar active #95BE45 — primary brand pops against the darker sidebar
|
||
* brand #95BE45 — primary buttons, accents, active states
|
||
* brand hover #7CA02E — darker derivative for primary:hover
|
||
* accents blue/yellow/purple/cyan/red for KPI cards
|
||
* fonts Inter, Montserrat
|
||
* ====================================================================== */
|
||
|
||
:host {
|
||
--sidebar-bg: #6E8E27;
|
||
/* matches the SME Settings page sidebar */
|
||
--sidebar-bg-2: #7DA02C;
|
||
/* matches the SME Settings page sidebar gradient bottom */
|
||
--sidebar-active-bg: #95BE45;
|
||
/* PRIMARY BRAND — pops on the darker sidebar */
|
||
--sidebar-text: #ffffff;
|
||
--sidebar-muted: rgba(255, 255, 255, 0.78);
|
||
|
||
--brand-green: #95BE45;
|
||
/* PRIMARY BRAND — buttons, accents, active states */
|
||
--brand-green-dark: #7CA02E;
|
||
/* darker derivative for primary:hover */
|
||
--brand-gradient: linear-gradient(125deg, #5fa832 0%, #3f9a86 55%, #2f8fb0 100%);
|
||
/* Accent gradient used in place of solid green for backgrounds */
|
||
--brand-gradient-solid: #3f9a86;
|
||
/* Flat fallback for text-color/border-color spots where a gradient value isn't valid CSS */
|
||
--shopify-green: #95BF47;
|
||
/* Shopify brand — DO NOT change */
|
||
--salesforce-blue: #00A1E0;
|
||
/* Salesforce brand — DO NOT change */
|
||
|
||
--page-bg: #f4f4f2;
|
||
--card-bg: #ffffff;
|
||
--card-bg-2: #fbfbfa;
|
||
|
||
--text-1: #1f2937;
|
||
--text-2: #4b5563;
|
||
--text-3: #9ca3af;
|
||
|
||
--border: #e5e7eb;
|
||
--border-strong: #d1d5db;
|
||
--row-hover: #f6f7f5;
|
||
|
||
--kpi-blue: #3b7ec4;
|
||
--kpi-green: #7CA02E;
|
||
--kpi-yellow: #b8932f;
|
||
--kpi-purple: #7c5cbf;
|
||
--kpi-cyan: #2f8f7f;
|
||
--kpi-red: #c14f4f;
|
||
|
||
--up-color: #16a34a;
|
||
--down-color: #dc2626;
|
||
--shadow: 0 1px 2px rgba(16, 24, 40, 0.06), 0 1px 3px rgba(16, 24, 40, 0.04);
|
||
--scrollbar-track: #edf2e8;
|
||
--scrollbar-thumb: #a2a2a2;
|
||
--scrollbar-thumb-hover: #a2a2a2;
|
||
--sidebar-scrollbar-track: rgba(255, 255, 255, 0.10);
|
||
--sidebar-scrollbar-thumb: rgba(255, 255, 255, 0.36);
|
||
--sidebar-scrollbar-thumb-hover: rgba(255, 255, 255, 0.56);
|
||
|
||
display: block;
|
||
background: var(--page-bg);
|
||
color: var(--text-1);
|
||
font-family: 'Inter', 'Montserrat', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
|
||
font-size: 13px;
|
||
}
|
||
|
||
/* ---- DARK THEME (tuned for contrast + brand visibility) ---- */
|
||
.app.dark {
|
||
--sidebar-bg: #4F671C;
|
||
/* darker olive base for dark mode */
|
||
--sidebar-bg-2: #3A4C14;
|
||
/* even darker gradient bottom */
|
||
--sidebar-active-bg: #95BE45;
|
||
/* brand pops brightly against dark olive */
|
||
--sidebar-text: #f0f3eb;
|
||
--sidebar-muted: rgba(240, 243, 235, 0.7);
|
||
|
||
--page-bg: #14191b;
|
||
--card-bg: #1c2226;
|
||
--card-bg-2: #232a2e;
|
||
|
||
--text-1: #f0f3eb;
|
||
--text-2: #d4d8ce;
|
||
--text-3: #9aa295;
|
||
|
||
--border: #2d343a;
|
||
--border-strong: #3d454c;
|
||
--row-hover: #232a2e;
|
||
|
||
--shadow: 0 1px 2px rgba(0, 0, 0, 0.45), 0 1px 3px rgba(0, 0, 0, 0.35);
|
||
--scrollbar-track: #111719;
|
||
--scrollbar-thumb: #a2a2a2;
|
||
--scrollbar-thumb-hover: #a2a2a2;
|
||
--sidebar-scrollbar-track: rgba(255, 255, 255, 0.08);
|
||
--sidebar-scrollbar-thumb: rgba(255, 255, 255, 0.30);
|
||
--sidebar-scrollbar-thumb-hover: rgba(255, 255, 255, 0.48);
|
||
}
|
||
|
||
/* Dark mode overrides for SVG elements that use hardcoded presentation attributes */
|
||
.app.dark .svg-line text,
|
||
.app.dark .svg-bar text {
|
||
fill: var(--text-2);
|
||
}
|
||
|
||
.app.dark .record-detail-id-row .record-detail-label,
|
||
.app.dark .record-detail-field .record-detail-label,
|
||
.app.dark .record-detail-id-row .record-detail-value,
|
||
.app.dark .record-detail-field .record-detail-value {
|
||
color: #ffffff !important;
|
||
}
|
||
|
||
|
||
.app.dark .svg-line line,
|
||
.app.dark .svg-bar line {
|
||
stroke: var(--border-strong);
|
||
}
|
||
|
||
.app.dark .svg-donut circle:first-child {
|
||
stroke: var(--border-strong);
|
||
}
|
||
|
||
/* ============== Theme-aware scrollbars ============== */
|
||
.main,
|
||
.store-menu,
|
||
.field-list,
|
||
.kpi-row,
|
||
.dash-row,
|
||
.table-scroll,
|
||
.record-detail-body,
|
||
.modal-card.schedule-card,
|
||
.menu.sort-menu,
|
||
.menu.filter-menu {
|
||
scrollbar-width: thin;
|
||
scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
|
||
}
|
||
|
||
.obj-list,
|
||
.sync-health-stores {
|
||
scrollbar-width: thin;
|
||
scrollbar-color: var(--sidebar-scrollbar-thumb) var(--sidebar-scrollbar-track);
|
||
}
|
||
|
||
.main::-webkit-scrollbar,
|
||
.store-menu::-webkit-scrollbar,
|
||
.field-list::-webkit-scrollbar,
|
||
.kpi-row::-webkit-scrollbar,
|
||
.dash-row::-webkit-scrollbar,
|
||
.table-scroll::-webkit-scrollbar,
|
||
.record-detail-body::-webkit-scrollbar,
|
||
.modal-card.schedule-card::-webkit-scrollbar,
|
||
.menu.sort-menu::-webkit-scrollbar,
|
||
.menu.filter-menu::-webkit-scrollbar {
|
||
width: 10px;
|
||
height: 10px;
|
||
}
|
||
|
||
.main::-webkit-scrollbar-track,
|
||
.store-menu::-webkit-scrollbar-track,
|
||
.field-list::-webkit-scrollbar-track,
|
||
.kpi-row::-webkit-scrollbar-track,
|
||
.dash-row::-webkit-scrollbar-track,
|
||
.table-scroll::-webkit-scrollbar-track,
|
||
.record-detail-body::-webkit-scrollbar-track,
|
||
.modal-card.schedule-card::-webkit-scrollbar-track,
|
||
.menu.sort-menu::-webkit-scrollbar-track,
|
||
.menu.filter-menu::-webkit-scrollbar-track {
|
||
background: var(--scrollbar-track);
|
||
border-radius: 999px;
|
||
}
|
||
|
||
.main::-webkit-scrollbar-thumb,
|
||
.store-menu::-webkit-scrollbar-thumb,
|
||
.field-list::-webkit-scrollbar-thumb,
|
||
.kpi-row::-webkit-scrollbar-thumb,
|
||
.dash-row::-webkit-scrollbar-thumb,
|
||
.table-scroll::-webkit-scrollbar-thumb,
|
||
.record-detail-body::-webkit-scrollbar-thumb,
|
||
.modal-card.schedule-card::-webkit-scrollbar-thumb,
|
||
.menu.sort-menu::-webkit-scrollbar-thumb,
|
||
.menu.filter-menu::-webkit-scrollbar-thumb {
|
||
background-color: var(--scrollbar-thumb);
|
||
border: 2px solid var(--scrollbar-track);
|
||
border-radius: 999px;
|
||
}
|
||
|
||
.main::-webkit-scrollbar-thumb:hover,
|
||
.store-menu::-webkit-scrollbar-thumb:hover,
|
||
.field-list::-webkit-scrollbar-thumb:hover,
|
||
.kpi-row::-webkit-scrollbar-thumb:hover,
|
||
.dash-row::-webkit-scrollbar-thumb:hover,
|
||
.table-scroll::-webkit-scrollbar-thumb:hover,
|
||
.record-detail-body::-webkit-scrollbar-thumb:hover,
|
||
.modal-card.schedule-card::-webkit-scrollbar-thumb:hover,
|
||
.menu.sort-menu::-webkit-scrollbar-thumb:hover,
|
||
.menu.filter-menu::-webkit-scrollbar-thumb:hover {
|
||
background-color: var(--scrollbar-thumb-hover);
|
||
}
|
||
|
||
.obj-list::-webkit-scrollbar,
|
||
.sync-health-stores::-webkit-scrollbar {
|
||
width: 8px;
|
||
}
|
||
|
||
.obj-list::-webkit-scrollbar-track,
|
||
.sync-health-stores::-webkit-scrollbar-track {
|
||
background: var(--sidebar-scrollbar-track);
|
||
border-radius: 999px;
|
||
}
|
||
|
||
.obj-list::-webkit-scrollbar-thumb,
|
||
.sync-health-stores::-webkit-scrollbar-thumb {
|
||
background-color: var(--sidebar-scrollbar-thumb);
|
||
border: 2px solid transparent;
|
||
background-clip: padding-box;
|
||
border-radius: 999px;
|
||
}
|
||
|
||
.obj-list::-webkit-scrollbar-thumb:hover,
|
||
.sync-health-stores::-webkit-scrollbar-thumb:hover {
|
||
background-color: var(--sidebar-scrollbar-thumb-hover);
|
||
}
|
||
|
||
/* ============== Toasts ============== */
|
||
.toast-container {
|
||
position: fixed;
|
||
top: 16px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
z-index: 2000;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 10px;
|
||
width: 100%;
|
||
max-width: 360px;
|
||
}
|
||
|
||
.toast {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
gap: 10px;
|
||
padding: 12px 14px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);
|
||
color: #fff;
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
animation: toast-in 180ms ease;
|
||
}
|
||
|
||
@keyframes toast-in {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateY(-10px);
|
||
}
|
||
|
||
to {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
.toast-icon {
|
||
flex-shrink: 0;
|
||
font-size: 14px;
|
||
line-height: 1.3;
|
||
}
|
||
|
||
.toast-body {
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
|
||
.toast-title {
|
||
font-weight: 700;
|
||
font-size: 12.5px;
|
||
line-height: 1.3;
|
||
}
|
||
|
||
.toast-message {
|
||
font-size: 12px;
|
||
line-height: 1.35;
|
||
opacity: 0.95;
|
||
margin-top: 2px;
|
||
word-break: break-word;
|
||
}
|
||
|
||
.toast-close {
|
||
flex-shrink: 0;
|
||
background: transparent;
|
||
border: none;
|
||
color: inherit;
|
||
opacity: 0.8;
|
||
cursor: pointer;
|
||
font-size: 16px;
|
||
line-height: 1;
|
||
padding: 0;
|
||
}
|
||
|
||
.toast-close:hover {
|
||
opacity: 1;
|
||
}
|
||
|
||
.toast-success {
|
||
background: var(--brand-gradient);
|
||
}
|
||
|
||
.toast-error {
|
||
background: #dc2626;
|
||
}
|
||
|
||
.toast-warning {
|
||
background: #f59e0b;
|
||
color: #1f2937;
|
||
}
|
||
|
||
.toast-info {
|
||
background: #3b7ec4;
|
||
}
|
||
|
||
/* ============== Layout ============== */
|
||
.app {
|
||
display: grid;
|
||
grid-template-columns: 250px 1fr;
|
||
/* Pin to the viewport and scroll .main internally — at 100% zoom the
|
||
content used to extend past the visible area with no scrollbar. */
|
||
height: 100vh;
|
||
max-height: 100vh;
|
||
min-height: 0;
|
||
overflow: hidden;
|
||
background: var(--page-bg);
|
||
transition: background 200ms ease;
|
||
}
|
||
|
||
/* When any modal is open, lock the dashboard's overflow so the underlying
|
||
content doesn't scroll behind the backdrop. */
|
||
.app.modal-open {
|
||
height: 100vh;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.app.modal-open .main {
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* ============== Refresh banner ============== */
|
||
.refresh-banner {
|
||
grid-column: 1 / -1;
|
||
background: var(--brand-gradient);
|
||
color: #fff;
|
||
padding: 10px 18px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
font-size: 12.5px;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.refresh-banner.blinking .dot-blink {
|
||
animation: blink 0.9s ease-in-out infinite;
|
||
}
|
||
|
||
.refresh-banner.done {
|
||
background: var(--brand-gradient);
|
||
}
|
||
|
||
.dot-blink {
|
||
width: 10px;
|
||
height: 10px;
|
||
border-radius: 50%;
|
||
background: #fff;
|
||
}
|
||
|
||
@keyframes blink {
|
||
|
||
0%,
|
||
100% {
|
||
opacity: 1;
|
||
}
|
||
|
||
50% {
|
||
opacity: 0.25;
|
||
}
|
||
}
|
||
|
||
.banner-text {
|
||
flex: 0 0 auto;
|
||
}
|
||
|
||
.banner-progress-track {
|
||
flex: 1;
|
||
height: 4px;
|
||
background: rgba(255, 255, 255, 0.25);
|
||
border-radius: 2px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.banner-progress-bar {
|
||
height: 100%;
|
||
background: #fff;
|
||
transition: width 200ms ease;
|
||
}
|
||
|
||
/* ============== Sidebar ============== */
|
||
.sidebar {
|
||
background: var(--brand-gradient);
|
||
color: var(--sidebar-text);
|
||
padding: 16px 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
min-height: 0;
|
||
/* .obj-list scrolls internally within the fixed sidebar */
|
||
overflow: hidden;
|
||
}
|
||
|
||
.brand {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
padding: 4px 12px 16px;
|
||
}
|
||
|
||
.brand-logo {
|
||
width: 38px;
|
||
height: 38px;
|
||
display: grid;
|
||
place-items: center;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.brand-logo-img {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: contain;
|
||
display: block;
|
||
}
|
||
|
||
.brand-text {
|
||
min-width: 0;
|
||
flex: 1;
|
||
}
|
||
|
||
.brand-text .t1 {
|
||
font-size: 18px;
|
||
font-weight: 700;
|
||
line-height: 1.1;
|
||
letter-spacing: -0.2px;
|
||
}
|
||
|
||
.brand-text .t1 .italic {
|
||
font-style: italic;
|
||
font-weight: 500;
|
||
opacity: 0.92;
|
||
}
|
||
|
||
.brand-text .t2 {
|
||
font-size: 8.5px;
|
||
opacity: 0.88;
|
||
letter-spacing: -0.1px;
|
||
margin-top: 3px;
|
||
line-height: 1.2;
|
||
display: flex;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.store-selector {
|
||
position: relative;
|
||
margin: 0 12px 14px;
|
||
padding: 10px 12px;
|
||
background: rgba(255, 255, 255, 0.10);
|
||
border-radius: 8px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.store-selector .store-icon {
|
||
width: 30px;
|
||
height: 30px;
|
||
border-radius: 6px;
|
||
background: rgba(255, 255, 255, 0.18);
|
||
display: grid;
|
||
place-items: center;
|
||
color: var(--sidebar-text);
|
||
}
|
||
|
||
.store-selector .meta {
|
||
min-width: 0;
|
||
line-height: 1.2;
|
||
}
|
||
|
||
.store-selector .meta .l1 {
|
||
font-weight: 600;
|
||
font-size: 13px;
|
||
}
|
||
|
||
.store-selector .meta .l2 {
|
||
font-size: 10.5px;
|
||
opacity: 0.85;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
max-width: 180px;
|
||
}
|
||
|
||
.store-selector .caret {
|
||
margin-left: auto;
|
||
opacity: 0.8;
|
||
}
|
||
|
||
.store-menu {
|
||
position: absolute;
|
||
top: calc(100% + 6px);
|
||
left: 0;
|
||
right: 0;
|
||
background: var(--card-bg);
|
||
color: var(--text-1);
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
box-shadow: var(--shadow);
|
||
padding: 6px;
|
||
z-index: 50;
|
||
display: none;
|
||
max-height: 260px;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.store-menu.open {
|
||
display: block;
|
||
}
|
||
|
||
.store-menu-row {
|
||
display: grid;
|
||
grid-template-columns: 8px 1fr auto;
|
||
gap: 8px;
|
||
padding: 8px 10px;
|
||
border-radius: 6px;
|
||
align-items: center;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.store-menu-row:hover {
|
||
background: var(--row-hover);
|
||
}
|
||
|
||
.store-menu-row.selected {
|
||
background: rgba(47, 158, 68, 0.10);
|
||
}
|
||
|
||
.store-menu-row .store-dot {
|
||
width: 8px;
|
||
height: 8px;
|
||
border-radius: 50%;
|
||
background: var(--brand-gradient);
|
||
}
|
||
|
||
.store-menu-row .store-name {
|
||
font-weight: 600;
|
||
font-size: 12.5px;
|
||
}
|
||
|
||
.store-menu-row .store-domain {
|
||
font-size: 11px;
|
||
color: var(--text-3);
|
||
}
|
||
|
||
.store-menu-row .store-status {
|
||
color: var(--brand-gradient-solid);
|
||
font-size: 12px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.nav-label {
|
||
font-size: 10.5px;
|
||
letter-spacing: 1px;
|
||
opacity: 0.75;
|
||
padding: 8px 16px 6px;
|
||
}
|
||
|
||
.obj-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 2px;
|
||
padding: 0 8px;
|
||
overflow-y: auto;
|
||
flex: 1 1 auto;
|
||
min-height: 0;
|
||
/* required for flex:1 + overflow:auto to behave correctly */
|
||
}
|
||
|
||
.obj-item {
|
||
position: relative;
|
||
display: grid;
|
||
grid-template-columns: minmax(0, 1fr) auto;
|
||
align-items: center;
|
||
gap: 4px;
|
||
padding: 8px 10px;
|
||
border-radius: 8px;
|
||
cursor: pointer;
|
||
color: var(--sidebar-text);
|
||
/* Subtle card style so each row reads as a distinct box */
|
||
background: rgba(255, 255, 255, 0.07);
|
||
border: 1px solid rgba(255, 255, 255, 0.10);
|
||
transition: background 100ms ease, border-color 100ms ease;
|
||
}
|
||
|
||
.obj-item:hover {
|
||
background: rgba(255, 255, 255, 0.14);
|
||
border-color: rgba(255, 255, 255, 0.22);
|
||
}
|
||
|
||
.obj-item.active {
|
||
background: var(--brand-gradient);
|
||
color: var(--sidebar-text);
|
||
border-color: rgba(255, 255, 255, 0.32);
|
||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
|
||
}
|
||
|
||
.obj-item.active::before {
|
||
content: "";
|
||
position: absolute;
|
||
left: -8px;
|
||
top: 6px;
|
||
bottom: 6px;
|
||
width: 3px;
|
||
border-radius: 3px;
|
||
background: #fff;
|
||
}
|
||
|
||
.obj-text {
|
||
min-width: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
}
|
||
|
||
.obj-icon {
|
||
flex-shrink: 0;
|
||
display: inline-grid;
|
||
place-items: center;
|
||
width: 18px;
|
||
height: 18px;
|
||
--sds-c-icon-color-foreground-default: var(--sidebar-text);
|
||
--sds-c-icon-color-foreground: var(--sidebar-text);
|
||
}
|
||
|
||
.obj-name {
|
||
font-weight: 600;
|
||
font-size: 13px;
|
||
line-height: 1.2;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
min-width: 0;
|
||
}
|
||
|
||
/* Counts — two pills stacked vertically. Each pill: [logo + name stack] [count].
|
||
Sizes tuned for visual balance with the object icon + name on the left side. */
|
||
.counts {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 5px;
|
||
align-items: stretch;
|
||
color: var(--sidebar-text);
|
||
}
|
||
|
||
.count-pill {
|
||
display: grid;
|
||
grid-template-columns: 42px auto;
|
||
/* narrower logo-stack column */
|
||
align-items: center;
|
||
gap: 6px;
|
||
/* tighter logo→count gap */
|
||
padding: 0;
|
||
background: transparent;
|
||
border: none;
|
||
border-radius: 0;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
|
||
.obj-item.active .count-pill {
|
||
background: transparent;
|
||
color: var(--sidebar-text);
|
||
}
|
||
|
||
.logo-stack {
|
||
display: inline-flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 2px;
|
||
line-height: 1;
|
||
}
|
||
|
||
.logo {
|
||
display: inline-grid;
|
||
place-items: center;
|
||
width: 18px;
|
||
height: 18px;
|
||
background: transparent;
|
||
border-radius: 0;
|
||
}
|
||
|
||
.logo svg {
|
||
width: 18px;
|
||
height: 18px;
|
||
}
|
||
|
||
.logo-name {
|
||
font-size: 8.5px;
|
||
font-weight: 500;
|
||
letter-spacing: 0.1px;
|
||
opacity: 0.9;
|
||
line-height: 1.1;
|
||
text-transform: none;
|
||
}
|
||
|
||
.count-val {
|
||
font-weight: 700;
|
||
font-size: 15px;
|
||
line-height: 1;
|
||
text-align: right;
|
||
font-family: 'Inter', 'Segoe UI', system-ui, sans-serif;
|
||
letter-spacing: -0.2px;
|
||
min-width: 32px;
|
||
/* room for 4-5 digit counts */
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* Shopify logo brand color #95BF47 visually collides with the active row
|
||
background #95BE45 (basically the same green) — switch the SVG fill to
|
||
white when the row is active so the logo stays recognizable.
|
||
CSS `fill` overrides the inline `fill` attribute on the SVG path. */
|
||
.obj-item.active .logo-shopify svg path {
|
||
fill: #ffffff;
|
||
}
|
||
|
||
/* ---- Sync Health panel (sidebar between object list and footer) ---- */
|
||
.sync-health {
|
||
margin: 12px 12px 0;
|
||
padding: 10px 12px;
|
||
background: rgba(255, 255, 255, 0.08);
|
||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||
border-radius: 8px;
|
||
color: var(--sidebar-text);
|
||
font-size: 11px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
}
|
||
|
||
.sync-health-title {
|
||
font-size: 9.5px;
|
||
font-weight: 700;
|
||
letter-spacing: 1px;
|
||
opacity: 0.6;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
/* Stores list — show 2 at a time, then scroll. Each store row is
|
||
~31px (label row + last-order subtitle) plus ~14px separator/gap between
|
||
rows, so 2 rows ≈ 80px. */
|
||
.sync-health-stores {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
max-height: 80px;
|
||
overflow-y: auto;
|
||
padding-right: 2px;
|
||
}
|
||
|
||
.sync-health-store {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 2px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.sync-health-store+.sync-health-store {
|
||
padding-top: 6px;
|
||
border-top: 1px solid rgba(255, 255, 255, 0.08);
|
||
}
|
||
|
||
.sync-health-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
line-height: 1.3;
|
||
}
|
||
|
||
.sync-health-label {
|
||
flex: 1;
|
||
font-weight: 600;
|
||
font-size: 11.5px;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
min-width: 0;
|
||
}
|
||
|
||
.sync-health-value {
|
||
font-weight: 600;
|
||
font-size: 10.5px;
|
||
opacity: 0.92;
|
||
}
|
||
|
||
.sync-health-last {
|
||
padding-left: 14px;
|
||
font-size: 9.5px;
|
||
opacity: 0.65;
|
||
letter-spacing: 0.1px;
|
||
line-height: 1.3;
|
||
}
|
||
|
||
.health-dot {
|
||
flex-shrink: 0;
|
||
width: 8px;
|
||
height: 8px;
|
||
border-radius: 50%;
|
||
}
|
||
|
||
.health-dot.health-ok {
|
||
background: #4ade80;
|
||
box-shadow: 0 0 0 2px rgba(74, 222, 128, 0.25);
|
||
}
|
||
|
||
.health-dot.health-err {
|
||
background: #ef4444;
|
||
box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.25);
|
||
}
|
||
|
||
.sidebar-footer {
|
||
margin-top: 10px;
|
||
padding: 12px 14px;
|
||
text-align: center;
|
||
font-size: 10px;
|
||
line-height: 1.4;
|
||
color: rgba(255, 255, 255, 0.78);
|
||
border-top: 1px solid rgba(255, 255, 255, 0.08);
|
||
letter-spacing: 0.1px;
|
||
}
|
||
|
||
.sidebar-footer a {
|
||
color: rgba(255, 255, 255, 0.95);
|
||
text-decoration: none;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.sidebar-footer a:hover {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.footer-heart {
|
||
color: #ef4444;
|
||
font-size: 11px;
|
||
vertical-align: -1px;
|
||
margin: 0 1px;
|
||
}
|
||
|
||
/* ============== Main column ============== */
|
||
.main {
|
||
display: flex;
|
||
flex-direction: column;
|
||
min-width: 0;
|
||
min-height: 0;
|
||
overflow-y: auto;
|
||
/* internal scroll — the whole page is now reachable */
|
||
}
|
||
|
||
.topbar {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
padding: 10px 16px;
|
||
background: var(--card-bg);
|
||
border-bottom: 1px solid var(--border);
|
||
flex-wrap: wrap;
|
||
row-gap: 8px;
|
||
}
|
||
|
||
.topbar-filters {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
flex-wrap: wrap;
|
||
min-width: 0;
|
||
flex: 1 1 auto;
|
||
}
|
||
|
||
.topbar-actions {
|
||
margin-left: auto;
|
||
display: flex;
|
||
gap: 6px;
|
||
align-items: center;
|
||
flex: 0 0 auto;
|
||
}
|
||
|
||
/* Force Refresh — subtle amber warning style so it reads as "use when needed" */
|
||
.btn.btn-force {
|
||
background: #fff8eb;
|
||
border-color: #f59e0b;
|
||
color: #b45309;
|
||
}
|
||
|
||
.btn.btn-force:hover {
|
||
background: #fef3c7;
|
||
border-color: #d97706;
|
||
color: #92400e;
|
||
}
|
||
|
||
.app.dark .btn.btn-force {
|
||
background: rgba(245, 158, 11, 0.15);
|
||
border-color: #b45309;
|
||
color: #fbbf24;
|
||
}
|
||
|
||
.btn {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
padding: 6px 10px;
|
||
border-radius: 6px;
|
||
border: 1px solid var(--border-strong);
|
||
background: var(--card-bg);
|
||
color: var(--text-1);
|
||
font-size: 12px;
|
||
cursor: pointer;
|
||
font-weight: 500;
|
||
font-family: inherit;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.btn:hover {
|
||
background: var(--row-hover);
|
||
}
|
||
|
||
.btn.primary {
|
||
background: var(--brand-gradient);
|
||
border-color: var(--brand-gradient-solid);
|
||
color: #fff;
|
||
}
|
||
|
||
.btn.primary:hover {
|
||
background: var(--brand-gradient);
|
||
border-color: var(--brand-gradient-solid);
|
||
}
|
||
|
||
.btn.small {
|
||
padding: 5px 10px;
|
||
font-size: 11.5px;
|
||
}
|
||
|
||
.icon-btn {
|
||
width: 30px;
|
||
height: 30px;
|
||
border-radius: 6px;
|
||
border: 1px solid var(--border-strong);
|
||
background: var(--card-bg);
|
||
color: var(--text-1);
|
||
cursor: pointer;
|
||
display: grid;
|
||
place-items: center;
|
||
}
|
||
|
||
.icon-btn:hover {
|
||
background: var(--row-hover);
|
||
}
|
||
|
||
.theme-icon {
|
||
font-size: 16px;
|
||
line-height: 1;
|
||
}
|
||
|
||
.menu-wrap {
|
||
position: relative;
|
||
}
|
||
|
||
.menu {
|
||
position: absolute;
|
||
top: calc(100% + 6px);
|
||
right: 0;
|
||
min-width: 200px;
|
||
background: var(--card-bg);
|
||
color: var(--text-1);
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
box-shadow: var(--shadow);
|
||
padding: 6px;
|
||
z-index: 100;
|
||
display: none;
|
||
}
|
||
|
||
.menu.open {
|
||
display: block;
|
||
}
|
||
|
||
.menu-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
padding: 8px 10px;
|
||
border-radius: 6px;
|
||
font-size: 12.5px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.menu-item:hover {
|
||
background: var(--row-hover);
|
||
}
|
||
|
||
.menu-icon {
|
||
width: 18px;
|
||
display: inline-grid;
|
||
place-items: center;
|
||
}
|
||
|
||
.menu-sep {
|
||
height: 1px;
|
||
background: var(--border);
|
||
margin: 4px 0;
|
||
}
|
||
|
||
.menu-title {
|
||
padding: 8px 10px 4px;
|
||
font-size: 11px;
|
||
letter-spacing: 0.8px;
|
||
color: var(--text-1);
|
||
font-weight: 800;
|
||
text-transform: uppercase;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
/* Field selector menu */
|
||
.field-menu {
|
||
position: absolute;
|
||
top: calc(100% + 6px);
|
||
right: 0;
|
||
width: 380px;
|
||
/* Triple-cap so the dropdown stays inside typical LWC card bounds:
|
||
1) hard ceiling 320px so it doesn't dwarf the card
|
||
2) 50vh so it never takes more than half the viewport
|
||
3) viewport - 200px to leave headroom for topbar + footer */
|
||
max-height: min(320px, 50vh, calc(100vh - 200px));
|
||
background: var(--card-bg);
|
||
color: var(--text-1);
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
box-shadow: var(--shadow);
|
||
padding: 6px;
|
||
z-index: 100;
|
||
display: none;
|
||
/* Flex column lets the title + search pin to the top while only the
|
||
.field-list region inside scrolls. */
|
||
flex-direction: column;
|
||
min-height: 0;
|
||
}
|
||
|
||
.field-menu.open {
|
||
display: flex;
|
||
}
|
||
|
||
.field-search {
|
||
padding: 6px 8px 4px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.field-search input {
|
||
width: 100%;
|
||
padding: 6px 10px;
|
||
border: 1px solid var(--border-strong);
|
||
border-radius: 6px;
|
||
background: var(--card-bg);
|
||
color: var(--text-1);
|
||
font-size: 12.5px;
|
||
font-family: inherit;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.field-search input:focus {
|
||
outline: none;
|
||
border-color: var(--brand-gradient-solid);
|
||
}
|
||
|
||
.field-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 2px;
|
||
/* Only this region scrolls — title + search stay pinned above */
|
||
flex: 1 1 auto;
|
||
min-height: 0;
|
||
overflow-y: auto;
|
||
padding-right: 2px;
|
||
/* small gap so scrollbar doesn't crowd content */
|
||
margin-top: 4px;
|
||
}
|
||
|
||
.field-row {
|
||
display: grid;
|
||
grid-template-columns: 22px 1fr auto;
|
||
gap: 8px;
|
||
padding: 6px 10px;
|
||
border-radius: 6px;
|
||
align-items: center;
|
||
user-select: none;
|
||
}
|
||
|
||
.field-row:hover {
|
||
background: var(--row-hover);
|
||
}
|
||
|
||
.field-row .check-box {
|
||
width: 18px;
|
||
height: 18px;
|
||
border-radius: 4px;
|
||
border: 1.5px solid var(--border-strong);
|
||
display: grid;
|
||
place-items: center;
|
||
font-size: 12px;
|
||
color: #fff;
|
||
background: var(--card-bg);
|
||
cursor: pointer;
|
||
}
|
||
|
||
.field-row.on .check-box {
|
||
background: var(--brand-gradient);
|
||
border-color: var(--brand-gradient-solid);
|
||
}
|
||
|
||
.field-meta {
|
||
min-width: 0;
|
||
line-height: 1.2;
|
||
}
|
||
|
||
.field-row .field-name {
|
||
font-weight: 600;
|
||
font-size: 12.5px;
|
||
}
|
||
|
||
.field-row .field-api {
|
||
font-size: 10.5px;
|
||
color: var(--text-3);
|
||
font-family: ui-monospace, monospace;
|
||
}
|
||
|
||
.field-reorder {
|
||
display: inline-flex;
|
||
flex-direction: column;
|
||
gap: 2px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.reorder-btn {
|
||
width: 24px;
|
||
height: 20px;
|
||
border: 1px solid var(--border-strong);
|
||
background: var(--card-bg);
|
||
color: var(--text-2);
|
||
font-size: 11px;
|
||
line-height: 1;
|
||
cursor: pointer;
|
||
border-radius: 4px;
|
||
padding: 0;
|
||
display: inline-grid;
|
||
place-items: center;
|
||
transition: background 100ms ease, color 100ms ease, border-color 100ms ease;
|
||
}
|
||
|
||
.reorder-btn:hover:not([disabled]) {
|
||
background: rgba(47, 158, 68, 0.08);
|
||
color: var(--brand-gradient-solid);
|
||
border-color: var(--brand-gradient-solid);
|
||
}
|
||
|
||
.reorder-btn[disabled] {
|
||
opacity: 0.3;
|
||
cursor: not-allowed;
|
||
}
|
||
|
||
/* ============== Filter bar (legacy — kept selector, no longer rendered) ============== */
|
||
.filterbar {
|
||
display: none;
|
||
}
|
||
|
||
.filter-label {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
color: var(--text-2);
|
||
padding-right: 10px;
|
||
margin-right: 4px;
|
||
border-right: 1px solid var(--border);
|
||
white-space: nowrap;
|
||
line-height: 1;
|
||
}
|
||
|
||
.filter-funnel {
|
||
color: var(--brand-gradient-solid);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.filter-label-text {
|
||
letter-spacing: 0.2px;
|
||
}
|
||
|
||
.select {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
padding: 5px 9px;
|
||
border: 1px solid var(--border-strong);
|
||
border-radius: 6px;
|
||
background: var(--card-bg);
|
||
font-size: 12px;
|
||
cursor: pointer;
|
||
min-width: 100px;
|
||
justify-content: space-between;
|
||
color: var(--text-1);
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.select>span:first-child {
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
max-width: 130px;
|
||
}
|
||
|
||
.select .caret {
|
||
color: var(--text-3);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
/* sort-by no longer needs auto margin — placement is controlled by topbar-filters flex order */
|
||
.sort-by {
|
||
min-width: 110px;
|
||
}
|
||
|
||
/* ============== Content ============== */
|
||
.content {
|
||
padding: 18px 24px 24px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 18px;
|
||
flex: 1;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 13.5px;
|
||
font-weight: 700;
|
||
color: var(--text-1);
|
||
text-transform: uppercase;
|
||
letter-spacing: 1px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
}
|
||
|
||
.section-title .muted-tag {
|
||
font-weight: 500;
|
||
text-transform: none;
|
||
letter-spacing: 0;
|
||
font-size: 11px;
|
||
color: var(--text-3);
|
||
background: var(--card-bg-2);
|
||
border: 1px solid var(--border);
|
||
padding: 2px 8px;
|
||
border-radius: 999px;
|
||
font-family: ui-monospace, monospace;
|
||
}
|
||
|
||
.report-title-row .report-actions {
|
||
margin-left: auto;
|
||
}
|
||
|
||
/* ============== KPI Cards ============== */
|
||
/* 8 KPIs ALWAYS in a single row at every screen size.
|
||
minmax(0, 1fr) lets cards shrink rather than wrap; overflow-x scroll
|
||
kicks in only if the viewport is truly too narrow to fit all 8. */
|
||
.kpi-row {
|
||
display: grid;
|
||
grid-template-columns: repeat(8, minmax(0, 1fr));
|
||
gap: 8px;
|
||
overflow-x: auto;
|
||
padding-bottom: 4px;
|
||
/* room for the horizontal scrollbar without clipping shadows */
|
||
}
|
||
|
||
.kpi {
|
||
background: var(--card-bg);
|
||
border: 1px solid var(--border);
|
||
border-radius: 10px;
|
||
padding: 10px 12px 12px;
|
||
position: relative;
|
||
box-shadow: var(--shadow);
|
||
overflow: hidden;
|
||
min-width: 0;
|
||
}
|
||
|
||
.kpi::before {
|
||
content: "";
|
||
position: absolute;
|
||
left: 0;
|
||
right: 0;
|
||
top: 0;
|
||
height: 3px;
|
||
background: var(--accent, var(--kpi-blue));
|
||
}
|
||
|
||
.kpi.k-blue {
|
||
--accent: var(--kpi-blue);
|
||
}
|
||
|
||
.kpi.k-green {
|
||
--accent: var(--brand-gradient);
|
||
}
|
||
|
||
.kpi.k-yellow {
|
||
--accent: var(--kpi-yellow);
|
||
}
|
||
|
||
.kpi.k-purple {
|
||
--accent: var(--kpi-purple);
|
||
}
|
||
|
||
.kpi.k-cyan {
|
||
--accent: var(--kpi-cyan);
|
||
}
|
||
|
||
.kpi.k-red {
|
||
--accent: var(--kpi-red);
|
||
}
|
||
|
||
.kpi .label {
|
||
font-size: 9px;
|
||
letter-spacing: 0.6px;
|
||
color: var(--text-3);
|
||
font-weight: 600;
|
||
text-transform: uppercase;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.kpi .value {
|
||
font-size: 18px;
|
||
font-weight: 700;
|
||
margin-top: 4px;
|
||
color: var(--text-1);
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
line-height: 1.15;
|
||
}
|
||
|
||
.kpi .sub {
|
||
font-size: 10px;
|
||
color: var(--text-3);
|
||
margin-top: 2px;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.kpi .delta {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 3px;
|
||
margin-top: 6px;
|
||
font-size: 10.5px;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.kpi .delta.up {
|
||
color: var(--up-color);
|
||
}
|
||
|
||
.kpi .delta.down {
|
||
color: var(--down-color);
|
||
}
|
||
|
||
/* ============== Panels / Dashboards ============== */
|
||
.panel {
|
||
background: var(--card-bg);
|
||
border: 1px solid var(--border);
|
||
border-radius: 10px;
|
||
box-shadow: var(--shadow);
|
||
display: flex;
|
||
flex-direction: column;
|
||
min-width: 0;
|
||
}
|
||
|
||
/* Dashboard panels specifically — hide overflow so chart legends/labels
|
||
never escape the card. Report panel is separately allowed to scroll
|
||
its table horizontally via .table-scroll. */
|
||
.dash-panel {
|
||
overflow: hidden;
|
||
}
|
||
|
||
.panel-head {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 14px 16px 10px;
|
||
gap: 10px;
|
||
}
|
||
|
||
.panel-head .title {
|
||
font-size: 13.5px;
|
||
font-weight: 600;
|
||
color: var(--text-1);
|
||
}
|
||
|
||
/* Dashboards ALWAYS in a single row of 3 at every screen size. */
|
||
.dash-row {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||
gap: 14px;
|
||
overflow-x: auto;
|
||
padding-bottom: 4px;
|
||
}
|
||
|
||
.dash-row.dash-single {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.dash-panel .chart-body {
|
||
padding: 6px 16px 18px;
|
||
min-height: 280px;
|
||
}
|
||
|
||
/* Hover targets on chart elements */
|
||
.svg-bar rect {
|
||
cursor: pointer;
|
||
}
|
||
|
||
.svg-bar rect:hover {
|
||
opacity: 0.85;
|
||
}
|
||
|
||
.hover-target {
|
||
cursor: pointer;
|
||
}
|
||
|
||
.svg-donut circle:not([stroke="#eef0ee"]) {
|
||
cursor: pointer;
|
||
}
|
||
|
||
.chip-group {
|
||
margin-left: auto;
|
||
display: inline-flex;
|
||
border: 1px solid var(--border-strong);
|
||
border-radius: 6px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.chip {
|
||
background: var(--card-bg);
|
||
border: none;
|
||
padding: 4px 8px;
|
||
cursor: pointer;
|
||
font-size: 13px;
|
||
color: var(--text-2);
|
||
font-family: inherit;
|
||
}
|
||
|
||
.chip:hover {
|
||
background: var(--row-hover);
|
||
}
|
||
|
||
.chip.on {
|
||
background: var(--brand-gradient);
|
||
color: #fff;
|
||
}
|
||
|
||
.svg-line,
|
||
.svg-bar {
|
||
width: 100%;
|
||
height: 280px;
|
||
display: block;
|
||
}
|
||
|
||
/* Flex (not grid) so the legend wraps BELOW the donut when the panel gets
|
||
narrow, instead of the legend column collapsing to ~0 width and clipping
|
||
the label text (which made chart/object names disappear). */
|
||
.donut-wrap {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 14px 18px;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-width: 0;
|
||
}
|
||
|
||
.svg-donut {
|
||
width: 150px;
|
||
max-width: 150px;
|
||
height: 150px;
|
||
aspect-ratio: 1 / 1;
|
||
flex: 0 0 auto;
|
||
}
|
||
|
||
.legend {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 11px;
|
||
font-size: 13px;
|
||
flex: 1 1 140px;
|
||
min-width: 140px;
|
||
}
|
||
|
||
/* Legend label colour is explicit so it stays visible in dark mode too. */
|
||
.legend-name {
|
||
color: var(--text-1);
|
||
}
|
||
|
||
.legend-row {
|
||
display: grid;
|
||
grid-template-columns: 14px minmax(0, 1fr) auto;
|
||
align-items: center;
|
||
gap: 10px;
|
||
min-width: 0;
|
||
}
|
||
|
||
.legend .sw {
|
||
width: 13px;
|
||
height: 13px;
|
||
border-radius: 3px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.legend-name {
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
min-width: 0;
|
||
}
|
||
|
||
.legend-value {
|
||
color: var(--text-2);
|
||
font-weight: 700;
|
||
font-variant-numeric: tabular-nums;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
/* ============== Report ============== */
|
||
.report-panel {
|
||
padding: 0;
|
||
}
|
||
|
||
.table-scroll {
|
||
overflow-x: auto;
|
||
}
|
||
|
||
.report {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
font-size: 12.5px;
|
||
}
|
||
|
||
.report th {
|
||
text-align: center;
|
||
font-weight: 700;
|
||
color: var(--text-1);
|
||
font-size: 11px;
|
||
letter-spacing: 0.6px;
|
||
padding: 11px 14px;
|
||
border-top: 1px solid var(--border);
|
||
border-bottom: 2px solid var(--border-strong);
|
||
background: var(--card-bg-2);
|
||
text-transform: uppercase;
|
||
cursor: pointer;
|
||
user-select: none;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.report th .sort-ind {
|
||
margin-left: 6px;
|
||
color: var(--text-3);
|
||
font-size: 11px;
|
||
}
|
||
|
||
.report th.sorted .sort-ind {
|
||
color: var(--brand-gradient-solid);
|
||
}
|
||
|
||
.report th:hover {
|
||
background: var(--row-hover);
|
||
}
|
||
|
||
/* ----- Drag-and-drop column reordering ----- */
|
||
.report th .col-grip {
|
||
display: inline-block;
|
||
opacity: 0;
|
||
color: var(--text-3);
|
||
font-size: 10px;
|
||
margin-right: 6px;
|
||
cursor: grab;
|
||
transition: opacity 100ms ease;
|
||
transform: rotate(90deg);
|
||
}
|
||
|
||
.report th:hover .col-grip {
|
||
opacity: 0.7;
|
||
}
|
||
|
||
.report th.col-dragging {
|
||
opacity: 0.4;
|
||
background: rgba(47, 158, 68, 0.10);
|
||
}
|
||
|
||
.report th[draggable="true"] {
|
||
cursor: pointer;
|
||
user-select: none;
|
||
}
|
||
|
||
.report th[draggable="true"]:active .col-grip {
|
||
cursor: grabbing;
|
||
}
|
||
|
||
/* ----- Pinned first column + clickable pin toggle ----- */
|
||
.report th.col-locked {
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* When pinned, freeze the whole first column (header + every cell) so it stays
|
||
locked in place while the other columns scroll/reorder. Opaque backgrounds so
|
||
scrolled cells don't bleed through. */
|
||
.report.pinned-first th:first-child,
|
||
.report.pinned-first td:first-child {
|
||
position: sticky;
|
||
left: 0;
|
||
z-index: 2;
|
||
background: var(--card-bg);
|
||
box-shadow: 1px 0 0 var(--border);
|
||
/* subtle separator from the moving columns */
|
||
}
|
||
|
||
.report.pinned-first th:first-child {
|
||
z-index: 3;
|
||
/* header above body cells */
|
||
background: var(--card-bg-2);
|
||
}
|
||
|
||
.report.pinned-first tbody tr:hover td:first-child {
|
||
background: var(--row-hover);
|
||
}
|
||
|
||
.report th .col-pin {
|
||
display: inline-block;
|
||
margin-right: 6px;
|
||
font-size: 11px;
|
||
vertical-align: middle;
|
||
cursor: pointer;
|
||
opacity: 0.35;
|
||
/* dim = unpinned */
|
||
filter: grayscale(1);
|
||
transition: opacity 100ms ease, filter 100ms ease, transform 100ms ease;
|
||
user-select: none;
|
||
}
|
||
|
||
.report th .col-pin:hover {
|
||
opacity: 0.7;
|
||
transform: scale(1.15);
|
||
}
|
||
|
||
.report th .col-pin.on {
|
||
opacity: 1;
|
||
/* bright = pinned */
|
||
filter: none;
|
||
}
|
||
|
||
/* ----- "<Object> Record Details" title with info icon ----- */
|
||
.records-title {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.records-info {
|
||
display: inline-grid;
|
||
place-items: center;
|
||
width: 20px;
|
||
height: 20px;
|
||
border-radius: 50%;
|
||
background: var(--card-bg-2);
|
||
border: 1px solid var(--border);
|
||
color: var(--text-3);
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
font-style: normal;
|
||
cursor: pointer;
|
||
transition: background 100ms ease, color 100ms ease, border-color 100ms ease;
|
||
}
|
||
|
||
.records-info:hover {
|
||
background: rgba(149, 190, 69, 0.12);
|
||
border-color: var(--brand-gradient-solid);
|
||
color: var(--brand-gradient-solid);
|
||
}
|
||
|
||
/* ----- Filter info modal styling ----- */
|
||
.modal-card.filter-info-card {
|
||
width: 480px;
|
||
}
|
||
|
||
.filter-info-list {
|
||
margin: 0;
|
||
padding: 0;
|
||
list-style: none;
|
||
}
|
||
|
||
.filter-info-row {
|
||
padding: 10px 12px;
|
||
margin-bottom: 6px;
|
||
background: var(--card-bg-2);
|
||
border: 1px solid var(--border);
|
||
border-radius: 6px;
|
||
font-family: ui-monospace, 'SF Mono', Menlo, monospace;
|
||
font-size: 12.5px;
|
||
color: var(--text-1);
|
||
word-break: break-all;
|
||
}
|
||
|
||
.filter-info-row:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.report td {
|
||
padding: 10px 14px;
|
||
border-bottom: 1px solid var(--border);
|
||
vertical-align: middle;
|
||
color: var(--text-1);
|
||
white-space: nowrap;
|
||
text-align: center;
|
||
}
|
||
|
||
.report tr:last-child td {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.report tbody tr:hover {
|
||
background: var(--row-hover);
|
||
}
|
||
|
||
/* Clickable record cell — primary record + lookup record links.
|
||
Clicking opens the record-detail popup, NOT a direct navigation. */
|
||
.record-link {
|
||
color: #1f6feb;
|
||
text-decoration: none;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.record-link:hover {
|
||
text-decoration: underline;
|
||
color: #1453c0;
|
||
}
|
||
|
||
.record-link:focus {
|
||
outline: 2px solid rgba(31, 111, 235, 0.35);
|
||
outline-offset: 2px;
|
||
border-radius: 2px;
|
||
}
|
||
|
||
/* ============== Record Detail modal ============== */
|
||
.modal-card.record-detail-card {
|
||
width: 540px;
|
||
max-height: 80vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.record-detail-body {
|
||
overflow-y: auto;
|
||
padding-right: 4px;
|
||
flex: 1 1 auto;
|
||
min-height: 0;
|
||
}
|
||
|
||
.record-detail-field {
|
||
display: grid;
|
||
grid-template-columns: minmax(140px, 200px) 1fr;
|
||
gap: 12px;
|
||
align-items: start;
|
||
padding: 8px 7px;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
|
||
.record-detail-field:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.record-detail-id-row {
|
||
background: var(--brand-gradient);
|
||
border: 1px solid var(--brand-gradient);;
|
||
border-radius: 6px;
|
||
padding: 10px 7px;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.record-detail-label {
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
color: #000000;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.3px;
|
||
}
|
||
|
||
.record-detail-value {
|
||
font-size: 13px;
|
||
color: var(--text-1);
|
||
word-break: break-word;
|
||
}
|
||
|
||
.record-id-link {
|
||
color: #000000;
|
||
text-decoration: none;
|
||
font-weight: 600;
|
||
font-family: ui-monospace, 'SF Mono', Menlo, monospace;
|
||
font-size: 12.5px;
|
||
}
|
||
|
||
.record-id-link:hover {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.record-detail-loading {
|
||
padding: 32px 16px;
|
||
text-align: center;
|
||
color: var(--text-3);
|
||
font-size: 13px;
|
||
font-style: italic;
|
||
}
|
||
|
||
.panel-footer {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 10px 16px;
|
||
border-top: 1px solid var(--border);
|
||
font-size: 11.5px;
|
||
color: var(--text-3);
|
||
}
|
||
|
||
.pager {
|
||
margin-left: auto;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
}
|
||
|
||
.pager .pg {
|
||
min-width: 26px;
|
||
height: 26px;
|
||
display: grid;
|
||
place-items: center;
|
||
border-radius: 5px;
|
||
cursor: pointer;
|
||
padding: 0 8px;
|
||
font-size: 12px;
|
||
color: var(--text-2);
|
||
}
|
||
|
||
.pager .pg:hover {
|
||
background: var(--brand-gradient);
|
||
}
|
||
|
||
.pager .pg.active {
|
||
background: var(--brand-gradient);
|
||
color: #fff;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.pager .nav {
|
||
height: 26px;
|
||
padding: 0 10px;
|
||
display: grid;
|
||
place-items: center;
|
||
border-radius: 5px;
|
||
color: var(--text-2);
|
||
cursor: pointer;
|
||
font-size: 12px;
|
||
}
|
||
|
||
.pager .nav:hover {
|
||
background: var(--row-hover);
|
||
}
|
||
|
||
.footer-copy {
|
||
text-align: center;
|
||
font-size: 11.5px;
|
||
color: var(--text-3);
|
||
padding: 12px 0 18px;
|
||
}
|
||
|
||
.footer-copy a {
|
||
color: var(--text-2);
|
||
text-decoration: underline;
|
||
}
|
||
|
||
/* ============== Modals ============== */
|
||
.modal-backdrop {
|
||
position: fixed;
|
||
inset: 0;
|
||
z-index: 1000;
|
||
background: rgba(0, 0, 0, 0.45);
|
||
display: grid;
|
||
place-items: center;
|
||
backdrop-filter: blur(2px);
|
||
}
|
||
|
||
.modal-card {
|
||
position: relative;
|
||
background: var(--card-bg);
|
||
color: var(--text-1);
|
||
border-radius: 10px;
|
||
box-shadow: var(--shadow);
|
||
width: 380px;
|
||
padding: 22px 24px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.modal-card::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 4px;
|
||
background: var(--brand-gradient);
|
||
}
|
||
|
||
.modal-card.share-card {
|
||
width: 480px;
|
||
}
|
||
|
||
.modal-title {
|
||
font-size: 16px;
|
||
font-weight: 700;
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
.modal-body {
|
||
font-size: 13px;
|
||
color: var(--text-2);
|
||
}
|
||
|
||
.modal-body p {
|
||
margin: 4px 0 8px;
|
||
}
|
||
|
||
.cooldown {
|
||
font-size: 22px;
|
||
font-weight: 700;
|
||
background: var(--brand-gradient);
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
background-clip: text;
|
||
font-variant-numeric: tabular-nums;
|
||
margin-top: 6px;
|
||
letter-spacing: 1px;
|
||
}
|
||
|
||
.app.dark .cooldown {
|
||
color: var(--shopify-green);
|
||
}
|
||
|
||
.modal-actions {
|
||
margin-top: 16px;
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
gap: 8px;
|
||
}
|
||
|
||
/* Share tiles */
|
||
.share-format-pill {
|
||
display: inline-block;
|
||
font-size: 11.5px;
|
||
color: var(--text-2);
|
||
background: var(--card-bg-2);
|
||
border: 1px solid var(--border);
|
||
padding: 4px 10px;
|
||
border-radius: 999px;
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
.more-share-hint {
|
||
margin: 0 0 14px;
|
||
padding: 10px 12px;
|
||
background: rgba(149, 190, 69, 0.08);
|
||
border: 1px solid rgba(149, 190, 69, 0.30);
|
||
border-radius: 6px;
|
||
font-size: 11.5px;
|
||
line-height: 1.45;
|
||
color: var(--text-2);
|
||
}
|
||
|
||
.more-share-hint strong {
|
||
color: var(--brand-green-dark);
|
||
font-weight: 700;
|
||
}
|
||
|
||
.more-share-hint em {
|
||
color: var(--text-1);
|
||
font-style: normal;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.share-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 10px;
|
||
}
|
||
|
||
.share-tile {
|
||
background: var(--card-bg-2);
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
padding: 14px 8px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 6px;
|
||
cursor: pointer;
|
||
transition: all 150ms ease;
|
||
}
|
||
|
||
.share-tile:hover {
|
||
background: var(--card-bg);
|
||
border-color: var(--brand-gradient-solid);
|
||
transform: translateY(-1px);
|
||
box-shadow: 0 2px 6px rgba(47, 158, 68, 0.18);
|
||
}
|
||
|
||
.share-tile-icon {
|
||
font-size: 22px;
|
||
line-height: 1;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 40px;
|
||
height: 40px;
|
||
}
|
||
|
||
.share-tile-icon svg {
|
||
display: block;
|
||
width: 40px;
|
||
height: 40px;
|
||
}
|
||
|
||
.share-tile-label {
|
||
font-size: 11.5px;
|
||
font-weight: 600;
|
||
color: var(--text-1);
|
||
}
|
||
|
||
/* ============== Schedule Report modal ============== */
|
||
.modal-card.schedule-card {
|
||
width: 480px;
|
||
max-height: 90vh;
|
||
}
|
||
.scrollbar-hidden{
|
||
max-height: 60vh;
|
||
overflow: scroll;
|
||
&::-webkit-scrollbar {
|
||
display: none;
|
||
}
|
||
|
||
/* Hide scrollbar for Firefox */
|
||
scrollbar-width: none;
|
||
|
||
/* Hide scrollbar for IE and Edge */
|
||
-ms-overflow-style: none;
|
||
}
|
||
|
||
.sched-form {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 12px;
|
||
}
|
||
|
||
.sched-row {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
}
|
||
|
||
.sched-label {
|
||
font-size: 11px;
|
||
letter-spacing: 0.5px;
|
||
font-weight: 600;
|
||
color: var(--text-2);
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
.sched-input {
|
||
padding: 8px 10px;
|
||
border: 1px solid var(--border-strong);
|
||
border-radius: 6px;
|
||
background: var(--card-bg);
|
||
color: var(--text-1);
|
||
font-size: 13px;
|
||
font-family: inherit;
|
||
box-sizing: border-box;
|
||
width: 100%;
|
||
}
|
||
|
||
.sched-input:focus {
|
||
outline: none;
|
||
border-color: var(--brand-gradient-solid);
|
||
}
|
||
|
||
.sched-input.sched-input-readonly {
|
||
background: var(--card-bg-2);
|
||
color: var(--text-2);
|
||
cursor: default;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.sched-input.sched-input-readonly:focus {
|
||
border-color: var(--border-strong);
|
||
}
|
||
|
||
.sched-textarea {
|
||
resize: vertical;
|
||
min-height: 48px;
|
||
}
|
||
|
||
/* Existing schedules list inside the Schedule Report modal */
|
||
.sched-existing {
|
||
margin-bottom: 16px;
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
padding: 10px 12px;
|
||
background: var(--row-hover);
|
||
}
|
||
|
||
.sched-existing-title {
|
||
font-size: 10.5px;
|
||
letter-spacing: 1px;
|
||
font-weight: 700;
|
||
color: var(--text-3);
|
||
margin-bottom: 4px;
|
||
}
|
||
|
||
.sched-existing-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
padding: 7px 0;
|
||
}
|
||
|
||
.sched-existing-row+.sched-existing-row {
|
||
border-top: 1px solid var(--border);
|
||
}
|
||
|
||
.sched-existing-meta {
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
|
||
.sched-existing-name {
|
||
font-weight: 600;
|
||
font-size: 12.5px;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.sched-existing-sub {
|
||
font-size: 11px;
|
||
color: var(--text-3);
|
||
}
|
||
|
||
.sched-delete-btn {
|
||
color: #dc2626;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.sched-delete-btn:disabled {
|
||
opacity: 0.55;
|
||
cursor: default;
|
||
}
|
||
|
||
.sched-existing-loading {
|
||
font-size: 12px;
|
||
color: var(--text-3);
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
.sched-hint {
|
||
font-size: 11px;
|
||
color: var(--text-3);
|
||
margin-top: 2px;
|
||
}
|
||
|
||
.sched-error {
|
||
background: rgba(220, 38, 38, 0.08);
|
||
border: 1px solid rgba(220, 38, 38, 0.35);
|
||
color: var(--down-color);
|
||
font-size: 12px;
|
||
padding: 8px 10px;
|
||
border-radius: 6px;
|
||
}
|
||
|
||
.rcpt-summary {
|
||
font-size: 11.5px;
|
||
color: var(--text-3);
|
||
margin-top: 4px;
|
||
}
|
||
|
||
.rcpt-pills {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 6px;
|
||
margin-top: 6px;
|
||
}
|
||
|
||
.rcpt-pill {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
padding: 3px 8px;
|
||
border-radius: 999px;
|
||
font-size: 11.5px;
|
||
font-weight: 500;
|
||
line-height: 1.3;
|
||
}
|
||
|
||
.rcpt-pill.rcpt-valid {
|
||
background: rgba(47, 158, 68, 0.12);
|
||
color: var(--brand-gradient-solid);
|
||
border: 1px solid rgba(47, 158, 68, 0.35);
|
||
}
|
||
|
||
.rcpt-pill.rcpt-invalid {
|
||
background: rgba(220, 38, 38, 0.10);
|
||
color: var(--down-color);
|
||
border: 1px solid rgba(220, 38, 38, 0.35);
|
||
}
|
||
|
||
.rcpt-pill.rcpt-overlimit {
|
||
background: rgba(245, 158, 11, 0.10);
|
||
color: #b45309;
|
||
border: 1px dashed rgba(245, 158, 11, 0.55);
|
||
}
|
||
|
||
.app.dark .rcpt-pill.rcpt-overlimit {
|
||
background: rgba(245, 158, 11, 0.15);
|
||
color: #fbbf24;
|
||
}
|
||
|
||
.rcpt-icon {
|
||
font-size: 11px;
|
||
}
|
||
|
||
/* Inline secondary hint inside a label (used in the Recipients label) */
|
||
.sched-label-hint {
|
||
font-weight: 500;
|
||
font-size: 10px;
|
||
color: var(--text-3);
|
||
text-transform: none;
|
||
letter-spacing: 0;
|
||
margin-left: 4px;
|
||
}
|
||
|
||
/* ============== Filter / Sort dropdown sizing ============== */
|
||
.sort-by-wrap {
|
||
margin-left: auto;
|
||
}
|
||
|
||
.menu.sort-menu {
|
||
min-width: 240px;
|
||
max-height: 360px;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.menu.filter-menu {
|
||
min-width: 180px;
|
||
max-height: 320px;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.menu-item.active {
|
||
background: rgba(47, 158, 68, 0.12);
|
||
color: var(--brand-gradient-solid);
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* ============== Responsive ============== */
|
||
/* Goal: filters + action buttons stay on ONE row at every typical laptop width.
|
||
We progressively shrink internal element padding/min-widths as the viewport
|
||
narrows — only at very small widths do we allow flex-wrap to break them. */
|
||
|
||
@media (max-width: 1440px) {
|
||
|
||
/* Common laptop (1366–1440px) — keep "Filter by" label, slightly tighter elements */
|
||
.topbar {
|
||
gap: 8px;
|
||
padding: 10px 14px;
|
||
}
|
||
|
||
.topbar-filters {
|
||
gap: 4px;
|
||
}
|
||
|
||
.topbar-actions {
|
||
gap: 4px;
|
||
}
|
||
|
||
.select {
|
||
min-width: 90px;
|
||
padding: 5px 8px;
|
||
font-size: 11.5px;
|
||
}
|
||
|
||
.select>span:first-child {
|
||
max-width: 110px;
|
||
}
|
||
|
||
.btn {
|
||
padding: 5px 9px;
|
||
font-size: 11.5px;
|
||
}
|
||
|
||
.filter-label {
|
||
font-size: 11.5px;
|
||
padding-right: 8px;
|
||
margin-right: 2px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 1280px) {
|
||
|
||
/* Topbar tighter — charts already at 2 cols by default */
|
||
.topbar {
|
||
gap: 6px;
|
||
padding: 9px 12px;
|
||
}
|
||
|
||
.topbar-filters {
|
||
gap: 3px;
|
||
}
|
||
|
||
.topbar-actions {
|
||
gap: 3px;
|
||
}
|
||
|
||
.select {
|
||
min-width: 80px;
|
||
padding: 4px 7px;
|
||
font-size: 11px;
|
||
}
|
||
|
||
.select>span:first-child {
|
||
max-width: 90px;
|
||
}
|
||
|
||
.btn {
|
||
padding: 5px 8px;
|
||
font-size: 11px;
|
||
gap: 4px;
|
||
}
|
||
|
||
.icon-btn {
|
||
width: 28px;
|
||
height: 28px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 1440px) {
|
||
|
||
/* Keep 8-col / 3-col single-row but slightly tighter type */
|
||
.kpi {
|
||
padding: 8px 10px 10px;
|
||
}
|
||
|
||
.kpi .value {
|
||
font-size: 16px;
|
||
}
|
||
|
||
.kpi .label {
|
||
font-size: 8.5px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 1280px) {
|
||
|
||
/* Same — single row enforced. Just shrink card type further. */
|
||
.kpi {
|
||
padding: 6px 8px 8px;
|
||
}
|
||
|
||
.kpi .value {
|
||
font-size: 14px;
|
||
}
|
||
|
||
.kpi .label {
|
||
font-size: 8px;
|
||
letter-spacing: 0.4px;
|
||
}
|
||
|
||
.kpi .sub {
|
||
font-size: 9px;
|
||
}
|
||
|
||
.kpi .delta {
|
||
font-size: 9.5px;
|
||
margin-top: 4px;
|
||
}
|
||
|
||
/* Give dashboard panels a min-width floor so charts/legends stay legible;
|
||
horizontal scroll engages instead of squishing them (which made the
|
||
donut legend collapse and chart layout break at ~100% on 1366px screens). */
|
||
.dash-row {
|
||
grid-template-columns: repeat(3, minmax(300px, 1fr));
|
||
}
|
||
|
||
/* Slightly smaller donut on tighter panels so it sits beside its legend. */
|
||
.svg-donut {
|
||
width: 130px;
|
||
max-width: 130px;
|
||
height: 130px;
|
||
}
|
||
|
||
.legend {
|
||
flex-basis: 130px;
|
||
min-width: 130px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 1100px) {
|
||
|
||
/* Topbar still single-row at this width — even tighter */
|
||
.select {
|
||
min-width: 72px;
|
||
max-width: 110px;
|
||
}
|
||
|
||
.select>span:first-child {
|
||
max-width: 78px;
|
||
}
|
||
|
||
.btn {
|
||
padding: 4px 7px;
|
||
font-size: 10.5px;
|
||
}
|
||
|
||
/* Below 1100px we drop the "Filter:" label to reclaim space */
|
||
.filter-label {
|
||
display: none;
|
||
}
|
||
|
||
/* KPIs keep single-row but each card needs a floor width to stay
|
||
legible — horizontal scroll handles overflow. */
|
||
.kpi-row {
|
||
grid-template-columns: repeat(8, minmax(110px, 1fr));
|
||
}
|
||
}
|
||
|
||
@media (max-width: 900px) {
|
||
.kpi-row {
|
||
grid-template-columns: repeat(8, minmax(100px, 1fr));
|
||
}
|
||
|
||
.dash-row {
|
||
grid-template-columns: repeat(3, minmax(320px, 1fr));
|
||
}
|
||
}
|
||
|
||
@media (max-width: 980px) {
|
||
|
||
/* Last stop before wrapping — drop verbose labels on action buttons */
|
||
.btn {
|
||
padding: 4px 6px;
|
||
font-size: 10.5px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 880px) {
|
||
|
||
/* Genuinely not enough horizontal room — allow filters block to wrap below actions */
|
||
.topbar-filters {
|
||
width: 100%;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.topbar-actions {
|
||
margin-left: 0;
|
||
width: 100%;
|
||
justify-content: flex-end;
|
||
}
|
||
|
||
.select {
|
||
flex: 0 0 auto;
|
||
min-width: 80px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 720px) {
|
||
.app {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.sidebar {
|
||
display: none;
|
||
}
|
||
|
||
/* Mobile keeps single-row enforcement — horizontal scroll handles
|
||
the narrow viewport. User scrolls left/right to see all cards/charts. */
|
||
.kpi-row {
|
||
grid-template-columns: repeat(8, minmax(96px, 1fr));
|
||
}
|
||
|
||
.dash-row {
|
||
grid-template-columns: repeat(3, minmax(300px, 1fr));
|
||
}
|
||
|
||
.share-grid {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
}
|
||
}
|
||
|
||
@media print {
|
||
|
||
/* Force-hide ALL modal backdrops by selector, regardless of state */
|
||
.modal-backdrop,
|
||
[class*="modal-backdrop"] {
|
||
display: none !important;
|
||
visibility: hidden !important;
|
||
opacity: 0 !important;
|
||
position: absolute !important;
|
||
z-index: -9999 !important;
|
||
}
|
||
|
||
/* Hide the modal card itself if backdrop failed */
|
||
.modal-card,
|
||
.share-card,
|
||
.schedule-card,
|
||
.filter-info-card,
|
||
.record-detail-card {
|
||
display: none !important;
|
||
visibility: hidden !important;
|
||
}
|
||
|
||
/* Hide non-content elements (sidebar nav + store name kept for print) */
|
||
.topbar,
|
||
.footer-copy,
|
||
.refresh-banner,
|
||
.sync-health,
|
||
.sidebar-footer {
|
||
display: none !important;
|
||
}
|
||
|
||
/* Restructure layout for print — stack sidebar on top of main content */
|
||
.app,
|
||
.app.modal-open {
|
||
display: block !important;
|
||
height: auto !important;
|
||
max-height: none !important;
|
||
min-height: auto !important;
|
||
overflow: visible !important;
|
||
}
|
||
|
||
.main,
|
||
.app.modal-open .main {
|
||
overflow: visible !important;
|
||
height: auto !important;
|
||
min-height: auto !important;
|
||
}
|
||
|
||
/* ---- Sidebar: transformed into a top center header for print ---- */
|
||
.sidebar {
|
||
background: transparent !important;
|
||
color: #1f2937 !important;
|
||
padding: 10px 0 15px 0 !important;
|
||
overflow: visible !important;
|
||
height: auto !important;
|
||
min-height: 0 !important;
|
||
border-right: none !important;
|
||
border-bottom: 2px solid #c5d6a4 !important;
|
||
width: 100% !important;
|
||
display: flex !important;
|
||
flex-direction: column !important;
|
||
align-items: center !important;
|
||
justify-content: center !important;
|
||
text-align: center !important;
|
||
}
|
||
|
||
.brand {
|
||
display: none !important;
|
||
}
|
||
|
||
.store-selector {
|
||
display: flex !important;
|
||
background: transparent !important;
|
||
border: none !important;
|
||
margin: 0 auto 5px !important;
|
||
cursor: default !important;
|
||
justify-content: center !important;
|
||
align-items: center !important;
|
||
text-align: center !important;
|
||
padding: 0 !important;
|
||
}
|
||
|
||
.store-selector .store-icon {
|
||
display: none !important;
|
||
}
|
||
|
||
.store-selector .meta {
|
||
text-align: center !important;
|
||
}
|
||
|
||
.store-selector .meta .l1 {
|
||
color: #000 !important;
|
||
font-weight: 700 !important;
|
||
font-size: 18px !important;
|
||
}
|
||
|
||
.store-selector .meta .l2 {
|
||
display: none !important; /* Hide store domain URL for a cleaner print header */
|
||
}
|
||
|
||
.store-selector .caret,
|
||
.store-menu {
|
||
display: none !important;
|
||
}
|
||
|
||
.nav-label {
|
||
display: none !important; /* Hide the "OBJECTS" label in print */
|
||
}
|
||
|
||
.obj-list {
|
||
overflow: visible !important;
|
||
height: auto !important;
|
||
display: flex !important;
|
||
justify-content: center !important;
|
||
align-items: center !important;
|
||
width: 100% !important;
|
||
margin-top: 5px !important;
|
||
}
|
||
|
||
/* Hide non-active navigation items from the print view completely */
|
||
.obj-item:not(.active) {
|
||
display: none !important;
|
||
}
|
||
|
||
/* Style the active object item to sit directly below the store name */
|
||
.obj-item.active {
|
||
background: transparent !important;
|
||
border: none !important;
|
||
color: #000 !important;
|
||
padding: 0 !important;
|
||
margin: 0 !important;
|
||
display: flex !important;
|
||
align-items: center !important;
|
||
justify-content: center !important;
|
||
gap: 8px !important;
|
||
box-shadow: none !important;
|
||
}
|
||
|
||
.obj-item.active::before {
|
||
display: none !important;
|
||
}
|
||
|
||
.obj-item.active .obj-text {
|
||
display: inline-flex !important;
|
||
align-items: center !important;
|
||
}
|
||
|
||
.obj-item.active .obj-icon {
|
||
display: none !important; /* Hide Salesforce icons in header */
|
||
}
|
||
|
||
.obj-item.active .obj-name {
|
||
color: #000 !important;
|
||
font-size: 14px !important;
|
||
font-weight: 700 !important;
|
||
}
|
||
|
||
.obj-item.active .obj-name::after {
|
||
content:" \2014" !important;
|
||
margin-left: 8px !important;
|
||
color: #9ca3af !important;
|
||
font-weight: normal !important;
|
||
}
|
||
|
||
.obj-item.active .counts {
|
||
display: inline-flex !important;
|
||
align-items: center !important;
|
||
gap: 8px !important;
|
||
}
|
||
|
||
.obj-item.active .count-pill {
|
||
background: transparent !important;
|
||
border: none !important;
|
||
padding: 0 !important;
|
||
font-size: 13px !important;
|
||
color: #374151 !important;
|
||
display: inline-flex !important;
|
||
align-items: center !important;
|
||
gap: 4px !important;
|
||
}
|
||
|
||
.obj-item.active .count-pill .logo-stack {
|
||
display: inline-flex !important;
|
||
align-items: center !important;
|
||
gap: 2px !important;
|
||
}
|
||
|
||
.obj-item.active .count-pill .logo {
|
||
display: none !important; /* Hide SVGs for a clean inline look */
|
||
}
|
||
|
||
.obj-item.active .count-pill .logo-name {
|
||
display: inline !important;
|
||
font-size: 13px !important;
|
||
font-weight: 600 !important;
|
||
color: #4b5563 !important;
|
||
}
|
||
|
||
.obj-item.active .count-pill .logo-name::after {
|
||
content: ":" !important;
|
||
}
|
||
|
||
.obj-item.active .count-pill .count-val {
|
||
font-size: 13px !important;
|
||
font-weight: 700 !important;
|
||
color: #000 !important;
|
||
}
|
||
|
||
/* Add a clean separator between Shopify and Salesforce counts if both exist */
|
||
.obj-item.active .count-pill + .count-pill::before {
|
||
content: "\2014 " !important;
|
||
margin-right: 8px !important;
|
||
color: #9ca3af !important;
|
||
font-weight: normal !important;
|
||
}
|
||
|
||
.content {
|
||
padding: 0 !important;
|
||
gap: 16px !important;
|
||
}
|
||
|
||
/* Ensure panels print cleanly */
|
||
.panel,
|
||
.kpi,
|
||
.dash-panel {
|
||
break-inside: avoid !important;
|
||
page-break-inside: avoid !important;
|
||
box-shadow: none !important;
|
||
border: 1px solid #ddd !important;
|
||
}
|
||
|
||
/* KPI row: keep horizontal but allow natural sizing */
|
||
.kpi-row {
|
||
display: grid !important;
|
||
grid-template-columns: repeat(8, 1fr) !important;
|
||
gap: 8px !important;
|
||
overflow: visible !important;
|
||
}
|
||
|
||
/* Dashboards: stack vertically for print */
|
||
.dash-row {
|
||
display: flex !important;
|
||
flex-direction: column !important;
|
||
gap: 16px !important;
|
||
overflow: visible !important;
|
||
}
|
||
|
||
.dash-row.dash-single {
|
||
display: block !important;
|
||
}
|
||
|
||
@page {
|
||
size: landscape;
|
||
margin: 10mm;
|
||
}
|
||
|
||
.report-panel {
|
||
zoom: 0.85 !important;
|
||
}
|
||
|
||
/* Report table: un-scroll and fit */
|
||
.table-scroll {
|
||
overflow: visible !important;
|
||
}
|
||
|
||
.section-title,
|
||
.panel-head .title {
|
||
font-size: 15px !important;
|
||
}
|
||
|
||
.kpi .label {
|
||
font-size: 11px !important;
|
||
}
|
||
|
||
.kpi .value {
|
||
font-size: 20px !important;
|
||
}
|
||
|
||
.kpi .sub,
|
||
.kpi .delta {
|
||
font-size: 11px !important;
|
||
}
|
||
|
||
.report {
|
||
font-size: 11.5px !important;
|
||
width: 100% !important;
|
||
}
|
||
|
||
.report th {
|
||
font-size: 11px !important;
|
||
}
|
||
|
||
.report th,
|
||
.report td {
|
||
padding: 5px 8px !important;
|
||
white-space: normal !important;
|
||
word-break: break-word !important;
|
||
}
|
||
|
||
/* Hide interactive chrome */
|
||
.chip-group,
|
||
.report-actions,
|
||
.panel-footer,
|
||
.pager,
|
||
.records-info,
|
||
.col-grip,
|
||
.col-pin,
|
||
.reorder-btn,
|
||
.hidden-download-anchor {
|
||
display: none !important;
|
||
}
|
||
|
||
/* Force background colors */
|
||
* {
|
||
-webkit-print-color-adjust: exact !important;
|
||
print-color-adjust: exact !important;
|
||
color-adjust: exact !important;
|
||
}
|
||
|
||
/* SVG sizing for print */
|
||
.svg-line,
|
||
.svg-bar {
|
||
height: 180px !important;
|
||
max-height: 200px !important;
|
||
}
|
||
|
||
/* Ensure text is black for readability */
|
||
body,
|
||
.app,
|
||
.main,
|
||
.content,
|
||
.panel,
|
||
.kpi,
|
||
.report {
|
||
color: #000 !important;
|
||
background: #fff !important;
|
||
}
|
||
}
|
||
|
||
@media print {
|
||
|
||
/* Force-hide ALL modal elements by structure — works even if JS fails */
|
||
.modal-backdrop,
|
||
.modal-card,
|
||
.share-card,
|
||
.schedule-card,
|
||
.filter-info-card,
|
||
.record-detail-card,
|
||
[class*="modal-"],
|
||
[class*="share-"] {
|
||
display: none !important;
|
||
visibility: hidden !important;
|
||
opacity: 0 !important;
|
||
position: absolute !important;
|
||
z-index: -9999 !important;
|
||
height: 0 !important;
|
||
width: 0 !important;
|
||
overflow: hidden !important;
|
||
}
|
||
}
|
||
|
||
/* --- Single-chart dashboard: cap height + center chart so it doesn't stretch --- */
|
||
.dash-row.dash-single {
|
||
grid-template-columns: minmax(0, 720px);
|
||
justify-content: center;
|
||
}
|
||
|
||
.dash-row.dash-single .dash-panel {
|
||
max-width: 720px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.dash-row.dash-single .dash-panel .chart-body {
|
||
min-height: 260px;
|
||
max-height: 320px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.dash-row.dash-single .svg-line,
|
||
.dash-row.dash-single .svg-bar {
|
||
height: 260px;
|
||
max-height: 260px;
|
||
}
|
||
|
||
.dash-row.dash-single .svg-donut {
|
||
width: 180px;
|
||
max-width: 180px;
|
||
height: 180px;
|
||
}
|
||
|
||
.panel-head {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 14px 16px 10px;
|
||
gap: 10px;
|
||
min-width: 0;
|
||
}
|
||
|
||
.panel-head .title {
|
||
font-size: 13px; /* slightly smaller so long titles fit in one line */
|
||
font-weight: 600;
|
||
color: var(--text-1);
|
||
flex: 1 1 auto; /* take all available space */
|
||
min-width: 0; /* allow shrinking */
|
||
white-space: nowrap; /* never wrap */
|
||
overflow: hidden;
|
||
text-overflow: ellipsis; /* "Top 6 Products by Unit…" instead of wrapping */
|
||
line-height: 1.3;
|
||
}
|
||
|
||
.chip-group {
|
||
flex-shrink: 0; /* never shrink — stays right-aligned */
|
||
margin-left: auto;
|
||
display: inline-flex;
|
||
align-items: center; /* vertically centre all chips together */
|
||
border: 1px solid var(--border-strong);
|
||
border-radius: 6px;
|
||
overflow: hidden;
|
||
height: 28px; /* fixed height so all 3 chips are the same size */
|
||
}
|
||
|
||
.chip {
|
||
background: var(--card-bg);
|
||
border: none;
|
||
border-right: 1px solid var(--border-strong); /* separator between chips */
|
||
padding: 0 8px;
|
||
height: 100%; /* fill the chip-group height — no size difference */
|
||
cursor: pointer;
|
||
font-size: 13px;
|
||
color: var(--text-2);
|
||
font-family: inherit;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
line-height: 1;
|
||
transition: background 100ms ease, color 100ms ease;
|
||
}
|
||
|
||
.chip:last-child {
|
||
border-right: none; /* no trailing separator on last chip */
|
||
}
|
||
|
||
.chip:hover {
|
||
background: var(--row-hover);
|
||
}
|
||
|
||
.chip.on {
|
||
background: var(--brand-gradient);
|
||
color: #fff;
|
||
} |