/* =============================================================================
   North PMG - stylesheet
   -----------------------------------------------------------------------------
   Every colour, font and spacing value used anywhere in this file is defined as a
   custom property in the :root block below. Brand colours are not defined yet
   (data/site.json themeColor is null), so these are a chosen placeholder palette:
   change the tokens and the whole site changes. Nothing below :root hardcodes a
   colour or a font family.

   Palette rationale, for whoever swaps it:
     White, brand navy and logo blue. The product is property management, so the
     interface should feel calm, operational and trustworthy before it feels decorative.
     Photography carries the local proof; the UI stays crisp and restrained.

   This is a single light palette. Dark bands are used only as emphasis for metrics,
   CTAs and the footer, where the navy gives contrast and weight without turning the
   whole site into a mood piece.

   The consequence to watch: this site has four substantial forms, and long forms are
   where palettes usually reveal their weak spots. So the contrast budget is spent there
   first - input borders clear 3:1 against their own background, field text clears 4.5:1,
   and every one of those pairs is machine-checked.

   Contrast discipline: every colour pair that carries text meets WCAG AA (4.5:1 for body
   text, 3:1 for large text and for non-text UI boundaries). The pairs are checked by
   scripts/verify-contrast.mjs, wired into `npm run verify`. Do not add a colour here
   without re-running it.

   Three tokens exist because the same idea is needed in more than one place:
     --brand-ink       the colour a link is, on --paper / --surface
     --accent-ink      the colour a link becomes on hover
     --accent-on-dark  accent that is safe as TEXT on --surface-invert
   --brand-600/700 stay dark because they are BUTTON BACKGROUNDS under ivory text.
   Do not merge them with --brand-ink.
   ============================================================================= */

:root {
  color-scheme: light;

  /* ---- structure: brand navy and blue ----------------------------------- */
  --brand-900: #071d31;
  --brand-800: #0b2f4e;
  --brand-700: #12456f;
  --brand-600: #185d94;
  --brand-500: #2f86c4;
  --brand-100: #d5e8f6;
  --brand-50:  #eef6fc;

  /* ---- accent blue ------------------------------------------------------- */
  --accent-700: #0a5a80;
  --accent-600: #0d6f9c;
  --accent-500: #1a93c9;
  --accent-100: #dff1fb;
  --accent-50:  #eff8fd;

  --brand-ink: var(--brand-600);
  --accent-ink: var(--accent-600);
  --accent-on-dark: #7fd0f5;

  /* ---- surfaces and text ------------------------------------------------- */
  --paper: #f7fafc;
  --surface: #ffffff;
  --surface-sunken: #eef3f8;
  --surface-invert: var(--brand-800);

  --text: #0f1e2b;
  --text-muted: #55677a;
  --text-heading: var(--brand-800);
  --text-invert: #f4f9fd;
  --text-invert-muted: #b6cfe3;

  --border: #dde6ee;
  /*
   * --border-strong is the visible boundary of a form control, so WCAG 1.4.11 wants 3:1
   * against --surface. It is intentionally stronger than a decorative hairline.
   */
  --border-strong: #7b91a5;
  --border-invert: #1b4a71;

  /* ---- state ------------------------------------------------------------- */
  --danger: #b3251c;
  --danger-bg: #fdf1f0;
  --success: #0d7a4f;
  --success-bg: #e8f7f0;
  /*
   * Warning is pushed orange, away from brand blue. It is what .placeholder uses, and a
   * placeholder the same colour as every button is a placeholder that ships by accident.
   */
  --warning: #7a5310;
  --warning-bg: #fdf4e3;

  /*
   * Primary button: brand blue under white text.
   */
  --btn-primary-bg: var(--brand-600);
  --btn-primary-bg-hover: var(--brand-700);
  --btn-primary-fg: #ffffff;

  /*
   * TWO focus rings, because no single colour clears 3:1 against both a white page and a
   * navy footer - a mid blue fails on one end or the other, and this was measured, not
   * assumed. --focus-ring is the default; --focus-ring-invert is scoped to the dark bands
   * further down.
   */
  --focus-ring: var(--accent-600);
  --focus-ring-invert: #7fd0f5;

  /* ---- type -------------------------------------------------------------- */
  /*
   * All sans. --font-display is kept as a separate token so a display face can be
   * reintroduced in one line if a brand ever specifies one, but it currently resolves
   * to the same stack as --font-body on purpose.
   */
  --font-body: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-display: var(--font-body);

  --step--1: clamp(0.82rem, 0.79rem + 0.13vw, 0.89rem);
  --step-0:  clamp(1rem, 0.96rem + 0.2vw, 1.08rem);
  --step-1:  clamp(1.15rem, 1.08rem + 0.35vw, 1.33rem);
  --step-2:  clamp(1.36rem, 1.24rem + 0.6vw, 1.7rem);
  --step-3:  clamp(1.6rem, 1.4rem + 1vw, 2.2rem);
  --step-4:  clamp(1.9rem, 1.55rem + 1.75vw, 2.9rem);
  --step-5:  clamp(2.35rem, 1.7rem + 3.1vw, 4.1rem);
  /* Display step, for hero headlines only. Nothing else should reach this size. */
  --step-6:  clamp(2.6rem, 1.95rem + 3.1vw, 4.4rem);

  /* ---- space ------------------------------------------------------------- */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-7: 3rem;
  --sp-8: 4rem;
  --sp-9: 6rem;

  --shell-max: 74rem;
  --prose-max: 40rem;

  --radius-sm: 4px;
  --radius: 8px;
  --radius-lg: 14px;
  --radius-xl: 20px;

  /*
   * Shadows stay layered and low-alpha so cards feel lifted without becoming decorative
   * tiles.
   */
  --shadow-sm: 0 1px 2px rgb(7 29 49 / 0.06), 0 1px 3px rgb(7 29 49 / 0.05);
  --shadow: 0 2px 4px rgb(7 29 49 / 0.05), 0 8px 24px rgb(7 29 49 / 0.08);
  --shadow-lg: 0 4px 8px rgb(7 29 49 / 0.06), 0 20px 44px rgb(7 29 49 / 0.13);
  --shadow-xl:
    0 2px 4px rgb(7 29 49 / 0.04),
    0 8px 16px rgb(7 29 49 / 0.06),
    0 24px 48px rgb(7 29 49 / 0.10),
    0 48px 96px rgb(7 29 49 / 0.12);
  --shadow-float:
    0 1px 2px rgb(7 29 49 / 0.08),
    0 8px 20px rgb(7 29 49 / 0.10),
    0 24px 56px rgb(7 29 49 / 0.16);

  /* ---- motion ------------------------------------------------------------ */
  /*
   * One decelerating curve used everywhere. It starts fast and settles slowly, which is
   * what makes an interface feel responsive rather than sluggish - the opposite of the
   * ease-in-out default, which feels hesitant at the start of every transition.
   */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --transition-slow: 420ms var(--ease);
  --transition-med: 260ms var(--ease);

  --header-h: 4.25rem;
  --transition: 160ms var(--ease);
}

/* =============================================================================
   Base
   ============================================================================= */

*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* The header is sticky, so an anchored target would otherwise land underneath it. */
  scroll-padding-top: calc(var(--header-h) + var(--sp-4));
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.65;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /*
   * `clip`, not `hidden`. `overflow-x: hidden` on <body> turns it into a scroll
   * container, which stops position:sticky working on the header. `clip` contains
   * stray horizontal overflow without that side effect.
   */
  overflow-x: clip;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: 0;
  text-wrap: balance;
  margin: 0 0 var(--sp-4);
}

h1 { font-size: var(--step-5); }
h2 { font-size: var(--step-4); }
/* Sub-headings step back down to semibold: 700 at these sizes crowds the body copy. */
h3 { font-size: var(--step-2); font-weight: 600; letter-spacing: 0; }
h4 { font-size: var(--step-1); font-weight: 600; letter-spacing: 0; }

p, ul, ol, dl, table { margin: 0 0 var(--sp-4); }
p { text-wrap: pretty; }

a {
  color: var(--brand-ink);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  transition: color var(--transition);
}
a:hover { color: var(--accent-ink); }

img, svg, video { max-width: 100%; height: auto; }
img { background: var(--surface-sunken); }

hr {
  border: 0;
  border-top: 1px solid var(--border);
  margin: var(--sp-7) 0;
}

/* Anchored headings must not hide behind the sticky header. */
:is(h1, h2, h3, h4, section, [id]) { scroll-margin-top: calc(var(--header-h) + var(--sp-5)); }

:where(a, button, input, select, textarea, summary, details):focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* The dark bands need the light ring; see the note on --focus-ring-invert. */
:is(.site-footer, .cta-band, .metrics) :where(a, button, input, select, textarea, summary):focus-visible {
  outline-color: var(--focus-ring-invert);
}

:where(a, button, summary, label, input, select) {
  touch-action: manipulation;
  /* Set deliberately: the browser default flash reads as a rendering fault. This is
     the accent blue, at the same weight as the focus ring. */
  -webkit-tap-highlight-color: rgb(41 171 226 / 0.20);
}

button { font: inherit; }

.muted { color: var(--text-muted); }
.small { font-size: var(--step--1); }
.eyebrow {
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--accent-ink);
  margin: 0 0 var(--sp-3);
}
.tnum { font-variant-numeric: tabular-nums; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.shell {
  width: 100%;
  max-width: var(--shell-max);
  margin-inline: auto;
  padding-inline: max(var(--sp-5), env(safe-area-inset-left), env(safe-area-inset-right));
}

.section { padding-block: var(--sp-8); }
.section--tight { padding-block: var(--sp-7); }
.section--sunken { background: var(--surface-sunken); }
.section__title { max-width: 22ch; }
.section__lead {
  max-width: var(--prose-max);
  font-size: var(--step-1);
  color: var(--text-muted);
  margin-bottom: var(--sp-6);
}

@media (min-width: 48rem) {
  .section { padding-block: var(--sp-9); }
}

.skip-link {
  position: absolute;
  left: var(--sp-4);
  top: var(--sp-2);
  z-index: 100;
  transform: translateY(-200%);
  background: var(--btn-primary-bg);
  color: var(--btn-primary-fg);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--radius);
  font-weight: 600;
  text-decoration: none;
}
.skip-link:focus-visible {
  transform: translateY(0);
  color: var(--btn-primary-fg);
}

/*
 * <main> is focused programmatically by the skip link, so it does not need a ring when
 * it receives focus that way. Keyboard-driven focus still shows one - this is not a
 * blanket outline:none.
 */
main:focus:not(:focus-visible) { outline: none; }

/* =============================================================================
   Buttons
   ============================================================================= */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: 2.75rem;
  padding: var(--sp-3) var(--sp-5);
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-weight: 600;
  font-size: var(--step-0);
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--transition), border-color var(--transition), color var(--transition), transform var(--transition);
}
.btn:active { transform: translateY(1px); }

.btn--primary {
  background: var(--btn-primary-bg);
  border-color: var(--btn-primary-bg);
  color: var(--btn-primary-fg);
}
.btn--primary:hover {
  background: var(--btn-primary-bg-hover);
  border-color: var(--btn-primary-bg-hover);
  color: var(--btn-primary-fg);
}

.btn--secondary {
  background: var(--brand-700);
  border-color: var(--brand-700);
  color: var(--text-invert);
}
.btn--secondary:hover {
  background: var(--brand-600);
  border-color: var(--brand-600);
  color: var(--text-invert);
}

.btn--outline {
  background: transparent;
  border-color: var(--border-strong);
  color: var(--text);
}
.btn--outline:hover {
  border-color: var(--accent-700);
  color: var(--brand-ink);
  background: var(--brand-50);
}

.btn--ghost {
  background: transparent;
  border-color: rgb(255 255 255 / 0.4);
  color: var(--text-invert);
}
.btn--ghost:hover {
  background: rgb(255 255 255 / 0.12);
  border-color: rgb(255 255 255 / 0.75);
  color: var(--text-invert);
}

.btn--sm { min-height: 2.25rem; padding: var(--sp-2) var(--sp-4); font-size: var(--step--1); }
.btn--lg { min-height: 3.1rem; padding: var(--sp-4) var(--sp-6); font-size: var(--step-1); }

.btn[aria-disabled="true"],
.btn:disabled,
button:disabled { opacity: 0.6; cursor: not-allowed; }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
}

.arrow { display: inline-block; transition: transform var(--transition); }

/* =============================================================================
   Header and navigation
   ============================================================================= */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--border);
  padding-top: env(safe-area-inset-top);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  min-height: var(--header-h);
}

.site-header__brand,
.site-footer__brand { text-decoration: none; color: inherit; }

/*
 * The logo is now a real image, not type. Height is fixed and width follows, so the mark
 * keeps its aspect ratio at every viewport; the intrinsic width/height on the <img> stop
 * it reflowing the header while it loads.
 */
.logo {
  display: block;
  width: auto;
  height: 2.7rem;
  /*
   * The global `img { background: var(--surface-sunken) }` placeholder shows straight
   * through a transparent PNG and puts a pale plate behind the mark. Off, here only.
   */
  background: none;
}
@media (max-width: 40rem) {
  /* The lockup is 2.8:1, so height is what governs whether the wordmark stays legible. */
  .logo { height: 2.3rem; }
}
.site-footer .logo { height: 3rem; }

.nav-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 2.75rem;
  padding: var(--sp-2) var(--sp-3);
  background: transparent;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  color: var(--text);
  font-size: var(--step--1);
  font-weight: 600;
  cursor: pointer;
}
.nav-toggle:hover { border-color: var(--border-strong); color: var(--brand-ink); }
.nav-toggle__bars {
  position: relative;
  width: 1rem;
  height: 2px;
  background: currentColor;
}
.nav-toggle__bars::before,
.nav-toggle__bars::after {
  content: "";
  position: absolute;
  left: 0;
  width: 1rem;
  height: 2px;
  background: currentColor;
}
.nav-toggle__bars::before { top: -5px; }
.nav-toggle__bars::after { top: 5px; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars { background: transparent; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars::before { top: 0; transform: rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars::after { top: 0; transform: rotate(-45deg); }

.site-nav__list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.site-nav__list a,
.site-nav__phone {
  display: block;
  white-space: nowrap;
  padding: var(--sp-3) 0;
  color: var(--text);
  font-weight: 500;
  font-size: var(--step-0);
  text-decoration: none;
}
.site-nav__list a:hover { color: var(--accent-ink); }
.site-nav__list a[aria-current="page"] {
  color: var(--brand-ink);
  font-weight: 600;
  box-shadow: inset 0 -2px 0 var(--accent-500);
}
.site-nav__phone { font-variant-numeric: tabular-nums; font-weight: 600; }
.site-nav__phone:hover { color: var(--accent-ink); }

/*
 * The disclosure nav runs up to 75rem, not the usual 64rem. Six top-level items plus a
 * phone number and a button genuinely need about 1200px; between 1024 and 1200 the bar
 * wraps onto two lines and looks broken.
 */
@media (max-width: 74.99rem) {
  .site-nav {
    display: none;
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow);
    padding: var(--sp-4) max(var(--sp-5), env(safe-area-inset-left)) var(--sp-6);
    max-height: calc(100dvh - var(--header-h));
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .site-nav.is-open { display: block; }
  /*
   * Portal Login stays in the bar beside Menu on phones and tablets (2026-09-17), so the
   * copy inside the dropdown is hidden rather than listed twice. margin-left: auto pushes
   * it right, next to the toggle, instead of space-between centring it.
   */
  .site-header__portal { margin-left: auto; white-space: nowrap; }
  .site-nav__portal { display: none; }
  .site-header__brand { flex-shrink: 0; }
}
/*
 * Logo + Portal Login + "Menu" needs ~330px and a 360px phone has ~312 inside the gutters.
 * Below 24rem the toggle keeps only its icon (the word stays for screen readers, same
 * clip as .visually-hidden) and the gaps and button padding tighten. Measured at 390,
 * 360 and 320.
 */
@media (max-width: 23.99rem) {
  .site-header__inner { gap: var(--sp-2); }
  .site-header__portal { padding-inline: var(--sp-3); }
  .nav-toggle { padding-inline: var(--sp-3); }
  .nav-toggle__text {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
  .site-nav__list li + li { border-top: 1px solid var(--border); }
  .site-nav__actions {
    display: grid;
    gap: var(--sp-3);
    margin-top: var(--sp-4);
    padding-top: var(--sp-4);
    border-top: 1px solid var(--border);
  }
}

@media (min-width: 75rem) {
  .nav-toggle { display: none; }
  .site-header__portal { display: none; }
  .site-nav {
    display: flex;
    align-items: center;
    gap: var(--sp-6);
  }
  .site-nav__list {
    display: flex;
    align-items: center;
    gap: var(--sp-5);
  }
  .site-nav__list a { padding: var(--sp-2) 0; }
  .site-nav__actions {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
  }
  /*
   * Portal Login (2026-09-17) made the bar a button wider. Without these the buttons
   * wrapped to two lines and the logo was squeezed rather than anything overflowing.
   */
  .site-header__brand { flex-shrink: 0; }
  .site-nav__actions .btn { white-space: nowrap; }
}
/* Between 75rem and 87.5rem the full bar only fits with tighter spacing. */
@media (min-width: 75rem) and (max-width: 87.49rem) {
  .site-nav { gap: var(--sp-4); }
  .site-nav__list { gap: var(--sp-4); }
  .site-nav__actions { gap: var(--sp-3); }
}

/* =============================================================================
   Hero
   ============================================================================= */

.hero {
  position: relative;
  /*
   * Light hero. Two very soft blue washes over a top-down tint, so the section reads
   * as "bright and open" rather than as a flat white band, and the photograph is the
   * only saturated thing in it. Every colour comes from a token via color-mix, so a
   * palette swap carries through here too.
   */
  background:
    radial-gradient(ellipse 70% 56% at 2% -16%, color-mix(in srgb, var(--accent-600) 20%, transparent), transparent 66%),
    radial-gradient(ellipse 56% 46% at 104% -6%, color-mix(in srgb, var(--accent-700) 12%, transparent), transparent 62%),
    linear-gradient(180deg, var(--brand-50) 0%, var(--paper) 74%);
  color: var(--text);
  border-bottom: 1px solid var(--border);
  padding-block: var(--sp-8) var(--sp-9);
  overflow: hidden;
}
/*
 * A faint dot grid, masked so it fades out before it reaches the copy. It is the one
 * piece of texture on the page; at 8% of the brand blue it is felt more than seen.
 */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(color-mix(in srgb, var(--brand-600) 14%, transparent) 1px, transparent 1.5px);
  background-size: 22px 22px;
  mask-image: linear-gradient(160deg, rgb(0 0 0 / 0.7), transparent 52%);
  -webkit-mask-image: linear-gradient(160deg, rgb(0 0 0 / 0.7), transparent 52%);
  pointer-events: none;
}
.hero > * { position: relative; z-index: 1; }
.hero__inner {
  display: grid;
  gap: var(--sp-7);
  align-items: center;
}
.hero__text { min-width: 0; }
.hero__media {
  min-width: 0;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  /* A hairline edge separates the photograph from the light hero field. */
  outline: 1px solid color-mix(in srgb, var(--brand-900) 12%, transparent);
  outline-offset: -1px;
}
.hero__media img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

@media (min-width: 60rem) {
  .hero__inner { grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr); }
  .hero__media img { aspect-ratio: 5 / 4; }
}
.hero .eyebrow { color: var(--accent-ink); }
.hero__title {
  font-size: var(--step-5);
  max-width: 18ch;
  margin-bottom: var(--sp-5);
  /* The headline carries the brand colour now that the background no longer does. */
  color: var(--text-heading);
  font-weight: 700;
  letter-spacing: 0;
}
.hero__lead {
  max-width: 46ch;
  font-size: var(--step-1);
  color: var(--text-muted);
}
/*
 * .btn--ghost is a white-on-transparent button built for the dark CTA band. In the
 * light hero it would be invisible, so it is restyled here rather than swapping the
 * class in the page generator - the markup is unchanged either way.
 */
.hero .btn--ghost {
  background: var(--surface);
  border-color: var(--border-strong);
  color: var(--brand-ink);
  box-shadow: var(--shadow-sm);
}
.hero .btn--ghost:hover {
  background: var(--brand-50);
  border-color: var(--brand-500);
  color: var(--brand-ink);
}
.hero__areas {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
  list-style: none;
  margin: var(--sp-6) 0 0;
  padding: 0;
  font-size: var(--step--1);
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--text-muted);
}
.hero__areas li + li { border-left: 1px solid var(--border-strong); padding-left: var(--sp-4); }

/*
 * Photographs of managed homes, used as imagery only. No price, no availability, no
 * link to a listing - see src/lib/showcase.mjs for why that distinction matters.
 */
.photo-band {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
  gap: var(--sp-4);
  list-style: none;
  margin: 0;
  padding: 0;
}
.photo-band__item {
  min-width: 0;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--surface-sunken);
}
.photo-band__item img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

.figure { margin: 0; min-width: 0; }
.figure img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
}
.figure__caption {
  margin-top: var(--sp-3);
  color: var(--text-muted);
  font-size: var(--step--1);
}

.page-hero {
  background:
    radial-gradient(ellipse 60% 70% at 0% 0%, color-mix(in srgb, var(--accent-600) 14%, transparent), transparent 70%),
    linear-gradient(180deg, var(--brand-50) 0%, var(--paper) 100%);
  border-bottom: 1px solid var(--border);
  padding-block: var(--sp-7) var(--sp-8);
}
.page-hero__title { max-width: 20ch; margin-bottom: var(--sp-4); color: var(--text-heading); }
.page-hero__lead {
  max-width: 58ch;
  font-size: var(--step-1);
  color: var(--text-muted);
  margin: 0;
}

/* =============================================================================
   Stats
   ============================================================================= */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: var(--sp-5);
  list-style: none;
  margin: var(--sp-7) 0 0;
  padding: 0;
}
.stats__item {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  padding-left: var(--sp-4);
  border-left: 2px solid var(--accent-500);
}
.stats__value {
  font-family: var(--font-display);
  font-size: var(--step-3);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.stats__label {
  font-size: var(--step--1);
  color: var(--text-muted);
  text-wrap: pretty;
}
.hero .stats__label { color: var(--text-muted); }

/* =============================================================================
   Cards
   ============================================================================= */

.grid {
  display: grid;
  gap: var(--sp-5);
}
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); }

.card {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: var(--sp-5);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  transition: border-color var(--transition), box-shadow var(--transition), transform var(--transition);
}
.card:has(.card__link:hover),
.card:has(.card__link:focus-visible) {
  border-color: var(--accent-700);
  box-shadow: var(--shadow);
}
.card:has(.card__link:hover) .arrow { transform: translateX(3px); }
.card__title { font-size: var(--step-1); margin-bottom: var(--sp-3); }
.card__link { color: inherit; text-decoration: none; }
/* Whole card is the hit target, but the accessible name stays on the real link. */
.card__link::after { content: ""; position: absolute; inset: 0; }
.card { position: relative; }
.card__body { color: var(--text-muted); }
.card__body > :last-child { margin-bottom: 0; }
.card__more {
  margin: auto 0 0;
  padding-top: var(--sp-4);
  color: var(--accent-ink);
  font-weight: 600;
  font-size: var(--step--1);
}

/* =============================================================================
   Service list (progressive disclosure) and process flow
   ============================================================================= */

.service-list {
  display: grid;
  gap: var(--sp-3);
  max-width: 56rem;
}

.service {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  transition: border-color var(--transition), box-shadow var(--transition);
}
.service[open] { border-color: var(--accent-700); box-shadow: var(--shadow); }
.service:hover:not([open]) { border-color: var(--border-strong); }

/*
 * The whole summary row is the hit target, and it stays above 44px at every viewport.
 * Removing the disclosure triangle needs both of these: ::-webkit-details-marker for
 * older Safari, list-style for everything else.
 */
.service__summary {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  cursor: pointer;
  list-style: none;
  border-radius: var(--radius-lg);
}
.service__summary::-webkit-details-marker { display: none; }
.service__summary:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.service__icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: var(--radius);
  background: var(--brand-50);
  color: var(--brand-ink);
  transition: background-color var(--transition), color var(--transition);
}
.service[open] .service__icon { background: var(--brand-600); color: var(--text-invert); }
.service__icon .icon { width: 1.4rem; height: 1.4rem; }

.service__heading {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
}
.service__title {
  margin: 0;
  font-weight: 600;
  font-size: var(--step-1);
  line-height: 1.3;
  letter-spacing: 0;
  color: var(--text);
  text-wrap: balance;
}
.service__summary-text {
  color: var(--text-muted);
  font-size: var(--step--1);
  text-wrap: pretty;
}
/* The one-line teaser is redundant once the full copy is on screen. */
.service[open] .service__summary-text { display: none; }

.service__chevron {
  flex: none;
  width: 0.6rem;
  height: 0.6rem;
  margin-top: 0.7rem;
  border-right: 2px solid var(--text-muted);
  border-bottom: 2px solid var(--text-muted);
  transform: rotate(45deg);
  transition: transform var(--transition);
}
.service[open] .service__chevron { transform: rotate(-135deg); }

.service__body {
  /* Aligns with the title rather than the icon. */
  padding: 0 var(--sp-5) var(--sp-5) calc(var(--sp-5) + 2.75rem + var(--sp-4));
  max-width: 68ch;
  color: var(--text-muted);
}
.service__body > :last-child { margin-bottom: 0; }
.service__body a { color: var(--brand-ink); }

@media (max-width: 40rem) {
  .service__summary { padding: var(--sp-4); gap: var(--sp-3); }
  .service__icon { width: 2.25rem; height: 2.25rem; }
  .service__icon .icon { width: 1.15rem; height: 1.15rem; }
  .service__body { padding: 0 var(--sp-4) var(--sp-4); }
}

/* Flow variant: the steps sit in a column beside a photo, so they run tighter. */
.steps--flow { gap: var(--sp-4); }
.steps--flow > li { padding-left: var(--sp-7); }
.steps--flow > li::before { width: 1.9rem; height: 1.9rem; font-size: var(--step--1); }
.steps--flow h3 { font-size: var(--step-0); margin-bottom: var(--sp-1); }
.steps--flow p { color: var(--text-muted); font-size: var(--step--1); }

/* =============================================================================
   Listing spec strip and grouped gallery
   ============================================================================= */

.spec-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3) var(--sp-5);
  list-style: none;
  margin: 0 0 var(--sp-6);
  padding: var(--sp-4) var(--sp-5);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.spec-strip__item { display: flex; align-items: baseline; gap: var(--sp-2); }
.spec-strip__item + .spec-strip__item {
  padding-left: var(--sp-5);
  border-left: 1px solid var(--border);
}
.spec-strip__unit { font-weight: 400; font-size: var(--step--1); color: var(--text-muted); }

@media (max-width: 40rem) {
  .spec-strip { gap: var(--sp-2) var(--sp-4); }
  .spec-strip__item + .spec-strip__item { padding-left: var(--sp-4); }
}

.listing-gallery-group { margin-bottom: var(--sp-6); }
.listing-gallery-group__title {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
  font-size: var(--step-1);
  margin-bottom: var(--sp-4);
}
.listing-gallery-group__count {
  font-size: var(--step--1);
  font-weight: 400;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
/*
 * Grouped sections are even grids - no oversized first tile.
 *
 * auto-FILL, not auto-fit: a room with a single photo is common (this listing has one
 * kitchen shot and one bathroom shot), and auto-fit collapses the empty tracks so that
 * lone photo stretches the full width of the page. auto-fill keeps the tracks, so one
 * photo is one tile.
 */
/*
 * Doubled class, not a single one: the base .listing-gallery rules live further down
 * this file, and at equal specificity the later rule wins. Without this the grouped
 * grid inherits auto-fit and the full-bleed first tile from the flat gallery.
 */
.listing-gallery.listing-gallery--grouped {
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
}
.listing-gallery.listing-gallery--grouped li:first-child { grid-column: auto; }
.listing-gallery.listing-gallery--grouped li:first-child img { aspect-ratio: 3 / 2; }

.listing-gallery__link {
  display: block;
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform var(--transition), box-shadow var(--transition);
}
.listing-gallery__link:hover { transform: translateY(-2px); box-shadow: var(--shadow); }
.listing-gallery__link:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 3px; }

/* =============================================================================
   Lightbox

   Injected by site/js/lightbox.js. With no JS none of this is ever rendered, and the
   gallery stays a grid of links to the full-size images.
   ============================================================================= */

body.has-lightbox { overflow: hidden; }

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-rows: auto minmax(0, 1fr);
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4);
  padding-top: max(var(--sp-4), env(safe-area-inset-top));
  padding-bottom: max(var(--sp-4), env(safe-area-inset-bottom));
  /* 0.97, not 0.9x: at lower opacity the page text behind reads through the overlay
     and competes with the photograph. verify-contrast checks against #050f1b. */
  background: rgb(8 9 12 / 0.97);
  /* Stops a scroll gesture at the edge of the overlay chaining to the page behind. */
  overscroll-behavior: contain;
  backdrop-filter: blur(4px);
  /* The overlay carries its own literals: it must stay dark and readable even if the
     palette is later given a light variant. */
  color: #f2efe9;
}
.lightbox[hidden] { display: none; }

.lightbox__bar {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
}
.lightbox__count {
  margin: 0;
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
  color: #b8b2a8;
}

.lightbox__btn {
  display: grid;
  place-items: center;
  min-width: 2.75rem;
  min-height: 2.75rem;
  padding: 0;
  border: 1px solid rgb(255 255 255 / 0.25);
  border-radius: var(--radius);
  background: rgb(255 255 255 / 0.08);
  color: inherit;
  font-size: var(--step-3);
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--transition), border-color var(--transition);
}
.lightbox__btn:hover { background: rgb(255 255 255 / 0.18); border-color: rgb(255 255 255 / 0.55); }
.lightbox__btn:focus-visible { outline: 2px solid #e3c567; outline-offset: 2px; }

.lightbox__figure {
  grid-column: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  margin: 0;
  min-width: 0;
  min-height: 0;
  max-height: 100%;
}
.lightbox__img {
  max-width: 100%;
  /* Leaves room for the bar and caption without measuring anything in JS. */
  max-height: calc(100dvh - 11rem);
  object-fit: contain;
  border-radius: var(--radius);
  background: rgb(255 255 255 / 0.04);
}
.lightbox__caption {
  margin: 0;
  max-width: 62ch;
  text-align: center;
  font-size: var(--step--1);
  color: #b8b2a8;
  text-wrap: pretty;
}

.lightbox__nav--prev { grid-column: 1; grid-row: 2; }
.lightbox__nav--next { grid-column: 3; grid-row: 2; }

@media (max-width: 40rem) {
  .lightbox { gap: var(--sp-2); padding-inline: var(--sp-2); }
  .lightbox__img { max-height: calc(100dvh - 13rem); }
}

/* =============================================================================
   Prose (blog posts, legal pages, long copy)
   ============================================================================= */

.prose { max-width: var(--prose-max); }
.prose h2 { font-size: var(--step-2); margin-top: var(--sp-7); }
.prose h3 { font-size: var(--step-1); margin-top: var(--sp-6); }
.prose h2:first-child, .prose h3:first-child { margin-top: 0; }
.prose ul, .prose ol { padding-left: var(--sp-5); }
.prose li { margin-bottom: var(--sp-2); }
.prose li::marker { color: var(--accent-500); }
.prose blockquote {
  margin: var(--sp-6) 0;
  padding: var(--sp-2) var(--sp-5);
  border-left: 3px solid var(--accent-500);
  color: var(--text-muted);
  font-style: italic;
}

.checklist { list-style: none; padding: 0; }
.checklist li {
  position: relative;
  padding-left: var(--sp-6);
  margin-bottom: var(--sp-3);
}
.checklist li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 0.65rem;
  height: 0.65rem;
  border-radius: 2px;
  background: var(--accent-500);
}

.steps {
  list-style: none;
  counter-reset: step;
  padding: 0;
  display: grid;
  gap: var(--sp-5);
}
.steps > li {
  counter-increment: step;
  position: relative;
  padding-left: var(--sp-8);
  min-width: 0;
}
.steps > li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0;
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  background: var(--brand-700);
  color: #fff;
  font-family: var(--font-display);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.steps h3 { font-size: var(--step-1); margin-bottom: var(--sp-2); }
.steps p:last-child { margin-bottom: 0; }

/* =============================================================================
   FAQ
   ============================================================================= */

.faq {
  border-top: 1px solid var(--border);
  max-width: 56rem;
}
.faq__item { border-bottom: 1px solid var(--border); }
.faq__q {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-4) 0;
  cursor: pointer;
  list-style: none;
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q-text {
  font-family: var(--font-body);
  font-size: var(--step-0);
  font-weight: 600;
  line-height: 1.5;
  margin: 0;
  letter-spacing: 0;
}
.faq__q::after {
  content: "+";
  flex: none;
  font-size: var(--step-2);
  line-height: 1;
  color: var(--accent-ink);
  transition: transform var(--transition);
}
.faq__item[open] .faq__q::after { content: "\2212"; }
.faq__q:hover .faq__q-text { color: var(--brand-ink); }
.faq__a {
  padding: 0 0 var(--sp-5);
  max-width: 62ch;
  color: var(--text-muted);
}
.faq__a > :last-child { margin-bottom: 0; }

/* =============================================================================
   Callouts, placeholders and blocked notices
   ============================================================================= */

.callout {
  padding: var(--sp-5);
  border: 1px solid var(--border);
  border-left: 3px solid var(--brand-500);
  border-radius: var(--radius);
  background: var(--surface);
  margin-bottom: var(--sp-5);
}
.callout > :last-child { margin-bottom: 0; }
.callout__title { font-size: var(--step-1); margin-bottom: var(--sp-2); }
.callout--warning { border-left-color: var(--warning); background: var(--warning-bg); }
.callout--danger { border-left-color: var(--danger); background: var(--danger-bg); }

/*
 * Deliberately loud. These mark content that cannot be written or published until
 * Pavan supplies a fact, and they must be impossible to miss in a review pass -
 * a quiet placeholder is one that ships.
 */
.placeholder {
  /*
   * inline-block, not inline: an inline element with a dashed border fragments into a
   * separate broken box on every wrapped line, which reads as a rendering fault rather
   * than as a note.
   */
  display: inline-block;
  line-height: 1.5;
  padding: 0.1em 0.4em;
  border: 1px dashed var(--warning);
  border-radius: var(--radius-sm);
  background: var(--warning-bg);
  color: var(--warning);
  font-family: var(--font-body);
  font-size: 0.9em;
  font-weight: 600;
}

/* =============================================================================
   Properties: filters and grid
   ============================================================================= */

.filters {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--sp-4);
  padding: var(--sp-5);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  margin-bottom: var(--sp-6);
}
.filters .field { margin: 0; flex: 1 1 10rem; min-width: 0; }
.filters__reset { flex: none; }
.filters__count {
  flex-basis: 100%;
  margin: 0;
  color: var(--text-muted);
  font-size: var(--step--1);
}

.property-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 18rem), 1fr));
  gap: var(--sp-5);
  list-style: none;
  margin: 0;
  padding: 0;
}

.property-card {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: border-color var(--transition), box-shadow var(--transition);
}
.property-card:has(a:hover),
.property-card:has(a:focus-visible) {
  border-color: var(--accent-700);
  box-shadow: var(--shadow);
}
.property-card__media {
  position: relative;
  aspect-ratio: 3 / 2;
  background: var(--surface-sunken);
}
.property-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.property-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-5) var(--sp-5);
  min-width: 0;
}
.property-card__price {
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.property-card__price span { font-family: var(--font-body); font-size: var(--step--1); font-weight: 400; color: var(--text-muted); }
.property-card__title { font-size: var(--step-1); margin: 0; }
.property-card__title a { color: inherit; text-decoration: none; }
.property-card__title a::after { content: ""; position: absolute; inset: 0; }
.property-card__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
  list-style: none;
  margin: 0;
  padding: 0;
  color: var(--text-muted);
  font-size: var(--step--1);
}

.badge {
  display: inline-block;
  padding: 0.2em 0.6em;
  border-radius: 999px;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0;
}
.badge--available { background: var(--success-bg); color: var(--success); }
.badge--leased { background: var(--surface-sunken); color: var(--text-muted); }
.badge--pending { background: var(--warning-bg); color: var(--warning); }
.property-card__media .badge {
  position: absolute;
  top: var(--sp-3);
  left: var(--sp-3);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}

/*
 * Dummy layer - see src/lib/dummy.mjs. Remove with it.
 * Must come after the rule above: same specificity, so source order decides, and
 * inheriting its `left` while setting `right` stretches the chip across the card.
 */
.badge--sample {
  background: var(--warning-bg);
  color: var(--warning);
  border: 1px dashed var(--warning);
}
.property-card__media .badge--sample {
  left: auto;
  right: var(--sp-3);
  background: var(--warning-bg);
  box-shadow: none;
}

.empty-state {
  padding: var(--sp-8) var(--sp-5);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
  background: var(--surface);
  text-align: center;
}
.empty-state h3 { font-size: var(--step-2); }
.empty-state p { max-width: 52ch; margin-inline: auto; color: var(--text-muted); }

/* =============================================================================
   Listing detail
   ============================================================================= */

.listing-header__price {
  font-family: var(--font-display);
  font-size: var(--step-4);
  font-variant-numeric: tabular-nums;
}
.listing-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: var(--sp-3);
  list-style: none;
  margin: 0 0 var(--sp-6);
  padding: 0;
}
.listing-gallery li { margin: 0; }
.listing-gallery img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: var(--radius);
  display: block;
}
.listing-gallery li:first-child { grid-column: 1 / -1; }
.listing-gallery li:first-child img { aspect-ratio: 16 / 9; }

.spec-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr));
  gap: var(--sp-4);
  margin: 0 0 var(--sp-6);
}
.spec-list div { min-width: 0; }
.spec-list dt {
  font-size: var(--step--1);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0;
}
.spec-list dd {
  margin: var(--sp-1) 0 0;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* =============================================================================
   Forms
   ============================================================================= */

.form-wrap { max-width: 44rem; }
.form { container-type: inline-size; }
.form__honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.fieldset {
  margin: 0 0 var(--sp-6);
  padding: var(--sp-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  min-width: 0;
}
.fieldset__legend {
  padding-inline: var(--sp-2);
  margin-left: calc(var(--sp-2) * -1);
  font-family: var(--font-display);
  font-size: var(--step-1);
  font-weight: 600;
}
.fieldset__hint {
  color: var(--text-muted);
  font-size: var(--step--1);
  margin-bottom: var(--sp-5);
  max-width: 62ch;
}

.field { margin-bottom: var(--sp-5); min-width: 0; }
.field__label {
  display: block;
  margin-bottom: var(--sp-2);
  font-weight: 600;
  font-size: var(--step--1);
}
.field__req { color: var(--danger); }
.field__opt { color: var(--text-muted); font-weight: 400; }
.field__hint {
  margin: var(--sp-2) 0 0;
  color: var(--text-muted);
  font-size: var(--step--1);
  max-width: 62ch;
}

.field input,
.field select,
.field textarea {
  width: 100%;
  min-height: 2.75rem;
  padding: var(--sp-3);
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  font: inherit;
  font-size: var(--step-0);
  transition: border-color var(--transition), box-shadow var(--transition);
}
.field textarea { min-height: 8rem; resize: vertical; }
.field select {
  /* Windows dark mode renders native selects unreadable without both of these. */
  background-color: var(--surface);
  color: var(--text);
  appearance: none;
  padding-right: var(--sp-7);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 1.15rem center, right 0.85rem center;
  background-size: 0.35rem 0.35rem, 0.35rem 0.35rem;
  background-repeat: no-repeat;
}
.field input:hover,
.field select:hover,
.field textarea:hover { border-color: var(--border-strong); }
.field input:focus,
.field select:focus,
.field textarea:focus {
  /*
   * Brass, not a structural grey. --brand-600 measured 1.4:1 against --surface on this
   * palette - an invisible focus ring on the most important control on the site.
   */
  border-color: var(--accent-600);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-600) 28%, transparent);
}
.field input[aria-invalid="true"],
.field select[aria-invalid="true"],
.field textarea[aria-invalid="true"] { border-color: var(--danger); }

.field__error:empty { display: none; }
.field__error {
  margin: var(--sp-2) 0 0;
  color: var(--danger);
  font-size: var(--step--1);
  font-weight: 500;
}

.check {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
}
.check input[type="checkbox"] {
  flex: none;
  width: 1.15rem;
  height: 1.15rem;
  min-height: 0;
  margin-top: 0.28em;
  accent-color: var(--accent-500);
}
.check label {
  font-weight: 400;
  font-size: var(--step-0);
  cursor: pointer;
  max-width: 62ch;
}

.field-row {
  display: grid;
  gap: 0 var(--sp-4);
  grid-template-columns: 1fr;
  align-items: start;
}
@container (min-width: 32rem) {
  .field-row--2 { grid-template-columns: 1fr 1fr; }
  .field-row--3 { grid-template-columns: repeat(3, 1fr); }
}

.form__submit { margin-top: var(--sp-6); }
.form__status { margin-top: var(--sp-4); }
.form__status:empty { display: none; }

.alert {
  padding: var(--sp-4) var(--sp-5);
  border: 1px solid var(--border);
  border-left: 3px solid var(--brand-500);
  border-radius: var(--radius);
  background: var(--surface);
}
.alert > :last-child { margin-bottom: 0; }
.alert__title { font-size: var(--step-1); margin-bottom: var(--sp-2); }
.alert--success { border-left-color: var(--success); background: var(--success-bg); }
.alert--error { border-left-color: var(--danger); background: var(--danger-bg); }
.alert--warning { border-left-color: var(--warning); background: var(--warning-bg); }

.is-busy { position: relative; }

/* Upload control, shown only when Firebase Storage is switched on. */
.upload[hidden] { display: none !important; }

/* =============================================================================
   CTA band and footer
   ============================================================================= */

.cta-band {
  background: var(--brand-700);
  color: var(--text-invert);
  padding-block: var(--sp-8);
}
.cta-band__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-6);
}
.cta-band__inner > div:first-child { flex: 1 1 24rem; min-width: 0; }
.cta-band__title { font-size: var(--step-3); margin-bottom: var(--sp-3); }
.cta-band__body { color: var(--text-invert-muted); max-width: 54ch; margin: 0; }
.cta-band .btn-row { margin-top: 0; }

.site-footer {
  background: var(--surface-invert);
  color: var(--text-invert-muted);
  padding-block: var(--sp-8) var(--sp-6);
  padding-bottom: max(var(--sp-6), env(safe-area-inset-bottom));
  font-size: var(--step--1);
}
.site-footer a { color: var(--text-invert); text-decoration: none; }
.site-footer a:hover { color: var(--accent-on-dark); text-decoration: underline; }
.site-footer__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
  gap: var(--sp-6);
}
.site-footer__col--brand { grid-column: span 1; min-width: 0; }
@media (min-width: 64rem) {
  .site-footer__col--brand { grid-column: span 1; padding-right: var(--sp-6); }
}
.site-footer__tagline { margin: var(--sp-4) 0; max-width: 34ch; }
.site-footer__contact { font-style: normal; }
.site-footer__contact p { margin: 0 0 var(--sp-2); }
.site-footer__heading {
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--text-invert);
  margin-bottom: var(--sp-4);
}
.link-list { list-style: none; margin: 0; padding: 0; }
.link-list li { margin-bottom: var(--sp-2); }
.link-list--inline { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); }
.link-list--inline li { margin: 0; }
.site-footer__grid--secondary {
  margin-top: var(--sp-7);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--border-invert);
}
.site-footer__legal {
  margin-top: var(--sp-6);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--border-invert);
}
.site-footer__legal p { margin: 0 0 var(--sp-2); }
.site-footer .muted { color: var(--text-invert-muted); }
.site-footer .placeholder { color: var(--warning); }

/* =============================================================================
   Breadcrumbs, split layouts
   ============================================================================= */

.breadcrumbs { margin-bottom: var(--sp-4); font-size: var(--step--1); }
.breadcrumbs ol {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  list-style: none;
  margin: 0;
  padding: 0;
  color: var(--text-muted);
}
.breadcrumbs li + li::before { content: "/"; margin-right: var(--sp-2); color: var(--border-strong); }

.split {
  display: grid;
  gap: var(--sp-7);
  align-items: start;
}
@media (min-width: 60rem) {
  .split { grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); gap: var(--sp-8); }
  .split--sidebar-left { grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr); }
}
.sidebar {
  position: sticky;
  top: calc(var(--header-h) + var(--sp-5));
  padding: var(--sp-5);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.sidebar > :last-child { margin-bottom: 0; }
/* A sidebar heading is a label for a panel, not a page-level heading. */
.sidebar :is(h2, h3) { font-size: var(--step-1); margin-bottom: var(--sp-3); }
@media (max-width: 59.99rem) {
  .sidebar { position: static; }
}

/* =============================================================================
   Blog
   ============================================================================= */

.post-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 19rem), 1fr));
  gap: var(--sp-5);
  list-style: none;
  margin: 0;
  padding: 0;
}
.post-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
  color: var(--text-muted);
  font-size: var(--step--1);
  margin-bottom: var(--sp-5);
}
.post-body { max-width: var(--prose-max); }

/* =============================================================================
   Motion primitives

   Scroll-reveal is opt-in per element via data-reveal, and it is DISABLED BY DEFAULT
   in CSS. site/js/reveal.js adds `js-reveal` to <html> before first paint, which is
   what arms it. So with no JavaScript - or if the script fails - every element is
   simply visible, at full opacity, in its final position. There is no state in which
   content is hidden waiting for a script that never arrives.

   prefers-reduced-motion switches the whole thing off, including for people who have
   JS enabled: the reveal becomes an instant appearance rather than a transform.
   ============================================================================= */

.js-reveal [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity var(--transition-slow),
    transform var(--transition-slow);
}
.js-reveal [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
}

/* Children stagger in sequence rather than all at once. */
.js-reveal [data-reveal-stagger] > * {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity var(--transition-slow),
    transform var(--transition-slow);
}
.js-reveal [data-reveal-stagger].is-revealed > * {
  opacity: 1;
  transform: none;
}
.js-reveal [data-reveal-stagger].is-revealed > :nth-child(1) { transition-delay: 0ms; }
.js-reveal [data-reveal-stagger].is-revealed > :nth-child(2) { transition-delay: 70ms; }
.js-reveal [data-reveal-stagger].is-revealed > :nth-child(3) { transition-delay: 140ms; }
.js-reveal [data-reveal-stagger].is-revealed > :nth-child(4) { transition-delay: 210ms; }
.js-reveal [data-reveal-stagger].is-revealed > :nth-child(5) { transition-delay: 280ms; }
.js-reveal [data-reveal-stagger].is-revealed > :nth-child(6) { transition-delay: 350ms; }

@media (prefers-reduced-motion: reduce) {
  .js-reveal [data-reveal],
  .js-reveal [data-reveal-stagger] > * {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* =============================================================================
   Header, elevated

   The header starts transparent over the hero and gains its surface and hairline
   once the page scrolls. site/js/header.js toggles `is-stuck`; with no JS the
   header keeps its solid state permanently, which is the safe end of the switch.
   ============================================================================= */

.site-header {
  transition:
    background-color var(--transition-med),
    box-shadow var(--transition-med),
    border-color var(--transition-med);
}
.js-header .site-header {
  background: transparent;
  border-bottom-color: transparent;
  backdrop-filter: none;
}
.js-header .site-header.is-stuck {
  background: color-mix(in srgb, var(--paper) 82%, transparent);
  backdrop-filter: saturate(1.6) blur(14px);
  border-bottom-color: var(--border);
  box-shadow: var(--shadow-sm);
}

/* =============================================================================
   Hero, elevated

   Still a split hero, not full-bleed, and deliberately. The source photographs top
   out at about 1023px wide (Facebook copies, not originals - notes/photo-audit.md),
   so stretching one behind the full width of a 1440px viewport would render visibly
   soft. Nothing reads cheaper than a blurry hero. At roughly half the width it stays
   sharp, and the depth comes from layering instead: a lifted photo card, a metric
   card overlapping its corner, and a soft field of colour behind both.
   ============================================================================= */

.hero {
  padding-block: var(--sp-8) var(--sp-9);
}
.hero__title {
  font-size: var(--step-6);
  letter-spacing: 0;
  line-height: 1.02;
  max-width: 15ch;
}
.hero__lead {
  font-size: var(--step-1);
  line-height: 1.6;
  max-width: 46ch;
}

/* The eyebrow gets a rule and a dot, so it reads as a label rather than small text. */
.hero .eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-4) var(--sp-2) var(--sp-3);
  border: 1px solid var(--border);
  border-radius: 999px;
  background: color-mix(in srgb, var(--surface) 70%, transparent);
  backdrop-filter: blur(6px);
  box-shadow: var(--shadow-sm);
  letter-spacing: 0;
}
.hero .eyebrow::before {
  content: "";
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: var(--accent-500);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-500) 22%, transparent);
}

.hero__media {
  position: relative;
  /*
   * overflow must be VISIBLE here - the base rule clips it, which cuts the floating
   * metric card off at the photo's edge and destroys the whole effect. The rounded
   * corners move onto the image itself instead, which is the only child that needs
   * clipping.
   */
  overflow: visible;
  outline: none;
  box-shadow: var(--shadow-xl);
  border-radius: var(--radius-xl);
}
.hero__media img {
  border-radius: var(--radius-xl);
  /* Light, not dark: a near-black hairline on a near-black page is invisible. */
  outline: 1px solid color-mix(in srgb, var(--brand-900) 10%, transparent);
  outline-offset: -1px;
}

/*
 * A single metric, lifted off the photograph's corner. This is the piece that does
 * most of the "expensive" work: one element breaking the boundary of another creates
 * depth that no amount of shadow on a flat grid will.
 */
.hero__float {
  position: absolute;
  left: calc(var(--sp-5) * -1);
  bottom: calc(var(--sp-6) * -1);
  z-index: 2;
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-float);
  max-width: min(20rem, 78%);
}
.hero__float-value {
  font-size: var(--step-3);
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0;
  color: var(--text-heading);
  font-variant-numeric: tabular-nums;
}
.hero__float-label {
  font-size: var(--step--1);
  color: var(--text-muted);
  line-height: 1.35;
  text-wrap: pretty;
}
.hero__float-rule {
  width: 1px;
  align-self: stretch;
  background: var(--border);
}

@media (max-width: 47.99rem) {
  /* Below the split breakpoint the card would hang off the screen edge. */
  .hero__float {
    left: var(--sp-4);
    right: var(--sp-4);
    bottom: calc(var(--sp-5) * -1);
    max-width: none;
  }
  .hero { padding-bottom: var(--sp-9); }
}

/* =============================================================================
   Trust bar
   ============================================================================= */

.trust-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-4) var(--sp-6);
  margin-top: var(--sp-9);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--border);
  list-style: none;
  padding-inline: 0;
}
.trust-bar__item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-size: var(--step--1);
  font-weight: 500;
  color: var(--text-muted);
}
.trust-bar__item .icon {
  width: 1.15rem;
  height: 1.15rem;
  color: var(--accent-ink);
  flex: none;
}

/* =============================================================================
   Metrics band
   ============================================================================= */

.metrics {
  background: var(--surface-invert);
  border-block: 0;
  color: var(--text-invert);
  padding-block: var(--sp-8);
  position: relative;
  overflow: hidden;
}
.metrics::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 60% 70% at 12% 0%, color-mix(in srgb, var(--accent-600) 18%, transparent), transparent 70%),
    radial-gradient(ellipse 50% 60% at 100% 100%, color-mix(in srgb, var(--accent-700) 14%, transparent), transparent 65%);
  pointer-events: none;
}
.metrics > * { position: relative; z-index: 1; }
.metrics__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
  gap: var(--sp-6);
  list-style: none;
  margin: 0;
  padding: 0;
}
.metrics__item { min-width: 0; }
.metrics__value {
  color: var(--text-invert);
  display: block;
  font-size: var(--step-4);
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  margin-bottom: var(--sp-2);
}
.metrics__label {
  display: block;
  font-size: var(--step--1);
  color: var(--text-invert-muted);
  text-wrap: pretty;
}

/* =============================================================================
   Section headers
   ============================================================================= */

.section__eyebrow {
  display: block;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--accent-ink);
  margin-bottom: var(--sp-3);
}
.section__title { letter-spacing: 0; }

/* =============================================================================
   Cards, elevated
   ============================================================================= */

.card {
  padding: var(--sp-6);
  border-radius: var(--radius-xl);
  overflow: hidden;
  transition:
    border-color var(--transition-med),
    box-shadow var(--transition-med),
    transform var(--transition-med);
}
/*
 * A hairline of brand colour that wipes across the top edge on hover. It is a
 * pseudo-element rather than a border so it can animate without shifting layout.
 */
.card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, var(--accent-600), var(--accent-ink));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--transition-med);
}
.card:has(.card__link:hover),
.card:has(.card__link:focus-visible) {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
}
.card:has(.card__link:hover)::before,
.card:has(.card__link:focus-visible)::before { transform: scaleX(1); }
.card__title { letter-spacing: 0; }

/* =============================================================================
   Property cards, elevated
   ============================================================================= */

.property-card {
  border-radius: var(--radius-xl);
  transition:
    border-color var(--transition-med),
    box-shadow var(--transition-med),
    transform var(--transition-med);
}
.property-card:has(a:hover),
.property-card:has(a:focus-visible) {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}
.property-card__media { overflow: hidden; }
.property-card__media img { transition: transform var(--transition-slow); }
.property-card:has(a:hover) .property-card__media img { transform: scale(1.045); }

/* =============================================================================
   Buttons, elevated
   ============================================================================= */

.btn--primary {
  box-shadow:
    0 1px 2px rgb(10 35 66 / 0.16),
    inset 0 1px 0 rgb(255 255 255 / 0.14);
}
.btn--primary:hover {
  box-shadow:
    0 4px 14px rgb(10 35 66 / 0.22),
    inset 0 1px 0 rgb(255 255 255 / 0.14);
  transform: translateY(-1px);
}
.btn--primary:active { transform: translateY(0); }
.btn--lg { border-radius: var(--radius-lg); }

/* =============================================================================
   Testimonials
   ============================================================================= */

.quotes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
  gap: var(--sp-5);
  list-style: none;
  margin: 0;
  padding: 0;
}
.quote {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  min-width: 0;
  padding: var(--sp-6);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
}
.quote__mark {
  font-size: var(--step-4);
  line-height: 0.6;
  color: var(--accent-500);
  font-weight: 700;
}
.quote__text {
  margin: 0;
  font-size: var(--step-1);
  line-height: 1.55;
  letter-spacing: 0;
  text-wrap: pretty;
}
.quote__who {
  margin: auto 0 0;
  padding-top: var(--sp-3);
  border-top: 1px solid var(--border);
  font-size: var(--step--1);
  color: var(--text-muted);
}
.quote__who strong { color: var(--text); font-weight: 600; }

/* =============================================================================
   Photo band, elevated
   ============================================================================= */

.photo-band__item {
  border-radius: var(--radius-xl);
  transition: transform var(--transition-med), box-shadow var(--transition-med);
}
.photo-band__item img { transition: transform var(--transition-slow); }
.photo-band__item:hover { box-shadow: var(--shadow-lg); }
.photo-band__item:hover img { transform: scale(1.04); }

/* =============================================================================
   Figures and sidebars
   ============================================================================= */

.figure img { border-radius: var(--radius-xl); }
.sidebar { border-radius: var(--radius-xl); }
.fieldset { border-radius: var(--radius-xl); }
.empty-state { border-radius: var(--radius-xl); }
.service { border-radius: var(--radius-xl); }
.service__summary { border-radius: var(--radius-xl); }

/* =============================================================================
   Premium operating-system pass
   ============================================================================= */

:where(h1, h2, h3, h4, .hero__title, .page-hero__title, .section__title, .card__title, .metrics__value, .quote__text) {
  letter-spacing: 0;
}

.section--flush {
  padding-block: 0;
}

.hero {
  padding-block: clamp(5rem, 7vw, 7.75rem) var(--sp-9);
}

.hero__inner {
  align-items: center;
}

@media (min-width: 60rem) {
  .hero__inner {
    grid-template-columns: minmax(0, 1.04fr) minmax(25rem, 0.82fr);
    gap: var(--sp-9);
  }
}

.hero__title {
  max-width: 18ch;
}

.hero__lead {
  max-width: 50ch;
}

.hero__media::before {
  content: "";
  position: absolute;
  inset: auto -1rem -1rem 18%;
  height: 2.35rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--brand-800) 12%, transparent);
  filter: blur(18px);
  z-index: -1;
}

.trust-bar {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
  gap: var(--sp-3);
  border-top: 0;
  padding: var(--sp-3);
  margin-top: var(--sp-8);
  background: color-mix(in srgb, var(--surface) 84%, transparent);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
}

.trust-bar__item {
  min-width: 0;
  padding: var(--sp-3);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--brand-50) 58%, transparent);
}

.operating-system {
  display: grid;
  gap: var(--sp-6);
  align-items: stretch;
}

@media (min-width: 64rem) {
  .operating-system {
    grid-template-columns: minmax(22rem, 0.9fr) minmax(0, 1.15fr);
  }
}

.operating-panel {
  position: relative;
  min-width: 0;
  padding: var(--sp-6);
  background:
    linear-gradient(145deg, color-mix(in srgb, var(--brand-900) 94%, black), var(--brand-800));
  color: var(--text-invert);
  border-radius: var(--radius-xl);
  border: 1px solid color-mix(in srgb, var(--accent-500) 22%, transparent);
  box-shadow: var(--shadow-xl);
  overflow: hidden;
}

.operating-panel::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: linear-gradient(color-mix(in srgb, var(--text-invert) 8%, transparent) 1px, transparent 1px);
  background-size: 100% 3.6rem;
  pointer-events: none;
}

.operating-panel__kicker {
  position: relative;
  z-index: 1;
  margin: 0 0 var(--sp-5);
  color: var(--accent-on-dark);
  font-size: var(--step--1);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0;
}

.operating-steps {
  position: relative;
  z-index: 1;
  display: grid;
  gap: var(--sp-3);
  list-style: none;
  margin: 0;
  padding: 0;
}

.operating-steps li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--sp-2) var(--sp-4);
  align-items: start;
  padding: var(--sp-4);
  background: rgb(255 255 255 / 0.075);
  border: 1px solid rgb(255 255 255 / 0.14);
  border-radius: var(--radius-lg);
}

.operating-steps span {
  grid-row: span 2;
  display: grid;
  place-items: center;
  width: 2.35rem;
  height: 2.35rem;
  border-radius: 50%;
  background: var(--accent-on-dark);
  color: var(--brand-900);
  font-size: var(--step--1);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.operating-steps strong {
  color: var(--text-invert);
  line-height: 1.2;
}

.operating-steps small {
  color: var(--text-invert-muted);
  line-height: 1.45;
}

.signal-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: var(--sp-4);
}

.signal-grid .card {
  min-height: 100%;
}

.card,
.property-card,
.sidebar,
.filters,
.empty-state,
.quote {
  box-shadow: var(--shadow);
}

.card {
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--surface) 98%, var(--brand-50)), var(--surface));
}

.card:not(:has(.card__link)):hover {
  border-color: var(--accent-700);
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
}

.section--sunken {
  background:
    linear-gradient(180deg, var(--surface-sunken), color-mix(in srgb, var(--surface-sunken) 72%, var(--paper)));
}

.page-hero {
  padding-block: var(--sp-8);
}

.page-hero .btn-row,
.hero .btn-row {
  gap: var(--sp-3);
}

@media (max-width: 40rem) {
  .hero__title {
    max-width: 11ch;
  }

  .hero .btn-row,
  .page-hero .btn-row,
  .cta-band .btn-row {
    width: 100%;
  }

  .hero .btn,
  .page-hero .btn,
  .cta-band .btn {
    width: 100%;
  }

  .operating-panel,
  .card,
  .quote,
  .sidebar {
    border-radius: var(--radius-lg);
  }
}
