/** * 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: #0f766e; .pm-container { // Wider than the usual form page: the extra width is what keeps this many fields off a // second screen. max-width: 1280px; margin: 0 auto; padding: 12px 16px 20px; } .pm-header { display: flex; align-items: center; gap: 14px; margin-bottom: 10px; &__title { margin: 0; font-size: 18px; font-weight: 500; } } .pm-back { color: $primary; } .pm-card { background: var(--md-sys-color-surface, #fff); border-radius: 8px; box-shadow: 0 2px 8px rgb(0 0 0 / 8%); } .pm-tabs { ::ng-deep .mat-mdc-tab-body-wrapper { min-height: 300px; } } .pm-tab-content { padding: 20px 24px; } .pm-section { padding: 16px 0; border-bottom: 1px solid rgb(0 0 0 / 8%); &:last-of-type { border-bottom: none; } &__header { display: flex; align-items: center; // The subtitle sits beside the title where there is room and drops below it where there is not. flex-wrap: wrap; gap: 2px 10px; margin-bottom: 16px; i { color: $primary; } h3 { margin: 0; font-size: 16px; font-weight: 600; // Held at its natural width: letting it shrink breaks a two-word heading onto three lines. flex: 0 0 auto; white-space: nowrap; } } } .pm-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 2px 18px; align-items: start; } /* * Label to the left of its field, the way the screen this replaces laid them out. A stacked label * costs a whole row of height per field, and with 60-odd fields that is the difference between an * operator seeing the form at once and scrolling through three screens of it. */ .pm-f { display: grid; grid-template-columns: 104px minmax(0, 1fr); align-items: start; column-gap: 7px; &--wide { grid-column: span 2; } } .pm-f-lbl { font-size: 11.5px; line-height: 1.25; text-align: right; color: rgb(0 0 0 / 68%); padding-top: 7px; // Required marker, in the same red the legacy screen used. b { color: #c1121f; font-weight: 400; margin-left: 2px; } } .pm-field { width: 100%; } .pm-checkbox-field { display: flex; align-items: center; height: 56px; } .pm-radio-group { display: flex; align-items: center; gap: 16px; height: 56px; } .pm-add-nominee { color: $primary; height: fit-content; align-self: center; } /* * The running total of the shares entered, beside the button that adds another. Reads as ordinary * text while the split still adds up and turns to the warning colour when it does not, so the clerk * sees the state of the whole nomination without having to try to save it. */ .pm-share-total { align-self: center; margin-left: 12px; font-size: 13px; color: rgb(0 0 0 / 60%); } .pm-share-total-bad { color: #b3261e; font-weight: 500; } .pm-empty { color: rgb(0 0 0 / 50%); font-size: 14px; margin: 0 0 8px; } /* * One nominee, laid out as fields that wrap rather than columns that must all fit. * * A fixed column per field only works while the count is fixed, and it is not - the Share % field * appears and disappears with the split mode, and a tenth column pushed the remove button onto a * line of its own. Each field instead states the width it needs to stay readable and the row breaks * where it runs out of space, so nothing is squeezed and nothing is orphaned. */ .pm-nominee-row { display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: start; padding: 12px 0; border-top: 1px dashed rgb(0 0 0 / 10%); &:first-of-type { border-top: none; } /* Names and addresses need room; a date, Yes/No or a percentage does not. */ .pm-f { flex: 1 1 170px; min-width: 0; } .pm-f--date { flex: 0 1 140px; } .pm-f--tight { flex: 0 1 100px; } } .pm-remove-nominee { color: #b91c1c; margin-top: 8px; } .pm-action-bar { display: flex; justify-content: flex-end; gap: 12px; padding: 16px 24px; border-top: 1px solid rgb(0 0 0 / 8%); } .pm-callout { display: flex; align-items: center; gap: 10px; margin: 0 24px; padding: 12px 16px; background: rgb(185 28 28 / 8%); border: 1px solid rgb(185 28 28 / 25%); border-radius: 6px; color: #b91c1c; font-size: 0.9rem; } @media (width <= 1000px) { .pm-grid { grid-template-columns: repeat(2, 1fr); } } /* Resolved name shown under a Client / Agent / Guardian id, as the legacy screen did in red. */ .pm-hint--found { color: #15803d; font-weight: 500; } .pm-hint--missing { color: #b91c1c; font-weight: 500; } /* Explains why a block of fields is absent, so the screen does not just look unfinished. */ .pm-note { margin: 4px 0 0; font-size: 0.8rem; color: rgb(0 0 0 / 55%); font-style: italic; } .pm-closed-badge { margin-left: 12px; padding: 3px 11px; border-radius: 11px; font-size: 0.72rem; font-weight: 500; background: rgb(0 0 0 / 7%); color: rgb(0 0 0 / 60%); } /* Says whose details a block of fields is for, so the screen explains itself. */ .pm-section__sub { flex: 1 1 auto; min-width: 0; font-size: 0.78rem; font-weight: 400; line-height: 1.45; color: rgb(0 0 0 / 55%); } .pm-search-ic { color: rgb(0 0 0 / 38%); font-size: 0.85rem; } /* * Money reads right to left, so a column of figures only lines up when it is right-aligned; the * tabular figures keep every digit the same width so the decimal points stack. */ input.pm-money { text-align: right; font-variant-numeric: tabular-nums; } /* One row of a Client / Sub Type search list: the id, the name, and where it belongs. */ .pm-opt { display: flex; align-items: baseline; gap: 10px; overflow: hidden; } /* The "there are more" footer row. Quieter than a real option, since it is not one. */ .pm-opt-more { font-size: 0.75rem; font-style: italic; opacity: 0.75; } .pm-opt-id { flex: 0 0 auto; min-width: 52px; font-family: ui-monospace, 'SF Mono', 'Cascadia Mono', monospace; font-size: 0.78rem; color: var(--pl-accent, #b45309); } /* The name is the reason the row exists, so it gets whatever width is going and is the last thing to be cut. Before this the branch was fixed-width and the name carried the ellipsis, so in the narrow panel every customer read as a single letter. */ .pm-opt-main { flex: 1 1 auto; min-width: 8rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .pm-opt-sub { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.75rem; color: rgb(0 0 0 / 50%); } /* * Dense data-entry layout. * * The screen this replaces fitted the whole form on one page - an officer opening accounts all day * reads it at a glance and never scrolls. Material's default field height and spacing turn the same * 56 fields into three screens' worth, so the whole card is tightened: shorter fields, smaller type, * and just enough room under each field for the hint that names the client or agent it resolved. */ /* * With the label moved outside, the box only has to hold the value - so it loses the height Material * reserves for a floating label, and the form fits a screen instead of three. */ .pm-card { ::ng-deep { .mat-mdc-form-field { font-size: 12.5px; } .mat-mdc-form-field-infix { min-height: 26px; padding-top: 3px !important; padding-bottom: 3px !important; border-top: 0; } .mat-mdc-text-field-wrapper { padding-left: 8px; padding-right: 8px; } .mat-mdc-input-element, .mat-mdc-select-value-text { font-size: 12.5px; } // Room for one line of hint - the resolved client/agent name that confirms the right record. .mat-mdc-form-field-subscript-wrapper { height: 14px; min-height: 14px; } .mat-mdc-form-field-hint { font-size: 10.5px; line-height: 14px; } // Suffix icons and the datepicker toggle default to a 48px touch target, which reopens all the // height just saved. .mat-mdc-icon-button.mat-mdc-button-base { width: 26px; height: 26px; padding: 3px; } .mat-mdc-form-field-icon-suffix { padding-left: 2px; .mat-datepicker-toggle svg { width: 15px; height: 15px; } } .mat-mdc-tab-body-wrapper { min-height: 0; } } } .pm-tab-content { padding: 8px 16px; } /* * Blocks drawn the way the screen this replaces drew them: a hairline between groups of fields, * with the group's name as a quiet caption above it rather than a heading bar of its own. An * operator who has filled this form a hundred times navigates by field position; one filling their * first still gets told which block is which. */ .pm-section { padding: 8px 0 2px; border-bottom: 1px solid rgb(0 0 0 / 11%); &__header { margin-bottom: 6px; gap: 0 10px; // Decoration the legacy screen did without, and the row is tighter for losing it. i { display: none; } h3 { font-size: 11px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: $primary; } } } .pm-section__sub { font-size: 0.72rem; color: rgb(0 0 0 / 45%); } .pm-grid { gap: 0 12px; } .pm-checkbox-field, .pm-radio-group { height: 28px; ::ng-deep label { font-size: 12.5px; } } // The nominee grid is its own row of fields, so its labels sit above rather than beside - there is // no room for a label column eight fields across. .pm-nominee-row { gap: 0 10px; padding: 3px 0; .pm-f { grid-template-columns: minmax(0, 1fr); row-gap: 1px; } .pm-f-lbl { text-align: left; padding-top: 0; font-size: 10.5px; } } .pm-note { margin: 0; font-size: 0.74rem; } .pm-action-bar { padding: 10px 18px; } /* The customer's real deposit account. Not a form field - nothing here is typed, it is what the bank's books say - so it reads as a fact rather than sitting in an input box pretending to be one. */ .pm-account { display: flex; flex-direction: column; gap: 2px; padding: 3px 0; min-height: 26px; justify-content: center; } .pm-account-no { font-family: ui-monospace, 'SF Mono', 'Cascadia Mono', monospace; font-size: 0.85rem; letter-spacing: 0.02em; } .pm-account-meta { font-size: 0.75rem; color: rgb(0 0 0 / 55%); } .pm-account-live { color: #15803d; font-weight: 500; } /* Said plainly: this party has no account behind it, which is a real gap, not a blank field. */ .pm-account-missing { font-size: 0.75rem; font-style: italic; color: #9b2c2c; } /* Something the branch has to do, rather than something that has gone wrong - so it reads as an instruction in the warning colour, not an error in red like the closed-account notice. */ .pm-callout--action { background: rgb(180 83 9 / 8%); border-color: rgb(180 83 9 / 25%); color: #b45309; }