/* App styles on top of Bootstrap 5. No inline styles anywhere: the CSP blocks them.
   Brand: Rent Management guidelines v2 (October 2026). Colours are tokens; Bootstrap's own
   variables are pointed at them so its components follow without template changes. */

/* Cairo (SIL OFL, fonts/OFL.txt), self-hosted: one variable file per script covering weights
   400 to 700. Arabic pages use it for Arabic and Latin text and digits alike, so a line never
   mixes two typefaces; English pages keep the system font and never download it. */
@font-face {
    font-family: "Cairo";
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url("../fonts/cairo-arabic.woff2") format("woff2");
    unicode-range: U+0600-06FF, U+0750-077F, U+0870-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}

@font-face {
    font-family: "Cairo";
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url("../fonts/cairo-latin.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "Cairo";
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url("../fonts/cairo-latin-ext.woff2") format("woff2");
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
    /* Light unless theme.js says dark (see the dark colours at the end of this file). Saying so
       keeps a phone in dark mode from darkening fields and scrollbars on its own. */
    color-scheme: light;
    --navy: #0E3B73;
    --ink: #0A2647;
    --muted: #5B6478;
    --bg: #F1F4F8;
    --surface: #FFFFFF;
    --border: #DDE3EB;
    --placeholder: #E3E9F1;
    --purple: #5B3FA8;
    --purple-dark: #46308A;
    --purple-tint: #EDE9F8;
    --green: #1F7A4A;
    --green-tint: #E6F4EC;
    --warning: #B54708;
    --warning-tint: #FEF0E6;
    --error: #B42318;
    --error-tint: #FDECEA;
    --neutral: #475467;
    --neutral-tint: #EEF0F4;
    --footer-text: #C9D3E3;
    --field-border: #8792A6;
    --shadow-card: 0 4px 12px rgba(10, 38, 71, .06);
    --navy-ink: var(--navy);
    --soft: #F7F9FB;
    --thead: #EDF1F6;
    --disabled-bg: #D5DFEA;
    --disabled-ink: #6B7A8C;
    --border-strong: #C5CED9;
    --error-strong: #912018;
    --green-line: #B7DCC6;
    --warning-line: #F5CDB0;
    --error-line: #F4C2BD;
    --purple-line: #D5CCEF;
    --placeholder-ink: #6B7488;
    --navy-wash: rgba(14, 59, 115, .04);
    --shadow-strong: rgba(10, 38, 71, .12);

    --bs-body-font-family: "Segoe UI", system-ui, -apple-system, Roboto, Arial, sans-serif;
    --bs-body-color: var(--ink);
    --bs-body-color-rgb: 10, 38, 71;
    --bs-body-bg: var(--surface);
    --bs-body-bg-rgb: 255, 255, 255;
    --bs-emphasis-color: var(--ink);
    --bs-heading-color: var(--ink);
    --bs-secondary-color: var(--muted);
    --bs-secondary-bg: var(--placeholder);
    --bs-tertiary-bg: var(--soft);
    --bs-border-color: var(--border);
    --bs-primary: var(--navy);
    --bs-primary-rgb: 14, 59, 115;
    --bs-secondary: var(--neutral);
    --bs-secondary-rgb: 71, 84, 103;
    --bs-success: var(--green);
    --bs-success-rgb: 31, 122, 74;
    --bs-warning: var(--warning);
    --bs-warning-rgb: 181, 71, 8;
    --bs-danger: var(--error);
    --bs-danger-rgb: 180, 35, 24;
    --bs-info: var(--purple);
    --bs-info-rgb: 91, 63, 168;
    --bs-link-color: var(--purple);
    --bs-link-color-rgb: 91, 63, 168;
    --bs-link-hover-color: var(--purple-dark);
    --bs-link-hover-color-rgb: 70, 48, 138;
    --bs-border-radius: 8px;
    --bs-border-radius-sm: 6px;
    --bs-border-radius-lg: 12px;
    --bs-border-radius-pill: 999px;
    --bs-focus-ring-color: rgba(14, 59, 115, .25);
}

/* Cairo is wide with a tall x-height: +1 px on the English size is enough, with more line height. */
[dir="rtl"] {
    --bs-body-font-family: "Cairo", "Segoe UI", Tahoma, sans-serif;
    --bs-body-font-size: 1.0625rem;
    --bs-body-line-height: 1.6;
}

/* Bootstrap paints cards, fields, menus and dialogs with --bs-body-bg (white, as the brand says);
   the page colour goes on body itself. */
body {
    background-color: var(--bg);
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
}

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    font-weight: 700;
}

/* Page title (H1 32/40, 28/36 on phones); section titles (H3 20/28). */
.page h1 {
    font-size: 1.75rem;
    line-height: 1.3;
}

.page h2.h5 {
    font-size: 1.25rem;
    line-height: 1.4;
}

.page h2.h6 {
    font-size: 1rem;
    font-weight: 600;
}

@media (min-width: 700px) {
    .page h1 {
        font-size: 2rem;
        line-height: 1.25;
    }
}

/* Every interactive element: 2 px navy focus outline with 2 px offset. */
a:focus-visible,
button:focus-visible,
.btn:focus-visible,
.nav-link:focus-visible,
.form-control:focus,
.form-select:focus,
.form-check-input:focus {
    outline: 2px solid var(--navy-ink);
    outline-offset: 2px;
    box-shadow: none;
}

.form-control:focus,
.form-select:focus {
    border-color: var(--navy);
}

/* ---- Header ---- */
.site-header {
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    --bs-navbar-padding-y: .75rem;
    --bs-navbar-color: var(--navy-ink);
    --bs-navbar-hover-color: var(--ink);
    --bs-navbar-active-color: var(--navy-ink);
    --bs-navbar-brand-padding-y: 0;
}

.site-header > .container-fluid {
    max-width: 1360px;
    padding-inline: 16px;
}

.site-header .nav-link {
    font-weight: 600;
    white-space: nowrap;
}

/* The menu stays at 16 px in Arabic too, so it fits on one line at 1280 px. */
[dir="rtl"] .site-header .navbar-nav {
    --bs-nav-link-font-size: 1rem;
}

.site-header .brand-logo {
    display: block;
    height: 48px;
    width: auto;
}

.site-header .brand-symbol {
    display: block;
    height: 36px;
    width: auto;
}

@media (min-width: 700px) {
    .site-header > .container-fluid {
        padding-inline: 40px;
    }
}

/* Active item: 2 px navy underline. */
.site-header .navbar-nav .nav-link.active {
    box-shadow: inset 0 -2px 0 var(--navy-ink);
}

.site-header .navbar-collapse {
    min-width: 0;
}

.site-header .user-menu {
    display: flex;
    align-items: center;
    gap: .35rem;
}

.nav-icon {
    flex: none;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.nav-icon .dot {
    fill: currentColor;
    stroke: none;
}

/* Below 1200 px: symbol logo, tighter menu, and a person icon for the account (no name, no
   caret), so the whole menu fits on one line from 768 px in both languages. */
@media (max-width: 1199.98px) {
    .site-header > .container-fluid {
        padding-inline: 16px;
    }

    .site-header .navbar-collapse {
        margin-inline-start: .25rem;
    }

    .site-header .navbar-nav {
        --bs-nav-link-font-size: .9375rem;
        --bs-navbar-nav-link-padding-x: .45rem;
    }

    .site-header .user-menu::after {
        display: none;
    }
}

@media (max-width: 991.98px) {
    .site-header .navbar-nav {
        --bs-nav-link-font-size: .875rem;
        --bs-navbar-nav-link-padding-x: .35rem;
    }
}

/* ---- Phone menu (below 768 px): bottom bar, with Money and More opening a sheet ---- */
.tabbar {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 1030;
    display: flex;
    background: var(--surface);
    border-top: 1px solid var(--border);
    padding-bottom: env(safe-area-inset-bottom, 0);
}

.tabbar > a,
.tabbar > button {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    margin-top: -1px;
    padding: 8px 2px 7px;
    border: 0;
    border-top: 2px solid transparent;
    background: none;
    color: var(--bs-secondary-color);
    font-size: .6875rem;
    font-weight: 600;
    line-height: 1.2;
    text-decoration: none;
}

.tabbar > a > span,
.tabbar > button > span {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tabbar > .active {
    color: var(--navy-ink);
    border-top-color: var(--navy-ink);
}

.tabbar > :focus-visible {
    outline: 2px solid var(--navy-ink);
    outline-offset: -2px;
}

.nav-sheet {
    --bs-offcanvas-height: auto;
    --bs-offcanvas-bg: var(--surface);
    max-height: 85vh;
    border-radius: 16px 16px 0 0;
}

.nav-sheet .offcanvas-header {
    padding-bottom: .25rem;
}

.nav-sheet .offcanvas-body {
    padding-top: .25rem;
    padding-bottom: calc(1rem + env(safe-area-inset-bottom, 0));
}

.nav-sheet-link {
    display: block;
    width: 100%;
    padding: .7rem .75rem;
    border: 0;
    border-radius: var(--bs-border-radius);
    background: none;
    color: var(--ink);
    font-weight: 600;
    text-align: start;
    text-decoration: none;
}

.nav-sheet-link.active {
    background: var(--neutral-tint);
    color: var(--navy-ink);
}

.nav-sheet-group {
    padding: .25rem .75rem;
    font-size: .75rem;
    font-weight: 600;
    color: var(--bs-secondary-color);
}

.nav-sheet hr {
    margin: .35rem .5rem;
}

@media (max-width: 767.98px) {
    .site-header {
        --bs-navbar-padding-y: .5rem;
    }

    /* The bottom bar replaces the top menu (Bootstrap forces it visible, hence !important). */
    .has-tabbar .site-header .navbar-collapse {
        display: none !important;
    }

    /* Room for the bar under the last line of the page. */
    .has-tabbar {
        padding-bottom: calc(58px + env(safe-area-inset-bottom, 0));
    }
}

@media print {
    .tabbar {
        display: none;
    }
}

/* ---- Page body ---- */
.page {
    flex: 1 0 auto;
    width: 100%;
    max-width: 1360px;
    margin-inline: auto;
    padding: 24px 16px 48px;
}

@media (min-width: 700px) {
    .page {
        padding: 32px 40px 64px;
    }
}

/* ---- Footer: solid navy, white symbol ---- */
.site-footer {
    background: var(--navy);
    color: var(--footer-text);
    font-size: .875rem;
}

.site-footer > div {
    max-width: 1360px;
    margin-inline: auto;
    padding: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
}

.site-footer img {
    height: 24px;
    width: auto;
}

@media (min-width: 700px) {
    .site-footer > div {
        padding: 16px 40px;
        justify-content: flex-start;
    }
}

/* ---- Sign-in pages ---- */
.auth-logo {
    display: block;
    height: 64px;
    width: auto;
    margin: 1.5rem auto 2rem;
}

.auth-card {
    max-width: 26rem;
    margin: 0 auto 3rem;
}

/* ---- Cards: white, 1 px border, 12 px radius, soft shadow ---- */
.card {
    --bs-card-border-color: var(--border);
    --bs-card-border-radius: 12px;
    --bs-card-inner-border-radius: 11px;
    --bs-card-spacer-y: 1.25rem;
    --bs-card-spacer-x: 1.25rem;
    --bs-card-cap-bg: var(--surface);
    box-shadow: var(--shadow-card);
}

.card.shadow-sm {
    box-shadow: var(--shadow-card) !important;
}

/* ---- Buttons ---- */
.btn {
    --bs-btn-font-weight: 600;
}

.btn:not(.btn-sm):not(.btn-lg):not(.btn-link):not(.btn-group-sm > .btn) {
    --bs-btn-padding-x: 1.5rem;
    --bs-btn-padding-y: .5625rem;
    min-height: 44px;
}

.btn-primary {
    --bs-btn-bg: var(--navy);
    --bs-btn-border-color: var(--navy);
    --bs-btn-hover-bg: var(--ink);
    --bs-btn-hover-border-color: var(--ink);
    --bs-btn-active-bg: var(--ink);
    --bs-btn-active-border-color: var(--ink);
    --bs-btn-disabled-bg: var(--disabled-bg);
    --bs-btn-disabled-border-color: var(--disabled-bg);
    --bs-btn-disabled-color: var(--disabled-ink);
    --bs-btn-focus-shadow-rgb: 14, 59, 115;
}

/* Secondary action: 2 px green border, green text, green tint on hover. */
.btn-outline-primary,
.btn-success {
    --bs-btn-color: var(--green);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--green);
    --bs-btn-border-width: 2px;
    --bs-btn-hover-color: var(--green);
    --bs-btn-hover-bg: var(--green-tint);
    --bs-btn-hover-border-color: var(--green);
    --bs-btn-active-color: var(--green);
    --bs-btn-active-bg: var(--green-tint);
    --bs-btn-active-border-color: var(--green);
    --bs-btn-disabled-color: var(--disabled-ink);
    --bs-btn-disabled-bg: transparent;
    --bs-btn-disabled-border-color: var(--disabled-bg);
}

.btn-outline-secondary {
    --bs-btn-color: var(--ink);
    --bs-btn-bg: var(--surface);
    --bs-btn-border-color: var(--border);
    --bs-btn-hover-color: var(--ink);
    --bs-btn-hover-bg: var(--neutral-tint);
    --bs-btn-hover-border-color: var(--border-strong);
    --bs-btn-active-color: var(--ink);
    --bs-btn-active-bg: var(--neutral-tint);
    --bs-btn-active-border-color: var(--border-strong);
    --bs-btn-disabled-color: var(--neutral);
    --bs-btn-disabled-bg: var(--surface);
    --bs-btn-disabled-border-color: var(--border);
}

.btn-danger {
    --bs-btn-bg: var(--error);
    --bs-btn-border-color: var(--error);
    --bs-btn-hover-bg: var(--error-strong);
    --bs-btn-hover-border-color: var(--error-strong);
    --bs-btn-active-bg: var(--error-strong);
    --bs-btn-active-border-color: var(--error-strong);
}

.btn-outline-danger {
    --bs-btn-color: var(--error);
    --bs-btn-border-color: var(--error);
    --bs-btn-hover-color: var(--error);
    --bs-btn-hover-bg: var(--error-tint);
    --bs-btn-hover-border-color: var(--error);
    --bs-btn-active-color: var(--error);
    --bs-btn-active-bg: var(--error-tint);
    --bs-btn-active-border-color: var(--error);
}

.btn-link {
    --bs-btn-color: var(--purple);
    --bs-btn-hover-color: var(--purple-dark);
    --bs-btn-active-color: var(--purple-dark);
    --bs-btn-font-weight: 400;
}

/* ---- Status pills and tags: tint background, coloured text, a dot for status ---- */
.badge {
    --bs-badge-padding-x: .625em;
    --bs-badge-padding-y: .3em;
    --bs-badge-font-size: .8125rem;
    --bs-badge-font-weight: 600;
    --bs-badge-border-radius: 999px;
}

[dir="rtl"] .badge {
    --bs-badge-font-size: .875rem;
}

.badge.text-bg-success {
    color: var(--green) !important;
    background-color: var(--green-tint) !important;
}

.badge.text-bg-warning {
    color: var(--warning) !important;
    background-color: var(--warning-tint) !important;
}

.badge.text-bg-danger {
    color: var(--error) !important;
    background-color: var(--error-tint) !important;
}

.badge.text-bg-secondary {
    color: var(--neutral) !important;
    background-color: var(--neutral-tint) !important;
}

.badge.text-bg-primary,
.badge.text-bg-info {
    color: var(--purple) !important;
    background-color: var(--purple-tint) !important;
}

.badge.text-bg-light {
    color: var(--neutral) !important;
    background-color: var(--surface) !important;
    box-shadow: inset 0 0 0 1px var(--border);
}

.badge.text-bg-success::before,
.badge.text-bg-warning::before,
.badge.text-bg-danger::before,
.badge.text-bg-secondary::before {
    content: "";
    display: inline-block;
    width: .5em;
    height: .5em;
    margin-inline-end: .4em;
    border-radius: 50%;
    background: currentColor;
    vertical-align: .08em;
}

/* ---- Alerts (flash messages) ---- */
.alert-success {
    --bs-alert-color: var(--green);
    --bs-alert-bg: var(--green-tint);
    --bs-alert-border-color: var(--green-line);
    --bs-alert-link-color: var(--green);
}

.alert-warning {
    --bs-alert-color: var(--warning);
    --bs-alert-bg: var(--warning-tint);
    --bs-alert-border-color: var(--warning-line);
    --bs-alert-link-color: var(--warning);
}

.alert-danger {
    --bs-alert-color: var(--error);
    --bs-alert-bg: var(--error-tint);
    --bs-alert-border-color: var(--error-line);
    --bs-alert-link-color: var(--error);
}

.alert-info {
    --bs-alert-color: var(--purple);
    --bs-alert-bg: var(--purple-tint);
    --bs-alert-border-color: var(--purple-line);
    --bs-alert-link-color: var(--purple);
}

/* ---- Forms ---- */
.form-label {
    font-weight: 600;
}

/* Touch targets: at least 44 px high. */
.form-control:not(.form-control-sm):not([type="file"]):not(textarea),
.form-select:not(.form-select-sm) {
    min-height: 44px;
}

/* Field edges reach 3:1 against the white field; placeholders 4.5:1. */
.form-control,
.form-select,
.form-check-input,
.input-group > .btn-outline-secondary {
    border-color: var(--field-border);
}

.form-control::placeholder {
    color: var(--placeholder-ink);
}

.form-check-input:checked {
    background-color: var(--navy);
    border-color: var(--navy);
}

/* ---- Tables: white panel with a border, muted header ---- */
.table {
    --bs-table-color: var(--ink);
    --bs-table-bg: var(--surface);
    --bs-table-border-color: var(--border);
    --bs-table-hover-bg: var(--soft);
    --bs-table-hover-color: var(--ink);
}

.table > thead th {
    color: var(--muted);
    font-weight: 600;
    background: var(--thead);
}

.table-responsive {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
}

.table-responsive > .table {
    margin-bottom: 0;
}

.table-responsive > .table > :last-child > tr:last-child > * {
    border-bottom-width: 0;
}

/* ---- Dropdowns ---- */
.dropdown-menu {
    --bs-dropdown-border-color: var(--border);
    --bs-dropdown-border-radius: 12px;
    --bs-dropdown-link-color: var(--ink);
    --bs-dropdown-link-hover-bg: var(--neutral-tint);
    --bs-dropdown-link-active-bg: var(--navy);
    box-shadow: 0 10px 24px var(--shadow-strong);
}

.breadcrumb {
    --bs-breadcrumb-item-active-color: var(--muted);
}

.input-group [data-password-toggle] {
    display: inline-flex;
    align-items: center;
}

/* Emails, codes and keys stay left-to-right inside Arabic pages. */
[dir="rtl"] .ltr {
    direction: ltr;
    text-align: right;
}

.table td,
.table th {
    vertical-align: middle;
}

.flag {
    border-radius: 2px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, .1);
    vertical-align: -2px;
}

.wa-link {
    color: var(--green);
}

/* Phone rows on the tenant form: the template row is cloned by app.js. */
.phone-row + .phone-row {
    border-top: 1px dashed var(--bs-border-color);
    padding-top: .75rem;
}

.dl-compact dt {
    font-weight: 500;
    color: var(--bs-secondary-color);
}

/* Date fields: the native date input only provides the calendar popup, so it sits invisibly
   over the calendar button. */
[data-date] {
    position: relative;
}

.date-native {
    position: absolute;
    inset-inline-end: 0;
    top: 0;
    width: 2.75rem;
    height: 100%;
    margin: 0;
    opacity: 0;
    pointer-events: none;
    border: 0;
    padding: 0;
    cursor: pointer;
    z-index: 6;
}

/* With JavaScript the invisible native field lies exactly over the calendar button, so a tap
   lands on a real date field: phones open their own picker for that, which showPicker() from a
   button does not do reliably on iOS. */
[data-date].has-picker .date-native {
    pointer-events: auto;
}

[data-date] [data-date-button] {
    flex: none;
    width: 2.75rem;
    padding-inline: 0;
}

.date-native::-webkit-calendar-picker-indicator {
    display: none;
}

/* Vacancy calendar: day columns of equal width, bars are cells spanning their days. */
.cal {
    table-layout: fixed;
    min-width: 960px;
    font-size: .8rem;
}

.cal-quarter {
    min-width: 1300px;
}

.cal-year {
    min-width: 2600px;
}

.cal-unit-col {
    width: 7rem;
}

.cal th,
.cal td {
    padding: .2rem .15rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cal-dow {
    font-weight: 400;
    color: var(--bs-secondary-color);
}

.cal .cal-weekend {
    background: var(--bs-tertiary-bg);
}

.cal .cal-today {
    background: var(--warning-tint);
}

.cal .cal-property th {
    background: var(--bs-secondary-bg);
}

.cal-gap a {
    display: block;
    height: 1.25rem;
}

.cal-gap a:hover {
    background: var(--placeholder);
}

.cal-bar a {
    display: block;
    color: #fff;
    text-decoration: none;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Scoped under .cal so they win over Bootstrap's .table cell background. */
.cal .cal-contract.cal-active,
.cal-key.cal-active {
    background: var(--green);
}

.cal .cal-contract.cal-ended,
.cal .cal-contract.cal-terminated,
.cal-key.cal-ended {
    background: var(--neutral);
}

.cal .cal-block,
.cal-key.cal-block {
    background: var(--warning);
}

.cal-key {
    display: inline-block;
    width: .9rem;
    height: .9rem;
    border-radius: 2px;
    vertical-align: -2px;
}

/* Summary card figures (H3 weight). */
.card .fs-4 {
    font-weight: 700;
}

/* Amounts and codes never break across lines; on phones the table scrolls instead. */
.table td[dir="ltr"],
.table td > [dir="ltr"] {
    white-space: nowrap;
}

/* ---- Design pass 3a: shared parts ---- */

/* Page header (partials/page_header): title and subtitle at the start, actions at the end edge. */
.page-head {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: flex-start;
    gap: 12px 16px;
    margin-bottom: 24px;
}

.page-head h1 {
    margin-bottom: 4px;
}

.page-head .page-sub {
    color: var(--muted);
    margin: 0;
}

.page-head .page-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* Amounts: end-aligned columns with tabular figures; the amount itself always reads left to right. */
.num {
    text-align: end;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.money {
    direction: ltr;
    unicode-bidi: isolate;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* Dates, receipt and contract numbers inside running text keep their own order. */
.ltr-run {
    direction: ltr;
    unicode-bidi: isolate;
}

/* Empty state (partials/empty): a short explanation and the main action. */
.empty-state {
    background: var(--surface);
    border: 1px dashed var(--border);
    border-radius: 12px;
    padding: 32px 20px;
    text-align: center;
    color: var(--muted);
}

.empty-state img {
    opacity: .45;
    margin-bottom: 12px;
}

.empty-state p {
    margin: 0 auto 4px;
    max-width: 36rem;
}

.empty-state .empty-title {
    color: var(--ink);
    font-weight: 600;
}

.empty-state .btn {
    margin-top: 12px;
}

/* File picker (partials/file_input): a translated button and the chosen file's name. */
.file-pick {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.file-pick input[type="file"] {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    overflow: hidden;
}

.file-pick input[type="file"]:focus-visible + label {
    outline: 2px solid var(--navy-ink);
    outline-offset: 2px;
}

.file-pick .file-name {
    color: var(--muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.file-pick.is-invalid .btn {
    border-color: var(--error);
}

/* Tabs on long pages (contract page). Without JavaScript every section shows in order. */
.page-tabs {
    border-bottom: 1px solid var(--border);
    margin-bottom: 24px;
    gap: 4px;
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
}

.page-tabs .nav-link {
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    color: var(--muted);
    font-weight: 600;
    padding: 10px 16px;
    white-space: nowrap;
    background: none;
}

.page-tabs .nav-link.active {
    color: var(--navy-ink);
    border-bottom-color: var(--navy-ink);
    background: none;
}

.page-tabs .count {
    font-weight: 400;
    color: var(--muted);
}

.tab-section + .tab-section {
    margin-top: 32px;
}

.tabs-ready .tab-section + .tab-section {
    margin-top: 0;
}

/* Balance strip at the top of the contract page: one card per currency. */
.balance-strip {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 12px;
    margin-bottom: 24px;
}

.balance-strip .card-body {
    padding: 14px 18px;
}

.balance-strip .label {
    color: var(--muted);
    font-size: .875rem;
}

.balance-strip .figure {
    font-size: 1.25rem;
    font-weight: 700;
}

/* Row actions: a quiet button per row. */
.row-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    justify-content: flex-end;
}

/* Phones: list tables become stacked cards. app.js copies each column header into data-label. */
@media (max-width: 575.98px) {
    .table-stack thead {
        display: none;
    }

    .table-stack,
    .table-stack tbody,
    .table-stack tfoot,
    .table-stack tr,
    .table-stack td,
    .table-stack th[scope="row"] {
        display: block;
        width: 100%;
    }

    .table-stack tr {
        border-bottom: 1px solid var(--border);
        padding: 8px 4px;
    }

    .table-stack tbody tr:last-child {
        border-bottom: 0;
    }

    .table-stack > :not(caption) > * > * {
        border-bottom: 0;
        padding: 4px 12px;
    }

    .table-stack td[data-label] {
        display: flex;
        justify-content: space-between;
        align-items: baseline;
        gap: 16px;
        text-align: end;
    }

    .table-stack td[data-label]::before {
        content: attr(data-label);
        color: var(--muted);
        font-size: .875rem;
        text-align: start;
        flex-shrink: 0;
    }

    .table-stack td:first-child {
        font-weight: 600;
    }

    .table-stack .row-actions {
        justify-content: flex-start;
    }

    .table-responsive:has(> .table-stack) {
        overflow-x: visible;
    }
}

/* Keep end-aligned amounts clear of the next column. */
.table .num {
    padding-inline-end: 24px;
}

@media (max-width: 575.98px) {
    /* Cells with fields or long text wrap under their label instead of overflowing. */
    .table-stack td[data-label] {
        flex-wrap: wrap;
    }

    .table-stack td[data-label] > .form-control,
    .table-stack td[data-label] > .form-select {
        flex: 1 1 10rem;
        width: auto;
    }

    .table-stack td[data-label] > span:not(.badge):not(.money) {
        white-space: normal;
        overflow-wrap: anywhere;
    }

    /* Empty cells add nothing to a card. */
    .table-stack td.is-empty {
        display: none;
    }
}

@media (max-width: 575.98px) {
    /* Price lines: component and currency side by side, the amount below at full width. */
    .lines-table thead {
        display: none;
    }

    .lines-table tbody tr {
        display: grid;
        grid-template-columns: 1fr 1fr;
        grid-template-areas: "component currency" "amount amount" "remove remove";
        gap: 8px;
        padding: 10px 12px;
        border-bottom: 1px solid var(--border);
    }

    .lines-table tbody td {
        display: block;
        padding: 0;
        border: 0;
    }

    .lines-table tbody td:nth-child(1) { grid-area: component; }
    .lines-table tbody td:nth-child(2) { grid-area: amount; }
    .lines-table tbody td:nth-child(3) { grid-area: currency; }
    .lines-table tbody td:nth-child(4) { grid-area: remove; text-align: start !important; }
}

/* Due and overdue page: one collapsed row per contract, its charges inside. */
.due-groups {
    display: grid;
    gap: 8px;
}

.due-group {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
}

.due-group > summary {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1.5fr) minmax(0, 1.5fr) auto;
    gap: 8px 16px;
    align-items: center;
    padding: 12px 16px;
    cursor: pointer;
    list-style: none;
}

.due-group > summary::-webkit-details-marker {
    display: none;
}

.due-group > summary::after {
    content: "";
    width: 8px;
    height: 8px;
    border-inline-end: 2px solid var(--muted);
    border-bottom: 2px solid var(--muted);
    transform: rotate(45deg);
    justify-self: end;
    grid-column: -1;
    grid-row: 1;
    margin-inline-start: 24px;
    transition: transform .15s;
}

.due-group[open] > summary::after {
    transform: rotate(-135deg);
}

.due-group[open] > summary {
    border-bottom: 1px solid var(--border);
}

.due-group > summary:focus-visible {
    outline: 2px solid var(--navy-ink);
    outline-offset: 2px;
    border-radius: 12px;
}

.due-who,
.due-when {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    min-width: 0;
}

.due-total {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    text-align: end;
    padding-inline-end: 32px;
}

.due-group .table-responsive {
    border: 0;
    border-radius: 0;
}

.due-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 12px 16px;
    border-top: 1px solid var(--border);
}

@media (max-width: 767.98px) {
    .due-group > summary {
        grid-template-columns: minmax(0, 1fr) auto;
    }

    .due-tenant {
        grid-column: 1;
    }

    .due-when {
        grid-column: 1;
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
    }

    .due-total {
        grid-column: 2;
        grid-row: 1 / span 3;
        align-self: center;
    }

    @media (prefers-reduced-motion: reduce) {
        .due-group > summary::after {
            transition: none;
        }
    }
}

/* Record payment: total still owed per currency under "What it pays". */
.pay-total th,
.pay-total td {
    background: var(--soft);
    border-top: 2px solid var(--border);
    border-bottom: 0;
}

@media (max-width: 575.98px) {
    .table-stack .pay-total {
        display: block;
        width: 100%;
    }

    .table-stack .pay-total tr {
        width: 100%;
        display: flex;
        justify-content: space-between;
        align-items: baseline;
        gap: 16px;
        padding: 10px 12px;
        background: var(--soft);
        border-top: 1px solid var(--border);
    }

    .table-stack .pay-total th,
    .table-stack .pay-total td {
        background: transparent;
    }

    .table-stack .pay-total th,
    .table-stack .pay-total td {
        display: block;
        width: auto;
        border: 0;
        padding: 0;
    }

    .table-stack .pay-total td:empty {
        display: none;
    }
}

/* Settings: collapsible groups, each a compact table (setting, value, help). */
.settings-group {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    margin-bottom: 12px;
}

.settings-group > summary {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 12px;
    padding: 14px 16px;
    cursor: pointer;
}

.settings-group[open] > summary {
    border-bottom: 1px solid var(--border);
}

.settings-group .table-responsive {
    border: 0;
    border-radius: 0 0 12px 12px;
}

.settings-table th[scope="row"] {
    width: 30%;
    font-weight: 600;
    color: var(--ink);
    background: transparent;
}

.settings-table .settings-value {
    width: 32%;
    min-width: 12rem;
}

.settings-save {
    position: sticky;
    bottom: 0;
    padding: 12px 0;
    background: var(--bg);
    margin-bottom: 12px;
}

@media (max-width: 767.98px) {
    .settings-table tr {
        display: grid;
        grid-template-columns: 1fr;
        padding: 8px 4px;
        border-bottom: 1px solid var(--border);
    }

    .settings-table th[scope="row"],
    .settings-table td {
        display: block;
        width: auto;
        border: 0;
        padding: 2px 8px;
    }
}

/* Needs attention: bell in the top bar and the list page. */
.attention-bell {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 8px;
    color: var(--navy-ink);
}

.attention-bell:hover,
.attention-bell.active {
    background: var(--neutral-tint);
    color: var(--navy-ink);
}

.attention-bell:focus-visible {
    outline: 2px solid var(--navy-ink);
    outline-offset: 2px;
}

.attention-count {
    position: absolute;
    top: 2px;
    inset-inline-end: 0;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    line-height: 18px;
    text-align: center;
    color: #fff;
    background: var(--warning);
}

.attention-count-danger {
    background: var(--error);
}

.attention-list {
    list-style: none;
    padding: 0;
    margin: 0;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
}

.attention-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 16px;
    border-inline-start: 4px solid transparent;
}

.attention-item + .attention-item {
    border-top: 1px solid var(--border);
}

.attention-danger {
    border-inline-start-color: var(--error);
}

.attention-warning {
    border-inline-start-color: var(--warning);
}

.attention-info {
    border-inline-start-color: var(--border);
}

.attention-text {
    min-width: 0;
}

.attention-text .badge {
    margin-inline-end: 6px;
}

@media (max-width: 575.98px) {
    .attention-item {
        flex-direction: column;
        align-items: flex-start;
    }
}

/* ---- Checks and inventory (iteration 6) ---- */
.photo-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: .75rem;
}

.photo-tile {
    margin: 0;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: .5rem;
    text-align: center;
}

.photo-tile img {
    display: block;
    width: 100%;
    height: 120px;
    object-fit: cover;
    border-radius: 8px;
    margin-bottom: .25rem;
}

.qty-input {
    width: 4.5rem;
}

.cost-input {
    min-width: 11rem;
}

.cost-input .form-select {
    flex: 0 0 5.5rem;
}

/* ---- Passkeys (iteration 6a) ---- */
/* The Face ID / fingerprint button next to Sign in; it pulses while the device prompt is open. */
/* Other ways in on the login page: icon + label, full width. */
.auth-alt {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
}

/* The one-time code: large, spaced digits. */
.otp-input {
    font-size: 1.75rem;
    letter-spacing: .5em;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.auth-divider {
    display: flex;
    align-items: center;
    gap: .75rem;
    color: var(--muted);
    font-size: .875rem;
}

.auth-divider::before,
.auth-divider::after {
    content: "";
    flex: 1;
    border-top: 1px solid var(--border);
}

.passkey-btn.is-busy {
    animation: passkey-pulse 1.2s ease-in-out infinite;
}

@keyframes passkey-pulse {
    50% { box-shadow: 0 0 0 6px var(--green-tint); }
}

@media (prefers-reduced-motion: reduce) {
    .passkey-btn.is-busy { animation: none; }
}

/* Portal "I paid": the folded "What it pays" section. */
.pay-split > summary {
    cursor: pointer;
    list-style: none;
}

.pay-split > summary::-webkit-details-marker {
    display: none;
}

.pay-split > summary::after {
    content: "";
    width: 8px;
    height: 8px;
    border-inline-end: 2px solid var(--muted);
    border-bottom: 2px solid var(--muted);
    transform: rotate(45deg);
    margin-inline-start: auto;
    align-self: center;
    transition: transform .15s;
}

.pay-split[open] > summary::after {
    transform: rotate(-135deg);
}

.pay-split > summary:focus-visible {
    outline: 2px solid var(--navy-ink);
    outline-offset: 2px;
}

/* Dashboard: converted totals in the report currency (≈ USD), kept visually apart from real amounts. */
.usd-total {
    margin-top: .5rem;
    padding-top: .5rem;
    border-top: 1px dashed var(--border);
    font-size: .875rem;
    font-weight: 600;
    color: var(--navy-ink);
}

.usd-col {
    color: var(--navy-ink);
}

tr.usd-row td {
    border-top: 2px solid var(--border);
    color: var(--navy-ink);
    font-weight: 600;
    background: var(--navy-wash);
}

/* Charges grouped by month (contract page, portal): a header row per month. */
.charge-months tr.month-head td {
    background: var(--bg);
    border-top: 2px solid var(--border);
    font-weight: 600;
    color: var(--navy-ink);
}

.charge-months .month-sub {
    font-weight: 400;
    font-size: .8rem;
    color: var(--muted);
    margin-inline-start: .5rem;
}

.charge-months .month-totals {
    float: inline-end;
    font-size: .875rem;
}

@media (max-width: 767.98px) {
    .charge-months tr.month-head td {
        display: block;
    }

    .charge-months tr.month-head td::before {
        display: none;
    }

    .charge-months .month-totals {
        float: none;
        display: block;
    }
}

/* ---- Review of 11 Oct 2026 (docs/enhancements.md) ---- */

/* Small button groups (the period filter) are small buttons: one line, the height of the
   selects and arrows beside them. */
.btn-group-sm > .btn {
    white-space: nowrap;
}

.period-filter {
    max-width: 100%;
}

.period-filter > .btn-group {
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
}

/* Amounts in Arabic tables read left to right, so a minus sign stays in front of its number. */
[dir="rtl"] td.num {
    unicode-bidi: plaintext;
    text-align: left;
}

/* Page tabs wider than the screen fade at the edge that holds more (app.js sets the classes). */
.page-tabs.more-end {
    -webkit-mask-image: linear-gradient(to left, transparent, #000 40px);
    mask-image: linear-gradient(to left, transparent, #000 40px);
}

.page-tabs.more-start {
    -webkit-mask-image: linear-gradient(to right, transparent, #000 40px);
    mask-image: linear-gradient(to right, transparent, #000 40px);
}

.page-tabs.more-start.more-end {
    -webkit-mask-image: linear-gradient(to right, transparent, #000 40px, #000 calc(100% - 40px), transparent);
    mask-image: linear-gradient(to right, transparent, #000 40px, #000 calc(100% - 40px), transparent);
}

[dir="rtl"] .page-tabs.more-end:not(.more-start) {
    -webkit-mask-image: linear-gradient(to right, transparent, #000 40px);
    mask-image: linear-gradient(to right, transparent, #000 40px);
}

[dir="rtl"] .page-tabs.more-start:not(.more-end) {
    -webkit-mask-image: linear-gradient(to left, transparent, #000 40px);
    mask-image: linear-gradient(to left, transparent, #000 40px);
}

/* A job's result line wraps inside its column instead of widening the table. */
.job-result {
    white-space: normal !important;
    overflow-wrap: anywhere;
    max-width: 28rem;
}

.jobs-table td:first-child {
    min-width: 14rem;
}

/* The installed app has no browser bar: keep the header clear of the status bar and the sides
   clear of the notch (the tab bar already adds the bottom inset). Needs viewport-fit=cover. */
.site-header {
    padding-top: env(safe-area-inset-top, 0);
}

@media (max-width: 699.98px) {
    .site-header > .container-fluid,
    .page {
        padding-left: max(16px, env(safe-area-inset-left, 0px));
        padding-right: max(16px, env(safe-area-inset-right, 0px));
    }
}

@media (max-width: 767.98px) {
    /* The tab bar ends the page on phones; the footer under it only left an empty strip. */
    .has-tabbar .site-footer {
        display: none;
    }

    /* Small controls are still easy to tap. */
    .btn-sm,
    .btn-group-sm > .btn,
    .form-control-sm,
    .form-select-sm {
        min-height: 40px;
    }

    .btn-sm,
    .btn-group-sm > .btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }

    .jobs-table td:first-child {
        min-width: 0;
    }

    .job-result {
        max-width: none;
    }
}

/* Keyboard users jump past the menu with the first Tab. */
.skip-link:focus {
    position: fixed;
    top: 8px;
    inset-inline-start: 8px;
    z-index: 2000;
    padding: 8px 16px;
    border-radius: 8px;
    background: var(--surface);
    color: var(--navy-ink);
    font-weight: 600;
}

main:focus {
    outline: 0;
}

/* Installed app: the page runs under the phone's status bar (viewport-fit=cover), and iOS softens
   whatever scrolls beneath it. A header pinned to the top keeps a solid bar there instead, so
   only the header's own white padding sits under the status bar. */
@media (display-mode: standalone) {
    .site-header {
        position: sticky;
        top: 0;
        z-index: 1030;
    }

    html {
        scroll-padding-top: calc(72px + env(safe-area-inset-top, 0px));
    }
}

/* ---- Second review batch (docs/enhancements.md) ---- */

/* One look for every summary figure: the balance strip's label and figure, also on the
   dashboard's stat cards. */
.stat-card .label,
.balance-strip .label {
    color: var(--muted);
    font-size: .875rem;
}

/* Dashboard to-do rows: the category on its own line, then the title and the detail. */
.todo-item .badge {
    margin-bottom: 4px;
}

@media (max-width: 575.98px) {
    /* Two buttons side by side (Record payment, Statement) stay on one line each. */
    .btn:not(.btn-sm):not(.btn-lg):not(.btn-link):not(.btn-group-sm > .btn) {
        --bs-btn-padding-x: 1rem;
        white-space: nowrap;
    }

    /* Stacked cards whose value is a block of lines (dashboard by property) keep the block
       together at the end of the row. */
    .table-stack td[data-label] > div {
        text-align: end;
    }

    .table-stack tr.usd-row td {
        font-weight: 600;
    }
}

/* Third review batch (12 Oct 2026). A thin bar at the top while the next page loads: the
   installed app has no browser bar to show it. It shows at once: pages load in well under a second,
   so a bar that waited was never seen. */
.nav-progress {
    position: fixed;
    top: env(safe-area-inset-top, 0px);
    inset-inline: 0;
    height: 4px;
    z-index: 2000;
    pointer-events: none;
    opacity: 0;
    background: linear-gradient(90deg, transparent, var(--green), transparent) no-repeat;
    background-size: 40% 100%;
    animation: nav-progress-in .1s forwards, nav-progress 1.1s linear infinite;
}

@keyframes nav-progress-in {
    to { opacity: 1; }
}

@keyframes nav-progress {
    from { background-position: -70% 0; }
    to { background-position: 170% 0; }
}

/* The button that sent the form shows a spinner in place of its label until the next page. */
.btn.is-busy {
    position: relative;
    color: transparent !important;
}

.btn.is-busy::after {
    content: "";
    position: absolute;
    inset: 0;
    margin: auto;
    width: 1rem;
    height: 1rem;
    border: 2px solid var(--bs-btn-disabled-color, var(--muted));
    border-inline-end-color: transparent;
    border-radius: 50%;
    animation: btn-busy .7s linear infinite;
}

@keyframes btn-busy {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .nav-progress {
        background-size: 100% 100%;
        animation: nav-progress-in .1s forwards;
    }

    .btn.is-busy::after {
        animation-duration: 2s;
    }
}

/* A dashboard card opens the list behind its figure: the label is the link, stretched over the
   card, with a chevron so it reads as one on a phone too. */
.stat-card .label a {
    color: inherit;
    text-decoration: none;
    display: flex;
    justify-content: space-between;
    gap: .5rem;
}

.stat-card .label a::before {
    content: "\203A";
    order: 2;
    font-size: 1.25rem;
    line-height: 1;
    color: var(--field-border);
}

[dir="rtl"] .stat-card .label a::before {
    content: "\2039";
}

.stat-card:has(a.stretched-link):hover {
    border-color: var(--field-border);
    box-shadow: var(--shadow-card);
}

.stat-card a.stretched-link:focus-visible {
    outline: 0;
}

.stat-card:has(a.stretched-link:focus-visible) {
    outline: 2px solid var(--purple);
    outline-offset: 2px;
}

/* A list row that opens its record (app.js): the whole row, or the whole card on a phone. */
tr.row-link {
    cursor: pointer;
}

tr.row-link:hover > * {
    --bs-table-bg-state: var(--bs-tertiary-bg);
}

/* Installed app on a phone (owner's notes, 12 Oct 2026).
   iOS lets the page bounce past its ends, and the bottom bar and the pinned header ride along
   with the bounce: switch the bounce off, and continue the bar's surface below it so no gap can
   show under it either way. */
@media (display-mode: standalone) {
    html,
    body {
        overscroll-behavior-y: none;
    }
}

.tabbar::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    top: 100%;
    height: 120px;
    background: var(--surface);
}

/* A phone held sideways has no status bar, so the header sat against the very top edge, and the
   notch is at one side: give the header some air on top and keep everything clear of the notch. */
@media (orientation: landscape) and (max-height: 500px) {
    .site-header {
        padding-top: max(10px, env(safe-area-inset-top, 0px));
        padding-left: env(safe-area-inset-left, 0px);
        padding-right: env(safe-area-inset-right, 0px);
    }

    .page {
        padding-left: max(16px, env(safe-area-inset-left, 0px));
        padding-right: max(16px, env(safe-area-inset-right, 0px));
    }

    .site-footer > div,
    .tabbar {
        padding-left: env(safe-area-inset-left, 0px);
        padding-right: env(safe-area-inset-right, 0px);
    }
}

@media (orientation: landscape) and (max-height: 500px) and (min-width: 700px) {
    .page {
        padding-left: max(40px, env(safe-area-inset-left, 0px));
        padding-right: max(40px, env(safe-area-inset-right, 0px));
    }
}

/* Total rows under a stacked table (phones): a card per total, each figure with its column's
   name, like the rows above them. */
@media (max-width: 575.98px) {
    .table-stack tfoot:not(.pay-total) {
        border-top: 2px solid var(--border);
    }

    .table-stack tfoot:not(.pay-total) td:first-child {
        font-weight: 700;
    }

    .table-stack tfoot:not(.pay-total) td:empty {
        display: none;
    }
}

/* Summary tiles on a phone: two fixed columns clipped amounts in the millions. Each tile is as
   wide as its figure needs, and they share the row or wrap. */
@media (max-width: 575.98px) {
    .balance-strip {
        display: flex;
        flex-wrap: wrap;
    }

    .balance-strip > .card {
        flex: 1 1 150px;
        min-width: max-content;
        max-width: 100%;
    }
}

/* ---- Phone layout batch (12 Oct 2026) ---- */

/* The calendar as a list on phones: one card per unit, a line per stay, block or free stretch. */
.cal-seg {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding-top: 8px;
    margin-top: 8px;
    border-top: 1px solid var(--border);
}

.cal-seg .cal-key {
    flex: none;
}

.cal-key.cal-free {
    background: var(--surface);
    border: 1px dashed var(--field-border);
}

@media (max-width: 575.98px) {
    /* Filter rows: two fields side by side, so the filters take two or three rows instead of
       one each before any content. A search box keeps the full width. */
    form[data-auto-filter].row > [class*="col-sm-"]:not(:has(input[type="search"])),
    form[data-auto-filter] .row > [class*="col-sm-"]:not(:has(input[type="search"])) {
        flex: 0 0 auto;
        width: 50%;
    }

    /* A stacked cell that holds several lines (price history) keeps them together at the end. */
    .table-stack td[data-label] > div > div {
        text-align: end;
    }

    .table-stack th[scope="row"] {
        text-align: start;
        font-weight: 600;
    }
}

/* ---- Dark theme (12 Oct 2026) -------------------------------------------------------------
   Set by theme.js on <html>: the device's setting, or the user's choice in My account. The
   brand guide gives the white logo on navy but no colours for dark screens, so these are drawn
   from its navy and ink: ink-blue surfaces, the same hues lightened for text, and the status
   colours as light text on deep tints. Checked for 4.5:1 on text. */
:root[data-theme="dark"] {
    color-scheme: dark;
    --navy: #1F5AA6;
    --navy-ink: #A9C8F5;
    --ink: #E8EEF7;
    --muted: #A7B2C6;
    --bg: #0A1322;
    --surface: #131F34;
    --border: #2B3B57;
    --placeholder: #1C2B45;
    --purple: #BBA9F4;
    --purple-dark: #D3C7FA;
    --purple-tint: #2B2452;
    --green: #63CF93;
    --green-tint: #12382B;
    --warning: #F4AD68;
    --warning-tint: #3E2B15;
    --error: #F79489;
    --error-tint: #421E1B;
    --neutral: #B6C0D2;
    --neutral-tint: #243049;
    --field-border: #62728F;
    --shadow-card: 0 4px 12px rgba(0, 0, 0, .35);
    --soft: #182641;
    --thead: #1B2A47;
    --disabled-bg: #24324C;
    --disabled-ink: #8492AB;
    --border-strong: #3A4C6C;
    --error-strong: #C2362A;
    --green-line: #23604A;
    --warning-line: #6B4A22;
    --error-line: #6E302B;
    --purple-line: #473C82;
    --placeholder-ink: #8E9AB1;
    --navy-wash: rgba(169, 200, 245, .08);
    --shadow-strong: rgba(0, 0, 0, .5);

    --bs-body-color-rgb: 232, 238, 247;
    --bs-body-bg-rgb: 19, 31, 52;
    --bs-primary-rgb: 31, 90, 166;
    --bs-secondary-rgb: 182, 192, 210;
    --bs-success-rgb: 99, 207, 147;
    --bs-warning-rgb: 244, 173, 104;
    --bs-danger-rgb: 247, 148, 137;
    --bs-info-rgb: 187, 169, 244;
    --bs-link-color-rgb: 187, 169, 244;
    --bs-link-hover-color-rgb: 211, 199, 250;
    --bs-secondary-bg: var(--placeholder);
    --bs-tertiary-bg: var(--soft);
    --bs-focus-ring-color: rgba(169, 200, 245, .35);
    --bs-emphasis-color-rgb: 255, 255, 255;
    --bs-secondary-color: var(--muted);
    --bs-tertiary-color: var(--muted);
    --bs-border-color-translucent: rgba(255, 255, 255, .12);
    --bs-warning-text-emphasis: var(--warning);
    --bs-danger-text-emphasis: var(--error);
    --bs-success-text-emphasis: var(--green);
    --bs-primary-border-subtle: var(--border-strong);
    --bs-danger-border-subtle: var(--error-line);
}

/* Fills that carry white text keep a deep tone in the dark theme. */
[data-theme="dark"] .btn-primary {
    --bs-btn-hover-bg: #2A6BBE;
    --bs-btn-hover-border-color: #2A6BBE;
    --bs-btn-active-bg: #2A6BBE;
    --bs-btn-active-border-color: #2A6BBE;
    --bs-btn-color: #fff;
}

[data-theme="dark"] .btn-outline-primary {
    --bs-btn-hover-color: #0A1322;
    --bs-btn-active-color: #0A1322;
}

[data-theme="dark"] .btn-danger,
[data-theme="dark"] .btn-outline-danger {
    --bs-btn-hover-color: #fff;
    --bs-btn-active-color: #fff;
}

[data-theme="dark"] .btn-danger {
    --bs-btn-bg: #C2362A;
    --bs-btn-border-color: #C2362A;
    --bs-btn-color: #fff;
}

[data-theme="dark"] .text-bg-light,
[data-theme="dark"] .alert-light,
[data-theme="dark"] .btn-light {
    background-color: var(--soft) !important;
    color: var(--ink) !important;
    border-color: var(--border);
}

[data-theme="dark"] .text-danger {
    color: var(--error) !important;
}

[data-theme="dark"] .text-success {
    color: var(--green) !important;
}

[data-theme="dark"] .table {
    --bs-table-color: var(--ink);
    --bs-table-bg: transparent;
    --bs-table-border-color: var(--border);
    --bs-table-striped-bg: var(--soft);
}

[data-theme="dark"] .form-control,
[data-theme="dark"] .form-select,
[data-theme="dark"] .input-group-text {
    background-color: #0F1A2D;
    color: var(--ink);
}

[data-theme="dark"] .form-control:disabled,
[data-theme="dark"] .form-select:disabled {
    background-color: var(--disabled-bg);
    color: var(--disabled-ink);
}

[data-theme="dark"] .site-footer {
    background: #0D2A52;
}

/* Flags and photos stay as they are; drawings in navy that have no white twin are lightened. */
[data-theme="dark"] .empty-state img {
    opacity: .9;
}

/* Calendar bars carry white text, so they keep deep fills in the dark theme. */
[data-theme="dark"] .cal .cal-contract.cal-active,
[data-theme="dark"] .cal-key.cal-active {
    background: #1F7A4A;
}

[data-theme="dark"] .cal .cal-contract.cal-ended,
[data-theme="dark"] .cal .cal-contract.cal-terminated,
[data-theme="dark"] .cal-key.cal-ended {
    background: #55617A;
}

[data-theme="dark"] .cal .cal-block,
[data-theme="dark"] .cal-key.cal-block {
    background: #A8560E;
}
