/* ================================================================================================
   SYNCFUSION DENSITY OVERRIDES  —  pass 1: text only
   ================================================================================================

   WHY THIS FILE EXISTS SEPARATELY FROM app.css.

   Display Density worked on Bootstrap form controls and did nothing whatsoever to Syncfusion
   ones. Measured on 2026-09-20 by injecting a Syncfusion-shaped input and reading the computed
   style at each density:

       .e-input            14px   14px   14px     (tiny / compact / comfortable)
       .e-input-group      32px   32px   32px
       .e-float-text       12px   12px   12px

   Identical. Nothing moved. And Syncfusion is not a minority of the form surface here - roughly
   891 Syncfusion inputs against 88 plain .form-control. So on a real CM form the LABEL shrank
   and the field beside it did not, which reads as "density does nothing", or worse, as a
   mismatched caption over a full-size box.

   The cause is load order. App.razor links bootstrap5.css LAST, after app.css, so a rule written
   in app.css loses an equal-specificity tie to the theme. This file is linked after the theme,
   and every rule is additionally prefixed with html[data-density] so it still wins if anybody
   ever reorders those links. Belt and braces, deliberately: a silent reversion to "density does
   nothing" is exactly the bug this is fixing.

   ------------------------------------------------------------------------------------------------
   THE ONE KNOB — read this before changing anything else.

   --cm-input-font decides how closely Syncfusion fields track the density. It is set to
   var(--cm-ui-font), so they match the labels exactly. That is what was asked for, and it means
   the DEFAULT density changes appearance too: at compact, fields go from Syncfusion's fixed 14px
   to 12.8px, matching their labels for the first time.

   If that turns out to be too small for everyday use, change the ONE line below to a fixed 14px
   and only non-default densities will differ from today. Nothing else in this file needs to move.
   ------------------------------------------------------------------------------------------------

   SCOPE: text size only. Heights, vertical padding and the icon buttons inside input groups are
   pass 2, and they are the ones that actually make rows shorter. Deliberately not attempted here,
   because Syncfusion vertically centres those icon buttons against a fixed 32px group height and
   changing one without the other puts dropdown arrows off-centre. Grids, dialogs and toolbars are
   pass 3.

   TO UNDO: delete this file and remove its <link> from App.razor. Nothing else was touched.
   ================================================================================================ */

:root {
    /* The single knob. See the note above. */
    --cm-input-font: var(--cm-ui-font);

    /* Float labels and helper captions sit one notch under the field, the way Syncfusion's own
       theme has them (12px against 14px).

       THIS WAS calc(var(--cm-input-font) * 0.86) AND IT DID NOT WORK. A calc() over a custom
       property that is itself a var() resolved once and then stayed frozen - measured at 9.632px
       (0.86 x tiny's 11.2px) at every density including comfortable, while every other field
       moved correctly. Caught because the verification pass printed all four densities side by
       side instead of checking one.

       --cm-hint-font is already defined per density and is already exactly one notch below
       --cm-ui-font at every level (0.65/0.7/0.75/0.85 against 0.7/0.75/0.8/0.9). Reusing it
       removes the arithmetic, removes a variable, and makes a Syncfusion float label the same
       size as the help text under a Bootstrap field - which it should have been anyway. */
    --cm-input-label-font: var(--cm-hint-font);
}

/* ---- the field itself -------------------------------------------------------------------------
   .e-input is the <input>; .e-input-group is the wrapper that Syncfusion sizes against. Both are
   set, because the wrapper's font-size is what several of the theme's internal em-based paddings
   are calculated from - leaving it at 14px while the input shrinks produces a box with the right
   text and the wrong proportions. */
html[data-density] .e-input-group,
html[data-density] .e-input-group.e-control-wrapper,
html[data-density] .e-input,
html[data-density] .e-control-wrapper .e-input,
html[data-density] input.e-input,
html[data-density] textarea.e-input {
    font-size: var(--cm-input-font);
}

/* ---- the named components -----------------------------------------------------------------------
   Listed individually rather than relying on .e-input alone. Each of these renders its display
   text through its own class as well, and a dropdown whose closed-state text is 14px next to a
   textbox at 12.8px is the same mismatch this file exists to remove - just moved one component
   along. Counts on 2026-09-20: SfTextBox 421, SfNumericTextBox 163, SfCheckBox 114,
   SfDatePicker 109, SfDropDownList 87, SfMultiSelect 6, SfMaskedTextBox 1. */
html[data-density] .e-ddl.e-input-group .e-input,
html[data-density] .e-dropdownlist,
html[data-density] .e-numeric.e-input-group .e-input,
html[data-density] .e-datepicker.e-input-group .e-input,
html[data-density] .e-datetimepicker.e-input-group .e-input,
html[data-density] .e-timepicker.e-input-group .e-input,
html[data-density] .e-maskedtextbox,
html[data-density] .e-multi-select-wrapper,
html[data-density] .e-multi-select-wrapper .e-searcher input {
    font-size: var(--cm-input-font);
}

/* The chips inside a multi-select carry their own size and look absurd at a different scale from
   the box holding them. */
html[data-density] .e-multi-select-wrapper .e-chips > .e-chipcontent {
    font-size: var(--cm-input-font);
}

/* ---- labels -------------------------------------------------------------------------------------
   Two different things, both called labels.

   .e-float-text is Syncfusion's floating caption, used where a component manages its own label.
   .e-label belongs to a checkbox or radio and sits BESIDE its box rather than above a field -
   it is set from --cm-input-font, not the smaller label size, because at rest it is body text
   next to a control rather than a caption over one.

   THE FLOAT-LABEL RULES BELOW ARE UNEXERCISED IN CM TODAY, and are kept rather than deleted so
   the day somebody reaches for one it is not a fresh regression. As of 2026-09-20 there are ZERO
   uses of FloatLabelType in the whole application - 1,168 plain .form-label elements and 613
   placeholders instead - so nothing on any screen currently renders an .e-float-text.

   IF FLOAT LABELS ARE EVER ADOPTED, know that this single rule is not enough. The theme carries
   roughly twenty-eight MORE SPECIFIC rules for the focused, filled, autofilled, textarea, e-small
   and e-bigger states, every one of them a fixed pixel value (10, 12, 14, 16). They beat this the
   moment a field is focused or has a value, which in a real form is most of the time. Matching
   them properly is a pass-2 job, not a one-line addition.

   Also worth knowing before measuring any of this: .e-float-text carries a 0.25s transition, so
   reading its computed size straight after changing the density returns a value mid-animation.
   That produced a convincing false negative during verification - four densities all reporting
   the first one's number - which looked exactly like a broken variable. */
html[data-density] .e-float-input label.e-float-text,
html[data-density] .e-float-input.e-control-wrapper label.e-float-text,
html[data-density] .e-input-group .e-float-text {
    font-size: var(--cm-input-label-font);
}

html[data-density] .e-checkbox-wrapper .e-label,
html[data-density] .e-css.e-checkbox-wrapper .e-label,
html[data-density] .e-radio + label {
    font-size: var(--cm-input-font);
}

/* ---- dropdown popups ----------------------------------------------------------------------------
   THESE ARE NOT INSIDE THE FORM. Syncfusion renders popup lists at the end of <body>, outside
   whatever container opened them, so a rule scoped to a form or a page would miss them entirely -
   the field would shrink and the list that drops out of it would not. They are still inside the
   same <html>, which is why html[data-density] reaches them and a container-scoped selector
   would not. */
html[data-density] .e-popup.e-ddl .e-list-item,
html[data-density] .e-dropdownbase .e-list-item,
html[data-density] .e-popup .e-list-group-item,
html[data-density] .e-ddl.e-popup .e-input-group input.e-input {
    font-size: var(--cm-input-font);
}

/* The "no records found" line, which is a different class again and looked oversized beside a
   shrunken list. */
html[data-density] .e-dropdownbase .e-nodata,
html[data-density] .e-popup .e-nodata {
    font-size: var(--cm-input-label-font);
}

/* ---- calendar -----------------------------------------------------------------------------------
   The date picker's popup, same argument as dropdown lists: rendered outside the form, and a
   full-size calendar hanging off a shrunken field is more jarring than no change at all. */
html[data-density] .e-calendar .e-header .e-title,
html[data-density] .e-calendar th,
html[data-density] .e-calendar td span.e-day {
    font-size: var(--cm-input-label-font);
}

/* ---- validation ---------------------------------------------------------------------------------
   Error text under a field. Left at the hint size the rest of the app uses for the same job, so a
   validation message matches the help text it usually appears next to. */
html[data-density] .e-input-group .e-float-text.e-error,
html[data-density] .validation-message {
    font-size: var(--cm-hint-font);
}

/* ================================================================================================
   PASS 2  —  heights, padding and rows
   ================================================================================================

   Pass 1 made the TEXT follow the density. It did not make anything shorter, which is the actual
   point of a density setting: more records on one screen without scrolling.

   MEASURED BEFORE CHANGING (2026-09-20, every density identical):

       .e-input-group          32px      .e-input              30px, padding-left 8px
       .e-input-group-icon     30px, min-height 30px           font 14px
       .e-btn                  32px, padding 4px 8px           font 14px
       .e-grid .e-rowcell      34px, padding 6px 8px           font 14px
       .e-grid .e-headercell   34px, padding 8px               font 14px
       .e-popup .e-list-item   19.19px

   Note the grid: pass 1 never touched it, so grid text was still 14px while the form fields
   around it had moved. Grids are the densest thing on any screen in this application, so they
   carry the most of the benefit here.

   WHY min-height MATTERS MORE THAN height. Syncfusion gives .e-input-group-icon an explicit
   min-height of 30px, matching the input. Setting only the group's height leaves that 30px floor
   in place, the icon refuses to shrink, and the group springs back to fit it - the rule appears
   to do nothing at all. The icons have to be released before any height below 32px is reachable.
   ================================================================================================ */

:root {
    /* Input row height. 32px everywhere today; compact deliberately comes down to 28 so the
       default gets the benefit, matching how pass 1 treated the font. */
    --cm-field-height: 28px;
    --cm-field-pad-x: 8px;

    /* Grid cell padding. The vertical half is what decides row height - a grid row is padding,
       then a line box, then padding - so this is the number that puts more records on screen. */
    --cm-row-pad-y: 4px;
    --cm-row-pad-x: 8px;

    /* Buttons and dropdown list items, so a toolbar and an open dropdown do not stay full height
       beside fields that shrank.

       LIST PADDING IS ZERO AT EVERY LEVEL BUT COMFORTABLE, on purpose. A popup list item starts
       with NO vertical padding - the theme gives it a fixed 19.2px line-height and nothing else -
       so the first attempt at 2/3/4/7px made dropdown lists TALLER at every density, which is the
       opposite of the exercise. With line-height at 1.5 the font alone carries it: 16.8px at tiny,
       19.2px at compact, which is exactly today. */
    --cm-btn-pad-y: 4px;
    --cm-list-pad-y: 0px;
}

[data-density="tiny"] {
    --cm-field-height: 24px;
    --cm-field-pad-x: 6px;
    --cm-row-pad-y: 1px;
    --cm-row-pad-x: 6px;
    --cm-btn-pad-y: 2px;
    --cm-list-pad-y: 0px;
}

[data-density="condensed"] {
    --cm-field-height: 26px;
    --cm-field-pad-x: 7px;
    --cm-row-pad-y: 2px;
    --cm-row-pad-x: 7px;
    --cm-btn-pad-y: 3px;
    --cm-list-pad-y: 0px;
}

[data-density="compact"] {
    --cm-field-height: 28px;
    --cm-field-pad-x: 8px;
    --cm-row-pad-y: 4px;
    --cm-row-pad-x: 8px;
    --cm-btn-pad-y: 4px;
    --cm-list-pad-y: 0px;
}

/* Comfortable is the one level that goes UP. It is meant for people who find the default
   cramped, so it sits above the theme's own 32px rather than merely matching it. */
[data-density="comfortable"] {
    --cm-field-height: 34px;
    --cm-field-pad-x: 10px;
    --cm-row-pad-y: 8px;
    --cm-row-pad-x: 10px;
    --cm-btn-pad-y: 6px;
    --cm-list-pad-y: 4px;
}

/* ---- the input row ------------------------------------------------------------------------- */
html[data-density] .e-input-group,
html[data-density] .e-input-group.e-control-wrapper,
html[data-density] .e-float-input.e-control-wrapper {
    height: var(--cm-field-height);
    min-height: 0;
}

/* height:100% rather than a fixed number so the input always fills whatever the group is, and
   one variable stays the single source of the row's height. */
html[data-density] .e-input-group .e-input,
html[data-density] .e-input-group.e-control-wrapper .e-input,
html[data-density] input.e-input,
html[data-density] .e-input-group input.e-input {
    height: 100%;
    min-height: 0;
    padding-top: 0;
    padding-bottom: 0;
    padding-left: var(--cm-field-pad-x);
}

/* THE RELEASE. Without min-height:0 here nothing above this line can take effect - see the note
   at the top. height:auto lets the icon stretch to the group rather than dictate to it, and the
   flex centring the theme already applies keeps it on the middle line. */
html[data-density] .e-input-group .e-input-group-icon,
html[data-density] .e-input-group.e-control-wrapper .e-input-group-icon,
html[data-density] .e-input-group .e-input-group-icon.e-ddl-icon,
html[data-density] .e-input-group .e-input-group-icon.e-date-icon,
html[data-density] .e-input-group span.e-input-group-icon {
    min-height: 0;
    height: auto;
    align-self: stretch;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--cm-input-font);
    padding-left: var(--cm-field-pad-x);
    padding-right: var(--cm-field-pad-x);
}

/* The numeric spinners are stacked two to a field, so they get half the room each and cannot
   carry the same minimum as a single icon. */
html[data-density] .e-numeric .e-input-group-icon.e-spin-up,
html[data-density] .e-numeric .e-input-group-icon.e-spin-down {
    min-height: 0;
    height: auto;
    padding-left: calc(var(--cm-field-pad-x) * 0.5);
    padding-right: calc(var(--cm-field-pad-x) * 0.5);
}

/* ---- the grid ------------------------------------------------------------------------------
   The biggest win available. Row height is padding + line box + padding, so the padding variable
   is what actually fits more records on a screen.

   Font is set here as well as in pass 1's block: grid cells are not .e-input and were still
   rendering at the theme's 14px while the fields around them had moved. */
html[data-density] .e-grid,
html[data-density] .e-grid .e-rowcell,
html[data-density] .e-grid .e-headercell,
html[data-density] .e-grid .e-headercelldiv,
html[data-density] .e-grid .e-gridheader .e-headertext {
    font-size: var(--cm-ui-font);
}

html[data-density] .e-grid .e-rowcell {
    padding-top: var(--cm-row-pad-y);
    padding-bottom: var(--cm-row-pad-y);
    padding-left: var(--cm-row-pad-x);
    padding-right: var(--cm-row-pad-x);
    line-height: 1.5;
}

/* height:auto is doing the work, not the padding. The theme sets an explicit
   ".e-grid .e-headercell { height: 34px }", so padding alone left the header stuck at 34 while
   the rows beneath it came down to 18.8 - a header taller than three of its own rows. */
html[data-density] .e-grid .e-headercell,
html[data-density] .e-grid .e-detailheadercell {
    height: auto;
    padding-top: var(--cm-row-pad-y);
    padding-bottom: var(--cm-row-pad-y);
    padding-left: var(--cm-row-pad-x);
    padding-right: var(--cm-row-pad-x);
}

/* Syncfusion sets an explicit line-height on the header's inner div, which holds the header row
   open independently of its padding. */
html[data-density] .e-grid .e-headercelldiv {
    line-height: 1.5;
    height: auto;
    padding: 0;
}

/* ---- buttons and popup lists ---------------------------------------------------------------- */
html[data-density] .e-btn,
html[data-density] .e-css.e-btn {
    font-size: var(--cm-input-font);
    padding-top: var(--cm-btn-pad-y);
    padding-bottom: var(--cm-btn-pad-y);
    line-height: 1.5;
}

html[data-density] .e-popup.e-ddl .e-list-item,
html[data-density] .e-dropdownbase .e-list-item {
    padding-top: var(--cm-list-pad-y);
    padding-bottom: var(--cm-list-pad-y);
    line-height: 1.5;
    height: auto;
    min-height: 0;
}

/* ================================================================================================
   PASS 3  —  the page around the fields  (top-down)
   ================================================================================================

   Passes 1 and 2 moved the form controls and the grids. They did not move the PAGE. An audit of
   twenty-three components at tiny against comfortable found these identical at both:

       .btn 16px     .table cell 16px    .card-body 16px   .alert 16px
       .badge 12px   .nav-link 16px      h3-h6 20px
       Syncfusion: dialog header 16, dialog content 14, tab header 16, toolbar 14,
                   pager 14, group-drop area 14, tooltip 12, listview 14,
                   accordion 14, chip 14

   So at tiny you got an 11.2px input sitting inside a card whose body text was still 16px. That
   is most of why the setting felt half-finished: the fields moved and their surroundings did not.

   TOP-DOWN RATHER THAN ENUMERATED. body carries the density and everything that inherits follows
   in one line, instead of another twenty selector groups to write and maintain. That is how a
   generated application gets an even result - it owns the whole page, so density is one root
   variable rather than a list of exceptions.

   WHY body AND NOT html. Setting a root font-size would rescale every rem in the application at
   once - not only text but Bootstrap's padding, margins, gutters and widths, changing layout
   everywhere. Worse, the density variables are themselves declared in rem (0.8rem and so on), so
   they would shrink against a shrinking root and compound. body moves inherited text and leaves
   the layout grid alone.

   THE COST OF body IS THAT rem-BASED SIZES IGNORE IT. rem resolves against html, never body, so
   Bootstrap's .btn (1rem) and h1-h6 (rem) sail straight past it. Those are the pin-backs below,
   and they are the only reason this section is longer than one line.

   TO UNDO THIS PASS ONLY: delete everything below this banner. Passes 1 and 2 are above it and
   stand on their own.
   ================================================================================================ */

/* ---- the one line that does most of the work ---------------------------------------------------
   Everything with no font-size of its own - card bodies, table cells, alerts, list text, plain
   paragraphs, the bulk of every page - inherits from here. */
html[data-density] body {
    font-size: var(--cm-ui-font);
}

/* ---- pin-backs: the rem-based holdouts --------------------------------------------------------
   These declare their size in rem, which resolves against html and so ignores body entirely.
   They have to be named. */

html[data-density] .btn {
    font-size: var(--cm-ui-font);
}

/* The size modifiers need their OWN sizes. Pointing all three at --cm-ui-font made .btn-sm and
   .btn-lg identical to a plain .btn - measured 11.2 / 12.8 / 14.4 for both - which silently
   deleted the distinction wherever the app uses them. */
html[data-density] .btn-sm { font-size: var(--cm-hint-font); }
html[data-density] .btn-lg { font-size: calc(var(--cm-ui-font) * 1.15); }

/* BADGES COMPOUND, AND THAT IS THE PROBLEM. Bootstrap sizes .badge at .75em of its PARENT, so
   once body carries the density the two multiply: 0.75 x 11.2px gave an 8.4px badge at tiny,
   which is not small text, it is unreadable. Given an absolute size off the hint variable it
   tracks the density without compounding, and bottoms out at 10.4px. */
html[data-density] .badge {
    font-size: var(--cm-hint-font);
}

/* Headings step down from the page title rather than being fixed, so the whole hierarchy moves
   together. h1 and h2 were already handled in app.css; h3-h6 were not, which left an h5 at 20px
   above 11.2px body text at tiny. */
html[data-density] h3, html[data-density] .h3 { font-size: calc(var(--cm-title-font) * 0.92); }
html[data-density] h4, html[data-density] .h4 { font-size: calc(var(--cm-title-font) * 0.84); }
html[data-density] h5, html[data-density] .h5 { font-size: calc(var(--cm-title-font) * 0.78); }
html[data-density] h6, html[data-density] .h6 { font-size: calc(var(--cm-title-font) * 0.74); }

/* ---- Syncfusion chrome -------------------------------------------------------------------------
   Syncfusion sets an explicit font-size on nearly every wrapper it renders, so none of it inherits
   from body no matter what body says. Each of these was measured as frozen before being listed. */

html[data-density] .e-dialog .e-dlg-header,
html[data-density] .e-dialog .e-dlg-header *,
html[data-density] .e-dlg-header-content .e-dlg-header {
    font-size: var(--cm-title-font);
}

html[data-density] .e-dialog,
html[data-density] .e-dialog .e-dlg-content,
html[data-density] .e-dlg-content {
    font-size: var(--cm-ui-font);
}

html[data-density] .e-tab .e-tab-header .e-item .e-tab-text,
html[data-density] .e-tab .e-tab-header .e-toolbar-item .e-tab-text {
    font-size: var(--cm-ui-font);
}

html[data-density] .e-toolbar .e-toolbar-item .e-tbar-btn-text,
html[data-density] .e-toolbar .e-toolbar-item .e-tbar-btn,
html[data-density] .e-toolbar {
    font-size: var(--cm-ui-font);
}

/* The pager's numbers and its "1 of 5" message are different elements with different classes and
   looked mismatched when only one of them moved. */
html[data-density] .e-pager,
html[data-density] .e-pager .e-link,
html[data-density] .e-pager .e-pagercontainer .e-numericitem,
html[data-density] .e-pager .e-parentmsgbar,
html[data-density] .e-pager .e-pagecountmsg,
html[data-density] .e-pager .e-pagesizes .e-input {
    font-size: var(--cm-ui-font);
}

html[data-density] .e-grid .e-groupdroparea {
    font-size: var(--cm-ui-font);
    padding-top: var(--cm-row-pad-y);
    padding-bottom: var(--cm-row-pad-y);
}

/* A tooltip is one notch down, the way hints and captions are everywhere else in the app. */
html[data-density] .e-tooltip-wrap .e-tip-content,
html[data-density] .e-tooltip-wrap {
    font-size: var(--cm-hint-font);
}

html[data-density] .e-listview,
html[data-density] .e-listview .e-list-item,
html[data-density] .e-listview .e-list-text {
    font-size: var(--cm-ui-font);
}

html[data-density] .e-accordion .e-acrdn-header,
html[data-density] .e-accordion .e-acrdn-header .e-acrdn-header-content,
html[data-density] .e-accordion .e-acrdn-panel .e-acrdn-content {
    font-size: var(--cm-ui-font);
}

html[data-density] .e-chip-list .e-chip,
html[data-density] .e-chip-list .e-chip .e-chip-text {
    font-size: var(--cm-ui-font);
}

/* ---- what must NOT scale ------------------------------------------------------------------------
   ICON FONTS ARE GLYPHS, NOT TEXT. Bootstrap Icons and Syncfusion's icon font both size off the
   inherited font, so body carrying the density would quietly shrink every icon in the application
   along with the words - and an icon at 11.2px is a smudge rather than a smaller icon. They are
   held at a readable size that still moves a little, rather than tracking the text exactly. */
html[data-density] .bi::before,
html[data-density] .e-icons,
html[data-density] .e-btn-icon,
html[data-density] .e-input-group-icon.e-icons {
    font-size: max(0.85rem, var(--cm-ui-font));
}
