/* ============================================================================
   Design tokens. Every colour, radius, shadow and duration in this file comes
   from here. Legacy names (--ink, --muted, --canvas, --surface, --line,
   --brand, --focus) are kept as aliases so the existing layout rules adopt the
   new system without being rewritten.
   ========================================================================= */
:root {
  color-scheme: light;

  --bg-primary: #f9f9fb;
  --bg-secondary: #f1f1f4;
  --bg-tertiary: #e8e8ec;
  --bg-elevated: #ffffff;

  --text-primary: #0f0f0f;
  --text-secondary: #5a5a5a;
  /* Spec value #9d9489 measures 2.94:1 on --bg-primary. Darkened to the
     nearest tone that clears WCAG AA for 13px text. */
  --text-tertiary: #6b6b6b;

  --border: #d5d5db;
  --border-strong: #b8b8b8;

  /* Identity accent. --accent-fill is the same hue darkened until white text
     on it clears 4.5:1; the spec value measures 3.77:1 and would regress the
     most-used control in the app. */
  --accent: #991b1b;
  --accent-fill: #991b1b;
  --accent-hover: #7f1616;
  --accent-ring: rgb(153 27 27 / 0.18);
  --on-accent: #ffffff;
  --on-critical: #ffffff;
  /* --brand is the sidebar surface. It is dark in both themes, so its text is
     light: #5f5f64 on #1c1c1e would be 2.68:1. */
  --on-brand: #0f0f0f;
  /* Derived, not hand-set: this token's correct value depends on whether
     --brand is light or dark, and it inverted on all three theme swaps when it
     was a literal. color-mix resolves lazily at use time, so it re-derives from
     whichever --on-brand/--brand pair is in scope. Pre-color-mix engines drop
     the declaration and .workspace-control inherits --on-brand instead, which
     is readable rather than broken. */
  --on-brand-muted: color-mix(in srgb, var(--on-brand) 65%, var(--brand));
  --brand-active: rgb(153 27 27 / 0.1);
  --brand-hover: color-mix(in srgb, var(--accent) 8%, transparent);
  --accent-glow: color-mix(in srgb, var(--accent) 8%, transparent);
  --workspace-surface: color-mix(in srgb, var(--accent) 6%, transparent);
  --workspace-surface-hover: color-mix(in srgb, var(--accent) 10%, transparent);
  --workspace-edge: color-mix(in srgb, var(--accent) 12%, transparent);
  --workspace-edge-hover: color-mix(in srgb, var(--accent) 20%, transparent);

  --success: #059669;
  --warning: #d97706;
  --critical: #dc2626;
  --critical-fill: #c92a2a;
  --critical-hover: #b91c1c;

  /* Badge text is darkened against its own tint; the raw hues measure
     3.34 / 2.80 / 4.29 on those tints. */
  --success-text: #047857;
  --warning-text: #92400e;
  --critical-text: #b91c1c;
  --success-tint: rgb(5 150 105 / 0.1);
  --warning-tint: rgb(217 119 6 / 0.12);
  --critical-tint: rgb(220 38 38 / 0.1);

  --shade-subtle: rgb(29 29 31 / 0.04);
  --shade-medium: rgb(29 29 31 / 0.08);
  --shadow-sm: 0 1px 3px rgb(29 29 31 / 0.08), 0 1px 2px rgb(29 29 31 / 0.04);
  --shadow-md: 0 4px 16px rgb(29 29 31 / 0.12);

  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 10px;
  --radius-pill: 999px;

  --space-1: 6px;
  --space-2: 12px;
  --space-3: 14px;
  --space-4: 16px;
  --space-5: 18px;
  --space-6: 20px;
  --space-7: 24px;
  --space-8: 28px;
  --space-9: 32px;
  --space-10: 40px;

  --motion: 150ms;
  --ease: cubic-bezier(0.2, 0, 0, 1);

  /* Legacy aliases. */
  --ink: var(--text-primary);
  --muted: var(--text-secondary);
  --canvas: var(--bg-primary);
  --surface: var(--bg-elevated);
  --line: var(--border);
  --brand: #e8e8ec;
  --focus: var(--accent-fill);

  font:
    15px/1.6 system-ui,
    sans-serif;
}

:root:not([data-theme='light']) {
  @media (prefers-color-scheme: dark) {
    color-scheme: dark;
    --bg-primary: #000000;
    --bg-secondary: #1c1c1e;
    --bg-tertiary: #2c2c2e;
    --bg-elevated: #1c1c1e;
    --text-primary: #f5f5f7;
    --text-secondary: #a1a1a6;
    --text-tertiary: #8e8e93;
    --border: #38383a;
    --border-strong: #545458;
    --accent: #f28b82;
    --accent-fill: #f28b82;
    --accent-hover: #f5a49d;
    --accent-ring: rgb(242 139 130 / 0.32);
    /* White on #f28b82 is 2.27:1; the ink tone is 7.12:1. */
    --on-accent: #1c1c1e;
    /* White on #ff6961 is 2.35:1; ink is 6.03:1. */
    --on-critical: #1c1c1e;
    --on-brand: #ffffff;
    --brand-active: rgb(242 139 130 / 0.1);
    --success: #30d158;
    --warning: #ffd60a;
    --critical: #ff6961;
    --critical-fill: #ff6961;
    --critical-hover: #ff8781;
    --success-text: #30d158;
    --warning-text: #ffd60a;
    --critical-text: #ff6961;
    --success-tint: rgb(48 209 88 / 0.16);
    --warning-tint: rgb(255 214 10 / 0.16);
    --critical-tint: rgb(255 105 97 / 0.16);
    --shade-subtle: rgb(255 255 255 / 0.05);
    --shade-medium: rgb(255 255 255 / 0.09);
    --shadow-sm: 0 1px 3px rgb(0 0 0 / 0.35);
    --shadow-md: 0 4px 16px rgb(0 0 0 / 0.45);
    --brand: #1c1c1e;
  }
}

:root[data-theme='dark'] {
  color-scheme: dark;
  --bg-primary: #000000;
  --bg-secondary: #1c1c1e;
  --bg-tertiary: #2c2c2e;
  --bg-elevated: #1c1c1e;
  --text-primary: #f5f5f7;
  --text-secondary: #a1a1a6;
  --text-tertiary: #8e8e93;
  --border: #38383a;
  --border-strong: #545458;
  --accent: #f28b82;
  --accent-fill: #f28b82;
  --accent-hover: #f5a49d;
  --accent-ring: rgb(242 139 130 / 0.32);
  --on-accent: #1c1c1e;
  --on-critical: #1c1c1e;
  --on-brand: #ffffff;
  --brand-active: rgb(242 139 130 / 0.1);
  --success: #30d158;
  --warning: #ffd60a;
  --critical: #ff6961;
  --critical-fill: #ff6961;
  --critical-hover: #ff8781;
  --success-text: #30d158;
  --warning-text: #ffd60a;
  --critical-text: #ff6961;
  --success-tint: rgb(48 209 88 / 0.16);
  --warning-tint: rgb(255 214 10 / 0.16);
  --critical-tint: rgb(255 105 97 / 0.16);
  --shade-subtle: rgb(255 255 255 / 0.05);
  --shade-medium: rgb(255 255 255 / 0.09);
  --shadow-sm: 0 1px 3px rgb(0 0 0 / 0.35);
  --shadow-md: 0 4px 16px rgb(0 0 0 / 0.45);
  --brand: #1c1c1e;
}
* {
  box-sizing: border-box;
}
html {
  height: 100%;
  overflow: hidden;
}
body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: var(--canvas);
  color: var(--ink);
}
/* The signed-in shell is exactly one viewport tall and scrolls its own content pane, so
   this used to be overflow: hidden. That clipped every page that is not the shell - the
   landing page could not be scrolled past its first screen, and a tall auth form on a
   short window had the same problem.
   
   auto rather than hidden: the shell still never overflows this box, so it gains no
   scrollbar, while a document-flow page inside it scrolls as a page should. */
#app {
  height: 100%;
  min-height: 0;
  overflow: auto;
}
.native-shell body {
  padding-top: env(safe-area-inset-top);
  padding-right: env(safe-area-inset-right);
  padding-bottom: env(safe-area-inset-bottom);
  padding-left: env(safe-area-inset-left);
}
.native-connectivity {
  position: fixed;
  right: max(0.75rem, env(safe-area-inset-right));
  bottom: max(0.75rem, env(safe-area-inset-bottom));
  left: max(0.75rem, env(safe-area-inset-left));
  z-index: 1000;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 0.75rem;
  max-width: 42rem;
  margin-inline: auto;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--warning);
  border-radius: 0.65rem;
  background: var(--warning-tint);
  box-shadow: 0 0.6rem 1.5rem var(--shade-medium);
}
.native-connectivity button {
  min-width: 44px;
  min-height: 44px;
  margin: -0.4rem -0.5rem -0.4rem auto;
  border: 0;
  background: transparent;
  font-size: 1.25rem;
}
.native-connectivity--online {
  border-color: var(--success);
  background: var(--success-tint);
}
button,
input,
select,
textarea {
  font: inherit;
  min-height: 44px;
}
button,
.button,
input,
select,
textarea {
  border-radius: 0.4rem;
}
.skip {
  position: absolute;
  left: -999px;
}
.skip:focus {
  left: 1rem;
  top: 1rem;
  background: var(--bg-elevated);
  padding: 0.75rem;
  z-index: 9;
}
.shell {
  display: grid;
  grid-template-columns: 16rem minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
  height: 100%;
  min-height: 0;
  overflow: hidden;
}
.sidebar {
  min-height: 0;
  overflow: auto;
  background: var(--brand);
  color: var(--on-brand);
  padding: 1.25rem;
}
.brand {
  font-weight: 700;
  font-size: 1.15rem;
  letter-spacing: 0.01em;
}
.sidebar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 1rem;
}
.nav-toggle {
  display: none;
}
.workspace-control {
  display: grid;
  gap: 0.35rem;
  margin-bottom: 0.85rem;
  color: var(--on-brand-muted);
}
.workspace-control span {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--accent);
  margin: 16px 0 8px;
  padding: 0 16px;
}
.nav a {
  color: var(--on-brand);
  display: flex;
  align-items: center;
  gap: 10px;
  /* min-height is retained over the 12px padding alone: it guarantees the 44px
     touch target the rest of the app holds to. */
  min-height: 44px;
  padding: 12px 16px;
  margin: 6px 12px;
  border-radius: 12px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
}
/* Nav hover: a lighter version of the current-item tint, excluded from the
   current item so it cannot wash out the active state. Colour comes from
   --brand-hover, which is mixed from --accent, so it follows the theme rather
   than staying burgundy on a dark sidebar where an 8% dark tint would vanish.
   No transition is declared here: `a` already animates background-color at
   --motion (150ms), and a rule-local transition would apply on hover-in only,
   snapping back on hover-out. */
.nav a:hover:not([aria-current='page']) {
  background: var(--brand-hover);
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}
.nav a[aria-current='page'] {
  background: var(--brand-active);
  box-shadow: 0 2px 8px var(--accent-glow);
  /* var(--accent), not the #991b1b literal: on the dark-mode sidebar that literal
     measures 1.37:1 against its own tint, where the token resolves to #f28b82 at
     4.78:1. */
  color: var(--accent);
  font-weight: 600;
}
.workspace,
.search input {
  width: 100%;
}
.workspace {
  display: block;
  width: auto;
  margin: 0 12px 16px;
  padding: 10px 16px;
  border: 1px solid var(--workspace-edge);
  border-radius: 10px;
  background: var(--workspace-surface);
  color: var(--on-brand);
  font-weight: 500;
  cursor: pointer;
}
.workspace:hover {
  background: var(--workspace-surface-hover);
  border-color: var(--workspace-edge-hover);
}
.utility-nav {
  margin-top: 0.75rem;
  border-top: 1px solid var(--border-strong);
  padding-top: 0.65rem;
}
.utility-nav summary {
  min-height: 44px;
  cursor: pointer;
  padding: 0.65rem 0.8rem;
  color: var(--on-brand);
}
.nav--secondary {
  margin-top: 0.25rem;
}
.connectivity-pill {
  margin: 0 0 0.75rem;
  padding: 0.45rem 0.6rem;
  border-radius: 999px;
  font-size: 0.8rem;
  text-align: center;
}
.connectivity-pill--offline {
  color: var(--warning-text);
  background: var(--warning-tint);
}
.sign-out {
  width: 100%;
  margin-top: 1rem;
}
.main {
  min-width: 0;
  min-height: 0;
  height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.topbar {
  flex: 0 0 auto;
  position: relative;
  z-index: 8;
  min-height: 4rem;
  background: var(--bg-elevated);
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0 2rem;
  border-bottom: 1px solid var(--line, var(--border));
}
.sync-indicator {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-left: auto;
  font-size: 0.8125rem;
  color: var(--muted, var(--text-secondary));
  white-space: nowrap;
}
.sync-indicator .sync-state[data-attention='true'] {
  color: var(--warning-text);
  font-weight: 600;
}
.button--quiet {
  min-height: 2.25rem;
  padding: 0.3rem 0.7rem;
  font-size: 0.8125rem;
}

/* A page's primary action. Trimmed so it reads as a control rather than a slab,
   but only where the pointer is precise: a coarse pointer keeps the 44px target,
   because shrinking a touch target to look tidier makes it harder to hit. */
@media (pointer: fine) {
  /* .button.button--compact, not .button--compact: the base rule is written as
     `button.button`, which outranks a single class and would otherwise keep the
     full padding, radius and text size. */
  .button.button--compact,
  .pagehead .actions .button,
  .quick-actions .button {
    min-height: 2.25rem;
    padding: 0.5rem 0.9rem;
    border-radius: var(--radius-sm);
    font-size: 0.875rem;
  }
}
/* Active filters, named above the list. */
.filter-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}
.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 2rem;
  padding: 4px 10px;
  border: 1px solid color-mix(in srgb, var(--accent-fill) 35%, transparent);
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--accent-fill) 12%, transparent);
  /* The accent on a 12% tint of itself: dark red on near-white in light mode,
     light salmon on near-black in dark. Both clear 4.5:1. */
  color: var(--accent);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.filter-chip:hover {
  background: color-mix(in srgb, var(--accent-fill) 20%, transparent);
}
.filter-chip__remove {
  font-size: 15px;
  line-height: 1;
  opacity: 0.7;
}
.filter-chip--clear {
  border-style: dashed;
  background: transparent;
}
/* The selection bar. Sticky at the foot of the page so the count and the way out
   of a selection stay visible however far the list scrolls. */
.bulk-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 30;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  padding: 12px 20px max(12px, env(safe-area-inset-bottom));
  background: var(--accent-fill);
  color: var(--on-accent);
  box-shadow: 0 -4px 16px var(--shade-medium);
}
.bulk-bar__count {
  margin: 0;
  /* Explicit, not inherited: a paragraph rule elsewhere sets a grey that lands at
     about 1.8:1 on this burgundy. White on #991b1b is 8.6:1. */
  color: var(--on-accent);
  font-size: 14px;
  font-weight: 600;
}
.bulk-bar__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  flex: 1 1 auto;
}
.bulk-bar__empty {
  margin: 0;
  color: var(--on-accent);
  font-size: 13px;
  opacity: 0.85;
}
/* Controls on the burgundy bar are light, so they read against it rather than
   borrowing the page's surface colours. */
.bulk-bar .button {
  background: color-mix(in srgb, #ffffff 16%, transparent);
  border-color: color-mix(in srgb, #ffffff 45%, transparent);
  color: var(--on-accent);
}
.bulk-bar .button:hover {
  background: color-mix(in srgb, #ffffff 26%, transparent);
  border-color: var(--on-accent);
}
.bulk-bar .button--danger {
  background: var(--on-accent);
  border-color: var(--on-accent);
  color: var(--accent-fill);
}
.bulk-bar .button--danger:hover {
  background: color-mix(in srgb, #ffffff 88%, var(--accent-fill));
}
.bulk-bar__clear {
  margin-left: auto;
}
@media (max-width: 767px) {
  /* Above the drawer's own safe-area padding, so a selection made in the list is
     still actionable while the record panel is open. */
  .bulk-bar {
    z-index: 25;
  }
  .bulk-bar__clear {
    margin-left: 0;
  }
}
/* The list gets room to scroll clear of the bar. */
.property-workspace {
  scroll-padding-bottom: 5rem;
}

/* The number of filters currently on, on the Filter control itself. */
.record-filters > summary {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.filter-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.25rem;
  height: 1.25rem;
  padding: 0 4px;
  border-radius: var(--radius-pill);
  background: var(--accent-fill);
  color: var(--on-accent);
  font-size: 11px;
  font-weight: 700;
}
.offline-summary {
  display: flex;
  flex: 1;
  flex-wrap: wrap;
  gap: 0.25rem 0.65rem;
  align-items: baseline;
  min-width: 0;
}

.offline-topbar-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-left: auto;
}

.offline-topbar-actions .button {
  min-height: 2.25rem;
  padding: 0.35rem 0.6rem;
}

.device-history {
  margin-top: 1rem;
  border-top: 1px solid var(--line);
  padding-top: 0.75rem;
}

.device-history > summary,
.technical-disclosure > summary {
  cursor: pointer;
  color: var(--muted);
}

.technical-disclosure code {
  display: block;
  margin-top: 0.35rem;
  overflow-wrap: anywhere;
  font-size: 0.8rem;
}
.offline-summary strong {
  color: var(--warning-text);
}
.offline-summary span {
  color: var(--muted);
  overflow-wrap: anywhere;
}
.offline-search-link {
  white-space: nowrap;
}
.offline-context {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.75rem;
  align-items: baseline;
  margin: 0 0 1rem;
  padding: 0.55rem 0.7rem;
  border-left: 4px solid var(--warning);
  background: var(--warning-tint);
  color: var(--muted);
}
.offline-context strong {
  color: var(--ink);
}
.offline-metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: 0.65rem;
}
.offline-metrics article {
  display: grid;
  gap: 0.15rem;
  padding: 0.75rem;
  border: 1px solid var(--line);
  border-radius: 0.5rem;
  background: var(--canvas);
}
.offline-metrics strong {
  font-size: 1.4rem;
}
.search {
  max-width: 38rem;
  width: 100%;
}
.content {
  flex: 1 1 0%;
  max-width: 88rem;
  width: 100%;
  margin-inline: auto;
  padding: 0 2rem 2rem;
  overflow: auto;
  min-height: 0;
  overscroll-behavior: contain;
}
.pagehead {
  display: flex;
  justify-content: space-between;
  gap: 2rem;
  padding-top: 1.5rem;
}
.actions,
.tabs,
.section-nav {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}
/* The page header is a flex row, so without this the action column stretches to the
   height of the title block beside it and drags the button up to ~49px tall. That
   stretch, not the padding, is what made the primary action read as a slab. */
.pagehead {
  align-items: flex-start;
}
.actions {
  align-items: flex-start;
}
.section-nav {
  position: sticky;
  top: var(--finance-nav-top, 0px);
  z-index: 6;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.75rem;
  border-bottom: 1px solid var(--line, var(--border));
  max-width: none;
  min-width: 0;
  width: auto;
  margin: 0 -2rem;
  padding: 0.2rem 2rem 0.25rem;
  box-sizing: border-box;
  background: var(--canvas, var(--bg-primary));
}
.section-nav a {
  color: inherit;
  text-decoration: none;
  padding: 0.55rem 0;
  border-bottom: 3px solid transparent;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}
.section-nav a[aria-current='location'] {
  border-bottom-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}
.panel[id^='finance-'] {
  scroll-margin-top: 0;
}
.button {
  padding: 0.55rem 0.9rem;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--ink);
  cursor: pointer;
}
.button--danger {
  color: var(--on-critical);
  background: var(--critical-fill);
}
.empty {
  text-align: center;
  padding: 4rem 1rem;
}
.empty.compact,
.empty-note {
  text-align: left;
  padding: 0.15rem 0 0.35rem;
  margin: 0;
}
.empty.compact h2,
.empty-note {
  font-size: 1rem;
  font-weight: 500;
  color: var(--muted);
}
.empty.compact p {
  margin: 0.25rem 0 0;
}
/* Superseded by the branded auth layout in the component layer below. Only the parts
   that still apply are kept here; max-width and margin moved to .auth-card. */
.auth {
  background: var(--bg-elevated);
}
.auth label,
.auth input {
  display: block;
  width: 100%;
}
.auth input {
  min-height: 48px;
  margin: 0.5rem 0 1rem;
}
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
}
:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}
@media (max-width: 760px) {
  html,
  body,
  #app {
    height: auto;
    overflow: visible;
  }
  .shell {
    display: block;
    height: auto;
    overflow: visible;
  }
  .main {
    min-height: 0;
    height: auto;
    overflow: visible;
  }
  .content {
    overflow: visible;
    flex: none;
    padding: 0 1rem 1rem;
  }
  .sidebar {
    position: sticky;
    top: 0;
    z-index: 9;
  }
  .topbar {
    position: sticky;
    top: 0;
    padding: 0.75rem 1rem;
  }
  .sync-indicator .sync-age {
    display: none;
  }
  .nav {
    display: flex;
    overflow: auto;
  }
  .nav a {
    white-space: nowrap;
  }
  .workspace {
    margin-bottom: 0.5rem;
  }
  .pagehead {
    display: block;
  }
  button {
    min-height: 48px;
  }
  .section-nav {
    margin: 0 -1rem;
    padding: 0.2rem 1rem 0.25rem;
  }
}
/* Phase 19 data-bound workflow surfaces. */
.topbar .search {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
}
.topbar .search label {
  flex: 1;
}
.topbar input {
  width: 100%;
}
.account {
  color: var(--ink);
  white-space: nowrap;
}
.workflow {
  display: grid;
  gap: 0.85rem;
  margin-top: 0.75rem;
  min-width: 0;
}
.panel,
.callout,
.command-form {
  background: var(--bg-elevated);
  border: 1px solid var(--line);
  border-radius: 0.35rem;
  padding: 1.25rem;
  min-width: 0;
  max-width: 100%;
}
.panel h2,
.command-form h3 {
  margin-top: 0;
}
.callout {
  border-left: 5px solid var(--accent-fill);
}
.callout--warning {
  border-left-color: var(--warning-text);
  background: var(--warning-tint);
}
.callout--error {
  border-left-color: var(--critical-fill);
  background: var(--critical-tint);
}
.callout--success {
  border-left-color: var(--success-text);
  background: var(--success-tint);
}
.command-form > summary {
  cursor: pointer;
  display: inline-flex;
  list-style: none;
}
.command-form[open] > summary {
  margin-bottom: 1rem;
}
.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 1rem;
  margin: 1rem 0;
  /*
   * Each field is as tall as it needs to be, not as tall as the tallest thing beside it.
   * Without this a grid row stretches its items: the date of birth label sat next to the
   * address fieldset, so its input was stretched to 276px - a date control the height of
   * six fields, where clicking landed on whichever segment the pointer happened to hit.
   */
  align-items: start;
}
/*
 * A grid item may be narrower than the thing inside it.
 *
 * Without this, min-width:auto keeps every item at its content's intrinsic width, and the
 * address fieldset - a form in its own right - held the row 75px wider than the dialog.
 * The overflow was invisible until a field took focus, at which point the browser scrolled
 * the whole form sideways to reach it. That is the form "jumping" when the date of birth
 * was clicked.
 */
.form-grid > *,
.form-grid .address-group * {
  min-width: 0;
}
/* The address block is a form inside a form; half a column is not enough for it. */
.form-grid .address-group {
  grid-column: 1 / -1;
}
.occupancy-plan,
.finance-plan {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.15rem;
  margin: 1rem 0;
  min-width: 0;
}
.occupancy-plan .field-wide,
.occupancy-plan label,
.finance-plan .field-wide,
.finance-plan label {
  min-width: 0;
}
.occupancy-plan select,
.occupancy-plan input,
.finance-plan select,
.finance-plan input {
  width: 100%;
  max-width: 100%;
}
.field-hint {
  margin: 0.35rem 0 0;
  font-weight: 400;
  color: var(--muted);
  overflow-wrap: anywhere;
}
input[type='date'].is-empty {
  color: transparent;
}
input[type='date'].is-empty::-webkit-datetime-edit {
  color: transparent;
}
input[type='date'].is-empty:focus,
input[type='date'].is-empty:focus-visible,
input[type='date'].is-empty:focus::-webkit-datetime-edit {
  color: inherit;
}
.form-grid label,
.auth label,
[data-security-flow] label,
dialog label {
  display: grid;
  gap: 0.35rem;
  font-weight: 600;
}
.form-grid input,
.form-grid select,
.form-grid textarea,
.auth input,
[data-security-flow] input,
[data-security-flow] select,
dialog input,
dialog textarea {
  min-height: 2.75rem;
  border: 1px solid var(--border-strong);
  border-radius: 0.2rem;
  padding: 0.55rem;
  background: var(--bg-elevated);
}
.form-grid textarea,
dialog textarea {
  min-height: 6rem;
}
.button--primary {
  background: var(--accent-fill);
  border-color: var(--accent-fill);
  color: var(--on-accent);
}
.button--device {
  border: 2px solid var(--accent);
  background: var(--success-tint);
  color: var(--success-text);
  font-weight: 700;
}
.device-action-label {
  margin: 1rem 0 0.5rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.9rem;
  font-weight: 650;
}
.offline-boundary p {
  margin-bottom: 0;
}
.button:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
.table-wrap {
  overflow: auto;
  max-width: 100%;
  min-width: 0;
}
[id^='finance-'] .table-wrap {
  container-type: inline-size;
  container-name: finance-table;
}
table {
  border-collapse: collapse;
  width: 100%;
  background: var(--bg-elevated);
}
caption {
  text-align: left;
  font-weight: 700;
  padding: 0.5rem 0;
}
th,
td {
  border-bottom: 1px solid var(--line);
  padding: 0.7rem;
  text-align: left;
  vertical-align: top;
  overflow-wrap: break-word;
  word-break: normal;
}
th {
  background: var(--bg-tertiary);
}
.status {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-weight: 700;
}
.status--active,
.status--available,
.status--enabled,
.status--settled,
.status--finalized {
  color: var(--success-text);
}
.status--archived,
.status--restricted,
.status--quarantined,
.status--reversed,
.status--failed {
  color: var(--critical-text);
}
.status--scanning,
.status--processing,
.status--syncing,
.status--not\ enabled {
  color: var(--warning-text);
}
.section-lead {
  margin: 0 0 0.75rem;
  color: var(--muted);
}
.section-action {
  margin: 0.65rem 0 0;
}
.finance-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: flex-start;
}
.finance-actions .command-form {
  flex: 1 1 12rem;
  padding: 0.55rem 0.75rem;
}
.finance-actions .command-form[open] {
  flex: 1 1 100%;
  padding: 1rem;
}
.finance-actions--correction {
  margin-top: 0.35rem;
  padding-top: 0.35rem;
  border-top: 1px solid var(--line, var(--border));
}
.finance-actions--correction .command-form {
  border-color: var(--critical);
}
select[data-derived='true'] {
  background: var(--bg-tertiary);
  color: var(--ink);
  pointer-events: none;
}
.col-money,
.col-status,
.col-date,
.col-support,
.col-capacity {
  width: 1%;
  white-space: nowrap;
  overflow-wrap: normal;
  word-break: keep-all;
}
.capacity-figure {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.1rem;
}
.capacity-figure > span {
  white-space: nowrap;
  overflow-wrap: normal;
  word-break: keep-all;
}
.col-money {
  font-variant-numeric: tabular-nums;
}
.panel .data-table caption {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
}
@container finance-table (max-width: 52rem) {
  .col-support {
    display: none;
  }
}
.secret {
  font-family: ui-monospace, monospace;
  overflow-wrap: anywhere;
}
dialog {
  border: 0;
  border-radius: 0.4rem;
  box-shadow: var(--shadow-md);
  max-width: 34rem;
  width: calc(100% - 2rem);
  padding: 1.5rem;
}
dialog::backdrop {
  background: var(--shade-medium);
}
.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.75rem;
  margin-top: 1.25rem;
}
@media (min-width: 761px) {
  .occupancy-plan,
  .finance-plan {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }
  .occupancy-plan .field-wide,
  .finance-plan .field-wide {
    grid-column: 1 / -1;
  }
}
/* Signing in.
 *
 * These fifteen screens are the first and last thing anybody sees, and they used to be
 * an unstyled box: no mark, no product name, and none of the accent that runs through
 * the rest of the application. The page now carries the same logo as the browser tab and
 * the same accent as every primary action behind it.
 *
 * The card holds its own width while the page fills the viewport, so the form sits in
 * one place rather than clinging to the top of a tall empty screen. */
.auth {
  min-height: 100vh;
  margin: 0;
  padding: 2rem 1rem 3rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
  background: var(--bg-primary);
  border: 0;
  max-width: none;
}
.auth-header {
  text-align: center;
}
.auth-logo {
  width: 48px;
  height: 48px;
  display: block;
  margin: 0 auto 0.75rem;
}
.auth-wordmark {
  margin: 0;
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--text-secondary);
}
.auth-card {
  width: 100%;
  max-width: 26rem;
  background: var(--bg-elevated);
  border: 1px solid var(--line, var(--border));
  /* The accent edge is the one piece of colour that ties this to the sidebar. */
  border-top: 3px solid var(--accent);
  border-radius: 12px;
  padding: 2rem;
}
.auth-card h1 {
  margin-top: 0;
  font-size: 1.5rem;
}
.auth form {
  display: grid;
  gap: 1rem;
}
.auth button {
  min-height: 2.75rem;
}
/* The submit button is the primary action on every one of these screens, and it was
   indistinguishable from the two links beside it. */
.auth-card form button[type='submit'] {
  background: var(--accent-fill);
  color: var(--on-accent);
  border: 1px solid var(--accent-fill);
  border-radius: 6px;
  font-weight: 600;
  width: 100%;
}
.auth-card form button[type='submit']:hover:not(:disabled) {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}
.auth-card form button[type='submit']:disabled {
  opacity: 0.6;
  cursor: progress;
}
/* Everything that is not the primary action reads as a link, because that is what
   "Create account" and "Forgot password" are. */
.auth-card nav button,
.auth-card > button[type='button'],
.auth-card form button[type='button']:not([data-use-recovery]) {
  background: none;
  border: 0;
  color: var(--accent);
  font-weight: 500;
  padding: 0.25rem;
  min-height: auto;
  cursor: pointer;
}
.auth-card nav button:hover,
.auth-card > button[type='button']:hover {
  text-decoration: underline;
}
.auth-card nav {
  display: flex;
  gap: 1.25rem;
  justify-content: center;
  margin-top: 1.25rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--line, var(--border));
}
@media (max-width: 480px) {
  .auth {
    padding: 1.5rem 0.75rem 2rem;
  }
  .auth-card {
    padding: 1.5rem;
  }
}
@media (max-width: 760px) {
  .content,
  .workflow,
  .section-nav,
  .table-wrap,
  .finance-overview {
    max-width: 100vw;
  }
  .section-nav {
    gap: 0.25rem 0.75rem;
    padding: 0.25rem 0;
  }
  .section-nav a {
    min-height: 2.5rem;
    padding: 0.35rem 0;
  }
  .topbar {
    height: auto;
    padding: 0.75rem;
  }
  .topbar .search button {
    min-height: 3rem;
  }
  .account {
    display: none;
  }
  .panel,
  .callout,
  .command-form {
    padding: 1rem;
  }
  .form-grid,
  .occupancy-plan,
  .finance-plan {
    grid-template-columns: 1fr;
  }
  .section-nav {
    margin-bottom: 0;
  }
  .col-money,
  .col-status,
  .col-date {
    white-space: nowrap;
  }
  [id^='maintenance-'] .col-location,
  [id^='maintenance-'] .col-priority {
    display: none;
  }
  [id^='maintenance-'] .data-table {
    table-layout: fixed;
    width: 100%;
  }
  [id^='maintenance-'] .col-status {
    width: 5rem;
    white-space: normal;
  }
  [id^='maintenance-'] .col-support {
    width: calc(17ch + 1.4rem);
    white-space: nowrap;
    overflow-wrap: normal;
    word-break: keep-all;
  }
  [data-table='documents'] {
    overflow: visible;
  }
  [data-table='documents'] thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
    padding: 0;
  }
  [data-table='documents'] .data-table,
  [data-table='documents'] tbody {
    display: block;
    width: 100%;
    table-layout: auto;
  }
  [data-table='documents'] tbody tr {
    display: grid;
    gap: 0.35rem;
    margin: 0 0 0.85rem;
    padding: 0.75rem 0.85rem;
    border: 1px solid var(--line, var(--border));
    border-radius: 0.35rem;
    background: var(--bg-elevated);
  }
  [data-table='documents'] td {
    display: grid;
    grid-template-columns: 7.5rem minmax(0, 1fr);
    align-items: start;
    gap: 0.65rem;
    width: auto;
    max-width: none;
    min-width: 0;
    padding: 0.2rem 0;
    border: 0;
    white-space: normal;
    overflow-wrap: break-word;
    word-break: normal;
  }
  [data-table='documents'] td::before {
    content: attr(data-label);
    font-weight: 700;
    color: var(--muted);
    white-space: nowrap;
  }
  [data-table='documents'] .col-status,
  [data-table='documents'] .col-type,
  [data-table='documents'] .col-text {
    width: auto;
    white-space: normal;
  }
  [data-table='reports'] {
    overflow: visible;
  }
  [data-table='reports'] thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
    padding: 0;
  }
  [data-table='reports'] .data-table,
  [data-table='reports'] tbody {
    display: block;
    width: 100%;
    table-layout: auto;
  }
  [data-table='reports'] tbody tr {
    display: grid;
    gap: 0.35rem;
    margin: 0 0 0.85rem;
    padding: 0.75rem 0.85rem;
    border: 1px solid var(--line, var(--border));
    border-radius: 0.35rem;
    background: var(--bg-elevated);
  }
  [data-table='reports'] td {
    display: grid;
    grid-template-columns: 7.5rem minmax(0, 1fr);
    align-items: start;
    gap: 0.65rem;
    width: auto;
    max-width: none;
    min-width: 0;
    padding: 0.2rem 0;
    border: 0;
    white-space: normal;
    overflow-wrap: break-word;
    word-break: normal;
  }
  [data-table='reports'] td::before {
    content: attr(data-label);
    font-weight: 700;
    color: var(--muted);
    white-space: nowrap;
  }
  [data-table='reports'] .col-status,
  [data-table='reports'] .col-type,
  [data-table='reports'] .col-date,
  [data-table='reports'] .col-text {
    width: auto;
    white-space: normal;
  }
  [data-table='occupancies'],
  [data-table='spaces'] {
    overflow: visible;
  }
  [data-table='occupancies'] thead,
  [data-table='spaces'] thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
    padding: 0;
  }
  [data-table='occupancies'] .data-table,
  [data-table='occupancies'] tbody,
  [data-table='spaces'] .data-table,
  [data-table='spaces'] tbody {
    display: block;
    width: 100%;
    table-layout: auto;
  }
  [data-table='occupancies'] tbody tr,
  [data-table='spaces'] tbody tr {
    display: grid;
    gap: 0.35rem;
    margin: 0 0 0.85rem;
    padding: 0.75rem 0.85rem;
    border: 1px solid var(--line, var(--border));
    border-radius: 0.35rem;
    background: var(--bg-elevated);
  }
  [data-table='occupancies'] td,
  [data-table='spaces'] td {
    display: grid;
    grid-template-columns: 6.75rem minmax(0, 1fr);
    align-items: start;
    gap: 0.65rem;
    width: auto;
    max-width: none;
    min-width: 0;
    padding: 0.2rem 0;
    border: 0;
    white-space: normal;
    overflow-wrap: break-word;
    word-break: normal;
  }
  [data-table='occupancies'] td::before,
  [data-table='spaces'] td::before {
    content: attr(data-label);
    font-weight: 700;
    color: var(--muted);
    white-space: nowrap;
  }
  [data-table='occupancies'] .col-status,
  [data-table='occupancies'] .col-support,
  [data-table='occupancies'] .col-capacity,
  [data-table='occupancies'] .col-resident,
  [data-table='occupancies'] .col-location,
  [data-table='occupancies'] .col-arrangement,
  [data-table='occupancies'] .col-date,
  [data-table='spaces'] .col-capacity,
  [data-table='spaces'] .col-status,
  [data-table='spaces'] .col-space,
  [data-table='spaces'] .col-type,
  [data-table='spaces'] .col-occupancy-mode,
  [data-table='spaces'] .col-property {
    width: auto;
    white-space: normal;
  }
  [data-table='occupancies'] .col-support,
  [data-table='occupancies'] .col-status,
  [data-table='spaces'] .col-status {
    overflow-wrap: normal;
    word-break: keep-all;
  }
  .dialog-actions {
    flex-direction: column-reverse;
  }
  .dialog-actions .button {
    width: 100%;
  }
}

/* Consolidated iPhone product layout. These rules intentionally apply after the
   historical route-specific mobile fixes so every data surface behaves coherently. */
@media (max-width: 760px) {
  .native-shell body {
    padding-top: env(safe-area-inset-top);
    padding-right: env(safe-area-inset-right);
    padding-bottom: env(safe-area-inset-bottom);
    padding-left: env(safe-area-inset-left);
  }
  .sidebar {
    position: sticky;
    top: 0;
    z-index: 12;
    padding: 0.35rem 0.7rem;
    box-shadow: 0 0.15rem 0.6rem var(--shade-medium);
  }
  .sidebar-head {
    min-height: 2.75rem;
    margin: 0;
  }
  .nav-toggle {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    border-color: var(--text-tertiary);
    background: var(--bg-tertiary);
    color: var(--on-brand);
  }
  .nav-panel {
    display: none;
    max-height: calc(100dvh - 4.5rem - env(safe-area-inset-top));
    overflow: auto;
    padding-top: 0.7rem;
  }
  .sidebar.nav-open .nav-panel {
    display: block;
  }
  .nav,
  .nav--secondary {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.3rem;
    overflow: visible;
  }
  .nav a {
    display: flex;
    align-items: center;
    min-width: 0;
    white-space: normal;
    border: 0;
  }
  .workspace {
    display: block;
    min-height: 48px;
    margin: 0;
  }
  .sign-out {
    width: auto;
    min-width: 8rem;
    border-color: var(--text-tertiary);
    background: transparent;
    color: var(--on-brand);
  }
  .topbar {
    position: relative;
    z-index: 7;
    gap: 0.5rem;
    min-height: 3.25rem;
    padding: 0 0.85rem;
  }
  .topbar .search {
    align-items: stretch;
  }
  .topbar .search button {
    flex: 0 0 auto;
  }
  .pagehead {
    padding-top: 0.75rem;
    gap: 0.75rem;
  }
  .pagehead h1 {
    font-size: clamp(1.55rem, 8vw, 2rem);
    line-height: 1.15;
  }
  .pagehead > div > p:last-child {
    margin-bottom: 0.45rem;
  }
  .offline-summary span {
    max-width: 12rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .offline-context {
    font-size: 0.875rem;
  }
  .pagehead p,
  .panel,
  .callout,
  .command-form,
  td,
  dd {
    overflow-wrap: break-word;
    word-break: normal;
  }
  .actions,
  .finance-actions {
    display: grid;
    grid-template-columns: 1fr;
  }
  .actions .button,
  .finance-actions .command-form,
  .command-form > summary,
  .command-form form > .button,
  .command-form form > .device-action-label + .button {
    width: 100%;
  }
  .command-form > summary {
    align-items: center;
    justify-content: space-between;
  }
  .command-form[open] > summary {
    border-bottom: 1px solid var(--line);
    border-radius: 0.4rem 0.4rem 0 0;
    padding-bottom: 0.85rem;
  }
  .form-grid input,
  .form-grid select,
  .form-grid textarea,
  .occupancy-plan input,
  .occupancy-plan select,
  .finance-plan input,
  .finance-plan select {
    width: 100%;
    max-width: 100%;
    min-height: 48px;
  }
  .table-wrap,
  [data-table] {
    overflow: visible;
    max-width: 100%;
  }
  .table-wrap thead,
  [data-table] thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
    padding: 0;
  }
  .table-wrap .data-table,
  .table-wrap tbody,
  [data-table] .data-table,
  [data-table] tbody {
    display: block;
    width: 100%;
    table-layout: auto;
  }
  .table-wrap tbody tr,
  [data-table] tbody tr {
    display: grid;
    gap: 0.25rem;
    margin: 0 0 0.75rem;
    padding: 0.8rem 0.85rem;
    border: 1px solid var(--line);
    border-radius: 0.55rem;
    background: var(--surface);
    box-shadow: 0 0.15rem 0.35rem var(--shade-subtle);
  }
  .table-wrap td,
  [data-table] td {
    display: grid;
    grid-template-columns: minmax(6.5rem, 34%) minmax(0, 1fr);
    align-items: start;
    gap: 0.55rem;
    width: auto !important;
    max-width: 100%;
    min-width: 0;
    padding: 0.28rem 0;
    border: 0;
    white-space: normal !important;
    overflow-wrap: break-word !important;
    word-break: normal !important;
  }
  .table-wrap td::before,
  [data-table] td::before {
    content: attr(data-label);
    min-width: 0;
    color: var(--muted);
    font-weight: 700;
    white-space: normal;
  }
  [id^='maintenance-'] .col-location,
  [id^='maintenance-'] .col-priority {
    display: grid;
  }
  .status,
  .secret,
  code {
    max-width: 100%;
    white-space: normal;
    overflow-wrap: anywhere;
  }
  .auth {
    width: auto;
    margin: 0.75rem;
    padding: 1.25rem;
  }
}

/* A page-header action is the single trigger for these forms; the disclosure keeps its
   open/close behaviour but not a second visible control. */
.command-form--header-led > summary {
  display: none;
}
.command-form__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
}

/* A deliberate server-only boundary, not a failure. */
.callout--boundary {
  border-left: 3px solid var(--accent, var(--success-text));
}
.callout--boundary .callout__hint {
  color: var(--muted, var(--text-secondary));
  font-size: 0.875rem;
  margin-bottom: 0;
}

/* Manual sync is a secondary escape hatch, not a primary action. */
.record-actions > summary {
  cursor: pointer;
  font-size: 0.875rem;
  color: var(--muted, var(--text-secondary));
  padding: 0.35rem 0;
}
.record-actions[open] > summary {
  margin-bottom: 0.5rem;
}

/* Dashboard tiles: each drills through to the list it counts. */
.metric-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 0.75rem;
  margin-bottom: 1.25rem;
}
.metric-card {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 1rem;
  background: var(--bg-elevated);
  border: 1px solid var(--line, var(--border));
  border-left: 3px solid var(--brand, var(--brand));
  text-decoration: none;
  color: inherit;
}
.metric-card:hover,
.metric-card:focus-visible {
  border-left-color: var(--success);
  background: var(--shade-subtle);
}
.metric-card strong {
  font-size: 1.5rem;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.metric-card span {
  font-size: 0.875rem;
  color: var(--muted, var(--text-secondary));
}
@media (max-width: 760px) {
  .metric-card strong {
    font-size: 1.25rem;
  }
}

/* ============================================================================
   Component layer. Later rules of equal specificity win, so this refines the
   layout above rather than replacing it.
   ========================================================================= */

/* --- Motion -------------------------------------------------------------- */
a,
button,
.button,
input,
select,
textarea,
summary,
.metric-card,
.card,
tbody tr {
  transition:
    background-color var(--motion) var(--ease),
    border-color var(--motion) var(--ease),
    color var(--motion) var(--ease),
    box-shadow var(--motion) var(--ease),
    transform var(--motion) var(--ease),
    opacity var(--motion) var(--ease);
}
button,
.button,
a,
summary {
  -webkit-tap-highlight-color: transparent;
}
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 1ms !important;
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
  }
}

/* --- Typography ---------------------------------------------------------- */
h1 {
  font-size: 32px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.02em;
}
h2 {
  font-size: 20px;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.01em;
}
h3 {
  font-size: 17px;
  font-weight: 600;
  line-height: 1.35;
}
h4 {
  font-size: 15px;
  font-weight: 600;
  line-height: 1.4;
}
body {
  color: var(--text-primary);
}
p {
  color: var(--text-secondary);
}
.pagehead h1 {
  color: var(--text-primary);
}
small,
.empty-note,
.device-action-label {
  font-size: 13px;
  color: var(--text-tertiary);
  font-weight: 400;
}
label > span,
caption,
th {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
td,
th {
  font-variant-numeric: tabular-nums;
}

/* --- Buttons ------------------------------------------------------------- */
.button,
button.button {
  padding: 11px 20px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  background: var(--bg-tertiary);
  color: var(--text-primary);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
}
.button:hover {
  background: var(--shade-medium);
  border-color: var(--border-strong);
}
.button:active {
  transform: translateY(0.5px);
  transition-duration: 60ms;
}
.button:disabled,
.button[disabled] {
  background: var(--bg-secondary);
  color: var(--text-tertiary);
  border-color: var(--border);
  cursor: not-allowed;
  opacity: 1;
}
.button--primary,
button.button--primary {
  background: var(--accent-fill);
  border-color: var(--accent-fill);
  color: var(--on-accent);
}
.button--primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  box-shadow: 0 2px 8px var(--accent-ring);
}
.button--danger,
button.button--danger {
  background: var(--critical-fill);
  border-color: var(--critical-fill);
  color: var(--on-critical);
}
.button--danger:hover {
  background: var(--critical-hover);
  border-color: var(--critical-hover);
  box-shadow: 0 2px 8px var(--critical-tint);
}
.button--quiet {
  padding: 6px 12px;
  font-size: 13px;
  background: transparent;
  border-color: transparent;
  color: var(--text-secondary);
}
.button--quiet:hover {
  background: var(--shade-subtle);
  border-color: var(--border);
}
.button--device {
  background: var(--bg-tertiary);
  border: 1px solid var(--border-strong);
  color: var(--text-primary);
  font-weight: 600;
}
.button--device:hover {
  background: var(--shade-medium);
}

/* --- Surfaces ------------------------------------------------------------ */
.metric-card,
.callout,
dialog {
  border-radius: var(--radius-lg);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
}
.metric-card {
  padding: var(--space-4);
  margin-bottom: var(--space-2);
  border-left: 1px solid var(--border);
}
.metric-card:hover,
.metric-card:focus-visible {
  border-color: var(--text-tertiary);
  box-shadow: var(--shadow-sm);
  background: var(--bg-elevated);
}
.metric-card strong {
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.metric-card span {
  color: var(--text-tertiary);
  font-size: 13px;
}
.callout {
  padding: var(--space-4);
  border-left: 3px solid var(--accent-fill);
}
.callout--boundary {
  border-left-color: var(--accent-fill);
  background: var(--bg-secondary);
}
dialog {
  padding: var(--space-7);
  box-shadow: var(--shadow-md);
}
dialog::backdrop {
  background: rgb(26 24 21 / 0.4);
}
table {
  background: var(--bg-elevated);
}
th {
  background: var(--bg-secondary);
}
th,
td {
  border-bottom: 1px solid var(--border);
  padding: var(--space-2) var(--space-3);
}
tbody tr:hover {
  background: var(--shade-subtle);
}

/* --- Inputs -------------------------------------------------------------- */
input,
select,
textarea {
  padding: 11px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
  color: var(--text-primary);
}
input:hover,
select:hover,
textarea:hover {
  border-color: var(--text-tertiary);
}
input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--accent-fill);
  box-shadow: 0 0 0 2px var(--accent-ring);
}
input:disabled,
select:disabled,
textarea:disabled {
  background: var(--bg-secondary);
  color: var(--text-tertiary);
  cursor: not-allowed;
}
:focus-visible {
  outline: 2px solid var(--accent-fill);
  outline-offset: 2px;
}

/* --- Badges -------------------------------------------------------------- */
.status {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  padding: 4px 8px;
  border-radius: var(--radius-sm);
  background: var(--bg-tertiary);
  color: var(--text-secondary);
  border: 0;
}
.status--success,
.status[data-tone='success'] {
  background: var(--success-tint);
  color: var(--success-text);
}
.status--warning,
.status[data-tone='warning'] {
  background: var(--warning-tint);
  color: var(--warning-text);
}
.status--critical,
.status[data-tone='critical'] {
  background: var(--critical-tint);
  color: var(--critical-text);
}

/* --- Sync indicator ------------------------------------------------------ */
.sync-state:empty {
  display: none;
}
.sync-state:not(:empty) {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: 13px;
  font-weight: 600;
  padding: 6px 12px;
  border-radius: var(--radius-sm);
  background: var(--success-tint);
  color: var(--success-text);
}
.sync-state:not(:empty)::before {
  content: '';
  width: 5px;
  height: 5px;
  border-radius: var(--radius-pill);
  background: currentColor;
  animation: sync-pulse 2s ease-in-out infinite;
}
.sync-state[data-attention='true'] {
  background: var(--warning-tint);
  color: var(--warning-text);
}
@keyframes sync-pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.35;
  }
}

/* ---------------------------------------------------------------------------
   Dashboard hierarchy. Requested as .stats-row/.stat-card/.section-title/
   .table-card/.table-row; those classes do not exist. The tiles render as
   .metric-cards > .metric-card, panels as section.panel > h2, and collections
   as .table-wrap > table, so the styling is applied there.
   ------------------------------------------------------------------------ */
.panel > h2 {
  font-size: 18px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.3px;
  margin: 32px 0 16px;
}
.panel:first-child > h2 {
  margin-top: 0;
}
.metric-cards {
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px;
  margin-bottom: 32px;
}
.metric-card {
  padding: 24px;
  border-radius: 14px;
  border: 1px solid var(--border);
  background: var(--bg-elevated);
  box-shadow: var(--shadow-sm);
  margin-bottom: 0;
}
.metric-card:hover,
.metric-card:focus-visible {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
  border-color: var(--border);
}
.metric-card span {
  order: -1;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 12px;
}
.metric-card strong {
  font-size: 36px;
  font-weight: 700;
  line-height: 1.05;
  color: var(--accent);
}
.table-wrap {
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--bg-elevated);
  box-shadow: var(--shadow-sm);
}
.table-wrap table {
  border-radius: inherit;
}
.table-wrap th:first-child,
.table-wrap td:first-child {
  padding-left: 20px;
}
.table-wrap th:last-child,
.table-wrap td:last-child {
  padding-right: 20px;
}
.table-wrap td {
  padding-block: 16px;
  font-size: 14px;
}
.table-wrap tbody tr:last-child td {
  border-bottom: 0;
}
.table-wrap tbody tr:hover {
  background: color-mix(in srgb, var(--accent) 2%, transparent);
}

/* ---------------------------------------------------------------------------
   Properties master/detail.
   ------------------------------------------------------------------------ */
.property-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--border);
}
.property-tab {
  border: 0;
  background: none;
  cursor: pointer;
  padding: 10px 16px;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-secondary);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.property-tab:hover {
  color: var(--text-primary);
}
.property-tab[aria-pressed='true'] {
  color: var(--accent);
  border-bottom-color: var(--accent);
}
.property-workspace {
  display: grid;
  /* One column by default: the list uses the full width until a row is chosen. The
     panel only claims space once there is something in it. */
  grid-template-columns: minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}
.property-row {
  cursor: pointer;
}
.property-row:hover {
  background: var(--brand-hover);
}
.property-row.is-selected {
  background: var(--brand-active);
}
.property-detail {
  position: relative;
  padding: 20px 60px 20px 20px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--bg-elevated);
  box-shadow: var(--shadow-sm);
  position: sticky;
  top: 16px;
}
.property-detail h3 {
  margin: 0 0 12px;
}
.property-detail h4 {
  margin: 24px 0 12px;
}
.property-facts {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 6px 16px;
  margin: 0;
  font-size: 14px;
}
.property-facts dt {
  color: var(--text-tertiary);
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  align-self: center;
}
.property-facts dd {
  margin: 0;
}
.property-form {
  display: grid;
  gap: 12px;
  margin-top: 16px;
}
.property-spaces {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 8px;
}
.property-spaces li {
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  font-size: 14px;
}
.property-spaces span {
  color: var(--text-tertiary);
  font-size: 13px;
}
@media (max-width: 899px) {
  .property-detail {
    position: static;
  }
}

/* ---------------------------------------------------------------------------
   Master/detail: side panel on desktop, bottom drawer below 768px.
   ------------------------------------------------------------------------ */
@media (min-width: 900px) {
  .property-workspace.has-detail {
    grid-template-columns: minmax(0, 1fr) minmax(340px, 38%);
  }
}
/* Hidden until selected, so it never sits empty beside the table. Below the drawer
   breakpoint it is a sheet and manages its own visibility. */
@media (min-width: 768px) {
  .property-detail {
    display: none;
  }
  .property-detail.is-open {
    display: block;
  }
}
.property-detail .detail-close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 32px;
  height: 32px;
  /* the mobile block sets button{min-height:48px}, which would otherwise win over height */
  min-height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--accent);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}
.property-detail .detail-close:hover {
  background: var(--brand-hover);
  color: var(--accent-hover);
}
.property-detail .detail-close:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.property-row:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.property-list .table-wrap {
  overflow-x: auto;
}

@media (max-width: 767px) {
  .property-workspace {
    display: block;
  }
  /* The panel becomes a sheet over the list rather than pushing it off-screen,
     so the row the user came from stays visible behind it. */
  .property-detail {
    position: fixed;
    inset: auto 0 0 0;
    z-index: 20;
    max-height: 82vh;
    overflow-y: auto;
    border-radius: 16px 16px 0 0;
    border: 1px solid var(--border);
    border-bottom: 0;
    box-shadow: var(--shadow-md);
    transform: translateY(101%);
    transition: transform var(--motion) var(--ease);
    padding-bottom: max(20px, env(safe-area-inset-bottom));
  }
  .property-detail.is-open {
    transform: translateY(0);
  }
  .property-detail__head {
    display: flex;
    position: sticky;
    top: 0;
    background: var(--bg-elevated);
    padding-top: 4px;
  }
  .property-detail:not(.is-open) [data-record-body] {
    display: none;
  }
  .property-form input,
  .property-form select {
    min-height: 44px;
    font-size: 16px; /* iOS zooms the page for anything smaller on focus */
  }
  .property-form .button,
  .property-detail .button {
    min-height: 44px;
  }
  .property-tab {
    min-height: 44px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .property-detail {
    transition: none;
  }
}

/* Helper text under a form field. */
.field-hint {
  display: block;
  margin-top: 4px;
  font-size: 13px;
  font-weight: 400;
  color: var(--text-tertiary);
  text-transform: none;
  letter-spacing: normal;
}

/* ---------------------------------------------------------------------------
   Command modal. A page-header action opens its form over the list rather than
   pushing the list down the page.
   ------------------------------------------------------------------------ */
.command-modal {
  width: min(640px, calc(100% - 2rem));
  /*
   * The generic dialog rule caps every dialog at 34rem, which quietly overrode the width
   * above and left these forms 510px wide on a 1440px screen. Record forms carry an
   * address block and two columns; they were built for the 640px asked for here.
   */
  max-width: min(640px, calc(100% - 2rem));
  max-height: 85vh;
  overflow-y: auto;
  padding: var(--space-7);
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--bg-elevated);
  color: var(--text-primary);
  box-shadow: var(--shadow-md);
}
.command-modal::backdrop {
  background: rgb(15 15 15 / 0.45);
}
.command-modal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
  position: sticky;
  top: 0;
  background: var(--bg-elevated);
}
.command-modal__head h3 {
  margin: 0;
}
.command-modal__head .button,
.command-modal .command-form__actions .button {
  min-height: 44px;
}
@media (max-width: 767px) {
  .command-modal {
    width: 100%;
    max-width: none;
    max-height: 92vh;
    margin: auto 0 0;
    border-radius: 16px 16px 0 0;
    padding-bottom: max(var(--space-7), env(safe-area-inset-bottom));
  }
  .command-modal input,
  .command-modal select {
    min-height: 44px;
    font-size: 16px;
  }
}

/* Immutable property location settings, shown for context in the edit form. */
.locked-group {
  display: grid;
  gap: 12px;
  padding: 12px;
  border: 1px dashed var(--border);
  border-radius: 10px;
  background: var(--bg-secondary);
}
.locked-group .field-hint {
  margin: 0;
}
.is-locked input:disabled {
  background: var(--bg-tertiary);
  color: var(--text-secondary);
  cursor: not-allowed;
}

/* Record search above the master list. */
.record-search {
  display: block;
  margin-bottom: 12px;
}
.record-search input {
  width: 100%;
  max-width: 22rem;
}

/* Toolbar above the master list: search on the left, the filter disclosure beside it. */
.record-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 12px;
}
.record-toolbar .record-search {
  flex: 1 1 16rem;
  margin-bottom: 0;
}
.record-filters {
  position: relative;
}
.record-filters > summary {
  list-style: none;
  cursor: pointer;
}
.record-filters > summary::-webkit-details-marker {
  display: none;
}
.record-filters__fields {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px;
  margin-top: 12px;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--bg-secondary);
}
.record-filters__fields label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text-secondary);
}
/* Counts above the list, and the narrowed-list count the filters write back. */
.record-metrics {
  margin: 0 0 12px;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-secondary);
}
.record-count {
  margin: 0 0 12px;
  font-size: 13px;
  color: var(--text-secondary);
}
/* Secondary value inside a table cell: a reference standing in for a missing name. */
.row-aside {
  color: var(--text-secondary);
  font-size: 13px;
}
/* Quick actions sit directly under the lease summary, above the expandable sections. */
.detail-actions__row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
}
.dialog-subject {
  margin: 0 0 8px;
  font-weight: 600;
  color: var(--text-primary);
}

/* Finance quick actions: the four ways to record money, always reachable. On a
   narrow screen they stay at the top of the page while the list scrolls under. */
.quick-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 8px;
  margin-bottom: 20px;
}
@media (max-width: 767px) {
  .quick-actions {
    position: sticky;
    top: 0;
    z-index: 5;
    padding: 12px 0;
    margin-bottom: 12px;
    background: var(--bg-primary);
  }
  .quick-actions .button {
    flex: 1 1 45%;
  }
}
/* A template's spaces, previewed on its row. */
.template-preview {
  gap: 6px 14px;
}
.template-preview span::before {
  content: '·';
  margin-right: 6px;
  opacity: 0.5;
}
.template-preview span:first-child::before {
  content: none;
  margin: 0;
}

/* The statements panel above the report tiles. */
.statement-panel {
  margin-bottom: 20px;
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--bg-secondary);
}
.statement-panel h3 {
  margin: 0 0 12px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.statement-panel .property-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px;
}

/* Report tiles below the transaction workspace. */
.report-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: 16px;
}
.report-tile {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--bg-secondary);
}
.report-tile h3 {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.report-tile__summary {
  margin: 0;
  font-size: 20px;
  font-weight: 600;
  color: var(--text-primary);
}
.report-tile__list {
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 14px;
  font-weight: 400;
}
.report-tile__list li {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 2px 0;
}
.report-tile .button {
  margin-top: auto;
}
/* The date pair in the filter panel reads as one range. */
.record-filters__fields input[type='date'] {
  min-width: 9rem;
}

/* Priority, shown as a coloured indicator rather than a word alone so a queue can
   be scanned. The word stays: colour is never the only carrier of the meaning. */
.priority-flag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
.priority-flag::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-secondary);
}
.priority-flag--urgent::before {
  background: var(--danger, #b3261e);
}
.priority-flag--high::before {
  background: #c2620f;
}
.priority-flag--normal::before {
  background: var(--accent);
}
.priority-flag--low::before {
  background: var(--text-secondary);
}
/* A request open longer than its priority usually takes. */
.ageing-flag {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  color: var(--danger, #b3261e);
  background: color-mix(in srgb, var(--danger, #b3261e) 12%, transparent);
}
/* A recurring charge in the lease panel: what it charges, when it charges next,
   and what can be done to it. */
.schedule-list li.schedule-row {
  display: grid;
  gap: 6px;
  padding: 12px 0;
}
.schedule-row__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--text-secondary);
}
.schedule-row__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* The reason a change carried, under the entry it belongs to. */
.audit-reason {
  flex-basis: 100%;
  font-style: italic;
  color: var(--text-secondary);
}

/* Workflow history inside the request panel. */
.timeline {
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}
.timeline__step {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  padding: 8px 0 8px 20px;
  position: relative;
  border-left: 2px solid var(--border);
  margin-left: 4px;
  font-size: 14px;
}
.timeline__step::before {
  content: '';
  position: absolute;
  left: -6px;
  top: 12px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--bg-primary);
  border: 2px solid var(--border);
}
.timeline__step.is-done::before {
  background: var(--accent);
  border-color: var(--accent);
}
.timeline__step span {
  color: var(--text-secondary);
}
/* Secondary forms inside a detail panel stay collapsed so the panel opens on the
   record itself rather than a wall of inputs. */
.panel-form {
  margin-top: 16px;
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px;
  background: var(--bg-secondary);
}
.panel-form > summary {
  cursor: pointer;
  font-weight: 600;
  min-height: 44px;
  display: flex;
  align-items: center;
}
.panel-form[open] > summary {
  margin-bottom: 8px;
}
.panel-form textarea {
  width: 100%;
  min-height: 6rem;
}

.dialog-description p {
  margin: 0 0 12px;
}
.dialog-description p:last-child {
  margin-bottom: 0;
}

/* Occupancy state on each space in the property panel. */
.property-spaces li {
  display: grid;
  gap: 4px;
}
.space-occupant {
  font-size: 13px;
  color: var(--text-secondary);
}
.space-occupant--vacant {
  color: var(--text-tertiary);
}
.property-spaces .button {
  justify-self: start;
  min-height: 44px;
}
.checkbox-field {
  display: flex;
  align-items: center;
  gap: 8px;
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
}
.checkbox-field input {
  min-height: auto;
  width: auto;
}

/* Disabled must win over every variant fill, so it is declared after them all.
   A destructive confirm that stays red while disabled reads as clickable. */
.button:disabled,
.button[disabled],
.button--primary:disabled,
.button--danger:disabled,
.button--device:disabled {
  background: var(--bg-secondary);
  color: var(--text-tertiary);
  border-color: var(--border);
  box-shadow: none;
  cursor: not-allowed;
  opacity: 1;
}

/* ---------------------------------------------------------------------------
   Detail panel: summary block, then one card per action.
   ------------------------------------------------------------------------ */
.property-detail > * + * {
  margin-top: 24px;
}
.detail-summary {
  display: grid;
  gap: 12px;
  justify-items: start;
  text-align: left;
  padding: 16px;
  border-radius: 10px;
  background: color-mix(in srgb, var(--accent) 4%, transparent);
  border-bottom: 1px solid var(--border);
}
.detail-name {
  margin: 0;
  font-size: 18px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--text-primary);
}
.detail-summary .detail-line {
  margin: 0;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.5;
  color: var(--text-secondary);
}
.detail-summary .detail-state {
  margin: 0;
}
.detail-summary .detail-reference {
  margin: 0;
  font-size: 11px;
  line-height: 1.4;
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}
.detail-summary .status--active {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
}

.detail-card {
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg-elevated);
}
.detail-card > h4,
.detail-card > summary h4 {
  margin: 0;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.detail-card > summary {
  cursor: pointer;
  min-height: 44px;
  display: flex;
  align-items: center;
  list-style: none;
}
.detail-card > summary::-webkit-details-marker {
  display: none;
}
.detail-card > summary::after {
  content: '+';
  margin-left: auto;
  color: var(--text-tertiary);
  font-size: 16px;
}
.detail-card[open] > summary::after {
  content: '–';
}
.detail-card .property-form {
  display: grid;
  gap: 12px;
  margin-top: 16px;
}
.detail-card label {
  display: grid;
  gap: 6px;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: normal;
  text-transform: none;
  color: var(--text-secondary);
}
.detail-card input,
.detail-card textarea,
.detail-card select {
  font-size: 14px;
  font-weight: 400;
}
.detail-card .command-form__actions {
  margin-top: 4px;
}

@media (max-width: 767px) {
  /* Below the drawer breakpoint the control has to meet the 44px touch target the rest
     of the app holds to, so it grows rather than staying at the 32px desktop size. */
  .property-detail .detail-close {
    width: 44px;
    height: 44px;
    min-height: 44px;
    top: 8px;
    right: 8px;
  }
  .property-detail {
    padding-right: 20px;
  }
  .property-detail .detail-summary {
    padding-right: 56px;
  }
}

/* Row selection for bulk actions. */
.row-select {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  margin: -12px -8px;
  cursor: pointer;
}
.row-select input {
  width: 18px;
  height: 18px;
  min-height: 18px;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}
.table-wrap th:first-child,
.table-wrap td:first-child {
  width: 1%;
  white-space: nowrap;
}

/* Sub-headings inside an expanded lease section. */
.detail-subhead {
  margin: 16px 0 8px;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.detail-card > .property-facts,
.detail-card > ul,
.detail-card > .empty-note {
  margin-top: 12px;
}

/* The vendor directory under the maintenance queue. */
.workspace-panel {
  margin-top: var(--space-4, 1rem);
}
.vendor-rating {
  font-weight: 600;
  color: var(--ink, inherit);
  white-space: nowrap;
}

/* The occupancy trend line on the dashboard. One line, no charting library. */
.spark {
  width: 100%;
  height: auto;
  display: block;
  margin: var(--space-3, 0.75rem) 0;
}
.spark__line {
  fill: none;
  stroke: var(--accent, currentColor);
  stroke-width: 2;
  stroke-linejoin: round;
}
.spark__dot {
  fill: var(--accent, currentColor);
}
.spark__grid {
  stroke: var(--rule, rgba(0, 0, 0, 0.12));
  stroke-width: 1;
}
.spark__axis {
  fill: var(--ink-muted, #666);
  font-size: 10px;
}

/* The one-line notice above the dashboard when late fees have never been configured. */
.banner {
  border: 1px solid var(--rule, rgba(0, 0, 0, 0.14));
  border-left-width: 3px;
  border-radius: var(--radius-2, 6px);
  padding: var(--space-3, 0.75rem) var(--space-4, 1rem);
  margin-bottom: var(--space-4, 1rem);
  background: var(--surface-2, rgba(0, 0, 0, 0.02));
}
.banner--notice {
  border-left-color: var(--accent, currentColor);
}
.banner p {
  margin: 0;
}
.banner__actions {
  display: flex;
  gap: var(--space-3, 0.75rem);
  align-items: center;
  margin-top: var(--space-2, 0.5rem);
}

/* Touch input, at any width. Keyed to the pointer rather than the viewport because a
   tablet held in the hand is a touch device at 1024px, and a desktop window dragged
   narrow is still a mouse. This is the same reasoning as the `pointer: fine` block that
   shrinks compact buttons, read from the other side. */
@media (pointer: coarse) {
  /* iOS Safari zooms the whole page when a focused field is under 16px, which throws the
     layout sideways and leaves the user pinching back out. The 14px fields elsewhere are
     a deliberate density choice for a mouse; on touch, legibility of a field being typed
     into wins. */
  input,
  select,
  textarea,
  .property-form input,
  .property-form select,
  .property-form textarea,
  .finance-plan input,
  .finance-plan select {
    font-size: 16px;
  }
  /* The quiet variant trims its padding, which left it two pixels under the target. */
  .button.button--quiet {
    min-height: 44px;
  }
}

/* Arrears aging.

   Bars are relative to the largest bracket rather than to the total, so a portfolio
   whose arrears sit almost entirely in one bracket still shows the others. Every bar
   carries its figure beside it: a bar nobody can read a number off is decoration. */
.arrears-block {
  margin-bottom: 1.25rem;
}
.arrears-brackets {
  list-style: none;
  margin: 0.75rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.5rem;
}
.arrears-bracket {
  display: grid;
  grid-template-columns: 7.5rem 1fr auto;
  align-items: center;
  gap: 0.75rem;
}
.arrears-bracket__label {
  font-size: 0.875rem;
  color: var(--muted, var(--text-secondary));
}
.arrears-bracket__track {
  background: var(--shade-subtle);
  height: 0.75rem;
  border: 1px solid var(--line, var(--border));
}
.arrears-bracket__fill {
  display: block;
  height: 100%;
  background: var(--brand);
}
/* The oldest money is the least likely to arrive, and is the reason to open this
   screen. Colour is not the only thing marking it: it is also the bottom row and
   labelled in words. */
.arrears-bracket--oldest .arrears-bracket__fill {
  background: var(--danger, var(--error));
}
.arrears-bracket--oldest .arrears-bracket__label,
.arrears-bracket--oldest .arrears-bracket__value {
  font-weight: 600;
}
.arrears-bracket__value {
  font-variant-numeric: tabular-nums;
}
.arrears-tenants {
  display: grid;
  gap: 0.5rem;
}
/* Money owed or lost, marked so a scanned column reads without arithmetic. The figure
   itself already carries a minus sign, so this adds emphasis rather than meaning. */
.col-money--negative {
  color: var(--danger, var(--error));
}
.inline-field {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.875rem;
}
@media (max-width: 640px) {
  .arrears-bracket {
    grid-template-columns: 1fr auto;
  }
  .arrears-bracket__track {
    grid-column: 1 / -1;
  }
}

/* The analytics tab strip.

   The only tabs in this application. The selected tab is marked by weight and an
   underline as well as by colour, so it is still legible to somebody who cannot tell
   the two colours apart or is looking at a washed-out screen in daylight. */
.analytics [role='tablist'] {
  border-bottom: 1px solid var(--line, var(--border));
  gap: 0;
  margin-bottom: 0;
}
.analytics-tab {
  border: 0;
  border-bottom: 3px solid transparent;
  border-radius: 0;
  background: none;
  font-weight: 500;
}
.analytics-tab[aria-selected='true'] {
  border-bottom-color: var(--brand);
  font-weight: 700;
  color: var(--text-primary, inherit);
}
.analytics-tab:hover {
  background: var(--shade-subtle);
}
.analytics-panel {
  border-top: 0;
}
/* A hidden panel is hidden from everything, not just from sight: left visible to a
   screen reader, four tabs read as four screens stacked on one page. */
.analytics-panel[hidden] {
  display: none;
}
/* Narrow screens scroll the strip sideways rather than wrapping it into two rows that
   push the figures below the fold. */
@media (max-width: 640px) {
  .analytics [role='tablist'] {
    flex-wrap: nowrap;
    overflow-x: auto;
  }
  .analytics-tab {
    white-space: nowrap;
  }
}

/* Sign-in with a provider. The divider says the two ways in are alternatives rather
   than steps, which a bare stack of buttons does not.
 *
 * A secondary button rather than a link: it does the same kind of thing as Sign in, so
 * it should look like it can be pressed. It is deliberately not accent-filled - there is
 * one primary action on this screen and two would make neither one primary. */
.auth [data-google] {
  display: block;
  width: 100%;
  text-align: center;
  text-decoration: none;
  background: var(--bg-secondary);
  color: var(--text-primary);
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  padding: 0.75rem 1rem;
  font-weight: 600;
  min-height: 2.75rem;
}
.auth [data-google]:hover {
  background: var(--bg-tertiary);
  border-color: var(--accent);
  color: var(--accent);
  text-decoration: none;
}
.auth__divider {
  text-align: center;
  color: var(--muted, var(--text-secondary));
  font-size: 0.875rem;
  margin: 1rem 0;
}

/* The account menu.

   The name in the top right used to be a bare link to Settings, and Sign out was a
   full-width button at the bottom of the sidebar - which is not where anybody looks for
   it. Both now live under the name, which is where every other application puts them. */
.account-menu {
  position: relative;
}
.account-trigger {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  background: none;
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 0.4rem 0.6rem;
  color: inherit;
  font: inherit;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
}
.account-trigger:hover {
  background: var(--bg-secondary);
  border-color: var(--border);
}
/* Drawn rather than shipped as an icon file: one glyph is not worth a request, and a
   CSS triangle rotates with the open state for free. */
.account-chevron {
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  transition: transform 120ms ease;
}
.account-trigger[aria-expanded='true'] .account-chevron {
  transform: rotate(180deg);
}
.account-trigger[aria-expanded='true'] {
  background: var(--bg-secondary);
  border-color: var(--border);
}
.account-dropdown {
  position: absolute;
  top: calc(100% + 0.35rem);
  right: 0;
  min-width: 12rem;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgb(0 0 0 / 0.16);
  padding: 0.35rem;
  z-index: 60;
}
/* Toggled with the hidden attribute rather than a class, so a closed menu is out of the
   accessibility tree and not just out of sight. */
.account-dropdown[hidden] {
  display: none;
}
/* Whose account this is. On a shared machine the name in the bar is easy to miss, and
   signing the wrong person out is a nuisance to undo. */
.account-dropdown__who {
  margin: 0 0 0.35rem;
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.8125rem;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dropdown-item {
  display: block;
  width: 100%;
  padding: 0.6rem 0.75rem;
  border: 0;
  border-radius: 4px;
  background: none;
  color: var(--text-primary);
  font: inherit;
  font-size: 0.875rem;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}
.dropdown-item:hover,
.dropdown-item:focus-visible {
  background: var(--bg-secondary);
  color: var(--accent);
}
/* Signing out ends the session; it is separated and coloured so it is not chosen by
   accident on the way to Settings. */
.dropdown-item--sign-out {
  margin-top: 0.35rem;
  border-top: 1px solid var(--border);
  border-radius: 0 0 4px 4px;
  color: var(--critical);
}
.dropdown-item--sign-out:hover,
.dropdown-item--sign-out:focus-visible {
  background: var(--critical-fill);
  color: var(--on-critical);
}
@media (max-width: 760px) {
  .account-name {
    max-width: 8rem;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

/* Settings values that are shown but cannot be changed here, with the reason beside
   them. A greyed-out field with no explanation reads as broken. */
.settings-fixed-list {
  margin: 1.25rem 0 0;
  display: grid;
  gap: 0.75rem;
}
.settings-fixed dt {
  font-weight: 600;
  font-size: 0.875rem;
}
.settings-fixed dd {
  margin: 0.15rem 0 0;
  font-variant-numeric: tabular-nums;
}
.settings-fixed dd .row-aside {
  display: block;
  font-variant-numeric: normal;
}
/* The notification grid. The label wraps the box so the whole cell is a target, which
   matters most on a phone. */
.checkbox-cell {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 44px;
  cursor: pointer;
}

/* Messages: a list beside a thread.

   The shape every messaging screen has, because it is the one that lets somebody scan
   for the conversation they mean and then stay inside it. Below the breakpoint the two
   panes stack, list first. */
.messages {
  display: grid;
  grid-template-columns: minmax(14rem, 20rem) 1fr;
  gap: 0;
  padding: 0;
  overflow: hidden;
}
.messages__list {
  border-right: 1px solid var(--border);
  overflow-y: auto;
  max-height: 34rem;
  padding: 0.5rem;
}
.messages__thread {
  display: flex;
  flex-direction: column;
  min-height: 20rem;
  max-height: 34rem;
  padding: 1rem;
}
.messages__head h3 {
  margin: 0 0 0.75rem;
}
.messages__log {
  list-style: none;
  margin: 0;
  padding: 0 0.25rem 0.75rem 0;
  overflow-y: auto;
  flex: 1;
  display: grid;
  gap: 0.75rem;
  align-content: start;
}
.message__meta {
  margin: 0 0 0.15rem;
  font-size: 0.8125rem;
  color: var(--text-secondary);
}
.message__body {
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  padding: 0.6rem 0.75rem;
  border-radius: 8px;
  background: var(--bg-secondary);
}
/* A tenant's message is tinted so the two sides of a conversation are told apart at a
   glance. The author's name is on every message as well, so the colour is a convenience
   and never the only thing carrying it. */
.message--tenant .message__body {
  background: var(--brand-active);
}
.messages__compose textarea {
  width: 100%;
  resize: vertical;
}
.conversation-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.25rem;
}
.conversation-item {
  display: grid;
  gap: 0.15rem;
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  border-radius: 6px;
  padding: 0.6rem 0.7rem;
  cursor: pointer;
  color: inherit;
  font: inherit;
  position: relative;
}
.conversation-item:hover {
  background: var(--bg-secondary);
}
.conversation-item[aria-current='true'] {
  background: var(--brand-active);
  box-shadow: inset 3px 0 0 var(--accent);
}
.conversation-item__subject {
  font-weight: 600;
}
.conversation-item__meta {
  font-size: 0.8125rem;
  color: var(--text-secondary);
}
.conversation-item__unread {
  position: absolute;
  top: 0.6rem;
  right: 0.7rem;
  background: var(--accent-fill);
  color: var(--on-accent);
  border-radius: 999px;
  min-width: 1.25rem;
  padding: 0 0.35rem;
  font-size: 0.75rem;
  font-weight: 700;
  text-align: center;
}
@media (max-width: 860px) {
  .messages {
    grid-template-columns: 1fr;
  }
  .messages__list {
    border-right: 0;
    border-bottom: 1px solid var(--border);
    max-height: 14rem;
  }
}

/* The tenant portal.

   One screen, no sidebar: a tenant has one tenancy to look at, not a workspace to
   navigate. It borrows the shell, the panels, the metric cards and the message list from
   the landlord side rather than inventing a second set, so the two stay in step when
   either is changed. */
.shell--portal {
  grid-template-columns: 1fr;
}
.topbar--portal {
  justify-content: space-between;
  gap: 1rem;
}
.portal-brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-width: 0;
}
.portal-logo {
  flex: none;
}
.portal-wordmark {
  font-weight: 600;
  font-size: 0.9375rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* A link styled as a button is still a link, so it arrives underlined. These are
   actions, and an underline on a filled button reads as a mistake. */
.pagehead .actions a.button {
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.portal-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.5rem;
}
.portal-item {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-elevated);
}
.portal-item > details {
  width: 100%;
}
.portal-item summary {
  display: grid;
  gap: 0.15rem;
  cursor: pointer;
}
.portal-item__title {
  display: block;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.portal-item__meta {
  display: block;
  font-size: 0.875rem;
  color: var(--text-secondary);
}
.portal-item__aside {
  display: block;
  font-size: 0.8125rem;
  color: var(--text-secondary);
}
.portal-item__side {
  flex: none;
  text-align: right;
}
/* Money that is late. Marked by an accent edge and by the words "overdue since", never
   by colour alone. */
.portal-item--late {
  border-left: 3px solid var(--critical);
}
.portal-flag--late {
  display: block;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--critical);
}
.portal-detail {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: 0.75rem;
  margin: 0.85rem 0 0;
  padding-top: 0.85rem;
  border-top: 1px solid var(--border);
}
.portal-detail dt {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
}
.portal-detail dd {
  margin: 0.15rem 0 0;
  font-weight: 500;
}
/* A card that reports something wrong takes the critical edge the rest of the app uses
   for the same thing. */
.metric-card--alert {
  border-left-color: var(--critical);
}
.portal-form {
  max-width: 32rem;
}
/* The label above its field rather than beside it. A tenant fills this in on a phone as
   often as not, and a label sharing a line with its input leaves the input too narrow to
   read what has been typed into it. */
.portal-form label {
  display: grid;
  gap: 0.3rem;
  font-weight: 500;
}
.portal-form input,
.portal-form select {
  width: 100%;
  min-height: 44px;
}
.portal-thread__subject {
  margin: 0 0 0.75rem;
  font-weight: 600;
}
@media (max-width: 640px) {
  .portal-item {
    flex-direction: column;
    align-items: stretch;
    gap: 0.35rem;
  }
  .portal-item__side {
    text-align: left;
  }
  .portal-wordmark {
    display: none;
  }
}

/* A payment the tenant has reported and nobody has confirmed.

   Deliberately not styled as good news. It sits under the charge it is against, and the
   charge above it still shows the full amount owed, because reporting a payment is a
   message to the landlord rather than a settlement. */
.portal-pending {
  display: block;
  margin-top: 0.4rem;
  padding-left: 0.6rem;
  border-left: 2px solid var(--warning);
  font-size: 0.8125rem;
  color: var(--text-secondary);
}
.portal-badge {
  display: inline-block;
  margin-top: 0.3rem;
  padding: 0.1rem 0.45rem;
  border: 1px solid var(--warning);
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--warning-text, var(--text-primary));
  white-space: nowrap;
}
.portal-badge--done {
  border-color: var(--success);
  color: var(--success-text, var(--text-primary));
}

/* Owing nothing is good news. The accent this application uses on a metric value is the
   same burgundy it uses for money that is late, so the settled state takes the ordinary
   text colour instead of shouting in the colour of a warning. */
.metric-card--clear strong {
  color: var(--text-primary);
}

/* A payment the landlord says never arrived. Not the same as pending: pending is waiting,
   this is answered and answered badly, and a tenant needs to know which they are looking
   at without reading closely. */
.portal-badge--failed {
  border-color: var(--critical);
  color: var(--critical);
}

/* ============================================================================
   The landing page.

   The only screen in this application a stranger sees, so it stands on its own
   rather than inside the signed-in shell. Everything scales from 320px up on a
   single column, widening into two where there is room for it.
   ============================================================================ */
.landing {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--bg-primary);
}
.landing-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem clamp(1rem, 4vw, 3rem);
  border-bottom: 1px solid var(--border);
  background: var(--bg-elevated);
  position: sticky;
  top: 0;
  z-index: 20;
}
.landing-brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-weight: 700;
  min-width: 0;
}
.landing-brand span {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.landing-nav {
  display: flex;
  gap: 0.5rem;
  flex: none;
}
.landing-nav .button {
  text-decoration: none;
  display: inline-flex;
  align-items: center;
}
.landing-main {
  flex: 1;
  width: 100%;
  max-width: 72rem;
  margin: 0 auto;
  padding: 0 clamp(1rem, 4vw, 3rem);
}
.hero {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: center;
  padding: clamp(2.5rem, 7vw, 5rem) 0;
}
@media (min-width: 900px) {
  .hero {
    grid-template-columns: 1.1fr 1fr;
  }
}
.hero h1 {
  font-size: clamp(1.9rem, 5vw, 3rem);
  line-height: 1.1;
  margin: 0 0 1rem;
}
.hero__lead {
  font-size: clamp(1rem, 2.2vw, 1.2rem);
  color: var(--text-secondary);
  max-width: 34rem;
  margin: 0 0 1.5rem;
}
.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 0 0 0.75rem;
}
.hero__actions .button {
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.button--large {
  padding: 0.85rem 1.6rem;
  font-size: 1rem;
  min-height: 3rem;
}
.hero__note {
  margin: 0;
  font-size: 0.875rem;
  color: var(--text-secondary);
}
.hero__art svg {
  width: 100%;
  height: auto;
  display: block;
}
.art-building {
  fill: var(--bg-tertiary);
  stroke: var(--border-strong);
}
.art-building--mid {
  fill: var(--bg-secondary);
}
.art-window {
  fill: var(--accent);
  opacity: 0.28;
}
.art-line {
  fill: none;
  stroke: var(--accent);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.art-dot {
  fill: var(--accent);
}
.landing-section {
  padding: clamp(2rem, 5vw, 3.5rem) 0;
  border-top: 1px solid var(--border);
}
.landing-section > h2 {
  font-size: clamp(1.4rem, 3vw, 2rem);
  margin: 0 0 1.5rem;
}
/* The tinted bands need to reach the window edge while their content stays in the
   column, which is what the negative margin plus matching padding does. */
.landing-section--tint {
  background: var(--bg-secondary);
  margin-inline: calc(clamp(1rem, 4vw, 3rem) * -1);
  padding-inline: clamp(1rem, 4vw, 3rem);
}
.feature-grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}
.feature {
  padding: 1.5rem;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-top: 3px solid var(--accent);
  border-radius: 12px;
}
.feature__icon {
  font-size: 2rem;
  margin: 0 0 0.5rem;
  line-height: 1;
}
.feature h3 {
  margin: 0 0 0.4rem;
  font-size: 1.1rem;
}
.feature p {
  margin: 0;
  color: var(--text-secondary);
}
.reason-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.85rem;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
}
.reason-list li {
  padding-left: 1.5rem;
  position: relative;
  color: var(--text-secondary);
}
.reason-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.45em;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--accent);
}
.reason-list strong {
  color: var(--text-primary);
}
.step-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  counter-reset: step;
}
.step {
  display: flex;
  gap: 0.85rem;
  align-items: flex-start;
}
.step__number {
  flex: none;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background: var(--accent-fill);
  color: var(--on-accent);
  display: grid;
  place-items: center;
  font-weight: 700;
}
.step h3 {
  margin: 0 0 0.25rem;
  font-size: 1rem;
}
.step p {
  margin: 0;
  color: var(--text-secondary);
}
.pricing__headline {
  font-size: clamp(1.3rem, 3vw, 1.8rem);
  font-weight: 700;
  margin: 0 0 0.75rem;
  color: var(--accent);
}
.pricing p {
  max-width: 44rem;
}
.landing-cta {
  text-align: center;
}
.landing-cta .button {
  text-decoration: none;
  display: inline-flex;
  align-items: center;
}
.landing-footer {
  border-top: 1px solid var(--border);
  padding: 1.5rem clamp(1rem, 4vw, 3rem);
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  justify-content: space-between;
  align-items: center;
  color: var(--text-secondary);
  font-size: 0.875rem;
}
.landing-footer nav {
  display: flex;
  gap: 1.25rem;
}
.landing-footer a {
  color: var(--text-secondary);
}

/* Signup and onboarding. */
.auth-lead {
  margin: -0.4rem 0 1.25rem;
  color: var(--text-secondary);
  font-size: 0.9375rem;
}
.auth-card--wide {
  max-width: 32rem;
}
/* A validation message under the field it belongs to, so nobody hunts for which one is
   wrong. Empty by default and takes no space until it has something to say. */
.field-error:empty {
  display: none;
}
.field-error {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--critical);
}
.auth-card input[aria-invalid='true'] {
  border-color: var(--critical);
}
.checkbox-row {
  display: flex !important;
  align-items: flex-start;
  gap: 0.6rem;
  font-weight: 400;
  font-size: 0.875rem;
  /* Form labels are uppercased elsewhere in this application, which turns a sentence
     with two links in it into shouting. This one is prose and reads as prose. */
  text-transform: none;
  letter-spacing: normal;
}
.checkbox-row a {
  color: var(--accent);
}
.checkbox-row input {
  width: auto !important;
  min-height: auto !important;
  margin-top: 0.15rem;
  flex: none;
}
.link-button {
  background: none;
  border: 0;
  padding: 0;
  color: var(--accent);
  font: inherit;
  font-weight: 500;
  cursor: pointer;
  text-decoration: underline;
}
.onboard-steps {
  list-style: none;
  display: flex;
  gap: 0.5rem;
  margin: 0 0 1.25rem;
  padding: 0;
  font-size: 0.8125rem;
  color: var(--text-secondary);
}
.onboard-step {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  flex: 1;
  min-width: 0;
}
.onboard-step span {
  flex: none;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  display: grid;
  place-items: center;
  font-weight: 600;
}
.onboard-step--current {
  color: var(--text-primary);
  font-weight: 600;
}
.onboard-step--current span {
  background: var(--accent-fill);
  border-color: var(--accent-fill);
  color: var(--on-accent);
}
.onboard-step--done span {
  background: var(--success);
  border-color: var(--success);
  color: var(--on-accent);
}
.onboard-exit {
  margin: 1.25rem 0 0;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
  text-align: center;
  font-size: 0.8125rem;
}
@media (max-width: 520px) {
  /* The step labels go on narrow screens; the numbered circles still show progress. */
  .onboard-step {
    flex: none;
  }
  .onboard-step:not(.onboard-step--current) {
    font-size: 0;
  }
}

/* ============================================================================
   The portfolio dashboard: which property, what is owed, who is in it.
   ============================================================================ */
.portfolio-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
  margin-bottom: 1rem;
}
.portfolio-controls select {
  min-height: 44px;
}
/* The search grows into whatever is left, so on a wide screen it is a search box and on
   a narrow one it takes its own line rather than squeezing the two selects. */
.portfolio-search {
  flex: 1 1 14rem;
}
.portfolio-search input {
  width: 100%;
  min-height: 44px;
}
/* A figure needs to say which property it belongs to. A portfolio total with no address
   attached tells somebody there is a problem and not where it is. */
.metric-card__detail {
  font-size: 0.8125rem;
  color: var(--text-secondary);
  line-height: 1.35;
}
.property-cards {
  display: grid;
  gap: 0.75rem;
}
.property-card {
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--bg-elevated);
  padding: 0.25rem 1rem;
}
.property-card > summary {
  display: grid;
  gap: 0.2rem;
  padding: 0.85rem 0;
  cursor: pointer;
}
.property-card__name {
  font-weight: 700;
  font-size: 1.05rem;
}
.property-card__meta {
  font-size: 0.875rem;
  color: var(--text-secondary);
}
.property-card__figures {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  font-size: 0.875rem;
  color: var(--text-secondary);
  margin-top: 0.15rem;
}
.property-card__owed {
  color: var(--critical);
  font-weight: 600;
}
.property-card__clear {
  color: var(--success-text, var(--text-secondary));
}
.tenancy-list {
  list-style: none;
  margin: 0 0 0.85rem;
  padding: 0.85rem 0 0;
  border-top: 1px solid var(--border);
  display: grid;
  gap: 0.5rem;
}
.tenancy {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 8px;
}
/* An overdue tenancy takes an edge as well as a badge, so it is findable by scanning
   rather than only by reading each row. */
.tenancy--overdue {
  border-left: 3px solid var(--critical);
}
.tenancy__meta {
  display: block;
  font-size: 0.8125rem;
  color: var(--text-secondary);
}
.tenancy__side {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex: none;
  flex-wrap: wrap;
  justify-content: flex-end;
}
@media (max-width: 700px) {
  .tenancy {
    flex-direction: column;
    align-items: stretch;
  }
  .tenancy__side {
    justify-content: flex-start;
  }
  .portfolio-controls {
    flex-direction: column;
    align-items: stretch;
  }
  .portfolio-controls .inline-field {
    display: flex;
  }
  .portfolio-controls select {
    width: 100%;
  }
}

/* A metric card that has working behind it.

   Pressable, and looks it: the same card as its static neighbours plus an affordance,
   rather than a second visual language for the same thing. */
.metric-card--opens {
  cursor: pointer;
  text-align: left;
  font: inherit;
  width: 100%;
}
.metric-card--opens:hover {
  border-color: var(--accent);
}
.metric-card--opens:focus-visible {
  outline: 2px solid var(--accent-ring, var(--accent));
  outline-offset: 2px;
}
.metric-card__more {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--accent);
}
.metric-card--opens[aria-expanded='true'] .metric-card__more {
  color: var(--text-secondary);
}
/* A tenant's name is a way to reach them, so it reads and behaves as a link rather than
   as text that happens to respond to a click. */
.tenancy__name {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-weight: 700;
  color: var(--accent);
  cursor: pointer;
  text-align: left;
}
.tenancy__name:hover,
.tenancy__name:focus-visible {
  text-decoration: underline;
}
.tenancy__phone {
  margin-left: 0.6rem;
  font-size: 0.875rem;
  color: var(--text-secondary);
  white-space: nowrap;
}
.tenancy__and {
  margin: 0 0.35rem;
  color: var(--text-secondary);
  font-size: 0.875rem;
}
/* A lease nobody is on. Stated plainly rather than dressed as a tenant called
   "No tenant recorded". */
.tenancy__unassigned {
  color: var(--text-secondary);
  font-style: italic;
  font-weight: 500;
}
/* The property selector and its neighbours carry the same weight as the controls
   elsewhere in the application: a bordered field on the elevated surface, with the accent
   on focus. They were browser default and looked it. */
.portfolio-controls select,
.portfolio-controls input[type='search'] {
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  padding: 0.5rem 0.75rem;
  font: inherit;
  color: var(--text-primary);
}
.portfolio-controls select:focus-visible,
.portfolio-controls input[type='search']:focus-visible {
  outline: 2px solid var(--accent-ring, var(--accent));
  outline-offset: 1px;
  border-color: var(--accent);
}
/* The property selector is the one that changes what the whole screen is about, so it
   is the one that looks like a decision. */
.portfolio-controls [data-property-select] {
  border-color: var(--accent);
  border-left-width: 3px;
  font-weight: 600;
  min-width: 12rem;
}
/* The occupancy line, folded away until asked for. */
.trend > summary {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  cursor: pointer;
}
.trend > summary h3 {
  display: inline;
  margin: 0;
}
.trend__now {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
}

/* Whether a workspace's mail actually works.

   Three states and no ambiguity: never set up, set up and proved, set up and failing.
   The middle one is the only one that sends, so the other two say plainly where mail is
   going instead. */
.mail-state {
  margin: 0 0 1rem;
  padding: 0.75rem 1rem;
  border-radius: 8px;
  border-left: 3px solid var(--border-strong);
  background: var(--bg-secondary);
  font-size: 0.9375rem;
}
.mail-state--ok {
  border-left-color: var(--success);
}
.mail-state--bad {
  border-left-color: var(--critical);
}
.mail-state--none {
  border-left-color: var(--warning);
}

/* Address autocomplete. The list is positioned over the fields below it rather than
   pushing them down the page - a form that reflows under the finger on every keystroke
   is unusable on a phone. */
.address-complete {
  position: relative;
  display: grid;
  gap: 0.3rem;
}
.address-complete__list {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 20;
  margin: 0.15rem 0 0;
  padding: 0.25rem;
  list-style: none;
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgb(0 0 0 / 0.14);
  /* Six suggestions at most, and a scroll rather than a list running off a short
     screen. */
  max-height: 17rem;
  overflow-y: auto;
}
.address-complete__option {
  display: grid;
  gap: 0.1rem;
  padding: 0.5rem 0.6rem;
  border-radius: 6px;
  cursor: pointer;
  /* A finger-sized target. The keyboard user and the phone user get the same list. */
  min-height: 44px;
  align-content: center;
}
.address-complete__option.is-active,
.address-complete__option:hover {
  background: var(--bg-secondary);
}
.address-complete__primary {
  font-weight: 500;
  color: var(--text-primary);
}
.address-complete__secondary {
  font-size: 0.8125rem;
  color: var(--text-secondary);
}
.address-complete__status:empty {
  display: none;
}
.address-complete__status {
  margin: 0;
  font-size: 0.8125rem;
  font-weight: 400;
  color: var(--text-secondary);
}
/* Province and postal code share a line on anything wider than a phone: they are short
   fields, and a column of half-empty inputs makes a three-field form look like six. */
.property-form__pair {
  display: grid;
  gap: 0.75rem;
}
@media (min-width: 30rem) {
  .property-form__pair {
    grid-template-columns: 1fr 1fr;
  }
}

/* A record's own menu, in its header. A <details> so it opens by click and by Enter and
   closes on Escape without any script behind it. */
.detail-summary__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
}
.record-menu {
  position: relative;
  flex: none;
}
.record-menu__button {
  list-style: none;
  cursor: pointer;
  padding: 0.4rem 0.7rem;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: var(--bg-elevated);
  font-weight: 500;
}
.record-menu__button::-webkit-details-marker {
  display: none;
}
.record-menu__items {
  position: absolute;
  right: 0;
  top: calc(100% + 0.25rem);
  z-index: 30;
  display: grid;
  min-width: 12rem;
  padding: 0.25rem;
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgb(0 0 0 / 0.14);
}
.record-menu__item {
  text-align: left;
  padding: 0.55rem 0.6rem;
  min-height: 44px;
  border: 0;
  border-radius: 6px;
  background: none;
  cursor: pointer;
  font: inherit;
  color: var(--text-primary);
}
.record-menu__item:hover,
.record-menu__item:focus-visible {
  background: var(--bg-secondary);
}
/* The destructive one is coloured, not shouted: it is reversible, and the confirmation
   says so. */
.record-menu__item--danger {
  color: var(--accent);
}

/* Spaces and leases as cards you can act on, rather than a list you can only read. */
.record-cards {
  display: grid;
  gap: 0.5rem;
  list-style: none;
  padding: 0;
  margin: 0;
}
.record-card {
  display: grid;
  gap: 0.4rem;
  padding: 0.7rem 0.8rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-elevated);
}
.record-card__open {
  display: grid;
  gap: 0.15rem;
  text-align: left;
  border: 0;
  padding: 0;
  background: none;
  cursor: pointer;
  font: inherit;
  color: inherit;
}
.record-card__name {
  font-weight: 600;
}
.record-card__meta {
  font-size: 0.8125rem;
  color: var(--text-secondary);
}
.record-card__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
/* Side by side once there is room; stacked on a phone, where a row of four things is
   four things too narrow to read. */
@media (min-width: 34rem) {
  .record-card {
    grid-template-columns: 1fr auto auto;
    align-items: center;
    gap: 0.75rem;
  }
}

/* Optional groups on the Add tenant form. Closed by default: most tenants are added with
   a name and an email, and four open sections of screening fields make that look like a
   long form when it is a short one. */
.tenant-extra {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.5rem 0.75rem;
  margin-bottom: 0.5rem;
}
.tenant-extra > summary {
  cursor: pointer;
  font-weight: 500;
  min-height: 44px;
  display: flex;
  align-items: center;
}
.tenant-extra[open] > summary {
  margin-bottom: 0.5rem;
}

/* ---------------------------------------------------------------------------
   Record disclosure: the detail opens as a row of the table, under the row it
   belongs to. Replaces the sticky side panel and the bottom sheet below it,
   both of which put the detail somewhere other than where it was opened.
   ------------------------------------------------------------------------ */
.record-workspace {
  display: block;
}
.record-expansion > td {
  padding: 0;
  background: var(--bg-secondary);
  border-bottom: 1px solid var(--border);
  /* The detail must not get a vote on how wide the table is. Without this the widest
     thing inside it - a long label, a wide grid - sets the cell's min-content width, the
     table grows to fit, and the page gains a horizontal scrollbar that the list alone
     never had. */
  max-width: 0;
  overflow: hidden;
}
.record-expansion__inner {
  position: relative;
  /* The cell above is max-width:0, so this needs a width of its own to be visible at all.
     It is the viewport rather than the cell because the cell no longer has a meaningful
     width - and the detail should be as wide as the screen allows, whatever the table
     next to it is doing.

     max-width, never width. A width of 100% here resolves against the table rather than
     the cell's content box - 311px against 284px on a phone - so the detail came out
     wider than the cell holding it, the table grew to fit, and the whole page gained a
     horizontal scrollbar. A max-width can only ever make this narrower than its cell, so
     it cannot widen the table; the viewport cap is what keeps a wide table's detail on
     screen. */
  width: calc(100vw - 2rem);
  max-width: 100%;
  padding: 20px 60px 20px 20px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow-sm);
  margin: 8px 0;
  box-sizing: border-box;
}
.record-expansion__inner > .detail-close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 32px;
  height: 32px;
  min-height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-elevated);
  color: var(--text-secondary);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
.record-expansion__inner > .detail-close:hover,
.record-expansion__inner > .detail-close:focus-visible {
  background: var(--bg-secondary);
  color: var(--text-primary);
}
.record-expansion__inner h3 {
  margin: 0 0 12px;
}
@media (max-width: 767px) {
  /*
   * Below this width the rows stop being table rows and stack as cards - `display: grid`
   * on the tr and its cells. Table width calculation is no longer in play, so the
   * max-width:0 that keeps the detail out of it above is not just unnecessary here, it
   * collapsed the cell to 40px and the detail inside it to 70.
   */
  /* The stacked-card rules give every row and cell padding of their own, which the
     detail does not want: it is not a field with a label, it is the whole record. Left
     as inherited it came out 244px inside a 311px row. */
  .record-expansion {
    padding: 0;
    margin: 0;
  }
  .record-expansion > td {
    display: block;
    max-width: none;
    overflow: visible;
    padding: 0;
    grid-column: 1 / -1;
  }
  .record-expansion__inner {
    width: auto;
    max-width: none;
    padding: 16px 52px 16px 16px;
    margin: 6px 0;
  }
}

/* The template form. Its labels sat beside their inputs, "Spaces" printed under its own
   textarea, and two of the hints were inside their <label> - so the hint read as part of
   the label and a screen reader announced the whole paragraph as the field's name. Label,
   control, hint: one per line, in that order. */
.template-form .template-field {
  display: grid;
  gap: 0.3rem;
  margin-bottom: 1rem;
}
.template-form .template-field > label {
  font-weight: 500;
  color: var(--text-primary);
}
.template-form .template-field > input,
.template-form .template-field > textarea {
  width: 100%;
  min-height: 44px;
  box-sizing: border-box;
}
.template-form .template-field > .field-hint {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--text-secondary);
}
.template-form > h4 {
  margin: 0 0 0.75rem;
}

/*
 * A date you can type.
 *
 * The text field is the control; the button beside it opens the browser's calendar
 * through a native date input that is rendered - showPicker refuses on anything that is
 * not - but carries no width of its own.
 */
.date-field {
  display: grid;
  grid-template-columns: 1fr auto;
  /* Stretch, so the button and the field beside it end up the same height. */
  align-items: stretch;
  gap: 0.35rem;
  position: relative;
  min-width: 0;
}
.date-field > label {
  min-width: 0;
}
.date-field__native {
  position: absolute;
  inset-inline-end: 0;
  bottom: 0;
  width: 1px;
  height: 1px;
  min-height: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  pointer-events: none;
}
.date-field__picker {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: end;
  /*
   * 44px, not 2.75rem. The root font is 15px here, so 2.75rem is 41.25px - under the
   * minimum touch target the mobile tests hold every button to, which is why they are
   * written in pixels everywhere else in this file.
   */
  min-height: 44px;
  min-width: 44px;
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: 0.2rem;
  background: var(--bg-elevated);
  color: inherit;
  cursor: pointer;
}
.date-field__picker:hover {
  background: var(--bg-subtle, var(--bg-elevated));
}

/*
 * An archived space stays on its property's list, because restoring it is done from
 * there. Looking identical to an active one is what made archiving appear to do nothing.
 */
.record-card--archived .record-card__name,
.record-card--archived .record-card__meta {
  color: var(--text-secondary, inherit);
}
.record-card--archived .record-card__open {
  opacity: 0.75;
}

/*
 * A long list gets a filter above it. The select itself is untouched: it keeps its name,
 * its label and its keyboard behaviour, and every form that reads it goes on reading it.
 */
.searchable-select {
  display: grid;
  gap: 0.35rem;
  min-width: 0;
}
.searchable-select__filter {
  min-height: 2.75rem;
  border: 1px solid var(--border-strong);
  border-radius: 0.2rem;
  padding: 0.55rem;
  background: var(--bg-elevated);
  font: inherit;
  color: inherit;
}
.searchable-select__count {
  margin: 0;
}
.searchable-select__count:empty {
  display: none;
}

/*
 * The space ↔ tenant ↔ lease dialogs. A short stack of labelled controls and, where the
 * space is already let, the choice between joining that lease and making another.
 */
.link-form {
  display: grid;
  gap: 0.35rem;
  margin: 0.75rem 0;
}
.link-form label {
  font-weight: 600;
}
.link-form label + label {
  margin-top: 0.5rem;
}
.link-choice {
  margin: 0.75rem 0 0;
  padding: 0.75rem;
  border: 1px solid var(--border);
  border-radius: 0.3rem;
}
.link-choice legend {
  padding: 0 0.35rem;
  font-weight: 700;
}
.link-choice__option {
  display: block;
  margin: 0.5rem 0;
  font-weight: 400;
}
.link-choice__option .field-hint {
  margin-left: 1.5rem;
}
.link-choice [hidden] {
  display: none !important;
}
.link-history {
  margin: 0.35rem 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.35rem;
}
.link-history li {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: baseline;
  padding: 0.35rem 0;
  border-top: 1px solid var(--border);
}
.link-history span {
  color: var(--muted);
}

/*
 * Recording many payments at once. A ticked list of residents with the amount beside
 * each name, and afterwards a line per resident saying what happened to theirs.
 */
.batch-people {
  margin: 0.5rem 0 1rem;
  border: 1px solid var(--border);
  border-radius: 0.3rem;
}
.batch-people__head {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
  justify-content: space-between;
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid var(--border);
}
.batch-people__list {
  margin: 0;
  padding: 0;
  list-style: none;
  max-height: 22rem;
  overflow-y: auto;
}
.batch-person {
  display: grid;
  grid-template-columns: 1fr 9rem;
  gap: 0.75rem;
  align-items: center;
  padding: 0.4rem 0.75rem;
  border-top: 1px solid var(--border);
}
.batch-person:first-child {
  border-top: 0;
}
.batch-person__amount {
  min-height: 2.75rem;
  min-width: 0;
  border: 1px solid var(--border-strong);
  border-radius: 0.2rem;
  padding: 0.4rem;
  background: var(--bg-elevated);
  font: inherit;
  color: inherit;
}
.batch-paste {
  margin-top: 0.75rem;
}
.batch-result {
  margin: 0.5rem 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.25rem;
}
.batch-result__row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0.35rem 0;
  border-top: 1px solid var(--border);
}
.batch-result__row span {
  color: var(--muted);
}
.batch-result__row--refused span {
  color: var(--danger-text, var(--muted));
}
@media (max-width: 720px) {
  .batch-person {
    grid-template-columns: 1fr;
  }
}

/* The Terms and Privacy pages, which are served on their own rather than inside the
   application shell: somebody reads them before they have an account. */
.legal-page {
  max-width: 42rem;
  margin: 0 auto;
  padding: max(2rem, env(safe-area-inset-top)) 1.25rem max(2rem, env(safe-area-inset-bottom));
  line-height: 1.6;
}
.legal-page__brand {
  font-weight: 600;
  letter-spacing: 0.02em;
  margin-bottom: 2rem;
}
.legal-page h1 {
  font-size: 1.6rem;
  margin-bottom: 1rem;
}
.legal-page h2 {
  font-size: 1.15rem;
  margin-top: 2rem;
}
.legal-page__version {
  margin-top: 2.5rem;
  color: var(--muted, #5b6670);
  font-size: 0.8125rem;
}
