/* Phone/small-tablet layer (<= 767.98px) on top of the vendored theme +
 * panel.css. Loaded LAST so it wins on equal specificity.
 *
 * The three signed-in areas -- console, gate, panel -- all render through
 * templates/panel/base.html, so every rule here lands on all three at once.
 * Desktop is untouched: nothing outside the token block escapes the media
 * query below.
 */

:root {
    --pm-touch: 42px;        /* minimum comfortable tap height */
    --pm-gutter: 0.85rem;    /* page gutter on a phone (theme uses 1.5rem) */
    --pm-line: #e8eaf1;
    --pm-label: #7c8496;
}

@media (max-width: 767.98px) {

/* ==================================================================== shell */

/* 70px of topbar furniture on an 844px-tall screen is a lot; 58 keeps the
 * hamburger comfortable and hands a whole row back to the content. */
html {
    --theme-topbar-height: 58px;
}

.app-topbar .topbar-menu {
    padding-inline: 0.35rem;
}

/* The theme's 1.5rem gutters cost 48px of a 390px screen. */
.content-page > .container-fluid {
    padding-inline: var(--pm-gutter);
}

.page-title-head {
    min-height: 46px;
    margin-inline: calc(var(--pm-gutter) * -1);
    padding-inline: var(--pm-gutter);
}

/* Page titles read "Members · Pramukh Demo Residency" -- at the theme's xl size
 * that is three lines of heading before any content. */
.page-main-title {
    font-size: 1.05rem !important;
    line-height: 1.35;
}

/* Scoped to .content-page so the auth screens, which load this file for its
 * field and tap-target rules but have no shell, keep their own card styling. */
.content-page .card {
    margin-bottom: var(--pm-gutter);
    border-radius: 12px;
}

/* Inside a grid the row gutter already does the spacing -- keeping the card's
 * own margin as well doubles every gap on a screen that has none to spare. */
.content-page .row > [class*="col"] > .card:last-child {
    margin-bottom: 0;
}

.content-page .card-header,
.content-page .card-body,
.content-page .card-footer {
    padding: 0.85rem;
}

.content-page .card-header {
    padding-block: 0.75rem;
}

footer.footer {
    font-size: 0.78rem;
}

/* Alerts sit right under the title on every page; keep them compact. */
.alert {
    padding: 0.7rem 0.85rem;
    font-size: 0.9rem;
}

/* ================================================================= controls */

/* iOS Safari zooms the whole page when a focused field is under 16px. Every
 * `-sm` field in this app is 14px, so tapping any filter box yanks the layout
 * sideways. Give fields full-size text back on phones -- this is the single
 * most jarring thing about the console on an iPhone. */
.form-control,
.form-select,
textarea,
select,
input[type="text"],
input[type="search"],
input[type="password"],
input[type="number"],
input[type="tel"],
input[type="email"],
input[type="date"],
input[type="month"],
input[type="datetime-local"] {
    font-size: 16px !important;
}

/* Tap targets: iOS asks for 44pt, Android 48dp. The `-sm` variants render at
 * ~31px, which is a miss-tap generator. */
.btn,
.form-control,
.form-select,
.input-group-text,
.page-link {
    min-height: var(--pm-touch);
}

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.btn-sm,
.form-control-sm,
.form-select-sm {
    padding-block: 0.45rem;
}

.btn-icon {
    min-width: var(--pm-touch);
}

/* The pager's prev/next are bare chevrons -- 42px tall but only 26px wide,
 * which is a thin target for a thumb. */
.page-link {
    min-width: var(--pm-touch);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Checkbox / radio hit areas -- the box itself stays visually the same size. */
.form-check {
    min-height: var(--pm-touch);
    display: flex;
    align-items: center;
}

.form-check-input {
    width: 1.15em;
    height: 1.15em;
    margin-top: 0;
}

.form-check .form-check-label {
    padding-left: 0.35rem;
}

/* ---------------------------------------------------------------- forms -- */

/* A filter form usually shares a card header with the section title. On a phone
 * the title eats the line and the search box is left with half of what remains
 * -- a 90px input next to its own button. Give the form a line of its own. */
.content-page .card-header form.row {
    flex: 1 0 100%;
    width: 100%;
    margin-top: 0.5rem;
}

/* Form columns, everywhere. Inline add-forms and filter bars lay their fields
 * out in thirds and quarters -- fine on a laptop, but at 350px a third is a
 * 100px box you cannot read your own typing in. Half a line is the floor, and
 * anything the template made wider than half takes the whole line. These match
 * the breakpoint-less `col-N` classes only, so `col-sm-4` / `col-md-6` and
 * friends keep their own behaviour at every other width. */
.content-page form.row > [class*="col"]:not([class*="col-auto"]),
.content-page form .row > [class*="col"]:not([class*="col-auto"]) {
    flex: 1 1 46%;
    width: auto;
    max-width: 100%;
}

/* Same selector shape as the rule above on purpose: it has to out-score it,
 * not just come after it. */
.content-page form.row > [class*="col"].col-5,
.content-page form.row > [class*="col"].col-7,
.content-page form.row > [class*="col"].col-8,
.content-page form.row > [class*="col"].col-9,
.content-page form.row > [class*="col"].col-10,
.content-page form.row > [class*="col"].col-11,
.content-page form.row > [class*="col"].col-12,
.content-page form .row > [class*="col"].col-5,
.content-page form .row > [class*="col"].col-7,
.content-page form .row > [class*="col"].col-8,
.content-page form .row > [class*="col"].col-9,
.content-page form .row > [class*="col"].col-10,
.content-page form .row > [class*="col"].col-11,
.content-page form .row > [class*="col"].col-12 {
    flex: 1 1 100%;
}

/* A field that carries a long value -- a search box, anything with a prefix or
 * suffix add-on, a long placeholder -- gets the whole line. Half a line of
 * "Search flat no., owner/tenant name or phone…" shows six characters.
 * mobile.js tags these; CSS cannot measure a placeholder. */
.content-page form.row > [class*="col"][data-pm-wide],
.content-page form .row > [class*="col"][data-pm-wide] {
    flex: 1 1 100%;
}

/* Once every field is on its own line, the form's action belongs at the end of
 * it -- not wherever the desktop grid happened to place it. */
.content-page form.row > [class*="col"][data-pm-submit],
.content-page form .row > [class*="col"][data-pm-submit] {
    order: 99;
}

/* Buttons take whatever the fields leave on their line. */
.content-page form.row > [class*="col-auto"],
.content-page form .row > [class*="col-auto"] {
    flex: 1 1 auto;
}

.content-page form.row > [class*="col-auto"] > .btn:not([data-pm-icon]),
.content-page form .row > [class*="col-auto"] > .btn:not([data-pm-icon]) {
    width: 100%;
}

/* Icon-only buttons stay square wherever they are: a filter bar, a stacked
 * card's action row, an inline form in a cell. mobile.js tags them. */
.content-page .btn[data-pm-icon] {
    width: var(--pm-touch);
    min-width: var(--pm-touch);
    flex: 0 0 auto;
    padding-inline: 0;
}

/* ...and their column does not stretch either. */
.content-page form.row > [class*="col-auto"][data-pm-icon],
.content-page form .row > [class*="col-auto"][data-pm-icon] {
    flex: 0 0 auto;
}

.content-page form.row > [class*="col-auto"][data-pm-icon] > .btn,
.content-page form .row > [class*="col-auto"][data-pm-icon] > .btn {
    width: var(--pm-touch);
    padding-inline: 0;
}

/* A primary action sitting straight in the card header (Add member, Add flat)
 * spans the line rather than floating beside a wrapped filter form. Buttons
 * *inside* a filter form are handled above -- stretching those turned every
 * search icon into a full-width grey slab. */
.content-page .card-header > .btn:not([data-pm-icon]),
.content-page .card-header > form:not(.row):not(.d-flex) > .btn:not([data-pm-icon]) {
    width: 100%;
}

/* Not every filter bar is a grid: several are a plain `form.d-flex` whose
 * fields carry hard inline widths (style="max-width:220px", style="width:auto")
 * sized for a desktop header. Give the form its own line and let the fields
 * share it -- inline styles need !important to move. */
.content-page .card-header form.d-flex {
    flex: 1 0 100%;
    width: 100%;
    margin-top: 0.5rem;
}

.content-page .card-header form.d-flex > .form-control,
.content-page .card-header form.d-flex > .form-select,
.content-page .card-header form.d-flex > .input-group {
    flex: 1 1 auto;
    min-width: 45%;
    width: auto !important;
    max-width: none !important;
}

/* Card headers hold a title, sometimes a filter form and often a line of help
 * text. Stacked on a phone they need real separation from the table below,
 * otherwise the whole card reads as one grey block. */
.content-page .card-header > .d-flex {
    row-gap: 0.5rem;
}

.content-page .card-header > p:last-child,
.content-page .card-header > .text-muted:last-child {
    margin-top: 0.55rem !important;
    line-height: 1.5;
}

/* Floor the smallest type at 12px -- the practical minimum for secondary text
 * on a phone. fs-12/fs-13 are used 340+ times for metadata; the theme's badge
 * (10.5px) and sidebar section headings (9.8px) are below that on their own. */
.fs-10, .fs-11, .fs-12 { font-size: 12px !important; }
.fs-13 { font-size: 13px !important; }

.badge {
    font-size: 12px;
}

/* The theme's h6 lands at 11.9px, and h6 is used for card titles. Bootstrap's
 * .form-text (field help) lands there too. */
h6, .h6 {
    font-size: 0.85rem;
}

.form-text {
    font-size: 12px;
}

.sidenav-menu .side-nav-title {
    font-size: 12px;
}

/* Our own dashboard micro-labels (panel.css) are set in rem and land between
 * 10.4 and 11.5px; lift them onto the same floor. */
.dash-stat-label,
.dash-stat-sub,
.dash-metric-label,
.dash-chip,
.dash-chart-label,
.dash-meter-cap,
.dash-balance-formula,
.dash-legend,
.dash-summary-title {
    font-size: 12px;
}

/* ============================================================== section nav */

/* The Finance pill bar carries up to 8 tabs; wrapped it becomes a three-line
 * block above every page. A single scrollable strip is the phone convention. */
.nav-pills {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 2px;
}

.nav-pills::-webkit-scrollbar {
    display: none;
}

.nav-pills > .nav-item {
    flex: 0 0 auto;
}

.nav-pills .nav-link {
    min-height: var(--pm-touch);
    display: inline-flex;
    align-items: center;
    white-space: nowrap;
}

/* Tables that stay tables: stop the theme's roomy cell padding from pushing
 * them wider than they need to be. */
.table-responsive:not(.is-stacked) > table > :not(caption) > * > * {
    padding: 0.55rem 0.5rem;
}

/* A card's pagination footer: count on one line, pager on the next. */
.card-footer.d-flex {
    justify-content: center !important;
    text-align: center;
}

/* ==================================================================== look */

/* Everything above makes the app *fit* a phone. This section makes it look like
 * it was meant for one: the vendored theme is a desktop admin skin, and at
 * 350px its hard borders, heavy headings and flush edges read as a shrunken
 * dashboard rather than an app. Phone-only, so the desktop skin is untouched. */

/* A soft ground so white cards actually sit on something. */
body {
    background-color: #f4f5f9;
}

/* Topbar: the theme draws its icon buttons with a *dashed* 1px outline, which
 * on a dark bar reads as an unfinished placeholder. Solid ghost buttons read as
 * part of the bar instead. The theme scopes these under [data-topbar-color], so
 * these selectors have to match that weight to win. */
html[data-topbar-color] .app-topbar .btn.btn-default,
html[data-topbar-color] .app-topbar .btn.btn-icon {
    background-color: rgba(255, 255, 255, 0.10);
    /* The theme's own rule is `border:1px dashed …!important`, so this has to
     * carry !important as well -- nothing else can beat it. */
    border: 1px solid transparent !important;
    color: #fff;
    border-radius: 10px;
}

html[data-topbar-color] .app-topbar .btn.btn-default:active,
html[data-topbar-color] .app-topbar .btn.btn-icon:active {
    background-color: rgba(255, 255, 255, 0.2);
}

html[data-topbar-color] .app-topbar .topbar-link {
    color: rgba(255, 255, 255, 0.92);
}

/* Page heading: give it room to breathe, and demote the society name -- it is
 * the same on every page and was costing a second line of bold heading.
 * splitTitle() in mobile.js wraps it; on desktop both spans stay inline. */
.page-title-head {
    padding-top: 0.35rem;
    padding-bottom: 0.15rem;
}

.page-main-title {
    font-weight: 600;
    letter-spacing: -0.01em;
}

.page-main-title .pm-title-sep {
    display: none;
}

.page-main-title .pm-title-community {
    display: block;
    margin-top: 0.15rem;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.01em;
    color: #8a91a3;
}

/* Cards: a hairline border plus a hard divider under every header is a lot of
 * lines on a small screen. One soft shadow and no border reads as a surface. */
.content-page .card {
    border: 0;
    border-radius: 14px;
    box-shadow: 0 1px 2px rgba(27, 22, 48, 0.04), 0 6px 16px -8px rgba(27, 22, 48, 0.14);
}

.content-page .card-header {
    background: transparent;
    border-bottom: 1px solid #eef0f5;
}

/* panel.css gives the KPI tiles a coloured top edge; the `border: 0` above wiped
 * it out along with the hairline, so put that one back. */
.content-page .card.dash-stat {
    border-top: 3px solid transparent;
}

.content-page .dash-stat--violet { border-top-color: #5546E0; }
.content-page .dash-stat--blue   { border-top-color: #2f6fed; }
.content-page .dash-stat--green  { border-top-color: #17a673; }
.content-page .dash-stat--amber  { border-top-color: #e08a1e; }

.content-page .card-header .card-title {
    font-size: 0.95rem;
    font-weight: 600;
    letter-spacing: -0.005em;
}

.content-page .card-header .card-title i {
    color: var(--pramukh-violet);
    opacity: 0.85;
}

/* Form rhythm: a label that reads as a label, and fields that line up. */
.content-page .form-label {
    font-size: 12px !important;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: #6b7280;
    margin-bottom: 0.3rem;
}

.content-page .form-control,
.content-page .form-select,
.content-page .input-group-text {
    border-radius: 10px;
    border-color: #e2e5ec;
}

.content-page .input-group > .form-control:not(:first-child),
.content-page .input-group > .form-select:not(:first-child) {
    border-start-start-radius: 0;
    border-end-start-radius: 0;
}

.content-page .input-group > :not(:last-child) {
    border-start-end-radius: 0;
    border-end-end-radius: 0;
}

.content-page .form-control:focus,
.content-page .form-select:focus {
    border-color: var(--pramukh-violet);
    box-shadow: 0 0 0 3px rgba(85, 70, 224, 0.12);
}

.content-page .btn {
    border-radius: 10px;
    font-weight: 500;
}

.content-page .btn-primary {
    box-shadow: 0 4px 12px -4px rgba(85, 70, 224, 0.5);
}

/* Section pills: solid violet for the current tab, quiet for the rest. */
.nav-pills .nav-link {
    border-radius: 10px;
    font-size: 0.85rem;
    font-weight: 500;
}

/* Row cards from a stacked table: match the surface treatment above. */
.table-responsive.is-stacked > table > tbody > tr {
    border-color: #eaecf2;
    border-radius: 12px;
}

.table-responsive.is-stacked > table > tbody > tr > td::before {
    color: #98a0b0;
    font-size: 0.7rem;
}

.table-responsive.is-stacked > table > tbody > tr > td:first-child {
    font-size: 1rem;
    letter-spacing: -0.005em;
}

/* ========================================================== page specifics */

/* Three-number summary strips (Billed / Collected / Pending, Income / Expense /
 * Balance). As full-width tiles they cost three screens of scrolling to read
 * three numbers, so they stay side by side and the numbers shrink to suit. */
.stat-strip {
    --bs-gutter-x: 0.5rem;
    --bs-gutter-y: 0.5rem;
}

.stat-strip .card-body {
    padding: 0.6rem 0.5rem;
}

.stat-strip .card-body > span {
    font-size: 12px !important;
    display: block;
    line-height: 1.25;
}

.stat-strip .card-body h4 {
    /* Scale with the screen so "₹173,700.00" fits a third of a 390px phone on
     * one line; break-word used to strand the last digit on its own line. Only
     * a truly huge figure still wraps, and then between characters, not mid-tile. */
    font-size: clamp(0.72rem, 3.5vw, 0.95rem);
    margin-top: 0.15rem !important;
    word-break: normal;
    overflow-wrap: anywhere;
}

/* Dashboard KPIs: four full-width cards is ~1400px of scrolling before the
 * first real number. Two up fits a phone screen. */
/* Two up, so a pair of tiles has to share a row height -- otherwise the one
 * whose caption wraps leaves a ragged hole beside it. */
.dash-stat {
    height: 100%;
}

.dash-stat .card-body {
    padding: 0.85rem;
}

.dash-chip {
    white-space: nowrap;
}

.dash-stat-value {
    font-size: 1.45rem;
}

.dash-stat-icon {
    width: 40px;
    height: 40px;
    border-radius: 11px;
    font-size: 1.05rem;
}

.dash-balance-hero {
    font-size: 1.65rem;
}

.dash-metric {
    padding: 0.7rem 0.75rem;
}

.dash-metric-value {
    font-size: 1.05rem;
}

.dash-chart {
    height: 170px;
    gap: 0.3rem;
}

/* Hierarchy: each holder is one inline-flex badge holding name + scope + phone
 * + copy button. With no wrapping allowed it runs 51px past the screen edge --
 * the only page-level overflow in the app (console and gate both). */
.hierarchy-holder,
.card-body .badge.d-inline-flex {
    flex-wrap: wrap;
    white-space: normal;
    text-align: left;
}

/* Permission bundle editor: one module per column (already handled in
 * panel.css) plus roomier rows for thumbs. */
.perm-code-list {
    gap: 0.3rem;
}

/* Modals go full-bleed rather than floating in a 12px margin. */
.modal-dialog {
    margin: 0.5rem;
}

/* Definition lists (member / user / unit detail) -- 5/7 split leaves the value
 * column too narrow for a phone number plus a badge. */
dl.row > dt {
    font-size: 0.78rem;
    color: var(--pm-label);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

dl.row > dt,
dl.row > dd {
    width: 100%;
    flex: 0 0 100%;
    max-width: 100%;
}

dl.row > dt {
    margin-bottom: 0.1rem;
}

/* Long identifiers (receipt numbers, join codes, phone strings) must not push
 * the page sideways. */
code, .text-break-all {
    word-break: break-word;
}

}  /* end max-width: 767.98px */

/* ======================================== tables -> stacked cards (wider) */

/* Stacking runs up to the `lg` breakpoint, not just on phones: a tablet in
 * portrait has room for most of these tables but not for the widest ones
 * (the audit log needs 772px). mobile.js measures each table against the
 * space it actually has, so on a tablet only the genuine overflows stack and
 * everything else stays a table. */
@media (max-width: 991.98px) {

/* ================================================== tables -> stacked cards */

/* A 6-to-8 column table cannot be read in 342px, and .table-responsive only
 * turns that into sideways scrolling *inside a card* -- the Roles / Actions
 * column ends up invisible. On phones each row becomes its own little card with
 * "Label   value" lines instead.
 *
 * mobile.js measures each table and adds `.is-stacked` only to the ones that
 * genuinely overflow, and copies each column's <th> text onto its cells as
 * data-label. Tables that already fit (2-3 columns) are left as real tables --
 * stacking those would only make them longer. Opt a table out for good with
 * class="table-keep". */

.table-responsive.is-stacked {
    overflow: visible;
}

.table-responsive.is-stacked > table,
.table-responsive.is-stacked > table > tbody,
.table-responsive.is-stacked > table > tfoot,
.table-responsive.is-stacked > table > tbody > tr,
.table-responsive.is-stacked > table > tfoot > tr,
.table-responsive.is-stacked > table > tbody > tr > td,
.table-responsive.is-stacked > table > tfoot > tr > td {
    display: block;
    width: auto;
}

.table-responsive.is-stacked > table > thead {
    display: none;
}

.table-responsive.is-stacked > table {
    border-collapse: separate;
}

/* One row = one card. */
.table-responsive.is-stacked > table > tbody > tr {
    border: 1px solid var(--pm-line);
    border-radius: 11px;
    padding: 0.15rem 0.8rem 0.55rem;
    margin-bottom: 0.6rem;
    background: var(--theme-secondary-bg, #fff);
}

.table-responsive.is-stacked > table > tbody > tr:last-child {
    margin-bottom: 0;
}

/* "Label            value" lines. */
.table-responsive.is-stacked > table > tbody > tr > td {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.4rem 0.75rem;
    border: 0;
    border-top: 1px solid var(--pm-line);
    padding: 0.5rem 0;
    text-align: left !important;
}

.table-responsive.is-stacked > table > tbody > tr > td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    max-width: 45%;
    color: var(--pm-label);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

/* First cell is the row's identity (name / date / flat) -- render it as the
 * card's heading, not as another labelled line. */
.table-responsive.is-stacked > table > tbody > tr > td:first-child {
    display: block;
    border-top: 0;
    padding-top: 0.7rem;
    font-size: 0.98rem;
    font-weight: 600;
}

.table-responsive.is-stacked > table > tbody > tr > td:first-child::before {
    display: none;
}

/* A column whose header is blank is the actions column -- give it the full
 * width so its buttons and inline forms are reachable. */
.table-responsive.is-stacked > table > tbody > tr > td[data-label=""] {
    display: block;
    padding-top: 0.6rem;
}

.table-responsive.is-stacked > table > tbody > tr > td[data-label=""]::before {
    display: none;
}

.table-responsive.is-stacked > table > tbody > tr > td[data-label=""] > .btn:not([data-pm-icon]),
.table-responsive.is-stacked > table > tbody > tr > td[data-label=""] > form > .btn:not([data-pm-icon]) {
    width: 100%;
}

/* A cell holding only a placeholder dash is a whole labelled line saying
 * nothing. As a table column it cost nothing; as a card row it is three lines
 * of "BUILDING  --" before the reader reaches anything real. mobile.js tags
 * these; values that happen to be zero or blank-looking numbers are never
 * tagged. */
.table-responsive.is-stacked > table > tbody > tr > td[data-empty] {
    display: none;
}

/* Empty-state / full-width rows keep their own single cell. */
.table-responsive.is-stacked > table > tbody > tr > td[colspan] {
    display: block;
    border-top: 0;
    text-align: center !important;
    font-weight: 400;
}

.table-responsive.is-stacked > table > tbody > tr > td[colspan]::before {
    display: none;
}

.table-responsive.is-stacked > table > tbody > tr:has(> td[colspan]) {
    border-style: dashed;
}

/* Totals row reads as a summary card. */
.table-responsive.is-stacked > table > tfoot > tr {
    border: 1px solid var(--pm-line);
    border-radius: 11px;
    margin-top: 0.6rem;
    padding: 0.15rem 0.8rem 0.55rem;
    background: #f6f7fb;
    font-weight: 600;
}

.table-responsive.is-stacked > table > tfoot > tr > td {
    display: flex;
    justify-content: space-between;
    gap: 0.75rem;
    border: 0;
    border-top: 1px solid var(--pm-line);
    padding: 0.5rem 0;
    text-align: left !important;
}

.table-responsive.is-stacked > table > tfoot > tr > td:first-child {
    border-top: 0;
}

.table-responsive.is-stacked > table > tfoot > tr > td::before {
    content: attr(data-label);
    color: var(--pm-label);
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
}

/* Inline forms living in a cell (approve / mark-paid / update status) need to
 * behave like a stacked form, not a table row. */
.table-responsive.is-stacked td form.d-flex,
.table-responsive.is-stacked td .d-flex {
    flex-wrap: wrap;
}

/* Several of these inline forms hard-code style="max-width:110px" to survive a
 * narrow table column. As a card row they have the whole width, and an inline
 * style can only be beaten with !important. */
.table-responsive.is-stacked td .form-control,
.table-responsive.is-stacked td .form-select,
.table-responsive.is-stacked td .input-group {
    min-width: 0;
    max-width: none !important;
}

.table-responsive.is-stacked td > form.d-flex,
.table-responsive.is-stacked td > form {
    width: 100%;
}

/* They are also right-aligned, and their controls sized `width:auto`, to sit in
 * a narrow table column. As a card row they get the whole width. */
.table-responsive.is-stacked td form.justify-content-end {
    justify-content: flex-start;
}

.table-responsive.is-stacked td form .form-control,
.table-responsive.is-stacked td form .form-select,
.table-responsive.is-stacked td form .input-group {
    flex: 1 1 auto;
    width: auto !important;
}

/* A stacked table sits flush against its card's edges (it is a direct child of
 * .card, not of .card-body), so the row cards would touch the rounded corners
 * without a gutter of their own. */
.table-responsive.is-stacked {
    padding: 0.6rem 0.75rem 0.75rem;
}

.card-body > .table-responsive.is-stacked {
    padding: 0;
}

}

/* ============================================================ small phones */

@media (max-width: 400px) {
    .page-main-title {
        font-size: 1rem !important;
    }

    .dash-stat-value {
        font-size: 1.3rem;
    }

    /* Two KPI cards side by side get tight below 400px -- drop the decorative
     * icon rather than squeezing the number. */
    .dash-stat-icon {
        display: none;
    }
}
