/* ==========================================================================
   cs-forms.css - the shared insert/edit form chrome
   Source of truth: resources\claude-design-project-files\New Page Insert Edit Form.dc.html
   Added 2026-09-08.

   WHAT THIS STYLES
   One chain renders the insert/edit form on EVERY page and in EVERY mode:

     forms/form.tpl                        the <form>, all modes
       forms/form_fields.tpl
         forms/form_sheet_layout.tpl       groups  -> .cs-form-view
           forms/form_field.tpl
             forms/form_edit_field.tpl
               forms/form_field_layout.tpl one field -> .form-group.cs-form-grid-item
                 forms/field_label.tpl     -> .control-label
                 editors/<name>.tpl        29 editors
       forms/form_footer.tpl

   ...wrapped by one of four chromes:
     forms/page_form.tpl          full-page insert/edit   -> .cs-form-page
     forms/modal_form.tpl         modal insert/edit       -> .cs-form-modal
     forms/inline_form.tpl        inline row insert/edit  -> .cs-form-inline
     forms/single_field_form.tpl  single-field inline     -> .cs-form-single

   WHY GEOMETRY *AND* TYPE ARE IN px
   [D-041] says "geometry in px, type in rem matched to the sibling screen". The
   rem half of that rule exists so sibling screens agree with each other - and the
   sibling here is the form chain itself, which was already authored in px
   (form_field_layout.tpl shipped `font-size:10.5px` long before this file).
   cornerstone.css sets `html { font-size: 82% }`, so 1rem is ~13.1px, not 16px,
   while the design file is authored at a 16px base. Expressing this design's type
   in rem would render it ~18% small - which is the exact failure D-041 was written
   to stop. px throughout is therefore the rule-following choice here, not a
   deviation from it.

   COLOURS ARE TOKENS, NOT HEX (AGENTS.md s3)
   The design file's palette maps 1:1 onto the existing --cs-* set:
     #f6f8fa --cs-gray-50   #eef1f5 --cs-gray-100  #e1e6ec --cs-gray-200
     #cdd5de --cs-gray-300  #9aa7b4 --cs-gray-400  #6b7986 --cs-gray-500
     #34424e --cs-gray-700  #102b3b --cs-gray-900/--cs-navy
     #0171df --cs-blue      #0160c0 --cs-blue-600  #e13b3b --cs-red
   One deviation: the design's field label is #8a97a3, which has no token. It uses
   --cs-gray-400 (#9aa7b4, one step lighter), matching what form_field_layout.tpl
   already shipped, rather than introducing a hex.

   TWO THINGS DELIBERATELY *NOT* COPIED FROM THE DESIGN FILE
   1. `.date-ip .cal { pointer-events: none }`. In the design that icon is a static
      decoration. In the app it is the datetimepicker's toggle button
      (.datepickerbutton) - the picker binds its open handler to exactly that
      element. pointer-events:none would re-break the picker that was fixed in the
      same session. See the .cs-form-view .datepickerbutton rule below.
   2. The design's own column/grouping choices. Per Rob 2026-09-08 those are
      authored per page; only the styling, padding and margins are taken.

   DO NOT REMOVE .form-group FROM THE PER-FIELD WRAPPER
   pgui.editors/custom.js resolves a field's container with
   closest('.form-group'). Without it, closest() walks up to the group <fieldset>
   and a single editors.X.setVisible(false) hides the whole group. The comment in
   form_field_layout.tpl says the same thing; it is repeated here because this file
   is what tempts someone to rename the class.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. SHELL - the save/cancel bar and the record card
   -------------------------------------------------------------------------- */

/* VERTICAL padding only. The design file pads the page 28px on all four sides, but in the
   app the blue page banner is already flush to the app container's own left/right inset -
   so a horizontal pad here DOUBLE-insets the form and the card no longer lines up with the
   banner above it. Measured on sales_orders.php: banner 78 -> 1883, card 106 -> 1855, i.e.
   28px out on both sides. Rob, 2026-09-08: "this offsets the X and misaligns the form with
   the page title bar (blue one) so its not flush to it". */
.cs-form-page {
    padding: 28px 0;
    background: var(--cs-gray-50);
}

/* Save / Cancel toolbar. Rob 2026-09-08: the button-group radius in the design
   file is a known artefact - not reproduced. */
.cs-form-actions {
    display: flex;
    gap: 8px;
    margin-bottom: 16px;
}

.cs-form-actions--bottom {
    margin-top: 16px;
    margin-bottom: 0;
}

.cs-form-actions .btn {
    border-radius: 8px;
    padding: 8px 22px;
    font-weight: 600;
}

.cs-form-actions .btn-group .btn {
    border-radius: 0;
}

.cs-form-actions .btn-group .btn:first-child {
    border-top-left-radius: 8px;
    border-bottom-left-radius: 8px;
}

.cs-form-actions .btn-group .btn:last-child {
    border-top-right-radius: 8px;
    border-bottom-right-radius: 8px;
    padding: 8px 10px;
}

.cs-form-card {
    background: #fff;
    border: 1px solid var(--cs-gray-200);
    border-radius: 12px;
}

.cs-form-card-head {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 56px;
    padding: 0 24px;
    border-bottom: 1px solid var(--cs-gray-100);
}

.cs-form-card-head .cs-form-ref {
    color: var(--cs-gray-400);
    font-size: 13px;
}

.cs-form-card-head .cs-form-title {
    font-family: "Poppins", sans-serif;
    font-weight: 700;
    font-size: 15px;
    color: var(--cs-navy);
}

.cs-form-card-body {
    padding: 26px 30px;
}

/* --------------------------------------------------------------------------
   2. GROUPS - eyebrow, group title, 26px rhythm with a hairline rule
   -------------------------------------------------------------------------- */

.cs-form-view .cs-form-group {
    width: 100%;
    padding: 0 0 26px 0;
    margin: 0 0 26px 0;
    border: 0;
    border-bottom: 1px solid var(--cs-gray-100);
    background: transparent;
}

.cs-form-view .cs-form-group:last-child {
    padding-bottom: 0;
    margin-bottom: 0;
    border-bottom: 0;
}

.cs-form-group-head {
    margin: 0 0 16px 0;
}

.cs-form-eyebrow {
    font-family: "Poppins", sans-serif;
    text-transform: uppercase;
    letter-spacing: .08em;
    font-size: 11px;
    font-weight: 700;
    color: var(--color-primary);
    margin-bottom: 4px;
}

.cs-form-grouptitle {
    font-family: "Poppins", sans-serif;
    font-size: 15px;
    font-weight: 600;
    color: var(--cs-navy);
    letter-spacing: normal;
}

/* --------------------------------------------------------------------------
   3. ROWS AND FIELDS - 20px gutters, 10.5px uppercase labels
   -------------------------------------------------------------------------- */

/* The groups are laid out with CSS grid, so the root does not need Bootstrap's .row - and
   .row's negative gutter margins (-9.84px each side) ATE the container's padding wherever
   this form is nested. In the modal that left 20px to the dialog edge instead of the 30px
   the body declares. Rob, 2026-09-08: "its too close to the edge of the modal in the x
   axis". The class is dropped in form_sheet_layout.tpl; this neutralises it for any other
   template that carries .row on the same element (the purchasing form, for instance). */
.cs-form-view {
    margin-left: 0;
    margin-right: 0;
}

.cs-form-view .row-group {
    display: grid !important;
    gap: 20px;
}

.cs-form-view .cs-form-grid-row {
    display: grid;
    column-gap: 20px;
    row-gap: 20px;
}

/* The field wrapper still carries a Bootstrap col-* class (form_field_layout.tpl
   emits col-{width} for the non-grid path). Inside a CSS grid row that width would
   fight grid-template-columns, so it is neutralised here. This replaces the inline
   style="width:auto;max-width:none;padding-right:0;padding-left:0" that the template
   used to emit - same declarations, moved, not dropped. */
.cs-form-view .form-group.cs-form-grid-item {
    width: auto;
    max-width: none;
    margin-bottom: 0;
    padding-left: 0;
    padding-right: 0;
}

/* The editor's own wrapper (form_edit_field.tpl .col-input) keeps its max-width
   from the column definition; the value row must not add another. */
.cs-form-view .cs-form-control-wrap {
    font-size: 14px;
    color: var(--text-strong);
}

.cs-form-view .control-label,
.cs-form-view .cs-form-label {
    display: block;
    font-family: "Poppins", sans-serif;
    text-transform: uppercase;
    letter-spacing: .06em;
    font-size: 10.5px;
    font-weight: 700;
    color: var(--cs-gray-400);
    margin-bottom: 8px;
    line-height: 1.4;
}

/* field_label.tpl nests a <label class="control-label"> inside the wrapper div,
   so the inner one must not re-apply the block margin. */
.cs-form-view .control-label .control-label {
    margin-bottom: 0;
}

.cs-form-view .required-mark {
    color: var(--cs-red);
    font-weight: 700;
    margin-left: 2px;
}

.cs-form-footnote {
    margin-top: 12px;
    font-size: 12px;
    color: var(--text-muted);
}

/* --------------------------------------------------------------------------
   4. CONTROLS - inputs, selects, textareas
   -------------------------------------------------------------------------- */

.cs-form-view .form-control,
.cs-form-view .form-select {
    border: 1.5px solid var(--cs-gray-300);
    border-radius: 10px;
    padding: 10px 14px;
    font-size: 14.5px;
    color: var(--cs-navy);
    background-color: #fff;
    box-shadow: none;
}

.cs-form-view .form-control:focus,
.cs-form-view .form-select:focus {
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px rgba(1, 113, 223, .15);
    outline: 0;
}

.cs-form-view .form-control::placeholder {
    color: var(--cs-gray-400);
    opacity: 1;
}

.cs-form-view .form-control:disabled,
.cs-form-view .form-control[readonly],
.cs-form-view .form-select:disabled {
    background-color: #f1f4f7;
    color: var(--cs-gray-700);
    opacity: 1;
}

.cs-form-view textarea.form-control {
    resize: vertical;
    min-height: 96px;
}

.cs-form-view .form-control-plaintext {
    padding: 10px 0;
    font-size: 14.5px;
    color: var(--cs-navy);
}

/* Checkboxes sit on their own row under the label, not inline with it. */
.cs-form-view .input-checkbox {
    padding-top: 2px;
}

.cs-form-view .form-check-input {
    width: 18px;
    height: 18px;
    border-color: var(--cs-gray-300);
}

.cs-form-view .form-check-input:checked {
    background-color: var(--color-primary);
    border-color: var(--color-primary);
}

.cs-form-view .form-check-input:focus {
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px rgba(1, 113, 223, .15);
}

/* --------------------------------------------------------------------------
   4b. ONE CONTROL HEIGHT
   Measured in the browser 2026-09-08, before this block existed, on one form:
       plain input / select   45px
       select2 lookup combo   33px
       date+time input-group  35px
   Three heights on the same screen, because each control type reaches its size a
   different way - the input from padding, select2 from its own vendor CSS, the
   input-group from its child. The design has ONE control height, so it is stated
   here explicitly rather than left to emerge from whatever each vendor does.
   -------------------------------------------------------------------------- */

.cs-form-view {
    --cs-form-control-h: 45px;
}

/* The height goes on the OUTERMOST box of each control type only. Setting it on an
   inner element as well makes that element's own borders and padding add on top of
   the floor - which is what left a 4px spread (45 / 47 / 49) on the first attempt. */
.cs-form-view .form-control,
.cs-form-view .form-select,
.cs-form-view .input-group,
.cs-form-view .select2-container {
    min-height: var(--cs-form-control-h);
}

/* ...so the two composite controls hand the height DOWN rather than re-declaring it.
   DESCENDANT, not child: editors/combobox.tpl nests the control inside an extra
   <div class="col">, so a `>` selector misses it and the select2 keeps both its own
   border and its own 45px floor inside an already-bordered group - which measured
   47px against 45px everywhere else. */
.cs-form-view .input-group .form-control,
.cs-form-view .input-group .form-select,
.cs-form-view .input-group .select2-container {
    min-height: 0;
    height: auto;
}

/* The select2 box carries its own floor rather than a percentage of its parent.
   `height:100%` was wrong here: inside an .input-group the container's min-height is
   zeroed (below), so there is no definite parent height for the percentage to resolve
   against and the box collapsed to the text line - 21px inside a 45px wrapper, with
   the text jammed against the top. Rob, 2026-09-08: "the select2 fields look off on
   line height". A fixed floor, minus the wrapper's 1.5px borders, fills the control on
   BOTH paths - standalone and nested - without depending on the parent. */
.cs-form-view .select2-container .select2-choice {
    min-height: calc(var(--cs-form-control-h) - 3px);
    height: auto;
    line-height: 1.4;
}

/* textareas grow, so the shared height is a floor they must not inherit as a cap */
.cs-form-view textarea.form-control {
    min-height: 96px;
}

/* select2 (v3) builds its own box inside a .form-control container: the container
   draws the border and the inner <a> draws the text, so the padding and line-height
   have to be set on the inner element or the combo sits 12px shorter than a text
   input beside it. */
.cs-form-view .select2-container .select2-choice {
    display: flex;
    align-items: center;
    padding: 0 14px;
    border: 0;
    border-radius: 10px;
    background: transparent;
    box-shadow: none;
    font-size: 14.5px;
    color: var(--cs-navy);
}

/* select2 v3 absolutely positions the arrow against the choice, so the choice is the
   element that has to be full height for the arrow to sit centred with the text. */
.cs-form-view .select2-container .select2-arrow b {
    background-position: center;
}

/* MULTI-value select2 is a different element - `.select2-choices` (plural), with no
   `.select2-choice` at all - so it needs its own rule or it collapses the same way
   (measured 26px inside a 45px box). It grows as chips are added, so this is a floor
   with the chips aligned to the top, not a centred single line. */
/* A multi-value control is inherently VARIABLE height - it grows as chips are added - so
   the single-line floor is the wrong target for it. Forcing it made an empty multi-select
   a 45px trough, which on a full-width row (stock_items > Safety is col-12 in the .pgtm)
   reads as an enormous empty box. Rob, 2026-09-08: "the multi select under the safety tab
   ... is way too big". It now sizes to its content and grows naturally.

   NOTE the width there is NOT from this stylesheet - measured with and without the
   .cs-form-view hook it is 1763px either way, straight from the page's own `col-12`
   column spec. Changing that is a .pgtm edit, not a styling one. */
.cs-form-view .select2-container-multi {
    min-height: 0;
}

.cs-form-view .select2-container-multi .select2-choices {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px;
    /* A modest floor, not the full control height and not none. Removing it entirely
       collapsed the box to 8px, because in a flex row select2's search <li> contributes
       no height of its own. 32px is close to select2's own natural 28px and grows from
       there as chips are added. */
    min-height: 32px;
    padding: 3px 9px;
    border: 0;
    border-radius: 10px;
    background: transparent;
}

.cs-form-view .select2-container-multi .select2-choices > li {
    float: none;
    margin: 0;
}

/* select2's search row is a bare <li> with no intrinsic height. As a flex item that makes
   it 0px, and the <input> inside then escapes the box - measured 11px below the bottom
   edge and 17px under the top, which is what clipped the "Please select" placeholder. It
   has to be given real dimensions of its own once the parent is a flex container. */
.cs-form-view .select2-container-multi .select2-choices > li.select2-search-field {
    display: flex;
    align-items: center;
    flex: 1 1 60px;
    min-height: 26px;
}

.cs-form-view .select2-container-multi .select2-search-field input {
    width: 100%;
    height: 26px;
    margin: 0;
    padding: 0;
    line-height: 26px;
    font-size: 14.5px;
}

.cs-form-view .select2-container .select2-choice > .select2-chosen {
    margin-right: 26px;
}

.cs-form-view .select2-container .select2-arrow {
    background: transparent;
    border: 0;
}

/* --------------------------------------------------------------------------
   5. INPUT GROUPS + THE DATE / TIME PICKER
   editors/datetime.tpl and editors/time.tpl share this markup.
   -------------------------------------------------------------------------- */

.cs-form-view .input-group {
    border: 1.5px solid var(--cs-gray-300);
    border-radius: 10px;
    background: #fff;
    overflow: hidden;
    flex-wrap: nowrap;
}

.cs-form-view .input-group:focus-within {
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px rgba(1, 113, 223, .15);
}

/* The control inside an input-group gives its border up to the group. Descendant
   rather than child for the reason given in 4b - combobox.tpl adds a wrapper div. */
.cs-form-view .input-group .form-control,
.cs-form-view .input-group .form-select,
.cs-form-view .input-group .select2-container {
    border: 0;
    border-radius: 0;
    box-shadow: none;
}

.cs-form-view .input-group .form-control:focus,
.cs-form-view .input-group .form-select:focus {
    box-shadow: none;
}

/* the extra wrapper combobox.tpl emits must not eat the group's width */
.cs-form-view .input-group > .col {
    padding: 0;
    min-width: 0;
}

/* The "+" nested-insert button beside a lookup (editors/nested_insert_button.tpl). It shipped
   at 33x31px with a 3px radius against a 42px control - Rob, 2026-09-08: "too small for the
   form". The design file's equivalent is the square accent button on the end of `cs-combo`, so
   it is squared off to the control's own height and given the icon some room. */
.cs-form-view .input-group > .col-auto {
    padding: 0;
}

.cs-form-view .js-nested-insert {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: calc(var(--cs-form-control-h) - 3px);
    height: calc(var(--cs-form-control-h) - 3px);
    padding: 0;
    border: 0;
    border-radius: 10px;
    font-size: 15px;
    line-height: 1;
}

/* butted against the lookup inside a group, only the outer corners round */
.cs-form-view .input-group .js-nested-insert {
    border-radius: 0 10px 10px 0;
}

/* Inside a group the WRAPPER draws the rounded box, so the lookup's own corners must be
   square or its 10px right radius meets the button's flat left edge and reads as a notch
   between two controls that are actually flush (measured gap: -1px). */
.cs-form-view .input-group .select2-container .select2-choice,
.cs-form-view .input-group .select2-container .select2-choices {
    border-radius: 0;
}

.cs-form-view .input-group-text {
    border: 0;
    background: transparent;
    color: var(--cs-gray-400);
    padding: 0 14px;
}

/* The picker's toggle. eonasdan 4.17.37 binds its open handler to
   .datepickerbutton (falling back to BS3's .input-group-addon); the template
   renders BS5's .input-group-text, so before 2026-09-08 nothing was bound and the
   widget could not be opened by any route. It MUST stay clickable - this is the
   design file's `.cal` element, minus its pointer-events:none. */
.cs-form-view .datepickerbutton {
    cursor: pointer;
}

.cs-form-view .datepickerbutton:hover {
    color: var(--cs-navy);
}

/* The date/time wrappers ship a Bootstrap mb-3 that fights the 20px row rhythm. */
.cs-form-view .pgui-date-time-edit.mb-3 {
    margin-bottom: 0 !important;
}

/* --------------------------------------------------------------------------
   6. MODAL CHROME - forms/modal_form.tpl
   The modal itself stays the app's own generator (CS_modal_*); this only sets
   the padding and rhythm of the form inside it.
   -------------------------------------------------------------------------- */

.cs-form-modal .modal-body {
    padding: 26px 30px;
    background: #fff;
}

/* cornerstone.css has `.modal-simple .modal-header + .modal-body { padding-top: 0 }`
   at specificity 0,3,0, which outranks the 0,2,0 rule above and flattened the top of
   every modal form. Matched here at equal specificity, and this file loads second.
   (The white background needed the opposite treatment - `.bg-gray-100` is !important
   in cornerstone.css, so the utility was removed from modal_form.tpl instead of
   being fought here.) */
.cs-form-modal .modal-header + .modal-body {
    padding-top: 26px;
}

.cs-form-modal .modal-header {
    padding: 0 24px;
    height: 56px;
    align-items: center;
}

.cs-form-modal .modal-title {
    font-family: "Poppins", sans-serif;
    font-weight: 700;
    font-size: 15px;
}

.cs-form-modal .modal-footer {
    padding: 14px 24px;
    border-top: 1px solid var(--cs-gray-100);
}

.cs-form-modal .modal-footer .btn {
    border-radius: 8px;
    font-weight: 600;
}

/* A TABBED form (forms/form_tabs.tpl, e.g. stock_items) puts a .tab-content between the
   modal body and the fields, and it carries a Bootstrap gutter padding that the untabbed
   path does not - so tabbed modals indented their fields 40px where plain ones indent 30px.
   The modal body already owns that padding; the tab wrapper must not add a second helping. */
.cs-form-modal .tab-content,
.cs-form-page .tab-content {
    padding-left: 0;
    padding-right: 0;
}

/* Inside a modal the form gets NO card of its own - the modal dialog is the card,
   and nesting a second bordered surface inside it double-frames the fields. The
   modal body supplies the 26px/30px padding the design gives the card body. */
.cs-form-modal .cs-form-view {
    background: transparent;
    border: 0;
    padding: 0;
}

/* --------------------------------------------------------------------------
   7. INLINE CHROME - forms/inline_form.tpl and forms/single_field_form.tpl
   These render inside a grid row, so they are tighter than the page form.
   -------------------------------------------------------------------------- */

.cs-form-inline {
    padding: 18px 22px;
    background: var(--cs-gray-50);
    border: 1px solid var(--cs-gray-200);
    border-radius: 12px;
}

.cs-form-inline .cs-form-view .cs-form-group {
    padding-bottom: 16px;
    margin-bottom: 16px;
}

.cs-form-inline .cs-form-view .row-group,
.cs-form-inline .cs-form-view .cs-form-grid-row {
    gap: 14px;
    column-gap: 16px;
    row-gap: 14px;
}

.cs-form-inline .cs-form-actions,
.cs-form-single .cs-form-actions {
    margin-top: 14px;
    margin-bottom: 0;
    justify-content: flex-end;
}

.cs-form-single {
    padding: 12px 14px;
}

.cs-form-single .cs-form-view .cs-form-group {
    padding-bottom: 0;
    margin-bottom: 0;
    border-bottom: 0;
}

/* --------------------------------------------------------------------------
   Amber alert (P-202): the record saved, but something after the save failed,
   such as an email that did not go. Not an error, so not alert-danger.
   A hook marks its message with <strong class="cs-msg-warning">, which reaches every
   route (AJAX modal, inline, full-page flash) as HTML inside .alert-success, so
   :has() covers them all. cs-tasks.js sets .cs-alert-warning directly.
   The theme's .alert-warning is white on amber, about 2:1, so it is not used.
   -------------------------------------------------------------------------- */
.alert.cs-alert-warning,
.alert.alert-success:has(.cs-msg-warning) {
    color: var(--text-strong);
    background-color: var(--status-warning);
    border-color: var(--status-warning);
}

.alert.cs-alert-warning a,
.alert.alert-success:has(.cs-msg-warning) a {
    color: var(--text-strong);
    text-decoration: underline;
}

/* The theme's close icon on .alert-success is a white SVG. */
.alert.alert-success:has(.cs-msg-warning) .btn-close {
    filter: brightness(0);
}
