/* ==========================================================================
   Nyumba PMS — Interactive components
   Overlays, feedback, navigation-in-page, and the stack plan.
   ========================================================================== */

/* ==========================================================================
   Overlay base — shared by modal, drawer and palette
   ========================================================================== */

.overlay {
  position: fixed; inset: 0; background: var(--overlay);
  backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
  opacity: 0; pointer-events: none;
  transition: opacity var(--duration) var(--ease);
}
.overlay[data-open] { opacity: 1; pointer-events: auto; }

/* --- Modal -------------------------------------------------------------- */
.modal-host { position: fixed; inset: 0; z-index: var(--z-modal); display: grid; place-items: center; padding: var(--space-4); pointer-events: none; }
/* Every modal occupies the SAME grid cell, so a host holding several stacks
   them rather than laying them out as rows. Without this, a page with four
   modals makes the grid four rows tall and the open one is pushed out of the
   viewport — its buttons become unclickable even though it looks fine. */
.modal {
  grid-area: 1 / 1; place-self: center;
  position: relative; width: 100%; max-width: 520px; max-height: calc(100vh - var(--space-8));
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  opacity: 0; transform: translateY(10px) scale(.985); pointer-events: none;
  transition: opacity var(--duration) var(--ease), transform var(--duration) var(--ease-spring);
}
.modal[data-open] { opacity: 1; transform: none; pointer-events: auto; }
.modal[aria-hidden="true"] { visibility: hidden; }
.modal[data-open] { visibility: visible; }
.modal--wide { max-width: 780px; }
.modal-head {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-5) var(--space-5) var(--space-4); flex: none;
}
.modal-title { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 620; letter-spacing: -.018em; }
.modal-sub { font-size: var(--text-sm); color: var(--ink-3); margin-top: var(--space-1); }
.modal-body { padding: 0 var(--space-5) var(--space-5); overflow-y: auto; flex: 1; }
.modal-foot {
  display: flex; align-items: center; gap: var(--space-2); justify-content: flex-end;
  padding: var(--space-4) var(--space-5); flex: none;
  border-top: 1px solid var(--line); background: var(--surface-2);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}

/* A destructive modal is marked by a red rule at the top, not a red panel. */
.modal--danger { border-top: 3px solid var(--neg); }

/* --- Drawer — for record detail without losing the list ---------------- */
.drawer-host { position: fixed; inset: 0; z-index: var(--z-drawer); pointer-events: none; }
.drawer {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: min(92vw, 460px); display: flex; flex-direction: column;
  background: var(--surface); border-left: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
  transform: translateX(100%); pointer-events: none;
  transition: transform var(--duration-slow) var(--ease);
}
.drawer[data-open] { transform: none; pointer-events: auto; }
.drawer--wide { width: min(96vw, 720px); }
.drawer-head {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-5); flex: none; border-bottom: 1px solid var(--line);
}
.drawer-body { flex: 1; overflow-y: auto; padding: var(--space-5); }
.drawer-foot { flex: none; padding: var(--space-4) var(--space-5); border-top: 1px solid var(--line); background: var(--surface-2); display: flex; gap: var(--space-2); }

@media (max-width: 640px) {
  /* On a phone a side drawer is a sheet from the bottom. */
  .drawer {
    top: auto; left: 0; width: 100%; max-height: 90vh;
    border-left: 0; border-top: 1px solid var(--line);
    border-radius: var(--radius-xl) var(--radius-xl) 0 0;
    transform: translateY(100%);
  }
  .drawer::before {
    content: ''; position: absolute; top: 8px; left: 50%; transform: translateX(-50%);
    width: 36px; height: 4px; border-radius: 99px; background: var(--line-2);
  }
  .drawer-head { padding-top: var(--space-6); }
}

/* ==========================================================================
   Toasts — confirmation of what just happened, bottom-right, self-dismissing
   ========================================================================== */

.toast-host {
  position: fixed; bottom: var(--space-5); right: var(--space-5); z-index: var(--z-toast);
  display: flex; flex-direction: column-reverse; gap: var(--space-2);
  pointer-events: none; max-width: min(92vw, 380px);
}
.toast {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface); border: 1px solid var(--line);
  border-left: 3px solid var(--neutral);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
  pointer-events: auto; animation: toast-in var(--duration-slow) var(--ease-spring) both;
}
.toast[data-leaving] { animation: toast-out var(--duration) var(--ease) both; }
@keyframes toast-in  { from { opacity: 0; transform: translateX(16px) scale(.97); } to { opacity: 1; transform: none; } }
@keyframes toast-out { to { opacity: 0; transform: translateX(16px) scale(.97); } }

.toast--success { border-left-color: var(--pos); }
.toast--error   { border-left-color: var(--neg); }
.toast--warning { border-left-color: var(--warn); }
.toast--info    { border-left-color: var(--info); }
.toast-icon { width: 17px; height: 17px; flex: none; margin-top: 1px; }
.toast--success .toast-icon { color: var(--pos); }
.toast--error   .toast-icon { color: var(--neg); }
.toast--warning .toast-icon { color: var(--warn); }
.toast--info    .toast-icon { color: var(--info); }
.toast-body { flex: 1; font-size: var(--text-sm); line-height: var(--leading-snug); }
.toast-close { flex: none; width: 20px; height: 20px; display: grid; place-items: center; border: 0; background: none; color: var(--ink-4); cursor: pointer; border-radius: var(--radius-xs); }
.toast-close:hover { color: var(--ink); background: var(--surface-2); }
.toast-close svg { width: 13px; height: 13px; }

@media (max-width: 640px) {
  .toast-host { bottom: var(--space-3); right: var(--space-3); left: var(--space-3); max-width: none; }
}

/* Inline alert — persistent, for context that must stay on the page. */
.alert {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-3) var(--space-4); border-radius: var(--radius);
  border: 1px solid var(--line); background: var(--surface-2);
  font-size: var(--text-sm); line-height: var(--leading-snug);
}
.alert svg { width: 17px; height: 17px; flex: none; margin-top: 1px; }
.alert--success { background: var(--pos-soft);  border-color: color-mix(in srgb, var(--pos) 28%, transparent);  color: var(--pos-ink); }
.alert--error   { background: var(--neg-soft);  border-color: color-mix(in srgb, var(--neg) 28%, transparent);  color: var(--neg-ink); }
.alert--warning { background: var(--warn-soft); border-color: color-mix(in srgb, var(--warn) 28%, transparent); color: var(--warn-ink); }
.alert--info    { background: var(--info-soft); border-color: color-mix(in srgb, var(--info) 28%, transparent); color: var(--info-ink); }
.alert-title { font-weight: 650; }

/* ==========================================================================
   Command palette — one keystroke to anywhere. ⌘K / Ctrl-K
   ========================================================================== */

.palette-host { position: fixed; inset: 0; z-index: var(--z-palette); display: flex; justify-content: center; padding: 10vh var(--space-4) var(--space-4); pointer-events: none; }
.palette {
  width: 100%; max-width: 580px; max-height: 60vh;
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line-2);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); overflow: hidden;
  opacity: 0; transform: translateY(-8px) scale(.99); pointer-events: none;
  transition: opacity var(--duration) var(--ease), transform var(--duration) var(--ease-spring);
}
.palette[data-open] { opacity: 1; transform: none; pointer-events: auto; }
.palette-search { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-4); border-bottom: 1px solid var(--line); flex: none; }
.palette-search svg { width: 18px; height: 18px; color: var(--ink-4); flex: none; }
.palette-search input { flex: 1; border: 0; background: none; font-size: var(--text-md); outline: none; }
.palette-search input::placeholder { color: var(--ink-4); }
.palette-results { overflow-y: auto; padding: var(--space-2); flex: 1; }
.palette-group-label {
  font-family: var(--font-mono); font-size: var(--text-2xs); font-weight: 600;
  letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--ink-4);
  padding: var(--space-3) var(--space-3) var(--space-2);
}
.palette-item {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm);
  cursor: pointer; font-size: var(--text-base);
}
.palette-item[data-active] { background: var(--brand-soft); }
[data-mode='dark'] .palette-item[data-active] { background: var(--surface-3); }
.palette-item svg { width: 16px; height: 16px; color: var(--ink-3); flex: none; }
.palette-item-main { flex: 1; min-width: 0; }
.palette-item-title { font-weight: 550; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.palette-item-sub { font-size: var(--text-xs); color: var(--ink-3); }
.palette-foot {
  flex: none; display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-2) var(--space-4); border-top: 1px solid var(--line);
  background: var(--surface-2); font-size: var(--text-2xs); color: var(--ink-3);
}
.palette-foot span { display: flex; align-items: center; gap: 4px; }
.palette-empty { padding: var(--space-8) var(--space-4); text-align: center; color: var(--ink-3); font-size: var(--text-sm); }

/* ==========================================================================
   Menus, tabs, tooltips
   ========================================================================== */

.menu-wrap { position: relative; display: inline-block; }
.menu {
  position: absolute; top: calc(100% + 4px); right: 0; min-width: 190px; z-index: var(--z-sticky);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow-lg); padding: var(--space-1);
  opacity: 0; transform: translateY(-4px) scale(.98); pointer-events: none;
  transform-origin: top right;
  transition: opacity var(--duration-fast) var(--ease), transform var(--duration-fast) var(--ease-spring);
}
.menu[data-open] { opacity: 1; transform: none; pointer-events: auto; }
.menu--left { right: auto; left: 0; transform-origin: top left; }
.menu-item {
  display: flex; align-items: center; gap: var(--space-3); width: 100%;
  padding: var(--space-2) var(--space-3); border: 0; background: none;
  border-radius: var(--radius-xs); font-size: var(--text-sm); text-align: left;
  color: var(--ink-2); cursor: pointer;
}
.menu-item:hover { background: var(--surface-2); color: var(--ink); }
.menu-item svg { width: 15px; height: 15px; flex: none; opacity: .75; }
.menu-item--danger { color: var(--neg); }
.menu-item--danger:hover { background: var(--neg-soft); }
.menu-sep { height: 1px; background: var(--line); margin: var(--space-1) 0; }
.menu-label { padding: var(--space-2) var(--space-3) var(--space-1); font-size: var(--text-2xs); font-weight: 650; color: var(--ink-4); text-transform: uppercase; letter-spacing: var(--tracking-wide); }

.tabs { display: flex; gap: var(--space-1); border-bottom: 1px solid var(--line); overflow-x: auto; }
.tab {
  padding: var(--space-3) var(--space-4); border: 0; background: none;
  font-size: var(--text-base); font-weight: 550; color: var(--ink-3);
  cursor: pointer; white-space: nowrap; position: relative;
  transition: color var(--duration-fast) var(--ease);
}
.tab:hover { color: var(--ink); }
.tab[aria-selected='true'] { color: var(--ink); font-weight: 650; }
.tab[aria-selected='true']::after {
  content: ''; position: absolute; left: var(--space-3); right: var(--space-3); bottom: -1px;
  height: 2px; background: var(--accent); border-radius: 2px 2px 0 0;
}
.tab-count { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--ink-4); margin-left: 4px; }
/* .tab-panel[hidden] is covered by the global [hidden] rule in app.css. */

/* Tooltip — attribute-driven so any element can carry one. */
[data-tip] { position: relative; }
[data-tip]::after {
  content: attr(data-tip); position: absolute; z-index: var(--z-toast);
  bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%) translateY(3px);
  padding: 5px 9px; border-radius: var(--radius-xs);
  background: var(--ink); color: var(--paper);
  font-size: var(--text-2xs); font-weight: 500; line-height: 1.35;
  white-space: nowrap; opacity: 0; pointer-events: none;
  transition: opacity var(--duration-fast) var(--ease), transform var(--duration-fast) var(--ease);
}
[data-tip]:hover::after, [data-tip]:focus-visible::after { opacity: 1; transform: translateX(-50%); }
[data-tip-side='right']::after { bottom: auto; top: 50%; left: calc(100% + 6px); transform: translateY(-50%) translateX(-3px); }
[data-tip-side='right']:hover::after { transform: translateY(-50%); }

/* ==========================================================================
   THE STACK PLAN
   --------------------------------------------------------------------------
   The signature element. A building drawn the way property managers actually
   think about one: floors stacked bottom to top, each unit a tile coloured by
   live status. The health of a whole block reads in one glance — which no
   list of rows can do.

   Colour carries meaning, but never alone: each tile also shows its number and
   a status glyph, and the legend names every state.
   ========================================================================== */

.stackplan { display: flex; flex-direction: column-reverse; gap: 3px; }

.stackplan-floor { display: flex; align-items: stretch; gap: 3px; }
.stackplan-floor-label {
  flex: none; width: 44px; display: flex; align-items: center; justify-content: flex-end;
  padding-right: var(--space-3);
  font-family: var(--font-mono); font-size: var(--text-2xs); font-weight: 600;
  color: var(--ink-4); letter-spacing: .04em;
}
.stackplan-units { flex: 1; display: flex; gap: 3px; flex-wrap: wrap; align-content: stretch; }

.stackplan-unit {
  /* Capped so a four-unit floor reads as four units rather than four banners.
     Wide tiles lose the sense of a building, which is the whole point. */
  position: relative; flex: 1 1 68px; min-width: 62px; max-width: 132px; min-height: 54px;
  display: flex; flex-direction: column; justify-content: space-between;
  padding: 6px 7px; border-radius: var(--radius-xs);
  border: 1px solid transparent; cursor: pointer; text-align: left;
  transition: transform var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}
.stackplan-unit:hover { transform: translateY(-2px); box-shadow: var(--shadow); z-index: 2; }
.stackplan-unit:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; z-index: 2; }

.stackplan-unit-number {
  font-family: var(--font-mono); font-size: var(--text-2xs); font-weight: 600;
  letter-spacing: -.01em; line-height: 1;
}
.stackplan-unit-meta { font-size: 9.5px; line-height: 1.25; font-variant-numeric: tabular-nums; }
.stackplan-unit-glyph { position: absolute; top: 5px; right: 5px; width: 11px; height: 11px; opacity: .55; }

/* States. Occupied-and-current is the quiet baseline; problems are the ones
   that carry colour, so a healthy building looks calm. */
.stackplan-unit[data-state='occupied'] { background: var(--brand-soft); color: var(--brand); border-color: color-mix(in srgb, var(--brand) 20%, transparent); }
[data-mode='dark'] .stackplan-unit[data-state='occupied'] { color: var(--ink); }

.stackplan-unit[data-state='vacant'] {
  background: repeating-linear-gradient(-45deg, var(--surface-2), var(--surface-2) 5px, var(--surface-3) 5px, var(--surface-3) 10px);
  color: var(--ink-3); border-color: var(--line);
}
.stackplan-unit[data-state='arrears']     { background: var(--neg-soft);  color: var(--neg-ink);  border-color: color-mix(in srgb, var(--neg) 32%, transparent); }
.stackplan-unit[data-state='notice']      { background: var(--warn-soft); color: var(--warn-ink); border-color: color-mix(in srgb, var(--warn) 32%, transparent); }
.stackplan-unit[data-state='maintenance'] { background: var(--info-soft); color: var(--info-ink); border-color: color-mix(in srgb, var(--info) 30%, transparent); }
.stackplan-unit[data-state='reserved']    { background: var(--accent-soft); color: var(--accent-ink); border-color: color-mix(in srgb, var(--accent) 32%, transparent); }
.stackplan-unit[data-state='unavailable'] { background: var(--surface-2); color: var(--ink-4); border-color: var(--line); opacity: .6; }

.stackplan-legend {
  display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-4);
  margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--line);
  font-size: var(--text-xs); color: var(--ink-3);
}
.stackplan-legend-item { display: flex; align-items: center; gap: var(--space-2); }
.stackplan-legend-swatch { width: 12px; height: 12px; border-radius: 3px; border: 1px solid transparent; flex: none; }

/* Compact strip: the whole portfolio as one row per property, for the dashboard. */
.heatstrip { display: flex; flex-direction: column; gap: var(--space-3); }
.heatstrip-row { display: flex; align-items: center; gap: var(--space-3); }
.heatstrip-name { flex: none; width: 130px; font-size: var(--text-sm); font-weight: 550; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.heatstrip-cells { flex: 1; display: flex; gap: 2px; }
.heatstrip-cell { flex: 1; height: 24px; min-width: 6px; border-radius: 2px; transition: transform var(--duration-fast) var(--ease); }
.heatstrip-cell:hover { transform: scaleY(1.25); }
.heatstrip-cell[data-state='occupied']    { background: var(--brand); }
.heatstrip-cell[data-state='vacant']      { background: var(--line-2); }
.heatstrip-cell[data-state='arrears']     { background: var(--neg); }
.heatstrip-cell[data-state='notice']      { background: var(--warn); }
.heatstrip-cell[data-state='maintenance'] { background: var(--info); }
.heatstrip-cell[data-state='reserved']    { background: var(--accent); }
.heatstrip-cell[data-state='unavailable'] { background: var(--surface-3); }
.heatstrip-stat { flex: none; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--ink-3); font-variant-numeric: tabular-nums; }

@media (max-width: 640px) {
  .stackplan-unit { flex-basis: 56px; min-width: 52px; min-height: 46px; }
  .stackplan-unit-meta { display: none; }
  .heatstrip-name { width: 90px; font-size: var(--text-xs); }
}

/* ==========================================================================
   The receipt — payments render as receipts, mono figures and a tear edge.
   A supporting detail, deliberately small, that speaks the trade's language.
   ========================================================================== */

.receipt {
  max-width: 380px; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  font-family: var(--font-mono); font-size: var(--text-xs);
  position: relative; padding: var(--space-5) var(--space-4);
}
.receipt::before, .receipt::after {
  content: ''; position: absolute; left: 0; right: 0; height: 6px;
  background: radial-gradient(circle at 4px 0, transparent 4px, var(--surface) 4px);
  background-size: 10px 6px;
}
.receipt::before { top: -1px; transform: scaleY(-1); }
.receipt::after  { bottom: -1px; }
.receipt-head { text-align: center; padding-bottom: var(--space-3); border-bottom: 1px dashed var(--line-2); }
.receipt-company { font-family: var(--font-sans); font-weight: 650; font-size: var(--text-base); letter-spacing: -.01em; }
.receipt-row { display: flex; justify-content: space-between; gap: var(--space-3); padding: 3px 0; }
.receipt-row dt { color: var(--ink-3); }
.receipt-row dd { font-variant-numeric: tabular-nums; text-align: right; }
.receipt-total {
  display: flex; justify-content: space-between; margin-top: var(--space-3);
  padding-top: var(--space-3); border-top: 1px dashed var(--line-2);
  font-size: var(--text-base); font-weight: 600;
}

/* ==========================================================================
   Timeline — ticket history, lease events, audit trail
   ========================================================================== */

.timeline { position: relative; padding-left: var(--space-6); }
.timeline::before { content: ''; position: absolute; left: 9px; top: 6px; bottom: 6px; width: 1px; background: var(--line); }
.timeline-item { position: relative; padding-bottom: var(--space-5); }
.timeline-item:last-child { padding-bottom: 0; }
.timeline-dot {
  position: absolute; left: calc(var(--space-6) * -1 + 4px); top: 3px;
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--surface); border: 2px solid var(--line-2);
}
.timeline-item[data-tone='pos']  .timeline-dot { border-color: var(--pos); }
.timeline-item[data-tone='neg']  .timeline-dot { border-color: var(--neg); }
.timeline-item[data-tone='warn'] .timeline-dot { border-color: var(--warn); }
.timeline-item[data-tone='accent'] .timeline-dot { background: var(--accent); border-color: var(--accent); }
.timeline-title { font-size: var(--text-sm); font-weight: 550; }
.timeline-meta { font-size: var(--text-xs); color: var(--ink-3); margin-top: 1px; }
.timeline-body {
  font-size: var(--text-sm); color: var(--ink-2); margin-top: var(--space-2);
  padding: var(--space-3); background: var(--surface-2);
  border-radius: var(--radius-sm); line-height: var(--leading-normal);
}
.timeline-body--internal { background: var(--warn-soft); border: 1px dashed color-mix(in srgb, var(--warn) 35%, transparent); }

/* ==========================================================================
   Progress and meters
   ========================================================================== */

.meter { height: 6px; background: var(--surface-3); border-radius: var(--radius-full); overflow: hidden; }
.meter-fill { height: 100%; background: var(--brand); border-radius: inherit; transition: width var(--duration-slow) var(--ease); }
.meter-fill[data-tone='pos']  { background: var(--pos); }
.meter-fill[data-tone='neg']  { background: var(--neg); }
.meter-fill[data-tone='warn'] { background: var(--warn); }

/* Segmented bar — arrears aging, collection mix. */
.segbar { display: flex; height: 8px; border-radius: var(--radius-full); overflow: hidden; background: var(--surface-3); }
.segbar-seg { height: 100%; transition: flex-grow var(--duration-slow) var(--ease); }

/* Definition list used on every detail page. */
.detail-list { display: grid; gap: var(--space-3); }
.detail-row { display: grid; grid-template-columns: minmax(110px, 34%) 1fr; gap: var(--space-3); align-items: baseline; }
.detail-row dt { font-size: var(--text-xs); color: var(--ink-3); font-weight: 550; }
.detail-row dd { font-size: var(--text-sm); }
@media (max-width: 480px) { .detail-row { grid-template-columns: 1fr; gap: 2px; } }

/* --- Dashboard "waiting on somebody" -------------------------------------
   Each item is a thing a person has to deal with, so the whole tile is the
   target rather than a link buried inside it. */
.attention-item {
  display: flex; gap: var(--space-3); align-items: flex-start;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--surface); text-decoration: none; color: inherit;
  transition: border-color var(--speed) var(--ease), background var(--speed) var(--ease);
}
.attention-item:hover { border-color: var(--line-2); background: var(--surface-2); }
.attention-item:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.attention-title {
  display: block; font-weight: 640; font-size: var(--text-sm); line-height: 1.35;
}
.attention-note {
  display: block; font-size: var(--text-xs); color: var(--ink-3);
  line-height: 1.5; margin-top: 2px;
}

/* --- Settings navigation --------------------------------------------------
   A vertical list rather than horizontal tabs: twelve groups will not fit
   across a screen, and wrapping tabs are hard to scan. */
.settings-tab {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm); font-weight: 500;
  color: var(--ink-2); text-decoration: none;
  transition: background var(--speed) var(--ease), color var(--speed) var(--ease);
}
.settings-tab:hover { background: var(--surface-2); color: var(--ink); }
.settings-tab:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.settings-tab.is-active {
  background: var(--brand-soft); color: var(--brand); font-weight: 640;
}
.settings-tab-count {
  margin-left: auto; font-size: var(--text-xs); font-variant-numeric: tabular-nums;
  color: var(--ink-3);
}
.settings-tab.is-active .settings-tab-count { color: var(--brand); }

.input-suffix {
  display: inline-flex; align-items: center; padding: 0 var(--space-3);
  font-size: var(--text-sm); color: var(--ink-3);
  background: var(--surface-2); border-left: 1px solid var(--line);
}


/* The audit filter bar carries seven controls, which will not sit on one line
   on a laptop. Wrapping beats a horizontal scrollbar on a form. */
.table-toolbar--wrap { flex-wrap: wrap; row-gap: var(--space-2); }

/* ==========================================================================
   Small helpers that views referenced but nothing defined
   ========================================================================== */

/* Hidden on narrow screens. The topbar uses it to drop the search hint and the
   user's name on a phone; without it both were rendering and wrapping. */
@media (max-width: 640px) {
  .hide-sm { display: none !important; }
}

/* The theme toggle swaps two glyphs. Without these rules both were visible at
   once, so the button showed a sun and a moon together. */
.mode-icon-light { display: none; }
[data-theme="dark"] .mode-icon-light { display: block; }
[data-theme="dark"] .mode-icon-dark  { display: none; }

/* How a tenant should pay, on an invoice or receipt. */
.doc-pay-method {
  font-weight: 600; color: var(--ink);
  font-size: var(--text-sm); margin-bottom: 2px;
}

/* ==========================================================================
   Tenant invoice — totals, and how to pay
   ========================================================================== */

/* The totals used to be tfoot rows inside the items table, where they picked
   up the item padding and read as if "Total" were another thing being charged
   for. A summary is a different kind of information and gets its own block. */
.pay-summary { border-top: 1px solid var(--line); padding-top: var(--space-4); }
.pay-row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-4); padding: var(--space-2) 0;
  font-size: var(--text-sm); color: var(--ink-2);
}
.pay-row--total {
  margin-top: var(--space-2); padding-top: var(--space-3);
  border-top: 1px solid var(--line-2);
  font-size: var(--text-base); font-weight: 600; color: var(--ink);
}
.pay-row--total .figure { font-size: var(--text-xl); font-weight: 650; }

/* How to pay. On an unpaid invoice this is the most useful thing on the page,
   so it is a panel rather than a sentence, and every value can be copied —
   a paybill mistyped on a phone is the commonest reason a payment goes
   unmatched for a week. */
.pay-how {
  border-top: 1px solid var(--line);
  background: var(--surface-2);
}
.pay-how-title {
  font-size: var(--text-2xs); font-weight: 700; letter-spacing: var(--tracking-caps);
  text-transform: uppercase; color: var(--ink-3); margin: 0 0 var(--space-3);
}
.pay-grid { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.pay-field {
  flex: 1 1 168px; display: flex; flex-direction: column; gap: 2px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-md); padding: var(--space-3);
}
.pay-label { font-size: var(--text-2xs); color: var(--ink-3); text-transform: uppercase;
             letter-spacing: var(--tracking-caps); font-weight: 600; }
.pay-value { font-size: var(--text-lg); font-weight: 650; color: var(--ink); }
.pay-field .btn { align-self: flex-start; margin-top: var(--space-1); }
.pay-note { font-size: var(--text-sm); color: var(--ink-3); margin: var(--space-3) 0 0;
            line-height: var(--leading-normal); }

.pay-receipt {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-4); padding: var(--space-3) 0;
  border-bottom: 1px solid var(--line);
}
.pay-receipt:last-child { border-bottom: 0; padding-bottom: 0; }
.pay-receipt-date { display: block; font-size: var(--text-sm); font-weight: 600; color: var(--ink); }
.pay-receipt-meta { display: block; font-size: var(--text-xs); color: var(--ink-3); margin-top: 1px; }

/* ==========================================================================
   Contractor portal — a list of jobs, readable on a phone in a stairwell
   ========================================================================== */

.joblist { border-top: 1px solid var(--line); }
.joblist-item {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-4); padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--line); text-decoration: none; color: inherit;
  transition: background var(--motion-fast) var(--ease);
}
.joblist-item:last-child { border-bottom: 0; }
.joblist-item:hover { background: var(--surface-2); }
.joblist-main { min-width: 0; }
.joblist-title {
  display: block; font-weight: 600; font-size: var(--text-base); color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.joblist-meta { display: block; font-size: var(--text-xs); color: var(--ink-3); margin-top: 2px; }
.joblist-side {
  display: flex; flex-direction: column; align-items: flex-end;
  gap: var(--space-1); flex: none; text-align: right;
}
@media (max-width: 560px) {
  .joblist-item { flex-direction: column; align-items: flex-start; gap: var(--space-2); }
  .joblist-side { flex-direction: row; align-items: center; }
}

/* A main column with a sidebar, that becomes one column on a phone.
   The inline `grid-template-columns` these screens used could not carry a
   media query, so on a narrow screen the sidebar stayed a second column and
   both halves were squeezed to nothing — worst on the contractor's job page,
   which is read on a phone in a stairwell more than anywhere else. */
.with-aside {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  align-items: start;
  gap: var(--space-5);
}
/* Two equal halves rather than a main column and a sidebar. */
.with-aside--even { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }

@media (max-width: 900px) {
  .with-aside,
  .with-aside--even { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   Settings — thirteen groups and a hundred and twenty settings
   ========================================================================== */

/* A narrow index beside the settings themselves, one column on a phone —
   the inline grid this replaced could not carry a media query, so on a
   handset the tab list and the form fought over 200px each. */
.settings-layout {
  display: grid;
  grid-template-columns: minmax(0, 240px) minmax(0, 1fr);
  align-items: start;
  gap: var(--space-5);
}
@media (max-width: 900px) {
  .settings-layout { grid-template-columns: minmax(0, 1fr); }
}

.settings-nav { position: sticky; top: var(--space-5); }

.settings-search { font-size: var(--text-sm); }

/* Results appear under the box and replace the tab list's job entirely —
   somebody who knows what they want should never have to guess a tab. */
.settings-results {
  margin-top: var(--space-2); max-height: 320px; overflow-y: auto;
  border: 1px solid var(--line); border-radius: var(--radius-md);
  background: var(--surface);
}
.settings-result {
  display: block; padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--line); text-decoration: none; color: inherit;
}
.settings-result:last-child { border-bottom: 0; }
.settings-result:hover,
.settings-result.is-active { background: var(--surface-2); }
.settings-result-label { display: block; font-size: var(--text-sm); font-weight: 600; color: var(--ink); }
.settings-result-where { display: block; font-size: var(--text-2xs); color: var(--ink-3); margin-top: 1px; }
.settings-results-empty { padding: var(--space-3); font-size: var(--text-sm); color: var(--ink-3); }

/* A word about the group's state, not a count of its fields. "SMS 8" said the
   same thing whether it was working or blank. */
.settings-tab-state {
  font-size: var(--text-2xs); font-weight: 600; letter-spacing: .02em;
  padding: 1px var(--space-2); border-radius: var(--radius-pill);
  background: var(--surface-2); color: var(--ink-3); white-space: nowrap;
}
.settings-tab-state.is-warn { background: var(--warn-soft); color: var(--warn); }
.settings-tab-state.is-on   { background: var(--pos-soft);  color: var(--pos); }
.settings-tab-state.is-off  { background: transparent; color: var(--ink-4); }

/* A heading between runs of related settings. */
.settings-section {
  font-size: var(--text-2xs); font-weight: 700; letter-spacing: var(--tracking-caps);
  text-transform: uppercase; color: var(--ink-3);
  margin: var(--space-6) 0 var(--space-3);
  padding-bottom: var(--space-2); border-bottom: 1px solid var(--line);
}
.settings-section:first-child { margin-top: 0; }

/* The save bar follows the viewport.
   `position: sticky` only sticks within its own scrolling ancestor, and the
   card is taller than the screen — so the bar sat at the foot of an 1,800px
   card, exactly where it was before. Fixed to the viewport instead, inset to
   line up with the form rather than spanning the sidebar. */
.settings-save {
  position: fixed; bottom: 0; z-index: 20;
  left: 0; right: 0;
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-6);
  background: var(--surface);
  border-top: 1px solid var(--line-2);
  box-shadow: 0 -4px 16px rgba(0, 0, 0, .06);
}
/* Clear of the sidebar on a desktop. */
@media (min-width: 901px) {
  .settings-save { left: var(--sidebar-width, 248px); }
}
/* And the page needs room underneath it, or the last field hides behind it. */
.settings-page-pad { padding-bottom: 84px; }
.settings-changed {
  font-size: var(--text-xs); font-weight: 600; color: var(--warn);
}

@media (max-width: 900px) {
  .settings-nav { position: static; }
  .settings-tabs { display: flex; flex-wrap: wrap; gap: var(--space-1); }
  .settings-tabs .settings-tab { width: auto; }
}

/* Arriving from the search box, so the right field is obvious among twenty. */
.field.is-highlighted {
  animation: settingFlash 2.4s var(--ease);
  border-radius: var(--radius-md);
}
@keyframes settingFlash {
  0%, 60% { background: var(--warn-soft); box-shadow: 0 0 0 6px var(--warn-soft); }
  100%    { background: transparent; box-shadow: none; }
}
