/* ===========================================================================
   The iPhone Home Screen app's layout (docs/features/ios-app-mobile-ui).

   EVERY selector here starts with `.ios-app`. That class is put on <html> by the head script in
   _Layout.cshtml, only when BUM is launched from the iPhone Home Screen icon. Without it, nothing
   in this file applies, so desktop, Safari on a phone, Android and installed desktop apps render
   exactly as before. scripts/check-ios-app-css.sh enforces the prefix.

   Phase 1: section tabs at the bottom, a brand-only header, no footer.
   Phase 2: the Users list (folded filters, one-row triage, compact cards).
   Phase 3: the Billing menu as a row of chips; pinned actions on the record pages.
   Phase 4: Reports: finger-sized switches and links, tighter summary tiles.
   Phase 5: a density and clarity pass across every section (CSS only, nothing removed).
   Phase 6: the rest of the canvas, and a tab bar that holds still between pages.
   =========================================================================== */

.ios-app {
  /* The bar's own height, without the home-indicator inset below it. */
  --tabbar-h: 58px;
  /* The page gutter, widened to clear the notch in landscape. The app runs with viewport-fit=cover
     (set by the head script), so content may reach under the notch and the home indicator; the
     env() insets are what keep it clear of both, and they are 0 where there is nothing to clear. */
  --app-gutter: max(clamp(1rem, 2.2vw, 2.25rem), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px));
}

/* -------------------------------------------------------------- header */
/* Under viewport-fit=cover the top inset is the status bar's when iOS reports one; 0 otherwise. */
.ios-app .app-bar { padding-top: env(safe-area-inset-top, 0px); }
.ios-app .app-bar > .container,
.ios-app .app-main > .container { padding-inline: var(--app-gutter); }
/* The flash message is fixed to the top right corner: keep it off the notch. */
.ios-app .flash-region { top: calc(1rem + env(safe-area-inset-top, 0px)); right: max(1rem, env(safe-area-inset-right, 0px)); }
/* The sections move to the tabs, so the top bar keeps only the brand. */
.ios-app .app-bar__collapse { display: none; }
/* A column in both orientations, so the brand sits left and vertically centred either way. */
.ios-app .app-bar__inner { flex-direction: column; justify-content: center; align-items: flex-start; min-height: 48px; padding-top: 0; padding-bottom: 0; }

/* --------------------------------------------------------------- shell */
/* Room for the fixed bar, so a page's last row or button never ends up behind it. */
.ios-app .app-main { padding-bottom: calc(var(--tabbar-h) + 1.5rem + env(safe-area-inset-bottom, 0px)); }
/* Its one line would sit under the bar; there is nothing in it the app needs. */
.ios-app .footer { display: none; }

/* ------------------------------------------------------------- tab bar */
/* `!important` only to beat Bootstrap's `[hidden] { display: none !important }`: the bar ships
   hidden for everyone else. */
.ios-app .app-tabbar {
  display: grid !important;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 1030;
  /* Below the tabs, the home-indicator inset (real now that the app runs with viewport-fit=cover);
     at the sides, the notch's in landscape. */
  padding: 0 max(.25rem, env(safe-area-inset-right, 0px)) env(safe-area-inset-bottom, 0px) max(.25rem, env(safe-area-inset-left, 0px));
  /* The header's navy, one step lighter, so the two dark bars frame the page without merging. */
  background: #1f2a47;
  border-top: 1px solid rgba(255, 255, 255, .08);
  box-shadow: 0 -1px 3px rgba(16, 32, 58, .05);
}
.ios-app .app-tabbar__tab {
  min-height: var(--tabbar-h);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  color: #a3acc4; text-decoration: none;
  font-size: .7rem; font-weight: 600; letter-spacing: .01em;
  -webkit-tap-highlight-color: transparent;
}
/* Stakeholders is the longest label; at 320px it would otherwise push past its column. */
.ios-app .app-tabbar__tab span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ios-app .app-tabbar__tab.is-active { color: #fff; }
/* White alone is a small step up from the grey labels: a soft pill behind the icon marks it too. */
.ios-app .app-tabbar__tab svg { box-sizing: content-box; padding: 2px 12px; border-radius: 999px; }
.ios-app .app-tabbar__tab.is-active svg { background: rgba(255, 255, 255, .14); }
.ios-app .app-tabbar__tab:focus-visible { outline: 2px solid #fff; outline-offset: -4px; border-radius: var(--radius-sm); }

/* ========================================================== Users list */
/* Phase 2. Markup hooks in _UserDashboard.cshtml: .js-filters-toggle (ships `hidden`) and the
   form's `is-open`, set when filters are active. */

/* The filter panel folds away behind the Filters button; active filters keep it open. */
.ios-app .users-filters__toggle { display: inline-flex !important; align-items: center; gap: .4rem; min-height: 44px; }
.ios-app .users-filters:not(.is-open) { display: none; }

/* Heading row: title on its own line, the triage tiles one scrolling row under it (scrolling
   inside itself, never the page), then New user and Filters side by side. */
.ios-app .page-head .triage {
  order: 1; flex: 0 0 100%; margin-right: 0;
  flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
  padding: 2px 2px 4px;
}
.ios-app .page-head .triage::-webkit-scrollbar { display: none; }
.ios-app .page-head .tile { flex: 0 0 auto; min-height: 44px; align-items: center; }
.ios-app .page-head .btn-new { order: 2; min-height: 44px; }
.ios-app .page-head .users-filters__toggle { order: 3; }

/* 44px page links. */
.ios-app .pagination .page-link { min-width: 44px; min-height: 44px; display: flex; align-items: center; justify-content: center; }

/* Compact cards, portrait only: landscape is wide enough for the existing table. The card shows
   what the list is scanned and acted on by; the six other columns stay on the user record,
   which a tap anywhere on the card opens (row-link). Picked by data-label, so the markup is the
   same as everywhere else. */
@media (max-width: 767.98px) {
  .ios-app .users-grid tr {
    display: flex; flex-wrap: wrap; align-items: center; gap: .45rem .6rem;
    padding: .85rem .95rem;
  }
  .ios-app .users-grid td { display: flex; align-items: center; justify-content: flex-start; padding: 0; border-bottom: 0; text-align: left; gap: .45rem; }
  .ios-app .users-grid td::before { display: none; }
  .ios-app .users-grid td[data-label="ID"],
  .ios-app .users-grid td[data-label="Appointment"],
  .ios-app .users-grid td[data-label="Strategy"],
  .ios-app .users-grid td[data-label="Applicants"],
  .ios-app .users-grid td[data-label="Client"],
  .ios-app .users-grid td[data-label="From"] { display: none; }

  /* Name + status, then email, then password: a line each. */
  .ios-app .users-grid td[data-label="Name"] { order: 1; flex: 0 0 100%; }
  .ios-app .users-grid__name { display: flex; align-items: center; width: 100%; }
  .ios-app .users-grid__name .row-link__anchor { font-weight: 600; font-size: 1.02rem; color: var(--ink); text-decoration: none; }
  .ios-app .users-grid__name .pill { margin-left: auto; }
  .ios-app .users-grid td[data-label="Email"] { order: 2; flex: 0 0 100%; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: .8rem; color: var(--muted); }
  .ios-app .users-grid td[data-label="Password"] { order: 3; flex: 0 0 100%; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: .8rem; }
  /* A bare string reads as noise without its name, so the password keeps a small label. */
  .ios-app .users-grid td[data-label="Password"]::before {
    display: block; content: "Password"; font-family: 'Inter', system-ui, sans-serif;
    font-size: .62rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); font-weight: 600;
  }

  /* Country · visa · device on one line, the device pushed right. */
  .ios-app .users-grid td[data-label="Country"] { order: 4; }
  .ios-app .users-grid td[data-label="Visa"] { order: 5; font-size: .82rem; color: var(--ink-soft); }
  .ios-app .users-grid td[data-label="Device"] { order: 6; margin-left: auto; font-size: .82rem; }

  /* A full-width divider (the row's own ::after, a flex item like the cells) starts the footer
     line on its own: the end date and time left, the delete button at the right. */
  .ios-app .users-grid tbody tr::after { content: ""; order: 7; flex: 0 0 100%; height: 1px; background: var(--line-soft); margin: .15rem 0; }
  .ios-app .users-grid td[data-label="To"] { order: 8; font-size: .8rem; color: var(--muted); }
  .ios-app .users-grid td[data-label="To"]::before { display: block; content: "To"; font-size: .62rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); font-weight: 600; }
  .ios-app .users-grid td[data-label="Expires"] { order: 9; font-size: .8rem; }
  .ios-app .users-grid td.actions { order: 10; margin-left: auto; display: flex; padding: 0; }
  .ios-app .users-grid td.actions::before { display: none; }

  /* Fingertip-sized: copy 40px, delete 44px. */
  .ios-app .users-grid .js-copy { width: 40px; height: 40px; margin: -6px 0; }
  .ios-app .users-grid td.actions .icon-btn { width: 44px; height: 44px; margin: -6px -8px -6px 0; }
}

/* ======================================================== Billing menu */
/* Phase 3. The side menu becomes one row of chips scrolling inside itself (a script in
   _BillingMenu brings the current one into view). Group labels and separators go; the page's
   crumb ("Billing · Money in") still names the direction. */
.ios-app .billing-menu {
  display: flex; flex-direction: row; flex-wrap: nowrap; gap: .5rem;
  overflow-x: auto; scrollbar-width: none; padding: .4rem;
}
.ios-app .billing-menu::-webkit-scrollbar { display: none; }
.ios-app .billing-menu__group,
.ios-app .billing-menu__sep,
.ios-app .billing-menu__icon { display: none; }
.ios-app .billing-menu__item {
  flex: 0 0 auto; min-height: 52px; padding: .45rem .75rem; border-color: var(--line);
  grid-template-columns: auto auto; grid-template-areas: "name count" "figure figure"; column-gap: .5rem;
}
.ios-app .billing-menu__name,
.ios-app .billing-menu__figure { white-space: nowrap; }

/* ===================================================== Record actions */
/* Phase 3. Each record page ends with a `hidden` .app-actions block (Edit, and Add payment /
   Restart where the page has them). Here it sticks to the bottom of the screen, above the tabs,
   full-bleed across the page gutter, and comes to rest at the end of the page. */
.ios-app .app-actions {
  display: flex !important; gap: .6rem;
  position: sticky; bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px)); z-index: 1020;
  margin: 1.25rem calc(-1 * var(--app-gutter)) 0;
  padding: .7rem var(--app-gutter);
  background: var(--surface); border-top: 1px solid var(--line);
  box-shadow: 0 -2px 8px rgba(16, 32, 58, .06);
}
/* The bar ends the page, so the space kept for the tabs is all it needs below it: otherwise it
   would hop up by that gap when the page reaches its end. */
.ios-app .app-main:has(.app-actions) { padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px)); }
/* Sized by their labels, then sharing what is left: three equal thirds clipped "Restart user". */
.ios-app .app-actions > * { flex: 1 1 auto; min-width: 0; }
.ios-app .app-actions .restart-on,
.ios-app .app-actions .restart-off { display: flex; }
.ios-app .app-actions__btn,
.ios-app .app-actions .restart-btn {
  min-height: 48px; margin: 0; padding-inline: .7rem;
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  font-size: .92rem; font-weight: 600; border-radius: var(--radius-sm); white-space: nowrap; overflow: hidden;
}
/* Restart sits inside its form (or the blocked wrapper), which is the flex item; the button fills
   it. The other buttons are flex items themselves, so a width here would become their basis. */
.ios-app .app-actions .restart-btn { width: 100%; }
.ios-app .app-actions__btn svg,
.ios-app .app-actions .restart-btn svg { width: 16px; height: 16px; flex: none; }
/* Restart is the action the app is opened for: the bar's filled button when it is allowed. */
.ios-app .app-actions .restart-on .restart-btn { background: var(--brand); border-color: var(--brand); color: #fff; }

/* ============================================================= Reports */
/* Phase 4, CSS only. The chart switches were 27px tall, the "See … →" links 18px and the table
   links 15px; and the seven summary tiles took ~800px before the first chart. The switch and tile
   classes are shared: the Billing lists and Stakeholders get the same treatment. */
/* Taller, never wider: extra width pushed Expenses' category select past its panel. Centred, since
   on the Billing lists and Stakeholders these switches are links, whose text would sit at the top. */
.ios-app .budget-toggle__opt { min-height: 44px; display: inline-flex; align-items: center; }
/* Expenses' month switch and category select share a row; on a narrow phone let the select drop
   under the switch rather than be clipped by the panel. */
.ios-app .budget-tabs__tools { flex-wrap: wrap; }
.ios-app .budget-kpi__link { display: inline-flex; align-items: center; min-height: 44px; }
.ios-app .budget-mix td a { display: inline-block; padding: .55rem 0; }

/* Tighter tiles: smaller padding and gaps, a slightly smaller figure. Same content, same order. */
.ios-app .budget-kpis { gap: .6rem; margin-bottom: .6rem; }
.ios-app .budget-kpi { padding: .8rem .95rem; gap: .1rem; }
.ios-app .budget-kpi__value { font-size: 1.3rem; }

/* ================================================== Phase 5: density */
/* CSS only: no markup, label or behaviour change, and every control stays on its page. The one
   control hidden is the header Restart, and only where the pinned bar shows the same partial
   with the same model. Before/after: https://claude.ai/artifact/RnifjE4o6PY4k6hws8x5Sy */

/* Header: the brand alone, on a shorter row. */
.ios-app .brand__sub { display: none; }
.ios-app .app-bar__inner { min-height: 40px; }

/* ---- Users list */
/* Folded, the panel still shows its search box; the other filters wait behind Filters. The
   label is hidden visually only, and stays the input's accessible name. It is the same GET form,
   submitting on change or Enter, so the query string is unchanged. */
.ios-app .users-filters:not(.is-open) { display: block; padding: .6rem; }
.ios-app .users-filters:not(.is-open) .row > :not(.users-filters__search),
.ios-app .users-filters:not(.is-open) .filters__status { display: none; }
.ios-app .users-filters:not(.is-open) .users-filters__search .form-label {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.ios-app .users-filters .users-filters__search .form-control { min-height: 44px; }

/* All six triage tiles at once, three to a row, instead of a row that hid two off-screen. */
.ios-app .page-head .triage {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .4rem;
  overflow: visible; padding: 2px 0 4px;
}
.ios-app .page-head .tile { min-width: 0; padding-inline: .5rem; gap: .35rem; }
.ios-app .page-head .tile__l { min-width: 0; font-size: .74rem; line-height: 1.15; }

@media (max-width: 767.98px) {
  /* "To — in 38 days" read as one value: the expiry gets its own label, as To has. */
  .ios-app .users-grid td[data-label="Expires"]::before {
    display: block; content: "Expiry"; font-size: .62rem; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); font-weight: 600;
  }
  .ios-app .users-grid td[data-label="Expires"] { margin-left: .5rem; }
}

/* ---- Record pages (user, device) */
/* The pinned bar renders the same _RestartControl, with the same model, so the header copy is a
   duplicate. Only on pages that have the bar. */
.ios-app .app-main:has(.app-actions) .page-head .restart-on,
.ios-app .app-main:has(.app-actions) .page-head .restart-off { display: none; }
/* A blocked Restart carries its reason only as a tooltip, which an iPhone never shows: print it. */
.ios-app .app-actions .restart-off { flex-direction: column; gap: .25rem; }
/* The reason makes Restart's column taller; Edit keeps its own height instead of stretching. */
.ios-app .app-actions { align-items: flex-start; }
.ios-app .app-actions .restart-off::after {
  content: attr(title); font-size: .72rem; line-height: 1.25; color: var(--muted); text-align: center; white-space: normal;
  /* Adds no width of its own, so the buttons keep the split they have without it. */
  width: 0; min-width: 100%;
}
/* Delete: a quiet text button at the far right, away from Book and the thumb's path. Same form,
   same confirm. */
.ios-app .page-head .detail-actions { width: 100%; display: flex; align-items: center; gap: .6rem; }
.ios-app .page-head .detail-actions .js-delete-form { margin-left: auto; }
.ios-app .page-head .detail-actions .btn-book { min-height: 44px; }
.ios-app .page-head .detail-actions .btn-outline-danger {
  border-color: transparent; background: transparent; min-height: 44px; padding-inline: .4rem; font-weight: 500;
}
/* Device record: Online and Running get their own line, so the name stops wrapping into them. */
.ios-app .page-head__title { flex-wrap: wrap; }
.ios-app .page-head__title > .device-status { order: 1; flex: 0 0 100%; }
.ios-app .page-head__title > .device-enable { order: 2; }

/* ---- Billing · Clients: two lines a row instead of four labelled rows. Only rows with a Users
   cell (the Clients list); every cell stays, its label inline. */
@media (max-width: 767.98px) {
  .ios-app .billing-list .data-table tr:has(> td[data-label="Users"]) {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .2rem 1rem;
    padding: .7rem .9rem; margin-bottom: .5rem;
  }
  .ios-app .billing-list .data-table tr:has(> td[data-label="Users"]) > td { padding: 0; border-bottom: 0; gap: .4rem; }
  .ios-app .billing-list .data-table tr:has(> td[data-label="Users"]) > td[data-label="Name"] { grid-area: 1 / 1; justify-content: flex-start; font-weight: 600; }
  .ios-app .billing-list .data-table tr:has(> td[data-label="Users"]) > td[data-label="Name"]::before { display: none; }
  .ios-app .billing-list .data-table tr:has(> td[data-label="Users"]) > td[data-label="Balance"] { grid-area: 1 / 2; justify-content: flex-end; font-weight: 600; }
  .ios-app .billing-list .data-table tr:has(> td[data-label="Users"]) > td[data-label="Balance"]::before { display: none; }
  .ios-app .billing-list .data-table tr:has(> td[data-label="Users"]) > td[data-label="Users"] { grid-area: 2 / 1; justify-content: flex-start; font-size: .84rem; color: var(--muted); }
  .ios-app .billing-list .data-table tr:has(> td[data-label="Users"]) > td[data-label="Profit"] { grid-area: 2 / 2; justify-content: flex-end; font-size: .84rem; }
}

/* ---- Client record */
@media (min-width: 360px) {
  .ios-app .client-figures { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .ios-app .client-figure--lead .client-figure__value { font-size: 1.15rem; }
}
.ios-app .client-figure__value { overflow-wrap: anywhere; }
/* One line a payment: amount, who received it (ellipsed), date. */
.ios-app .payment-list__row { grid-template-columns: auto minmax(0, 1fr) auto; }
.ios-app .payment-list__amount,
.ios-app .payment-list__who,
.ios-app .payment-list__when { grid-area: auto; }

/* ---- Reports: the three month tiles a step smaller, so their lines wrap less. */
.ios-app .budget-kpis--four .budget-kpi:not(.budget-kpi--lead) .budget-kpi__value { font-size: 1.1rem; }
.ios-app .budget-kpis--four .budget-kpi:not(.budget-kpi--lead) .budget-kpi__note { font-size: .78rem; }

/* ---- Stakeholders: Received, Financed and Expenses paid on one row. A long figure wraps before
   its ֏ rather than being clipped. Narrower phones keep the two-column grid. */
@media (min-width: 360px) {
  .ios-app .stake-kpis--four { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .4rem; }
  .ios-app .stake-kpis--four .budget-kpi--lead,
  .ios-app .stake-kpis--four .stake-kpi--exp { grid-column: auto; }
  .ios-app .stake-kpis--four .budget-kpi--lead { grid-column: 1 / -1; }
  .ios-app .stake-kpis--four .budget-kpi:not(.budget-kpi--lead) { padding: .6rem .6rem; min-width: 0; }
  .ios-app .stake-kpis--four .budget-kpi:not(.budget-kpi--lead) .budget-kpi__value { font-size: .85rem; white-space: normal; }
  .ios-app .stake-kpis--four .budget-kpi:not(.budget-kpi--lead) .budget-kpi__label { font-size: .6rem; }
  .ios-app .stake-kpis--four .budget-kpi:not(.budget-kpi--lead) .budget-kpi__note { font-size: .7rem; line-height: 1.25; }
}

/* ---- Devices: the same card, less air. */
.ios-app .device-grid { gap: .7rem; }
.ios-app .device-card { gap: .55rem; padding: .85rem .95rem .8rem; }
.ios-app .device-card__icon { width: 2.4rem; height: 2.4rem; }
.ios-app .device-card__hours,
.ios-app .device-card__browsers { margin-top: 0; }
.ios-app .device-card__foot { padding-top: .55rem; }

/* ============================================ Phase 6: steady tab bar */
/* The head script opts the app (and only the app) into cross-document view transitions. The old
   page stays up until the new one is ready; the tab bar and header are their own layers that swap
   in place, with no fade, so they never blink. The page body cross-fades briefly. Where iOS has no
   support (before Safari 18.2) nothing here applies and navigation is as before. */
.ios-app .app-tabbar { view-transition-name: app-tabbar; }
.ios-app .app-bar { view-transition-name: app-header; }
.ios-app::view-transition-group(app-tabbar),
.ios-app::view-transition-group(app-header) { animation: none; }
.ios-app::view-transition-old(app-tabbar),
.ios-app::view-transition-old(app-header) { display: none; }
.ios-app::view-transition-new(app-tabbar),
.ios-app::view-transition-new(app-header) { animation: none; }
.ios-app::view-transition-old(root),
.ios-app::view-transition-new(root) { animation-duration: .12s; }
@media (prefers-reduced-motion: reduce) {
  .ios-app::view-transition-old(root),
  .ios-app::view-transition-new(root) { animation: none; }
}

/* ======================================== Phase 6: rest of the canvas */
/* Users: New user and Filters share the title row; the triage grid goes under it. They wrap
   under the title on a phone too narrow for all three. */
.ios-app .page-head:has(> .triage) { flex-wrap: wrap; align-items: center; gap: .6rem; }
.ios-app .page-head:has(> .triage) > h1 { flex: 1 1 auto; margin: 0; }
.ios-app .page-head:has(> .triage) .btn-new,
.ios-app .page-head:has(> .triage) .users-filters__toggle { order: 0; padding-inline: .75rem; }
.ios-app .page-head:has(> .triage) .triage { order: 1; }

/* Billing menu: slimmer chips, so the next one peeks in (the row still scrolls). */
.ios-app .billing-menu__item { padding: .4rem .6rem; column-gap: .4rem; }
.ios-app .billing-menu__name { font-size: .86rem; }
.ios-app .billing-menu__figure { font-size: .74rem; }

/* Search and its All / Has debt (or Active / All) switch on one row: the search takes what the
   switch leaves. Expenses has no search box and is unaffected. */
.ios-app .budget-search { flex: 1 1 8rem; min-width: 0; }
.ios-app .budget-tabs__tools .budget-toggle,
.ios-app .stake-tools .budget-toggle { flex: none; }
.ios-app .stake-tools { flex-wrap: nowrap; }

/* Stakeholders: a slightly smaller title, so New stakeholder stays beside it. */
.ios-app .stake-page .page-head h1 { font-size: 1.45rem; }

/* Device record: the Enabled switch, colour and description on one row. The title block's own
   box steps aside (display: contents, a plain div), so its children and the description line
   share one wrapping row: back + name, then the status pills, then switch · colour · text. */
.ios-app .device-head { display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; gap: .35rem .7rem; flex: 1 1 100%; }
.ios-app .device-head > .page-head__title { display: contents; }
.ios-app .device-head > .page-head__title > .device-status { order: 1; }
.ios-app .device-head > .page-head__title > .device-enable { order: 2; }
.ios-app .device-head > .device-head__sub { order: 3; margin: 0; padding: 0; }

/* Reports: tighter tiles, so the debt row starts sooner. */
.ios-app .budget-kpi { padding: .65rem .8rem; }
.ios-app .budget-kpi__note { font-size: .76rem; }
.ios-app .budget-kpis { gap: .5rem; margin-bottom: .5rem; }

/* Device cards: a step tighter again, with the same content. */
.ios-app .device-card { gap: .45rem; padding: .75rem .85rem .7rem; }
.ios-app .device-card__name { font-size: 1rem; margin: 0; }
.ios-app .device-card__icon { width: 2.2rem; height: 2.2rem; }
.ios-app .device-card__foot { padding-top: .45rem; gap: .4rem .8rem; }
