/* Simpli Management 2.0 — marketing layer: the light variant of the public shell.

   Linked by Views/Shared/_Layout.cshtml and _ValuationToolLayout.cshtml, AFTER Bootstrap 5.2.2,
   site.css, tokens.css and app.css, with asp-append-version. It is never @imported: tokens.css's
   @import chain is unversioned, and this file has to change in step with the layouts.

   NOT a cascade layer, for the reason app.css gives: Bootstrap and site.css are unlayered, and an
   unlayered rule always beats a layered one.

   HOW THE LIGHT VARIANT WORKS. `.sm-site` goes on _Layout's <body> and REDECLARES the semantic
   aliases that app.css components consume (--surface*, --border*, --text*, --brand-text, the
   status text colours, the elevation and focus tokens). An alias is resolved where it is declared
   and inherited as a value, so rebinding a ramp step (--ink-900) would change nothing; the aliases
   themselves have to be redeclared. With that done, .sm-card, .sm-badge, .sm-alert, .sm-btn and
   the rest render light on marketing pages with no --on-light modifier.

   DARK SCOPES INSIDE THE LIGHT SITE (section 2). Two kinds.
   - Islands. The public apply flow (Building/ViewAvailableUnits, ViewAvailableUnit,
     ApplyToAvailableUnit, ViewPayApplicationFee) renders as dark `<div class="sm-app …">` blocks
     inside this layout, and stays dark (decision D3). `.sm-public-dark` is the generic public-dark
     scope stage 2D adopts for those views and the error pages (D2). Both get the :root dark
     values back, and so does <body> on any page that holds one, because .sm-site paints <body>'s
     canvas from <body>'s own aliases, and app.css section 19 bridges the TempData notices from
     them.
   - Marketing dark bands: .sm-section--ink, .sm-cta-band, .sm-screen (the app-window frame),
     .sm-ink-panel (the calculator result), and the site nav and footer.
   The dark values are not copied from tokens/colors.css by hand. Section 0 snapshots each alias
   on :root, where only the dark theme is ever declared, and section 2 hands the snapshot back. So
   the islands always get exactly what :root resolves to, including app.css's own redeclarations
   (the 0.2 gap focus ring, the 0.3 field-border hover), and the two cannot drift. That requires
   `.sm-site` to stay on <body>: on <html> the snapshot would capture the light values.

   SPECIFICITY AGAINST site.css. site.css is linked before this file, so an equal-weight selector
   here already wins by source order. Element rules are therefore written at the element's own
   weight — `:where(.sm-site) a` is (0,0,1), the same as site.css's `a{color:#0366d6}` — so they
   win that tie and still lose to every class: .btn-login, .nav-link, .text-light, .sm-btn keep
   their own colours. Island content is excluded from every element rule with
   `:not(:where(.sm-app *, .sm-public-dark *))`, which adds no weight. Where site.css paints a
   Bootstrap component with literals (.accordion-button, .page-link, .footer) the override is
   scoped `.sm-site …` at one class above site.css's selector.

   TWO DISPLAY TRAPS (DESIGN-SYSTEM-BRIEF, binding). Nothing here declares `display` on a
   Bootstrap `.collapse` — the navbar's mobile menu, the FAQ accordion panels — or on anything
   jQuery .show()/.hide()/.toggle()s (Home's #OwnerSection/#ManagerSection/#TenantSection and
   `.section` panels, `.invalid-feedback`). The grid and flex containers below (.sm-split, the
   footer parts, …) go on wrappers of those elements, never on them.

   Motion goes through app.css's section 0 aliases (--sm-duration-*), which drop to 1ms under
   prefers-reduced-motion; the one transform here (the feature-card lift) only exists under
   prefers-reduced-motion: no-preference. */

/* ============================================================================
   0. Dark snapshot
   Evaluated on :root, where tokens/colors.css and app.css declare only the dark theme. Each
   --sm-dark-* holds that alias's resolved dark value; section 2 restores it in dark scopes. The
   names are the alias names with --sm-dark- in front (a leading sm- dropped). Inert on its own.
   ========================================================================= */
:root{
  --sm-dark-surface-canvas:var(--surface-canvas);         /* --ink-950 */
  --sm-dark-surface-sunken:var(--surface-sunken);         /* #08080C, colors.css */
  --sm-dark-surface:var(--surface);                       /* --ink-900 */
  --sm-dark-surface-raised:var(--surface-raised);         /* --ink-850 */
  --sm-dark-surface-overlay:var(--surface-overlay);       /* --ink-800 */
  --sm-dark-surface-field:var(--surface-field);           /* #0F0F15, colors.css */
  --sm-dark-surface-hover:var(--surface-hover);           /* --white-a04 */
  --sm-dark-border-subtle:var(--border-subtle);           /* --white-a06 */
  --sm-dark-border:var(--border);                         /* --white-a10 */
  --sm-dark-border-strong:var(--border-strong);           /* --white-a16 */
  --sm-dark-text:var(--text);                             /* --ink-50 */
  --sm-dark-text-strong:var(--text-strong);               /* --ink-0 */
  --sm-dark-text-secondary:var(--text-secondary);         /* --ink-300 */
  --sm-dark-text-muted:var(--text-muted);                 /* --ink-400 */
  --sm-dark-text-link:var(--text-link);                   /* --purple-300 */
  --sm-dark-text-link-hover:var(--text-link-hover);       /* --purple-200 */
  --sm-dark-brand-hover:var(--brand-hover);               /* --purple-500 */
  --sm-dark-brand-active:var(--brand-active);             /* --purple-700 */
  --sm-dark-brand-text:var(--brand-text);                 /* --purple-300 */
  --sm-dark-success-text:var(--success-text);             /* --success-400 */
  --sm-dark-warning-text:var(--warning-text);             /* --warning-400 */
  --sm-dark-danger-text:var(--danger-text);               /* --danger-400 */
  --sm-dark-info-text:var(--info-text);                   /* --info-400 */
  --sm-dark-neutral-subtle:var(--neutral-subtle);         /* --white-a06 */
  --sm-dark-neutral-border:var(--neutral-border);         /* --white-a16 */
  --sm-dark-elev-dark-1:var(--elev-dark-1);
  --sm-dark-elev-dark-2:var(--elev-dark-2);
  --sm-dark-elev-dark-3:var(--elev-dark-3);
  --sm-dark-focus-ring:var(--focus-ring);                 /* app.css 0.2: --sm-focus-ring-dark */
  --sm-dark-focus-ring-danger:var(--sm-focus-ring-danger);
  --sm-dark-focus-ring-inset:var(--sm-focus-ring-inset);
  --sm-dark-field-border-hover:var(--sm-field-border-hover); /* app.css 0.3: --ink-300 */
  --sm-dark-chart-grid:var(--chart-grid);                 /* --white-a06 */
  --sm-dark-chart-axis:var(--chart-axis);                 /* --ink-400 */
  /* Type sizes the app reads through .sm-lead / .sm-eyebrow (app.css 9). Undefined on :root
     today, so these snapshot as invalid and the classes fall back to their own defaults. */
  --sm-dark-text-lead:var(--text-lead);
  --sm-dark-text-eyebrow:var(--text-eyebrow);
}

/* ============================================================================
   1. Scope root: .sm-site on <body>
   Contrast (WCAG 2.x) of the light text aliases, on white (--page, --surface) / --page-alt
   (--surface-raised) / --page-tint (.sm-section--tint), all against the 4.5:1 floor:
     --text            --ink-800     16.72 / 16.04 / 15.05
     --text-strong     --ink-950     19.61 / 18.81 / 17.65
     --text-secondary  --ink-600      9.96 /  9.55 /  8.97
     --text-muted      --ink-500      6.61 /  6.34 /  5.95
     --text-link, --brand-text  --purple-700  10.15 / 9.74 / 9.14   (hover --purple-800 13.05)
     --success-text    app.css --sm-success-700   6.31 / 6.05 / 5.68 (5.47 on its own tint)
     --warning-text    see below                  5.55 / 5.32 / 4.99 (4.99 on its own tint)
     --danger-text     --danger-600   5.80 /  5.56 /  5.22 (4.85 on its own tint)
     --info-text       --info-600     5.73 /  5.50 /  5.16 (4.91 on its own tint)
   Non-text (3:1): --border-strong --ink-400 4.07 / 3.90 / 3.66; the focus ring's --purple-600
   7.98 on white. --border and --border-subtle (1.54 and 1.23 on white) only separate surfaces;
   every control boundary reads --sm-field-border (app.css 0.3, --ink-400) or --border-strong.

   --success-600 is only 4.61 on white and 4.00 on its own tint, so success text takes the 700
   step app.css 0.3 already records (--success-600 mixed 80/20 with --ink-950), with the 600 step
   as fallback. The warning ramp has no step that reaches 4.5:1 on white (--warning-600 is 3.56),
   so its text is --warning-600 mixed 75/25 with --ink-950 — a colour DERIVED from two ramp
   tokens rather than a new literal, and like app.css's 700 steps it is pending sign-off as a
   palette addition. A browser without color-mix() drops the value, and whatever reads it
   inherits its parent's text colour instead, which is still readable.

   Hover and active DARKEN on light (--brand-hover --purple-700, --brand-active --purple-800):
   the dark theme's lighter --purple-500 hover would lose contrast against white. The same goes
   for the field-border hover, which app.css 0.3 lightens to --ink-300 on dark (2.34:1 on white). */
.sm-site{
  color-scheme:light;

  --surface-canvas:var(--page);
  --surface-sunken:var(--ink-50);
  --surface:var(--page);
  --surface-raised:var(--page-alt);
  --surface-overlay:var(--page);
  --surface-field:var(--page);
  --surface-hover:var(--ink-a06);
  --border-subtle:var(--border-light);
  --border:var(--border-light-strong);
  --border-strong:var(--ink-400);
  --text:var(--text-on-light);
  --text-strong:var(--text-on-light-strong);
  --text-secondary:var(--ink-600);
  --text-muted:var(--text-on-light-muted);
  --text-link:var(--brand-text-on-light);
  --text-link-hover:var(--purple-800);
  --brand-hover:var(--purple-700);
  --brand-active:var(--purple-800);
  --brand-text:var(--brand-text-on-light);
  --success-text:var(--sm-success-700, var(--success-600));
  --warning-text:color-mix(in srgb, var(--warning-600) 75%, var(--ink-950));
  --danger-text:var(--danger-600);
  --info-text:var(--info-600);
  --neutral-subtle:var(--ink-a06);
  --neutral-border:var(--border-light-strong);
  /* app.css components ask for these by name; on a light surface they must lift with shadow. */
  --elev-dark-1:var(--elev-1);
  --elev-dark-2:var(--elev-2);
  --elev-dark-3:var(--elev-3);
  /* The light rings from app.css 0.2: a --page gap, then --purple-600 (--danger-600 for an
     invalid field). The fallbacks restate them in case this file ever meets an app.css
     without 0.2. */
  --focus-ring:var(--sm-focus-ring-light, 0 0 0 2px var(--page), 0 0 0 4px var(--purple-600));
  --sm-focus-ring-danger:var(--sm-focus-ring-danger-light, 0 0 0 2px var(--page), 0 0 0 4px var(--danger-600));
  --sm-focus-ring-inset:inset 0 0 0 var(--sm-focus-width, 2px) var(--purple-600);
  --sm-field-border-hover:var(--ink-500);
  /* Button roles (section 16), light values. The primary keeps its transparent border on light, so
     its own #6D30A7 fill is its edge (7.98 / 7.66 / 7.19:1 on white, --page-alt and --page-tint)
     and the call to action looks exactly as it did on 8 Oct at rest, hovered, pressed and
     disabled. The tonal role (.sm-btn--secondary and --soft) is a --purple-500 outline on a
     --brand-a08 wash under a --brand-text label; hover darkens each part one step, as everything
     on light does. */
  --sm-site-btn-primary-rim:transparent;
  --sm-site-btn-primary-rim-hover:transparent;
  --sm-site-btn-tonal-fill:var(--brand-a08);
  --sm-site-btn-tonal-fill-hover:var(--brand-subtle);
  --sm-site-btn-tonal-rim:var(--purple-500);
  --sm-site-btn-tonal-rim-hover:var(--brand);
  --sm-site-btn-tonal-on-hover:var(--purple-800);
  --chart-grid:var(--ink-a10);
  --chart-axis:var(--ink-500);
  /* Marketing sizes for app.css's .sm-lead and .sm-eyebrow (section 9 there), which read these
     tokens: a lead that grows 18px -> 22px with the viewport, and a 13px eyebrow. The classes
     themselves are app.css's; only the values change here. */
  --text-lead:clamp(var(--text-lg), calc(var(--text-md) + 0.5vw), var(--text-xl));
  --text-eyebrow:var(--text-sm);

  background-color:var(--surface-canvas);
  color:var(--text);
  font-family:var(--font-sans);
}

/* ============================================================================
   2. Dark scopes inside the light site
   Every alias section 1 rebinds, handed back its :root value. Two selector shapes:
   - `.sm-site:is(:has(…))` is <body> itself on a page that holds an island or a public-dark
     block, at (0,2,0) so it beats section 1. :has() sits inside :is() because :is() takes a
     FORGIVING selector list: a browser without :has() drops that one selector and keeps the
     rest of the rule. There <body> simply stays light, as it always did there: the per-view
     canvas rules stage 2D retired (available-units.css, application-payment.css) were :has()
     rules too.
   - `:where(.sm-site) :where(…)` is the scope element itself, at (0,0,0). Declared on the
     element, it beats the light values it would otherwise inherit, and it still loses to
     anything app.css declares on `.sm-app` directly — so the island keeps app.css's own
     scope-level overrides.
   The --light variants of the nav and footer opt out and inherit <body>'s values: light on a
   marketing page, dark on a page that holds an island (its whole shell turns dark there).
   ========================================================================= */
.sm-site:is(:has(.sm-app, .sm-public-dark)),
:where(.sm-site) :where(.sm-app, .sm-public-dark, .sm-section--ink, .sm-cta-band, .sm-screen, .sm-ink-panel, .sm-site-nav:not(.sm-site-nav--light), .sm-site-footer:not(.sm-site-footer--light)){
  --surface-canvas:var(--sm-dark-surface-canvas);
  --surface-sunken:var(--sm-dark-surface-sunken);
  --surface:var(--sm-dark-surface);
  --surface-raised:var(--sm-dark-surface-raised);
  --surface-overlay:var(--sm-dark-surface-overlay);
  --surface-field:var(--sm-dark-surface-field);
  --surface-hover:var(--sm-dark-surface-hover);
  --border-subtle:var(--sm-dark-border-subtle);
  --border:var(--sm-dark-border);
  --border-strong:var(--sm-dark-border-strong);
  --text:var(--sm-dark-text);
  --text-strong:var(--sm-dark-text-strong);
  --text-secondary:var(--sm-dark-text-secondary);
  --text-muted:var(--sm-dark-text-muted);
  --text-link:var(--sm-dark-text-link);
  --text-link-hover:var(--sm-dark-text-link-hover);
  --brand-hover:var(--sm-dark-brand-hover);
  --brand-active:var(--sm-dark-brand-active);
  --brand-text:var(--sm-dark-brand-text);
  --success-text:var(--sm-dark-success-text);
  --warning-text:var(--sm-dark-warning-text);
  --danger-text:var(--sm-dark-danger-text);
  --info-text:var(--sm-dark-info-text);
  --neutral-subtle:var(--sm-dark-neutral-subtle);
  --neutral-border:var(--sm-dark-neutral-border);
  --elev-dark-1:var(--sm-dark-elev-dark-1);
  --elev-dark-2:var(--sm-dark-elev-dark-2);
  --elev-dark-3:var(--sm-dark-elev-dark-3);
  --focus-ring:var(--sm-dark-focus-ring);
  --sm-focus-ring-danger:var(--sm-dark-focus-ring-danger);
  --sm-focus-ring-inset:var(--sm-dark-focus-ring-inset);
  --sm-field-border-hover:var(--sm-dark-field-border-hover);
  /* Button roles (section 16), dark values: app.css 0.5's paint, the raw ramp steps app.css 1.1
     paints the app with, so the nav, the bands and the islands beside them read alike. */
  --sm-site-btn-primary-rim:var(--sm-btn-rim-brand);
  --sm-site-btn-primary-rim-hover:var(--sm-btn-rim-brand-hover);
  --sm-site-btn-tonal-fill:var(--sm-btn-tonal-fill);
  --sm-site-btn-tonal-fill-hover:var(--sm-btn-tonal-fill-hover);
  --sm-site-btn-tonal-rim:var(--sm-btn-rim-brand);
  --sm-site-btn-tonal-rim-hover:var(--sm-btn-rim-brand-hover);
  --sm-site-btn-tonal-on-hover:var(--sm-btn-tonal-on-hover);
  --chart-grid:var(--sm-dark-chart-grid);
  --chart-axis:var(--sm-dark-chart-axis);
}
/* Islands are app surfaces, so they also get the app's type sizes back. The marketing dark
   bands keep the marketing lead and eyebrow. */
.sm-site:is(:has(.sm-app, .sm-public-dark)),
:where(.sm-site) :where(.sm-app, .sm-public-dark){
  --text-lead:var(--sm-dark-text-lead);
  --text-eyebrow:var(--sm-dark-text-eyebrow);
}
/* Native controls and scrollbars in a dark band. `.sm-app` already sets this itself (app.css
   16.1), and <body> keeps the light scheme it has today. */
:where(.sm-site) :where(.sm-public-dark, .sm-section--ink, .sm-cta-band, .sm-screen, .sm-ink-panel, .sm-site-nav:not(.sm-site-nav--light), .sm-site-footer:not(.sm-site-footer--light)){
  color-scheme:dark;
}

/* The generic public-dark scope for stage 2D, on the view's root beside `.sm-app`
   (`<div class="sm-app sm-public-dark">`). It paints its own canvas so it also works alone, and
   its presence turns the page's <body> dark (above), which is why stage 2D retired the three
   per-view body:has() canvas rules. */
.sm-public-dark{
  background-color:var(--surface-canvas);
  color:var(--text);
}

/* ============================================================================
   3. Base typography and links
   ========================================================================= */
/* Headings keep Bootstrap's sizes and weight; they only take the display tracking of the type
   system, and balanced line breaks where the browser supports text-wrap. No colour: several
   public headings sit on dark video or purple calculators and inherit white from there. */
:where(.sm-site) :is(h1, h2, h3, h4, h5, h6):not(:where(.sm-app *, .sm-public-dark *)){
  letter-spacing:var(--tracking-tight);
  text-wrap:balance;
}

/* Links. Underlined at rest, as Bootstrap's reboot has them: --purple-700 is only 1.65:1 against
   --ink-800 body text, so colour alone cannot mark a link inside a sentence (WCAG 1.4.1). Hover
   and keyboard focus thicken the underline. (0,0,1) at rest and (0,1,1) on hover: they tie
   site.css's `a` and Bootstrap's `a:hover` and win by source order, and lose to every class.
   .sm-btn is excluded so an <a class="sm-btn"> keeps its label colour on hover — the
   .sm-auth__panel precedent in app.css 10.1. */
:where(.sm-site) a:not(:where(.sm-btn, .sm-app *, .sm-public-dark *)){
  color:var(--text-link);
  text-decoration-thickness:1px;
  text-underline-offset:0.2em;
}
:where(.sm-site) a:not(:where(.sm-btn, .sm-app *, .sm-public-dark *)):hover{
  color:var(--text-link-hover);
  text-decoration-thickness:2px;
}
/* The token ring rather than an outline: its --page gap keeps it visible on the black navbar and
   footer this layout still ships, where --purple-600 alone is 2.39:1. No border-radius here: at
   (0,1,1) it would reshape every class-styled anchor (a card, a .btn-lg) while it has focus, and
   the ring follows whatever radius the element already has. */
:where(.sm-site) a:not(:where(.sm-btn, .sm-app *, .sm-public-dark *)):focus-visible{
  outline:var(--sm-focus-outline);
  box-shadow:var(--focus-ring);
  text-decoration-thickness:2px;
}

/* The skip link's target, #main: a <main id="main"> in _Layout and in _ValuationToolLayout, whose
   <body> carries no scope class, hence the unscoped selector (app.css 9 has the same rule). In
   _Layout it takes tabindex="-1" only while site.js moves focus there from the skip link, and
   drops it on blur: a permanent tabindex made every mouse click on plain content focus the whole
   container, so the next Tab restarted at the top of the page. The container is not a control,
   and a browser ring round the whole content area on arrival reads as a stray frame (the GOV.UK
   pattern drops it too). */
[id="main"][tabindex="-1"]:focus{ outline:none; }

/* ============================================================================
   4. Display type
   The three display tokens had no consumer. Element-agnostic: each declares its own margin.
   No colour, so a headline inherits the band it sits in (--text on light, --ink-50 on ink).
   Defined before the layout rules in section 5, which space these inside a section header.
   ========================================================================= */
.sm-display-1,
.sm-display-2,
.sm-display-3,
.sm-display-4{
  margin:0;
  font-family:var(--font-display);
  font-weight:var(--weight-bold);
  letter-spacing:var(--tracking-display);
  text-wrap:balance;
}
.sm-display-1{
  font-size:var(--text-display-1);    /* 44-64px */
  font-weight:var(--weight-black);
  line-height:var(--leading-display);
}
.sm-display-2{
  font-size:var(--text-display-2);    /* 36-48px */
  line-height:var(--leading-display);
}
.sm-display-3{
  font-size:var(--text-display-3);    /* 32px */
  line-height:var(--leading-tight);
}

/* ============================================================================
   5. Layout: wide container, sections, section header, media/text split
   ========================================================================= */
/* --content-max-wide (1360px) with the 16px phone gutter the brief asks for, 24px from 768px and
   32px from --bp-lg (1120px). Bootstrap's reboot makes it border-box, so the cap includes them. */
.sm-container-wide{
  width:100%;
  max-width:var(--content-max-wide);
  margin-inline:auto;
  padding-inline:var(--space-4);
}

/* Vertical rhythm is --section-y (96px), --section-y-tight (64px) on phones and for --tight.
   A plain section paints nothing and sits on the page canvas. */
.sm-section{ padding-block:var(--section-y-tight); }
.sm-section--tight{ padding-block:var(--space-12); }
.sm-section--alt{ background-color:var(--surface-raised); }
/* On the tint, status text that sits on its own translucent tint (an alert's title and icon, a
   badge, a metric delta) composites darker than it does on white: --danger-600 on --danger-subtle
   over --page-tint is 4.41:1 and --info-600 on --info-subtle 4.45:1. The band takes one step
   darker: app.css 0.3's --sm-danger-700, and the same recipe for info (--info-600 mixed 80/20
   with --ink-950, derived like section 1's warning text and pending the same sign-off): 5.90:1
   and 5.91:1 on those tints, 6.99:1 and 6.85:1 on the band itself. Success (4.96:1) and warning
   (4.55:1) already clear 4.5:1 there. */
.sm-section--tint{
  --danger-text:var(--sm-danger-700, var(--danger-600));
  --info-text:color-mix(in srgb, var(--info-600) 80%, var(--ink-950));
  background-color:var(--page-tint);
}
/* A dark band on --page-ink: section 2 hands it the dark aliases, so every component inside it
   (buttons, cards, links, the lead) renders dark with no modifier. */
.sm-section--ink{
  background-color:var(--page-ink);
  color:var(--text);
}

@media (min-width:768px){
  .sm-container-wide{ padding-inline:var(--space-6); }
  .sm-section{ padding-block:var(--section-y); }
  .sm-section--tight{ padding-block:var(--section-y-tight); }
}
@media (min-width:1120px){
  .sm-container-wide{ padding-inline:var(--space-8); }
}

/* Eyebrow, headline and lead above a section's content. A stack, not a flex column, so it never
   carries a `display` of its own. */
.sm-section__header{
  max-width:var(--prose-max);
  margin:0 0 var(--space-10);
}
.sm-section__header > *{ margin-block:0; }
.sm-section__header > * + *{ margin-top:var(--space-4); }
.sm-section__header--center{
  margin-inline:auto;
  text-align:center;
}
/* app.css's .sm-lead carries its own max-width, so it needs centring too. */
.sm-section__header--center .sm-lead{ margin-inline:auto; }

/* Media beside text. One column, in source order (put the text first), until --bp-lg (1120px),
   the breakpoint tokens/layout.css names for "marketing switches to single column". --reverse
   puts the media on the leading side from there on, without changing the reading order.
   Put .sm-split on a wrapper INSIDE any panel jQuery shows and hides (Home's role sections):
   its display:grid on the toggled element itself would not survive one .hide()/.show(). */
.sm-split{
  display:grid;
  align-items:center;
  gap:var(--space-10);
}
.sm-split__text,
.sm-split__media{ min-width:0; }
.sm-split__media :is(img, video){
  display:block;
  width:100%;
  height:auto;
  border-radius:var(--radius-xl);
}
@media (min-width:1120px){
  .sm-split{
    grid-template-columns:repeat(2, minmax(0, 1fr));
    gap:var(--space-16);
  }
  .sm-split--reverse > .sm-split__media{ order:-1; }
}

/* ============================================================================
   6. Prose — articles (Views/BlogPosts, BlogPosts/Article's ingested body_html)
   Class-level only: BlogPosts titles, meta, H1/H2 text, URLs and JSON-LD are frozen.
   Every element rule is `:where(.sm-prose) <element>`, (0,0,1): it ties Bootstrap's reboot and
   wins by source order, and any class an author put on an element (`h3.h5`, `.lead`, `.table`,
   the spacing utilities) still wins, so authored intent survives.
   ========================================================================= */
.sm-prose{
  --sm-prose-gap:1.25em;
  max-width:var(--prose-max);
  font-size:var(--text-md);
  line-height:var(--leading-relaxed);
  color:var(--text);
  /* Long URLs and identifiers break instead of pushing the page sideways. Tables opt back
     out below, so their columns size to whole words; code blocks wrap (see pre, below). */
  overflow-wrap:anywhere;
}
@media (min-width:768px){
  .sm-prose{ font-size:var(--text-lg); }
}

:where(.sm-prose) :is(p, ul, ol, dl, blockquote, pre, figure, table, details){
  margin-top:0;
  margin-bottom:var(--sm-prose-gap);
}
:where(.sm-prose) > :first-child{ margin-top:0; }
:where(.sm-prose) > :last-child{ margin-bottom:0; }

/* Headings inherit their colour, for the same reason as section 3. scroll-margin keeps an
   anchor jump (the posts' table of contents) from parking a heading against the viewport edge. */
:where(.sm-prose) :is(h2, h3, h4, h5, h6){
  margin-top:1.8em;
  margin-bottom:0.6em;
  font-family:var(--font-display);
  font-weight:var(--weight-bold);
  line-height:var(--leading-tight);
  letter-spacing:var(--tracking-tight);
  text-wrap:balance;
}
:where(.sm-prose) h2{ font-size:var(--text-xl); }
:where(.sm-prose) h3{ font-size:var(--text-lg); }
:where(.sm-prose) :is(h4, h5, h6){ font-size:var(--text-md); }
@media (min-width:768px){
  :where(.sm-prose) h2{ font-size:var(--text-2xl); }
  :where(.sm-prose) h3{ font-size:var(--text-xl); }
  :where(.sm-prose) h4{ font-size:var(--text-lg); }
}
:where(.sm-prose) :is(section, h2, h3, h4)[id]{ scroll-margin-top:var(--space-8); }

:where(.sm-prose) :is(ul, ol){ padding-inline-start:1.5em; }
:where(.sm-prose) li + li{ margin-top:0.5em; }
:where(.sm-prose) li > :is(ul, ol){
  margin-top:0.5em;
  margin-bottom:0;
}
:where(.sm-prose) li::marker{ color:var(--text-muted); }
:where(.sm-prose) dt{
  font-weight:var(--weight-semibold);
  color:var(--text-strong);
}
:where(.sm-prose) dd{ margin:0.25em 0 0.75em; }

/* Media never overflows the column. height:auto keeps an <img> with width/height attributes in
   proportion; video embeds get a 16:9 box because an iframe has no ratio of its own. */
:where(.sm-prose) :is(img, video){
  max-width:100%;
  height:auto;
}
:where(.sm-prose) :is(iframe, embed, object){ max-width:100%; }
:where(.sm-prose) :is(iframe[src*="youtube.com"], iframe[src*="youtube-nocookie.com"], iframe[src*="player.vimeo.com"]){
  width:100%;
  height:auto;
  aspect-ratio:16 / 9;
}
/* Wrapper for any other embed: it reserves the 16:9 box and the frame fills it. */
.sm-prose__embed{
  aspect-ratio:16 / 9;
  margin-bottom:var(--sm-prose-gap);
}
.sm-prose__embed > :is(iframe, video, embed, object){
  display:block;
  width:100%;
  height:100%;
  border:0;
}
:where(.sm-prose) figure{ margin-inline:0; }
:where(.sm-prose) figcaption{
  margin-top:0.75em;
  font-size:var(--text-sm);
  line-height:var(--leading-snug);
  color:var(--text-muted);
}

:where(.sm-prose) blockquote{
  padding:0.25em 0 0.25em 1.25em;
  border-inline-start:calc(var(--border-emphasis) * 2) solid var(--brand);
  color:var(--text-secondary);
}
:where(.sm-prose) blockquote > :last-child{ margin-bottom:0; }

:where(.sm-prose) :is(code, kbd, samp){
  font-family:var(--font-mono);
  font-size:0.875em;
}
:where(.sm-prose) code{
  padding:0.125em 0.375em;
  color:var(--text-strong);
  background-color:var(--neutral-subtle);
  border-radius:var(--radius-xs);
}
:where(.sm-prose) pre{
  padding:var(--space-4);
  overflow-x:auto;
  font-size:var(--text-sm);
  line-height:var(--leading-normal);
  white-space:pre-wrap;
  overflow-wrap:anywhere;
  tab-size:2;
  color:var(--text);
  background-color:var(--surface-raised);
  border:var(--border-hairline) solid var(--border-subtle);
  border-radius:var(--radius-md);
}
:where(.sm-prose) pre code{
  padding:0;
  font-size:inherit;
  color:inherit;
  background:none;
  border-radius:0;
}
:where(.sm-prose) hr{
  margin-block:2.5em;
  border:0;
  border-top:var(--border-hairline) solid var(--border);
  opacity:1;
}

/* Tables. break-word, not the column's `anywhere`: it still breaks a word that cannot fit, but
   it does not shrink the table's minimum width, so a wide table overflows (and scrolls) instead
   of squeezing each column to a letter. Bootstrap `.table` tables keep their own cell rules. */
:where(.sm-prose) table{
  width:100%;
  border-collapse:collapse;
  font-size:0.9375em;
  line-height:var(--leading-snug);
  font-variant-numeric:var(--numeric-tabular);
  overflow-wrap:break-word;
}
:where(.sm-prose) :is(th, td){
  padding:0.625em 0.875em;
  text-align:start;
  vertical-align:top;
  border-bottom:var(--border-hairline) solid var(--border-subtle);
}
:where(.sm-prose) thead th{
  font-weight:var(--weight-semibold);
  color:var(--text-strong);
  background-color:var(--surface-raised);
  border-bottom-color:var(--border);
}
:where(.sm-prose) caption{
  padding-top:0.75em;
  font-size:var(--text-sm);
  text-align:start;
  color:var(--text-muted);
}
/* The horizontal scroll wrapper for a hand-written table:
     <div class="sm-prose__table" tabindex="0" role="region" aria-label="…"><table>…</table></div>
   tabindex and a name make the scroller reachable and announced from the keyboard. Bootstrap's
   .table-responsive is treated the same. */
.sm-prose__table{
  max-width:100%;
  margin-bottom:var(--sm-prose-gap);
  overflow-x:auto;
  -webkit-overflow-scrolling:touch;
}
.sm-prose__table:focus-visible{
  outline:var(--sm-focus-outline);
  border-radius:var(--radius-xs);
  box-shadow:var(--focus-ring);
}
:where(.sm-prose) :is(.sm-prose__table, .table-responsive) > table{ margin-bottom:0; }
/* An ingested article's tables arrive with no wrapper, and CSS cannot add one: section 12.7
   makes them their own horizontal scroller at every width, for .sm-prose--ingested only.
   Hand-written tables keep display:table (they are authored to fit; a wide one takes the
   wrapper above). */

:where(.sm-prose) details{
  padding:var(--space-3) var(--space-4);
  border:var(--border-hairline) solid var(--border);
  border-radius:var(--radius-md);
}
:where(.sm-prose) summary{
  cursor:pointer;
  font-weight:var(--weight-semibold);
  color:var(--text-strong);
}
:where(.sm-prose) details[open] > summary{ margin-bottom:var(--space-3); }
:where(.sm-prose) summary:focus-visible{
  outline:var(--sm-focus-outline);
  border-radius:var(--radius-xs);
  box-shadow:var(--focus-ring);
}

/* ============================================================================
   7. Marketing components
   ========================================================================= */
/* --- 7.1 Feature card --------------------------------------------------------
   A white card with light elevation (the elevation aliases resolve light under .sm-site, and to
   the dark border-led style inside an ink band). It lifts only when it is a link — the whole card
   as an <a>, or a card whose title holds .sm-feature-card__link, which stretches over the card —
   because a hover lift on an inert card promises a click that goes nowhere. The lift itself is
   motion, so it exists only when the reader has not asked for reduced motion. */
.sm-feature-card{
  position:relative;
  padding:var(--pad-card);
  color:var(--text);
  text-decoration:none;
  background-color:var(--surface);
  border:var(--border-hairline) solid var(--border-subtle);
  border-radius:var(--radius-xl);
  box-shadow:var(--elev-dark-1);
  transition:
    border-color var(--sm-duration-fast) var(--ease-standard),
    box-shadow var(--sm-duration-base) var(--ease-standard),
    transform var(--sm-duration-base) var(--ease-standard);
}
.sm-feature-card__icon{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:var(--space-12);
  height:var(--space-12);
  margin-bottom:var(--space-4);
  font-size:var(--text-xl);
  line-height:1;
  color:var(--brand-text);
  background-color:var(--brand-subtle);
  border-radius:var(--radius-md);
}
.sm-feature-card__title{
  margin:0 0 var(--space-2);
  font-family:var(--font-display);
  font-size:var(--text-lg);
  font-weight:var(--weight-bold);
  line-height:var(--leading-tight);
  letter-spacing:var(--tracking-tight);
  color:var(--text-strong);
}
.sm-feature-card__body{
  margin:0;
  font-size:var(--text-md);
  line-height:var(--leading-normal);
  color:var(--text-secondary);
}
.sm-feature-card__link{
  color:inherit;
  text-decoration:none;
}
.sm-feature-card__link::after{
  content:"";
  position:absolute;
  inset:0;
  border-radius:inherit;
}
/* An <a> is inline by default; the card around block content needs a block box. */
a.sm-feature-card{ display:block; }
/* (0,2,0)-(0,3,0): above section 3's link rules and Bootstrap's `a:hover`. */
.sm-site a.sm-feature-card,
.sm-site a.sm-feature-card:hover,
.sm-site .sm-feature-card__link,
.sm-site .sm-feature-card__link:hover{
  color:inherit;
  text-decoration:none;
}
:is(a.sm-feature-card, .sm-feature-card:has(.sm-feature-card__link)):hover{
  border-color:var(--border);
  box-shadow:var(--elev-dark-3);
}
@media (prefers-reduced-motion:no-preference){
  :is(a.sm-feature-card, .sm-feature-card:has(.sm-feature-card__link)):hover{ transform:var(--lift-hover); }
}
/* Two rules, not one list: a browser without :has() drops a whole selector list that
   contains it. */
.sm-site a.sm-feature-card:focus-visible{
  outline:var(--sm-focus-outline);
  box-shadow:var(--focus-ring);
}
.sm-feature-card:has(.sm-feature-card__link:focus-visible){
  outline:var(--sm-focus-outline);
  box-shadow:var(--focus-ring);
}
/* The card carries the ring, so the title link drops its own — but only where :has() puts the
   ring on the card. Anywhere else the link keeps section 3's ring round its text. */
@supports selector(:has(*)){
  .sm-site .sm-feature-card__link:focus-visible{ box-shadow:none; }
}

/* --- 7.2 Price card ----------------------------------------------------------
   One pricing tier. A flex column so the call to action sits at the foot of every card in a row
   whatever the length of its feature list. --featured is the recommended tier. */
.sm-price-card{
  position:relative;
  display:flex;
  flex-direction:column;
  gap:var(--space-5);
  height:100%;
  padding:var(--pad-panel);
  color:var(--text);
  background-color:var(--surface);
  border:var(--border-hairline) solid var(--border-subtle);
  border-radius:var(--radius-xl);
  box-shadow:var(--elev-dark-2);
}
.sm-price-card--featured{
  border-color:var(--brand);
  box-shadow:0 0 0 var(--border-hairline) var(--brand), var(--elev-dark-3);
}
.sm-price-card__badge{
  align-self:flex-start;
  margin:0;
  padding:var(--space-1) var(--space-3);
  font-size:var(--text-xs);
  font-weight:var(--weight-semibold);
  line-height:var(--leading-tight);
  letter-spacing:var(--tracking-caps);
  text-transform:uppercase;
  color:var(--brand-text);
  background-color:var(--brand-subtle);
  border-radius:var(--radius-pill);
}
.sm-price-card__name{
  margin:0;
  font-family:var(--font-display);
  font-size:var(--text-lg);
  font-weight:var(--weight-semibold);
  line-height:var(--leading-tight);
  color:var(--text-strong);
}
.sm-price-card__price{
  display:flex;
  flex-wrap:wrap;
  align-items:baseline;
  gap:var(--space-1) var(--space-2);
  margin:0;
  font-family:var(--font-display);
  font-size:var(--text-metric-lg);
  font-weight:var(--weight-bold);
  line-height:var(--leading-tight);
  letter-spacing:var(--tracking-display);
  color:var(--text-strong);
  font-variant-numeric:var(--numeric-tabular);
}
.sm-price-card__period{
  font-size:var(--text-sm);
  font-weight:var(--weight-medium);
  letter-spacing:var(--tracking-normal);
  color:var(--text-muted);
}
.sm-price-card__desc{
  margin:0;
  line-height:var(--leading-normal);
  color:var(--text-secondary);
}
.sm-price-card__features{
  display:grid;
  gap:var(--space-3);
  margin:0;
  padding:0;
  list-style:none;
}
.sm-price-card__feature{
  display:flex;
  align-items:flex-start;
  gap:var(--space-2);
  line-height:var(--leading-snug);
}
.sm-price-card__feature-icon{
  flex:0 0 auto;
  margin-top:0.15em;
  color:var(--brand-text);
}
.sm-price-card__cta{ margin-top:auto; }

/* --- 7.3 Call-to-action band ------------------------------------------------
   A rounded panel on --page-ink (a dark scope, section 2), with the one gradient the system
   sanctions — app.css's .sm-auth__glow — behind its content. isolation keeps the glow's
   negative z-index inside the band. */
.sm-cta-band{
  position:relative;
  isolation:isolate;
  overflow:hidden;
  padding:var(--space-16) var(--space-6);
  text-align:center;
  color:var(--text);
  background-color:var(--page-ink);
  border-radius:var(--radius-2xl);
}
.sm-cta-band::before{
  content:"";
  position:absolute;
  z-index:-1;
  top:-40%;
  left:50%;
  width:70%;
  aspect-ratio:1;
  transform:translateX(-50%);
  background:radial-gradient(closest-side, var(--brand-a24), transparent 70%);
  filter:blur(40px);
  pointer-events:none;
}
.sm-cta-band__title{
  max-width:24ch;
  margin:0 auto var(--space-3);
  font-family:var(--font-display);
  font-size:var(--text-display-3);
  font-weight:var(--weight-bold);
  line-height:var(--leading-tight);
  letter-spacing:var(--tracking-display);
  color:var(--text-strong);
  text-wrap:balance;
}
.sm-cta-band__body{
  max-width:var(--prose-max);
  margin:0 auto var(--space-8);
  font-size:var(--text-lg);
  line-height:var(--leading-normal);
  color:var(--text-secondary);
}
.sm-cta-band__actions{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:var(--space-3);
}
@media (min-width:768px){
  .sm-cta-band{ padding:var(--space-20) var(--space-12); }
}

/* --- 7.4 Logo strip ----------------------------------------------------------
   A row of integration or partner logos (<ul>, one logo per <li>, each <img> with its alt text).
   Monochrome and quiet at rest, full colour on hover or when its link has focus. */
.sm-logo-strip{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  justify-content:center;
  gap:var(--space-6) var(--space-10);
  margin:0;
  padding:0;
  list-style:none;
}
.sm-logo-strip__label{
  flex-basis:100%;
  margin:0;
  font-size:var(--text-xs);
  font-weight:var(--weight-semibold);
  line-height:var(--leading-tight);
  letter-spacing:var(--tracking-caps);
  text-align:center;
  text-transform:uppercase;
  color:var(--text-muted);
}
.sm-logo-strip__item{
  display:flex;
  align-items:center;
}
.sm-logo-strip__logo{
  display:block;
  width:auto;
  max-width:calc(var(--space-32) + var(--space-8));
  height:var(--space-8);
  object-fit:contain;
  filter:grayscale(1);
  opacity:.72;
  transition:
    filter var(--sm-duration-base) var(--ease-standard),
    opacity var(--sm-duration-base) var(--ease-standard);
}
.sm-logo-strip__item:hover .sm-logo-strip__logo,
.sm-logo-strip__item :focus-visible .sm-logo-strip__logo{
  filter:none;
  opacity:1;
}

/* ============================================================================
   8. Bootstrap mirrors — the technique of app.css 11 and 12.9
   The Bootstrap classes stay (their data-bs-* behaviour binds to them); only the paint changes.
   Variables are declared one class above Bootstrap's own declaration; where site.css paints a
   literal over Bootstrap's variable, the variable-driven paint is restated one class above
   site.css.
   ========================================================================= */
/* --- 8.1 Accordion (the FAQs on 25 public pages) ---------------------------
   site.css paints an open question solid #6d30a7 with a white chevron, and its focus as a 25%
   purple wash. Here: a --brand-subtle tint with --brand-text (8.33:1), the token ring on keyboard
   focus only, and a chevron drawn as a mask in currentColor, so it follows the question's colour
   on light and on dark instead of shipping a colour inside an SVG. Never a `display` on
   .accordion-collapse: it is the Bootstrap .collapse. */
.sm-site .accordion{
  --bs-accordion-color:var(--text);
  --bs-accordion-bg:var(--surface);
  --bs-accordion-border-color:var(--border);
  --bs-accordion-border-radius:var(--radius-lg);
  --bs-accordion-inner-border-radius:calc(var(--radius-lg) - var(--border-hairline));
  --bs-accordion-btn-padding-x:var(--space-5);
  --bs-accordion-btn-padding-y:var(--space-4);
  --bs-accordion-btn-color:var(--text-strong);
  --bs-accordion-btn-bg:var(--surface);
  --bs-accordion-btn-focus-border-color:var(--brand);
  --bs-accordion-btn-focus-box-shadow:var(--focus-ring);
  --bs-accordion-btn-icon-transition:transform var(--sm-duration-base) var(--ease-standard);
  --bs-accordion-body-padding-x:var(--space-5);
  --bs-accordion-body-padding-y:var(--space-4);
  --bs-accordion-active-color:var(--brand-text);
  --bs-accordion-active-bg:var(--brand-subtle);
  --bs-accordion-transition:
    color var(--sm-duration-fast) var(--ease-standard),
    background-color var(--sm-duration-fast) var(--ease-standard),
    border-color var(--sm-duration-fast) var(--ease-standard),
    box-shadow var(--sm-duration-fast) var(--ease-standard);
}
/* column-gap keeps the question off the chevron. Bootstrap pushes the ::after to the end with
   margin-left:auto and no gap, so a question that just filled its line ran into it (0-1.4px,
   BestPropertyManagementSoftware at 768-1440). Every public FAQ button holds its question as one
   flex item (bare text, or one <b>), so the 12px only ever falls between question and chevron. */
.sm-site .accordion-button{
  column-gap:var(--space-3);
  font-family:inherit;
  font-weight:var(--weight-semibold);
  line-height:var(--leading-snug);
}
/* site.css:843-853, (0,2,0). */
.sm-site .accordion-button:not(.collapsed){
  color:var(--bs-accordion-active-color);
  background-color:var(--bs-accordion-active-bg);
}
.sm-site .accordion-button:focus{
  border-color:var(--bs-accordion-btn-focus-border-color);
  box-shadow:var(--bs-accordion-btn-focus-box-shadow);
}
/* Bootstrap rings on every :focus, mouse clicks included; keep the open question's divider. */
.sm-site .accordion-button:focus:not(:focus-visible){ box-shadow:none; }
.sm-site .accordion-button:not(.collapsed):focus:not(:focus-visible){
  box-shadow:inset 0 calc(var(--bs-accordion-border-width) * -1) 0 var(--bs-accordion-border-color);
}
.sm-site .accordion-button:focus-visible{ outline:var(--sm-focus-outline); }
@supports ((-webkit-mask-image:none) or (mask-image:none)){
  .sm-site .accordion-button::after{
    background-color:currentColor;
    background-image:none;
    -webkit-mask:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='black' fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") center / contain no-repeat;
    mask:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='black' fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") center / contain no-repeat;
  }
  /* site.css:855, (0,2,1): its white chevron is the only thing left to clear. */
  .sm-site .accordion-button:not(.collapsed)::after{ background-image:none; }
}

/* --- 8.2 Pagination (no public page uses it yet; the blog index will) ------
   site.css:436-462 paints .page-link dark with literals, one to three classes deep, after
   Bootstrap — so Bootstrap's own variable-driven rules are restated one class higher. The
   DataTables pager is untouched: it lives only in _UserLayout and the valuation tool. */
.sm-site .pagination{
  --bs-pagination-padding-x:var(--space-3);
  --bs-pagination-padding-y:var(--space-2);
  --bs-pagination-font-size:var(--text-sm);
  --bs-pagination-color:var(--text-link);
  --bs-pagination-bg:var(--surface);
  --bs-pagination-border-width:var(--border-hairline);
  --bs-pagination-border-color:var(--border);
  --bs-pagination-border-radius:var(--radius-md);
  --bs-pagination-hover-color:var(--text-link-hover);
  --bs-pagination-hover-bg:var(--surface-hover);
  --bs-pagination-hover-border-color:var(--border-strong);
  --bs-pagination-focus-color:var(--text-link-hover);
  --bs-pagination-focus-bg:var(--surface-hover);
  --bs-pagination-focus-box-shadow:var(--focus-ring);
  --bs-pagination-active-color:var(--brand-on);
  --bs-pagination-active-bg:var(--brand);
  --bs-pagination-active-border-color:var(--brand);
  --bs-pagination-disabled-color:var(--text-muted);
  --bs-pagination-disabled-bg:var(--surface-raised);
  --bs-pagination-disabled-border-color:var(--border-subtle);
}
.sm-site .page-link{
  font-weight:var(--weight-medium);
  color:var(--bs-pagination-color);
  background-color:var(--bs-pagination-bg);
  border-color:var(--bs-pagination-border-color);
}
.sm-site .page-link:hover{
  color:var(--bs-pagination-hover-color);
  background-color:var(--bs-pagination-hover-bg);
  border-color:var(--bs-pagination-hover-border-color);
}
.sm-site .page-link:focus:not(:focus-visible){ box-shadow:none; }
.sm-site .page-link:focus-visible{ outline:var(--sm-focus-outline); }
.sm-site :is(.page-item.active .page-link, .page-link.active){
  color:var(--bs-pagination-active-color);
  background-color:var(--bs-pagination-active-bg);
  border-color:var(--bs-pagination-active-border-color);
}
.sm-site :is(.page-item.disabled .page-link, .page-link.disabled){
  color:var(--bs-pagination-disabled-color);
  background-color:var(--bs-pagination-disabled-bg);
  border-color:var(--bs-pagination-disabled-border-color);
}

/* --- 8.3 Focus on Bootstrap buttons and fields -----------------------------
   A bare `.btn` never defines --bs-btn-focus-shadow-rgb, so .btn:focus-visible resolves an
   invalid box-shadow after `outline:0` and the `.btn.btn-login` calls to action (74 on public
   views, per the Phase 0 public audit) show NO focus at all. Bootstrap reads the ring from
   --bs-btn-focus-box-shadow, declared on .btn (0,1,0); declaring it one class higher gives every
   .btn the token ring. Fields: the stock `.form-control:focus` ring is a 25% blue wash (about
   1.4:1 on white). Islands are left to app.css.
   Forced colours drop box-shadow, and Bootstrap's own `outline:0` on .btn:focus-visible and
   .form-control/.form-select:focus is (0,2,0), above app.css 0.2's (0,1,0) forced-colours
   fallback, so both rules below restate the outline through --sm-focus-outline (none until
   forced colours are active, then the 2px CanvasText line). */
.sm-site .btn:not(:where(.sm-app *, .sm-public-dark *)){
  --bs-btn-focus-box-shadow:var(--focus-ring);
}
.sm-site .btn:focus-visible:not(:where(.sm-app *, .sm-public-dark *)){
  outline:var(--sm-focus-outline);
}
.sm-site :is(.form-control, .form-select):focus:not(:where(.sm-app *, .sm-public-dark *)){
  border-color:var(--brand);
  outline:var(--sm-focus-outline);
  box-shadow:var(--focus-ring);
}

/* --- 8.4 The legacy purple calls to action: .btn-login, .blog-btn-custom ------
   site.css paints both classes with literals: #6d30a7 (the --brand value) and white text at rest,
   and a hover of #7E3FF2 (lighter; 5.41:1) or #5a2491. Their other states are Bootstrap's, read
   from variables a bare .btn never defines: .btn:focus-visible (0,2,0) paints --bs-btn-hover-bg
   and --bs-btn-hover-color, and `:not(.btn-check) + .btn:active` / `.btn:first-child:active`
   (0,3,0) paint --bs-btn-active-*. Both resolve invalid, so keyboard focus and a press left the
   button transparent with inherited text. The app.css 11 technique: the variables are declared
   one class above Bootstrap's .btn, and the variable-driven paint is restated at (0,3,0), where
   site.css's (0,2,0) :hover literal and Bootstrap's (0,3,0) :active rules would otherwise
   decide. Focus keeps the rest fill (the 8.3 ring marks it); hover and press darken, as
   everywhere on light (section 1): white on --purple-600 7.98:1, --purple-700 10.15:1,
   --purple-800 13.05:1. Order matters: hover after focus, press last. Disabled stays site.css's.
   Islands are left to app.css. */
.sm-site :is(.btn-login, .blog-btn-custom):not(:where(.sm-app *, .sm-public-dark *)){
  --bs-btn-color:var(--brand-on);
  --bs-btn-bg:var(--brand);
  --bs-btn-hover-color:var(--brand-on);
  --bs-btn-hover-bg:var(--brand-hover);
  --bs-btn-hover-border-color:transparent;
  --bs-btn-active-color:var(--brand-on);
  --bs-btn-active-bg:var(--brand-active);
  --bs-btn-active-border-color:transparent;
}
.sm-site :is(.btn-login, .blog-btn-custom):focus-visible:not(:where(.sm-app *, .sm-public-dark *)){
  color:var(--bs-btn-color);
  background-color:var(--bs-btn-bg);
}
.sm-site :is(.btn-login, .blog-btn-custom):hover:not(:where(.sm-app *, .sm-public-dark *)){
  color:var(--bs-btn-hover-color);
  background-color:var(--bs-btn-hover-bg);
}
.sm-site :is(.btn-login, .blog-btn-custom):active:not(:where(.sm-app *, .sm-public-dark *)){
  color:var(--bs-btn-active-color);
  background-color:var(--bs-btn-active-bg);
}

/* ============================================================================
   9. Site chrome — nav and footer (adopted by stage 2A)
   Both are dark bands by default (section 2): the only logo asset is white
   (img/simpli-white-tp.png, and the 2x webp stage F adds). --light opts a block out of the dark
   aliases and leaves it light, which needs a dark logo first.
   ========================================================================= */
/* --- 9.1 Nav -----------------------------------------------------------------
   On the existing Bootstrap navbar root:
     <nav class="navbar navbar-expand-lg sm-site-nav">
   A variable mirror: Bootstrap's navbar, nav-link and toggler rules read --bs-navbar-* and
   --bs-nav-link-*, so the classes, the #navbarTogglerDemo02 collapse and every data-bs-* and
   aria-* hook stay exactly as they are. Drop `navbar-dark` and `bg-black` in the same edit
   (`bg-black` is !important). Never a `display` on .navbar-collapse (it is the .collapse) or on
   .navbar-toggler (Bootstrap hides it at lg with a display rule this would outrank). Parts:
     .sm-site-nav__logo     the <img> inside a.navbar-brand
     .sm-site-nav__links    ul.navbar-nav            .sm-site-nav__link   its a.nav-link
     .sm-site-nav__actions  the sign-up / log-in list (a plain <ul>, not `.navbar`)
     .sm-site-nav__toggler  button.navbar-toggler
   The current page takes aria-current="page" on its link (Bootstrap's `.active` also works); a page
   inside a nav section takes aria-current="true" on that section's link (pass 2 Tier B: Solutions on
   the product pages, Blog on posts). */
.sm-site .sm-site-nav{
  --bs-navbar-padding-x:0;
  --bs-navbar-padding-y:var(--space-3);
  --bs-navbar-color:var(--text-secondary);
  --bs-navbar-hover-color:var(--text-strong);
  --bs-navbar-active-color:var(--text-strong);
  --bs-navbar-disabled-color:var(--text-muted);
  --bs-navbar-brand-color:var(--text-strong);
  --bs-navbar-brand-hover-color:var(--text-strong);
  --bs-navbar-brand-padding-y:0;
  --bs-navbar-brand-margin-end:var(--space-8);
  --bs-navbar-nav-link-padding-x:var(--space-3);
  --bs-navbar-toggler-padding-y:0;
  --bs-navbar-toggler-padding-x:0;
  --bs-navbar-toggler-border-color:var(--sm-field-border);
  --bs-navbar-toggler-border-radius:var(--radius-md);
  --bs-navbar-toggler-focus-width:0;
  font-family:var(--font-sans);
  background-color:var(--surface-canvas);
  border-bottom:var(--border-hairline) solid var(--border-subtle);
}
/* Bootstrap lays out `.navbar > .container-fluid`; the same for the wide container. */
.sm-site .sm-site-nav > .sm-container-wide{
  display:flex;
  flex-wrap:inherit;
  align-items:center;
  justify-content:space-between;
}
.sm-site-nav__logo{
  display:block;
  width:auto;
  height:var(--space-10);
}
.sm-site .sm-site-nav__link{
  padding-block:var(--space-2);
  font-size:var(--text-md);
  font-weight:var(--weight-medium);
  line-height:var(--leading-tight);
  text-decoration:none;
  border-radius:var(--radius-sm);
}
.sm-site .sm-site-nav__link:is(:hover, :focus-visible, [aria-current="page"], [aria-current="true"], .active){
  text-decoration-line:underline;
  text-decoration-thickness:2px;
  text-underline-offset:0.45em;
}
.sm-site .sm-site-nav__link:is([aria-current="page"], [aria-current="true"], .active){
  color:var(--bs-navbar-active-color);
  text-decoration-color:var(--brand-text);
}
.sm-site .sm-site-nav__link:focus-visible{
  outline:var(--sm-focus-outline);
  box-shadow:var(--focus-ring);
}
.sm-site .sm-site-nav__actions{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--space-2);
  margin:0;
  padding:0;
  list-style:none;
}
/* The toggler is a tool (section 16): the neutral outline, --sm-field-border on the ink bar
   (4.82:1; the old white-10% hairline was 1.26:1) and --sm-field-border-hover under the pointer
   (8.40:1). The bars themselves are --text-secondary, 8.40:1. */
.sm-site .sm-site-nav__toggler{
  width:var(--touch-target-min);
  height:var(--touch-target-min);
  color:var(--bs-navbar-color);
  transition:
    color var(--sm-duration-fast) var(--ease-standard),
    background-color var(--sm-duration-fast) var(--ease-standard),
    border-color var(--sm-duration-fast) var(--ease-standard);
}
.sm-site .sm-site-nav__toggler:hover{
  color:var(--bs-navbar-hover-color);
  background-color:var(--surface-hover);
  border-color:var(--sm-field-border-hover);
}
.sm-site .sm-site-nav__toggler:focus-visible{
  outline:var(--sm-focus-outline);
  box-shadow:var(--focus-ring);
}
/* The three bars as a mask in currentColor, so the icon follows the nav's own colour instead of
   Bootstrap's navbar-dark/-light SVG with a colour baked in. */
@supports ((-webkit-mask-image:none) or (mask-image:none)){
  .sm-site .sm-site-nav__toggler .navbar-toggler-icon{
    background-color:currentColor;
    background-image:none;
    -webkit-mask:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='black' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") center / 100% 100% no-repeat;
    mask:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='black' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") center / 100% 100% no-repeat;
  }
}
/* The open mobile menu (below Bootstrap's lg, where the toggler shows). Spacing sits on the lists
   inside the collapse, never on the collapse itself, which would make its height animation jump. */
@media (max-width:991.98px){
  .sm-site .sm-site-nav__links{ padding-block:var(--space-3); }
  .sm-site .sm-site-nav__link{
    min-height:var(--touch-target-min);
    padding-block:var(--space-3);
  }
  .sm-site .sm-site-nav__actions{
    padding-block:var(--space-3) var(--space-4);
    border-top:var(--border-hairline) solid var(--border-subtle);
  }
}

/* --- 9.2 Footer --------------------------------------------------------------
   On the <footer>, with .sm-container-wide inside. (0,2,0) so it also beats site.css's
   `.footer{white-space:nowrap;line-height:60px}` if that class stays on the element. Drop the
   inline styles and the Bootstrap border/text/spacing utilities in the same edit: they are
   !important or inline and would beat this. Parts:
     .sm-site-footer__grid     columns of links (auto-fit, 9.5rem minimum: two columns on a 343px phone);
                               the legal links are its Legal column
     .sm-site-footer__heading  a column's caps heading
     .sm-site-footer__links    a column's <ul>       .sm-site-footer__link   its <a>
     .sm-site-footer__social   the icon row <ul>, in the brand row above the grid (.sm-site-footer__top, 11.1)
                               .sm-site-footer__social-link  a 44px icon link
     .sm-site-footer__bottom   the closing row: the copyright only    .sm-site-footer__copyright  the © line
     .sm-site-footer__legal    unused since the legal links left the closing row (section 15)
   Text is --text-secondary (8.40:1 on the ink canvas) and the bottom row --text-muted (4.82:1). */
.sm-site .sm-site-footer{
  padding-block:var(--space-12) var(--space-8);
  font-family:var(--font-sans);
  font-size:var(--text-sm);
  line-height:var(--leading-normal);
  white-space:normal;
  color:var(--text-secondary);
  background-color:var(--surface-canvas);
  border-top:var(--border-hairline) solid var(--border-subtle);
}
.sm-site-footer__grid{
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(min(100%, 9.5rem), 1fr));
  gap:var(--space-8);
}
.sm-site-footer__heading{
  margin:0 0 var(--space-3);
  font-size:var(--text-xs);
  font-weight:var(--weight-semibold);
  line-height:var(--leading-tight);
  letter-spacing:var(--tracking-caps);
  text-transform:uppercase;
  color:var(--text-strong);
}
.sm-site-footer__links,
.sm-site-footer__social,
.sm-site-footer__legal{
  margin:0;
  padding:0;
  list-style:none;
}
.sm-site-footer__links{
  display:grid;
  gap:var(--space-2);
}
.sm-site .sm-site-footer__link{
  color:var(--text-secondary);
  text-decoration:none;
  border-radius:var(--radius-xs);
}
.sm-site .sm-site-footer__link:hover{
  color:var(--text-strong);
  text-decoration:underline;
  text-decoration-thickness:1px;
  text-underline-offset:0.2em;
}
.sm-site .sm-site-footer__link:focus-visible{
  outline:var(--sm-focus-outline);
  box-shadow:var(--focus-ring);
  text-decoration:underline;
}
.sm-site-footer__social{
  display:flex;
  flex-wrap:wrap;
  gap:var(--space-1);
}
/* No underline: the old footer's icon links underlined the whitespace around each glyph. */
.sm-site .sm-site-footer__social-link{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:var(--touch-target-min);
  height:var(--touch-target-min);
  font-size:var(--sm-icon-lg, var(--text-xl));
  line-height:1;
  color:var(--text-secondary);
  text-decoration:none;
  border-radius:var(--radius-md);
  transition:
    color var(--sm-duration-fast) var(--ease-standard),
    background-color var(--sm-duration-fast) var(--ease-standard);
}
.sm-site .sm-site-footer__social-link:hover{
  color:var(--text-strong);
  background-color:var(--surface-hover);
}
.sm-site .sm-site-footer__social-link:focus-visible{
  outline:var(--sm-focus-outline);
  box-shadow:var(--focus-ring);
}
.sm-site-footer__bottom{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  justify-content:space-between;
  gap:var(--space-4);
  margin-top:var(--space-10);
  padding-top:var(--space-6);
  color:var(--text-muted);
  border-top:var(--border-hairline) solid var(--border-subtle);
}
.sm-site-footer__legal{
  display:flex;
  flex-wrap:wrap;
  gap:var(--space-2) var(--space-5);
}
.sm-site-footer__copyright{ margin:0; }

/* ============================================================================
   11. Stage 2A — marketing shell and page components
   Home, the seven SimpliManagementFor* pages, the shared _Layout chrome and the
   _EmailSubscription partial. Same contract as the sections above: tokens only, no
   @layer, no !important, no `display` on a .collapse or on anything jQuery toggles
   (Home's #OwnerSection/#ManagerSection/#TenantSection and their `.section` panels).
   ========================================================================= */

/* --- 11.1 Shell ------------------------------------------------------------
   A column on <body>, so a short page's footer meets the viewport floor instead of
   leaving white under it. <body> and #main are neither collapses nor toggled. */
.sm-site{
  display:flex;
  flex-direction:column;
  min-height:100vh;
  min-height:100dvh;
}
.sm-site > #main{ flex:1 0 auto; }

/* The header is sticky from Bootstrap's lg up (<header class="sticky-lg-top">), where the
   navbar never collapses, so an open mobile menu can never pin itself over the page.
   Anchor jumps (/#FeaturesSection, /#PaymentSection, /#ScheduleADemo, the subscribe
   redirect's #emailSubscriptionSection), Home's scrollIntoView and the blog's JS-fixed
   TOC (site.css .blogpost-sticky-active, top:50px) clear the 64px bar. */
@media (min-width:992px){
  html:has(> body.sm-site){ scroll-padding-top:calc(var(--topbar-height) + var(--space-4)); }
  .sm-site .blogpost-sticky-active{ top:calc(var(--topbar-height) + var(--space-4)); }
}

/* TempData notices carry .sm-alert beside Bootstrap's .alert (the dismiss plugin needs it).
   .sm-alert's padding shorthand outranks .alert-dismissible's 3rem end padding by source
   order, which would run the text under the absolutely placed close button. */
.sm-site .sm-alert.alert-dismissible{ padding-inline-end:var(--space-12); }

/* Nav: in the open mobile menu each action takes a full-width row. Three abreast (Log in, Book a
   Demo and Sign up, signed out) wrapped "Book a / Demo" and "Sign / up" at 375 (pass 2 Tier B). */
@media (max-width:991.98px){
  .sm-site .sm-site-nav__actions > li{ flex:1 1 100%; }
  .sm-site .sm-site-nav__actions .sm-btn{ width:100%; }
}

/* Footer: a brand row (logo, social icons) above the closing row. */
.sm-site-footer__top{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  justify-content:space-between;
  gap:var(--space-6);
}
.sm-site-footer__brand{
  display:block;
  width:auto;
  height:var(--space-8);
}
/* Calendly's floating "Book a Demo" badge (Home's initBadgeWidget: widget.js puts a fixed
   .calendly-badge-widget, 45px tall and 15px off the bottom, first in <body>). Below 768px it is
   hidden: at 375 it covered the pricing card's own Book a Demo, and the hero and the mobile menu
   carry one too. widget.js writes no inline style on the badge itself, only the colours on its
   content, so this needs no !important. From 768px the footer keeps room for it, or the badge
   would sit on the footer's last row at the end of the page. */
@media (max-width:767.98px){
  .sm-site .calendly-badge-widget{ display:none; }
}
@media (min-width:768px){
  .sm-site:has(.calendly-badge-widget) .sm-site-footer{
    padding-bottom:calc(var(--space-8) + var(--space-16));
  }
}

/* --- 11.2 Type and layout helpers --------------------------------------------- */
.sm-display-4{
  font-size:var(--text-title, var(--text-xl));          /* 24px */
  line-height:var(--leading-title, var(--leading-tight));
  letter-spacing:var(--tracking-tight);
}
/* One step down below 768px, so the product pages' 70-100 character SEO H1s stay within
   four to six lines on a phone: display-2 36px -> 32px, display-3 32px -> 28px. */
@media (max-width:767.98px){
  .sm-display-2{ font-size:var(--text-display-3); }
  .sm-display-3{ font-size:var(--text-2xl); }
}
/* A 900px measure for pricing, the fee table, the FAQ and the promo card. */
.sm-container-narrow{
  max-width:calc(var(--content-max) * .75);
  margin-inline:auto;
}
/* A 4:5 portrait photo beside text (the property photos): a 16:10 crop while the split is
   one column, so it never runs a phone screen and a half tall; capped at 28rem from --bp-lg. */
.sm-split__media--portrait img{
  aspect-ratio:16 / 10;
  object-fit:cover;
}
@media (min-width:1120px){
  .sm-split__media--portrait{
    justify-self:center;
    width:100%;
    max-width:28rem;
  }
  .sm-split__media--portrait img{ aspect-ratio:4 / 5; }
}

/* --- 11.3 Hero: full-bleed video band, and the contained --band variant -------
   Always paired with .sm-section--ink on the same element, which supplies the page-ink
   canvas behind the video and the dark aliases (section 2). The scrim is a flat
   --ink-a64 wash, at least as dark as the old filter:brightness(40%), so the q60
   posters' artefacts stay invisible, plus a softer pool behind the text: a white video
   pixel comes out near rgb(92,92,95), and white text on that is above 6:1. */
.sm-hero{
  position:relative;
  isolation:isolate;
  overflow:hidden;
  display:flex;
  align-items:center;
  min-height:32.5rem;
  min-height:clamp(32.5rem, calc(100vh - var(--topbar-height) - var(--space-24)), 47.5rem);
  min-height:clamp(32.5rem, calc(100svh - var(--topbar-height) - var(--space-24)), 47.5rem);
  padding-block:var(--space-20);
  text-align:center;
}
.sm-hero::before{
  content:"";
  position:absolute;
  inset:0;
  z-index:-1;
  background-color:var(--ink-a64);
  background-image:radial-gradient(ellipse 60% 55% at 50% 50%, var(--ink-a40), transparent);
  pointer-events:none;
}
.sm-hero__video{
  position:absolute;
  inset:0;
  z-index:-2;
  width:100%;
  height:100%;
  object-fit:cover;
}
.sm-hero__content{
  position:relative;
  width:100%;
}
.sm-hero__pill{
  display:inline-flex;
  align-items:center;
  gap:var(--space-2);
  max-width:100%;
  margin:0 0 var(--space-6);
  padding:var(--space-1) var(--space-4) var(--space-1) var(--space-1);
  font-size:var(--text-sm);
  font-weight:var(--weight-semibold);
  line-height:var(--leading-snug);
  text-align:start;
  color:var(--text-strong);
  background-color:var(--white-a10);
  border:var(--border-hairline) solid var(--white-a16);
  border-radius:var(--radius-pill);
}
.sm-hero__pill-logo{
  flex:0 0 auto;
  display:block;
  width:var(--space-6);
  height:var(--space-6);
}
.sm-hero__title{
  max-width:14ch;
  margin-inline:auto;
  color:var(--text-strong);
}
/* .sm-lead is --text-secondary; over moving video the body colour is the safe one. */
.sm-hero .sm-hero__lead{
  margin:var(--space-5) auto 0;
  color:var(--text);
}
.sm-hero__actions{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:var(--space-3);
  margin-top:var(--space-8);
}
.sm-hero__statement{
  max-width:20ch;
  margin-inline:auto;
  color:var(--text-strong);
}
/* The pause/play control (WCAG 2.2.2): a 44px circle in the band's bottom-start corner, away from
   the bottom-right corner where Calendly's fixed "Book a Demo" badge floats. A tool (section 16),
   so its edge is the neutral outline: --sm-field-border, 4.82:1 on the ink canvas and at least
   3.12:1 against every pixel of the video round it (13 frames, 1280 and 375), and
   --sm-field-border-hover under the pointer. The old white-16% hairline was 1.54:1. */
.sm-hero__toggle{
  position:absolute;
  inset-block-end:var(--space-4);
  inset-inline-start:var(--space-4);
  z-index:1;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:var(--touch-target-min);
  height:var(--touch-target-min);
  padding:0;
  font-size:var(--text-md);
  line-height:1;
  color:var(--text-strong);
  background-color:var(--ink-a64);
  border:var(--border-hairline) solid var(--sm-field-border);
  border-radius:var(--radius-circle);
  cursor:pointer;
  transition:
    background-color var(--sm-duration-fast) var(--ease-standard),
    border-color var(--sm-duration-fast) var(--ease-standard);
}
.sm-hero__toggle:hover{
  background-color:var(--page-ink);
  border-color:var(--sm-field-border-hover);
}
.sm-hero__toggle:focus-visible{
  outline:var(--sm-focus-outline);
  box-shadow:var(--focus-ring);
}
.sm-hero--band{
  min-height:20rem;
  min-height:clamp(20rem, 38vw, 30rem);
  padding:var(--space-12) var(--space-6);
  border-radius:var(--radius-2xl);
}
@media (min-width:768px){
  .sm-hero{ padding-block:var(--space-24); }
  .sm-hero--band{ padding:var(--space-16); }
  .sm-hero__toggle{
    inset-block-end:var(--space-6);
    inset-inline-start:var(--space-6);
  }
}

/* --- 11.4 Screen: product screenshots and the demo video in an app-window frame ----
   A dark scope (section 2), so the carousel controls take the dark ring on the dark UI
   they sit over. --elev-4 is a light-surface shadow and is not rebound there. */
.sm-screen{
  position:relative;
  padding:var(--space-2);
  background-color:var(--page-ink);
  border-radius:var(--radius-xl);
  box-shadow:var(--elev-4);
}
.sm-screen img{
  display:block;
  width:100%;
  height:auto;
}
/* The fill shows while a lazy slide decodes, instead of a white flash. */
.sm-screen :is(.carousel-inner, .ratio){
  overflow:hidden;
  background-color:var(--surface-raised);
  border-radius:var(--radius-md);
}
/* The arrows are tools (section 16): the neutral outline on the --ink-a64 disc. The disc parts them
   from light screenshot pixels and the --sm-field-border rim (4.82:1 on the frame) from dark ones;
   over the measured slides 96.6% of the pixels round an arrow meet 3:1 against one or the other
   (the white-16% hairline managed 6.5%), and 99.95% under the pointer, where the disc goes opaque
   and the rim takes --sm-field-border-hover. The arrow glyph stays white on the disc, 6:1 or
   more. */
.sm-site .sm-screen :is(.carousel-control-prev, .carousel-control-next){
  top:50%;
  bottom:auto;
  width:var(--space-10);
  height:var(--space-10);
  margin-inline:var(--space-3);
  background-color:var(--ink-a64);
  border:var(--border-hairline) solid var(--sm-field-border);
  border-radius:var(--radius-circle);
  opacity:1;
  transform:translateY(-50%);
  transition:
    background-color var(--sm-duration-fast) var(--ease-standard),
    border-color var(--sm-duration-fast) var(--ease-standard);
}
.sm-site .sm-screen :is(.carousel-control-prev, .carousel-control-next):hover{
  background-color:var(--page-ink);
  border-color:var(--sm-field-border-hover);
}
.sm-site .sm-screen :is(.carousel-control-prev, .carousel-control-next):focus-visible{
  outline:var(--sm-focus-outline);
  box-shadow:var(--focus-ring);
}
.sm-site .sm-screen :is(.carousel-control-prev-icon, .carousel-control-next-icon){
  width:var(--space-4);
  height:var(--space-4);
}

/* --- 11.5 Feature explorer (Home's Owner / Manager / Tenant sections) ----------
   The grid goes on the wrapper INSIDE each role section, never on #OwnerSection etc. or
   on a `.section` panel: jQuery shows and hides those. */
.sm-role-switch{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:var(--space-4);
  margin:0 0 var(--space-10);
}
.sm-role-switch__title{
  min-width:7ch;
  text-align:center;
}
.sm-explorer{
  display:grid;
  gap:var(--space-8);
}
@media (min-width:992px){
  .sm-explorer{
    grid-template-columns:minmax(0, 5fr) minmax(0, 7fr);
    align-items:start;
    gap:var(--space-12);
  }
}
.sm-feature-tabs{
  display:grid;
  gap:var(--space-1);
  margin:0;
  padding:0;
  list-style:none;
}
/* The <li> keeps .list-group-item: the page script selects `.list-group-item a`. site.css
   paints that class dark, and `.feature-list .list-group-item` white at 18px, (0,2,0). */
.sm-site .sm-feature-tabs .list-group-item{
  padding:0;
  font-size:inherit;
  color:inherit;
  background-color:transparent;
  border:0;
}
.sm-feature-tabs__link{
  display:flex;
  align-items:center;
  gap:var(--space-3);
  min-height:var(--touch-target-min);
  padding:var(--space-3) var(--space-4);
  font-size:var(--text-md);
  font-weight:var(--weight-medium);
  line-height:var(--leading-snug);
  text-align:start;
  text-decoration:none;
  color:var(--text-secondary);
  border-radius:var(--radius-md);
  transition:
    color var(--sm-duration-fast) var(--ease-standard),
    background-color var(--sm-duration-fast) var(--ease-standard);
}
.sm-site .sm-feature-tabs__link:hover{
  color:var(--text-strong);
  text-decoration:none;
  background-color:var(--surface-hover);
}
/* .selected is the page script's class. site.css gives it color:#6d30a7 !important (the
   brand: 7.2:1 on this tint, so it stands) and a 22px size that reflowed the list. */
.sm-site .sm-feature-tabs__link.selected{
  font-size:var(--text-md);
  font-weight:var(--weight-semibold);
  background-color:var(--brand-subtle);
  box-shadow:inset calc(var(--border-emphasis) * 2) 0 0 var(--brand);
}
.sm-site .sm-feature-tabs__link:focus-visible{
  outline:var(--sm-focus-outline);
  box-shadow:var(--focus-ring);
}
/* The focus ring is a box-shadow too, so on the selected tab it replaced the bar above: while that
   tab had keyboard focus, only the 1.21:1 tint and the label's colour and weight marked it. The
   selected tab keeps its bar inside the ring: 6.31:1 against the tint and 7.98:1 against the
   ring's --page gap. Forced colours drop both shadows and draw the bar as a Highlight border
   (DA-D3), so nothing changes there. (0,4,0), over the (0,3,0) rules above. */
.sm-site .sm-feature-tabs__link.selected:focus-visible{
  box-shadow:var(--focus-ring), inset calc(var(--border-emphasis) * 2) 0 0 var(--brand);
}
/* Brand-coloured glyphs: the tab icons, and the icon in a panel caption's title (Home's
   explorer, the product pages' "See Our Software in Action" caption). */
.sm-feature-tabs__link > .sm-icon,
.sm-feature-card__title > .sm-icon{ color:var(--brand-text); }

/* --- 11.6 Feature-card art and the checklist ----------------------------------- */
.sm-feature-card__art{
  display:block;
  width:var(--space-20);
  height:auto;
  margin-bottom:var(--space-4);
}
.sm-feature-card__art--lg{ width:var(--space-24); }

/* A list whose items are benefits. Brand check marks drawn as a mask in currentColor;
   plain bullets where masks are unsupported. */
.sm-checklist{
  display:grid;
  gap:var(--space-3);
  margin:0;
  padding-inline-start:1.25em;
  line-height:var(--leading-normal);
  color:var(--text-secondary);
}
.sm-checklist > li::marker{ color:var(--brand-text); }
@supports ((-webkit-mask-image:none) or (mask-image:none)){
  .sm-checklist{
    padding-inline-start:0;
    list-style:none;
  }
  .sm-checklist > li{
    position:relative;
    padding-inline-start:calc(1em + var(--space-3));
  }
  .sm-checklist > li::before{
    content:"";
    position:absolute;
    inset-inline-start:0;
    top:0.15em;
    width:1em;
    height:1em;
    background-color:var(--brand-text);
    -webkit-mask:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M3 8.5l3.25 3.25L13 5'/%3e%3c/svg%3e") center / contain no-repeat;
    mask:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M3 8.5l3.25 3.25L13 5'/%3e%3c/svg%3e") center / contain no-repeat;
  }
}

/* --- 11.7 Comparison table (Home's hidden-fees table) ---------------------------
   Sits flush in its .sm-card between __header and __footer, inside the .sm-prose__table
   scroll wrapper (section 6; tabindex, role and a name). The outer cells carry the card's
   inner padding, so the brand-washed last column (Simpli Management's) runs to the card
   edge. Tightened below 576px so all three columns fit a 320px screen without scrolling. */
.sm-compare-table{
  width:100%;
  margin:0;
  border-collapse:collapse;
  font-size:var(--text-base);
  line-height:var(--leading-snug);
}
.sm-compare-table :is(th, td){
  padding:var(--space-3) var(--space-4);
  text-align:center;
  vertical-align:middle;
  border-bottom:var(--border-hairline) solid var(--border-subtle);
}
.sm-compare-table :is(th, td):first-child{
  padding-inline-start:var(--pad-card);
  text-align:start;
  color:var(--text);
}
.sm-compare-table :is(th, td):last-child{ padding-inline-end:var(--pad-card); }
.sm-compare-table thead th{
  font-size:var(--text-sm);
  font-weight:var(--weight-semibold);
  color:var(--text-strong);
  background-color:var(--surface-raised);
  border-bottom-color:var(--border);
}
.sm-compare-table :is(th, td):last-child{ background-color:var(--brand-a08); }
.sm-compare-table thead th:last-child{
  color:var(--brand-text);
  background-color:var(--brand-subtle);
}
.sm-compare-table tbody tr:last-child > *{ border-bottom:0; }
@media (max-width:575.98px){
  .sm-compare-table{ font-size:var(--text-sm); }
  .sm-compare-table :is(th, td){ padding:var(--space-3) var(--space-2); }
  .sm-compare-table :is(th, td):first-child{ padding-inline-start:var(--space-4); }
  .sm-compare-table :is(th, td):last-child{ padding-inline-end:var(--space-4); }
  .sm-compare-table thead th{ font-size:var(--text-xs); }
}

/* --- 11.8 Ink panel (the pricing calculator's result) --------------------------
   A dark scope (section 2): a rounded page-ink panel with the sanctioned brand glow. */
.sm-ink-panel{
  position:relative;
  isolation:isolate;
  overflow:hidden;
  padding:var(--pad-panel);
  color:var(--text);
  background-color:var(--page-ink);
  border-radius:var(--radius-xl);
}
.sm-ink-panel::before{
  content:"";
  position:absolute;
  z-index:-1;
  top:-40%;
  right:-25%;
  width:80%;
  aspect-ratio:1;
  background:radial-gradient(closest-side, var(--brand-a24), transparent 70%);
  filter:blur(40px);
  pointer-events:none;
}

/* Bootstrap 5.2.2 paints .form-range from Sass literals (a #0d6efd thumb), not variables.
   One rule per engine: a selector list mixing -webkit- and -moz- pseudo-elements is
   dropped whole by the engine that does not know one of them. */
.sm-site .form-range:not(:where(.sm-app *, .sm-public-dark *))::-webkit-slider-thumb{ background-color:var(--brand); }
.sm-site .form-range:not(:where(.sm-app *, .sm-public-dark *))::-webkit-slider-thumb:active{ background-color:var(--brand-active); }
.sm-site .form-range:not(:where(.sm-app *, .sm-public-dark *))::-webkit-slider-runnable-track{ background-color:var(--border); }
.sm-site .form-range:not(:where(.sm-app *, .sm-public-dark *)):focus::-webkit-slider-thumb{ box-shadow:none; }
.sm-site .form-range:not(:where(.sm-app *, .sm-public-dark *)):focus-visible::-webkit-slider-thumb{ box-shadow:var(--focus-ring); }
.sm-site .form-range:not(:where(.sm-app *, .sm-public-dark *))::-moz-range-thumb{ background-color:var(--brand); }
.sm-site .form-range:not(:where(.sm-app *, .sm-public-dark *))::-moz-range-thumb:active{ background-color:var(--brand-active); }
.sm-site .form-range:not(:where(.sm-app *, .sm-public-dark *))::-moz-range-track{ background-color:var(--border); }
.sm-site .form-range:not(:where(.sm-app *, .sm-public-dark *)):focus::-moz-range-thumb{ box-shadow:none; }
.sm-site .form-range:not(:where(.sm-app *, .sm-public-dark *)):focus-visible::-moz-range-thumb{ box-shadow:var(--focus-ring); }
/* The range's own outline. Forced colours drop the thumb ring above, and Bootstrap's
   `.form-range:focus{outline:0}` (0,2,0) outranks app.css 0.2's (0,1,0) forced-colours
   catch-all, so the outline is restated through --sm-focus-outline as 8.3 does for .btn and
   fields: none until forced colours are active, then the 2px CanvasText line. 11.13 repaints
   the thumb and track there. */
.sm-site .form-range:not(:where(.sm-app *, .sm-public-dark *)):focus-visible{ outline:var(--sm-focus-outline); }

/* The demo video under Home's "Book a Demo Today" band (7.3). */
.sm-cta-band__media{
  max-width:50rem;
  margin:var(--space-12) auto 0;
}

/* --- 11.9 Promo card (the free valuation tool: Home and the seven product pages) --- */
.sm-promo-card{
  display:grid;
  justify-items:center;
  align-items:center;
  gap:var(--space-6);
  padding:var(--pad-panel) var(--space-6);
  text-align:center;
  color:var(--text);
  background-color:var(--surface);
  border:var(--border-hairline) solid var(--border-subtle);
  border-radius:var(--radius-2xl);
  box-shadow:var(--elev-dark-2);
}
.sm-promo-card__media{
  display:block;
  width:min(12.5rem, 100%);
  height:auto;
}
.sm-promo-card__body{ max-width:var(--prose-max); }
.sm-promo-card__body > *{ margin:0; }
.sm-promo-card__body > * + *{ margin-top:var(--space-3); }
.sm-promo-card__body > .sm-btn{ margin-top:var(--space-6); }
@media (min-width:768px){
  .sm-promo-card{
    grid-template-columns:minmax(0, 15rem) minmax(0, 1fr);
    justify-items:start;
    gap:var(--space-10);
    padding:var(--space-10) var(--space-12);
    text-align:start;
  }
  .sm-promo-card__media{ width:100%; }
}

/* --- 11.10 Post card (Home's latest posts; the blog index in 2B) -----------------
   The whole card is the link: __link's ::after covers it. The image takes a fixed 16:9
   box whatever the source ratio, so rows never go ragged and nothing shifts on load. */
.sm-post-card{
  position:relative;
  display:flex;
  flex-direction:column;
  height:100%;
  overflow:hidden;
  color:var(--text);
  background-color:var(--surface);
  border:var(--border-hairline) solid var(--border-subtle);
  border-radius:var(--radius-xl);
  box-shadow:var(--elev-dark-1);
  transition:
    border-color var(--sm-duration-fast) var(--ease-standard),
    box-shadow var(--sm-duration-base) var(--ease-standard),
    transform var(--sm-duration-base) var(--ease-standard);
}
.sm-post-card__media{
  display:block;
  width:100%;
  height:auto;
  aspect-ratio:16 / 9;
  object-fit:cover;
  background-color:var(--surface-raised);
}
.sm-post-card__body{
  display:flex;
  flex:1 1 auto;
  flex-direction:column;
  gap:var(--space-3);
  padding:var(--pad-card);
}
.sm-post-card__title{
  margin:0;
  font-family:var(--font-display);
  font-size:var(--text-lg);
  font-weight:var(--weight-bold);
  line-height:var(--leading-tight);
  letter-spacing:var(--tracking-tight);
  color:var(--text-strong);
}
.sm-post-card__excerpt{
  margin:0;
  line-height:var(--leading-normal);
  color:var(--text-secondary);
}
.sm-site .sm-post-card__link{
  margin-top:auto;
  padding-top:var(--space-2);
  font-weight:var(--weight-semibold);
  color:var(--text-link);
  text-decoration:none;
}
.sm-site .sm-post-card__link:hover{
  color:var(--text-link-hover);
  text-decoration:underline;
}
.sm-post-card__link::after{
  content:"";
  position:absolute;
  inset:0;
}
.sm-post-card:hover{
  border-color:var(--border);
  box-shadow:var(--elev-dark-3);
}
@media (prefers-reduced-motion:no-preference){
  .sm-post-card:hover{ transform:var(--lift-hover); }
}
.sm-post-card:has(.sm-post-card__link:focus-visible){
  outline:var(--sm-focus-outline);
  box-shadow:var(--focus-ring);
}
@supports selector(:has(*)){
  .sm-site .sm-post-card__link:focus-visible{ box-shadow:none; }
}

/* --- 11.11 Subscribe panel (_EmailSubscription: blog index, 36 posts, Article) ---- */
.sm-subscribe{
  max-width:48rem;
  margin:var(--space-16) auto;
  padding:var(--space-10) var(--space-6);
  text-align:center;
  color:var(--text);
  background-color:var(--page-tint);
  border:var(--border-hairline) solid var(--brand-a12);
  border-radius:var(--radius-2xl);
}
.sm-subscribe__title{
  margin:0;
  font-family:var(--font-display);
  font-size:var(--text-2xl);
  font-weight:var(--weight-bold);
  line-height:var(--leading-tight);
  letter-spacing:var(--tracking-tight);
  color:var(--text-strong);
}
.sm-subscribe__body{
  max-width:46ch;
  margin:var(--space-3) auto var(--space-6);
  line-height:var(--leading-normal);
  color:var(--text-secondary);
}
.sm-subscribe > .alert{
  margin-bottom:var(--space-4);
  text-align:start;
}
.sm-subscribe__form{
  max-width:32rem;
  margin:0 auto;
  text-align:start;
}
.sm-subscribe__form .sm-input-group{ flex-wrap:wrap; }
.sm-subscribe__form .sm-input{ flex:1 1 14rem; }
.sm-subscribe__form .sm-btn{ flex:0 0 auto; }
.sm-subscribe__form .sm-field__error{ margin-top:var(--space-2); }
@media (min-width:768px){
  .sm-subscribe{ padding:var(--space-12); }
}
@media (max-width:575.98px){
  .sm-subscribe__form .sm-btn{ flex-basis:100%; }
}

/* --- 11.12 Phones: long button labels wrap instead of overflowing ---------------
   .sm-btn is nowrap at a fixed height, sized for the app's short labels. */
@media (max-width:575.98px){
  .sm-site .sm-btn:not(:where(.sm-btn--icon, .sm-app *, .sm-public-dark *)){
    max-width:100%;
    height:auto;
    min-height:var(--touch-target-min);
    padding-block:var(--space-2);
    line-height:var(--leading-tight);
    white-space:normal;
    text-wrap:balance;
  }
  .sm-site .sm-btn--lg:not(:where(.sm-btn--icon, .sm-app *, .sm-public-dark *)){
    min-height:var(--control-height-lg);
  }
  /* A pair of calls to action stacks full width rather than wrapping ragged. */
  .sm-site .sm-btn-group:not(:where(.sm-app *, .sm-public-dark *)){ display:flex; }
  .sm-site .sm-btn-group:not(:where(.sm-app *, .sm-public-dark *)) > .sm-btn{ flex:1 1 100%; }
}

/* --- 11.13 Forced colours: the paint that vanished ----------------------------
   Forced colours (Windows High Contrast) repaint the page from the user's palette: an author
   background takes the palette's (Canvas, ButtonFace in a button), keeping its alpha; text and
   borders take CanvasText, LinkText or ButtonText; box-shadow goes. System colours are exempt,
   and so is anything that opts out with forced-color-adjust:none. Focus already survives
   through --sm-focus-outline (app.css 0.2, restated in 8.3 and 11.8); these rules bring back
   what was drawn only with a background or a shadow. From the Stage 2A verification (lens
   DA-D1 to DA-D4, and the logo), each seen in Chrome's forced-colours emulation. */
@media (forced-colors: active){
  /* DA-D1: the calculator sliders (#unitsRange, #occupancyRateRange). Thumb and track are
     appearance:none pseudo-elements painted only by their backgrounds, so both took the
     palette's background and the sliders vanished. The thumb takes ButtonText, the track
     GrayText. The pressed thumb is restated because 11.8's :active rule is one pseudo-class
     heavier. One list per engine, as in 11.8. */
  .sm-site .form-range:not(:where(.sm-app *, .sm-public-dark *))::-webkit-slider-thumb,
  .sm-site .form-range:not(:where(.sm-app *, .sm-public-dark *))::-webkit-slider-thumb:active{ background-color:ButtonText; }
  .sm-site .form-range:not(:where(.sm-app *, .sm-public-dark *))::-webkit-slider-runnable-track{ background-color:GrayText; }
  .sm-site .form-range:not(:where(.sm-app *, .sm-public-dark *))::-moz-range-thumb,
  .sm-site .form-range:not(:where(.sm-app *, .sm-public-dark *))::-moz-range-thumb:active{ background-color:ButtonText; }
  .sm-site .form-range:not(:where(.sm-app *, .sm-public-dark *))::-moz-range-track{ background-color:GrayText; }

  /* DA-D2: icons drawn as a mask over an author background-color — the nav toggler's bars
     (9.1) and the FAQ chevron (8.1) in currentColor, the checklist ticks (11.6) in --brand-text.
     Neither is a system colour, so each took the palette's background and vanished; below 992px
     the toggler was an empty square. Each takes the system colour of the text it sits with:
     ButtonText in the two buttons, CanvasText in the list. Same weights as the rules they
     repaint, later in the file. */
  @supports ((-webkit-mask-image:none) or (mask-image:none)){
    .sm-site .sm-site-nav__toggler .navbar-toggler-icon,
    .sm-site .accordion-button::after{ background-color:ButtonText; }
    .sm-checklist > li::before{ background-color:CanvasText; }
  }

  /* DA-D3: the selected explorer tab (the page script's .selected) was marked by a tint and an
     inset box-shadow bar. Both go here, which left weight alone. A Highlight bar on the leading
     edge instead, with the padding reduced by its width so the label does not move. */
  .sm-site .sm-feature-tabs__link.selected{
    border-inline-start:calc(var(--border-emphasis) * 2) solid Highlight;
    padding-inline-start:calc(var(--space-4) - var(--border-emphasis) * 2);
  }

  /* DA-D4: the carousel arrows. The arrow is Bootstrap's white SVG, which forced colours keep,
     and the --ink-a64 disc under it became ButtonFace at 64%: white on near-white in a light
     palette. The controls opt out and keep their disc, hairline and arrow; they only ever sit
     over a product screenshot, which forced colours leave alone. Opting out also brings their
     box-shadow focus ring back, which the CanvasText outline (offset 2px by app.css 0.2) would
     cover exactly, leaving a light palette's black outline as the only mark over a dark
     screenshot. The outline moves out past the ring, so both show. */
  .sm-site .sm-screen :is(.carousel-control-prev, .carousel-control-next){ forced-color-adjust:none; }
  .sm-site .sm-screen :is(.carousel-control-prev, .carousel-control-next):focus-visible{
    outline-offset:calc(var(--sm-focus-width) * 2);
  }

  /* The logo in the nav and the footer. The only logo asset is white on transparent (9), drawn
     on the ink bands; forced colours turn the bands Canvas, so a light palette showed white on
     white. The image opts out and carries its own --page-ink plate, the backdrop it was drawn
     for, so it reads on any palette; a CanvasText outline would only frame an empty box. On a
     dark palette the plate all but disappears into Canvas. The plate is on the <img> itself:
     one rule serves both logos, the footer logo shares its row with the social links (which
     keep the user's colours), and the brand link keeps its plain forced-colours outline. The
     glyphs run to the image's edges, so the padding is what parts them from a light Canvas.
     content-box keeps the logo at its own height; the radius is smaller than the side padding,
     so the image's own corners stay square and uncut. */
  .sm-site-nav__logo,
  .sm-site-footer__brand{
    forced-color-adjust:none;
    box-sizing:content-box;
    padding:var(--space-1) var(--space-2);
    background-color:var(--page-ink);
    border-radius:var(--radius-xs);
  }
}

/* ============================================================================
   12. Stage 2B — the blog: the index (Home/BlogPosts), the 36 hand-written posts
   (Views/BlogPosts/*) and the Staffiva article (BlogPosts/Article, body_html via Html.Raw).
   Same contract as sections 1–11: tokens only, no @layer, no !important, no `display` on a
   .collapse or on anything a script toggles.

   THE POST SCRIPTS STAY BYTE-IDENTICAL, and three rules below exist because of them:
   - The contents highlight and the sticky choreography measure offsetTop, which is relative to
     the nearest POSITIONED ancestor. Nothing from .sm-post down to the article's sections and
     headings may take a `position` (the rails may: they are siblings of the article).
   - They toggle .blogpost-sticky-active (site.css: position:fixed) and .blogpost-pinned-bottom
     (position:absolute) on .blogpost-toc and .blogpost-ad-banner, and write an inline `left` on
     the banner. 12.4 holds both elements static, so none of that moves them; the rail AROUND
     each one is what sticks.
   - BlogPosts/Article's script writes an inline display:none on .blogpost-toc when a body has
     no h2. Nothing here declares `display` on .blogpost-toc or .blogpost-ad-banner.
   A section counts as current once its top is within 100px of the viewport top, so from 992px
   (2A's 80px scroll-padding under the sticky header) a contents jump may add at most 19px (12.5).
   ========================================================================= */

/* --- 12.1 Blog index -----------------------------------------------------------
   Title and lead at the start, the demo button at the end, wrapping under them on narrow
   screens. The cards are 2A's .sm-post-card (11.10) in Bootstrap's row-cols grid. */
.sm-blog-head{
  display:flex;
  flex-wrap:wrap;
  align-items:flex-end;
  justify-content:space-between;
  gap:var(--space-6) var(--space-10);
}

/* Excerpts are teasers of any length (a Staffiva excerpt can run to 370 characters): four
   lines, then an ellipsis, so one long excerpt cannot stretch a whole row. Titles are never
   clamped. On a <p>, never a toggled element. */
.sm-post-card__excerpt{
  display:-webkit-box;
  -webkit-box-orient:vertical;
  -webkit-line-clamp:4;
  overflow:hidden;
}

/* A Staffiva post with no hero image still gets the 16:9 media slot, drawn by CSS (no markup
   branch), so its card lines up with its row: a purple-50 panel with a faint brand wash.
   .sm-post-card is a flex column, so the pseudo-element is its first item. */
.sm-post-card:not(:has(> .sm-post-card__media))::before{
  content:"";
  display:block;
  aspect-ratio:16 / 9;
  background-color:var(--page-tint);
  background-image:radial-gradient(circle at 30% 20%, var(--brand-a12), transparent 60%);
}

/* Three static cards keep a frozen src of a -small.webp: an 800x450 copy of a 1200x630 original
   that was squashed, not cropped (P-SMALL; mean pixel difference 2.5-3.0 against a squash, 20-27
   against a 16:9 crop). The file is already 16:9, so 11.10's object-fit:cover has nothing to crop,
   and the content showed 7% narrow. It is stretched back across its width by
   (1200 / 630) / (800 / 450) = 1.0714, and the card's overflow:hidden trims the overhang: the
   result is the original's 16:9 cover crop (within 3.3-4.8 of it, against 20-27 before). A
   transform leaves the layout box alone, and the card link's ::after still paints above it. */
.sm-post-card__media[src*="/img/blogPosts/"][src$="-small.webp"]{ transform:scaleX(1.0714); }

/* --- 12.2 Post header -----------------------------------------------------------
   On the page's own container (<div class="sm-container-wide sm-post">): the title block and
   the hero in 2A's .sm-split (one column below 1120px, text first), then a hairline. */
.sm-post{ padding-top:var(--space-8); }
.sm-post__header{
  padding-bottom:var(--space-10);
  margin-bottom:var(--space-10);
  border-bottom:var(--border-hairline) solid var(--border-subtle);
}
/* The <h1> carries .sm-display-2 (2A: 48px, 32px below 768px). A Staffiva title can be
   long; an unbroken token must still wrap. */
.sm-post__title{ overflow-wrap:break-word; }
/* BlogPosts/Article renders the media column whether or not the article has a hero: without
   one, the empty column goes and the title block spans the split. (Without :has() the title
   keeps its half of the split.) The column is never script-toggled. */
.sm-post__hero:not(:has(img)){ display:none; }
.sm-post__split:not(:has(.sm-post__hero img)) > .sm-post__intro{ grid-column:1 / -1; }
.sm-post__meta{
  margin:var(--space-5) 0 0;
  font-size:var(--text-base);
  line-height:var(--leading-snug);
  color:var(--text-secondary);
}
/* "Categories:" / "Tags:" and their .sm-badge chips. On a <div>, never toggled. */
.sm-post__terms{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--space-2);
  margin:var(--space-3) 0 0;
  font-size:var(--text-sm);
  line-height:var(--leading-tight);
  color:var(--text-secondary);
}
.sm-post__terms > strong{
  margin-inline-end:var(--space-1);
  font-weight:var(--weight-semibold);
  color:var(--text-strong);
}
/* One frame for every hero, hand-written or ingested: 16:9 cover, the same crop the index card
   shows, so the box is known before the image arrives (no layout shift, dimensions or not).
   .sm-split__media already makes it a full-width block with the 20px radius. */
.sm-post__hero-img{
  aspect-ratio:16 / 9;
  object-fit:cover;
  background-color:var(--surface-raised);
}
/* Except the brand graphics: the six comparison posts' "Simpli Management vs ..." artwork and the
   QuickBooks setup guide's, all 1824x1216 (3:2) and drawn nearly to their edges. The artwork
   starts 68px down (the Simpli wordmark's roof apex) and ends 1015-1202px down, and a 16:9 band
   is only 1026px tall: the centred crop cut the apex off all seven, and no crop position keeps
   both edges of Buildium's 1050px or TurboTenant's 1135px of artwork. They take their own 3:2
   frame, so nothing is cut and the box is still known before the image loads. Matched by file
   name (the URLs are frozen), case-insensitively because the names mix VS, Vs and And. */
.sm-post__hero-img[src*="/img/blogPosts/simpliManagement" i]{ aspect-ratio:3 / 2; }
@media (min-width:768px){
  .sm-post{ padding-top:var(--space-12); }
  .sm-post__header{
    padding-bottom:var(--space-12);
    margin-bottom:var(--space-12);
  }
}
/* Title beside hero from 992px, where the contents rail also starts: a full-width hero there
   is 960px wide and pushes the article below the fold. 2A's .sm-split takes over at 1120px
   with its wider gap. */
@media (min-width:992px){
  .sm-post__split{ grid-template-columns:repeat(2, minmax(0, 1fr)); }
}

/* --- 12.3 Body layout: contents rail | article | aside rail ----------------------
   Below 992px one column: both rails hidden (site.css already hides their contents below
   768px), the header and the article held to one centred reading width. From 992px the
   contents rail joins; from 1200px the aside rail too. Each rail is a grid item that sticks
   under 2A's sticky header (sticky-lg-top, 64px) for the length of the article. */
.sm-post__main{ min-width:0; }
.sm-post__rail{ display:none; }
@media (max-width:991.98px){
  .sm-post__header,
  .sm-post__layout{
    max-width:44rem;
    margin-inline:auto;
  }
}
@media (min-width:992px){
  .sm-post__layout{
    display:grid;
    grid-template-columns:13rem minmax(0, 1fr);
    align-items:start;
    column-gap:var(--space-10);
  }
  .sm-post__rail--toc{
    display:block;
    position:sticky;
    top:calc(var(--topbar-height) + var(--space-8));
    max-height:calc(100vh - var(--topbar-height) - var(--space-16));
    overflow-y:auto;
    overscroll-behavior:contain;
  }
}
@media (min-width:1200px){
  .sm-post__layout{
    grid-template-columns:14rem minmax(0, 1fr) 15rem;
    column-gap:var(--space-12);
  }
  .sm-post__rail--aside{
    display:block;
    position:sticky;
    top:calc(var(--topbar-height) + var(--space-8));
  }
}
/* BlogPosts/Article builds its contents from the body's h2s and, when there are none, writes
   an inline display:none on the nav (its only signal). The empty rail then gives its column
   to the article. The rail is never toggled by script; the nav inside it is left alone. */
@supports selector(:has(*)){
  @media (min-width:992px){
    .sm-post__layout:has(> .sm-post__rail--toc > .blogpost-toc[style*="none"]) > .sm-post__rail--toc{ display:none; }
    .sm-post__layout:has(> .sm-post__rail--toc > .blogpost-toc[style*="none"]) > .sm-post__main{ grid-column:1 / 3; }
  }
}

/* --- 12.4 The rails' contents ----------------------------------------------------
   The scripts' classes (see the header) are held static: (0,2,0) over site.css's (0,1,0)
   .blogpost-sticky-active / .blogpost-pinned-bottom and .blogpost-toc/.blogpost-ad-banner, and
   2A's (0,2,0) top offset is inert on a static box. The inline `left` is inert too. */
.sm-post__rail > :is(.blogpost-toc, .blogpost-ad-banner){ position:static; }

/* The "Contents" <h2> (text unchanged) as a caps label: 12px/600 --text-muted, 6.61:1. */
.sm-post__toc-title{
  margin:0 0 var(--space-3);
  font-size:var(--text-xs);
  font-weight:var(--weight-semibold);
  line-height:var(--leading-tight);
  letter-spacing:var(--tracking-caps);
  text-transform:uppercase;
  color:var(--text-muted);
}
/* A hairline track; the current section's link (the script's .active) takes a brand bar on it.
   (0,3,0)/(0,4,0): over site.css's .blogpost-toc .nav-link (0,2,0) and its .active (0,3,0). */
.sm-post .blogpost-toc .nav{
  flex-wrap:nowrap;
  border-inline-start:var(--border-hairline) solid var(--border-subtle);
}
.sm-post .blogpost-toc .nav-link{
  margin-inline-start:calc(var(--border-hairline) * -1);
  padding:var(--space-15) var(--space-3);
  font-size:var(--text-base);
  font-weight:var(--weight-medium);
  line-height:var(--leading-snug);
  color:var(--text-secondary);
  text-decoration:none;
  border-inline-start:calc(var(--border-hairline) * 2) solid transparent;
  border-radius:0 var(--radius-xs) var(--radius-xs) 0;
  /* Pass 2: a heading with one unbreakable token (a 60-character name) wraps inside the rail instead
     of clipping behind a horizontal scrollbar. .nav{flex-wrap:nowrap} above already holds the link
     to the rail's width, so break-word is enough. */
  overflow-wrap:break-word;
}
.sm-post .blogpost-toc .nav-link:hover{
  color:var(--text-strong);
  border-inline-start-color:var(--border-strong);
}
.sm-post .blogpost-toc .nav-link.active{
  font-weight:var(--weight-semibold);
  color:var(--brand-text);
  border-inline-start-color:var(--brand);
}
/* Inset (app.css 0.2): each link spans the rail, and from 992px the rail is its own scroll box
   (12.3), which clipped both sides of an outset ring and the last link's bottom band. Inside the
   link the ring is whole: --purple-600, 7.98:1 on the white rail. The negative offset keeps the
   forced-colours outline inside the clip too. */
.sm-post .blogpost-toc .nav-link:focus-visible{
  outline:var(--sm-focus-outline);
  outline-offset:var(--sm-focus-offset-inset);
  box-shadow:var(--sm-focus-ring-inset);
}
/* Forced colours paint every border in the text colour, the transparent resting bars included,
   so each link showed the same 2px bar and the current section differed by weight alone (the
   explorer-tab failure 11.13 fixed). There the resting bars, and the hairline track they cover,
   take Canvas and vanish; at rest only the current link keeps a bar, in Highlight (the heavier
   :hover rule still marks a hovered link). System colours are not forced. Same weights as the
   rules they repaint, later in the file. */
@media (forced-colors: active){
  .sm-post .blogpost-toc .nav-link{ border-inline-start-color:Canvas; }
  .sm-post .blogpost-toc .nav-link.active{ border-inline-start-color:Highlight; }
}

/* The aside banner (img/blogSideBanner.webp, 500×1251, a dark artwork): the rail's full width,
   the panel radius, a light lift. site.css scales it 1.05 on hover with no motion guard;
   (0,3,0) over its (0,2,1). The lift exists only without reduced motion. */
.sm-post__ad > a{
  display:block;
  border-radius:var(--radius-xl);
}
.sm-post .sm-post__ad-img{
  display:block;
  width:100%;
  max-width:none;
  height:auto;
  border-radius:var(--radius-xl);
  box-shadow:var(--elev-2);
  transition:
    box-shadow var(--sm-duration-base) var(--ease-standard),
    transform var(--sm-duration-base) var(--ease-standard);
}
.sm-post .sm-post__ad-img:hover{
  transform:none;
  box-shadow:var(--elev-3);
}
@media (prefers-reduced-motion:no-preference){
  .sm-post .sm-post__ad > a:hover .sm-post__ad-img{ transform:var(--lift-hover); }
}

/* --- 12.5 Prose in a post ---------------------------------------------------------
   The article keeps section 6's measure and sits at the start of its column, so its left
   edge lines up with the title above whether or not a contents rail is beside it. */

/* The hand-written article is a run of <section id="…" class="mb-5">, each opening with its
   h2. Bootstrap's mb-5 (48px) already separates them, so the opening heading drops the top
   margin section 6 gives it. (0,1,1) over section 6's (0,0,1). */
:where(.sm-prose) section > :first-child{ margin-top:0; }
:where(.sm-prose) section > :last-child{ margin-bottom:0; }

/* The contents jump (see the header): 2A's 80px scroll-padding + 8px stays under the scripts'
   100px threshold, so the section jumped to is the one highlighted. Phones have no rail. */
@media (min-width:992px){
  .sm-post :where(.sm-prose) :is(section, h2, h3, h4)[id]{ scroll-margin-top:var(--space-2); }
}

/* FAQ accordions inside prose (24 of the 36 posts). The questions are h2.accordion-header
   (text frozen): the prose heading margin and size stay off them; the question reads at the
   body size, semibold, like its answer. Paint is section 8.1's. (0,1,0), after Bootstrap. */
:where(.sm-prose) .accordion{ margin-bottom:var(--sm-prose-gap); }
:where(.sm-prose) .accordion-header{
  margin:0;
  font-size:inherit;
}
:where(.sm-prose) .accordion-button{ font-size:inherit; }

/* Bootstrap `.table` in a post (the 9 hand-written tables): its own variables, in tokens. */
.sm-prose .table{
  --bs-table-color:var(--text);
  --bs-table-bg:transparent;
  --bs-table-border-color:var(--border-subtle);
  --bs-table-striped-color:var(--text);
  --bs-table-striped-bg:var(--surface-raised);
  --bs-table-hover-color:var(--text);
  --bs-table-hover-bg:var(--surface-hover);
  margin-bottom:var(--sm-prose-gap);
}
.sm-prose .table > thead{
  --bs-table-color:var(--text-strong);
  --bs-table-bg:var(--surface-sunken);
  --bs-table-border-color:var(--border);
}
/* Under 375px. The column is 288px at 320 (WCAG 1.4.10), and at 15px with Bootstrap's 8px cell
   padding the bond post's table needs 328px ("(Ginnie/Freddie", "Prepayment" and "maintenance,"
   cannot break) and TurboTenant's 314px, so a last column was cut off with no way to scroll to it.
   13px text and 6px inline padding bring the widest of the nine to 280px (all nine computed from
   Archivo's metrics, a model that reproduces the four widths measured at 320 within 0.5px), so
   each fits, no text changes and none needs a scroll wrapper. Ingested bodies scroll (12.7). */
@media (max-width:374.98px){
  .sm-prose:not(.sm-prose--ingested) .table{ font-size:var(--text-sm); }
  .sm-prose:not(.sm-prose--ingested) .table > :not(caption) > * > *{ padding-inline:var(--space-15); }
}

/* The comparison posts' marks — Font Awesome check / x / gear with aria-hidden and a
   .sm-visually-hidden word beside them. Colour carries the verdict for a scan (success 6.31:1,
   danger 5.80:1 on white; a glyph needs 3:1); the word carries it for a screen reader. */
.sm-mark{
  width:1.25em;
  text-align:center;
}
.sm-mark--yes{ color:var(--success-text); }
.sm-mark--no{ color:var(--danger-text); }
.sm-mark--pending{ color:var(--text-muted); }
/* A list item that opens with a mark shows the mark where its bullet was. The bullet goes
   transparent rather than list-style:none, so the list keeps its list semantics. */
@supports selector(:has(*)){
  :where(.sm-prose) li:has(> .sm-mark:first-child)::marker{ color:transparent; }
  :where(.sm-prose) li > .sm-mark:first-child{
    margin-inline-start:-1.5em;
    width:1.5em;
    text-align:start;
  }
  /* Forced colours repaint the transparent bullet in CanvasText, and it came back beside the
     mark ("X" plus a bullet fragment). There the marker is emptied instead; the <li> is still a
     list item. */
  @media (forced-colors: active){
    :where(.sm-prose) li:has(> .sm-mark:first-child)::marker{ content:""; }
  }
}

/* --- 12.6 Calculators (ProratedRentCalculator ×2, RentToIncomeRatio,
   HowTheBondMarketAffectsMortgageRates) -------------------------------------------
   The source order stays fields, result, button (the frozen id order). Grid areas show the
   button under the fields — before the result on phones, beside it from 576px, where the ink
   result panel (2A's .sm-ink-panel, a dark scope) spans both rows. Focus order is unchanged:
   the result panel holds nothing focusable. */
.sm-calculator{
  display:grid;
  grid-template-areas:"fields" "actions" "result";
  gap:var(--space-6);
  margin:var(--space-6) 0 0;
}
.sm-calculator__fields{
  grid-area:fields;
  min-width:0;
}
.sm-calculator__fields > :last-child{ margin-bottom:0; }
.sm-calculator__result{ grid-area:result; }
.sm-calculator__actions{ grid-area:actions; }
.sm-calculator__title{
  margin:0 0 var(--space-5);
  font-family:var(--font-display);
  font-size:var(--text-lg);
  font-weight:var(--weight-bold);
  line-height:var(--leading-tight);
  letter-spacing:var(--tracking-tight);
  color:var(--text-strong);
}
/* <p><strong>Label:</strong> <span id="…">value</span></p>: the label over its figure. */
.sm-calculator__row{
  display:flex;
  flex-direction:column;
  gap:var(--space-1);
  margin:0;
}
.sm-calculator__row + .sm-calculator__row{ margin-top:var(--space-5); }
.sm-calculator__row > strong{
  font-size:var(--text-sm);
  font-weight:var(--weight-semibold);
  line-height:var(--leading-snug);
  color:var(--text-secondary);
}
.sm-calculator__value{
  font-family:var(--font-display);
  font-size:var(--text-metric);
  font-weight:var(--weight-bold);
  line-height:var(--leading-tight);
  letter-spacing:var(--tracking-display);
  color:var(--text-strong);
  font-variant-numeric:var(--numeric-tabular);
  overflow-wrap:anywhere;
}
@media (min-width:576px){
  .sm-calculator{
    grid-template-columns:repeat(2, minmax(0, 1fr));
    grid-template-areas:"fields result" "actions result";
    align-items:start;
  }
}

/* --- 12.7 Ingested bodies (<article class="sm-prose sm-prose--ingested">) ------------
   body_html is rendered with Html.Raw and never edited: everything is CSS.
   Tables: a real table while it fits the column; wider, it scrolls inside its own box — at
   every width, because an ingested table can outgrow the desktop column too (the QA rent roll
   has twelve columns). Hand-written tables are authored to fit and keep display:table.
   (0,1,1) over Bootstrap's `.table` (0,1,0). */
.sm-prose--ingested table:not(:where(.sm-prose__table > table, .table-responsive > table)){
  display:block;
  max-width:100%;
  overflow-x:auto;
  -webkit-overflow-scrolling:touch;
}
/* A table that scrolls can take keyboard focus (Chromium and Firefox make scrollers
   focusable; proposal P-2B-A18 adds tabindex for Safari): the token ring. */
.sm-prose--ingested table:focus-visible{
  outline:var(--sm-focus-outline);
  border-radius:var(--radius-xs);
  box-shadow:var(--focus-ring);
}
/* A stray h1 in a body sits at the section heading size, under the page's own h1. */
.sm-prose--ingested h1{
  margin:1.8em 0 0.6em;
  font-family:var(--font-display);
  font-size:var(--text-2xl);
  font-weight:var(--weight-bold);
  line-height:var(--leading-tight);
  letter-spacing:var(--tracking-tight);
}
.sm-prose--ingested > h1:first-child{ margin-top:0; }
.sm-prose--ingested img{ border-radius:var(--radius-md); }
/* An embed of unknown ratio keeps its authored height, never more than the column's width
   (section 6), and gets a frame so a blank or loading embed still reads as a box. */
.sm-prose--ingested iframe{
  display:block;
  border:var(--border-hairline) solid var(--border);
  border-radius:var(--radius-md);
}

/* ============================================================================
   13. Stage 2C — legal documents and the property valuation tool
   Home/Privacy, Home/TermsOfUse and Home/SaasAgreement frame a Word export from
   /resources/legal/ that is frozen verbatim: only the frame around it is styled here, never
   the document. Home/PropertyValuationTool is a dark public island
   (<div class="sm-app sm-public-dark sm-valuation">) built from the same app.css components as
   Building/ViewBuildingAssumptions; only its page-level extras live here.
   Same contract as the sections above: tokens only, no @layer, no !important, no `display` on
   a .collapse or on anything jQuery shows, hides or toggles — the tool's #AnalysisSection,
   #InputSection, #AnalysisNoData, #AnalysisWithData, #AccountInitialMessage,
   #UnitInitialMessage, #CapExInitialMessage and every validation span.
   ========================================================================= */

/* --- 13.1 Legal document frame ----------------------------------------------
   The document keeps its own typography (Times New Roman 12pt, justified, and the bold capitals
   and underlines that carry legal emphasis), so it is presented as a sheet, never restyled.
   From 768px: a white sheet on the --alt band. On phones the sheet dissolves into the page and
   the document gets the whole column. The iframe's width is the reading measure; its height
   follows the document (js/design/legal-frame.js measures the same-origin document). */
.sm-legal{
  /* The document's own measure: the 6.5in text block of the US Letter page it was written for
     (8.5in less its 1in margins, 624px), plus the frame's 8px body margins either side. */
  --sm-legal-measure:40rem;
  --sm-legal-sheet-pad:0px;
}
@media (min-width:768px){
  .sm-legal{
    --sm-legal-sheet-pad:var(--space-8);
    background-color:var(--surface-raised);
  }
}
@media (min-width:1120px){
  .sm-legal{ --sm-legal-sheet-pad:var(--space-12); }
}
.sm-legal__layout{
  --sm-legal-sheet:calc(var(--sm-legal-measure) + 2 * var(--sm-legal-sheet-pad) + 2 * var(--border-hairline));
  display:grid;
  grid-template-columns:minmax(0, var(--sm-legal-sheet));
  justify-content:center;
  row-gap:var(--space-8);
}
.sm-legal__head,
.sm-legal__sheet{ min-width:0; }
.sm-legal__sheet{
  padding:var(--sm-legal-sheet-pad);
  background-color:var(--surface);
}
@media (min-width:768px){
  .sm-legal__sheet{
    border:var(--border-hairline) solid var(--border-subtle);
    border-radius:var(--radius-xl);
    box-shadow:var(--elev-dark-2);     /* resolves to the light --elev-2 under .sm-site */
  }
}
/* 100vh until the script has measured the document, so the footer never flashes up under a
   150px frame; the script then writes the measured height and min-height:0 inline. */
.sm-legal__frame{
  display:block;
  width:100%;
  min-height:100vh;
  border:0;
}

/* Contents: the document's own section titles, built by the script and shown only where a
   second column fits. The script removes `hidden` and adds .sm-legal__layout--toc once it has
   at least three entries, so a page whose script never ran keeps the one centred column.
   (Bootstrap's reboot keeps [hidden] at display:none !important until then.) */
@media (max-width:1199.98px){
  .sm-legal__toc{ display:none; }
}
@media (min-width:1200px){
  .sm-legal__layout--toc{
    grid-template-columns:minmax(0, 15rem) minmax(0, var(--sm-legal-sheet));
    grid-template-areas:". head" "toc sheet";
    column-gap:var(--space-12);
  }
  .sm-legal__layout--toc > .sm-legal__head{ grid-area:head; }
  .sm-legal__layout--toc > .sm-legal__toc{ grid-area:toc; }
  .sm-legal__layout--toc > .sm-legal__sheet{ grid-area:sheet; }
  /* Pinned under the sticky 64px header (11.1), scrolling on its own when the list is taller
     than the window (Terms of Use has 23 sections). */
  .sm-legal__toc{
    position:sticky;
    top:calc(var(--topbar-height) + var(--space-6));
    align-self:start;
    max-height:calc(100vh - var(--topbar-height) - var(--space-12));
    overflow-y:auto;
    overscroll-behavior:contain;
    scrollbar-width:thin;
    scrollbar-color:var(--border) transparent;
  }
}
.sm-legal__toc-list{
  display:grid;
  gap:var(--space-05);
  margin:0;
  padding:0;
  list-style:none;
}
/* (0,2,0): above section 3's link rules, like the footer's links. The ring is inset because the
   list is its own scroll container, which would clip an outset one; the outline offset is inset
   with it, or the forced-colours outline (app.css 0.2's 2px offset) was clipped at both sides. */
.sm-site .sm-legal__toc-link{
  display:block;
  padding:var(--space-15) var(--space-3);
  font-size:var(--text-sm);
  font-weight:var(--weight-medium);
  line-height:var(--leading-snug);
  text-decoration:none;
  color:var(--text-secondary);
  border-radius:var(--radius-sm);
  transition:
    color var(--sm-duration-fast) var(--ease-standard),
    background-color var(--sm-duration-fast) var(--ease-standard);
}
.sm-site .sm-legal__toc-link:hover{
  color:var(--text-strong);
  text-decoration:none;
  background-color:var(--surface-hover);
}
.sm-site .sm-legal__toc-link:focus-visible{
  outline:var(--sm-focus-outline);
  outline-offset:var(--sm-focus-offset-inset);
  box-shadow:var(--sm-focus-ring-inset);
}

/* Print. An iframe prints as one tall picture sliced at each page edge, which cuts lines of
   text in half (measured: Chrome 154). On `beforeprint` the script copies the document (its own
   <style> blocks and body, verbatim) into a shadow root on .sm-legal__print and marks the section
   .sm-legal--print; the copy paginates like any text, and the paper shows the document exactly as
   authored, its own title first. The page H1 stays off paper: the document's `page:WordSection1`
   forces a page break before it, which would strand the H1 alone on page one. `afterprint`
   empties the copy. A browser that never fires the event still prints the frame, as today. */
.sm-legal__print{ display:none; }
@media print{
  .sm-site:has(.sm-legal) > :is(header, footer){ display:none; }
  .sm-legal{
    padding-block:0;
    background:none;
  }
  .sm-legal__layout{ display:block; }
  .sm-legal__sheet{
    padding:0;
    border:0;
    box-shadow:none;
  }
  .sm-legal--print .sm-legal__head,
  .sm-legal--print .sm-legal__frame{ display:none; }
  .sm-legal--print .sm-legal__print{ display:block; }
}

/* --- 13.2 Property valuation tool --------------------------------------------
   The public copy of the app's Building > Assumptions screen, kept dark: a public-dark island
   inside the light site, exactly as the apply flow is (decision D3), and built from the same
   app.css components as Building/ViewBuildingAssumptions, so a prospect who signs up meets the
   same screen in the product. Section 2 hands the island (and <body>) the dark aliases. */

/* Phones: the site chrome's 16px gutter instead of .sm-page's 24px, so the tool's edges line up
   with the nav logo and the footer, and the year tables keep 16px more width. (0,3,0) over
   12.1's `.sm-app .sm-page` (0,2,0) in app.css. */
@media (max-width:767.98px){
  .sm-app.sm-valuation .sm-page{ padding-inline:var(--space-4); }
}
/* Small phones: 16px card padding (the apply flow's phone step), through the token, so every card
   part and the year tables' edge-to-edge bleed below move together. */
@media (max-width:575.98px){
  .sm-valuation{ --pad-card:var(--space-4); }
}

/* The demo banner: a 1600x300 artwork that carries its own text. Capped at 800px, rounded, and
   given the token ring. It replaces site.css's .horizontalAdBanner, whose hover zoom and 10px
   corner leave with that class. */
.sm-valuation__promo{
  display:block;
  max-width:50rem;
  overflow:hidden;
  border-radius:var(--radius-lg);
}
.sm-valuation__promo > img{
  display:block;
  width:100%;
  height:auto;
}
.sm-app .sm-valuation__promo:focus-visible{
  outline:var(--sm-focus-outline);
  box-shadow:var(--focus-ring);
}

/* Year tables: an account's, a unit's and the capital-expense cash flows, one row of inputs per
   analysis year (up to 13). Every input keeps a readable width ($1,000,000.00 fits at the 16px a
   touch screen gets) and the table scrolls sideways inside .sm-table-scroll instead of squeezing
   the figures to "$20,0". The table runs to the card's edges, so the scroller does too, and its
   outer cells line up with the fields above. DataTables Responsive is switched off on these three
   tables in the script: folding a column into a child row would clone its <input>, id and all. */
.sm-valuation__years{
  margin-inline:calc(var(--pad-card) * -1);
  margin-bottom:calc(var(--pad-card) * -1);
  border-top:var(--border-hairline) solid var(--border-subtle);
  /* The card's bottom corners: the scroller clips its rows to them. */
  border-end-start-radius:calc(var(--radius-lg) - var(--border-hairline));
  border-end-end-radius:calc(var(--radius-lg) - var(--border-hairline));
}
/* DataTables' Bootstrap 5 layout wraps each table in .row > .col-sm-12, whose 12px gutter would
   inset the table from the card edge; section 6 already removes the row's negative margins. */
.sm-valuation__years .dataTables_wrapper .row > [class*="col-"]{ padding-inline:0; }
.sm-valuation__years .sm-table.sm-table > * > tr > :is(th, td){ padding-inline:var(--space-2); }
.sm-valuation__years .sm-table.sm-table > * > tr > :is(th, td):first-child{ padding-inline-start:var(--pad-card); }
.sm-valuation__years .sm-table.sm-table > * > tr > :is(th, td):last-child{ padding-inline-end:var(--pad-card); }
.sm-valuation__years .sm-table.sm-table > tbody > tr > td{ padding-block:var(--space-2); }
.sm-valuation__years .sm-table.sm-table .sm-input{ min-width:9rem; }
/* On a phone the next year's input peeks past the card edge, which says "scroll" without a word. */
@media (max-width:575.98px){
  .sm-valuation__years .sm-table.sm-table .sm-input{ min-width:8rem; }
}
/* The capital-expense table sits in a card of its own with no fields above it. */
.sm-valuation__years--flush{
  margin:0;
  border-top:0;
  border-radius:calc(var(--radius-lg) - var(--border-hairline));
}

/* The discounted cash flow statement. The script rebuilds it from its own text through
   DataTables, which drops the bold section and total rows it was written with; its createdRow
   callback (smDcfRow) puts the two roles back as classes. Section rows ("Income", "Expenses",
   ...) read as caps sub-headers on the raised surface; the four totals are semibold under a rule.
   --surface is rebound rather than overridden, because section 6 paints every cell with an
   !important background of var(--surface). */
.sm-valuation .sm-table.sm-table > tbody > tr.sm-valuation__dcf-group{ --surface:var(--surface-raised); }
.sm-valuation .sm-table.sm-table > tbody > tr.sm-valuation__dcf-group > td{
  height:var(--control-height);
  font-size:var(--text-xs);
  font-weight:var(--weight-semibold);
  letter-spacing:var(--tracking-caps);
  text-transform:uppercase;
  color:var(--text-secondary);
}
.sm-valuation .sm-table.sm-table > tbody > tr.sm-valuation__dcf-total > td{
  font-weight:var(--weight-semibold);
  color:var(--text-strong);
  border-top:var(--border-hairline) solid var(--border);
}
/* A section row has no figures, so on a narrow screen DataTables Responsive's expand control there
   would reveal an empty list: the glyph goes and the cell stops answering the pointer. */
.sm-app .sm-valuation__dcf-group > td.dtr-control{ pointer-events:none; }
.sm-app table.sm-table.dataTable.dtr-inline.collapsed > tbody > tr.sm-valuation__dcf-group > .dtr-control::before{ content:none; }
/* The Category column from 1280px, where the page's 1200px cap holds the statement at 1150px. The
   widths DataTables measured left it narrow, so "DSCR (Excluding Sale)", "Operating Margin" and
   "Cash on Cash Return" broke over two or three lines beside half-empty year columns. A width on
   the first cells is the column's floor in the auto table layout. 10.5rem (168px) holds the
   longest label the tool writes (155px at 15px), and a longer account or unit name (up to 45
   characters) still wraps, rather than widening the table until Responsive folds a year away.
   DataTables' cells are content-box, so the 16px padding sits outside it. The selector names no
   id, so the hidden copies DataTables and Responsive measure (the statement is the tool's only
   .sm-table-wrap table) size the same way. */
@media (min-width:1280px){
  .sm-valuation .sm-table-wrap .sm-table.sm-table > tbody > tr > td:first-child{ width:10.5rem; }
}

/* DataTables Buttons' "Copy to clipboard" confirmation (buttons.info()) is appended to <body>,
   outside the island, so app.css's `.sm-app div.dt-button-info` skin never reaches it here. This
   <body> holds the dark aliases (section 2) and the Buttons stylesheet paints the box white, so
   the message printed near-white on white (1.01-1.10:1). The same skin, from <body>'s own
   aliases: dark here (--ink-50 on --ink-800 15.24:1, the title 16.72:1), light on a page without
   an island (16.72:1 and 19.61:1). (0,2,1)/(0,2,2) over Buttons' (0,1,1)/(0,1,2), which load
   later, from the end of <body>. No `display`: the script fades it in and out. Buttons also
   fixes the box at 400px with margin-left:-200px, past both edges of a phone, so it is capped
   at the page gutter and centred by transform. (The collection popover and its background
   layer never render on a public page: no collection button, and the layer is inserted after
   <body> and left unpainted by the bs5 build.) */
.sm-site div.dt-button-info{
  max-width:calc(100vw - 2 * var(--space-4));
  margin:0;
  transform:translate(-50%, -50%);
  color:var(--text);
  background-color:var(--surface-overlay);
  border:var(--border-hairline) solid var(--border);
  border-radius:var(--radius-lg);
  box-shadow:var(--elev-dark-3);
}
.sm-site div.dt-button-info h2{
  font-size:var(--text-md);
  font-weight:var(--weight-semibold);
  color:var(--text-strong);
  background-color:transparent;
  border-bottom-color:var(--border-subtle);
}

/* Money tiles print up to 14 characters ("$12,345,678.91"): 228px of Archivo 700 at the 32px
   --text-metric step (measured), while a four-up tile is 198-222px inside. The value therefore
   scales with its own tile, never with the window: the auto-fit grid, not the viewport, decides
   how wide a tile is (DESIGN-SYSTEM-BRIEF, Stage 5). 14% of the tile's width fits 14 characters;
   it never grows past the 32px step. A browser without container units keeps the 32px step. */
.sm-valuation .sm-metric{ container-type:inline-size; }
.sm-valuation .sm-metric__value{ font-size:min(var(--text-metric), 14cqi); }

/* ============================================================================
   14. Pass 2 (8 Oct 2026) — footer link columns, section-title step
   ========================================================================= */

/* --- 14.1 Footer link columns ----------------------------------------------------
   _Layout's and _ValuationToolLayout's <nav class="sm-site-footer__grid"> (9.2's parts, unused until
   pass 2), between the brand row and the closing row: the seven product pages, the blog, the valuation
   tool and the QuickBooks guide on every public page. Its column labels are
   <p class="sm-site-footer__heading">, not headings, because the footer also renders on the 36
   hand-written posts, whose heading list is frozen. Never toggled by script. */
.sm-site-footer__grid{
  margin-top:var(--space-10);
  padding-top:var(--space-8);
  border-top:var(--border-hairline) solid var(--border-subtle);
}

/* --- 14.2 Section-title step ------------------------------------------------------
   The H1 is 64px and every centred section title 32px: one 2x jump, then 18px card titles. From
   --bp-lg (1120px) the centred section titles take a 40px step (display-3 x 1.25, no new token) and the
   header a wider measure, so the longest current title ("Simple Software, With Everything You Need for
   Building Management") stays at two lines (landing-modern survey, measured at 1280 and 1440, 11
   headers). Left-aligned prose titles (product-page bodies, the legal .sm-legal__head H1s) are untouched.
   The 28px phone step (11.2) is unchanged. */
@media (min-width:1120px){
  .sm-section__header--center{ max-width:56rem; }
  .sm-section__header--center > .sm-display-3{ font-size:calc(var(--text-display-3) * 1.25); }
}

/* ============================================================================
   15. Pass 2, Tier B (8 Oct 2026) — Home's hero proof row, the one-plan pricing card, the public
   breadcrumb
   Henry's 8 Oct landing-page decisions. Same contract as sections 1-14: tokens only, no @layer, no
   !important, no `display` on a .collapse or on anything a script shows or hides. The other Tier B
   blocks reuse existing parts: How it works and the condensed About are .sm-feature-card rows (7.1),
   the product pages' related guides are .sm-post-card (11.10) and their closing band .sm-cta-band
   (7.3); the footer's Company and Legal columns are 9.2/14.1 columns, and since the legal links moved
   out of the closing row, 9.2's .sm-site-footer__legal is unused.
   ========================================================================= */

/* --- 15.1 Hero proof row ---------------------------------------------------------------
   Three facts under Home's hero calls to action, in the sign-in page's words (_AuthLayout
   .sm-auth__checks). On the ink hero --text is the light body colour and the tick takes
   --brand-text. One line each on desktop, wrapping centred on phones. Never toggled. */
.sm-hero__proof{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:var(--space-2) var(--space-6);
  margin:var(--space-8) 0 0;
  padding:0;
  list-style:none;
  font-size:var(--text-sm);
  font-weight:var(--weight-medium);
  line-height:var(--leading-snug);
  color:var(--text);
}
.sm-hero__proof > li{
  display:inline-flex;
  align-items:center;
  gap:var(--space-2);
}
.sm-hero__proof .fa-solid{ color:var(--brand-text); }

/* --- 15.2 Pricing: one plan with both per-unit rates, beside the calculator ----------------
   Home's #PaymentSection: the .sm-price-card--featured plan (7.2) and the calculator. One column
   below Bootstrap's lg; from 992px the card takes 5/12 and the calculator 7/12. The two rates sit
   side by side between hairlines. */
.sm-pricing{
  display:grid;
  gap:var(--space-8);
  align-items:start;
}
.sm-pricing__calc{ min-width:0; }
.sm-price-card__rates{
  display:grid;
  grid-template-columns:repeat(2, minmax(0, 1fr));
  margin:0;
  padding-block:var(--space-4);
  border-block:var(--border-hairline) solid var(--border-subtle);
}
.sm-price-card__rates > *{ min-width:0; }
.sm-price-card__rates > * + *{
  padding-inline-start:var(--space-5);
  border-inline-start:var(--border-hairline) solid var(--border-subtle);
}
.sm-price-card__rates > :first-child{ padding-inline-end:var(--space-5); }
.sm-price-card__rates .sm-price-card__name{
  font-size:var(--text-md);
  color:var(--text-secondary);
}
.sm-price-card__rates .sm-price-card__price{ margin-top:var(--space-2); }
@media (min-width:992px){
  .sm-pricing{ grid-template-columns:minmax(0, 5fr) minmax(0, 7fr); }
}

/* --- 15.3 Breadcrumb on public pages ----------------------------------------------------
   app.css 8.5 paints .sm-breadcrumb only inside .sm-app; this is the light shell's copy, above the
   seven product pages' H1s (Home / Solutions / the page). Island content keeps app.css's rule. */
:where(.sm-site) .sm-breadcrumb:not(:where(.sm-app *, .sm-public-dark *)){
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--space-2);
  margin:0 0 var(--space-6);
  padding:0;
  list-style:none;
  font-size:var(--text-sm);
  line-height:var(--leading-tight);
  color:var(--text-muted);
}
:where(.sm-site) .sm-breadcrumb__item:not(:where(.sm-app *, .sm-public-dark *)){
  display:inline-flex;
  align-items:center;
  gap:var(--space-2);
}
:where(.sm-site) .sm-breadcrumb__item:not(:where(.sm-app *, .sm-public-dark *)) + .sm-breadcrumb__item::before{
  content:"/";
  color:var(--text-muted);
}
.sm-site .sm-breadcrumb__link:not(:where(.sm-app *, .sm-public-dark *)){
  color:var(--text-link);
  text-decoration:underline;
  text-decoration-thickness:1px;
  text-underline-offset:0.2em;
}
.sm-site .sm-breadcrumb__current:not(:where(.sm-app *, .sm-public-dark *)){
  color:var(--text);
  font-weight:var(--weight-medium);
}

/* ============================================================================
   16. Button roles on the public site (9 Oct 2026)
   Henry approved extending app.css 1.1's button roles to the public pages ("fix low-contrast
   buttons on the public pages too", the 8 Oct landing design otherwise unchanged). Measured
   before this section: every outline/secondary button on white or --page-alt was 1.48-1.54:1 (its
   --ink-200 hairline), the soft buttons 1.22:1, and on the ink nav, hero and call-to-action bands
   the secondary was 1.46:1 and the #6D30A7 primary 2.46:1. Every label already passed. WCAG 1.4.11
   asks 3:1 for a control's boundary.

   THE APP'S ROLES, painted for the surface they sit on (outside the islands, no public page has a
   danger, success or selected button):
     filled purple   .sm-btn--primary     the main call to action: Book a Demo, Get Started,
                                          Sign up, Subscribe, Try it Now. Fill and label untouched.
     tonal purple    .sm-btn--secondary   every other action: the second call to action, Read the
                     .sm-btn--soft        Setup Guide, View All Posts, the role explorer, social
                                          links. Soft paints the same, as in the app.
     neutral outline (no class on the     the tools: the nav toggler, the hero's pause/play, the
                     public site)         screenshot arrows (9.1, 11.3, 11.4 read --sm-field-border)
     ghost           .sm-btn--ghost       chrome only, unchanged: Log in / Log out.
   On light surfaces (white, --page-alt, --page-tint):
     primary  unchanged: its border stays transparent, so the fill is the edge, 7.98 / 7.66 / 7.19
     tonal    --purple-500 rim 5.51 / 5.29 / 4.96, label --purple-700 on the 8% wash 8.92 / 8.57 /
              8.06; hover --brand rim 7.98 / 7.66 / 7.19, --purple-800 on the 12% wash 10.73 /
              10.32 / 9.72
   On the ink bands (nav, call-to-action bands, footer; --page-ink), the app's 0.5 paint:
     primary  --purple-400 rim 5.43 (hover --purple-300 8.28), white on the fill 7.98 (hover 5.51)
     tonal    --purple-400 rim 5.43, --purple-300 on the 18% wash 7.56; hover --purple-300 rim
              8.28, --purple-100 on the 40% wash 11.93
   (The call-to-action band's brand glow lifts the ink behind its buttons at 1280: the
   --purple-400 rims measure 4.87:1 there at the worst pixel.)
   The light and dark values are aliases (sections 1 and 2), so one pair of rules serves both, and
   <body> on an island page, which holds the dark aliases, needs nothing extra.

   THE HERO (16.2). Its buttons sit on moving video under the 11.3 scrim. Sampled round both
   buttons at 1280 and 375, the brightest video pixel is #4a4642 (L 0.062), against which
   --purple-400 falls to 2.59:1. The hero takes the next step instead, --purple-300, which is
   3.6:1 or more against every pixel sampled (three samplings, 13 and 16 frames each: primary
   4.03, tonal 3.63 at the worst, over the 720p video at 375), and --purple-200 on hover (5.73:1
   against that pixel). Its tonal fill is
   opaque, --purple-950 (hover --purple-900), so the label never depends on the frame behind it:
   --purple-300 7.94:1, hover --purple-100 12.95:1. The 8 Oct secondary was opaque there too.

   SCOPE AND WEIGHT. Islands (.sm-app, .sm-public-dark) are left to app.css 1.1, which already
   paints them, by the zero-weight `:not(:where(.sm-app *, .sm-public-dark *))`. Rest rules are
   (0,2,0) and hover rules (0,3,0), one class over app.css section 1's (0,1,0) and (0,2,0); no
   box-shadow is declared, so `.sm-btn:focus-visible` keeps the token ring (light: --page gap and
   --purple-600; dark scopes: --surface-canvas gap and --purple-300). Every :hover restates `color`,
   which defeats Bootstrap's a:hover on an <a class="sm-btn">. Paint only: no `display`, no markup,
   and no box changes size except Calendly's badge, which 16.4 widens by 2px. Every edge is the
   real 1px border .sm-btn already has, so forced colours still draw it.
   ========================================================================= */

/* --- 16.1 Primary and tonal ------------------------------------------------ */
.sm-site .sm-btn--primary:not(:where(.sm-app *, .sm-public-dark *)){
  border-color:var(--sm-site-btn-primary-rim);
}
.sm-site .sm-btn--primary:not(:where(.sm-app *, .sm-public-dark *)):hover:not(:where([disabled],[aria-disabled="true"],.sm-is-disabled)){
  color:var(--brand-on);
  border-color:var(--sm-site-btn-primary-rim-hover);
}
.sm-site :is(.sm-btn--secondary, .sm-btn--soft):not(:where(.sm-app *, .sm-public-dark *)){
  background-color:var(--sm-site-btn-tonal-fill);
  color:var(--brand-text);
  border-color:var(--sm-site-btn-tonal-rim);
}
.sm-site :is(.sm-btn--secondary, .sm-btn--soft):not(:where(.sm-app *, .sm-public-dark *)):hover:not(:where([disabled],[aria-disabled="true"],.sm-is-disabled)){
  color:var(--sm-site-btn-tonal-on-hover);
  background-color:var(--sm-site-btn-tonal-fill-hover);
  border-color:var(--sm-site-btn-tonal-rim-hover);
}

/* --- 16.2 The hero: buttons over video (see the header) ---------------------- */
:where(.sm-site) .sm-hero{
  --sm-site-btn-primary-rim:var(--sm-btn-rim-brand-hover);
  --sm-site-btn-primary-rim-hover:var(--purple-200);
  --sm-site-btn-tonal-fill:var(--purple-950);
  --sm-site-btn-tonal-fill-hover:var(--purple-900);
  --sm-site-btn-tonal-rim:var(--sm-btn-rim-brand-hover);
  --sm-site-btn-tonal-rim-hover:var(--purple-200);
}

/* --- 16.3 Home's QuickBooks compare handle ----------------------------------------
   site.css draws the knob as a #6D30A7 disc with no edge, so against the dark Simpli screenshot on
   its right it was 2.42:1 (35-56% of the pixels round it met 3:1). A 2px --brand-on ring, the
   colour of its glyph and of the white handle line it sits on, parts it from dark pixels while the
   fill parts it from light ones: 99% or more of the pixels round it now meet 3:1, and in forced
   colours the ring is what keeps the knob visible. The box stays 38px (border-box). (0,2,0) over
   site.css's (0,1,0). */
.sm-site .image-compare-handle-knob{
  border:calc(var(--border-hairline) * 2) solid var(--brand-on);
}

/* --- 16.4 Calendly's floating "Book a Demo" badge -------------------------------
   Fixed to the corner (from 768px, 11.1), so it passes over white sections, the ink bands and, on
   a short window, the hero. Its #6D30A7 fill (widget.js writes it inline) carries 7.98:1 on white
   but 2.46:1 on ink; a --sm-btn-rim-brand-hover (--purple-300) rim carries 8.28:1 there, and 3.95:1
   against the brightest video pixel sampled round the hero's own buttons. On white the rim is only
   2.37:1, but there the fill carries the edge. Forced colours turn the fill into Canvas and drop
   the shadow, so there the border is the badge's only edge (before, only its label showed).
   widget.js writes no border, so none of this needs !important; the badge grows 2px wider and
   stays 45px tall. */
.sm-site .calendly-badge-content{
  border:var(--border-hairline) solid var(--sm-btn-rim-brand-hover);
}
