/** * Copyright since 2025 Mifos Initiative * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ $primary: #1a73e8; $primary-dark: #0c447c; $primary-light: #e8f0fe; $gray-50: #f8f9fa; $gray-100: #f1f3f4; $gray-200: #e8eaed; $gray-500: #9aa0a6; $gray-700: #5f6368; $gray-900: #202124; $white: #fff; $green: #1d9e75; $green-light: #e1f5ee; $teal-900: #085041; $teal-700: #0f6e56; $red: #d85a30; $red-light: #faece7; $amber: #ba7517; $amber-light: #faeeda; $purple: #6a4cb3; $purple-light: #efeafb; .cv-container { padding: 22px 26px 40px; max-width: 1400px; margin: 0 auto; } /* ---------- Header ---------- */ .cv-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 18px; flex-wrap: wrap; gap: 12px; &__left { display: flex; align-items: center; gap: 14px; } &__icon { width: 44px; height: 44px; border-radius: 10px; background: linear-gradient(135deg, $teal-700, $green); color: $white; display: flex; align-items: center; justify-content: center; font-size: 18px; box-shadow: 0 3px 10px rgba($green, 0.3); flex-shrink: 0; } &__title { margin: 0; font-size: 20px; font-weight: 700; color: $gray-900; } &__sub { margin: 2px 0 0; font-size: 13px; color: $gray-500; } } .cv-btn { display: inline-flex; align-items: center; gap: 8px; padding: 0 16px; height: 38px; border-radius: 8px; font-size: 13px; font-weight: 600; border: 1px solid $gray-200; background: $white; color: $gray-700; cursor: pointer; transition: all 0.15s; fa-icon { font-size: 12px; } &:hover:not(:disabled) { background: $gray-50; border-color: $gray-500; } &--ghost { /* default */ } &--primary { background: $primary; border-color: $primary; color: $white; &:hover:not(:disabled) { background: #1557b5; border-color: #1557b5; } } } /* ---------- KPIs ---------- */ .cv-kpis { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 14px; margin-bottom: 18px; } .cv-kpi { display: flex; align-items: center; gap: 12px; padding: 14px 16px; background: $white; border: 1px solid $gray-200; border-radius: 12px; &__icon { width: 40px; height: 40px; border-radius: 10px; color: $white; display: flex; align-items: center; justify-content: center; font-size: 15px; flex-shrink: 0; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); &--blue { background: linear-gradient(135deg, $primary, #4285f4); } &--teal { background: linear-gradient(135deg, $teal-700, $green); } &--amber { background: linear-gradient(135deg, $amber, #d4892f); } &--green { background: linear-gradient(135deg, $green, #2fb88c); } &--purple { background: linear-gradient(135deg, $purple, #8a6fd4); } } &__label { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.4px; color: $gray-500; margin-bottom: 2px; } &__value { font-size: 18px; font-weight: 700; color: $gray-900; &--mono { font-family: 'SF Mono', Consolas, monospace; font-size: 13px; color: $primary; } } } /* ---------- Filters ---------- */ .cv-filters { background: $white; border: 1px solid $gray-200; border-radius: 12px; padding: 18px 20px; margin-bottom: 18px; &__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px 18px; margin-bottom: 16px; } &__actions { display: flex; justify-content: flex-end; gap: 10px; padding-top: 14px; border-top: 1px dashed $gray-200; } } .cv-field { display: flex; flex-direction: column; gap: 5px; min-width: 0; } .cv-label { font-size: 11px; font-weight: 600; color: $gray-700; display: inline-flex; align-items: center; gap: 6px; fa-icon { color: $primary; font-size: 11px; } } .cv-input { width: 100%; padding: 10px 12px; border: 1px solid $gray-200; border-radius: 8px; background: $gray-50; color: $gray-900; font-size: 13px; font-family: inherit; height: 40px; box-sizing: border-box; transition: all 0.15s; &:focus { outline: none; border-color: $primary; background: $white; box-shadow: 0 0 0 3px rgba($primary, 0.1); } } select.cv-input { appearance: none; padding-right: 34px; background-image: url("data:image/svg+xml;utf8,"); background-repeat: no-repeat; background-position: right 12px center; cursor: pointer; } /* ---------- Section tabs ---------- */ .cv-tabs { display: flex !important; gap: 10px !important; margin-bottom: 16px !important; background: $white !important; border: 1px solid $gray-200 !important; border-radius: 14px !important; padding: 8px !important; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03) !important; } button.cv-tab, .cv-tabs .cv-tab { flex: 1 1 0 !important; display: inline-flex !important; align-items: center !important; justify-content: center !important; gap: 10px !important; padding: 14px 20px !important; min-height: 52px !important; border: 1.5px solid transparent !important; border-radius: 10px !important; background: transparent !important; color: $gray-700 !important; font-size: 14px !important; font-weight: 600 !important; cursor: pointer !important; transition: all 0.15s !important; font-family: inherit !important; white-space: nowrap !important; min-width: 0 !important; line-height: 1 !important; outline: none !important; box-shadow: none !important; > fa-icon { font-size: 15px !important; color: $gray-500 !important; } > span:not(.cv-tab__badge):not(.cv-tab__count) { display: inline-flex !important; align-items: center !important; } &:hover { background: $gray-50 !important; color: $gray-900 !important; > fa-icon { color: $primary !important; } } &--active { background: $primary-light !important; border-color: rgba($primary, 0.35) !important; color: $primary-dark !important; box-shadow: 0 2px 8px rgba($primary, 0.12) !important; > fa-icon { color: $primary !important; } } } .cv-tab__badge { display: inline-block !important; padding: 3px 9px !important; border-radius: 10px !important; font-size: 9px !important; font-weight: 700 !important; text-transform: uppercase !important; letter-spacing: 0.3px !important; margin-left: 2px !important; &--blue { background: $primary-light !important; color: $primary-dark !important; } &--amber { background: $amber-light !important; color: $amber !important; } } .cv-tab__count { display: inline-flex !important; align-items: center !important; justify-content: center !important; min-width: 22px !important; height: 20px !important; padding: 0 8px !important; border-radius: 10px !important; background: $amber !important; color: $white !important; font-size: 10px !important; font-weight: 700 !important; font-variant-numeric: tabular-nums !important; } @media (width <= 680px) { .cv-tabs { flex-direction: column !important; } button.cv-tab, .cv-tabs .cv-tab { justify-content: space-between !important; } } /* Hide the per-section header badge since the tab strip already carries it */ .cv-section .cv-badge { display: none; } /* ---------- Section card ---------- */ .cv-section { background: $white; border: 1px solid $gray-200; border-radius: 14px; padding: 18px 20px 20px; margin-bottom: 18px; &__head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; padding-bottom: 12px; border-bottom: 1px solid $gray-100; } &__title { display: flex; align-items: center; gap: 12px; > fa-icon { width: 36px; height: 36px; border-radius: 10px; background: $primary-light; color: $primary; display: flex !important; align-items: center; justify-content: center; font-size: 14px; } h3 { margin: 0; font-size: 15px; font-weight: 700; color: $gray-900; } p { margin: 2px 0 0; font-size: 11px; color: $gray-500; } } &--placeholder { background: linear-gradient(135deg, $gray-50, $primary-light); } } .cv-badge { display: inline-block; padding: 3px 10px; border-radius: 10px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.3px; &--blue { background: $primary-light; color: $primary-dark; } &--amber { background: $amber-light; color: $amber; } } /* ---------- State banners ---------- */ .cv-state { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 30px 20px; border-radius: 10px; font-size: 13px; fa-icon { font-size: 18px; } &--loading { background: $primary-light; color: $primary; border: 1px dashed rgba($primary, 0.3); } &--error { background: $red-light; color: $red; border: 1px solid rgba($red, 0.25); } &--empty { background: $gray-50; color: $gray-500; border: 1px dashed $gray-200; fa-icon { color: $primary; margin-bottom: 4px; } h4 { margin: 0; font-size: 15px; font-weight: 600; color: $gray-900; } p { margin: 0; font-size: 12px; } } } /* ---------- Batch groups ---------- */ .cv-groups { display: flex; flex-direction: column; gap: 10px; } .cv-group { background: $white; border: 1px solid $gray-200; border-radius: 10px; overflow: hidden; transition: border-color 0.15s, box-shadow 0.15s; &:hover { border-color: rgba($primary, 0.3); } &--open { border-color: $primary-light; box-shadow: 0 2px 10px rgba($primary, 0.05); } &__head { width: 100%; padding: 14px 18px; background: $gray-50; border: none; display: flex; align-items: center; justify-content: space-between; gap: 14px; cursor: pointer; font-family: inherit; text-align: left; &:hover { background: $gray-100; } } &__left { display: flex; align-items: center; gap: 14px; flex: 1; min-width: 0; } &__chev { color: $primary; font-size: 14px; flex-shrink: 0; } &__date-pill { display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; background: $primary-light; color: $primary-dark; border-radius: 10px; font-size: 12px; font-weight: 700; fa-icon { color: $primary; font-size: 11px; } } &__summary { font-size: 12px; color: $gray-700; display: flex; gap: 8px; flex-wrap: wrap; strong { color: $gray-900; font-weight: 700; } } &__sep { color: $gray-200; } &__right { display: flex; gap: 6px; flex-shrink: 0; } &__body { background: $white; border-top: 1px solid $gray-200; overflow-x: auto; } } .cv-pill { display: inline-flex; align-items: center; gap: 5px; padding: 4px 10px; border-radius: 12px; font-size: 11px; font-weight: 700; fa-icon { font-size: 10px; } &--green { background: $green-light; color: $teal-900; border: 1px solid rgba($green, 0.25); } &--amber { background: $amber-light; color: $amber; border: 1px solid rgba($amber, 0.3); } &--red { background: $red-light; color: $red; border: 1px solid rgba($red, 0.3); } } /* ---------- SFTP logs ---------- */ .cv-sftp-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; padding: 16px 20px 4px; } .cv-sftp-kpi { display: flex; align-items: center; gap: 12px; padding: 14px 16px; border-radius: 12px; border: 1px solid $gray-200; background: $white; &__icon { width: 40px; height: 40px; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 18px; flex-shrink: 0; } &__value { font-size: 20px; font-weight: 700; color: $gray-900; line-height: 1.1; } &__label { font-size: 11px; color: $gray-500; text-transform: uppercase; letter-spacing: 0.4px; margin-top: 2px; } &--green { border-color: rgba($green, 0.3); background: linear-gradient(180deg, $green-light, $white); .cv-sftp-kpi__icon { background: $green; color: $white; } } &--red { border-color: rgba($red, 0.3); background: linear-gradient(180deg, $red-light, $white); .cv-sftp-kpi__icon { background: $red; color: $white; } } &--amber { border-color: rgba($amber, 0.3); background: linear-gradient(180deg, $amber-light, $white); .cv-sftp-kpi__icon { background: $amber; color: $white; } } } .cv-sftp-logs { display: flex; flex-direction: column; gap: 10px; padding: 12px 20px 20px; } .cv-sftp-log { display: flex; align-items: flex-start; gap: 14px; padding: 14px 16px; border: 1px solid $gray-200; border-left-width: 4px; border-radius: 10px; background: $white; transition: background 0.15s, box-shadow 0.15s; &:hover { background: #fafbfc; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04); } &--success { border-left-color: $green; } &--failed { border-left-color: $red; } &__icon { width: 36px; height: 36px; border-radius: 10px; display: flex; align-items: center; justify-content: center; background: $gray-100; color: $gray-500; font-size: 16px; flex-shrink: 0; } &--success .cv-sftp-log__icon { background: $green-light; color: $green; } &--failed .cv-sftp-log__icon { background: $red-light; color: $red; } &__body { flex: 1; min-width: 0; } &__head { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 8px; } &__bid { font-family: 'SF Mono', Consolas, monospace; font-size: 13px; font-weight: 700; color: $primary; fa-icon { font-size: 11px; margin-right: 4px; } } &__time { font-size: 11px; color: $gray-500; margin-left: auto; fa-icon { font-size: 10px; margin-right: 4px; } } &__meta { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 8px 16px; font-size: 12px; > div { display: flex; flex-direction: column; gap: 2px; min-width: 0; } } &__label { font-size: 10px; text-transform: uppercase; letter-spacing: 0.4px; color: $gray-500; font-weight: 600; } &__value { color: $gray-900; font-weight: 500; word-break: break-all; &--mono { font-family: 'SF Mono', Consolas, monospace; font-size: 11px; } } &__remarks { margin-top: 8px; padding: 8px 10px; border-radius: 8px; background: $gray-50; border: 1px solid $gray-200; font-size: 12px; color: $gray-700; display: flex; align-items: flex-start; gap: 8px; fa-icon { font-size: 12px; color: $gray-500; margin-top: 2px; } &--err { background: $red-light; border-color: rgba($red, 0.3); color: $red; fa-icon { color: $red; } } } &__actions { display: flex; align-items: center; flex-shrink: 0; } } /* ---------- Batches table ---------- */ .cv-batches { width: 100%; border-collapse: collapse; font-size: 12px; thead tr { background: $gray-50; } th { text-align: left; padding: 10px 14px; font-size: 10px; font-weight: 700; color: $gray-500; text-transform: uppercase; letter-spacing: 0.4px; white-space: nowrap; } td { padding: 12px 14px; border-top: 1px solid $gray-100; color: $gray-900; vertical-align: middle; } tbody tr:hover { background: #f5f8fc; } &__num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; } &__actions { text-align: right; width: 100px; } &__bid { font-family: 'SF Mono', Consolas, monospace; font-size: 12px; font-weight: 600; color: $primary; white-space: nowrap; fa-icon { color: $primary; margin-right: 6px; font-size: 11px; } } &__file { color: $gray-700; fa-icon { color: $primary; margin-right: 6px; font-size: 11px; } span { word-break: break-all; max-width: 280px; display: inline-block; vertical-align: middle; } } } .cv-action-btn { width: 32px; height: 32px; border-radius: 8px; border: 1px solid $gray-200; background: $white; color: $gray-700; cursor: pointer; margin-left: 4px; transition: all 0.15s; fa-icon { font-size: 12px; } &:hover { background: $primary-light; color: $primary; border-color: $primary; } &--primary { background: $primary; color: $white; border-color: $primary; &:hover { background: #1557b5; color: $white; } } } /* ---------- SFTP placeholder ---------- */ .cv-placeholder { padding: 30px 24px; text-align: center; &__icon { width: 64px; height: 64px; border-radius: 16px; background: $white; border: 1px solid $primary-light; color: $primary; display: flex; align-items: center; justify-content: center; font-size: 28px; margin: 0 auto 12px; box-shadow: 0 4px 14px rgba($primary, 0.1); } h4 { margin: 0 0 6px; font-size: 15px; font-weight: 700; color: $gray-900; } p { margin: 0 auto 14px; font-size: 12px; color: $gray-700; max-width: 480px; line-height: 1.55; } &__tags { display: flex; justify-content: center; gap: 8px; flex-wrap: wrap; } } .cv-chip { padding: 5px 12px; background: $white; border: 1px solid $gray-200; border-radius: 16px; font-size: 11px; font-weight: 600; color: $gray-700; } /* ---------- Manifest modal ---------- */ .cv-modal { position: fixed; inset: 0; background: rgba(15, 25, 45, 0.55); backdrop-filter: blur(3px); z-index: 100; display: flex; align-items: center; justify-content: center; padding: 20px; &__card { background: $white; border-radius: 16px; width: 100%; max-width: 720px; max-height: 90vh; display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 24px 60px rgba(0, 0, 0, 0.25); } &__header { display: flex; align-items: center; justify-content: space-between; padding: 18px 22px; border-bottom: 1px solid $gray-100; } &__title { display: flex; align-items: center; gap: 10px; font-size: 16px; font-weight: 700; color: $gray-900; fa-icon { width: 34px; height: 34px; border-radius: 10px; background: linear-gradient(135deg, $primary, #4285f4); color: $white; display: flex; align-items: center; justify-content: center; font-size: 14px; box-shadow: 0 3px 10px rgba($primary, 0.3); } } &__close { width: 32px; height: 32px; border-radius: 8px; border: 1px solid $gray-200; background: $white; color: $gray-500; cursor: pointer; &:hover { color: $red; border-color: $red; background: $red-light; } } &__body { padding: 20px 22px; overflow-y: auto; flex: 1; } &__footer { padding: 16px 22px; border-top: 1px solid $gray-100; display: flex; justify-content: flex-end; gap: 10px; background: $gray-50; } } .cv-manifest-head { background: linear-gradient(135deg, $primary-light, $green-light); border: 1px solid rgba($primary, 0.12); border-radius: 10px; padding: 16px 18px; margin-bottom: 16px; &__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px 20px; } &__grid-span { grid-column: 1 / -1; } /* Force stacked layout inside each field */ > .cv-manifest-head__grid > div { display: flex; flex-direction: column; gap: 4px; min-width: 0; .cv-kpi__label { display: block; font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; color: $teal-700; opacity: 0.85; margin: 0; } .cv-kpi__value { display: block; font-size: 13px; font-weight: 700; color: $gray-900; word-break: break-word; line-height: 1.35; &--mono { font-family: 'SF Mono', 'Cascadia Code', Consolas, monospace; font-size: 11px; color: $primary-dark; letter-spacing: 0.2px; word-break: break-all; } } .cv-pill { align-self: flex-start; } } } .cv-manifest-title { font-size: 11px; font-weight: 700; color: $gray-500; text-transform: uppercase; letter-spacing: 0.5px; margin: 10px 0 8px; display: inline-flex; align-items: center; gap: 6px; fa-icon { color: $primary; font-size: 12px; } } .cv-manifest-table-wrap { max-height: 320px; overflow-y: auto; border: 1px solid $gray-200; border-radius: 10px; } .cv-manifest-table { width: 100%; border-collapse: collapse; font-size: 11px; thead tr { background: $gray-50; position: sticky; top: 0; z-index: 1; } th { text-align: left; padding: 8px 12px; font-size: 9px; font-weight: 700; color: $gray-500; text-transform: uppercase; letter-spacing: 0.4px; white-space: nowrap; border-bottom: 1px solid $gray-200; } td { padding: 8px 12px; border-bottom: 1px solid $gray-100; vertical-align: middle; } tbody tr:last-child td { border-bottom: none; } tbody tr:hover { background: #f5f8fc; } } .cv-th-c { text-align: center !important; width: 38px; } .cv-th-r { text-align: right !important; } .cv-td-c { text-align: center; } .cv-td-r { text-align: right; } .cv-manifest-client { display: flex; flex-direction: column; gap: 2px; strong { font-size: 12px; font-weight: 600; color: $gray-900; } } .cv-manifest-cif { font-size: 10px; color: $gray-500; font-family: 'SF Mono', Consolas, monospace; fa-icon { font-size: 8px; margin-right: 2px; } } .cv-dot { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 50%; font-size: 9px; font-weight: 700; &--ok { background: $green-light; color: $green; border: 1px solid rgba($green, 0.3); } &--miss { background: $red-light; color: $red; border: 1px solid rgba($red, 0.3); } } .cv-manifest-size { font-size: 11px; font-weight: 600; color: $gray-700; font-family: 'SF Mono', Consolas, monospace; white-space: nowrap; } .cv-manifest-row--complete { background: rgba($green, 0.03); } /* ---------- Responsive ---------- */ @media (width <= 1100px) { .cv-kpis { grid-template-columns: repeat(3, 1fr); } } @media (width <= 700px) { .cv-kpis { grid-template-columns: repeat(2, 1fr); } .cv-filters__grid { grid-template-columns: 1fr; } .cv-manifest-head__grid { grid-template-columns: 1fr; } }