/* ============================================================================
   Clyptus ATS — density and mobile layer                  assets/density.css
   ----------------------------------------------------------------------------
   Module 109.

   WHY ONE STYLESHEET RATHER THAN 147 PAGE EDITS
   The complaint is that pages waste space and do not work on a phone. That is
   true of nearly every screen, and it is true for the same handful of reasons
   each time: Bootstrap's default card padding is generous, headings are sized
   for a marketing page, table cells are loose, and form rows stack at the
   wrong breakpoint.

   Fixing that in one place fixes it everywhere at once and cannot drift. Fixing
   it page by page means 147 edits, 147 chances to break a working screen, and a
   guarantee that the 148th page will not match.

   This file is loaded LAST, after theme.css and Bootstrap, so it wins on equal
   specificity without anything being marked !important. Where !important does
   appear it is because Bootstrap sets the property inline-equivalent via a
   utility class, and the comment says so.

   WHAT IT DELIBERATELY DOES NOT DO
   It does not change colours, and it does not restyle any component. The theme
   is somebody's decision and the dark mode in prefs.css depends on it. This
   only changes SPACING, SIZE and BREAKPOINTS — the three things that make a
   dense screen dense.
   ============================================================================ */

/* ---------------------------------------------------------------- 1. Rhythm
   Every vertical gap in the application traces back to these. Tightened by
   roughly a third, which is the difference between six rows on a phone screen
   and nine. */
:root {
    --d-gap-xs: .25rem;
    --d-gap-sm: .45rem;
    --d-gap-md: .7rem;
    --d-gap-lg: 1rem;
}

/* ---------------------------------------------------------------- 2. Cards
   Bootstrap's .card-body is 1rem all round and most of this application's
   cards hold a form row or a grid, neither of which needs that much air. */
.card-body { padding: .75rem .85rem; }
.card-body.py-2 { padding-top: .55rem; padding-bottom: .55rem; }
.card { margin-bottom: var(--d-gap-md); }
.card-header { padding: .5rem .85rem; }

/* A card immediately inside another card is a panel, not a card. Drop the
   double border and the double padding — it reads as a box in a box otherwise. */
.card .card { border: 0; box-shadow: none; margin-bottom: var(--d-gap-sm); }
.card .card > .card-body { padding: 0; }

/* ---------------------------------------------------------------- 3. Headings
   h4 at Bootstrap's default is 1.5rem, which on a page header sits alone on a
   line and pushes the content below the fold on a phone. */
h4 { font-size: 1.15rem; margin-bottom: .15rem; }
h5 { font-size: 1rem; }
h6 { font-size: .9rem; }
.page-body > .d-flex:first-child { margin-bottom: .6rem !important; }

/* ---------------------------------------------------------------- 4. Tables
   The single biggest source of wasted space in the product. A .table-sm cell
   is .3rem; this takes it to .28rem vertical and tightens the line height,
   which fits about two extra rows per screen without anything feeling cramped. */
.table > :not(caption) > * > * { padding: .32rem .5rem; }
.table-sm > :not(caption) > * > * { padding: .26rem .45rem; }
.table { margin-bottom: 0; font-size: .84rem; }
.table thead th {
    font-size: .68rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    font-weight: 700;
    white-space: nowrap;
}

/* A table is almost always the last thing in its card, and the card already
   has padding. The extra bottom margin just pushes the next card down. */
.card > .table-responsive > .table { margin-bottom: 0; }

/* ---------------------------------------------------------------- 5. Forms
   Controls sized for a mouse waste a third of every form row. 34px is still a
   comfortable click target with a pointer; the mobile rules below take them
   back to 44px where a thumb needs it. */
.form-control-sm, .form-select-sm { min-height: 34px; padding: .25rem .5rem; font-size: .84rem; }
.form-label { margin-bottom: .1rem; font-size: .78rem; font-weight: 500; }
.form-label.small { font-size: .72rem; }
.form-text { font-size: .72rem; margin-top: .15rem; }
.row.g-2 { --bs-gutter-y: .45rem; }

/* An input group of a label and a control is one thing. Bootstrap gives the
   label a block of its own; this pulls them together. */
.col-md-2 > .form-label, .col-md-3 > .form-label,
.col-6 > .form-label, .col-12 > .form-label { line-height: 1.2; }

/* ---------------------------------------------------------------- 6. Buttons
   Small buttons carrying an icon and a word are the standard action in this
   application, and Bootstrap's padding makes a row of three of them wrap. */
.btn-sm { padding: .25rem .55rem; font-size: .8rem; }
.btn-sm .bi { font-size: .85rem; vertical-align: -1px; }
.btn { --bs-btn-border-radius: var(--r, 9px); }

/* An icon-only button should be square, not a wide rectangle with a glyph
   floating in the middle of it. */
.btn-sm > .bi:only-child { margin: 0; }

/* ---------------------------------------------------------------- 7. Alerts
   Used throughout as inline feedback, where the default padding makes a
   one-line message occupy three lines' worth of page. */
.alert { padding: .5rem .75rem; margin-bottom: var(--d-gap-sm); font-size: .85rem; }
.alert.py-2 { padding-top: .45rem; padding-bottom: .45rem; }

/* ---------------------------------------------------------------- 8. Badges */
.badge { font-weight: 600; font-size: .68rem; padding: .28em .5em; }

/* ---------------------------------------------------------------- 9. Paging
   The bar assets/paging.js inserts under every long table. */
.pg-bar {
    display: flex;
    align-items: center;
    gap: .3rem;
    padding: .45rem .2rem .1rem;
    font-size: .78rem;
    color: var(--muted, #64748b);
    flex-wrap: wrap;
}
.pg-btn {
    min-width: 30px;
    height: 30px;
    border: 1px solid var(--line, #e2e8f0);
    background: var(--surface, #fff);
    border-radius: var(--r, 9px);
    color: var(--ink, #1f2933);
    line-height: 1;
    cursor: pointer;
}
.pg-btn:hover:not(:disabled) { border-color: var(--accent, #4f46e5); color: var(--accent, #4f46e5); }
.pg-btn:disabled { opacity: .38; cursor: default; }
.pg-mid { padding: 0 .35rem; white-space: nowrap; }
.pg-count { margin-left: auto; white-space: nowrap; }

/* ---------------------------------------------------------------- 10. Mobile
   The application had one viewport tag and almost no media queries, so on a
   phone it was a desktop layout scaled down. These are the rules that make it
   usable rather than merely visible. */
@media (max-width: 768px) {

    /* Touch targets. The Android and iOS guidance is 44-48px and it is right:
       a 34px control is a mis-tap waiting to happen on a moving train, which
       is where half of these punches and approvals actually happen. */
    .form-control, .form-select, .form-control-sm, .form-select-sm {
        min-height: 44px;
        font-size: 16px;    /* under 16px, iOS Safari zooms the page on focus */
    }
    .btn, .btn-sm { min-height: 40px; padding-left: .7rem; padding-right: .7rem; }
    .btn-sm { font-size: .85rem; }

    /* A full-width button is easier to hit and stops three buttons wrapping
       into an unreadable stack of halves. */
    .card-body .row > [class*="col-"] > .btn.w-100 { margin-top: .2rem; }

    /* Page header: the title and its action stop competing for one line. */
    .page-body > .d-flex.justify-content-between { flex-direction: column; align-items: stretch !important; }
    .page-body > .d-flex.justify-content-between > div:last-child { margin-top: .4rem; }

    /* Tables scroll horizontally rather than crushing every column to three
       characters. The wrapper exists on most grids already; this makes it
       behave on the ones where it does not. */
    .table-responsive { -webkit-overflow-scrolling: touch; }
    .table { font-size: .8rem; }
    .table > :not(caption) > * > * { padding: .3rem .4rem; }

    /* Two columns of tiles rather than four. Four on a 360px screen gives
       each one 80px, which fits neither a number nor its label. */
    .cc-grid, .lv-bal { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }

    /* Cards edge to edge. A 12px gutter either side of a card on a narrow
       screen is 24px of the 360 you have, spent on nothing. */
    .card { border-radius: var(--r, 9px); }
    .card-body { padding: .65rem .7rem; }

    /* Modal and offcanvas full height, so a form in one is not a letterbox. */
    .modal-dialog { margin: .4rem; }

    h4 { font-size: 1.05rem; }
}

/* Very narrow — a 360px phone in portrait, which is most of them. */
@media (max-width: 400px) {
    .cc-grid, .lv-bal { grid-template-columns: 1fr !important; }
    .pg-count { margin-left: 0; width: 100%; }
}

/* ---------------------------------------------------------------- 11. Print
   Reports get printed and sent. Chrome's default drops the background of
   every badge and header band, which turns a colour-coded sheet into grey. */
@media print {
    .card { border: 1px solid #ccc !important; box-shadow: none !important; break-inside: avoid; }
    .btn, .pg-bar, .form-control, .form-select { display: none !important; }
    .table { font-size: .72rem; }
    * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* ---------------------------------------------------------------- 12. Focus
   maintainScrollPositionOnPostBack restores the scroll and UiFocus restores
   the caret; this makes the restored caret visible. Without a ring, focus
   lands somewhere the user cannot see and the fix looks like it did nothing. */
.form-control:focus, .form-select:focus {
    box-shadow: 0 0 0 3px rgba(79, 70, 229, .18);
    border-color: var(--accent, #4f46e5);
}
