:root {
    --navy: #504F53;
    --navy-light: #6D6E71;
    --accent: #FAB613;
    --accent-light: rgba(250, 182, 19, 0.15);
    --accent-dark: #E0A20E;
    --border: #B6B7B9;
    --text: #23303c;
    --text-muted: #6D6E71;
    --bg: #f4f6f8;
    --surface: #ffffff;
    --danger: #b3261e;
    --warning: #DF5E24;
    --radius: 8px;
    --label-green: #62B42C;
    --label-green-light: #89C97F;
    --label-orange: #DF5E24;
    --label-purple: #8E75B5;
    --label-pink: #A73C68;
    --label-blue: #2F6FED;
}

* { box-sizing: border-box; }

/* Always hide scrollbars (macOS overlays them by default; Windows shows fixed
   bars, sometimes in odd positions). Scrolling still works — only the visible
   bar is suppressed, for a consistent look across platforms. */
* {
    scrollbar-width: none;         /* Firefox */
    -ms-overflow-style: none;      /* legacy Edge/IE */
}
*::-webkit-scrollbar { width: 0; height: 0; display: none; }  /* Chromium/Safari */

html, body { height: 100%; }

body {
    margin: 0;
    display: flex;
    flex-direction: column;
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    color: var(--text);
    background: var(--bg);
}

a { color: var(--accent-dark); text-decoration: none; }
a:hover { text-decoration: underline; }

.topbar {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: nowrap;
    background: var(--navy);
    color: #fff;
    padding: calc(0.55rem + env(safe-area-inset-top, 0px)) 1.5rem 0.55rem;
    overflow: hidden;
}

.topbar-left { display: flex; align-items: center; min-width: 0; }

.topbar .brand {
    color: #fff;
    font-weight: 700;
    font-size: 1rem;
    letter-spacing: 0.02em;
    white-space: nowrap;
    display: flex;
    align-items: center;
}

.brand-logo { display: block; height: 28px; width: auto; }

.topbar-title {
    margin-left: 0.85rem;
    padding-left: 0.85rem;
    border-left: 1px solid rgba(255, 255, 255, 0.25);
    font-weight: 600;
    font-size: 1rem;
}

.topnav {
    display: flex;
    align-items: center;
    gap: 1.25rem;
    font-size: 0.85rem;
}

.topnav a { color: #d9d9d9; }
.topnav .user-name { color: #fff; }

.subheader {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 0.6rem;
    background: #eef1f4;
    border-bottom: 1px solid var(--border);
    padding: 0.4rem 1.5rem;
    font-size: 0.8rem;
}

.subheader .back-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 6px;
    color: var(--text-muted);
    font-size: 0.95rem;
    flex-shrink: 0;
}

.subheader .back-btn:hover { background: #e2e7eb; text-decoration: none; }

.subheader-crumbs { color: var(--text-muted); }
.subheader-crumbs .sep { margin: 0 0.4rem; }

.subheader-mobile-back { display: none; margin-left: auto; font-weight: 600; flex-shrink: 0; }

.page {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    max-width: 1100px;
    width: 100%;
    margin: 0 auto;
    padding: 1.5rem;
}

.page.wide {
    max-width: 1500px;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding: 1rem 1.25rem;
}

h1 { font-size: 1.5rem; margin: 0 0 1.25rem; }
h2 { font-size: 1.15rem; margin: 1.75rem 0 0.75rem; }

.subtitle {
    color: var(--text-muted);
    margin-top: -0.75rem;
    margin-bottom: 1.5rem;
    max-width: 640px;
    margin-left: auto;
    margin-right: auto;
}

.subtitle.wide { max-width: 1100px; }

/* Tile grid (homepage & module landing pages) */
.tile-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 1.25rem;
}

.tile {
    display: grid;
    grid-template-rows: 1fr 1fr;
    justify-items: center;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 2rem 1.25rem;
    aspect-ratio: 1 / 1;
    text-align: center;
    color: var(--text);
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.tile:hover {
    box-shadow: 0 4px 14px rgba(28, 43, 58, 0.12);
    transform: translateY(-2px);
    text-decoration: none;
}

/* Row 1: icon+label bottom-align to the tile's vertical center; row 2: description
   top-aligns to that same center — so both stay put regardless of description length. */
.tile-header {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.6rem;
    align-self: end;
}

.tile-icon {
    width: 2.5rem;
    height: 2.5rem;
    color: var(--accent-dark);
    flex-shrink: 0;
}

.tile-label {
    font-weight: 700;
    font-size: 1.05rem;
}

.tile-description {
    font-weight: 400;
    font-size: 0.82rem;
    color: var(--text-muted);
    line-height: 1.35;
    align-self: start;
    margin-top: 0.6rem;
}

.tile .tile-count {
    font-weight: 400;
    font-size: 0.8rem;
    color: var(--text-muted);
}

@media (max-width: 640px) {
    .tile-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 0.8rem; }
    .tile { padding: 1.25rem 0.8rem; }
    .tile-header { gap: 0.4rem; }
    .tile-icon { width: 2rem; height: 2rem; }
    .tile-label { font-size: 0.92rem; }
    .tile-description { font-size: 0.75rem; margin-top: 0.4rem; }
}

/* Cards */
.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 1.25rem 1.5rem;
    margin-bottom: 1.25rem;
}

/* Tables */
table {
    width: 100%;
    border-collapse: collapse;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
}

th, td {
    text-align: left;
    padding: 0.65rem 0.9rem;
    border-bottom: 1px solid var(--border);
    font-size: 0.92rem;
}

th {
    background: #eef1f4;
    color: var(--text-muted);
    font-weight: 600;
    text-transform: uppercase;
    font-size: 0.75rem;
    letter-spacing: 0.03em;
}

tbody tr:last-child td { border-bottom: none; }
tbody tr:hover { background: var(--accent-light); }

tr.row-link { cursor: pointer; }
th.col-tight, td.col-tight { padding-left: 0.5rem; padding-right: 0.5rem; white-space: nowrap; }
th.col-center, td.col-center { text-align: center; }

@media (max-width: 640px) {
    .col-hide-mobile { display: none; }
}

/* Shrink-wraps to its widest child (the table) so a sibling full-width element
   (the page-header-row) can match the table's true rendered width via width:100%,
   instead of stretching to the page's own max-width. */
.shrink-wrap { display: inline-block; max-width: 100%; overflow-x: auto; }
.shrink-wrap > .page-header-row { width: 100%; max-width: none; position: static; }
.shrink-wrap table { width: auto; }
.shrink-wrap th, .shrink-wrap td { white-space: nowrap; }

/* Bulk plot-entry table column widths, sized to their actual content so the
   whole table fits without horizontal scroll (see plot_bulk_form.php). */
.bulk-plot-table td { padding: 0.5rem 0.4rem; white-space: nowrap; }
.bulk-plot-table th { padding: 0.5rem 0.4rem; white-space: normal; vertical-align: bottom; }
.bulk-plot-table input, .bulk-plot-table select { width: 100%; box-sizing: border-box; padding: 0.35rem 0.4rem; font-size: 0.85rem; }
.bulk-plot-table .currency-input-wrap { display: block; }
.bulk-plot-table .currency-input-wrap input { text-align: right; }

/* Native number-input spinners eat into the already-narrow Beds/Baths/spaces
   columns and hide the digit behind them - remove them, the columns are too
   tight to spare the width and a plain narrow text-like number field is fine. */
.bulk-plot-table input[type=number]::-webkit-outer-spin-button,
.bulk-plot-table input[type=number]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
.bulk-plot-table input[type=number] { -moz-appearance: textfield; }

/* Bulk table selects don't sit inside .field, so they miss the app's usual
   custom chevron + right-padding - without it the native arrow overlaps the
   end of the longest option text. Reuse the same chevron here. */
.bulk-plot-table select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M5 8l5 5 5-5' stroke='%2364748b' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.3rem center;
    background-size: 0.7rem;
    padding-right: 1.3rem;
}

.bulk-plot-table col.col-plot { width: 3.5rem; }
.bulk-plot-table col.col-house-type { width: 10.5rem; }
.bulk-plot-table col.col-num1 { width: 3rem; }
.bulk-plot-table col.col-area { width: 4rem; }
.bulk-plot-table col.col-garage { width: 12.5rem; }
.bulk-plot-table col.col-spaces { width: 2.5rem; }
.bulk-plot-table col.col-parking-type { width: 8rem; }
.bulk-plot-table col.col-price { width: 9.5rem; }
.bulk-plot-table col.col-address { width: 10rem; }

.bulk-plot-number { display: inline-block; padding: 0.35rem 0; font-weight: 600; }
.btn-copy-down {
    border: 1px solid var(--border);
    border-radius: 4px;
    background: var(--surface);
    color: var(--text-muted);
    font-size: 0.75rem;
    line-height: 1;
    padding: 0.1rem 0.3rem;
    cursor: pointer;
    margin-left: 0.2rem;
}
.btn-copy-down:hover { background: var(--accent-light); color: var(--text); }

/* Forms */
form.stacked-form {
    max-width: 640px;
    margin-left: auto;
    margin-right: auto;
}

form.stacked-form.wide { max-width: 1100px; }
.page-header-row.wide { max-width: 1100px; }

.field {
    margin-bottom: 1rem;
}

.field label {
    display: block;
    font-size: 0.85rem;
    font-weight: 600;
    margin-bottom: 0.3rem;
}

.field input[type=text],
.field input[type=email],
.field input[type=date],
.field input[type=number],
.field input[type=password],
.field select,
.field textarea {
    width: 100%;
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 0.95rem;
    font-family: inherit;
}

.field input[readonly] { background: #f4f6f8; color: var(--text-muted); }

.field select,
.control-row select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M5 8l5 5 5-5' stroke='%2364748b' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.65rem center;
    background-size: 0.8rem;
}

.field select { padding-right: 2.2rem; }

.field textarea { min-height: 80px; }

.field input[type=date] {
    -webkit-appearance: none;
    appearance: none;
    min-height: 0;
    line-height: 1.4;
}

.field-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
}

.field-row.cols-3 { grid-template-columns: 1fr 1fr 1fr; }

.checkbox-field { display: flex; align-items: center; gap: 0.5rem; }
.checkbox-field input { width: auto; }
.field-hint { font-size: 0.78rem; color: var(--text-muted); margin: 0.2rem 0 0; flex-basis: 100%; }

.tile-picker-list { max-width: 400px; margin-bottom: 1rem; }
.tile-picker-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    margin-bottom: 0.4rem;
    background: var(--surface);
}
.tile-picker-row .checkbox-field { gap: 0.6rem; }
.tile-picker-move { display: flex; gap: 0.3rem; }
.tile-picker-move .icon-btn { width: 1.8rem; height: 1.8rem; }
.tile-picker-move .icon-btn:disabled { opacity: 0.35; cursor: default; }

/* Buttons */
.btn {
    display: inline-block;
    padding: 0.55rem 1.1rem;
    border-radius: 6px;
    border: 1px solid var(--accent);
    background: var(--accent);
    color: var(--navy);
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
}

.btn:hover { background: var(--accent-dark); border-color: var(--accent-dark); text-decoration: none; }

.btn-secondary {
    background: var(--surface);
    color: var(--text);
    border-color: var(--border);
}

.btn-secondary:hover { background: #eef1f4; }

.btn-danger { background: var(--danger); border-color: var(--danger); color: #fff; }

.actions { display: flex; gap: 0.6rem; margin-top: 1.25rem; }

/* Badges */
.badge {
    display: inline-block;
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 600;
    background: #e2e8f0;
    color: var(--text);
}

.badge-green { background: #dcf3e6; color: #1f7a4d; }
.badge-amber { background: #fdecc8; color: #92620a; }
.badge-red { background: #fbe0de; color: var(--danger); }
.badge-blue { background: #dbe8fb; color: #1d4ed8; }

.badge-status-new { background: rgba(223, 94, 36, 0.15); color: var(--label-orange); }
.badge-status-sent { background: rgba(47, 111, 237, 0.15); color: var(--label-blue); }
.badge-status-awaiting { background: rgba(142, 117, 181, 0.15); color: var(--label-purple); }
.badge-status-delivered { background: rgba(98, 180, 44, 0.15); color: var(--label-green); }
.badge-status-default { background: #e2e8f0; color: var(--text-muted); }

.status-new { color: var(--label-orange) !important; }
.status-sent { color: var(--label-blue) !important; }
.status-awaiting { color: var(--label-purple) !important; }
.status-delivered { color: var(--label-green) !important; }
.status-default { color: var(--text-muted) !important; }

/* Land sub-stage badges: Sourcing -> Offer Made -> Legals -> Conditions -> Exchanged -> Completed */
.badge-substage-sourcing { background: #e2e8f0; color: var(--text-muted); }
.badge-substage-offer-made { background: rgba(223, 94, 36, 0.15); color: var(--label-orange); }
.badge-substage-legals { background: rgba(47, 111, 237, 0.15); color: var(--label-blue); }
.badge-substage-conditions { background: rgba(142, 117, 181, 0.15); color: var(--label-purple); }
.badge-substage-exchanged { background: rgba(167, 60, 104, 0.15); color: var(--label-pink); }
.badge-substage-completed { background: rgba(98, 180, 44, 0.15); color: var(--label-green); }

/* Same 6 sub-stages as plain right-aligned sidebar text (no pill background), matching
   how Orders' status is shown via .item-meta + a text-only colour class. */
.substage-sourcing { color: var(--text-muted) !important; }
.substage-offer-made { color: var(--label-orange) !important; }
.substage-legals { color: var(--label-blue) !important; }
.substage-conditions { color: var(--label-purple) !important; }
.substage-exchanged { color: var(--label-pink) !important; }
.substage-completed { color: var(--label-green) !important; }

/* Login */
.login-wrap {
    min-height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}

.login-card {
    width: 100%;
    max-width: 360px;
}

.login-admin-toggle { margin-top: 1rem; }
.login-admin-toggle summary {
    list-style: none;
    cursor: pointer;
    text-align: center;
    color: var(--text-muted);
    font-size: 0.85rem;
    text-decoration: underline;
}
.login-admin-toggle summary::-webkit-details-marker { display: none; }
.login-admin-toggle summary:hover { color: var(--accent-dark); }
.login-admin-toggle .stacked-form { margin-top: 1rem; }

.error-message {
    background: #fbe0de;
    color: var(--danger);
    border-radius: 6px;
    padding: 0.6rem 0.9rem;
    margin-bottom: 1rem;
    font-size: 0.9rem;
}

.notice-box {
    border-radius: 6px;
    padding: 0.8rem 1rem;
    margin-bottom: 1rem;
    max-width: 640px;
    margin-left: auto;
    margin-right: auto;
}
.notice-box p { margin: 0 0 0.75rem; font-size: 0.92rem; }
.notice-box .actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.notice-warning {
    background: var(--accent-light);
    border: 1px solid var(--accent);
    color: var(--text);
}

.empty-state {
    color: var(--text-muted);
    padding: 2rem 1rem;
    text-align: center;
}

.site-footer {
    flex: 0 0 auto;
    text-align: center;
    color: var(--text-muted);
    font-size: 0.7rem;
    line-height: 1.2;
    padding-top: 0.2rem;
    padding-left: 1rem;
    padding-right: 1rem;
    /* env(safe-area-inset-bottom) has a known WebKit bug in standalone PWA
       mode on some iOS versions where it reports a wildly inflated value —
       cap the total so a buggy reading can never balloon the footer. */
    padding-bottom: min(calc(0.2rem + env(safe-area-inset-bottom, 0px)), 1.25rem);
}

.site-footer p { margin: 0; }

/* ============================================================
   Master-detail layout (sidebar list + split detail panels)
   ============================================================ */

.screen-tabs {
    display: flex;
    gap: 0.4rem;
    margin-bottom: 1.25rem;
}

.screen-tabs a {
    padding: 0.5rem 1rem;
    border-radius: 6px;
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--text-muted);
}

.screen-tabs a:hover { background: var(--accent-light); text-decoration: none; }
.screen-tabs a.active { background: var(--navy); color: #fff; }

.screen-tabs.compact { margin: 0; gap: 0.25rem; }
.screen-tabs.compact a { padding: 0.3rem 0.65rem; font-size: 0.82rem; }

/* Small in-panel view switcher (e.g. People/Orders on Companies) — visually
   lighter than .screen-tabs so it doesn't compete with the page-level
   Companies/Contacts switcher in the sidebar header. */
.linked-panel-switcher {
    display: flex;
    gap: 0.2rem;
    padding: 0.5rem 0.75rem 0;
    background: var(--surface);
}
.linked-panel-switcher a {
    padding: 0.2rem 0.55rem;
    border-radius: 5px;
    font-weight: 600;
    font-size: 0.75rem;
    color: var(--text-muted);
    border: 1px solid var(--border);
}
.linked-panel-switcher a:hover { background: var(--accent-light); text-decoration: none; }
.linked-panel-switcher a.active { background: var(--navy); color: #fff; border-color: var(--navy); }
/* When the switcher sits inside a styled panel-header (in place of the title),
   drop its own padding/background so it lines up with the header's actions. */
.panel-header .linked-panel-switcher { padding: 0; background: transparent; }

.split-layout {
    display: flex;
    gap: 1rem;
    align-items: stretch;
    flex: 1;
    min-height: 0;
}

.split-layout.no-sidebar {
    max-width: 1100px;
    width: 100%;
    margin: 0 auto;
}

.split-sidebar {
    width: 320px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
}

.sidebar-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.375rem 0.5rem;
    background: #eef1f4;
    border-bottom: 1px solid var(--border);
    font-weight: 700;
    font-size: 0.9rem;
}

.sidebar-controls {
    padding: 0 1rem;
    border-bottom: 1px solid var(--border);
}

/* Non-accordion sidebars (no filter-slide-track) still need vertical breathing room. */
.sidebar-controls.static {
    padding: 0.9rem 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.65rem;
}

/* DOM order is fixed: filters, then the toggle bar, then search — the bar itself
   never moves. Filters live ABOVE the bar, search lives BELOW it. The container
   itself carries no vertical padding at all — instead each collapsible panel
   owns its OWN margin on the side facing away from the bar (so it collapses to
   0 together with max-height when hidden), which means whichever one is
   currently touching the bar contributes zero space, and the bar is always
   flush against the outer boundary it's nearest to: the sidebar header when at
   the top (search shown), the sort bar below when at the bottom (filters shown). */
.filter-slide-track { display: flex; flex-direction: column; }

.filter-slide-track #sort-filter-controls {
    display: flex;
    flex-direction: column;
    gap: 0.65rem;
    max-height: 0;
    overflow: hidden;
    margin-top: 0;
    margin-bottom: 0;
    transition: max-height 0.25s ease, margin-top 0.25s ease, margin-bottom 0.25s ease, overflow 0s linear 0s;
}
.filter-slide-track.filter-mode #sort-filter-controls {
    max-height: 600px;
    margin-top: 0.9rem;
    margin-bottom: 0.65rem;
    overflow: visible;
    transition: max-height 0.25s ease, margin-top 0.25s ease, margin-bottom 0.25s ease, overflow 0s linear 0.25s;
}

.filter-slide-track #search-controls {
    display: flex;
    flex-direction: column;
    gap: 0.65rem;
    max-height: 600px;
    overflow: hidden;
    margin-top: 0.65rem;
    margin-bottom: 0.9rem;
    transition: max-height 0.25s ease, margin-top 0.25s ease, margin-bottom 0.25s ease;
}
.filter-slide-track.filter-mode #search-controls {
    max-height: 0;
    margin-top: 0;
    margin-bottom: 0;
}

.filter-slide-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    margin: 0 -1rem;
    padding: 0.3rem;
    background: var(--navy);
    color: #fff;
    font-weight: 600;
    font-size: 0.82rem;
    cursor: pointer;
}
.filter-slide-toggle:hover { background: var(--navy-light); text-decoration: none; }

.sort-bar {
    display: flex;
    border-bottom: 1px solid var(--border);
    background: #f4f6f8;
}
.sort-col {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.25rem;
    padding: 0.5rem 0.3rem;
    font-size: 0.76rem;
    font-weight: 600;
    color: var(--text-muted);
}
.sort-col:hover { background: var(--accent-light); text-decoration: none; }
.sort-col.active { color: var(--navy); background: var(--accent-light); }
.sort-col .sort-arrow { font-size: 0.7rem; }

.control-row { display: flex; gap: 0.4rem; align-items: center; }
.control-row > input, .control-row > select { flex: 1; min-width: 0; }

.control-row > input[type=text],
.control-row > input[type=number],
.control-row > select {
    padding: 0.5rem 0.65rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 0.88rem;
    font-family: inherit;
}

.control-row > select { padding-right: 2.1rem; }
.control-row > .area-picker { flex: 1; min-width: 0; }

/* Per-filter clear "×" — shown only when a filter holds a non-default value,
   sits at the right of the control (clear of a select's native arrow). */
.control-row.has-filter-clear { position: relative; }
.filter-clear {
    position: absolute;
    top: 50%;
    right: 1.7rem;
    transform: translateY(-50%);
    border: none;
    background: transparent;
    color: var(--text-muted);
    font-size: 1.15rem;
    line-height: 1;
    padding: 0 0.2rem;
    cursor: pointer;
    z-index: 2;
}
.filter-clear:hover { color: var(--danger); }
.control-row.has-filter-clear > input[type=text],
.control-row.has-filter-clear > input[type=search] { padding-right: 1.9rem; }
.accounts-filter-row .control-row .filter-clear { right: 1.9rem; }

.icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border-radius: 6px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text-muted);
    font-size: 1.15rem;
    line-height: 1;
    flex-shrink: 0;
}

.icon-btn:hover { background: #eef1f4; text-decoration: none; }

.chip-row { display: flex; flex-wrap: wrap; gap: 0.4rem; }

.chip {
    display: inline-block;
    padding: 0.3rem 0.75rem;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: #f4f6f8;
    color: var(--text);
    font-size: 0.8rem;
    font-weight: 600;
}

.chip:hover { text-decoration: none; background: #e8ecf0; }
.chip.active { background: var(--accent); border-color: var(--accent); color: var(--navy); }

/* Searchable combobox — progressively enhances a <select data-combobox> */
.combobox { position: relative; }

.combobox-select-hidden { display: none; }

.combobox-input {
    width: 100%;
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 0.95rem;
    font-family: inherit;
}

.combobox-list {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 20;
    margin-top: 0.25rem;
    max-height: 220px;
    overflow-y: auto;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.08);
}

.combobox-option {
    padding: 0.5rem 0.7rem;
    font-size: 0.9rem;
    cursor: pointer;
}

.combobox-option:hover { background: var(--accent-light); }

.combobox-empty {
    padding: 0.5rem 0.7rem;
    font-size: 0.85rem;
    color: var(--text-muted);
}

/* Tickbox area picker — progressively enhances a <select multiple data-area-picker> */
.area-picker { position: relative; }

.area-picker-select-hidden { display: none; }

.area-picker-toggle {
    width: 100%;
    text-align: left;
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 0.95rem;
    font-family: inherit;
    background: var(--surface);
    cursor: pointer;
}

.area-picker-panel {
    display: none;
    position: fixed;
    z-index: 20;
    margin-top: 0.25rem;
    max-height: 180px;
    overflow-y: auto;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.08);
}

.area-picker-panel.open { display: block; }

.landstack-ref-row { display: flex; gap: 0.4rem; align-items: center; position: relative; }
.landstack-ref-row > input[type=text] { flex: 1; min-width: 0; }
.landstack-ref-row .icon-btn { flex-shrink: 0; }
.icon-btn-active { background: var(--accent-light); border-color: var(--accent); color: var(--navy); }

.landstack-link-popup {
    position: absolute;
    top: 100%;
    right: 0;
    z-index: 20;
    margin-top: 0.25rem;
    width: 280px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.08);
    padding: 0.75rem;
}
.landstack-link-popup.hidden { display: none; }
.landstack-link-popup label { display: block; font-size: 0.82rem; font-weight: 600; margin-bottom: 0.3rem; }
.landstack-link-popup input[type=url] { width: 100%; margin-bottom: 0.6rem; }
.landstack-link-popup-actions { display: flex; justify-content: flex-end; gap: 0.4rem; }

.area-picker-option {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.7rem;
    font-size: 0.9rem;
    cursor: pointer;
}

.area-picker-option:hover { background: var(--accent-light); }

.sidebar-list {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}

.sidebar-item {
    display: block;
    padding: 0.8rem 1rem;
    border-bottom: 1px solid var(--border);
    color: var(--text);
    border-left: 3px solid transparent;
    overflow: hidden;
}

.sidebar-item:last-child { border-bottom: none; }
.sidebar-item:hover { background: var(--accent-light); text-decoration: none; }

.sidebar-item.active {
    background: var(--accent-light);
    border-left-color: var(--accent);
}

.sidebar-item.priority-low { background: rgba(47, 111, 237, 0.1); }
.sidebar-item.priority-normal { background: var(--accent-light); }
.sidebar-item.priority-high { background: rgba(179, 38, 30, 0.08); }
.sidebar-item.priority-urgent { background: rgba(179, 38, 30, 0.16); font-weight: 700; }

.sidebar-item .item-title { font-weight: 700; display: block; }
.sidebar-item .item-sub { color: var(--text-muted); font-size: 0.83rem; display: block; margin-top: 0.1rem; min-height: 1.15em; }
.sidebar-item .item-meta { float: right; font-size: 0.75rem; font-weight: 600; color: var(--text-muted); margin-left: 0.5rem; }
/* Site issue rows: a right-aligned column stacking Category above the author's initials. */
.sidebar-item .item-meta-col { float: right; margin-left: 0.5rem; text-align: right; }
.sidebar-item .item-meta-col .item-meta { float: none; display: block; margin-left: 0; }
.sidebar-item .item-author-initials { display: block; font-size: 0.72rem; font-weight: 600; color: var(--text-muted); margin-top: 0.1rem; }
.sidebar-item .item-issue-ref { display: block; font-size: 0.72rem; font-weight: 600; color: var(--text-muted); margin-top: 0.1rem; }
.sidebar-item .item-areas { color: var(--text-muted); font-size: 0.75rem; font-style: italic; display: block; margin-top: 0.1rem; }

/* Mobile swipe-to-reveal: swiping a .swipe-row's .sidebar-item to the right slides it
   just far enough off the underlying .swipe-action-reveal to expose a fixed-width
   coloured action button — not the full row, so an accidental swipe is easy to undo. */
.swipe-row { position: relative; overflow: hidden; }
.swipe-row .sidebar-item { position: relative; z-index: 1; background: var(--surface); transition: transform 0.2s ease; }
/* Priority washes are semi-transparent, so they must sit on TOP of an opaque
   surface — otherwise the coloured .swipe-action-reveal behind the row bleeds
   through. Layer the wash as a background-image over an opaque background-color. */
.swipe-row .sidebar-item.priority-low { background-color: var(--surface); background-image: linear-gradient(rgba(47, 111, 237, 0.1), rgba(47, 111, 237, 0.1)); }
.swipe-row .sidebar-item.priority-normal { background-color: var(--surface); background-image: none; }
.swipe-row .sidebar-item.priority-high { background-color: var(--surface); background-image: linear-gradient(rgba(179, 38, 30, 0.08), rgba(179, 38, 30, 0.08)); }
.swipe-row .sidebar-item.priority-urgent { background-color: var(--surface); background-image: linear-gradient(rgba(179, 38, 30, 0.16), rgba(179, 38, 30, 0.16)); font-weight: 700; }
.swipe-action-reveal {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 96px;
    z-index: 0;
    margin: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}
.swipe-action-reveal.swipe-action-complete { background: var(--label-green); }
.swipe-action-reveal.swipe-action-clear { background: var(--label-blue); }
.swipe-action-btn {
    width: 100%;
    height: 100%;
    border: none;
    background: none;
    color: #fff;
    font-weight: 700;
    font-size: 0.9rem;
    text-align: center;
    cursor: pointer;
}

/* Bulk select mode: toggled on .sidebar-list, slides every row over by the same
   fixed amount to reveal a checkbox instead of the single-row swipe action. */
.select-checkbox-reveal {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 56px;
    z-index: 0;
    margin: 0;
    display: none;
    align-items: center;
    justify-content: center;
    background: #eef1f4;
    cursor: pointer;
}
.select-checkbox-reveal input[type=checkbox] { width: 20px; height: 20px; }
.sidebar-list.bulk-select-mode .select-checkbox-reveal { display: flex; }
.sidebar-list.bulk-select-mode .swipe-action-reveal { display: none; }
.sidebar-list.bulk-select-mode .swipe-row .sidebar-item { transform: translateX(56px); pointer-events: none; }

.sidebar-item-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 0.5rem; }
.sidebar-item-main { min-width: 0; }
.sidebar-item-side { flex-shrink: 0; display: flex; flex-direction: column; align-items: flex-end; gap: 0.25rem; }
.sidebar-item-side .item-price { font-size: 0.83rem; color: var(--text-muted); }

.expiry-ok { color: var(--label-green) !important; }
.expiry-soon { color: var(--label-purple) !important; }
.expiry-expired { color: var(--danger) !important; }

.split-main {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 1rem;
    min-width: 0;
    min-height: 0;
    overflow: hidden;
}

.detail-panel, .linked-panel {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;
}

/* detail-panel never shrinks below its own natural content size — flex-shrink:0.
   Without this, a large photo's intrinsic size inflates linked-panel's flex-basis
   during the flex hypothetical-sizing pass, and flex-shrink distributes the
   resulting overflow proportionally across BOTH siblings (not just the one that
   grew), squeezing detail-panel even though its own content never changed. */
.detail-panel { flex: 0 0 auto; }
.linked-panel { flex: 1 1 auto; }

/* Projects: project info is close to a full panel of fields, and the plots
   list can run long, so unlike every other module this page never shows
   both panels stacked — it always uses the mobile-style single-panel slide
   (detail <-> linked, driven by data-mobile-view + panel-nav.js), even on
   desktop. This duplicates the shape of the @media(max-width:900px) rules
   below without the width gate. */
.split-main.projects-slide-main { position: relative; overflow: hidden; gap: 0; }
.split-main.projects-slide-main .detail-panel,
.split-main.projects-slide-main .linked-panel {
    position: absolute;
    inset: 0;
    margin: 0;
    transition: transform 0.25s ease;
    touch-action: pan-y;
}
/* Default to showing detail (not just when data-mobile-view="detail" explicitly) since
   this page auto-selects the first project without necessarily setting ?id=, which
   leaves data-mobile-view="list" — a state every other module only uses to hide
   .split-main entirely, which doesn't apply here (the sidebar has its own column). */
.split-main.projects-slide-main .detail-panel { transform: translateY(0); }
.split-main.projects-slide-main .linked-panel { transform: translateY(100%); }
body[data-mobile-view="linked"] .split-main.projects-slide-main .detail-panel { transform: translateY(-100%); }
body[data-mobile-view="linked"] .split-main.projects-slide-main .linked-panel { transform: translateY(0); }
.split-main.projects-slide-main .mobile-slide-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    padding: 0.65rem;
    background: var(--navy);
    color: #fff;
    font-weight: 600;
    font-size: 0.85rem;
    flex: 0 0 auto;
    touch-action: pan-x;
}
.split-main.projects-slide-main .mobile-slide-toggle:hover { background: var(--navy-light); text-decoration: none; }
.split-main.projects-slide-main .detail-panel .panel-header,
.split-main.projects-slide-main .linked-panel .panel-header { touch-action: pan-x; }

.panel-header {
    flex: 0 0 auto;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.375rem 0.55rem;
    background: #eef1f4;
    border-bottom: 1px solid var(--border);
    font-weight: 700;
    font-size: 0.92rem;
}

.panel-body { flex: 1; padding: 1.1rem 1.25rem; overflow-y: auto; min-height: 0; }

.panel-header-actions { display: flex; gap: 0.4rem; align-items: center; flex-shrink: 0; }
.panel-header-actions form { display: contents; }
.icon-btn-complete { color: var(--label-green); border-color: var(--label-green); }
.icon-btn-clear { color: var(--label-blue); border-color: var(--label-blue); }

/* Compact header for Add Invoice screens (reduce top padding) */
.page-header-row.invoice-form-header { padding-bottom: 0.4rem; margin-bottom: 0.5rem; }
.subtitle.invoice-form-subtitle { margin-top: 0; margin-bottom: 0.6rem; }
.invoice-form-page h2 { margin: 0.75rem 0 0.5rem; }
.invoice-form-page .line-picker-toolbar { margin-bottom: 0.4rem; }
.invoice-form-picker { margin-bottom: 0.6rem; }

/* Invoice line picker + adjustments */
.line-picker-toolbar { display: flex; justify-content: flex-end; gap: 0.5rem; margin-bottom: 0.6rem; }

.invoice-line-picker input[type=number],
.invoice-line-picker input[type=text] {
    width: 100%;
    min-width: 90px;
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 0.88rem;
    font-family: inherit;
    text-align: right;
}

th.col-narrow, td.col-narrow { width: 80px; }
.invoice-line-picker .col-narrow input[type=number],
.invoice-line-picker .col-narrow input[type=text] { min-width: 55px; }
.invoice-line-picker .col-narrow { width: 90px; }

.line-total-display { font-variant-numeric: tabular-nums; padding-left: 0.6rem !important; padding-right: 0.6rem !important; }

.invoice-summary {
    max-width: 420px;
    margin: 1rem 0 0 auto;
    border-collapse: collapse;
}

.invoice-summary td {
    padding: 0.5rem 0.6rem;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}

.invoice-summary td.col-tight { text-align: right; }

.invoice-summary .summary-value {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

#row-total td { font-weight: 700; border-top: 2px solid var(--text); border-bottom: none; }

.invoice-summary input[type=number],
.invoice-summary input[type=text] {
    width: 100px;
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 0.88rem;
    font-family: inherit;
    text-align: right;
}

.vat-rate-input { width: 76px !important; display: inline-block; }
.adjustment-amount-input { width: 114px !important; }

.currency-input-wrap { position: relative; display: inline-block; }
.field .currency-input-wrap { display: block; }
.currency-input-wrap::before {
    content: "£";
    position: absolute;
    left: 0.6rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-muted);
    font-size: 0.88rem;
    pointer-events: none;
}
.currency-input-wrap input[type=number],
.currency-input-wrap input[type=text] { padding-left: 1.35rem !important; }

.adjustment-position-toggle {
    display: flex;
    gap: 0.75rem;
    font-weight: 400;
    font-size: 0.78rem;
    color: var(--text-muted);
    margin-top: 0.3rem;
}

.adjustment-position-toggle label { display: flex; align-items: center; gap: 0.3rem; }

.adjustment-fields { margin: 1.25rem 0; }
.adjustment-fields label { display: block; font-size: 0.85rem; font-weight: 600; margin-bottom: 0.3rem; }
.adjustment-fields textarea { width: 100%; min-height: 80px; padding: 0.55rem 0.7rem; border: 1px solid var(--border); border-radius: 6px; font-size: 0.95rem; font-family: inherit; }

.panel-list { flex: 1; overflow-y: auto; min-height: 0; }

/* Sales plot detail: the full field grid is hidden by default (the compact grid
   shows). Collapsing the Progression pane swaps to the full grid and lets the
   details pane grow to fill the height while progression shrinks to its header. */
.field-grid.plot-full-grid { display: none; }
.progression-toggle { text-decoration: none; }
.split-main.progression-collapsed .plot-compact-grid { display: none; }
.split-main.progression-collapsed .plot-full-grid { display: grid; }
.split-main.progression-collapsed .detail-panel { flex: 1 1 auto; }
.split-main.progression-collapsed .linked-panel { flex: 0 0 auto; }
.split-main.progression-collapsed .linked-panel .progression-add,
.split-main.progression-collapsed .linked-panel .linked-table-header,
.split-main.progression-collapsed .linked-panel .panel-list { display: none; }
.panel-list.file-panel-list { display: flex; flex-direction: column; overflow-y: hidden; }

.field-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
}

.field-grid.span-full { grid-template-columns: 1fr; }

.field-grid.cols-12 { grid-template-columns: repeat(12, 1fr); }

.field-grid .span-1 { grid-column: span 1; }
.field-grid .span-2 { grid-column: span 2; }
.field-grid .span-3 { grid-column: span 3; }
.field-grid .span-4 { grid-column: span 4; }
.field-grid .span-6 { grid-column: span 6; }
.field-grid .span-8 { grid-column: span 8; }
.field-grid .span-12 { grid-column: span 12; }

.order-progress { margin-top: 1.25rem; }
.order-progress-label {
    display: flex;
    justify-content: space-between;
    font-size: 0.85rem;
    color: var(--text-muted);
    margin-bottom: 0.35rem;
}
.order-progress-bar {
    height: 8px;
    background: #e5e8eb;
    border-radius: 4px;
    overflow: hidden;
}
.order-progress-fill { height: 100%; background: var(--accent); border-radius: 4px; }

.field-view {
    display: flex;
    flex-direction: column;
}

.field-view label {
    display: block;
    font-size: 0.75rem;
    line-height: 1.4;
    color: var(--text-muted);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    margin-bottom: 0.25rem;
}

.field-view .value {
    background: #f4f6f8;
    border-radius: 6px;
    padding: 0.5rem 0.7rem;
    min-height: 1.3rem;
    font-size: 0.92rem;
}

.field-view.field-long .value { min-height: 4.5rem; }

.linked-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.75rem 1.1rem;
    border-bottom: 1px solid var(--border);
    color: var(--text);
}

.linked-item:last-child { border-bottom: none; }
.linked-item:hover { background: var(--accent-light); text-decoration: none; }
.linked-item .item-title { font-weight: 700; }
.linked-item .item-sub { color: var(--text-muted); font-size: 0.83rem; }
.linked-item .item-meta { font-size: 0.8rem; color: var(--text-muted); }

.sidebar-item .item-ref { font-size: 0.78rem; color: var(--text-muted); display: block; }

/* Multi-column linked list (e.g. Appointments within a project), with a
   non-scrolling header row and totals footer either side of the scrollable body */
.linked-table-header, .linked-table-row, .linked-table-footer {
    display: grid;
    grid-template-columns: 1.4fr 1fr 100px 100px;
    gap: 0.75rem;
    align-items: center;
}

.linked-table-header {
    flex: 0 0 auto;
    padding: 0.5rem 1.1rem;
    background: #f4f6f8;
    border-bottom: 1px solid var(--border);
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--text-muted);
}

.linked-table-row {
    padding: 0.75rem 1.1rem;
    border-bottom: 1px solid var(--border);
    color: var(--text);
}

.linked-table-row:last-child { border-bottom: none; }
.linked-table-row:hover { background: var(--accent-light); text-decoration: none; }

.linked-table-footer {
    flex: 0 0 auto;
    padding: 0.65rem 1.1rem;
    border-top: 1px solid var(--border);
    background: #f4f6f8;
    font-weight: 700;
}

.linked-table-header .col-num, .linked-table-row .col-num, .linked-table-footer .col-num { text-align: right; }

.linked-table-row .item-title { font-weight: 700; display: block; }
.linked-table-row .item-sub { color: var(--text-muted); font-size: 0.83rem; display: block; margin-top: 0.1rem; }

@media (max-width: 640px) {
    .linked-table-header, .linked-table-row, .linked-table-footer {
        grid-template-columns: 1fr 90px;
    }
}

.linked-table-header.appt-lines, .linked-table-row.appt-lines, .linked-table-footer.appt-lines {
    grid-template-columns: 1fr 120px 120px 120px;
}

@media (max-width: 640px) {
    .linked-table-header.appt-lines, .linked-table-row.appt-lines, .linked-table-footer.appt-lines {
        grid-template-columns: 1fr 100px;
    }
}

.linked-table-header.order-lines, .linked-table-row.order-lines, .linked-table-footer.order-lines {
    grid-template-columns: 55px 1.4fr 80px 65px 65px 90px;
}

@media (max-width: 640px) {
    .linked-table-header.order-lines, .linked-table-row.order-lines, .linked-table-footer.order-lines {
        grid-template-columns: 1fr 90px;
    }
}

.linked-table-header.accounts-rows, .linked-table-row.accounts-rows, .linked-table-footer.accounts-rows {
    grid-template-columns: 1.5fr 1fr 1.1fr 100px 100px 100px;
}

.linked-table-header.accounts-invoice-rows, .linked-table-row.accounts-invoice-rows, .linked-table-footer.accounts-invoice-rows {
    grid-template-columns: 1.5fr 1fr 1.1fr 100px 100px 100px 36px;
}

.linked-table-row.accounts-invoice-rows .icon-btn {
    width: 1.4rem;
    height: 1.4rem;
    font-size: 0.75rem;
}

@media (max-width: 640px) {
    .linked-table-header.accounts-rows { display: none; }
    .linked-table-row.accounts-rows, .linked-table-footer.accounts-rows {
        grid-template-columns: 1fr;
        gap: 0.2rem;
    }
    .linked-table-row.accounts-rows .col-num, .linked-table-footer.accounts-rows .col-num { text-align: left; }
    .linked-table-row.accounts-rows .col-num[data-label]::before,
    .linked-table-footer.accounts-rows .col-num[data-label]::before {
        content: attr(data-label) ": ";
        font-weight: 600;
        color: var(--text-muted);
    }
}

.linked-table-header.plots-summary, .linked-table-row.plots-summary {
    grid-template-columns: 1fr 1fr;
}

/* Progression / updates pane: a simple append-only Author / Date+time / Comment log,
   used in place of a linked-table of child records (Land projects, Sales plots,
   Customer Care issues each get one) — reuses the linked-table-row grid machinery
   with its own column layout via the .progression variant. */
.progression-add {
    flex: 0 0 auto;
    display: flex;
    gap: 0.6rem;
    align-items: flex-start;
    padding: 0.75rem 1.1rem;
    border-bottom: 1px solid var(--border);
    background: #f4f6f8;
}

.progression-add textarea {
    flex: 1;
    min-height: 2.4rem;
    padding: 0.5rem 0.65rem;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 0.88rem;
    font-family: inherit;
    resize: vertical;
}

.linked-table-header.progression, .linked-table-row.progression, .linked-table-footer.progression {
    grid-template-columns: 130px 140px 1fr;
    align-items: start;
}

.linked-table-row.progression { cursor: default; }
.linked-table-row.progression:hover { background: none; }
.linked-table-row.progression .progression-comment { white-space: pre-line; }

@media (max-width: 640px) {
    .linked-table-header.progression { display: none; }
    .linked-table-row.progression {
        grid-template-columns: 1fr;
        gap: 0.2rem;
    }
    .linked-table-row.progression .progression-meta { color: var(--text-muted); font-size: 0.78rem; }
}

/* Top-of-page Save/Cancel bar, next to the H1, instead of scrolling to the bottom */
.page-header-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    margin-bottom: 1.25rem;
    position: sticky;
    top: -1.5rem;
    margin-top: -1.5rem;
    margin-left: auto;
    margin-right: auto;
    padding: 1.5rem 0 1rem;
    background: var(--bg);
    z-index: 5;
    max-width: 640px;
}

/* Single-column (no-sidebar) pages: the header spans the full panel width so its
   action buttons right-justify to the panel edge rather than the 640px form width. */
.split-layout.no-sidebar .page-header-row { max-width: none; width: 100%; }

/* Accounts & Admin: the header spans the full width of the stacked panels below
   it (both "columns"), so the title sits left and the action buttons right. */
.accounts-desktop-only .page-header-row,
.admin-desktop-only .page-header-row { max-width: none; width: 100%; }

.page-header-row h1 { min-width: 0; }

.page-header-row .actions .btn .btn-text { display: inline; }
.page-header-row .actions .btn .btn-icon { display: none; }

@media (max-width: 640px) {
    .page-header-row .actions .btn {
        padding: 0.55rem 0.7rem;
    }
    .page-header-row .actions .btn .btn-text { display: none; }
    .page-header-row .actions .btn .btn-icon { display: inline; }
}

.page-header-row h1 { margin: 0; }
.page-header-row .actions { margin-top: 0; flex-shrink: 0; }

/* Mobile single-pane navigation (list -> detail -> linked), JS-driven via
   data-mobile-view on <body>. Hidden entirely above the breakpoint. */
.mobile-slide-toggle { display: none; touch-action: pan-x; }

@media (max-width: 900px) {
    .page.wide { padding: 0; }

    .split-layout {
        flex-direction: column;
        align-items: stretch;
        flex: 1;
        min-height: 0;
        height: 100%;
    }

    .split-sidebar {
        width: 100%;
        height: 100%;
        border-radius: 0;
        border-width: 0;
    }

    .split-main {
        width: 100%;
        height: 100%;
        position: relative;
        overflow: hidden;
        gap: 0;
    }

    .split-main .detail-panel, .split-main .linked-panel {
        position: absolute;
        inset: 0;
        margin: 0;
        border-radius: 0;
        border-width: 0;
        transition: transform 0.25s ease;
        touch-action: pan-y;
    }

    /* default state (e.g. JS not run yet): show list only */
    body:not([data-mobile-view="detail"]):not([data-mobile-view="linked"]) .split-main {
        display: none;
    }

    /* .split-layout.no-sidebar pages (e.g. plot_detail.php) have no sidebar and never set
       data-mobile-view, so the rule above would hide their only content forever — restore it.
       (Needs "body" in the selector to out-specificity the rule above, which also starts with body.) */
    body .split-layout.no-sidebar .split-main {
        display: block;
    }

    /* .page-header-row's sticky trick relies on being a direct child of .page
       (whose own padding cancels its negative margin). Nested inside .split-main
       here, its sticky-positioning ancestor becomes .split-main instead — which has
       no padding and overflow:hidden on mobile — pulling the header up over the
       panel's own top content. Drop the sticky behavior in this nested context. */
    .split-layout.no-sidebar .split-main > .page-header-row {
        position: static;
        margin-top: 0;
        padding-top: 0;
    }

    /* .split-layout.no-sidebar has no list pane to slide from/to, so the generic
       slide-panel absolute-positioning above doesn't apply here — it was covering
       the (sibling, normal-flow) .page-header-row above with an opaque panel.
       Restore normal flow so the header stays visible. */
    .split-layout.no-sidebar .split-main .detail-panel,
    .split-layout.no-sidebar .split-main .linked-panel {
        position: static;
    }

    body[data-mobile-view="detail"] .split-sidebar,
    body[data-mobile-view="linked"] .split-sidebar {
        display: none;
    }

    body[data-mobile-view="detail"] .split-main .detail-panel { transform: translateY(0); }
    body[data-mobile-view="detail"] .split-main .linked-panel { transform: translateY(100%); }
    body[data-mobile-view="linked"] .split-main .detail-panel { transform: translateY(-100%); }
    body[data-mobile-view="linked"] .split-main .linked-panel { transform: translateY(0); }

    body[data-mobile-view="detail"] .subheader-mobile-back,
    body[data-mobile-view="linked"] .subheader-mobile-back {
        display: inline-flex;
    }

    .mobile-slide-toggle {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 0.4rem;
        padding: 0.65rem;
        background: var(--navy);
        color: #fff;
        font-weight: 600;
        font-size: 0.85rem;
        flex: 0 0 auto;
        touch-action: pan-x;
    }

    .mobile-slide-toggle:hover { background: var(--navy-light); text-decoration: none; }

    .split-main .detail-panel .panel-header, .split-main .linked-panel .panel-header { touch-action: pan-x; }

    .field-grid { grid-template-columns: repeat(2, 1fr); }

    .field-grid.cols-12 { grid-template-columns: 1fr; }
    .field-grid.cols-12 .span-2,
    .field-grid.cols-12 .span-3,
    .field-grid.cols-12 .span-4,
    .field-grid.cols-12 .span-6,
    .field-grid.cols-12 .span-8,
    .field-grid.cols-12 .span-12 { grid-column: span 1; }
}

@media (max-width: 560px) {
    .topbar .brand { display: none; }
    .topbar-title { margin-left: 0; padding-left: 0; border-left: 0; font-size: 0.95rem; }
    .topnav { gap: 0.75rem; }
    .topnav .user-name { display: none; }
    .field-grid { grid-template-columns: 1fr; }
}

/* Shared modal overlay (image lightbox, change-log popup) */
.modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.85);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    padding: 1rem;
}

.modal-overlay.hidden { display: none; }

.modal-overlay .modal-close {
    position: fixed;
    top: 1rem;
    right: 1.25rem;
    background: none;
    border: none;
    color: #fff;
    font-size: 2rem;
    line-height: 1;
    cursor: pointer;
    z-index: 1001;
}

.modal-overlay .lightbox-img { max-width: 92vw; max-height: 92vh; border-radius: 6px; }

.modal-overlay .modal-panel {
    background: var(--surface);
    border-radius: var(--radius);
    padding: 1.5rem;
    max-width: 640px;
    width: 100%;
    max-height: 80vh;
    overflow-y: auto;
}

.modal-overlay .modal-panel.wide {
    max-width: 900px;
    width: 95vw;
    max-height: 88vh;
    display: flex;
    flex-direction: column;
}
.modal-overlay .modal-panel.wide .modal-picker-controls { flex: 0 0 auto; }
.modal-overlay .modal-panel.wide .modal-picker-list {
    flex: 1;
    overflow-y: auto;
    min-height: 0;
    border: 1px solid var(--border);
    border-radius: 6px;
    margin-top: 0.75rem;
}
.modal-overlay .modal-panel.wide .modal-picker-list .sidebar-item { cursor: pointer; }
.modal-overlay .modal-panel.wide .modal-picker-actions { flex: 0 0 auto; margin-top: 1rem; text-align: right; }

/* Site issue photo gallery: top half of the panel, natural per-image width, horizontal scroll.
   Document list (.document-list) takes the bottom half, scrolling independently. The gallery's
   height is proportional (flex:1 1 50%) so it fills the available panel space at its full
   original (Phase 5) size — no max-height cap here. The panel-hiding bug this cap was guarding
   against turned out to be caused entirely by the file-picker staging context below (a non-flex
   ancestor where height:100% couldn't resolve), which now has its own fixed height, so this
   gallery's percentage-based sizing is safe uncapped. */
.file-gallery {
    display: flex;
    gap: 0.6rem;
    flex: 1 1 50%;
    min-height: 0;
    height: auto;
    overflow-x: auto;
    overflow-y: hidden;
    padding: 0.75rem;
    touch-action: pan-x;
}

.document-list { flex: 1 1 50%; min-height: 0; overflow-y: auto; }
.document-list .empty-state { text-align: left; padding: 0.75rem; }

.file-gallery-item { position: relative; flex: 0 0 auto; height: 100%; }

.file-gallery-item img {
    height: 100%;
    width: auto;
    border-radius: 6px;
    cursor: pointer;
    display: block;
}

/* Delete/remove control overlay: the real gallery wraps it in a <form> (page POST), the
   file-picker's staging thumbnails use a plain <button> (client-only, no submit) — both need
   to sit absolutely on the item's top-right corner. */
.file-gallery-item form,
.file-gallery-item > button.icon-btn {
    position: absolute;
    top: 2px;
    right: 2px;
    margin: 0;
}

.file-gallery-item .icon-btn {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: none;
    background: rgba(0, 0, 0, 0.6);
    color: #fff;
    font-size: 0.7rem;
    line-height: 22px;
    padding: 0;
}

/* Multi-file picker: staged thumbnails before upload (reuses .file-gallery/.file-gallery-item,
   but smaller — this is a compact "small thumbnails" strip, not the detail-panel gallery). */
.file-picker-staging { height: 90px; flex: 0 0 auto; border: 1px dashed var(--border); border-radius: 6px; margin-top: 0.5rem; touch-action: pan-x; }
.file-picker-staging .file-gallery-item { height: 100%; }
.file-picker-doc-icon {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.3rem;
    width: 90px;
    height: 100%;
    padding: 0.5rem;
    background: #f4f6f8;
    border-radius: 6px;
    font-size: 0.7rem;
    color: var(--text-muted);
    text-align: center;
    word-break: break-word;
}
.file-picker-doc-icon span { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

/* Site issue status colouring on the sidebar item title */
.item-title.status-completed { color: var(--label-green); }
.item-title.status-cleared { color: var(--text-muted); font-style: italic; }

/* ============================================================
   Accounts (top/bottom panel, no sidebar — deliberately different
   from the rest of the app; hidden entirely on mobile, see below)
   ============================================================ */

/* Mirrors .split-main's role: a height-constrained flex column directly inside
   .page.wide, so the bottom panel can flex to fill remaining space and scroll
   internally instead of pushing the page taller than the viewport. */
.accounts-desktop-only {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
    min-height: 0;
    overflow: hidden;
}

/* .page-header-row already carries its own margin-bottom; without this override
   it stacks with the flex gap above and doubles the space before .detail-panel. */
.accounts-desktop-only > .page-header-row { margin-bottom: 0; }

.btn-disabled { opacity: 0.5; cursor: default; pointer-events: none; }

.accounts-desktop-only .panel-body { padding-top: 0.85rem; }

.acct-sort { cursor: pointer; user-select: none; white-space: nowrap; }
.acct-sort .sort-arrow { font-size: 0.7rem; color: var(--text-muted); }
.acct-sort:hover { color: var(--navy); }

.accounts-filter-row {
    display: flex;
    gap: 0.6rem;
    flex-wrap: wrap;
    align-items: center;
    margin-bottom: 1rem;
}
.accounts-filter-row .control-row { width: 240px; flex: 0 0 240px; }
.accounts-filter-row .accounts-search { width: 260px; flex: 0 0 260px; margin-left: auto; }

.accounts-kpi-row {
    display: flex;
    gap: 1rem;
    flex-wrap: wrap;
}

.accounts-kpi-tile {
    flex: 1 1 200px;
    background: #f4f6f8;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 1rem 1.25rem;
}

.accounts-kpi-value { font-size: 1.9rem; font-weight: 700; color: var(--navy); }
.accounts-kpi-label { color: var(--text-muted); font-size: 0.88rem; margin-top: 0.2rem; }

.accounts-mobile-notice { display: none; }

@media (max-width: 900px) {
    .accounts-desktop-only { display: none; }
    .accounts-mobile-notice {
        display: block;
        padding: 3rem 1.5rem;
        text-align: center;
        color: var(--text-muted);
        font-size: 1rem;
    }
    a.tile[href*="modules/accounts/"] { display: none; }
}

/* Sales "add site" intake screens (add_project.php, plot_bulk_form.php) — same
   CSS-only desktop-gate pattern as Accounts, these two screens don't scale to mobile. */
.sales-intake-mobile-notice { display: none; }

@media (max-width: 900px) {
    .sales-intake-desktop-only { display: none; }
    .sales-intake-mobile-notice {
        display: block;
        padding: 3rem 1.5rem;
        text-align: center;
        color: var(--text-muted);
        font-size: 1rem;
    }
    .sales-add-site-btn { display: none; }
}

/* Admin: top/bottom stacked layout (user list over access-control panel), same
   CSS-only desktop-gate pattern as Accounts — a multi-column permission grid
   isn't usable on a phone. */
.stacked-layout { flex: 1; display: flex; flex-direction: column; gap: 0.85rem; min-height: 0; overflow: hidden; }
.stacked-layout > .page-header-row { margin-bottom: 0; }

.admin-user-list-pane {
    flex: 0 0 260px;
    max-width: 1100px;
    width: 100%;
    margin: 0 auto;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
.admin-user-list-pane .sidebar-list { flex: 1; overflow-y: auto; }

.stacked-layout > .detail-panel { flex: 1 1 auto; max-width: 1100px; width: 100%; margin: 0 auto; min-height: 0; overflow: hidden; }

/* Admin edit form wraps the details (top) + access-control (bottom) panels, so it
   must itself be the flex column that split-main would otherwise provide. */
/* Height-constrained flex column (mirrors .accounts-desktop-only) so the split
   layout fills the viewport and each pane scrolls internally, instead of the
   sidebar/panels growing with content and spilling past the bottom of the screen. */
.admin-desktop-only {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
    min-height: 0;
    overflow: hidden;
}

/* Keep every pane header the same height, whether it carries a button (sidebar
   "Users +", detail "name / Save") or is text-only ("Access control"). */
.admin-desktop-only .sidebar-header,
.admin-desktop-only .panel-header { min-height: 2.75rem; }

/* Admin is desktop-only, so its action buttons always show their text label and
   never the icon-only form — matching how buttons look on every other page at
   desktop width (the tick/cross icons are the mobile-collapsed appearance). */
.admin-desktop-only .btn .btn-text { display: inline; }
.admin-desktop-only .btn .btn-icon { display: none; }

.admin-edit-form { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 1rem; }
/* Access control reuses the shared linked-table look (like the Orders and
   Design/Construction appointment line panes): a proper table-header row under
   the panel header, then scrolling data rows — no extra in-body header line. */
.linked-table-header.admin-access,
.linked-table-row.admin-access {
    grid-template-columns: 1fr 70px 70px;
}
.linked-table-header.admin-access span:nth-child(2),
.linked-table-header.admin-access span:nth-child(3) { text-align: center; }
.admin-access-label { font-size: 0.92rem; }
.admin-access-cell { display: flex; justify-content: center; cursor: pointer; margin: 0; }
.admin-access-cell input { width: 1.05rem; height: 1.05rem; cursor: pointer; }

.admin-mobile-notice { display: none; }

@media (max-width: 900px) {
    .admin-desktop-only { display: none; }
    .admin-mobile-notice {
        display: block;
        padding: 3rem 1.5rem;
        text-align: center;
        color: var(--text-muted);
        font-size: 1rem;
    }
    a.tile[href*="modules/admin/"] { display: none; }
}
