/*
 * Project site theme. One stylesheet for every project: premium, image-led, calm. Everything is
 * driven by the --pj-* custom properties, so a different ProjectBranding palette / font pair
 * restyles the whole site without touching this file.
 *
 * Rules for this file (see CONTENT-CONTRACT.md):
 *  - colours and fonts come only from the --pj-* branding properties Views/Layout.cshtml emits
 *    from the ProjectBranding settings, plus the layout tokens and color-mix() tints defined below;
 *  - no !important on the padding, width or text-align of sections: those belong to the editor
 *    (ContentBannerCommon / Content Block Styling padding, LayoutOptions TextAlign / ContentWidth /
 *    Columns / Width Options). The few !important declarations here beat base-theme !important
 *    rules on things the editor does not control (the base container's fixed 1136px width and 12px
 *    gutter, the p-2 / w-100 utilities NavButton puts on every button, inline background colours
 *    under a brand background class) and each one says so;
 *  - style variants are opt-in classes (LayoutOptions.CssClass); the only structural assumption is
 *    the page hero (LayoutOptions.Anchor "page-hero"), which the generator puts first on a page.
 *
 * Sections: tokens · base + type · buttons · header · page hero · sections (flow content) ·
 * variants (split, band, contact, backgrounds) · project widgets · forms · footer · motion.
 */

/* ================================================================ tokens */
/* Branding tokens from the Layout (<style id="pj-branding">): --pj-primary, --pj-secondary,
   --pj-accent, --pj-surface, --pj-text, their -rgb triplets, --pj-on-primary / --pj-on-secondary /
   --pj-on-accent, --pj-font-heading, --pj-font-body. Layout also emits --pj-logo-primary /
   --pj-logo-reversed (url()) when those logos are set. Everything else derives from them. */
:root {
  /* layout */
  --pj-nav-h: 64px;
  --pj-gutter: 1.25rem;
  --pj-max: 76rem;          /* Standard width (Width Options "Standard") */
  --pj-max-wide: 96rem;     /* Wide (Width Options "Wide") */
  --pj-narrow: 46rem;       /* reading measure for prose; ContentWidth "narrow" */
  --pj-measure: var(--pj-narrow);
  --pj-block-space: clamp(4rem, 2.75rem + 5vw, 8rem);

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

  /* shape */
  --pj-radius: 6px;         /* cards, frames */
  --pj-radius-sm: 4px;      /* images, chips inside cards */
  --pj-radius-lg: 14px;     /* floating card, form card */
  --pj-radius-btn: 8px;     /* every button (999px = pill buttons) */
  --pj-radius-field: min(var(--pj-radius-btn), 8px); /* inputs, selects, textareas: follows a smaller button radius, but pill buttons keep 8px fields */
  --pj-btn-h: 52px;
  --pj-btn-h-sm: 44px;

  /* type */
  --pj-fs-body: 1.0625rem;  /* 17px; 18px from 992px */
  --pj-lh-body: 1.65;
  --pj-fs-small: 0.875rem;
  --pj-fs-xs: 0.75rem;
  --pj-fs-lead: clamp(1.125rem, 1rem + 0.45vw, 1.375rem);
  --pj-fs-h1: clamp(2.75rem, 1.85rem + 3.6vw, 4.5rem);
  --pj-fs-h2: clamp(2.125rem, 1.45rem + 2.6vw, 3.5rem);
  --pj-fs-h3: clamp(1.375rem, 1.2rem + 0.7vw, 1.75rem);
  --pj-fs-h4: 1.25rem;
  --pj-heading-weight: 500;
  --pj-heading-lh: 1.08;
  --pj-heading-tracking: -0.015em;
  --pj-eyebrow-tracking: 0.18em;

  /* derived colours (color-mix from the branding tokens) */
  --pj-paper: color-mix(in srgb, #fff 72%, var(--pj-surface));
  --pj-heading: var(--pj-primary);
  --pj-muted: color-mix(in srgb, var(--pj-text) 72%, var(--pj-surface));
  --pj-line: color-mix(in srgb, var(--pj-text) 14%, var(--pj-surface));
  --pj-line-strong: color-mix(in srgb, var(--pj-text) 32%, var(--pj-surface));
  --pj-surface-alt: color-mix(in srgb, var(--pj-primary) 5%, var(--pj-surface));
  --pj-surface-tint: color-mix(in srgb, var(--pj-secondary) 13%, var(--pj-surface));
  --pj-primary-dark: color-mix(in srgb, var(--pj-primary) 80%, #000);
  --pj-primary-soft: color-mix(in srgb, var(--pj-primary) 10%, var(--pj-surface));
  --pj-accent-dark: color-mix(in srgb, var(--pj-accent) 82%, #000);
  --pj-link: color-mix(in srgb, var(--pj-accent) 78%, var(--pj-text));
  --pj-link-hover: var(--pj-primary);
  --pj-focus: var(--pj-accent);
  --pj-shadow: 0 1px 2px rgb(var(--pj-text-rgb) / 0.06), 0 12px 32px rgb(var(--pj-text-rgb) / 0.12);
  --pj-shadow-lg: 0 2px 4px rgb(var(--pj-text-rgb) / 0.08), 0 24px 56px rgb(var(--pj-text-rgb) / 0.18);

  /* hero overlay: a wash of the primary colour so white type always reads */
  --pj-overlay-rgb: var(--pj-primary-rgb);
  --pj-on-overlay: #fff;

  /* buttons (redefined per context: dark sections, hero) */
  --pj-btn-bg: var(--pj-primary);
  --pj-btn-fg: var(--pj-on-primary);
  --pj-btn-bg-hover: var(--pj-primary-dark);
  --pj-btn-line: var(--pj-primary);

  /* lot status chips, from the brand: available = secondary, under offer = accent tint,
     reserved = primary tint, sold = muted grey, coming soon / not released = outline,
     future release = dashed outline. Any other status (added in the admin) is a neutral tint:
     --pj-status-other / -other-line with --pj-status-ink. */
  --pj-status-available: var(--pj-secondary);
  --pj-status-available-ink: var(--pj-on-secondary);
  --pj-status-under-offer: color-mix(in srgb, var(--pj-accent) 15%, var(--pj-surface));
  --pj-status-under-offer-ink: color-mix(in srgb, var(--pj-accent) 72%, var(--pj-text));
  --pj-status-reserved: color-mix(in srgb, var(--pj-primary) 12%, var(--pj-surface));
  --pj-status-reserved-ink: color-mix(in srgb, var(--pj-primary) 80%, var(--pj-text));
  --pj-status-sold: color-mix(in srgb, var(--pj-text) 8%, var(--pj-surface));
  --pj-status-sold-ink: var(--pj-muted);
  --pj-status-coming-soon: color-mix(in srgb, var(--pj-primary) 55%, var(--pj-surface));
  --pj-status-coming-soon-ink: var(--pj-primary);
  --pj-status-future-release: color-mix(in srgb, var(--pj-primary) 40%, var(--pj-surface));
  --pj-status-future-release-ink: color-mix(in srgb, var(--pj-primary) 60%, var(--pj-muted));
  --pj-status-not-released: var(--pj-line-strong);
  --pj-status-not-released-ink: var(--pj-muted);
  --pj-status-ink: var(--pj-text);
  --pj-status-other: color-mix(in srgb, var(--pj-text) 4%, var(--pj-surface));
  --pj-status-other-line: var(--pj-line-strong);

  /* spec icons (floor plan cards): stroke icons used as masks, so they take currentColor */
  --pj-icon-beds: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 19V6M3 15h18v4M21 15v-3a3 3 0 0 0-3-3h-7v6'/%3E%3Ccircle cx='7' cy='11.5' r='1.6'/%3E%3C/svg%3E");
  --pj-icon-baths: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 12h18v2a5 5 0 0 1-5 5H8a5 5 0 0 1-5-5z'/%3E%3Cpath d='M6 12V6.5a2.5 2.5 0 0 1 4.8-1M7 19l-1 2M17 19l1 2'/%3E%3C/svg%3E");
  --pj-icon-parking: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 17v-4l2.2-5.2A2 2 0 0 1 7 6.5h10a2 2 0 0 1 1.8 1.3L21 13v4zM3 17v2h3v-2M18 17v2h3v-2M3 13h18'/%3E%3Ccircle cx='7.5' cy='15' r='.6'/%3E%3Ccircle cx='16.5' cy='15' r='.6'/%3E%3C/svg%3E");
  --pj-icon-area: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5'/%3E%3Crect x='8' y='8' width='8' height='8' rx='1'/%3E%3C/svg%3E");
}
@media (min-width: 768px) {
  :root { --pj-gutter: 2rem; }
}
@media (min-width: 992px) {
  :root { --pj-nav-h: 76px; --pj-gutter: 2.5rem; --pj-fs-body: 1.125rem; }
}

/* Dark contexts (brand backgrounds, photo hero, footer): text, lines and buttons follow the
   section's own foreground colour, so a light or a dark brand colour both work. */
:is(.pj-bg-primary, .pj-bg-secondary, .pj-bg-accent, .pj-bg-dark, .pj-on-dark) {
  --pj-heading: currentColor;
  --pj-muted: color-mix(in srgb, currentColor 78%, transparent);
  --pj-line: color-mix(in srgb, currentColor 22%, transparent);
  --pj-line-strong: color-mix(in srgb, currentColor 45%, transparent);
  --pj-link: currentColor;
  --pj-link-hover: currentColor;
  --pj-focus: currentColor;
}
.pj-bg-primary, .pj-bg-dark { --pj-btn-bg: var(--pj-on-primary); --pj-btn-fg: var(--pj-primary); --pj-btn-bg-hover: color-mix(in srgb, var(--pj-on-primary) 86%, var(--pj-primary)); --pj-btn-line: var(--pj-on-primary); }
.pj-bg-secondary { --pj-btn-bg: var(--pj-on-secondary); --pj-btn-fg: var(--pj-secondary); --pj-btn-bg-hover: color-mix(in srgb, var(--pj-on-secondary) 86%, var(--pj-secondary)); --pj-btn-line: var(--pj-on-secondary); }
.pj-bg-accent { --pj-btn-bg: var(--pj-on-accent); --pj-btn-fg: var(--pj-accent); --pj-btn-bg-hover: color-mix(in srgb, var(--pj-on-accent) 86%, var(--pj-accent)); --pj-btn-line: var(--pj-on-accent); }
.pj-on-dark { --pj-btn-bg: #fff; --pj-btn-fg: var(--pj-primary); --pj-btn-bg-hover: color-mix(in srgb, #fff 86%, var(--pj-primary)); --pj-btn-line: #fff; }
/* .pj-btn-inverse (any section): white buttons with primary text, whatever the band's own --pj-on-*
   colour is (e.g. a mid-grey call-to-action band whose computed foreground would be dark). After the
   band rules above, so it wins at the same specificity. */
.pj-btn-inverse { --pj-btn-bg: #fff; --pj-btn-fg: var(--pj-primary); --pj-btn-bg-hover: color-mix(in srgb, #fff 86%, var(--pj-primary)); --pj-btn-line: #fff; }

/* ================================================================ base + type */
html { scroll-padding-top: var(--pj-nav-h); }
@media (prefers-reduced-motion: no-preference) {
  html:has(body.pj) { scroll-behavior: smooth; }
}
body.pj {
  background: var(--pj-surface);
  color: var(--pj-text);
  font-family: var(--pj-font-body);
  font-size: var(--pj-fs-body);
  line-height: var(--pj-lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
/* The base bundle sets its own families on buttons, form controls and table cells. */
body.pj :is(p, li, dd, dt, a, button, input, select, textarea, label, legend, td, th, figcaption, blockquote, .block-paragraph) {
  font-family: inherit;
}
body.pj :is(h1, h2, h3, h4, h5, .h1, .h2, .h3, .h4, .h5) {
  font-family: var(--pj-font-heading);
  font-weight: var(--pj-heading-weight);
  line-height: var(--pj-heading-lh);
  letter-spacing: var(--pj-heading-tracking);
  color: var(--pj-heading);
  text-transform: none;
  text-wrap: balance;
}
body.pj :is(h1, .h1) { font-size: var(--pj-fs-h1); }
body.pj :is(h2, .h2) { font-size: var(--pj-fs-h2); }
body.pj :is(h3, .h3) { font-size: var(--pj-fs-h3); line-height: 1.2; letter-spacing: -0.01em; }
body.pj :is(h4, .h4) { font-size: var(--pj-fs-h4); line-height: 1.3; letter-spacing: 0; }
body.pj :is(h5, .h5) { font-size: 1.0625rem; line-height: 1.35; letter-spacing: 0; }
/* H6 is the eyebrow: small, tracked capitals above a heading. Also .pj-eyebrow for inline HTML. */
body.pj :is(h6, .h6, .pj-eyebrow) {
  display: block;
  font-family: var(--pj-font-body);
  font-size: var(--pj-fs-small);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: var(--pj-eyebrow-tracking);
  text-transform: uppercase;
  color: var(--pj-muted);
}
body.pj p { margin: 0 0 1em; text-wrap: pretty; }
body.pj .pj-lead { font-size: var(--pj-fs-lead); line-height: 1.55; }
body.pj strong, body.pj b { font-weight: 600; }
body.pj a { color: var(--pj-link); text-decoration-thickness: 1px; text-underline-offset: 0.2em; }
body.pj a:hover { color: var(--pj-link-hover); }
body.pj :focus-visible { outline: 2px solid var(--pj-focus); outline-offset: 3px; border-radius: 2px; }
body.pj ::selection { background: color-mix(in srgb, var(--pj-secondary) 35%, transparent); }
body.pj img { max-width: 100%; }

.pj-skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 2000;
  padding: 0.75rem 1rem;
  background: var(--pj-primary);
  color: var(--pj-on-primary);
}
.pj-skip:focus { left: 1rem; top: 1rem; }

/* ================================================================ buttons */
/* One system: 52px (44px small), 8px radius, 2px border on every variant so solid and outline
   buttons line up. Solid = primary (NavButton styles stdbluebutton / stdbutton / submit, .pj-button),
   accent = stdredbutton* / .pj-button--accent, outline = stdwhitebutton* / .pj-button--ghost /
   .pj-button--outline. Inside a dark section every variant inverts (the --pj-btn-* tokens). The
   base NavButton markup is <a class="p-2 text-center w-100 {style}">: p-2 and w-100 are
   !important utilities, hence the !important on this button's own padding and width. */
body.pj :is(.pj-button, .stdbutton, .stdbluebutton, .stdsquarebluebutton, .stdbluebuttonwhiteborder, .stdredbutton, .stdredbutton-noround, .stdredbuttonwhiteborder, .stdwhitebutton, .stdwhitebuttonnoborder, .stdwhitebuttonblueborder, .stdsquarewhitebuttonblueborder, .btn-primary),
body.pj form :is(button[type="submit"], input[type="submit"]) {
  --_bg: var(--pj-btn-bg);
  --_fg: var(--pj-btn-fg);
  --_line: var(--_bg);
  --_bg-hover: var(--pj-btn-bg-hover);
  --_fg-hover: var(--_fg);
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  width: auto !important;
  min-height: var(--pj-btn-h);
  margin: 0;
  padding: 0 1.75rem !important;
  border: 2px solid var(--_line);
  border-radius: var(--pj-radius-btn) !important;
  background: var(--_bg);
  color: var(--_fg) !important;
  font-family: var(--pj-font-body);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.01em;
  text-align: center;
  text-decoration: none;
  text-transform: none;
  white-space: nowrap;
  box-shadow: none;
  cursor: pointer;
  transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}
body.pj :is(.pj-button, .stdbutton, .stdbluebutton, .stdsquarebluebutton, .stdbluebuttonwhiteborder, .stdredbutton, .stdredbutton-noround, .stdredbuttonwhiteborder, .stdwhitebutton, .stdwhitebuttonnoborder, .stdwhitebuttonblueborder, .stdsquarewhitebuttonblueborder, .btn-primary):is(:hover, :focus-visible),
body.pj form :is(button[type="submit"], input[type="submit"]):is(:hover, :focus-visible) {
  background: var(--_bg-hover);
  border-color: var(--_bg-hover);
  color: var(--_fg-hover) !important;
  text-decoration: none;
}
body.pj :is(.pj-button--accent, .stdredbutton, .stdredbutton-noround, .stdredbuttonwhiteborder) {
  --_bg: var(--pj-accent);
  --_fg: var(--pj-on-accent);
  --_bg-hover: var(--pj-accent-dark);
}
body.pj :is(.pj-button--ghost, .pj-button--outline, .stdwhitebutton, .stdwhitebuttonnoborder, .stdwhitebuttonblueborder, .stdsquarewhitebuttonblueborder) {
  --_bg: transparent;
  --_fg: var(--pj-btn-line);
  --_line: var(--pj-btn-line);
  --_bg-hover: var(--pj-btn-line);
  --_fg-hover: var(--pj-btn-fg);
}
body.pj :is(.pj-button--ghost, .pj-button--outline, .stdwhitebutton, .stdwhitebuttonnoborder, .stdwhitebuttonblueborder, .stdsquarewhitebuttonblueborder):is(:hover, :focus-visible) {
  border-color: var(--pj-btn-line);
}
body.pj .pj-button--small { min-height: var(--pj-btn-h-sm); padding: 0 1.1rem !important; font-size: 0.9375rem; }
/* Buttons in a flow sit side by side (each NavButton is its own flow column). */
body.pj .widget-row > .widget-column:has(> .pe-2 > a:only-child) { flex: 0 0 auto; width: auto; max-width: none; }
body.pj .widget-row > .widget-column > .pe-2:has(> a:only-child) { padding-right: 0.75rem; padding-top: 0.75rem; }
body.pj .widget-row > .widget-column > .pe-2 > img { display: none; }
/* In a centred section (TextAlign "center", .pj-intro) the buttons' row is centred too, as the text is. */
body.pj :is(.pj-center, .pj-intro) .widget-row:has(> .widget-column > .pe-2 > a:only-child) { justify-content: center; }
body.pj :is(.pj-center, .pj-intro) .widget-row > .widget-column > .pe-2:has(> a:only-child) { padding-left: 0.375rem; padding-right: 0.375rem; }

/* ================================================================ header */
/* Markup: Views/Layout.cshtml, Branding.cshtml, Menu.cshtml, ProjectMenuItem.cshtml. A slim
   fixed bar on --pj-surface. Over a photo page hero (first on the page) it starts transparent
   with light type and the reversed logo, and turns solid once the page scrolls (.pj-scrolled,
   project.js) or the mobile panel opens. */
body.pj #mainNav.pj-nav {
  height: var(--pj-nav-h);
  min-height: var(--pj-nav-h);
  background: var(--pj-surface);
  color: var(--pj-text);
  border-bottom: 1px solid transparent;
  z-index: 1030;
  transition: background-color 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease;
}
body.pj.pj-scrolled #mainNav.pj-nav { border-bottom-color: var(--pj-line); box-shadow: 0 6px 24px rgb(var(--pj-text-rgb) / 0.06); }
body.pj .mainwrapper { margin-top: var(--pj-nav-h); }

.pj-nav-inner {
  display: flex;
  align-items: center;
  height: 100%;
  max-width: var(--pj-max-wide);
  margin: 0 auto;
  padding: 0 var(--pj-gutter);
  gap: 1.5rem;
}
.pj-brand { flex: 0 0 auto; display: flex; align-items: center; height: 100%; }
body.pj .pj-logo-link { display: block; padding: 0; margin: 0; line-height: 0; color: var(--pj-heading); text-decoration: none; }
.pj-logo { display: block; height: calc(var(--pj-nav-h) - 26px); width: auto; max-width: 200px; object-fit: contain; object-position: left center; }
.pj-logo--reversed { display: none; }
.pj-logo-text { font-family: var(--pj-font-heading); font-size: 1.35rem; font-weight: var(--pj-heading-weight); line-height: 1.2; letter-spacing: 0.02em; }

.pj-nav-panel { flex: 1 1 auto; display: flex; align-items: center; justify-content: flex-end; gap: 1rem; }
.pj-menu { list-style: none; margin: 0; padding: 0; display: flex; align-items: center; }
.pj-menu-item { position: relative; }
body.pj .pj-menu-link {
  position: relative;
  display: block;
  padding: 0.5rem 0.85rem;
  color: inherit;
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  text-decoration: none;
  white-space: nowrap;
}
body.pj .pj-menu--main > .pj-menu-item > .pj-menu-link::after {
  content: "";
  position: absolute;
  left: 0.85rem;
  right: 0.85rem;
  bottom: 0.3rem;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.25s ease;
}
body.pj .pj-menu--main > .pj-menu-item > .pj-menu-link:is(:hover, :focus-visible)::after,
body.pj .pj-menu--main > .pj-current > .pj-menu-link::after { transform: scaleX(1); }
body.pj .pj-menu-link:hover, body.pj .pj-menu-link:focus-visible { color: inherit; }

.pj-sub-toggle { display: none; }
.pj-submenu {
  list-style: none;
  margin: 0;
  padding: 0.5rem;
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 14rem;
  background: var(--pj-surface);
  color: var(--pj-text);
  border: 1px solid var(--pj-line);
  border-radius: var(--pj-radius);
  box-shadow: var(--pj-shadow);
  visibility: hidden;
  opacity: 0;
  z-index: 10;
  transition: opacity 0.2s ease, visibility 0.2s;
}
.pj-menu-item:hover > .pj-submenu,
.pj-menu-item:focus-within > .pj-submenu { visibility: visible; opacity: 1; }
body.pj .pj-submenu .pj-menu-link { padding: 0.55rem 0.75rem; }

/* Right menu: the Enquire button, outlined in the header's own colour. */
body.pj .pj-menu--right > .pj-menu-item > .pj-menu-link {
  display: inline-flex;
  align-items: center;
  min-height: var(--pj-btn-h-sm);
  padding: 0 1.25rem;
  border: 2px solid currentColor;
  border-radius: var(--pj-radius-btn);
  color: var(--pj-primary);
  font-weight: 600;
  transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
body.pj .pj-menu--right > .pj-menu-item > .pj-menu-link:is(:hover, :focus-visible) {
  background: var(--pj-primary);
  border-color: var(--pj-primary);
  color: var(--pj-on-primary);
}

.pj-burger {
  display: none;
  width: 44px;
  height: 44px;
  padding: 14px 10px;
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
  flex-direction: column;
  justify-content: space-between;
}
.pj-burger span { display: block; height: 2px; width: 100%; background: currentColor; transition: transform 0.25s ease, opacity 0.2s ease; }
.pj-nav-open .pj-burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.pj-nav-open .pj-burger span:nth-child(2) { opacity: 0; }
.pj-nav-open .pj-burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 991.98px) {
  .pj-burger { display: flex; margin-left: auto; margin-right: -10px; }
  .pj-nav-panel {
    display: none;
    position: fixed;
    top: var(--pj-nav-h);
    left: 0;
    right: 0;
    bottom: 0;
    overflow-y: auto;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    padding: 1rem var(--pj-gutter) 2rem;
    background: var(--pj-surface);
    color: var(--pj-text);
    border-top: 1px solid var(--pj-line);
  }
  .pj-nav-open .pj-nav-panel { display: flex; }
  body.pj.pj-nav-open { overflow: hidden; }
  .pj-menu { flex-direction: column; align-items: stretch; }
  .pj-menu-item { display: flex; flex-wrap: wrap; align-items: center; border-bottom: 1px solid var(--pj-line); }
  body.pj .pj-menu--main .pj-menu-link { flex: 1 1 auto; padding: 1rem 0; font-family: var(--pj-font-heading); font-size: 1.375rem; letter-spacing: 0; }
  body.pj .pj-menu--main > .pj-menu-item > .pj-menu-link::after { display: none; }
  .pj-sub-toggle { display: block; flex: 0 0 44px; height: 44px; border: 0; background: transparent; color: inherit; }
  .pj-sub-toggle::before { content: ""; display: block; width: 10px; height: 10px; margin: 0 auto; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(45deg); transition: transform 0.2s ease; }
  .pj-menu-item.is-open > .pj-sub-toggle::before { transform: rotate(-135deg); }
  .pj-submenu { position: static; flex: 1 0 100%; display: none; visibility: visible; opacity: 1; box-shadow: none; border: 0; padding: 0 0 0.75rem 1rem; background: transparent; }
  body.pj .pj-submenu .pj-menu-link { font-size: 1.0625rem; font-family: var(--pj-font-body); padding: 0.6rem 0; }
  .pj-menu-item:hover > .pj-submenu,
  .pj-menu-item:focus-within > .pj-submenu { display: none; }
  .pj-menu-item.is-open > .pj-submenu { display: block; }
  .pj-menu--right { margin-top: 1.5rem; }
  body.pj .pj-menu--right > .pj-menu-item { border-bottom: 0; }
  body.pj .pj-menu--right > .pj-menu-item > .pj-menu-link { flex: 1 1 auto; justify-content: center; min-height: var(--pj-btn-h); background: var(--pj-primary); border-color: var(--pj-primary); color: var(--pj-on-primary); }
}

/* Over a photo hero. The page hero is a FlowBanner whose LayoutOptions.Anchor is "page-hero"
   (<a id="page-hero"> first in .contentbanner, then the BackgroundMediaBanner); it has a photo
   when a .media-box carries a background (--pb-bg-main) or there is a video. Only when that hero
   is the first thing on the page does the header sit over it. */
body.pj:has(.pj-page > .contentbanner:first-child > a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video), .pj-page > .pj-section:first-child > .contentbanner > a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video)) {
  & .mainwrapper { margin-top: 0; }
  & .contentbanner:has(> a#page-hero) > .masthead-media-container + div > div { padding-top: var(--pj-nav-h); }
  &:not(.pj-scrolled):not(.pj-nav-open) {
    & #mainNav.pj-nav {
      background: transparent;
      border-bottom-color: transparent;
      box-shadow: none;
      color: var(--pj-on-overlay);
    }
    & #mainNav .pj-logo-link { color: var(--pj-on-overlay); }
    & #mainNav .pj-logo-link:has(.pj-logo--reversed) .pj-logo--primary { display: none; }
    & #mainNav .pj-logo--reversed { display: block; }
    & #mainNav .pj-logo-link:not(:has(.pj-logo--reversed)) .pj-logo--primary { filter: brightness(0) invert(1); }
    & #mainNav .pj-menu--right > .pj-menu-item > .pj-menu-link { color: var(--pj-on-overlay); }
    & #mainNav .pj-menu--right > .pj-menu-item > .pj-menu-link:is(:hover, :focus-visible) { background: var(--pj-on-overlay); border-color: var(--pj-on-overlay); color: var(--pj-primary); }
    & #mainNav :focus-visible { outline-color: var(--pj-on-overlay); }
  }
  /* A soft top shade so the transparent bar reads on bright skies. */
  & .contentbanner:has(> a#page-hero) > .masthead-media-container::before {
    content: "";
    position: absolute;
    inset: 0 0 auto;
    height: calc(var(--pj-nav-h) * 2.2);
    z-index: 1;
    background: linear-gradient(180deg, rgb(var(--pj-overlay-rgb) / 0.55), rgb(var(--pj-overlay-rgb) / 0));
    pointer-events: none;
  }
}

/* ================================================================ page hero */
/* Every rule keys off .contentbanner:has(> a#page-hero) (LayoutOptions.Anchor "page-hero").
   - With a photo / video: full-bleed, the primary-colour gradient overlay (the editor's
     UseOverlay flag is ignored: legibility is not optional), white type, content centred.
     Height from HeightOptions (bannerheight50 / 35 / 17, contentheight) unless .pj-hero--full.
   - Without: a quiet title band on --pj-surface-alt, primary heading, left aligned.
   Variants (LayoutOptions.CssClass on the hero banner, see CONTENT-CONTRACT.md §4):
   .pj-hero--full (80vh, 70vh on phones; location line; scroll cue), .pj-hero--logo (the logo
   lockup instead of the H1 text, which stays for screen readers), .pj-hero--bottom (content
   anchored bottom-left like an editorial cover), .pj-hero--clear (no overlay). */
body.pj .contentbanner { isolation: isolate; }
body.pj .large-caret { display: none; }
body.pj .contentbanner:has(> a#page-hero) { overflow: hidden; }
body.pj .contentbanner:has(> a#page-hero) > .masthead-media-container { z-index: -1; }

/* Title band (no photo). */
body.pj .contentbanner:has(> a#page-hero):not(:has(> a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video))) {
  background: var(--pj-surface-alt);
  border-bottom: 1px solid var(--pj-line);
}
body.pj .contentbanner:has(> a#page-hero):not(:has(> a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video))) > .masthead-media-container .media-box { background-color: transparent !important; /* inline BackgroundColor; the band colour is the theme's */ }

/* Photo hero. */
body.pj .contentbanner:has(> a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video)) {
  --pj-heading: var(--pj-on-overlay);
  --pj-muted: color-mix(in srgb, var(--pj-on-overlay) 82%, transparent);
  --pj-link: var(--pj-on-overlay);
  --pj-link-hover: var(--pj-on-overlay);
  --pj-focus: var(--pj-on-overlay);
  --pj-btn-bg: var(--pj-on-overlay);
  --pj-btn-fg: var(--pj-primary);
  --pj-btn-bg-hover: color-mix(in srgb, var(--pj-on-overlay) 86%, var(--pj-primary));
  --pj-btn-line: var(--pj-on-overlay);
  color: var(--pj-on-overlay);
  background: var(--pj-primary);
  text-align: center;
}
body.pj .contentbanner:has(> a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video)) .media-box-overlay { display: none; }
body.pj .contentbanner:has(> a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video)) > .masthead-media-container::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(180deg, rgb(var(--pj-overlay-rgb) / 0.35) 0%, rgb(var(--pj-overlay-rgb) / 0.12) 38%, rgb(var(--pj-overlay-rgb) / 0.3) 64%, rgb(var(--pj-overlay-rgb) / 0.78) 100%),
    rgb(0 0 0 / 0.12);
  pointer-events: none;
}
/* Height: the padding div (editor padding classes) carries the min-height and centres the
   content; the base height div inside it is only as tall as its content. */
body.pj .contentbanner:has(> a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video)) > .masthead-media-container + div {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: var(--pj-hero-h);
}
body.pj .contentbanner:has(> a#page-hero) { --pj-hero-h: auto; }
body.pj .contentbanner:has(> a#page-hero):has(.bannerheight50) { --pj-hero-h: max(56vh, 28rem); }
body.pj .contentbanner:has(> a#page-hero):has(.bannerheight35) { --pj-hero-h: max(40vh, 22rem); }
body.pj .contentbanner:has(> a#page-hero):has(.bannerheight17) { --pj-hero-h: max(24vh, 16rem); }
body.pj .contentbanner:has(> a#page-hero) :is(.bannerheight50, .bannerheight35, .bannerheight17, .halfbannerheight) { min-height: 0; }
body.pj .pj-hero--full > .contentbanner:has(> a#page-hero) { --pj-hero-h: 70vh; --pj-hero-h: 70svh; }
@media (min-width: 768px) {
  body.pj .pj-hero--full > .contentbanner:has(> a#page-hero) { --pj-hero-h: 80vh; --pj-hero-h: 80svh; }
}

/* Hero type. */
body.pj .contentbanner:has(> a#page-hero) .widget-flowbanner .widget-row { max-width: var(--pj-measure); }
body.pj .contentbanner:has(> a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video)) .widget-flowbanner .widget-row { margin-left: auto; margin-right: auto; justify-content: center; }
body.pj :is(.pj-left, .pj-hero--bottom) > .contentbanner:has(> a#page-hero) .widget-flowbanner .widget-row { margin-left: 0; margin-right: auto; justify-content: flex-start; }
body.pj .pj-left > .contentbanner:has(> a#page-hero) { text-align: left; }
body.pj .pj-center > .contentbanner:has(> a#page-hero) { text-align: center; }
body.pj .pj-center > .contentbanner:has(> a#page-hero) .widget-flowbanner .widget-row { margin-left: auto; margin-right: auto; justify-content: center; }
body.pj .pj-full > .contentbanner:has(> a#page-hero) .widget-flowbanner .widget-row { max-width: none; }
/* The same alignment on a photo hero: the photo hero's centring above keys off a longer :has()
   (1,4,2 / 1,6,2), which out-ranks the plain variant rules (1,3,2 / 1,5,2), so they are repeated with
   that :has() to win. .pj-center comes last, as above. */
body.pj :is(.pj-left, .pj-hero--bottom) > .contentbanner:has(> a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video)) { text-align: left; }
body.pj :is(.pj-left, .pj-hero--bottom) > .contentbanner:has(> a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video)) .widget-flowbanner .widget-row { margin-left: 0; margin-right: auto; justify-content: flex-start; }
body.pj .pj-center > .contentbanner:has(> a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video)) { text-align: center; }
body.pj .pj-center > .contentbanner:has(> a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video)) .widget-flowbanner .widget-row { margin-left: auto; margin-right: auto; justify-content: center; }
body.pj .contentbanner:has(> a#page-hero) h1 { margin: 0; }
body.pj .contentbanner:has(> a#page-hero) :is(h1, h2) + p { margin-top: 1.25rem; }
body.pj .contentbanner:has(> a#page-hero) p { font-size: var(--pj-fs-lead); line-height: 1.5; color: var(--pj-muted); }
body.pj .contentbanner:has(> a#page-hero) p:last-child { margin-bottom: 0; }
body.pj .contentbanner:has(> a#page-hero) .widget-row > .widget-column > .pe-2:has(> a:only-child) { padding: 1.75rem 0.375rem 0; }

/* .pj-hero--full: the home cover. The paragraph under the H1 is the location line. */
body.pj .pj-hero--full > .contentbanner:has(> a#page-hero) p {
  font-size: var(--pj-fs-small);
  font-weight: 500;
  letter-spacing: var(--pj-eyebrow-tracking);
  text-transform: uppercase;
  color: var(--pj-on-overlay);
}
@media (min-width: 992px) {
  body.pj .pj-hero--full > .contentbanner:has(> a#page-hero) p { font-size: 0.9375rem; }
}
body.pj .pj-hero--full > .contentbanner:has(> a#page-hero) :is(h1, h2) + p { margin-top: 1.75rem; }
/* The scroll cue: a thin line that drifts down, decorative only. */
body.pj .pj-hero--full > .contentbanner:has(> a#page-hero)::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: clamp(1.25rem, 4vh, 2.5rem);
  z-index: 2;
  width: 1px;
  height: 3.5rem;
  background: linear-gradient(180deg, transparent, currentColor 45%, currentColor 55%, transparent);
  opacity: 0.75;
  transform: translateX(-50%);
  pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  body.pj .pj-hero--full > .contentbanner:has(> a#page-hero)::after { animation: pj-cue 2.4s ease-in-out infinite; }
}
@keyframes pj-cue {
  0% { transform: translate(-50%, -30%) scaleY(0.4); opacity: 0; }
  40% { opacity: 0.8; }
  100% { transform: translate(-50%, 20%) scaleY(1); opacity: 0; }
}

/* .pj-hero--logo: the logo lockup (LogoReversed, else LogoPrimary turned white) replaces the H1
   text visually; the text stays in the H1 for screen readers and search. Needs a logo
   (body.pj-has-logo, set by the Layout); without one the H1 shows as text. */
body.pj.pj-has-logo .pj-hero--logo > .contentbanner:has(> a#page-hero) h1 {
  font-size: 0;
  line-height: 0;
  color: transparent;
  letter-spacing: 0;
}
body.pj.pj-has-logo .pj-hero--logo > .contentbanner:has(> a#page-hero) h1::before {
  content: "";
  display: block;
  width: min(100%, var(--pj-hero-logo-w, 26rem));
  height: var(--pj-hero-logo-h, clamp(7rem, 5rem + 10vw, 13rem));
  margin: 0 auto;
  background: var(--pj-hero-logo, var(--pj-logo-reversed, var(--pj-logo-primary))) no-repeat center / contain;
}
body.pj.pj-has-logo:not(.pj-has-logo-reversed) .pj-hero--logo > .contentbanner:has(> a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video)) h1::before { filter: brightness(0) invert(1); }
body.pj.pj-has-logo .pj-hero--logo:is(.pj-left, .pj-hero--bottom) > .contentbanner:has(> a#page-hero) h1::before { margin-left: 0; background-position: left center; }
/* On a title band (no photo) the lockup is the primary logo, in its own colours. */
body.pj.pj-has-logo .pj-hero--logo > .contentbanner:has(> a#page-hero):not(:has(> a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video))) h1::before { background-image: var(--pj-logo-primary); }

/* .pj-hero--bottom: content bottom-left, like an editorial cover. */
body.pj .pj-hero--bottom > .contentbanner:has(> a#page-hero) { text-align: left; }
body.pj .pj-hero--bottom > .contentbanner:has(> a#page-hero) > .masthead-media-container + div { justify-content: flex-end; }
/* The same on a photo hero, whose centring (above) keys off the longer :has() and out-ranks the line before. */
body.pj .pj-hero--bottom > .contentbanner:has(> a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video)) > .masthead-media-container + div { justify-content: flex-end; }

/* .pj-content--bottom: a FlowBanner (not the hero) with a height option (bannerheight50 / 35 / 17) keeps
   its content at the bottom of that height, e.g. a headline over a photo band. */
body.pj .pj-content--bottom > .contentbanner > .masthead-media-container + div > :is(.bannerheight50, .bannerheight35, .bannerheight17, .halfbannerheight) {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

/* .pj-hero--clear: no overlay (a photo that already carries its own contrast). */
body.pj .pj-hero--clear > .contentbanner:has(> a#page-hero) > .masthead-media-container::after { display: none; }
/* .pj-overlay--light: a flat 15% wash of the overlay colour instead of the gradient, for a photo that
   carries white type by itself (the FlowBanner form is with the pj-on-dark rules). */
body.pj .pj-overlay--light > .contentbanner:has(> a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video)) > .masthead-media-container::after { background: rgb(var(--pj-overlay-rgb) / 0.15); }

/* A brand band class (pj-bg-*) on a title-band hero (no photo) paints the band: the title band's own
   tint gives way (the :not(:has()) repeats the title band rule's, to out-rank it). */
body.pj :is(.pj-bg-primary, .pj-bg-secondary, .pj-bg-accent, .pj-bg-dark, .pj-bg-surface, .pj-bg-tint, .pj-bg-paper) > .contentbanner:has(> a#page-hero):not(:has(> a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video))) {
  background: transparent;
  border-bottom-color: transparent;
}

/* Title band type. */
body.pj .contentbanner:has(> a#page-hero):not(:has(> a#page-hero + .masthead-media-container :is([style*="--pb-bg-main"], video))) h1 { font-size: clamp(2.375rem, 1.7rem + 2.6vw, 3.75rem); }

/* ================================================================ sections: flow content */
/* FlowBanner / ContentBanner / Container sections. The base markup nests Bootstrap rows two
   deep (.pbroker-container > .row.widget-flowbanner > .col-12 > .row.widget-row > .widget-column
   .p-0): the gutters are cancelled here so content sits on the container's own gutter. */
body.pj .pj-page :is(.pbroker-container, .pbroker-container-no-padding-mobile) {
  width: 100% !important;          /* base: 1136px !important; the Standard width is the theme's */
  max-width: var(--pj-max);
  padding-left: var(--pj-gutter) !important;   /* base: 12px !important (container gutter, not section padding) */
  padding-right: var(--pj-gutter) !important;
  margin-left: auto;
  margin-right: auto;
}
body.pj .pj-page .pbroker-container-wide { max-width: var(--pj-max-wide); padding-left: var(--pj-gutter); padding-right: var(--pj-gutter); }
body.pj .pj-page :is(.widget-flowbanner, .widget-row) { --bs-gutter-x: 0; }
body.pj .pj-page .widget-flowbanner > .col-12 { padding-left: 0; padding-right: 0; }
body.pj .pj-page .contentbanner .contentheight { min-height: 0; }

/* Bleed: how far a container's content edge sits from the viewport edge (split images). */
body.pj .pj-page :is(.pbroker-container, .pbroker-container-no-padding-mobile) { --pj-container: var(--pj-max); }
body.pj .pj-page .pbroker-container-wide { --pj-container: var(--pj-max-wide); }
body.pj .pj-page .maxcontentwrapper { --pj-container: 100vw; }
body.pj .pj-page :is(.pbroker-container, .pbroker-container-no-padding-mobile, .pbroker-container-wide) { --pj-bleed: calc((100vw - min(100vw, var(--pj-container))) / 2 + var(--pj-gutter)); }
body.pj .pj-page .maxcontentwrapper { --pj-bleed: 0px; }

/* A flow widget's own alignment defaults to "left" (FlowMetadata), which would pin every block
   left; in a centred section (TextAlign "center", the photo hero, .pj-intro) the section's
   alignment wins. A widget set to centre or right keeps its own. */
body.pj :is(.pj-center, .pj-intro, .contentbanner:has(> a#page-hero)) .widget-align-left { text-align: inherit; }

/* Text in content blocks. Prose keeps a ~46rem measure; LayoutOptions ContentWidth "full" lifts
   it, TextAlign "center" centres it. */
body.pj .section__content > :is(p, ul, ol, blockquote, h1, h2, h3, h4, h5, h6, .pj-lead) { max-width: var(--pj-measure); }
body.pj .pj-full .section__content > * { max-width: none; }
body.pj .pj-center .section__content > * { margin-left: auto; margin-right: auto; }
body.pj .section__content > .block-header + :not(.block-header) { margin-top: clamp(1rem, 0.6rem + 1.2vw, 1.75rem); }
body.pj .section__content > :is(h6, .pj-eyebrow) + :is(h1, h2, h3) { margin-top: 0.75rem; }
body.pj .section__content > :not(.block-header) + :is(h2, h3, h4).block-header { margin-top: 2.5rem; }
body.pj .section__content > h2.block-header + p { font-size: var(--pj-fs-lead); line-height: 1.55; }
body.pj .section__content :is(ul, ol) { padding-left: 1.25rem; margin: 0 0 1.25em; }
body.pj .section__content li { margin-bottom: 0.4em; }
body.pj .section__content li::marker { color: var(--pj-secondary); }
body.pj :is(.pj-bg-primary, .pj-bg-secondary, .pj-bg-accent, .pj-bg-dark, .pj-on-dark) .section__content li::marker { color: currentColor; }
body.pj .section__content blockquote {
  margin: 2rem 0;
  padding: 0 0 0 1.5rem;
  border-left: 2px solid var(--pj-secondary);
  font-family: var(--pj-font-heading);
  font-size: var(--pj-fs-h3);
  line-height: 1.35;
  color: var(--pj-heading);
}
body.pj .section__content hr { border: 0; border-top: 1px solid var(--pj-line); margin: 2.5rem 0; opacity: 1; }
body.pj .section__content figure.block-image { margin: 0 0 1.5rem; }
body.pj .section__content figure.block-image img { border-radius: var(--pj-radius-sm); }
body.pj .section__content figcaption { margin-top: 0.6rem; font-size: var(--pj-fs-small); color: var(--pj-muted); }

/* Side-by-side flow columns get a gutter (the base columns are .p-0, so the gap goes on the
   widget inside). Forms have their own field gap. */
@media (min-width: 768px) {
  body.pj .widget-row:not(form .widget-row) > .widget-column:not(.col-md-12) + .widget-column:not(.col-md-12):not(:has(> .pe-2 > a:only-child)) > .widget {
    padding-left: clamp(1.5rem, 4vw, 4rem);
  }
}
@media (max-width: 767.98px) {
  body.pj .widget-row:not(form .widget-row) > .widget-column + .widget-column:not(:has(> .pe-2 > a:only-child)) { margin-top: 2rem; }
}

/* Wrapped rows. A flow whose columns are all one size (33, 25 or 50) and that holds more than fit on a
   line wraps onto further lines; the side-by-side gutter above would indent the first item of each
   later line. For those rows the gutter is dropped at the start of every line and the lines get the
   stacked spacing between them. Rows that fit on one line match nothing here (their first item has no
   gutter anyway), so they are unchanged. Not for a section with the Columns option (an even grid with
   its own gap, below) nor a row holding buttons (NavButton columns are as wide as their button, so a
   line holds more of them than their size says). (The doubled class beats the gutter rule.) */
@media (min-width: 768px) {
  body.pj .pj-page .widget-row:not(form .widget-row, :is(.pj-cols-2, .pj-cols-3, .pj-cols-4) .widget-row):not(:has(> .widget-column > .pe-2 > a:only-child)):not(:has(> .widget-column:not(.col-md-4))) > .widget-column.col-md-4.col-md-4:nth-child(3n + 1) > .widget,
  body.pj .pj-page .widget-row:not(form .widget-row, :is(.pj-cols-2, .pj-cols-3, .pj-cols-4) .widget-row):not(:has(> .widget-column > .pe-2 > a:only-child)):not(:has(> .widget-column:not(.col-md-3))) > .widget-column.col-md-3.col-md-3:nth-child(4n + 1) > .widget,
  body.pj .pj-page .widget-row:not(form .widget-row, :is(.pj-cols-2, .pj-cols-3, .pj-cols-4) .widget-row):not(:has(> .widget-column > .pe-2 > a:only-child)):not(:has(> .widget-column:not(.col-md-6))) > .widget-column.col-md-6.col-md-6:nth-child(2n + 1) > .widget { padding-left: 0; }
  body.pj .pj-page .widget-row:not(form .widget-row, :is(.pj-cols-2, .pj-cols-3, .pj-cols-4) .widget-row):not(:has(> .widget-column > .pe-2 > a:only-child)):not(:has(> .widget-column:not(.col-md-4))) > .widget-column.col-md-4:nth-child(n + 4),
  body.pj .pj-page .widget-row:not(form .widget-row, :is(.pj-cols-2, .pj-cols-3, .pj-cols-4) .widget-row):not(:has(> .widget-column > .pe-2 > a:only-child)):not(:has(> .widget-column:not(.col-md-3))) > .widget-column.col-md-3:nth-child(n + 5),
  body.pj .pj-page .widget-row:not(form .widget-row, :is(.pj-cols-2, .pj-cols-3, .pj-cols-4) .widget-row):not(:has(> .widget-column > .pe-2 > a:only-child)):not(:has(> .widget-column:not(.col-md-6))) > .widget-column.col-md-6:nth-child(n + 3) { margin-top: 2rem; }
}

/* ---- Columns (LayoutOptions.Columns 2 / 3 / 4, class pj-cols-N): from 768px an even grid with a
   gutter between items, for the cards of a ContentBanner, the columns of a FlowBanner's flow and the
   columns of a Container, whatever sizes they were given. A full-width (100) column such as a section
   heading keeps the whole row. Phones stack as before. Project widgets have their own grids (below). */
.pj-cols-2 { --pj-cols: 2; }
.pj-cols-3 { --pj-cols: 3; }
.pj-cols-4 { --pj-cols: 4; }
@media (min-width: 768px) {
  body.pj .pj-section:is(.pj-cols-2, .pj-cols-3, .pj-cols-4) .contentbanner .row.px-0,
  body.pj .pj-section:is(.pj-cols-2, .pj-cols-3, .pj-cols-4) .widget-flowbanner > .col-12 > .widget-row:not(form .widget-row),
  body.pj .widget-container:is(.pj-cols-2, .pj-cols-3, .pj-cols-4) {
    display: grid;
    grid-template-columns: repeat(var(--pj-cols), minmax(0, 1fr));
    gap: clamp(2rem, 1.5rem + 1.5vw, 3rem) clamp(1.25rem, 0.75rem + 1.5vw, 2.5rem);
    margin-left: 0;
    margin-right: 0;
  }
  body.pj .pj-section:is(.pj-cols-2, .pj-cols-3, .pj-cols-4) .contentbanner .row.px-0 > *,
  body.pj .pj-section:is(.pj-cols-2, .pj-cols-3, .pj-cols-4) .widget-flowbanner > .col-12 > .widget-row:not(form .widget-row) > .widget-column,
  body.pj .widget-container:is(.pj-cols-2, .pj-cols-3, .pj-cols-4) > .widget-column {
    width: auto;
    max-width: none;
    margin: 0;
  }
  body.pj .pj-section:is(.pj-cols-2, .pj-cols-3, .pj-cols-4) .contentbanner .row.px-0 > * { padding-left: 0; padding-right: 0; }
  /* The side-by-side gutter gives way to the grid's own gap (doubled classes: its specificity). */
  body.pj .pj-section.pj-section:is(.pj-cols-2, .pj-cols-3, .pj-cols-4) .widget-flowbanner > .col-12 > .widget-row.widget-row:not(form .widget-row) > .widget-column.widget-column > .widget,
  body.pj .widget-container.widget-container:is(.pj-cols-2, .pj-cols-3, .pj-cols-4) > .widget-column.widget-column > .widget { padding-left: 0; }
  body.pj .pj-section:is(.pj-cols-2, .pj-cols-3, .pj-cols-4) .widget-flowbanner > .col-12 > .widget-row:not(form .widget-row) > .widget-column.col-md-12,
  body.pj .widget-container:is(.pj-cols-2, .pj-cols-3, .pj-cols-4) > .widget-column.col-md-12 { grid-column: 1 / -1; }
}

/* ---- tables: Editor.js table blocks (Etch Block-Table: a bare <table>, header row of <th> first,
   inline grey header / 1px borders / 8px padding on every cell, hence !important on exactly those).
   Header row on the primary colour, hairlines, a faint zebra, tabular numbers. The content block
   scrolls sideways when a table is wider than the screen (the page itself never does). */
body.pj .section__content:has(> table) { max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
body.pj .section__content > table {
  width: 100%;
  margin: 0 0 2rem;
  border-collapse: collapse;
  font-size: 0.9375rem;
  line-height: 1.45;
  font-variant-numeric: tabular-nums lining-nums;
}
body.pj .section__content > table th {
  padding: 0.75rem 1rem !important;
  border: 0 !important;
  background-color: var(--pj-primary) !important;
  color: var(--pj-on-primary);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-align: left;
  vertical-align: bottom;
}
body.pj .section__content > table td {
  padding: 0.65rem 1rem !important;
  border: 0 !important;
  border-bottom: 1px solid var(--pj-line) !important;
  vertical-align: top;
}
body.pj .section__content > table tr:nth-child(odd) > td { background-color: color-mix(in srgb, var(--pj-primary) 3%, transparent); }
body.pj .section__content > table tr:hover > td { background-color: color-mix(in srgb, var(--pj-primary) 7%, transparent); }
body.pj :is(.pj-bg-primary, .pj-bg-secondary, .pj-bg-accent, .pj-bg-dark) .section__content > table th { background-color: color-mix(in srgb, currentColor 16%, transparent) !important; color: inherit; }
@media (max-width: 767.98px) {
  body.pj .section__content > table { font-size: 0.875rem; }
  body.pj .section__content > table :is(th, td) { padding: 0.5rem 0.6rem !important; }
}
@media (max-width: 480px) {
  body.pj .section__content > table { font-size: 0.8125rem; }
  body.pj .section__content > table th { letter-spacing: 0; }
  body.pj .section__content > table :is(th, td) { padding: 0.45rem 0.4rem !important; }
}

/* ---- video: the Video widget (YouTube field) and Editor.js embed blocks both render
   .videoWrapper > iframe. Responsive 16:9, black until the player loads. */
body.pj .videoWrapper { position: relative; width: 100%; height: auto; aspect-ratio: 16 / 9; background: #000; border-radius: var(--pj-radius-sm); overflow: hidden; }
body.pj .videoWrapper iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
body.pj .embed { margin: 0 0 1.5rem; }
body.pj .embed__caption { margin: 0; font-size: var(--pj-fs-small); color: var(--pj-muted); }

/* In-page anchors on base banners land below the fixed header: html scroll-padding-top already
   keeps --pj-nav-h clear, so the anchor itself sits at the banner top (an extra -nav-h offset here
   used to land them a second header height down). */
.contentbanner > a[id] { display: block; position: relative; top: 0; visibility: hidden; /* the base theme offsets it by -120px */ }

/* ================================================================ variants (LayoutOptions.CssClass) */
/* ---- .pj-split: image and text side by side, the image bleeding to the viewport edge on its
   side. A FlowBanner with two content blocks (FlowMetadata sizes 50/50 or 58/42 ...); the column
   holding an image block (figure.block-image) is the image side, first = left, last = right.
   Stacked under 992px with the image full-bleed on top. .pj-split--contained keeps the image
   inside the container (no bleed). */
@media (min-width: 992px) {
  body.pj .pj-split .widget-flowbanner .widget-row { align-items: center; flex-wrap: nowrap; }
  /* The image column keeps its own height (it does not stretch to a long text column, which
     distorted the crop) and stays in view while the text scrolls past it. */
  body.pj .pj-split .widget-row > .widget-column:has(figure.block-image) {
    align-self: flex-start;
    position: sticky;
    top: calc(var(--pj-nav-h) + 1.5rem);
  }
  body.pj .pj-split .widget-row > .widget-column:has(figure.block-image) :is(.widget, .widget-body, .section, .section__content) { height: auto; }
  /* A caption stays inside the figure, under the image. */
  body.pj .pj-split .widget-row > .widget-column:has(figure.block-image) figure.block-image { height: auto; margin: 0; display: flex; flex-direction: column; }
  body.pj .pj-split .widget-row > .widget-column:has(figure.block-image) figure.block-image figcaption { flex: none; padding: 0.6rem var(--pj-gutter) 0; }
  body.pj .pj-split .widget-row > .widget-column:has(figure.block-image) figure.block-image img {
    display: block;
    width: 100%;
    height: min(78vh, 44rem);
    min-height: 0;
    flex: none;
    object-fit: cover;
    border-radius: 0;
  }
  body.pj .pj-split:not(.pj-split--contained) .widget-row > .widget-column:has(figure.block-image) figure.block-image { max-width: none; width: auto; }
  body.pj .pj-split:not(.pj-split--contained) .widget-row > .widget-column:first-child:has(figure.block-image) figure.block-image { margin-left: calc(-1 * var(--pj-bleed)); }
  body.pj .pj-split:not(.pj-split--contained) .widget-row > .widget-column:last-child:has(figure.block-image) figure.block-image { margin-right: calc(-1 * var(--pj-bleed)); }
  body.pj .pj-split .widget-row > .widget-column:has(figure.block-image) + .widget-column > .widget { padding-left: clamp(2.5rem, 5vw, 5rem); }
  body.pj .pj-split .widget-row > .widget-column:not(:has(figure.block-image)):has(+ .widget-column figure.block-image) > .widget { padding-right: clamp(2.5rem, 5vw, 5rem); }
  /* .pj-split--gutter (opt-in, so existing sites keep their layout): a text column with buttons is a
     Container (a .row carrying the !important ps-0 / pe-0 utilities), which the gutter above misses;
     this gives it the same gutter as its margin. */
  body.pj .pj-split.pj-split--gutter .widget-row > .widget-column:has(figure.block-image) + .widget-column > .widget-container { width: calc(100% - clamp(2.5rem, 5vw, 5rem)); margin-left: clamp(2.5rem, 5vw, 5rem); margin-right: 0; }
  body.pj .pj-split.pj-split--gutter .widget-row > .widget-column:not(:has(figure.block-image)):has(+ .widget-column figure.block-image) > .widget-container { width: calc(100% - clamp(2.5rem, 5vw, 5rem)); margin-left: 0; margin-right: clamp(2.5rem, 5vw, 5rem); }
  /* Beats the generic column gutter (".widget-row:not(form .widget-row) > .widget-column:not(...) + ..."). */
  body.pj .pj-split.pj-split .widget-flowbanner .widget-row:not(form .widget-row) > .widget-column + .widget-column:has(figure.block-image) > .widget { padding-left: 0; }
  body.pj .pj-split--contained .widget-row > .widget-column:has(figure.block-image) figure.block-image img { border-radius: var(--pj-radius); }
}
@media (max-width: 991.98px) {
  body.pj .pj-split .widget-row > .widget-column { flex: 0 0 100%; width: 100%; max-width: 100%; }
  body.pj .pj-split .widget-row > .widget-column:has(figure.block-image) { order: -1; }
  body.pj .pj-split .widget-row > .widget-column + .widget-column { margin-top: 2rem; }
  body.pj .pj-split .widget-row > .widget-column > .widget { padding-left: 0; }
  body.pj .pj-split:not(.pj-split--contained) .widget-column figure.block-image { margin-left: calc(-1 * var(--pj-bleed)); margin-right: calc(-1 * var(--pj-bleed)); }
  body.pj .pj-split .widget-column figure.block-image img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: 0; }
}

/* ---- .pj-band: a full-width landscape image band. Either a FlowBanner with a background photo
   and no text (its height from HeightOptions, at least a landscape strip), or a FlowBanner set to
   Width Options "Full" holding one image block. .pj-band--tall: a taller 16:9 crop. */
body.pj .pj-band > .contentbanner:has(> .masthead-media-container [style*="--pb-bg-main"]) > .masthead-media-container + div { min-height: clamp(16rem, 42vw, 44rem); }
body.pj .pj-band.pj-band--tall > .contentbanner:has(> .masthead-media-container [style*="--pb-bg-main"]) > .masthead-media-container + div { min-height: clamp(20rem, 56vw, 56rem); }
body.pj .pj-band .media-box-overlay { display: none; }
body.pj .pj-band figure.block-image { margin: 0; }
body.pj .pj-band figure.block-image img { display: block; width: 100%; aspect-ratio: 3 / 2; object-fit: cover; border-radius: 0; }
@media (min-width: 768px) {
  body.pj .pj-band figure.block-image img { aspect-ratio: 21 / 9; }
  body.pj .pj-band.pj-band--tall figure.block-image img { aspect-ratio: 16 / 9; }
}
body.pj .pj-band figcaption { padding: 0.6rem var(--pj-gutter) 0; }
body.pj .pj-band .section__content > * { max-width: none; }

/* ---- .pj-intro: a centred opening statement (large lead type, narrow measure). */
body.pj .pj-intro { text-align: center; }
body.pj .pj-intro .section__content > * { margin-left: auto; margin-right: auto; }
body.pj .pj-intro .section__content > p { font-family: var(--pj-font-heading); font-size: clamp(1.375rem, 1.1rem + 1.1vw, 2rem); line-height: 1.4; color: var(--pj-heading); letter-spacing: -0.005em; }
/* TextAlign "left" on an intro (a longer story): the eyebrow and heading stay centred, the body
   reads left-aligned in the same centred measure. */
body.pj .pj-intro.pj-left { text-align: left; }
body.pj .pj-intro.pj-left .section__content > :is(h1, h2, h3, h4, h5, h6) { text-align: center; }

/* ---- .pj-contact: the enquiry section. Details (content block) and form (SimpleFormPicker)
   side by side on a tinted surface, the form in a raised card. */
/* A brand background class (pj-bg-primary ...) on the same section wins over the tint. */
body.pj .pj-contact:not(.pj-bg-primary, .pj-bg-secondary, .pj-bg-accent, .pj-bg-dark, .pj-bg-surface, .pj-bg-tint, .pj-bg-paper) { background: var(--pj-surface-tint); }
body.pj .pj-contact > .contentbanner > .masthead-media-container .media-box { background-color: transparent !important; /* inline BackgroundColor under the variant's own tint */ }
@media (min-width: 992px) {
  body.pj .pj-contact .widget-flowbanner .widget-row:has(> .widget-column :is(form, .pj-form-thanks)) { flex-wrap: nowrap; align-items: flex-start; }
  /* The form column holds the Form content item directly (no .widget wrapper), so pad the column. */
  body.pj .pj-contact .widget-flowbanner > .col-12 > .widget-row > .widget-column:has(form, .pj-form-thanks) { padding-left: clamp(2rem, 5vw, 5rem) !important; }
}
@media (max-width: 991.98px) {
  body.pj .pj-contact .widget-row:has(> .widget-column :is(form, .pj-form-thanks)) > .widget-column { flex: 0 0 100%; width: 100%; max-width: 100%; }
  body.pj .pj-contact .widget-row:has(> .widget-column :is(form, .pj-form-thanks)) > .widget-column + .widget-column { margin-top: 2rem; }
  body.pj .pj-contact .widget-row:has(> .widget-column :is(form, .pj-form-thanks)) > .widget-column > .widget { padding-left: 0; }
}
body.pj .pj-contact form {
  padding: clamp(1.5rem, 1rem + 2vw, 2.75rem);
  background: var(--pj-paper);
  border-radius: var(--pj-radius-lg);
  box-shadow: var(--pj-shadow);
}
body.pj .pj-contact .section__content a[href^="tel:"],
body.pj .pj-contact .section__content a[href^="mailto:"] { color: var(--pj-heading); font-weight: 500; }

/* ---- section backgrounds: brand-coloured bands (BackgroundInfo.BackgroundColor holds fixed
   neutrals only). On a FlowBanner / ContentBanner the base views paint the editor's
   BackgroundColor inline on an inner box; under a brand class that inline colour gives way
   (!important is the only way past an inline style; only the colour, never an image). */
.pj-bg-primary { background: var(--pj-primary); color: var(--pj-on-primary); }
.pj-bg-secondary { background: var(--pj-secondary); color: var(--pj-on-secondary); }
.pj-bg-accent { background: var(--pj-accent); color: var(--pj-on-accent); }
.pj-bg-surface { background: var(--pj-surface-alt); color: var(--pj-text); }
.pj-bg-tint { background: var(--pj-surface-tint); color: var(--pj-text); }
.pj-bg-paper { background: var(--pj-paper); color: var(--pj-text); }
.pj-bg-dark { background: var(--pj-primary-dark); color: var(--pj-on-primary); }
:is(.pj-bg-primary, .pj-bg-secondary, .pj-bg-accent, .pj-bg-surface, .pj-bg-tint, .pj-bg-paper, .pj-bg-dark) > .contentbanner :is(.media-box, .contentbanner > div[style]):not(.cardcontent *) { background-color: transparent !important; }
:is(.pj-bg-primary, .pj-bg-secondary, .pj-bg-accent, .pj-bg-dark) :is(h1, h2, h3, h4, h5, h6, p, li, .block-paragraph, td, th, figcaption):not(.cardcontent *) { color: inherit; }
:is(.pj-bg-primary, .pj-bg-secondary, .pj-bg-accent, .pj-bg-dark) a:not([class*="button"]):not(.cardcontent *) { color: inherit; }
/* .pj-on-dark: light type for a section over a dark photo (FlowBanner background image). */
.pj-on-dark { color: #fff; }
.pj-on-dark > .contentbanner > .masthead-media-container::after { content: ""; position: absolute; inset: 0; background: rgb(var(--pj-overlay-rgb) / 0.55); }
.pj-on-dark .media-box-overlay { display: none; }
/* .pj-overlay--light on a FlowBanner with a background photo (pj-on-dark band): 15% instead of 55%. */
body.pj .pj-overlay--light > .contentbanner > .masthead-media-container::after { background: rgb(var(--pj-overlay-rgb) / 0.15); }

/* ---- layout options (LayoutCssClasses.cs). TextAlign and ContentWidth apply to the section
   content; Columns to card / item grids. */
.pj-center { text-align: center; }
.pj-left { text-align: left; }
.pj-narrow .pj-block-inner,
.pj-section.pj-narrow .pbroker-container,
.pj-section.pj-narrow .pbroker-container-no-padding-mobile,
.pj-section.pj-narrow .contentwrapper { max-width: calc(var(--pj-narrow) + 2 * var(--pj-gutter)); margin-left: auto; margin-right: auto; }
.pj-block.pj-full .pj-block-inner { max-width: none; }

/* ================================================================ project widgets: shared */
/* Every project widget renders <section class="pj-block pj-block--{kind} {layout classes}"
   id="{LayoutOptions.Anchor}"> > .pj-block-inner > header.pj-block-header (h2 + intro) + content.
   Spacing is the theme's block space (.pj-flush-top / .pj-flush-bottom drop one side, e.g. an
   availability table straight under its masterplan). */
.pj-block { padding-top: var(--pj-block-space); padding-bottom: var(--pj-block-space); }
.pj-block.pj-flush-top { padding-top: 0; }
.pj-block.pj-flush-bottom { padding-bottom: 0; }
.pj-block-inner { max-width: calc(var(--pj-max) + 2 * var(--pj-gutter)); margin: 0 auto; padding: 0 var(--pj-gutter); }
.pj-block.pj-width-full .pj-block-inner { max-width: none; }
.pj-block.pj-width-wide .pj-block-inner { max-width: calc(var(--pj-max-wide) + 2 * var(--pj-gutter)); }
.pj-block-header { margin-bottom: clamp(2rem, 1.5rem + 2vw, 3.5rem); max-width: var(--pj-measure); }
.pj-center .pj-block-header { margin-left: auto; margin-right: auto; }
body.pj .pj-block-heading { margin: 0; }
body.pj .pj-block-intro { margin: 1.25rem 0 0; font-size: var(--pj-fs-lead); line-height: 1.55; color: var(--pj-muted); }
body.pj .pj-block-intro + .pj-block-intro { margin-top: 0.75rem; font-size: inherit; }
body.pj :is(.pj-bg-primary, .pj-bg-secondary, .pj-bg-accent, .pj-bg-dark) .pj-block-intro { color: var(--pj-muted); }

/* Card grids: 1 column, 2 from 768px, 3 from 1100px; LayoutOptions.Columns overrides from 768px. */
.pj-floorplans, .pj-sectors, .pj-places, .pj-agents {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(1.25rem, 1rem + 1.2vw, 2.25rem);
  grid-template-columns: 1fr;
}
@media (min-width: 768px) {
  .pj-floorplans, .pj-sectors, .pj-places, .pj-agents { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pj-cols-2 :is(.pj-floorplans, .pj-sectors, .pj-places, .pj-agents) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pj-cols-3 :is(.pj-floorplans, .pj-sectors, .pj-places, .pj-agents) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .pj-cols-4 :is(.pj-floorplans, .pj-sectors, .pj-places, .pj-agents) { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (min-width: 1100px) {
  .pj-block:not(.pj-cols-2):not(.pj-cols-4) :is(.pj-floorplans, .pj-sectors, .pj-agents) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.pj-floorplans img, .pj-sectors img, .pj-places img, .pj-agents img { display: block; width: 100%; height: auto; }

/* ================================================================ floor plan cards */
/* A card on paper: the render (cover) or, without one, the floor plan on white (contain,
   .pj-floorplan-media--plan); name; a specs row with icons; blurb; link to the plan. */
.pj-floorplan {
  display: flex;
  flex-direction: column;
  background: var(--pj-paper);
  color: var(--pj-text);
  border: 1px solid var(--pj-line);
  border-radius: var(--pj-radius);
  overflow: hidden;
  transition: box-shadow 0.25s ease, transform 0.25s ease;
}
.pj-floorplan:hover { box-shadow: var(--pj-shadow); }
.pj-floorplan-media { background: #fff; border-bottom: 1px solid var(--pj-line); }
.pj-floorplan-media img { aspect-ratio: 4 / 3; object-fit: cover; }
.pj-floorplan-media--plan img { object-fit: contain; padding: clamp(1rem, 3vw, 1.75rem); }
.pj-floorplan-body { padding: clamp(1.25rem, 1rem + 1vw, 1.75rem); display: flex; flex-direction: column; gap: 1rem; flex: 1 1 auto; }
body.pj .pj-floorplan-name { margin: 0; font-size: var(--pj-fs-h3); }
.pj-specs {
  list-style: none;
  margin: 0;
  padding: 0.9rem 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  border-top: 1px solid var(--pj-line);
  border-bottom: 1px solid var(--pj-line);
  color: var(--pj-muted);
  font-size: 0.9375rem;
  font-variant-numeric: tabular-nums lining-nums;
}
.pj-spec { display: inline-flex; align-items: center; gap: 0.4rem; white-space: nowrap; }
.pj-spec::before {
  content: "";
  flex: 0 0 auto;
  width: 1.3em;
  height: 1.3em;
  background: var(--pj-secondary);
  -webkit-mask: var(--pj-spec-icon, none) center / contain no-repeat;
  mask: var(--pj-spec-icon, none) center / contain no-repeat;
}
.pj-spec--beds { --pj-spec-icon: var(--pj-icon-beds); }
.pj-spec--baths { --pj-spec-icon: var(--pj-icon-baths); }
.pj-spec--parking { --pj-spec-icon: var(--pj-icon-parking); }
.pj-spec--area { --pj-spec-icon: var(--pj-icon-area); }
.pj-spec-value { font-weight: 600; color: var(--pj-text); }
.pj-floorplan-blurb { margin: 0; color: var(--pj-muted); }
body.pj .pj-floorplan-link { margin-top: auto; align-self: flex-start; font-weight: 600; color: var(--pj-heading); text-decoration: none; border-bottom: 1px solid currentColor; padding-bottom: 2px; }
body.pj .pj-floorplan-link::after { content: " \2192"; }
body.pj .pj-floorplan-link:hover { color: var(--pj-link); }

/* ================================================================ availability table */
/* A premium price list: hairline rules, tabular numbers, status chips from the brand tokens,
   filter pills. A value every lot shares is one line above the table (.pj-lots-shared). Small
   tablets: each lot is a small card, cells labelled from data-label. Phones (under 576px): one
   compact line per lot (number, stage, price, status); the .pj-lot-extra cells are hidden. */
.pj-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem 1.75rem; margin-bottom: 1.75rem; }
.pj-filters:empty { display: none; }
.pj-filter-group { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.pj-filter-group + .pj-filter-group { padding-left: 1.75rem; border-left: 1px solid var(--pj-line); }
body.pj .pj-filter {
  min-height: 40px;
  padding: 0 1.1rem;
  border: 1px solid var(--pj-line-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--pj-text);
  font-size: 0.9375rem;
  font-weight: 500;
  cursor: pointer;
  transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}
body.pj .pj-filter:hover { border-color: var(--pj-primary); }
body.pj .pj-filter.is-active { background: var(--pj-primary); border-color: var(--pj-primary); color: var(--pj-on-primary); }
@media (max-width: 767.98px) {
  .pj-filter-group + .pj-filter-group { padding-left: 0; border-left: 0; }
}
.pj-table-wrap { overflow-x: auto; }
.pj-lots { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums lining-nums; }
.pj-lots th, .pj-lots td { padding: 1.05rem 1rem; border-bottom: 1px solid var(--pj-line); text-align: left; vertical-align: middle; }
.pj-lots :is(th, td):first-child { padding-left: 0; }
.pj-lots :is(th, td):last-child { padding-right: 0; }
.pj-lots thead th {
  padding-top: 0;
  padding-bottom: 0.85rem;
  border-bottom: 1px solid var(--pj-heading);
  font-size: var(--pj-fs-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--pj-muted);
  white-space: nowrap;
}
body.pj .pj-lot-number { font-family: var(--pj-font-heading); font-size: 1.1875rem; font-weight: var(--pj-heading-weight); color: var(--pj-heading); white-space: nowrap; }
.pj-lots .pj-num { text-align: right; white-space: nowrap; }
.pj-lot-price { font-weight: 600; color: var(--pj-heading); }
.pj-lot-notes { color: var(--pj-muted); font-size: 0.9375rem; }
.pj-lot { transition: background-color 0.2s ease; }
.pj-lot:hover { background: color-mix(in srgb, var(--pj-primary) 3%, transparent); }
.pj-lot--sold, .pj-lot--sold :is(.pj-lot-number, .pj-lot-price) { color: var(--pj-muted); }
.pj-lots-empty { margin: 1.5rem 0 0; color: var(--pj-muted); }
.pj-lots-shared { margin: 0 0 1.25rem; font-size: var(--pj-fs-small); color: var(--pj-muted); }
.pj-lot-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.pj-lots tr[hidden] { display: none !important; }
.pj-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  min-height: 1.9rem;
  padding: 0 0.8rem;
  border: 1px solid var(--pj-status-other-line);
  border-radius: 999px;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1;
  white-space: nowrap;
  color: var(--pj-status-ink);
  background: var(--pj-status-other);
}
.pj-chip::before { content: ""; width: 0.45em; height: 0.45em; border-radius: 50%; background: currentColor; }
/* One class per status (no :is() grouping), so a tenant's Custom CSS overrides them as before. */
.pj-chip--available { border-color: transparent; background: var(--pj-status-available); color: var(--pj-status-available-ink); }
.pj-chip--under-offer { border-color: transparent; background: var(--pj-status-under-offer); color: var(--pj-status-under-offer-ink); }
.pj-chip--reserved { border-color: transparent; background: var(--pj-status-reserved); color: var(--pj-status-reserved-ink); }
.pj-chip--sold { border-color: transparent; background: var(--pj-status-sold); color: var(--pj-status-sold-ink); }
.pj-chip--sold::before { display: none; }
.pj-chip--coming-soon { border-color: var(--pj-status-coming-soon); background: transparent; color: var(--pj-status-coming-soon-ink); }
.pj-chip--future-release { border-color: var(--pj-status-future-release); border-style: dashed; background: transparent; color: var(--pj-status-future-release-ink); }
.pj-chip--not-released { border-color: var(--pj-status-not-released); background: transparent; color: var(--pj-status-not-released-ink); }
.pj-chip:is(.pj-chip--coming-soon, .pj-chip--future-release, .pj-chip--not-released)::before { background: transparent; box-shadow: inset 0 0 0 1px currentColor; }
@media (min-width: 576px) and (max-width: 767.98px) {
  .pj-lots thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .pj-lots, .pj-lots tbody { display: block; }
  .pj-lots tr { display: grid; grid-template-columns: 1fr auto; gap: 0.35rem 1rem; padding: 1.1rem 0; border-bottom: 1px solid var(--pj-line); }
  .pj-lots tr:first-child { border-top: 1px solid var(--pj-heading); }
  .pj-lots th, .pj-lots td { display: flex; justify-content: space-between; gap: 1rem; padding: 0; border: 0; grid-column: 1 / -1; }
  .pj-lots th.pj-lot-number { grid-column: 1; align-items: center; font-size: 1.375rem; }
  .pj-lots td[data-label="Status"] { grid-column: 2; grid-row: 1; justify-content: flex-end; }
  .pj-lots td[data-label="Status"]::before { display: none; }
  .pj-lots td::before { content: attr(data-label); content: attr(data-label) / ""; color: var(--pj-muted); font-size: 0.9375rem; font-weight: 400; }
  .pj-lots .pj-num { text-align: right; }
  .pj-lots :is(th, td):is(:first-child, :last-child) { padding: 0; }
  .pj-lot:hover { background: transparent; }
  .pj-lots td:empty { display: none; }
}
@media (max-width: 575.98px) {
  .pj-lots thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .pj-lots, .pj-lots tbody { display: block; }
  .pj-lots tr { display: flex; align-items: center; gap: 0.75rem; padding: 0.7rem 0; border-bottom: 1px solid var(--pj-line); }
  .pj-lots tr:first-child { border-top: 1px solid var(--pj-heading); }
  .pj-lots th, .pj-lots td { padding: 0; border: 0; }
  .pj-lots .pj-lot-extra { display: none; }
  body.pj .pj-lots th.pj-lot-number { flex: none; font-size: 1.0625rem; }
  .pj-lots .pj-lot-label { position: static; width: auto; height: auto; overflow: visible; clip: auto; }
  .pj-lots .pj-lot-stage { flex: 1 1 auto; min-width: 0; color: var(--pj-muted); font-size: 0.9375rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  body.pj .pj-lots th.pj-lot-number:not(:has(+ .pj-lot-stage)) { margin-right: auto; }
  .pj-lots .pj-lot-price { font-size: 0.9375rem; }
  .pj-lots .pj-lot-status { flex: none; }
  .pj-lots .pj-chip { min-height: 1.6rem; padding: 0 0.6rem; font-size: 0.75rem; }
  .pj-lot:hover { background: transparent; }
}

/* ================================================================ masterplan */
/* Underline tabs; the plan in a light frame. */
.pj-tabs { display: flex; flex-wrap: wrap; gap: 0 2rem; margin-bottom: 2rem; border-bottom: 1px solid var(--pj-line); }
.pj-center .pj-tabs { justify-content: center; }
body.pj .pj-tab {
  position: relative;
  padding: 0.75rem 0;
  margin-bottom: -1px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: transparent;
  color: var(--pj-muted);
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: color 0.2s ease, border-color 0.2s ease;
}
body.pj .pj-tab:hover { color: var(--pj-text); }
body.pj .pj-tab.is-active { color: var(--pj-heading); border-bottom-color: var(--pj-accent); }
.pj-tab-panel + .pj-tab-panel { margin-top: 3rem; }
.pj-tabs ~ .pj-tab-panel + .pj-tab-panel { margin-top: 0; }
body.pj .pj-stage-name { margin: 0 0 1.25rem; font-size: var(--pj-fs-h3); }
.pj-masterplan-image {
  display: block;
  padding: clamp(0.75rem, 2vw, 1.75rem);
  background: var(--pj-paper);
  border: 1px solid var(--pj-line);
  border-radius: var(--pj-radius);
  transition: box-shadow 0.25s ease;
}
.pj-masterplan-image:hover { box-shadow: var(--pj-shadow); }
.pj-masterplan-image img { display: block; width: 100%; height: auto; }
.pj-stage-blurb { margin: 1.5rem 0 0; max-width: var(--pj-measure); color: var(--pj-muted); }
.pj-center .pj-stage-blurb { margin-left: auto; margin-right: auto; }
/* Project-wide plan (no stage plans): framed, "View full size" chip, caption, then a stage key. */
.pj-masterplan-figure { margin: 0; }
.pj-masterplan--project .pj-masterplan-image { position: relative; background: #fff; }
.pj-masterplan-open {
  position: absolute;
  right: clamp(1.25rem, 3vw, 2.5rem);
  bottom: clamp(1.25rem, 3vw, 2.5rem);
  padding: 0.45rem 0.9rem;
  border-radius: 999px;
  background: var(--pj-primary);
  color: var(--pj-on-primary);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  box-shadow: 0 2px 10px rgb(var(--pj-text-rgb) / 0.18);
  transition: background-color 0.2s ease, color 0.2s ease;
}
.pj-masterplan-image:hover .pj-masterplan-open,
.pj-masterplan-image:focus-visible .pj-masterplan-open { background: var(--pj-accent); color: var(--pj-on-accent); }
.pj-masterplan-caption { margin: 0.9rem 0 0; color: var(--pj-muted); font-size: 0.875rem; max-width: var(--pj-measure); }
.pj-center .pj-masterplan-caption { margin-left: auto; margin-right: auto; }
.pj-stage-key { list-style: none; margin: 2rem 0 0; padding: 0; display: grid; gap: 1.25rem 2rem; }
@media (min-width: 768px) { .pj-stage-key { grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); } }
.pj-stage-key-item { display: flex; flex-direction: column; gap: 0.25rem; padding-top: 0.9rem; border-top: 2px solid var(--pj-accent); text-align: left; }
.pj-stage-key-name { font-family: var(--pj-font-heading); font-weight: var(--pj-heading-weight); color: var(--pj-heading); font-size: 1.125rem; }
.pj-stage-key-blurb { color: var(--pj-muted); font-size: 0.9375rem; }
@media (max-width: 575.98px) { .pj-masterplan-open { right: 0.75rem; bottom: 0.75rem; font-size: 0.75rem; padding: 0.35rem 0.7rem; } }

/* ================================================================ nearby places */
/* The map (framed) beside image cards with a distance badge over the photo. */
.pj-nearby { display: grid; gap: clamp(2rem, 1.5rem + 2vw, 3.5rem); }
@media (min-width: 992px) {
  .pj-nearby--with-map { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); align-items: start; }
  .pj-nearby--with-map .pj-places { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pj-nearby--with-map .pj-map { position: sticky; top: calc(var(--pj-nav-h) + 1.5rem); }
}
.pj-map-embed { display: block; width: 100%; aspect-ratio: 4 / 3; border: 1px solid var(--pj-line); border-radius: var(--pj-radius); background: var(--pj-paper); }
.pj-map-image { display: block; width: 100%; height: auto; border: 1px solid var(--pj-line); border-radius: var(--pj-radius); }
.pj-map-address { margin: 1rem 0 0; color: var(--pj-muted); font-size: 0.9375rem; }
.pj-place { position: relative; display: flex; flex-direction: column; gap: 0.2rem; }
.pj-place-image { aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--pj-radius-sm); margin-bottom: 0.65rem; }
.pj-place-name { font-weight: 600; color: var(--pj-heading); line-height: 1.35; }
.pj-place-distance { color: var(--pj-muted); font-size: 0.875rem; font-variant-numeric: tabular-nums; }
.pj-place-blurb { color: var(--pj-muted); font-size: 0.875rem; line-height: 1.45; }
.pj-place:has(.pj-place-image) .pj-place-distance {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  padding: 0.3rem 0.65rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--pj-surface) 92%, transparent);
  color: var(--pj-heading);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  box-shadow: 0 2px 8px rgb(var(--pj-text-rgb) / 0.12);
}

/* ================================================================ show-home card */
/* Floating card bottom right from 768px; a slim bar across the bottom on phones. project.js
   closes it (hidden, remembered per session) and adds .is-ready. */
.pj-block--showhome {
  position: fixed;
  right: var(--pj-gutter);
  bottom: var(--pj-gutter);
  z-index: 1020;
  width: min(22rem, calc(100vw - 2 * var(--pj-gutter)));
  padding: 1.5rem 1.5rem 1.25rem;
  background: var(--pj-paper);
  color: var(--pj-text);
  border-top: 3px solid var(--pj-secondary);
  border-radius: var(--pj-radius-lg);
  box-shadow: var(--pj-shadow-lg);
  font-size: 0.9375rem;
  line-height: 1.5;
}
.pj-block--showhome[hidden] { display: none; }
@media (prefers-reduced-motion: no-preference) {
  .pj-block--showhome.is-ready { animation: pj-rise 0.5s ease-out 0.6s both; }
}
@keyframes pj-rise { from { opacity: 0; transform: translateY(1rem); } to { opacity: 1; transform: none; } }
body.pj .pj-showhome-close {
  position: absolute;
  top: 0.35rem;
  right: 0.35rem;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--pj-muted);
  cursor: pointer;
}
body.pj .pj-showhome-close:hover { background: var(--pj-surface-alt); color: var(--pj-text); }
body.pj .pj-showhome-title { margin: 0 2rem 0.75rem 0; font-size: 1.3125rem; letter-spacing: -0.005em; }
body.pj :is(.pj-showhome-times p, .pj-showhome-address, .pj-showhome-intro) { margin: 0 0 0.35rem; }
.pj-showhome-times { font-weight: 500; color: var(--pj-heading); }
.pj-showhome-address, .pj-showhome-intro { color: var(--pj-muted); }
.pj-showhome-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 1rem 0 0; }
@media (max-width: 767.98px) {
  .pj-block--showhome {
    left: 0;
    right: 0;
    bottom: 0;
    width: auto;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 0 0.75rem;
    padding: 0.7rem 3rem 0.7rem var(--pj-gutter);
    border-top-width: 2px;
    border-radius: var(--pj-radius-lg) var(--pj-radius-lg) 0 0;
    font-size: 0.8125rem;
  }
  body.pj .pj-showhome-title { grid-column: 1; margin: 0; font-size: 1rem; line-height: 1.25; }
  .pj-showhome-times { grid-column: 1; }
  body.pj .pj-showhome-times p { margin: 0; }
  .pj-showhome-times p + p { display: none; }
  .pj-showhome-intro, .pj-showhome-address { display: none; }
  .pj-showhome-actions { grid-column: 2; grid-row: 1 / span 2; margin: 0; flex-wrap: nowrap; }
  body.pj .pj-showhome-actions .pj-button--ghost { display: none; }
  body.pj .pj-showhome-actions .pj-button { min-height: 40px; padding: 0 0.9rem !important; font-size: 0.875rem; }
  body.pj .pj-showhome-close { top: 50%; right: 0.25rem; transform: translateY(-50%); }
  /* Room at the foot of the page so the bar never covers the footer. */
  body.pj:has(.pj-block--showhome:not([hidden])) .pj-legal { padding-bottom: 5rem; }
}

/* ================================================================ sectors */
/* "Who it's for": an icon / text grid with a hairline over each item. .pj-sectors--photos (on
   the widget's CssClass) shows each Sector image as a 4:3 photo instead of an icon. */
.pj-sectors { gap: clamp(2rem, 1.5rem + 2vw, 3rem) clamp(1.5rem, 1rem + 2vw, 2.5rem); }
@media (min-width: 600px) and (max-width: 767.98px) {
  .pj-sectors { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1100px) {
  .pj-block.pj-cols-4 .pj-sectors { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.pj-sector { padding-top: 1.5rem; border-top: 1px solid var(--pj-line-strong); }
.pj-sectors img.pj-sector-image { width: 3rem; height: 3rem; object-fit: contain; margin-bottom: 1.25rem; }
.pj-center .pj-sectors img.pj-sector-image { margin-left: auto; margin-right: auto; }
.pj-sectors--photos .pj-sectors img.pj-sector-image { width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--pj-radius-sm); }
.pj-sectors--photos .pj-sector { padding-top: 0; border-top: 0; }
body.pj .pj-sector-name { margin: 0 0 0.6rem; font-size: var(--pj-fs-h4); line-height: 1.3; }
.pj-sector-blurb { margin: 0; color: var(--pj-muted); font-size: 0.9375rem; }

/* ================================================================ partners */
/* A logo strip, greyscale until hover / focus. */
.pj-partners { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 2rem clamp(2rem, 1rem + 4vw, 4.5rem); }
.pj-center .pj-partners { justify-content: center; }
.pj-partner-logo {
  display: block;
  max-height: 56px;
  max-width: 180px;
  width: auto;
  height: auto;
  filter: grayscale(1);
  opacity: 0.7;
  transition: filter 0.3s ease, opacity 0.3s ease;
}
.pj-partner:hover .pj-partner-logo,
.pj-partner-link:focus-visible .pj-partner-logo { filter: none; opacity: 1; }
:is(.pj-bg-primary, .pj-bg-secondary, .pj-bg-accent, .pj-bg-dark) .pj-partner-logo { filter: grayscale(1) brightness(0) invert(1); }
:is(.pj-bg-primary, .pj-bg-secondary, .pj-bg-accent, .pj-bg-dark) .pj-partner:hover .pj-partner-logo { filter: brightness(0) invert(1); }
.pj-partner-name { font-family: var(--pj-font-heading); font-size: 1.125rem; font-weight: var(--pj-heading-weight); color: var(--pj-muted); }
body.pj .pj-partner-link { text-decoration: none; }
.pj-partner--with-blurb { display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem; max-width: 16rem; }
.pj-center .pj-partner--with-blurb { align-items: center; text-align: center; }
.pj-partner-blurb { color: var(--pj-muted); font-size: 0.8125rem; line-height: 1.45; }
.pj-partners:has(.pj-partner--with-blurb) { align-items: flex-start; }
.pj-partner--with-blurb > :first-child { min-height: 56px; display: flex; align-items: center; }
:is(.pj-bg-primary, .pj-bg-secondary, .pj-bg-accent, .pj-bg-dark) .pj-partner-blurb { color: inherit; opacity: 0.75; }

/* ================================================================ agents */
.pj-agent {
  display: flex;
  gap: 1.25rem;
  align-items: center;
  padding: 1.5rem;
  background: var(--pj-paper);
  border: 1px solid var(--pj-line);
  border-radius: var(--pj-radius);
  color: var(--pj-text);
}
.pj-agent-photo { flex: 0 0 96px; width: 96px; aspect-ratio: 1; object-fit: cover; border-radius: 50%; }
.pj-agents img.pj-agent-photo { width: 96px; height: 96px; }
.pj-agent-body { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
body.pj .pj-agent-name { margin: 0; font-size: 1.3125rem; line-height: 1.25; }
.pj-agent-role { margin: 0 0 0.35rem; color: var(--pj-muted); font-size: 0.875rem; letter-spacing: 0.02em; }
body.pj .pj-agent-phone { color: var(--pj-heading); font-weight: 600; text-decoration: none; font-variant-numeric: tabular-nums; }
body.pj .pj-agent-email { font-size: 0.9375rem; }
.pj-agent-phone, .pj-agent-email { overflow-wrap: anywhere; }
body.pj .pj-agent-phone:hover { color: var(--pj-link); }
.pj-center .pj-agent { flex-direction: column; text-align: center; }

/* ================================================================ FAQ (pj-block--faq) */
/* Widget-Faq.cshtml: .pj-faq > details.pj-faq-item > summary.pj-faq-q + .pj-faq-a (the answer's
   Editor.js blocks, styled as content-block prose). Native disclosure, no script: hairline rules
   between the questions, a chevron in a circle (a mask, so it takes the heading colour on light and
   dark sections) that turns when the answer is open. ContentWidth "narrow" gives the reading column;
   TextAlign "center" centres the header only, the questions and answers stay left-aligned. */
:root {
  --pj-icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}
.pj-faq { border-top: 1px solid var(--pj-line); text-align: left; }
.pj-faq-item { border-bottom: 1px solid var(--pj-line); }
body.pj .pj-faq-q {
  position: relative;
  display: block;
  list-style: none;
  min-height: 44px;
  padding: 1.25rem 3.5rem 1.25rem 0;
  cursor: pointer;
  font-family: var(--pj-font-heading);
  font-size: var(--pj-fs-h4);
  font-weight: var(--pj-heading-weight);
  line-height: 1.35;
  color: var(--pj-heading);
  text-wrap: balance;
}
.pj-faq-q::-webkit-details-marker { display: none; }
.pj-faq-q::marker { content: ""; }
.pj-faq-q::before,
.pj-faq-q::after { content: ""; position: absolute; top: 50%; pointer-events: none; }
/* The circle. */
.pj-faq-q::before { right: 0; width: 2.25rem; height: 2.25rem; margin-top: -1.125rem; border: 1px solid var(--pj-line-strong); border-radius: 50%; }
/* The chevron. */
.pj-faq-q::after {
  right: 0.625rem;
  width: 1rem;
  height: 1rem;
  margin-top: -0.5rem;
  background: currentColor;
  -webkit-mask: var(--pj-icon-chevron) center / contain no-repeat;
  mask: var(--pj-icon-chevron) center / contain no-repeat;
}
.pj-faq-item[open] > .pj-faq-q::after { transform: rotate(180deg); }
.pj-faq-q:is(:hover, :focus-visible)::before,
.pj-faq-item[open] > .pj-faq-q::before { border-color: currentColor; background: color-mix(in srgb, currentColor 10%, transparent); }
body.pj .pj-faq-q:focus-visible { outline-offset: 4px; border-radius: var(--pj-radius-sm); }
@media (prefers-reduced-motion: no-preference) {
  .pj-faq-q::before { transition: background-color 0.2s ease, border-color 0.2s ease; }
  .pj-faq-q::after { transition: transform 0.25s ease; }
}
.pj-faq-a { padding: 0 3.5rem 1.5rem 0; }
body.pj .pj-faq .pj-faq-a > * { margin-left: 0; margin-right: 0; }
body.pj .pj-faq-a > :last-child { margin-bottom: 0; }
@media (max-width: 575.98px) {
  body.pj .pj-faq-q { padding-right: 3rem; }
  .pj-faq-a { padding-right: 0; }
}

/* ================================================================ Rental variants */
/* Opt-in section classes for rental / apartment releases (CONTENT-CONTRACT.md §4): .pj-checklist,
   .pj-price, .pj-stats--inline (modifier on .pj-stats) and .pj-tile-tints (Sectors). Tokens a
   tenant's CustomCss may set: --pj-tick / --pj-tick-ink, --pj-price-color, --pj-tint-1..4. */
:root { --pj-icon-tick: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6.5 12.5 4 4 7-8.5'/%3E%3C/svg%3E"); }

/* ---- .pj-checklist: bullet lists become ticks (a filled circle, the tick cut in --pj-tick-ink). */
body.pj .pj-checklist .section__content ul { list-style: none; padding-left: 0; }
body.pj .pj-checklist .section__content ul > li { position: relative; padding-left: 2.25rem; }
body.pj .pj-checklist .section__content ul > li::before,
body.pj .pj-checklist .section__content ul > li::after { content: ""; position: absolute; left: 0; top: 0.2em; width: 1.5rem; height: 1.5rem; }
body.pj .pj-checklist .section__content ul > li::before { border-radius: 50%; background: var(--pj-tick, var(--pj-primary)); }
body.pj .pj-checklist .section__content ul > li::after {
  background: var(--pj-tick-ink, var(--pj-on-primary));
  -webkit-mask: var(--pj-icon-tick) center / 80% no-repeat;
  mask: var(--pj-icon-tick) center / 80% no-repeat;
}
/* On a brand band the circle takes the band's text colour and the tick the band's colour. */
.pj-checklist:is(.pj-bg-primary, .pj-bg-dark) { --pj-tick: var(--pj-on-primary); --pj-tick-ink: var(--pj-primary); }
.pj-checklist.pj-bg-secondary { --pj-tick: var(--pj-on-secondary); --pj-tick-ink: var(--pj-secondary); }
.pj-checklist.pj-bg-accent { --pj-tick: var(--pj-on-accent); --pj-tick-ink: var(--pj-accent); }

/* ---- .pj-price: the body's first H3 is the display figure (a rent, "$650"), the paragraph straight
   after it the small print ("per week"). The section heading stays a normal H2. Exactly one element
   per block: h3:first-of-type is the first H3 among .section__content's children (a text section's
   eyebrow, H2 and body are one ContentBlock); the generator refuses pj-price without a body H3 or with
   bodyColumns (each column would be its own .section__content). Pairs with CountUp: project.js keeps
   the "$" as plain text. */
body.pj .pj-price .section__content > h3:first-of-type {
  max-width: none;
  margin-bottom: 0;
  font-size: clamp(4rem, 1.5rem + 10vw, 9.4rem);
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--pj-price-color, var(--pj-accent));
  font-variant-numeric: lining-nums;
}
body.pj .pj-price .section__content > h3:first-of-type + p { margin-top: 0.5rem; font-size: var(--pj-fs-small); letter-spacing: 0.08em; text-transform: uppercase; color: var(--pj-muted); }
/* On a brand band the figure takes the band's text colour (the accent would vanish on accent). */
body.pj .pj-price:is(.pj-bg-primary, .pj-bg-secondary, .pj-bg-accent, .pj-bg-dark, .pj-on-dark) .section__content > h3:first-of-type { color: inherit; }
body.pj .pj-price:is(.pj-bg-primary, .pj-bg-secondary, .pj-bg-accent, .pj-bg-dark, .pj-on-dark) .section__content > h3:first-of-type + p { color: inherit; opacity: 0.85; }

/* ---- .pj-stats--inline (with .pj-stats): the figure and its label share a baseline.
   Note: this block sits before the base .pj-stats rules ("a band of key figures", further down) and
   wins over them by specificity alone (each selector carries .pj-stats.pj-stats--inline). Keep both
   classes in these selectors, or move the block after the base rules. */
body.pj .pj-stats.pj-stats--inline .section__content { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center; column-gap: 0.75rem; }
body.pj .pj-stats.pj-stats--inline .section__content > :is(h2, h3, h4) + :is(h6, p) { margin-top: 0; }
body.pj .pj-stats.pj-stats--inline .section__content > :is(h6, p) { margin-bottom: 0; }
:is(.pj-stats--inline.widget-container, .pj-stats--inline .widget-row) { justify-content: space-between; }

/* ---- .pj-tile-tints (Sectors): each item a bordered card, its icon on a tinted tile (the four
   tints repeat). Sector icons should be transparent SVGs / PNGs so the tint shows behind them. */
.pj-tile-tints {
  --pj-tint-1: color-mix(in srgb, var(--pj-primary) 16%, #fff);
  --pj-tint-2: color-mix(in srgb, var(--pj-accent) 16%, #fff);
  --pj-tint-3: color-mix(in srgb, var(--pj-secondary) 16%, #fff);
  --pj-tint-4: color-mix(in srgb, #8c9a3e 24%, var(--pj-surface));
}
.pj-tile-tints .pj-sector { padding: 1.5rem; border: 1px solid var(--pj-line); border-radius: var(--pj-radius-lg); }
.pj-tile-tints .pj-sector:nth-child(4n + 1) { --_tint: var(--pj-tint-1); }
.pj-tile-tints .pj-sector:nth-child(4n + 2) { --_tint: var(--pj-tint-2); }
.pj-tile-tints .pj-sector:nth-child(4n + 3) { --_tint: var(--pj-tint-3); }
.pj-tile-tints .pj-sector:nth-child(4n + 4) { --_tint: var(--pj-tint-4); }
.pj-tile-tints .pj-sectors img.pj-sector-image { box-sizing: content-box; width: 2.25rem; height: 2.25rem; padding: 1rem; border-radius: var(--pj-radius-lg); background: var(--_tint); }

/* ================================================================ Gallery carousel */
/* Views/Widget-Images-Carousel.cshtml (an Images widget with MediaProfile "gallery-carousel"):
   .pj-gallery > ul.pj-gallery-track (a native scroll-snap row) > li.pj-gallery-slide > a.pj-gallery-link
   > img, then .pj-gallery-controls: .pj-gallery-dots (left) and .pj-gallery-nav > round
   .pj-gallery-prev / .pj-gallery-next (right). project.js §14 shows the controls (.is-ready) and keeps
   them in step with the scroll; without it the row simply scrolls / swipes. Cards per view: about 1.2 on
   phones (the next card peeks), 2.2 from 600px, 4 from 1100px. Tokens a tenant's CustomCss may set on
   .pj-gallery: --pj-gallery-per (cards per view), --pj-gallery-gap, --pj-gallery-ratio (card shape,
   default 4 / 5), --pj-gallery-radius, --pj-gallery-dot / --pj-gallery-dot-active. Buttons and dots take
   the button colours (--pj-btn-bg / -fg), so they invert on a pj-bg-* band. */
:root {
  --pj-icon-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E");
}
.pj-gallery {
  --pj-gallery-per: 1.2;
  --pj-gallery-gap: 0.875rem;
  --pj-gallery-ratio: 4 / 5;
  --pj-gallery-radius: var(--pj-radius-lg);
  position: relative;
  text-align: left;
}
@media (min-width: 600px) { .pj-gallery { --pj-gallery-per: 2.2; } }
@media (min-width: 1100px) { .pj-gallery { --pj-gallery-per: 4; } }
body.pj .pj-gallery-track {
  position: relative;
  display: flex;
  gap: var(--pj-gallery-gap);
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
}
/* Once project.js has shown the buttons and dots the scrollbar goes; without it the row keeps a thin
   one so a mouse user can still move it. */
.pj-gallery.is-ready .pj-gallery-track { scrollbar-width: none; }
.pj-gallery.is-ready .pj-gallery-track::-webkit-scrollbar { display: none; }
.pj-gallery:not(.is-ready) .pj-gallery-track { padding-bottom: 0.5rem; scrollbar-width: thin; }
body.pj .pj-gallery-slide {
  flex: 0 0 calc((100% - (var(--pj-gallery-per) - 1) * var(--pj-gallery-gap)) / var(--pj-gallery-per));
  min-width: 0;
  margin: 0;
  padding: 0;
  scroll-snap-align: start;
}
.pj-gallery-link { display: block; overflow: hidden; border-radius: var(--pj-gallery-radius); background: var(--pj-surface-alt); cursor: zoom-in; }
body.pj .pj-gallery-link:focus-visible { outline: 3px solid var(--pj-focus); outline-offset: -3px; }
.pj-gallery-link img { display: block; width: 100%; height: auto; aspect-ratio: var(--pj-gallery-ratio); object-fit: cover; }
.pj-gallery-controls { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-top: clamp(1.5rem, 1rem + 1.5vw, 2.25rem); }
.pj-gallery-controls[hidden] { display: none; }
.pj-gallery-dots { display: flex; flex-wrap: wrap; align-items: center; min-width: 0; margin-left: -8px; }
/* Each dot is a 24px target around an 8px dot. */
body.pj .pj-gallery-dot { position: relative; flex: none; width: 24px; height: 24px; margin: 0; padding: 0; border: 0; border-radius: 50%; background: transparent; cursor: pointer; }
.pj-gallery-dot::before { content: ""; position: absolute; top: 50%; left: 50%; width: 8px; height: 8px; margin: -4px 0 0 -4px; border-radius: 50%; background: var(--pj-gallery-dot, color-mix(in srgb, var(--pj-btn-bg) 35%, transparent)); }
.pj-gallery-dot[aria-current="true"]::before { background: var(--pj-gallery-dot-active, var(--pj-btn-bg)); transform: scale(1.25); }
.pj-gallery-dot:hover::before { background: var(--pj-gallery-dot-active, var(--pj-btn-bg)); }
body.pj .pj-gallery-dot:focus-visible { outline: 2px solid var(--pj-focus); outline-offset: -2px; }
.pj-gallery-nav { display: flex; flex: none; gap: 0.75rem; }
body.pj .pj-gallery-btn {
  position: relative;
  width: 48px;
  height: 48px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--pj-btn-bg);
  color: var(--pj-btn-fg);
  cursor: pointer;
}
.pj-gallery-btn::before {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 20px;
  height: 20px;
  background: currentColor;
  -webkit-mask: var(--pj-icon-arrow) center / contain no-repeat;
  mask: var(--pj-icon-arrow) center / contain no-repeat;
}
.pj-gallery-prev::before { transform: scaleX(-1); }
body.pj .pj-gallery-btn:hover:not(:disabled) { background: var(--pj-btn-bg-hover); }
body.pj .pj-gallery-btn:disabled { background: color-mix(in srgb, var(--pj-btn-bg) 18%, transparent); cursor: default; }
body.pj .pj-gallery-btn:focus-visible { outline: 3px solid var(--pj-focus); outline-offset: 3px; }
@media (prefers-reduced-motion: no-preference) {
  .pj-gallery-link img { transition: transform 0.5s cubic-bezier(.22, 1, .36, 1); }
  .pj-gallery-link:hover img { transform: scale(1.03); }
  .pj-gallery-btn, .pj-gallery-dot::before { transition: background-color 0.2s ease, transform 0.2s ease; }
}
@media print {
  body.pj .pj-gallery-track { flex-wrap: wrap; overflow: visible; }
  .pj-gallery-controls { display: none; }
}

/* Zoom viewer, grouped (gallery links carry data-pj-zoom-group, project.js §11): round prev / next
   either side of the image and an "n of N" count in the bar. A single image (the masterplan) gets none.
   Note: these come before the base viewer rules ("zoomable plan viewer", further down) and win by
   specificity alone (body.pj .pj-zoom ...): keep that prefix, or move the block after the base rules. */
body.pj .pj-zoom .pj-zoom-nav {
  position: absolute;
  top: calc(50% - 2.5rem);
  z-index: 1;
  width: 48px;
  height: 48px;
  margin: 0;
  padding: 0;
  border: 1px solid color-mix(in srgb, currentColor 45%, transparent);
  border-radius: 50%;
  background: color-mix(in srgb, var(--pj-primary) 70%, transparent);
  color: inherit;
  cursor: pointer;
}
body.pj .pj-zoom .pj-zoom-prev { left: var(--pj-gutter); }
body.pj .pj-zoom .pj-zoom-next { right: var(--pj-gutter); }
.pj-zoom-nav::before { content: ""; position: absolute; inset: 0; margin: auto; width: 20px; height: 20px; background: currentColor; -webkit-mask: var(--pj-icon-arrow) center / contain no-repeat; mask: var(--pj-icon-arrow) center / contain no-repeat; }
.pj-zoom-prev::before { transform: scaleX(-1); }
body.pj .pj-zoom .pj-zoom-nav:hover { background: var(--pj-primary); }
body.pj .pj-zoom-count { flex: none; margin: 0; font-size: var(--pj-fs-small); font-variant-numeric: tabular-nums; }
@media (max-width: 575.98px) {
  /* Room for the count and five buttons: the gesture hint goes on phones. */
  .pj-zoom--group .pj-zoom-hint { display: none; }
  body.pj .pj-zoom--group .pj-zoom-count { flex: 1 1 auto; }
}

/* ================================================================ forms */
/* Views/Widget-Input / Widget-TextArea / Widget-Select: visible labels (.pj-label), 52px fields,
   a clear focus ring, the submit button from the button system. */
body.pj form .px-2 { padding-left: 0 !important; padding-right: 0 !important; /* base field wrapper gutter; the form lays its own grid */ }
body.pj form .pj-field { margin: 0 0 1.1rem !important; }
body.pj form .widget-row { --bs-gutter-x: 0; column-gap: 1rem; }
@media (min-width: 768px) {
  body.pj form .widget-row > .widget-column.col-md-6 { flex: 0 0 calc(50% - 0.5rem); width: calc(50% - 0.5rem); max-width: calc(50% - 0.5rem); }
}
body.pj .pj-label { display: block; margin-bottom: 0.4rem; font-size: 0.9375rem; font-weight: 500; color: var(--pj-heading); }
body.pj .pj-required { color: var(--pj-accent); }
body.pj form :is(input[type="text"], input[type="email"], input[type="tel"], input[type="number"], input[type="date"], input[type="url"], select, textarea).form-control,
body.pj form :is(input[type="text"], input[type="email"], input[type="tel"], input[type="number"], input[type="date"], input[type="url"], select, textarea) {
  width: 100%;
  min-height: var(--pj-btn-h);
  padding: 0.75rem 1rem;
  border: 1px solid var(--pj-line-strong);
  border-radius: var(--pj-radius-field);
  background: color-mix(in srgb, #fff 85%, var(--pj-surface));
  color: var(--pj-text);
  font-size: 1rem;
  line-height: 1.4;
  box-shadow: none;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
body.pj form textarea { min-height: 9rem; resize: vertical; }
body.pj form select { appearance: auto; }
body.pj form :is(input, select, textarea):focus {
  outline: none;
  border-color: var(--pj-primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--pj-primary) 18%, transparent);
}
body.pj form .form-control::placeholder { color: color-mix(in srgb, var(--pj-text) 45%, var(--pj-surface)); opacity: 1; }
body.pj form .input-validation-error { border-color: var(--pj-accent); }
body.pj form .invalid-feedback { color: var(--pj-accent-dark); font-size: 0.875rem; }
body.pj form .form-check-input:checked { background-color: var(--pj-primary); border-color: var(--pj-primary); }
body.pj form :is(input[type="checkbox"], input[type="radio"]) { accent-color: var(--pj-primary); }
body.pj form :is(button[type="submit"], input[type="submit"]) { margin-top: 0.75rem; min-width: 12rem; }
@media (max-width: 575.98px) {
  body.pj form :is(button[type="submit"], input[type="submit"]) { width: 100% !important; }
}
body.pj form .block-paragraph { font-size: 0.875rem; color: var(--pj-muted); }
/* The form card on a brand band (.pj-contact with pj-bg-primary / -secondary / -accent / -dark, not
   .pj-form-minimal) is paper, so inside it the light-context tokens come back: dark text, the
   brand heading colour, solid primary buttons. */
body.pj .pj-contact:is(.pj-bg-primary, .pj-bg-secondary, .pj-bg-accent, .pj-bg-dark, .pj-on-dark):not(.pj-form-minimal) form {
  --pj-heading: var(--pj-primary);
  --pj-muted: color-mix(in srgb, var(--pj-text) 72%, var(--pj-surface));
  --pj-line: color-mix(in srgb, var(--pj-text) 14%, var(--pj-surface));
  --pj-line-strong: color-mix(in srgb, var(--pj-text) 32%, var(--pj-surface));
  --pj-link: color-mix(in srgb, var(--pj-accent) 78%, var(--pj-text));
  --pj-link-hover: var(--pj-primary);
  --pj-focus: var(--pj-accent);
  --pj-btn-bg: var(--pj-primary);
  --pj-btn-fg: var(--pj-on-primary);
  --pj-btn-bg-hover: var(--pj-primary-dark);
  --pj-btn-line: var(--pj-primary);
  color: var(--pj-text);
}
/* Inline errors (project.js §15 marks a step's invalid fields when Next is pressed). */
body.pj form [aria-invalid="true"]:not([type="radio"], [type="checkbox"]) { border-color: var(--pj-accent-dark); }
body.pj form .pj-field-error { display: block; margin: 0.4rem 0 0; color: var(--pj-accent-dark); font-size: 0.875rem; font-weight: 500; }

/* ---- multi-step forms: Containers with CssClass pj-step inside the form (CONTENT-CONTRACT.md §6).
   Without JavaScript every step shows, one under the other, and the form posts as one page.
   project.js §15 shows one step at a time ([hidden], never disabled, so every answer still posts),
   adds the progress (.pj-steps-progress: a bar of one segment per step and "Step n of N") above
   the first step and Back / Next (.pj-step-nav) to each step; the submit button is in the last. */
body.pj form .pj-step { --bs-gutter-x: 0; column-gap: 1rem; margin: 0; }
body.pj form .pj-step[hidden] { display: none; /* beats Bootstrap's .row display:flex */ }
@media (min-width: 768px) {
  body.pj form .pj-step > .widget-column.col-md-6 { flex: 0 0 calc(50% - 0.5rem); width: calc(50% - 0.5rem); max-width: calc(50% - 0.5rem); }
}
body.pj form .widget-column:has(> .pj-step) + .widget-column:has(> .pj-step:not([hidden])) { margin-top: 1.5rem; padding-top: 1.5rem !important; border-top: 1px solid var(--pj-line); /* no-JS: steps one under the other (p-0 is the base column's !important utility) */ }
body.pj form.pj-steps-ready .widget-column:has(> .pj-step) + .widget-column:has(> .pj-step) { margin-top: 0; padding-top: 0 !important; border-top: 0; }
body.pj form .pj-step :is(h2, h3, h4):first-child { margin-top: 0; }
body.pj form .pj-step :is(h2, h3, h4)[tabindex="-1"]:focus { outline: none; /* focused by script on a step change, for screen readers */ }
body.pj .pj-steps-progress { flex: 0 0 100%; width: 100%; margin: 0 0 1.25rem; }
body.pj .pj-steps-bar { display: flex; gap: 0.375rem; margin: 0 0 1.5rem; }
body.pj .pj-steps-bar > span { flex: 1 1 0; height: 6px; border-radius: 999px; background: var(--pj-line); transition: background-color 0.3s ease; }
body.pj .pj-steps-bar > span.is-done { background: var(--pj-primary); }
body.pj form .pj-steps-count { margin: 0; font-size: var(--pj-fs-small); color: var(--pj-muted); }
body.pj .pj-step-nav { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem; width: 100%; margin-top: 1.5rem; }
body.pj .pj-step-nav .pj-step-next { margin-left: auto; }
body.pj .pj-step-nav > button[hidden] { display: none; /* beats the button system's inline-flex */ }
body.pj .pj-step-nav--last { margin-top: 0.75rem; }
@media (max-width: 575.98px) {
  body.pj .pj-step-nav { flex-direction: column-reverse; align-items: stretch; }
  body.pj .pj-step-nav .pj-step-next { margin-left: 0; }
}
@media (prefers-reduced-motion: reduce) {
  body.pj .pj-steps-bar > span { transition: none; }
}

/* ---- choice cards: a radio Select with Display "cards" (Views/Widget-Select.cshtml). Each label is a
   card (icon, text, hint); the radio stays in the page, visually hidden but focusable, so arrow keys
   and screen readers work as for any radio group. The chosen card gets a tinted fill, a heavier
   primary border and a filled tick badge (the empty ring of the others), so it reads without colour. */
body.pj .pj-choice-cards .pj-choices { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.875rem; }
@media (min-width: 480px) {
  body.pj .pj-choice-cards .pj-choices { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
body.pj .pj-choice-cards .form-check.pj-choice { position: relative; display: block; min-height: 0; margin: 0; padding: 0; }
body.pj .pj-choice-cards .pj-choice > input {
  position: absolute; top: 0; left: 0; width: 1px; height: 1px; margin: 0; padding: 0; float: none;
  opacity: 0; overflow: hidden; clip-path: inset(50%); pointer-events: none;
}
body.pj .pj-choice-card {
  position: relative;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.3rem;
  height: 100%;
  min-height: 8.5rem;
  margin: 0;
  padding: 1.5rem 2.25rem 1.25rem;
  border: 2px solid var(--pj-line);
  border-radius: var(--pj-radius-lg);
  background: #fff;
  color: var(--pj-text);
  text-align: center;
  cursor: pointer;
  transition: border-color 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
}
body.pj .pj-choice-card:hover { border-color: var(--pj-line-strong); }
body.pj .pj-choice-icon { display: block; width: 2.5rem; height: 2.5rem; margin-bottom: 0.4rem; object-fit: contain; }
body.pj .pj-choice-text { font-size: 1.125rem; font-weight: 500; line-height: 1.3; }
body.pj .pj-choice-hint { font-size: var(--pj-fs-small); line-height: 1.35; color: var(--pj-muted); }
/* The badge: an empty ring, filled with a tick once chosen. */
body.pj .pj-choice-card::after {
  content: "";
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  width: 1.375rem;
  height: 1.375rem;
  box-sizing: border-box;
  border: 2px solid var(--pj-line-strong);
  border-radius: 50%;
  background: transparent center / 0.875rem no-repeat;
}
body.pj .pj-choice > input:checked + .pj-choice-card {
  border-color: var(--pj-primary);
  background: var(--pj-primary-soft);
  box-shadow: inset 0 0 0 1px var(--pj-primary);
}
body.pj .pj-choice > input:checked + .pj-choice-card::after {
  border-color: var(--pj-primary);
  background-color: var(--pj-primary);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5l3 3 6-7'/%3E%3C/svg%3E");
}
body.pj .pj-choice > input:focus-visible + .pj-choice-card { outline: 3px solid var(--pj-focus); outline-offset: 2px; }
body.pj .pj-choice-cards:has(input.is-invalid, input[aria-invalid="true"]) .pj-choice-card { border-color: var(--pj-accent-dark); }
@media (forced-colors: active) {
  body.pj .pj-choice > input:checked + .pj-choice-card { outline: 3px solid Highlight; outline-offset: -5px; }
  body.pj .pj-choice > input:checked + .pj-choice-card::after { background-color: Highlight; forced-color-adjust: none; }
}
@media (prefers-reduced-motion: reduce) {
  body.pj .pj-choice-card { transition: none; }
}

/* ================================================================ footer */
/* The Footer widget zone and the settings-driven legal band (Layout): one dark band on
   --pj-primary. The base Footer widget paints its BackgroundInfo colour inline on several
   boxes; the brand colour wins over it. */
.pj-footer-zone { background: var(--pj-primary); color: var(--pj-on-primary); }
.pj-footer-zone [style*="background-color"] { background-color: transparent !important; }
.pj-footer-zone :is(a, p, h2, h3, h4, h5, li, button) { color: inherit !important; }
.pj-footer-zone .pbroker-container { width: 100% !important; max-width: var(--pj-max); padding-left: var(--pj-gutter) !important; padding-right: var(--pj-gutter) !important; }
/* Widget-Footer.cshtml (project override): the bag content beside the footer-menu links. The
   bag's ContentBanner keeps its markup but not its own padding or container width. */
.pj-footer-inner {
  max-width: calc(var(--pj-max) + 2 * var(--pj-gutter));
  margin: 0 auto;
  padding: clamp(3rem, 2rem + 3vw, 4.5rem) var(--pj-gutter) 2rem;
  display: grid;
  gap: 2rem 3rem;
}
@media (min-width: 768px) { .pj-footer-inner--split { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); } }
.pj-footer-content .contentbanner > div { padding: 0 !important; }
.pj-footer-zone .pj-footer-content .pbroker-container { padding: 0 !important; max-width: none; }
.pj-footer-content .row { margin: 0; }
.pj-footer-content :is(.col-12, .widget-column) { padding: 0; }
.pj-footer-content .block-paragraph { margin: 0 0 0.35rem; opacity: 0.85; }
.pj-footer-content h4 { font-family: var(--pj-font-heading); margin: 0 0 0.75rem; }
.pj-footer-heading { font-size: var(--pj-fs-xs); letter-spacing: 0.12em; text-transform: uppercase; margin: 0 0 0.75rem; opacity: 0.75; }
.pj-footer-links { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.4rem; }
@media (min-width: 768px) { .pj-footer-nav { justify-self: end; text-align: right; } }
.pj-footer-links a { text-decoration: none; }
.pj-footer-links a:hover, .pj-footer-links a:focus-visible { text-decoration: underline; }
.pj-legal {
  --pj-heading: currentColor;
  --pj-muted: color-mix(in srgb, currentColor 72%, transparent);
  --pj-line: color-mix(in srgb, currentColor 20%, transparent);
  --pj-focus: currentColor;
  background: var(--pj-primary);
  color: var(--pj-on-primary);
}
.pj-footer-zone + .pj-legal .pj-legal-inner { background: linear-gradient(var(--pj-line), var(--pj-line)) top center / calc(100% - 2 * var(--pj-gutter)) 1px no-repeat; }
.pj-legal-inner {
  max-width: calc(var(--pj-max) + 2 * var(--pj-gutter));
  margin: 0 auto;
  padding: clamp(3rem, 2rem + 4vw, 5rem) var(--pj-gutter) 2.5rem;
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem 3rem;
  font-size: var(--pj-fs-small);
  line-height: 1.6;
}
@media (min-width: 768px) {
  .pj-legal-inner { grid-template-columns: minmax(0, 1fr) auto; align-items: end; }
  .pj-legal-brand { grid-column: 1; }
  .pj-legal-lockup { grid-column: 2; grid-row: 1; justify-self: end; }
  .pj-legal-text, .pj-legal-disclaimer { grid-column: 1 / -1; }
}
body.pj .pj-legal-brand { display: inline-block; align-self: start; justify-self: start; line-height: 0; }
.pj-legal-logo { display: block; height: clamp(3.5rem, 3rem + 2vw, 5rem); width: auto; max-width: 240px; object-fit: contain; object-position: left center; }
.pj-legal-logo--invert { filter: brightness(0) invert(1); }
.pj-legal-lockup { display: block; max-height: 56px; max-width: 280px; width: auto; height: auto; }
.pj-legal-text, .pj-legal-disclaimer { margin: 0; }
body.pj .pj-legal-text { color: inherit; }
.pj-legal-text { padding-top: 1.5rem; border-top: 1px solid var(--pj-line); }
body.pj .pj-legal-disclaimer { font-size: var(--pj-fs-xs); line-height: 1.6; color: var(--pj-muted); max-width: 60rem; }
.pj-legal-brand + .pj-legal-disclaimer,
.pj-legal-lockup + .pj-legal-disclaimer { padding-top: 1.5rem; border-top: 1px solid var(--pj-line); }
.pj-legal a { color: inherit; }
/* Social icons (ProjectBranding.SocialLinks) and the copyright line (ProjectBranding.Copyright), last in
   the band. Icons take the band's text colour (.pj-social-link--{network} for a per-network colour). */
.pj-social { grid-column: 1 / -1; list-style: none; display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0; padding: 0; }
body.pj .pj-social-link { display: inline-grid; place-items: center; width: 44px; height: 44px; border-radius: 50%; color: inherit; transition: background-color 0.2s ease; }
body.pj .pj-social-link:is(:hover, :focus-visible) { background: color-mix(in srgb, currentColor 14%, transparent); color: inherit; }
.pj-social-link svg { display: block; width: 22px; height: 22px; }
body.pj .pj-legal-copyright { grid-column: 1 / -1; margin: 0; font-size: var(--pj-fs-xs); color: var(--pj-muted); }

/* ================================================================ opt-in features */
/* Each of these does nothing until a page or setting asks for it (CONTENT-CONTRACT.md §3, §4):
   section eyebrows, key-figure bands, stage strips, numbered nearby lists, lot schedule tabs, the
   zoomable plan viewer, inline video, the minimal form and inline thank-you, the full-screen menu.
   Tokens: --pj-ease (the reveal easing), --pj-anim-step / --pj-anim-load-delay (project.js),
   --pj-nav-solid-after (project.js), --pj-hero-logo (hero lockup image). */
:root { --pj-ease: cubic-bezier(0.22, 1, 0.36, 1); }

/* Project widget eyebrow (ProjectSection.Eyebrow), above the heading. */
body.pj .pj-block-eyebrow { margin: 0 0 0.9rem; }
.pj-center .pj-block-eyebrow { text-align: center; }


/* ---- photo grid (Images widget, Media Profile "Gallery grid": Views/Widget-Images-PhotoGrid.cshtml):
   square thumbnails, 2 to a row on phones, 3 from 768px, 4 from 1100px. Each opens the grouped zoom
   viewer (project.js §11, .pj-zoom--group). */
body.pj ul.pj-photo-grid { list-style: none; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; margin: 0 0 2rem; padding: 0; }
@media (min-width: 768px) { body.pj ul.pj-photo-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; } }
@media (min-width: 1100px) { body.pj ul.pj-photo-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.pj-photo-grid-item { margin: 0; }
body.pj .pj-photo-grid-link { position: relative; display: block; overflow: hidden; aspect-ratio: 1 / 1; background: var(--pj-surface-alt); border-radius: var(--pj-radius-sm); cursor: zoom-in; }
.pj-photo-grid-link img { display: block; width: 100%; height: 100%; object-fit: cover; }
body.pj .pj-photo-grid-link:focus-visible { outline: 3px solid var(--pj-focus); outline-offset: 2px; }
@media (prefers-reduced-motion: no-preference) {
  .pj-photo-grid-link img { transition: transform 0.4s var(--pj-ease), opacity 0.3s ease; }
  .pj-photo-grid-link:is(:hover, :focus-visible) img { transform: scale(1.04); opacity: 0.92; }
}

/* ---- entrance animations (LayoutOptions.Animation; project.js marks the items). */
.pj-reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 1.1s var(--pj-ease), transform 1.1s var(--pj-ease);
  transition-delay: var(--pj-reveal-delay, 0ms);
}
.pj-reveal.is-visible { opacity: 1; transform: none; }
.pj-reveal--load { transition: none; animation: pj-fade-up 1s var(--pj-ease) var(--pj-reveal-delay, 0ms) both; }
@keyframes pj-fade-up { from { opacity: 0; transform: translateY(22px); } to { opacity: 1; transform: none; } }
@media print { .pj-reveal { opacity: 1 !important; transform: none !important; animation: none !important; } }

/* ---- count-up numbers (LayoutOptions.CountUp). */
.pj-count-num { font-variant-numeric: tabular-nums lining-nums; }

/* ---- .pj-stats: a band of key figures (a Container or section of content blocks, one figure
   each: a heading with the number, an H6 label). Two per row, four from 1120px, hairline rules. */
.pj-stats { border-top: 1px solid var(--pj-line); border-bottom: 1px solid var(--pj-line); }
:is(.pj-stats.widget-container, .pj-stats .widget-row) { --bs-gutter-x: 0; margin-left: 0; margin-right: 0; flex-wrap: wrap; }
:is(.pj-stats.widget-container, .pj-stats .widget-row) > .widget-column { flex: 0 0 50%; width: 50%; max-width: 50%; }
:is(.pj-stats.widget-container, .pj-stats .widget-row) > .widget-column > .widget { padding: clamp(1.25rem, 1rem + 1.5vw, 2.5rem) clamp(1rem, 0.5rem + 2vw, 3rem) !important; height: 100%; }
:is(.pj-stats.widget-container, .pj-stats .widget-row) > .widget-column:nth-child(even) { border-left: 1px solid var(--pj-line); }
:is(.pj-stats.widget-container, .pj-stats .widget-row) > .widget-column:nth-child(n + 3) { border-top: 1px solid var(--pj-line); }
body.pj .pj-stats .section__content { text-align: left; }
body.pj .pj-stats .section__content > * { max-width: none; margin-left: 0; margin-right: 0; }
body.pj .pj-stats .section__content :is(h2, h3, h4) { margin: 0; font-size: clamp(1.875rem, 1.4rem + 1.6vw, 3rem); line-height: 1; white-space: nowrap; }
body.pj .pj-stats .section__content :is(h2, h3, h4) + :is(h6, p) { margin-top: 1rem; }
/* A unit straight after the number (project.js wraps it): small, beside the figure. */
.pj-stats .pj-count-unit { margin: 0 0.15em 0 0.3em; font-size: max(0.75rem, 0.3em); letter-spacing: 0; opacity: 0.7; }
@media (min-width: 1120px) {
  :is(.pj-stats.widget-container, .pj-stats .widget-row) { flex-wrap: nowrap; }
  :is(.pj-stats.widget-container, .pj-stats .widget-row) > .widget-column { flex: 1 1 auto; width: auto; max-width: none; }
  :is(.pj-stats.widget-container, .pj-stats .widget-row) > .widget-column + .widget-column { border-left: 1px solid var(--pj-line); }
  :is(.pj-stats.widget-container, .pj-stats .widget-row) > .widget-column:nth-child(n + 3) { border-top: 0; }
}

/* ---- .pj-strip: a row of cards between hairline rules (e.g. stages). The last paragraph of each
   card reads as a small status tag. Stacked under 768px. */
@media (min-width: 768px) {
  body.pj .pj-strip .widget-row:not(form .widget-row) > .widget-column + .widget-column > .widget { padding-left: clamp(1.5rem, 3vw, 2.5rem); border-left: 1px solid var(--pj-line); }
  body.pj .pj-strip .widget-row > .widget-column > .widget { padding-right: clamp(1.5rem, 3vw, 2.5rem); height: 100%; }
}
@media (max-width: 767.98px) {
  body.pj .pj-strip .widget-row > .widget-column + .widget-column { margin-top: 0; }
  body.pj .pj-strip .widget-row > .widget-column > .widget { padding: 2rem 0; border-top: 1px solid var(--pj-line); }
}
body.pj .pj-strip .section__content > :is(h2, h3) { margin: 0.75rem 0 0; }
body.pj .pj-strip .section__content > p { margin: 0.75rem 0 0; font-size: var(--pj-fs-small); color: var(--pj-muted); }
body.pj .pj-strip .section__content > p:last-child:not(:first-child) {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 1.75rem;
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--pj-line-strong);
  background: color-mix(in srgb, currentColor 6%, transparent);
  font-size: 0.6875rem;
  letter-spacing: var(--pj-eyebrow-tracking);
  text-transform: uppercase;
}
body.pj .pj-strip .section__content > p:last-child:not(:first-child)::before { content: ""; width: 6px; height: 6px; background: currentColor; opacity: 0.75; }

/* ---- .pj-colophon: a closing credits section (e.g. who markets and develops the project): a
   full-width first block (a centred logo) above columns of small text under a hairline. */
body.pj .pj-colophon .widget-row:not(form .widget-row) > .widget-column.col-md-12:first-child .section__content { text-align: center; }
body.pj .pj-colophon .widget-row:not(form .widget-row) > .widget-column.col-md-12:first-child figure.block-image { margin: 0 auto; }
body.pj .pj-colophon .widget-row:not(form .widget-row) > .widget-column.col-md-12:first-child ~ .widget-column:not(.col-md-12) { margin-top: clamp(2.5rem, 2rem + 2vw, 4rem); }
body.pj .pj-colophon .widget-row:not(form .widget-row) > .widget-column:not(.col-md-12) { border-top: 1px solid var(--pj-line); padding-top: 3rem !important; }
body.pj .pj-colophon .widget-row:not(form .widget-row) > .widget-column:not(.col-md-12) .section__content { font-size: var(--pj-fs-small); }
body.pj .pj-colophon .widget-row:not(form .widget-row) > .widget-column:not(.col-md-12) .section__content > p { margin: 0 0 0.6rem; }
body.pj .pj-colophon .widget-row:not(form .widget-row) > .widget-column:not(.col-md-12) figure.block-image { margin: 0.5rem 0 1.25rem; }
@media (max-width: 767.98px) {
  body.pj .pj-colophon .widget-row:not(form .widget-row) > .widget-column:not(.col-md-12) + .widget-column:not(.col-md-12) { border-top: 0; padding-top: 0 !important; }
}

/* ---- .pj-nearby--list (NearbyPlaces): the map beside a numbered list of places (number circle,
   name, then the distance with the blurb under it on the right), the numbers matching a map that
   has them marked. */
.pj-nearby--list .pj-places { display: block; counter-reset: pj-place; border-top: 1px solid var(--pj-line); }
@media (min-width: 992px) {
  .pj-nearby--list .pj-nearby--with-map { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); align-items: center; gap: clamp(2.5rem, 4vw, 3.5rem); }
  .pj-nearby--list .pj-nearby--with-map .pj-map { position: static; }
}
.pj-nearby--list .pj-place {
  counter-increment: pj-place;
  display: grid;
  grid-template-columns: 1.75rem minmax(0, 1fr);
  column-gap: 1rem;
  align-items: center;
  padding: 1.25rem 0;
  border-bottom: 1px solid var(--pj-line);
}
.pj-nearby--list .pj-place::before {
  content: counter(pj-place);
  grid-row: 1 / span 2;
  display: grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  border: 1px solid var(--pj-accent);
  border-radius: 50%;
  color: var(--pj-accent);
  font-size: 0.6875rem;
  font-variant-numeric: tabular-nums;
}
.pj-nearby--list .pj-place-image { display: none; }
.pj-nearby--list .pj-place-name { grid-column: 2; font-weight: 400; }
body.pj .pj-nearby--list .pj-place-distance { grid-column: 2; position: static; padding: 0; background: none; box-shadow: none; border-radius: 0; font-size: 1rem; font-weight: 500; letter-spacing: 0; color: var(--pj-heading); }
.pj-nearby--list .pj-place-blurb { grid-column: 2; }
@media (min-width: 640px) {
  .pj-nearby--list .pj-place { grid-template-columns: 1.75rem minmax(0, 1fr) auto; }
  .pj-nearby--list .pj-place::before { grid-row: 1 / span 2; }
  .pj-nearby--list .pj-place-name { grid-row: 1 / span 2; }
  body.pj .pj-nearby--list .pj-place-distance { grid-column: 3; grid-row: 1; text-align: right; }
  .pj-nearby--list .pj-place-blurb { grid-column: 3; grid-row: 2; text-align: right; }
  .pj-nearby--list .pj-place:not(:has(.pj-place-blurb)) .pj-place-distance { grid-row: 1 / span 2; }
}

/* ---- lot schedule tabs (AvailabilityTable.Filters "tabs"). */
body.pj .pj-lots--tabs .pj-block-header { max-width: none; display: grid; grid-template-columns: minmax(0, 1fr); gap: 0 2rem; padding-bottom: 1.25rem; margin-bottom: 2rem; border-bottom: 1px solid var(--pj-heading); }
@media (min-width: 768px) {
  .pj-lots--tabs .pj-block-header { grid-template-columns: minmax(0, 1fr) auto; align-items: end; }
  .pj-lots--tabs .pj-block-header > :not(.pj-lots-summary) { grid-column: 1; }
  .pj-lots--tabs .pj-lots-summary { grid-column: 2; grid-row: 1 / span 3; align-self: end; text-align: right; }
}
body.pj .pj-lots-summary { margin: 0.75rem 0 0; font-size: var(--pj-fs-small); color: var(--pj-muted); }
.pj-lot-tabs { display: flex; flex-wrap: wrap; gap: 0.75rem; margin: 0 0 2.5rem; }
.pj-lot-tabs[hidden] { display: none; }
body.pj .pj-lot-tab {
  display: inline-flex;
  align-items: center;
  gap: 0.9em;
  min-height: 2.75rem;
  padding: 0 1.5rem;
  border: 1px solid var(--pj-line);
  border-radius: var(--pj-radius-btn);
  background: transparent;
  color: var(--pj-muted);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: var(--pj-eyebrow-tracking);
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}
body.pj .pj-lot-tab:is(:hover, :focus-visible) { background: var(--pj-accent); border-color: var(--pj-accent); color: var(--pj-on-accent); }
body.pj .pj-lot-tab.is-active { background: var(--pj-heading); border-color: var(--pj-heading); color: var(--pj-surface); }
.pj-lot-tab-count { opacity: 0.6; }
.pj-lot-enter { animation: pj-row-in 0.55s var(--pj-ease) var(--pj-row-delay, 0ms) both; }
@keyframes pj-row-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
/* Tabs mode on phones and small tablets: each lot is a card (the lot number and its status chip on
   top, then every other cell as a labelled line, the land area included), so no column is ever
   off-screen. The tabs filter the cards and they fade in as the rows do. */
@media (max-width: 767.98px) {
  .pj-lots--tabs .pj-table-wrap { overflow: visible; }
  .pj-lots--tabs .pj-lots thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .pj-lots--tabs .pj-lots, .pj-lots--tabs .pj-lots tbody { display: block; }
  .pj-lots--tabs .pj-lots tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 0.45rem 1rem; padding: 1.1rem 0; border-bottom: 1px solid var(--pj-line); }
  .pj-lots--tabs .pj-lots tr:first-child { border-top: 1px solid var(--pj-heading); }
  .pj-lots--tabs .pj-lots tr[hidden] { display: none !important; }
  .pj-lots--tabs .pj-lots :is(th, td) { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; grid-column: 1 / -1; padding: 0; border: 0; text-align: right; }
  body.pj .pj-lots--tabs .pj-lots th.pj-lot-number { grid-column: 1; grid-row: 1; justify-content: flex-start; align-items: center; gap: 0.3em; margin: 0; font-size: 1.25rem; text-align: left; }
  .pj-lots--tabs .pj-lots td.pj-lot-status { grid-column: 2; grid-row: 1; justify-content: flex-end; align-items: center; }
  .pj-lots--tabs .pj-lots .pj-lot-label { position: static; width: auto; height: auto; overflow: visible; clip: auto; }
  .pj-lots--tabs .pj-lots td::before { content: attr(data-label); content: attr(data-label) / ""; flex: none; color: var(--pj-muted); font-size: 0.875rem; font-weight: 400; text-align: left; }
  .pj-lots--tabs .pj-lots td.pj-lot-status::before { content: none; }
  .pj-lots--tabs .pj-lots .pj-lot-extra { display: flex; }
  .pj-lots--tabs .pj-lots td:empty { display: none; }
  .pj-lots--tabs .pj-lots .pj-lot-stage { flex: initial; white-space: normal; overflow: visible; }
  .pj-lots--tabs .pj-lot:hover { background: transparent; }
}

/* ---- zoomable plan viewer (Masterplan.Viewer "zoom"). The chip shows on phones only. */
.pj-masterplan--zoom .pj-masterplan-image { cursor: zoom-in; }
@media (min-width: 768px) { .pj-masterplan--zoom .pj-masterplan-open { display: none; } }
.pj-zoom:not([open]) { display: none; }
.pj-zoom {
  position: fixed;
  inset: 0;
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: var(--pj-primary);
  color: var(--pj-on-primary);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.pj-zoom::backdrop { background: rgb(var(--pj-primary-rgb) / 0.9); }
.pj-zoom-stage { position: relative; flex: 1 1 auto; overflow: hidden; display: grid; place-items: center; touch-action: none; cursor: grab; }
.pj-zoom-stage:active { cursor: grabbing; }
.pj-zoom-img { max-width: 100%; max-height: 100%; user-select: none; transform-origin: center; will-change: transform; }
.pj-zoom-bar { flex: none; display: flex; align-items: center; gap: 0.5rem; padding: 0.75rem var(--pj-gutter); border-top: 1px solid color-mix(in srgb, currentColor 18%, transparent); }
body.pj .pj-zoom-hint { flex: 1 1 auto; margin: 0; font-size: 0.75rem; opacity: 0.7; }
body.pj .pj-zoom-btn { flex: none; width: 44px; height: 44px; border: 1px solid color-mix(in srgb, currentColor 45%, transparent); border-radius: var(--pj-radius-btn); background: transparent; color: inherit; font-size: 1.375rem; line-height: 1; cursor: pointer; }
body.pj .pj-zoom-btn:disabled { opacity: 0.35; cursor: default; }
body.pj .pj-zoom-close { background: var(--pj-accent); border-color: var(--pj-accent); color: var(--pj-on-accent); }
body.pj .pj-zoom :focus-visible { outline-color: currentColor; }

/* ---- inline video: an image block linked to a video file (project.js adds the play button). */
.pj-video-link { position: relative; display: block; }
.pj-play {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 4rem;
  height: 4rem;
  margin: -2rem 0 0 -2rem;
  border: 1px solid rgb(255 255 255 / 0.45);
  border-radius: 50%;
  background: rgb(var(--pj-primary-rgb) / 0.35);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  transition: transform 0.3s ease;
}
@media (min-width: 640px) { .pj-play { width: 5rem; height: 5rem; margin: -2.5rem 0 0 -2.5rem; } }
.pj-play::before { content: ""; position: absolute; top: 50%; left: 50%; margin: -0.5rem 0 0 -0.3rem; border-style: solid; border-width: 0.5rem 0 0.5rem 0.8rem; border-color: transparent transparent transparent #fff; transition: border-color 0.3s ease; }
.pj-play::after { content: ""; position: absolute; inset: -1px; border: 1px solid rgb(255 255 255 / 0.6); border-radius: 50%; opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
  .pj-play::after { animation: pj-pulse 2.8s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
}
@keyframes pj-pulse { 0% { opacity: 0.55; transform: scale(1); } 70%, 100% { opacity: 0; transform: scale(1.75); } }
.pj-video-link:is(:hover, :focus-visible) .pj-play { transform: scale(1.1); }
.pj-video-link:is(:hover, :focus-visible) .pj-play::before { border-left-color: var(--pj-accent); }
.pj-video-wrap { position: relative; }
.pj-video { display: block; width: 100%; height: auto; background: #000; }
body.pj .pj-video-error { margin: 0.75rem 0 0; font-size: var(--pj-fs-small); }

/* ---- .pj-form-minimal (on the section holding a form): underline-only fields with the label
   sitting in the field like a placeholder until it is focused or filled; the select's own first
   option is its prompt (its label is kept for screen readers only). */
body.pj .pj-form-minimal form { padding: 0; background: transparent; border-radius: 0; box-shadow: none; }
body.pj .pj-form-minimal form .pj-field { position: relative; margin: 0 0 1.75rem !important; }
body.pj .pj-form-minimal form :is(input[type="text"], input[type="email"], input[type="tel"], input[type="number"], input[type="url"], select, textarea) {
  min-height: 3.5rem;
  padding: 1rem 0;
  border: 0;
  border-bottom: 1px solid var(--pj-line-strong);
  border-radius: 0;
  background: transparent;
  color: inherit;
}
body.pj .pj-form-minimal form :is(input, select, textarea):focus { border-bottom-color: var(--pj-accent); box-shadow: none; }
body.pj .pj-form-minimal form .pj-label {
  position: absolute;
  top: 1rem;
  left: 0;
  margin: 0;
  font-weight: 300;
  font-size: 1rem;
  color: var(--pj-muted);
  pointer-events: none;
  transition: transform 0.2s ease, font-size 0.2s ease, top 0.2s ease;
}
body.pj .pj-form-minimal form .pj-field:has(:is(input, textarea):focus, :is(input, textarea):not(:placeholder-shown)) .pj-label { top: -0.5rem; font-size: 0.6875rem; letter-spacing: 0.08em; }
body.pj .pj-form-minimal form .pj-field:has(select) .pj-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
body.pj .pj-form-minimal form select option { color: var(--pj-text); }
/* A radio / checkbox group (fieldset, Widget-Select) is not a floating label: a radio is never
   :placeholder-shown, so the rules above would lift its legend out of flow over the options or cards.
   The legend stays in flow, set like a floated label. (0,6,5) beats the floated-label rule (0,5,3);
   colour is left to the rules above and the tenant's CustomCss. */
body.pj .pj-form-minimal form fieldset.pj-field:has(:is(input[type="radio"], input[type="checkbox"])) > legend.pj-label {
  position: static;
  top: auto;
  left: auto;
  float: none;
  width: auto;
  margin: 0 0 0.75rem;
  padding: 0;
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  pointer-events: auto;
  transition: none;
}
/* A field with its own placeholder as well as a label: the placeholder shows once the label has floated up. */
body.pj .pj-form-minimal form .pj-field:has(.pj-label) :is(input, textarea)::placeholder { color: transparent; }
body.pj .pj-form-minimal form .pj-field:has(.pj-label) :is(input, textarea):focus::placeholder { color: var(--pj-muted); }
.pj-form-thanks { padding: 1rem 0; outline: none; }
body.pj .pj-form-thanks p { margin: 0; font-family: var(--pj-font-heading); font-size: var(--pj-fs-h3); line-height: 1.35; color: var(--pj-heading); }
body.pj .pj-form-thanks .pj-form-thanks-text { margin-top: 0.5rem; font-size: var(--pj-fs-lead); color: var(--pj-muted); }

/* ---- full-screen menu (ProjectBranding.MenuStyle "overlay", body.pj-menu-overlay): the menu
   collapses under 1280px instead of 992px, into a full-screen panel on the primary colour with
   large links and a full-width accent button. Same markup and script as the drop-down panel. */
@media (min-width: 992px) and (max-width: 1279.98px) {
  body.pj-menu-overlay .pj-burger { display: flex; margin-left: auto; margin-right: -10px; }
  body.pj-menu-overlay .pj-nav-panel { display: none; position: fixed; top: var(--pj-nav-h); left: 0; right: 0; bottom: 0; overflow-y: auto; flex-direction: column; align-items: stretch; justify-content: flex-start; }
  body.pj-menu-overlay.pj-nav-open .pj-nav-panel { display: flex; }
  body.pj.pj-menu-overlay.pj-nav-open { overflow: hidden; }
  body.pj-menu-overlay .pj-menu { flex-direction: column; align-items: stretch; }
  body.pj-menu-overlay .pj-menu-item { display: flex; flex-wrap: wrap; align-items: center; }
  body.pj.pj-menu-overlay .pj-menu--main > .pj-menu-item > .pj-menu-link::after { display: none; }
  body.pj-menu-overlay .pj-sub-toggle { display: block; flex: 0 0 44px; height: 44px; border: 0; background: transparent; color: inherit; }
  body.pj-menu-overlay .pj-submenu { position: static; flex: 1 0 100%; display: none; visibility: visible; opacity: 1; box-shadow: none; border: 0; padding: 0 0 0.75rem 1rem; background: transparent; }
  body.pj-menu-overlay .pj-menu-item.is-open > .pj-submenu { display: block; }
  body.pj-menu-overlay .pj-sub-toggle::before { content: ""; display: block; width: 10px; height: 10px; margin: 0 auto; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor; transform: rotate(45deg); transition: transform 0.2s ease; }
  body.pj-menu-overlay .pj-menu-item.is-open > .pj-sub-toggle::before { transform: rotate(-135deg); }
}
@media (max-width: 1279.98px) {
  body.pj-menu-overlay .pj-nav-panel { padding: 1.5rem var(--pj-gutter) 2.5rem; background: var(--pj-primary); color: var(--pj-on-primary); border-top: 0; }
  body.pj-menu-overlay.pj-nav-open #mainNav.pj-nav { background: var(--pj-primary); color: var(--pj-on-primary); border-bottom-color: transparent; box-shadow: none; }
  body.pj-menu-overlay.pj-nav-open #mainNav .pj-logo-link:has(.pj-logo--reversed) .pj-logo--primary { display: none; }
  body.pj-menu-overlay.pj-nav-open #mainNav .pj-logo--reversed { display: block; }
  body.pj-menu-overlay .pj-nav-panel .pj-menu-item { border-bottom: 1px solid color-mix(in srgb, currentColor 10%, transparent); }
  body.pj.pj-menu-overlay .pj-nav-panel .pj-menu--main .pj-menu-link { flex: 1 1 auto; padding: 1.25rem 0; font-family: var(--pj-font-heading); font-size: clamp(1.75rem, 1.2rem + 2.5vw, 2.25rem); font-weight: var(--pj-heading-weight); letter-spacing: -0.01em; text-transform: none; color: color-mix(in srgb, currentColor 85%, transparent); }
  body.pj.pj-menu-overlay .pj-nav-panel .pj-menu--main .pj-menu-link:is(:hover, :focus-visible) { color: currentColor; }
  body.pj-menu-overlay .pj-nav-panel .pj-submenu { color: inherit; }
  body.pj.pj-menu-overlay .pj-nav-panel .pj-submenu .pj-menu-link { padding: 0.6rem 0; font-family: var(--pj-font-body); font-size: 1.0625rem; }
  body.pj-menu-overlay .pj-nav-panel .pj-menu--right { margin-top: 2rem; }
  body.pj.pj-menu-overlay .pj-nav-panel .pj-menu--right > .pj-menu-item { border-bottom: 0; }
  body.pj.pj-menu-overlay .pj-nav-panel .pj-menu--right > .pj-menu-item > .pj-menu-link { flex: 1 1 auto; justify-content: center; min-height: var(--pj-btn-h); background: var(--pj-accent); border-color: var(--pj-accent); color: var(--pj-on-accent); }
}

/* ---- deferred section backgrounds (project.js §13): until a banner below the page hero nears the
   viewport (.pj-bg-in) only its small blurred copy paints, so its full photo is not downloaded with
   the page. The first banner on a page is never deferred. html.pj-lazy-bg is set by the Layout and
   removed again if project.js never ran; print always gets the full photos. */
@media screen {
  html.pj-lazy-bg body.pj .pj-page .contentbanner:not(:has(> a#page-hero)):not(.pj-page > .contentbanner:first-child):not(.pj-page > .pj-section:first-child > .contentbanner) .media-box[style*="--pb-bg-main"]:not(.pj-bg-in) {
    background-image: var(--pb-bg-gradient, none), var(--pb-bg-lowres, none);
  }
}

/* A section focused by an in-page link (project.js §2b) shows no focus ring of its own. */
body.pj [data-pj-focus-target]:is(:focus, :focus-visible) { outline: none; }

/* Touch screens: theme links that sit on their own line get a 44px tall hit area. */
@media (pointer: coarse) {
  .pj-footer-links { row-gap: 0; }
  body.pj .pj-footer-links a,
  body.pj :is(.pj-agent-phone, .pj-agent-email) { display: inline-flex; align-items: center; min-height: 44px; }
}

/* ================================================================ motion */
@media (prefers-reduced-motion: reduce) {
  body.pj *, body.pj *::before, body.pj *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; }
  /* Opt-in motion off entirely (project.js does not mark items either; this covers a late change). */
  .pj-reveal, .pj-reveal--load, .pj-lot-enter { opacity: 1 !important; transform: none !important; animation: none !important; transition: none !important; }
}
