/* =============================================================================
   Alabama Signature Homes — main stylesheet
   =============================================================================

   Vanilla CSS, no build step, no preprocessor, no nesting. Flat selectors
   throughout: native CSS nesting needs Safari 17.2+/Chrome 120+ and parses
   differently in older Chromium, and there is no autoprefixer to normalise it.

   Layer order is declared once below, so a rule's weight comes from its layer,
   not from where it happens to sit in the file. `utilities` is last because a
   utility that a later layer can beat is not a utility.

   Media queries live inside whichever layer owns the rule. One breakpoint,
   768px, mobile-first — matching the Astro build this replaces. `--bp-md`
   exists as a token so main.js can read the same number via getComputedStyle;
   CSS itself cannot use a custom property inside @media, so 768px is written
   literally in every query.

   This file holds the shared vocabulary only — reset, base, layout, components
   and utilities. Page-specific rules live in their own stylesheets; see the
   PAGES note further down for the convention. This file is always linked first,
   which is what lets the @layer statement below fix the order those files sort
   into.

   Two state class names are grandfathered in from the old build: `.loaded` on
   `.img-loader` and `.active` on nav links. Everything else expresses runtime
   state as `.is-*`, and `data-*` attributes are JS query hooks that CSS never
   selects.
   ========================================================================== */

@layer reset, base, layout, components, pages, utilities;

/* =============================================================================
   RESET
   Several of these reproduce Tailwind Preflight behaviour the old markup
   silently relied on — zero-width borders, unstyled lists, transparent
   buttons, borderless <hr>. Removing any of them changes the design.
   ========================================================================== */

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

  * {
    margin: 0;
    padding: 0;
    /* Preflight parity: `border-b-4 border-primary-400` assumed a 0-width base. */
    border: 0 solid;
  }

  html {
    scroll-behavior: smooth;
    -webkit-text-size-adjust: 100%;
  }

  img,
  svg,
  video,
  iframe,
  picture {
    display: block;
    max-width: 100%;
  }

  img,
  video {
    height: auto;
  }

  ul,
  ol {
    list-style: none;
  }

  a {
    color: inherit;
    text-decoration: none;
  }

  button {
    background: none;
    cursor: pointer;
    text-align: inherit;
    color: inherit;
  }

  input,
  button,
  textarea,
  select {
    font: inherit;
    color: inherit;
  }

  textarea {
    resize: vertical;
  }

  hr {
    border: 0;
  }

  /* The popup JS sets `el.hidden = true`, and the popups set display themselves. */
  [hidden] {
    display: none !important;
  }

  /* #contact deep links used to land underneath the sticky header. */
  :target {
    scroll-margin-block-start: 5rem;
  }

  @media (prefers-reduced-motion: reduce) {
    html {
      scroll-behavior: auto;
    }

    *,
    *::before,
    *::after {
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.01ms !important;
    }
  }
}

/* =============================================================================
   BASE — tokens, element defaults, typography
   ========================================================================== */

@layer base {
  /* ---------------------------------------------------------------------------
     Self-hosted fonts. Both families are SIL OFL 1.1 (see OFL-Lato.txt and
     OFL-Oswald.txt beside the woff2 files). Latin subset only: the copy is
     English, and latin covers the em-dashes and curly quotes it uses.

     Previously loaded from fonts.googleapis.com, which cost two extra
     connections, a render-blocking third-party stylesheet, and sent every
     visitor's IP to Google.
     ------------------------------------------------------------------------ */

  @font-face {
    font-family: "Lato";
    font-style: italic;
    font-weight: 100;
    font-display: swap;
    src: url("../fonts/lato-100-italic.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  @font-face {
    font-family: "Lato";
    font-style: italic;
    font-weight: 300;
    font-display: swap;
    src: url("../fonts/lato-300-italic.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  @font-face {
    font-family: "Lato";
    font-style: italic;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/lato-400-italic.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  @font-face {
    font-family: "Lato";
    font-style: italic;
    font-weight: 700;
    font-display: swap;
    src: url("../fonts/lato-700-italic.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  @font-face {
    font-family: "Lato";
    font-style: italic;
    font-weight: 900;
    font-display: swap;
    src: url("../fonts/lato-900-italic.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  @font-face {
    font-family: "Lato";
    font-style: normal;
    font-weight: 100;
    font-display: swap;
    src: url("../fonts/lato-100.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  @font-face {
    font-family: "Lato";
    font-style: normal;
    font-weight: 300;
    font-display: swap;
    src: url("../fonts/lato-300.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  @font-face {
    font-family: "Lato";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/lato-400.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  @font-face {
    font-family: "Lato";
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("../fonts/lato-700.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  @font-face {
    font-family: "Lato";
    font-style: normal;
    font-weight: 900;
    font-display: swap;
    src: url("../fonts/lato-900.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  @font-face {
    font-family: "Oswald";
    font-style: normal;
    font-weight: 200;
    font-display: swap;
    src: url("../fonts/oswald-200.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  @font-face {
    font-family: "Oswald";
    font-style: normal;
    font-weight: 300;
    font-display: swap;
    src: url("../fonts/oswald-300.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  @font-face {
    font-family: "Oswald";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/oswald-400.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  @font-face {
    font-family: "Oswald";
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url("../fonts/oswald-500.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  @font-face {
    font-family: "Oswald";
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url("../fonts/oswald-600.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  @font-face {
    font-family: "Oswald";
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url("../fonts/oswald-700.woff2") format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  body {
    /* brand */
    --clr-primary-400: hsl(359 67% 32%);
    --clr-primary-200: hsl(359 67% 42%);
    --primary-clr: var(--clr-primary-400); /* legacy alias: shape gradients */

    /* neutrals — only the steps the old markup actually used */
    --clr-neutral-100: #f5f5f5;
    --clr-neutral-200: #e5e5e5;
    --clr-neutral-300: #d4d4d4;
    --clr-neutral-400: #a3a3a3;
    --clr-neutral-600: #525252;
    --clr-neutral-700: #404040;
    --clr-neutral-800: #262626;
    --clr-neutral-900: rgb(23 23 23);
    --neutral-900: var(--clr-neutral-900); /* legacy alias: .triangle gradient */
    --clr-neutral-950: #0a0a0a;
    --clr-white: #fff;
    --clr-black: #000;

    /* surfaces */
    --clr-surface: var(--clr-neutral-900);
    --clr-surface-band: var(--clr-neutral-800);
    --clr-surface-strip: var(--clr-neutral-700);
    --clr-surface-glass: hsl(0 0% 0% / 0.9);
    --clr-surface-card: rgb(10 10 10 / 0.5);
    --clr-surface-light: var(--clr-white);
    --clr-surface-feedback: #dfdad9;

    /* text */
    --clr-text: var(--clr-white);
    --clr-text-muted: var(--clr-neutral-300);
    --clr-text-faint: var(--clr-neutral-400);
    --clr-text-dim: var(--clr-neutral-600);
    --clr-text-invert: var(--clr-black);

    /* accents */
    --clr-star: #eab308;
    --clr-facebook: #2563eb;
    --clr-alert: #7f1d1d;
    --clr-alert-link: #ef4444;
    --clr-hover-mute: #94a3b8;

    /* type */
    --ff-heading: "Oswald", system-ui, sans-serif;
    --ff-body: "Lato", system-ui, sans-serif;

    --fs-2xs: 0.7rem;
    --fs-xs: 0.75rem;
    --fs-sm: 0.875rem;
    --fs-base: 1rem;
    --fs-lg: 1.125rem;
    --fs-xl: 1.25rem;
    --fs-2xl: 1.5rem;
    --fs-3xl: 1.875rem;
    --fs-4xl: 2.25rem;
    --fs-5xl: 3rem;
    --fs-9xl: 8rem;

    --fs-fluid-hero: clamp(1rem, 10vw, 4.5rem);
    --fs-fluid-lg: clamp(1.25rem, 6vw, 2.5rem);
    --fs-fluid-md: clamp(1rem, 4vw, 1.75rem);
    --fs-fluid-label: clamp(1rem, 4vw, 1.5rem);

    --lh-tight: 1;
    --lh-snug: 1.25;
    --lh-body: 1.5;

    --fw-light: 300;
    --fw-regular: 400;
    --fw-semibold: 600;
    --fw-bold: 700;
    --fw-black: 900;

    /* space */
    --space-3xs: 0.25rem;
    --space-2xs: 0.5rem;
    --space-xs: 1rem;
    --space-sm: 1.5rem;
    --space-md: 2rem;
    --space-lg: 3rem;
    --space-xl: 4rem;
    --space-2xl: 6rem;
    --space-3xl: 8rem;

    --section-pad: var(--space-xl);
    --section-pad-lg: var(--space-3xl);

    /* sizes */
    --size-container: 1200px;
    --size-gutter: 2rem;
    --size-rule: 4px;
    --size-logo-header: 4rem;
    --size-logo-footer: 10rem;
    --size-sidebar: 300px;

    --measure-2xs: 25ch;
    --measure-sm: 45ch;
    --measure-md: 55ch;
    --measure-lg: 100ch;
    --measure-lead: 600px;

    --radius-sm: 0.125rem;
    --radius-md: 6px;
    --radius-lg: 0.5rem;
    --radius-full: 9999px;

    --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
    --shadow-inner: inset 0 2px 4px 0 rgb(0 0 0 / 0.05);
    --shadow-tile: 0.25em 0.25em 0 hsl(0 0% 0% / 0.25);
    --shadow-float: 5px 5px 2px var(--clr-white);

    --z-behind: -1;
    --z-above: 3;
    --z-header: 100;
    --z-popup: 200;

    --dur-fast: 200ms;
    --dur-slow: 500ms;
    --dur-popup: 1000ms;
    --delay-popup: 3000ms;

    /* Read by main.js; CSS @media cannot use a custom property. */
    --bp-md: 768px;

    background-color: var(--clr-surface);
    color: var(--clr-text);
    font-family: var(--ff-body);
    font-size: var(--fs-base);
    line-height: var(--lh-body);
    min-height: 100dvh;
  }

  :where(h1, h2, h3, h4, h5, h6) {
    font-family: var(--ff-heading);
    font-weight: var(--fw-regular);
    line-height: var(--lh-snug);
    text-wrap: balance;
  }

  /* Real heading sizes, unlike Preflight's font-size:inherit. Components that
     relied on the old 1rem default compensate explicitly — see `.prose h3`. */
  :where(h1) { font-size: var(--fs-5xl); line-height: var(--lh-tight); }
  :where(h2) { font-size: var(--fs-3xl); }
  :where(h3) { font-size: var(--fs-2xl); }
  :where(h4) { font-size: var(--fs-xl); }
  :where(h5), :where(h6) { font-size: var(--fs-base); }

  :where(p, a, span, li, label) {
    font-family: var(--ff-body);
  }

  :where(p) {
    text-wrap: pretty;
  }

  :where(a:not([class*="button"])):hover,
  :where(a:not([class*="button"])):focus-visible {
    color: var(--clr-primary-200);
  }

  :focus-visible {
    outline: 2px solid var(--clr-primary-200);
    outline-offset: 2px;
  }

  :where(strong, b) {
    font-weight: var(--fw-bold);
  }

  :where(input, textarea, select) {
    background-color: var(--clr-surface-light);
    color: var(--clr-text-invert);
  }

  ::selection {
    background-color: var(--clr-primary-400);
    color: var(--clr-white);
  }
}

/* =============================================================================
   LAYOUT — page skeleton, header, nav, footer, sidebar
   ========================================================================== */

@layer layout {
  /* ----- containers ----- */

  .wrapper {
    --max-width: var(--size-container);
    --padding: var(--size-gutter);

    width: min(var(--max-width), 100% - (var(--padding) * 2));
    margin-inline: auto;
  }

  .page-main {
    isolation: isolate;
  }

  /* ----- header ----- */

  .page-header {
    position: relative;
    z-index: var(--z-header);
    box-shadow: var(--shadow-md);
    background-color: var(--clr-surface-glass);
    background-image: url("../images/black-texture-1200x106.webp");
    background-size: cover;
    background-position: center center;
    background-blend-mode: overlay;
  }

  .page-header__inner {
    max-width: var(--size-container);
    margin-inline: auto;
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: stretch;
  }

  .page-header__logo {
    padding: var(--space-xs) var(--space-md);
  }

  .page-header__logo:hover {
    filter: brightness(1.25);
  }

  .page-header__logo img {
    max-width: var(--size-logo-header);
    width: 100%;
    height: 74px;
    object-fit: contain;
  }

  @media (min-width: 768px) {
    .page-header__inner {
      grid-template-columns: auto 1fr auto;
    }
  }

  /* ----- nav toggle -----
     Only rendered as a control when JS can drive it. */

  .nav-toggle {
    display: none;
    background-color: var(--clr-primary-400);
    color: var(--clr-white);
    font-size: var(--fs-4xl);
    padding-inline: var(--space-xs);
  }

  .js .nav-toggle {
    display: grid;
    place-items: center;
  }

  @media (min-width: 768px) {
    .nav-toggle,
    .js .nav-toggle {
      display: none;
    }
  }

  .nav-toggle .icon {
    width: 1em;
    height: 1em;
  }

  /* ----- primary nav -----
     Mobile-first and visible by default so the site stays navigable without
     JS. `.js` hides it; `.is-open` brings it back as an overlay panel.

     Every desktop rule re-lists the stateful selectors: `.is-open` is (0,2,0)
     and a media query adds nothing to specificity, so a bare `.primary-nav`
     inside the query would lose to it and leave the panel absolutely
     positioned on desktop. */

  .primary-nav {
    width: 100%;
  }

  .primary-nav__list {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--space-xs);
    padding: var(--space-md);
    text-align: center;
    text-transform: uppercase;
    filter: drop-shadow(0 1px 1px rgb(0 0 0 / 0.1));
  }

  @media screen and (width < 768px) {
    .js .primary-nav {
      display: none;
    }

    .js .primary-nav.is-open {
      display: block;
      position: absolute;
      inset-inline: 0;
      top: 100%;
      background-color: var(--clr-surface-light);
      color: var(--clr-text-invert);
    }
  }

  @media (min-width: 768px) {
    .primary-nav,
    .js .primary-nav,
    .js .primary-nav.is-open {
      display: block;
      position: static;
      background: none;
      color: var(--clr-text);
    }

    .primary-nav__list {
      /* Full height so align-items:center centres the links against the logo
         and the phone ribbon, rather than leaving them at the top of the
         stretched grid row. This is the old build's h-full. */
      height: 100%;
      flex-direction: row;
      flex-wrap: wrap;
      column-gap: var(--space-xs);
      row-gap: 0;
      padding: 0;
    }
  }

  .nav-item {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
  }

  .nav-item__label {
    position: relative;
    display: block;
    isolation: isolate;
    width: min-content;
  }

  .nav-item__link {
    display: block;
    font-family: var(--ff-heading);
    font-size: var(--fs-2xl);
    border-block-end: var(--size-rule) solid transparent;
    white-space: nowrap;
  }

  .nav-item__link:hover {
    border-block-end-color: var(--clr-primary-400);
  }

  .nav-item__toggle {
    position: absolute;
    top: 0;
    left: calc(100% + 4px);
    width: min-content;
    z-index: 10;
    font-size: var(--fs-2xl);
    outline: 1px solid transparent;
  }

  .nav-item__toggle:hover {
    color: var(--clr-primary-400);
    outline-color: var(--clr-primary-400);
  }

  @media (min-width: 768px) {
    .nav-item {
      align-items: flex-start;
    }

    .nav-item__link {
      font-size: var(--fs-base);
      padding-block: 2px;
    }

    .nav-item__toggle {
      display: none;
    }
  }

  /* ----- submenu -----
     Desktop opens on hover AND focus-within: the old build used Tailwind's
     group-hover, which no keyboard could reach. */

  .nav-submenu {
    display: none;
    min-width: max-content;
    border: 2px solid hsl(0 0% 0% / 0.25);
    padding: var(--space-2xs);
    margin-block-start: var(--space-xs);
  }

  html:not(.js) .nav-submenu {
    display: block;
  }

  .js .nav-item.is-open > .nav-submenu {
    display: block;
  }

  .nav-submenu__item {
    margin-block-end: var(--space-xs);
  }

  .nav-submenu__link {
    font-family: var(--ff-heading);
    font-size: var(--fs-2xl);
  }

  @media (min-width: 768px) {
    .nav-item:hover > .nav-submenu,
    .nav-item:focus-within > .nav-submenu,
    .nav-item.is-open > .nav-submenu {
      display: block;
    }

    .nav-submenu {
      position: absolute;
      top: 100%;
      left: 0;
      text-align: left;
      border: 0;
      padding: 0;
      /* Must be zero: a gap here and the pointer leaves .nav-item on the way
         to the menu, which snaps it shut. */
      margin: 0;
    }

    .nav-submenu__item {
      margin: 0;
      background-color: var(--clr-surface-light);
      color: var(--clr-text-invert);
    }

    .nav-submenu__item:hover {
      background-color: var(--clr-neutral-200);
    }

    .nav-submenu__link {
      display: block;
      padding: var(--space-2xs) var(--space-xs);
      font-size: var(--fs-base);
    }
  }

  /* ----- header phone CTA ----- */

  .header-cta {
    display: none;
  }

  @media (min-width: 768px) {
    .header-cta {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      background-color: var(--clr-primary-400);
      color: var(--clr-white);
      text-transform: uppercase;
      text-align: center;
      isolation: isolate;
    }

    .header-cta:hover {
      color: var(--clr-white);
      filter: brightness(1.1);
    }
  }

  .header-cta__label {
    font-family: var(--ff-heading);
  }

  .header-cta__number {
    display: flex;
    align-items: center;
    gap: var(--space-2xs);
    font-family: var(--ff-heading);
    font-size: var(--fs-2xl);
  }

  /* The number sits in a nested span, and :where(span) in `base` applies Lato
     to it directly — so there is nothing to inherit. Name it explicitly, the
     way the old build did with an extra font-oswald class. */
  .header-cta__number span {
    font-family: var(--ff-heading);
  }

  .header-cta__number .icon {
    width: 1em;
    height: 1em;
  }

  /* ----- footer ----- */

  .page-footer {
    background-color: var(--clr-surface);
  }

  .footer-columns {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2xl);
    justify-content: center;
    font-family: var(--ff-heading);
    padding-block: var(--space-lg);
  }

  .footer-logo {
    max-width: var(--size-logo-footer);
    width: 100%;
    height: auto;
    object-fit: contain;
  }

  .footer-column {
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    gap: var(--space-2xs);
  }

  .footer-column--address {
    font-style: normal;
  }

  .footer-column__title {
    font-family: var(--ff-heading);
    font-size: var(--fs-xl);
    font-weight: var(--fw-semibold);
    color: var(--clr-primary-200);
    margin-block-end: var(--space-2xs);
  }

  .footer-column__list {
    display: flex;
    flex-direction: column;
    gap: var(--space-2xs);
  }

  .footer-column a,
  .footer-column__list a {
    font-family: var(--ff-heading);
  }

  .footer-social {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2xs);
  }

  .social-badge {
    border-radius: var(--radius-full);
    background-color: var(--clr-facebook);
    aspect-ratio: 1;
    width: 30px;
    display: grid;
    place-items: center;
  }

  .social-badge:hover {
    filter: brightness(1.25);
  }

  .social-badge .icon {
    width: 18px;
    height: 18px;
    fill: var(--clr-white);
  }

  .footer-divider {
    height: 2px;
    background-color: var(--clr-primary-200);
  }

  .footer-copyright {
    text-align: center;
    padding: var(--space-xs);
  }

  .footer-credit {
    display: block;
    font-size: var(--fs-xs);
    color: var(--clr-text-dim);
  }

  /* ----- sidebar layout ----- */

  .show-sidebar {
    display: grid;
    grid-template-areas:
      "header header"
      "content aside";
    grid-template-columns: 1fr minmax(0, var(--size-sidebar));
    column-gap: var(--space-md);
  }

  @media screen and (width < 768px) {
    .show-sidebar {
      grid-template-areas:
        "header"
        "content"
        "aside";
      grid-template-columns: 1fr;
    }
  }

  .show-sidebar > header {
    grid-area: header;
  }

  .show-sidebar > :not(aside) {
    grid-area: content;
  }

  .show-sidebar > aside {
    grid-area: aside;
  }

  .sidebar {
    padding: var(--space-xs);
  }

  @media (min-width: 768px) {
    .sidebar {
      margin-block-start: var(--space-xl);
    }
  }

  .sidebar__title {
    font-size: var(--fs-xl);
    text-decoration: underline;
    text-decoration-color: var(--clr-primary-400);
    text-underline-offset: 4px;
  }

  .related-list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2xs);
    justify-content: space-between;
    align-items: flex-start;
    list-style: disc;
    margin-block-start: var(--space-xs);
  }

  .related-list > li {
    margin-inline-start: var(--space-md);
    flex-basis: 300px;
  }
}

/* =============================================================================
   COMPONENTS
   ========================================================================== */

@layer components {
  /* ----- brand shapes -----
     clip-paths and gradients carried over verbatim from the Astro build. */

  .hexagon,
  .hero {
    position: relative;
    isolation: isolate;
    --block-buffer: 1px;
  }

  .hexagon::before,
  .hero::after {
    content: "";
    display: block;
    position: absolute;
    inset-inline: 0;
    height: 25%;
    background-color: var(--clr-primary-400);
  }

  .hexagon::before {
    clip-path: polygon(0 0, 100% 0, 100% 35%, 96% 100%, 92% 30%, 90% 65%, 88% 25%);
    max-height: 70px;
    z-index: var(--z-behind);
    top: calc(0% - var(--block-buffer));
  }

  .hexagon--mirrored::before,
  .hero--mirrored::after {
    transform: scaleX(-1);
  }

  .hero::after {
    clip-path: polygon(0 0, 0% 100%, 100% 100%);
    max-height: 28px;
    z-index: var(--z-above);
    bottom: calc(0% - var(--block-buffer));
  }

  .ribbon {
    position: relative;
    clip-path: polygon(100% 0, 100% 50%, 100% 100%, 0% 100%, 12% 50%, 0% 0%);
  }

  @media (min-width: 768px) {
    .ribbon {
      padding-inline: 5rem;
    }
  }

  .triangle {
    position: relative;
    isolation: isolate;
  }

  .triangle::after {
    content: "";
    display: block;
    position: absolute;
    bottom: 0;
    right: 0;
    height: 5rem;
    aspect-ratio: 1 / 1;
    z-index: var(--z-above);
    background-color: hsl(0 0% 0% / 0);
    background-image: linear-gradient(
      -45deg,
      var(--primary-clr) 35%,
      var(--neutral-900) 35%,
      var(--neutral-900) 50%,
      transparent 50%
    );
  }

  .triangles {
    aspect-ratio: 1 / 1;
    width: clamp(8rem, 15vw, 12rem);
    background-color: hsl(0 0% 0% / 0);
    background-image: linear-gradient(-45deg, transparent 75%, var(--primary-clr) 75%);
    background-size: 1.5rem 1.5rem;
    opacity: 0.75;
    z-index: var(--z-behind);
    position: absolute;
    top: -1rem;
    left: -2.5rem;
  }

  .triangles--faint {
    opacity: 0.25;
  }

  .pentagon {
    display: block;
    clip-path: polygon(100% 0, 100% calc(100% - 1.5em), calc(100% - 1.5em) 100%, 0 100%, 0 0);
    padding: var(--space-2xs);
  }

  /* ----- icons ----- */

  .icon {
    width: 1em;
    height: 1em;
    fill: currentColor;
    flex-shrink: 0;
  }

  /* ----- buttons ----- */

  .maroon-button,
  :is(button, a).maroon-button {
    display: inline-block;
    background-color: var(--clr-primary-400);
    color: var(--clr-white);
    font-family: var(--ff-heading);
    text-transform: uppercase;
    text-align: center;
    padding: var(--space-2xs) var(--space-md);
    font-size: var(--fs-xl);
  }

  .maroon-button:hover {
    background-color: var(--clr-primary-200);
    color: var(--clr-white);
  }

  .maroon-button--sm { font-size: var(--fs-sm); }
  .maroon-button--md { font-size: var(--fs-base); }
  .maroon-button--lg { font-size: var(--fs-lg); }

  .maroon-button--block {
    display: block;
    max-width: max-content;
    margin-inline: auto;
  }

  .maroon-button--rounded {
    border-radius: var(--radius-md);
    display: block;
    max-width: max-content;
  }

  .maroon-button--tight {
    text-transform: capitalize;
    padding-block: 0.75rem;
  }

  .button-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs);
    justify-content: center;
    align-items: center;
  }

  /* ----- titles ----- */

  .section-title {
    max-width: max-content;
    margin-inline: auto;
    margin-block-end: var(--space-md);
    text-align: center;
    font-size: var(--fs-5xl);
    line-height: var(--lh-tight);
    position: relative;
  }

  .section-title::after {
    content: "";
    display: block;
    position: absolute;
    top: calc(100% + 1rem);
    left: 50%;
    translate: -50% 0;
    width: 75%;
    height: var(--size-rule);
    background-color: var(--clr-primary-400);
  }

  .section-title > span,
  .page-title > span {
    font-family: var(--ff-heading);
    color: var(--clr-primary-400);
    font-weight: var(--fw-bold);
  }

  @media (min-width: 768px) {
    .section-title--start {
      margin-inline: 0;
      text-align: left;
    }
  }

  .page-title {
    margin-block-end: var(--space-2xs);
    font-size: var(--fs-5xl);
    line-height: var(--lh-tight);
  }

  .eyebrow {
    font-size: var(--fs-xl);
  }

  .rule-title {
    max-width: max-content;
    border-block-end: var(--size-rule) solid var(--clr-primary-400);
    padding-block-end: var(--space-xs);
    margin-block-end: var(--space-md);
    font-size: var(--fs-5xl);
    line-height: var(--lh-tight);
  }

  .rule-title--cta {
    margin-inline-end: auto;
    padding-block: var(--space-xs);
  }

  .rule-title--cta > span {
    font-family: var(--ff-heading);
    font-weight: var(--fw-bold);
    color: var(--clr-primary-200);
  }

  /* Only the blog index uses this, but a .rule-title modifier has to follow
     .rule-title to win — same layer, same specificity, so source order decides.
     That is why it is here rather than in blog/index.css. */
  .rule-title--sm {
    font-size: var(--fs-3xl);
    padding-block-end: 0;
    margin-block-end: 0;
  }

  .link-underline {
    color: var(--clr-primary-400);
    text-decoration: underline;
    text-underline-offset: 3px;
  }

  .link-underline:hover {
    color: var(--clr-primary-200);
  }

  /* ----- sections ----- */

  .section {
    position: relative;
    isolation: isolate;
    padding-block: var(--section-pad);
  }

  .section--tall {
    padding-block: var(--section-pad-lg);
  }

  .section--flush {
    padding-block: 2.5rem;
  }

  .section--panel {
    background-color: var(--clr-surface);
    box-shadow: var(--shadow-inner);
  }

  .section--textured {
    background-color: var(--clr-surface-glass);
    background-image: url("../images/black-texture-1200x628.webp");
    background-size: cover;
    background-position: center;
    background-blend-mode: overlay;
  }

  .section--band {
    background-color: var(--clr-surface-band);
  }

  .section--strip {
    background-color: var(--clr-surface-strip);
    padding-block: var(--space-xs);
  }

  .section-bg {
    position: absolute;
    inset: 0;
    z-index: var(--z-behind);
    pointer-events: none;
  }

  .section-bg--dim { filter: brightness(0.25); }
  .section-bg--hero { filter: brightness(0.7); }
  .section-bg--ghost { opacity: 0.05; filter: grayscale(1); }
  .section-bg--deep { filter: brightness(0.3); }

  /* ----- hero ----- */

  .hero {
    padding-block: var(--section-pad);
    min-height: min-content;
  }

  .hero__body {
    display: grid;
    gap: var(--space-xs);
  }

  .hero__services {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2xs);
    justify-content: center;
    align-items: center;
    text-align: center;
    font-size: var(--fs-xl);
  }

  .hero__service {
    font-family: var(--ff-heading);
  }

  .hero__service:hover {
    color: var(--clr-white);
    text-decoration: underline;
  }

  /* Replaces a run of empty bullet spans that used `first:hidden`. */
  .hero__service + .hero__service::before {
    content: "\25CF";
    color: var(--clr-primary-200);
    font-size: var(--fs-xs);
    margin-inline-end: var(--space-2xs);
  }

  .hero__title {
    font-size: var(--fs-fluid-hero);
    line-height: var(--lh-tight);
    text-align: center;
    margin-block: var(--space-2xs);
  }

  .hero__title > span {
    font-family: var(--ff-heading);
    color: var(--clr-primary-200);
    font-weight: var(--fw-semibold);
  }

  .hero__lead {
    text-align: center;
    color: var(--clr-text-muted);
    max-width: var(--measure-lead);
    margin-inline: auto;
  }

  .hero__ratings {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-lg);
    justify-content: center;
    align-items: center;
    margin-block-end: var(--space-md);
  }

  .rating-badge {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: var(--space-2xs);
    width: max-content;
  }

  .rating-badge__icon {
    aspect-ratio: 1 / 1;
    width: 25px;
    border-radius: var(--radius-full);
    background-color: var(--clr-surface-light);
    color: var(--clr-text-invert);
    display: grid;
    place-items: center;
    font-size: var(--fs-xs);
    font-weight: var(--fw-bold);
    font-family: var(--ff-heading);
  }

  .rating-badge__stars {
    display: flex;
    gap: 1px;
    font-size: var(--fs-xl);
    color: var(--clr-star);
  }

  .rating-badge__label {
    font-size: var(--fs-2xs);
    color: var(--clr-text-faint);
  }

  .hero__phone {
    text-align: center;
    text-transform: capitalize;
  }

  .hero__phone-number {
    font-family: var(--ff-heading);
    font-size: var(--fs-2xl);
  }

  /* ----- credentials ----- */

  .credentials-strip {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: var(--space-md);
  }

  .credentials-strip__item {
    display: flex;
    align-items: center;
    gap: var(--space-2xs);
    font-family: var(--ff-heading);
    text-transform: uppercase;
    font-size: var(--fs-2xl);
  }

  .credentials-strip__item .icon {
    color: var(--clr-star);
  }

  .credentials-list {
    list-style: disc;
    margin-inline-start: var(--space-xs);
    margin-block-end: var(--space-2xl);
  }

  .credentials-list > li {
    margin-inline-start: var(--space-xs);
  }

  /* ----- cards and grids ----- */

  .service-grid {
    position: relative;
    isolation: isolate;
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-md);
    padding-block: var(--space-md);
  }

  @media (min-width: 768px) {
    .service-grid {
      grid-template-columns: repeat(4, 1fr);
    }
  }

  .service-card {
    display: grid;
    grid-template-columns: 1fr;
    grid-template-rows: 200px 1fr;
    gap: var(--space-xs);
    align-items: stretch;
  }

  .service-card:hover {
    filter: brightness(1.1);
  }

  .service-card__media {
    height: 100%;
  }

  @media (min-width: 768px) {
    .service-card__media > .img-loader {
      max-height: 250px;
    }
  }

  .service-card__body {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-xs);
  }

  .service-card__title {
    font-family: var(--ff-heading);
    font-size: var(--fs-2xl);
  }

  .service-card__text {
    border-inline-start: var(--size-rule) solid var(--clr-primary-400);
    padding-inline-start: var(--space-xs);
  }

  .service-card__cta {
    margin-block-start: auto;
  }

  .service-tiles {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-md);
    justify-content: center;
    align-items: center;
    padding-block: var(--space-lg);
    margin-block-end: var(--space-lg);
    text-align: left;
    font-weight: var(--fw-semibold);
  }

  .service-tile {
    filter: drop-shadow(var(--shadow-tile));
  }

  .service-tile:hover {
    filter: brightness(1.25);
  }

  .service-tile__link {
    background-color: var(--clr-primary-400);
  }

  .service-tile__link:hover {
    color: var(--clr-white);
  }

  .service-tile__media {
    max-width: 254px;
    height: 170px;
    margin-block-end: var(--space-2xs);
  }

  .service-tile__label {
    text-transform: uppercase;
    font-family: var(--ff-heading);
  }

  .gallery {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-sm);
    padding-block: var(--space-md);
    grid-auto-rows: minmax(0, var(--gallery-row, 350px));
  }

  @media (min-width: 768px) {
    .gallery {
      grid-template-columns: repeat(3, 1fr);
      gap: 1.25rem;
      grid-auto-rows: minmax(0, var(--gallery-row-md, 450px));
    }
  }

  .gallery--compact {
    --gallery-row: 150px;
    --gallery-row-md: 250px;
  }

  .gallery--fluid {
    --gallery-row: 300px;
    --gallery-row-md: 300px;
    gap: var(--space-2xs);
  }

  @media (min-width: 768px) {
    .gallery--fluid {
      grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
      gap: var(--space-2xs);
    }
  }

  .gallery--framed > * {
    border: var(--size-rule) solid var(--clr-primary-400);
  }

  .project-mosaic {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-xs);
    padding-block: var(--space-lg);
  }

  @media (min-width: 768px) {
    .project-mosaic {
      grid-template-columns: repeat(4, 1fr);
      grid-template-rows: repeat(2, 300px);
    }

    .project-mosaic__feature {
      grid-column: 1 / 3;
      grid-row: 1 / 3;
    }

    .project-mosaic__wide {
      grid-column: 3 / 5;
    }
  }

  .project-mosaic__cell {
    --cell-max-h: 250px;
  }

  .project-mosaic__cell > .img-loader {
    height: 100%;
    width: 100%;
    max-height: var(--cell-max-h);
  }

  @media (min-width: 768px) {
    .project-mosaic__cell {
      --cell-max-h: 650px;
    }
  }

  .project-feature {
    height: 100%;
    isolation: isolate;
  }

  .project-feature__media {
    position: absolute;
    inset: 0;
    height: 100%;
    width: 100%;
    z-index: var(--z-behind);
  }

  .project-feature__body {
    padding: var(--space-xl);
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
    align-items: flex-start;
    min-height: min-content;
  }

  @media (min-width: 768px) {
    .project-feature__body {
      max-height: 650px;
    }
  }

  .post-list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-md);
    justify-content: center;
    align-items: stretch;
    padding-block: var(--space-md);
  }

  .post-card {
    flex: 1 1 500px;
    max-width: 100%;
    display: grid;
    gap: var(--space-2xs);
    justify-items: start;
    align-content: start;
    padding: var(--space-xs);
    background-color: var(--clr-surface-card);
    border-radius: var(--radius-sm);
  }

  .post-card__title {
    font-size: var(--fs-2xl);
    font-weight: var(--fw-bold);
  }

  .post-card__date {
    margin-block-end: var(--space-2xs);
    color: var(--clr-text-muted);
  }

  .post-card__excerpt {
    margin-block-end: var(--space-xs);
  }

  .post-card__cta {
    margin-block-start: auto;
  }

  .post-header__title {
    font-size: var(--fs-5xl);
    line-height: var(--lh-tight);
    margin-block-end: var(--space-xs);
  }

  .post-header__meta {
    margin-block-end: var(--space-2xl);
    color: var(--clr-text-muted);
  }

  .cta-panel {
    position: relative;
    padding: var(--space-2xl) var(--space-md);
  }

  .cta-panel__grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-md);
    align-items: center;
    place-items: center;
  }

  @media (min-width: 768px) {
    .cta-panel__grid {
      grid-template-columns: repeat(2, 1fr);
    }
  }

  /* Only the homepage uses this, but it modifies .cta-panel, so it belongs with
     the rest of the family rather than in home/index.css. */
  .cta-panel__text {
    margin-block-end: var(--space-md);
  }

  /* ----- contact form ----- */

  .contact-section__inner {
    position: relative;
    padding-block: var(--space-md);
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--inner-gap, var(--space-md));
  }

  @media (min-width: 768px) {
    .contact-section__inner {
      grid-template-columns: repeat(2, 1fr);
    }
  }

  .contact-section__media {
    display: none;
  }

  @media (min-width: 768px) {
    .contact-section__media {
      display: block;
    }
  }

  .contact-section__body {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
  }

  .contact-section__title {
    font-size: var(--fs-5xl);
    line-height: var(--lh-tight);
  }

  .contact-section__title > span {
    font-family: var(--ff-heading);
    color: var(--clr-primary-200);
    font-weight: var(--fw-bold);
  }

  /* Why the last submission was refused. Rendered above the first field in
     both the contact form and the feedback card, so it has to read against the
     dark textured contact band and the light feedback card alike — hence the
     opaque light surface rather than a tint of whatever sits behind it. */
  .form-errors {
    margin-block-end: var(--space-xs);
    padding: var(--space-2xs) var(--space-xs);
    background-color: var(--clr-surface-light);
    color: var(--clr-text-invert);
    border-inline-start: var(--size-rule) solid var(--clr-alert);
    border-radius: var(--radius-sm);
    font-size: var(--fs-sm);
  }

  .form-errors__title {
    font-family: var(--ff-heading);
    font-weight: var(--fw-bold);
    color: var(--clr-alert);
  }

  .form-errors__list {
    margin-block-start: var(--space-3xs);
    padding-inline-start: var(--space-xs);
    list-style: disc;
  }

  .form-errors__list li + li {
    margin-block-start: var(--space-3xs);
  }

  .contact-form {
    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
    color: var(--clr-text-invert);
  }

  .form-field {
    flex-grow: 1;
    width: 100%;
    padding: var(--space-2xs);
    background-color: var(--clr-surface-light);
    color: var(--clr-text-invert);
  }

  .form-row {
    flex-grow: 1;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs);
  }

  .form-row .form-field {
    width: auto;
  }

  .form-row__label {
    flex-grow: 1;
    padding: var(--space-2xs);
    color: var(--clr-text);
  }

  .form-check input {
    cursor: pointer;
  }

  .form-check__label {
    font-size: var(--fs-xs);
    color: var(--clr-text);
    cursor: pointer;
  }

  .form-check__link {
    color: var(--clr-alert-link);
  }

  /* Honeypot. Its own class rather than .visually-hidden so the intent stays
     obvious in the markup. */
  .form-honeypot {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
    z-index: -1;
  }

  .form-submit {
    flex-grow: 1;
  }

  /* ----- prose -----
     .prose h3 pulls the size back to 1rem. Preflight reset every heading to
     font-size:inherit, so `<h3 class="mt-6">` used to render at body size;
     without this the service pages' sub-items jump ~50%. */

  .prose {
    max-inline-size: var(--measure-lg);
  }

  .prose > p {
    margin-block-start: var(--space-xs);
  }

  .prose h2 {
    font-size: var(--fs-2xl);
    margin-block-start: var(--space-md);
  }

  .prose h3 {
    font-size: var(--fs-base);
    font-weight: var(--fw-semibold);
    margin-block-start: var(--space-sm);
  }

  .prose ol {
    list-style: decimal;
  }

  .prose ul {
    list-style: disc;
  }

  .prose :where(ol, ul) > li {
    margin-inline-start: var(--space-md);
  }

  .prose :where(ol, ul) > li > p,
  .prose h2 + p {
    padding-inline-start: var(--space-xs);
  }

  /* The old page indented these with ml-8 / ml-16. */
  .prose--legal > p,
  .prose--legal > ul {
    margin-inline-start: var(--space-md);
  }

  .prose--legal > ul {
    margin-inline-start: var(--space-xl);
    margin-block-start: var(--space-xs);
  }

  .prose--legal > ul > li {
    margin-inline-start: var(--space-xs);
  }

  .prose--legal > h1,
  .prose--legal > h2 {
    margin-inline-start: 0;
  }

  /* In-prose links need to read as links: the old markup gave each one an
     explicit accent class, which the semantic refactor dropped. */
  .prose a {
    color: var(--clr-primary-200);
    text-decoration: underline;
    text-underline-offset: 3px;
  }

  .prose a:hover {
    color: var(--clr-primary-400);
  }

  /* ----- long-form text shared across unrelated pages -----
     These were in the `pages` layer, which was wrong: each is used by pages
     sharing no controller and no layout, so no per-page file can own one.
     `.about-copy` dresses about, contact and the services index; `.error-lede`
     dresses both the 404 and message-sent. Being used by unrelated pages is
     what makes something shared vocabulary. */

  .about-copy > p,
  .about-copy {
    margin-block-end: var(--space-md);
  }

  .about-copy > p:last-child {
    margin-block-end: 0;
  }

  .error-lede {
    max-width: var(--measure-lg);
    margin-block-end: var(--space-md);
  }

  .faq-list {
    margin-block-start: var(--space-xs);
  }

  .faq-item {
    margin-block-end: var(--space-sm);
  }

  .faq-item__question {
    font-size: var(--fs-base);
    font-weight: var(--fw-semibold);
  }

  .faq-item__answer {
    padding-inline-start: var(--space-xs);
  }

  /* Styles markdown-derived HTML with no classes of its own, so descendant
     selectors are correct here. */
  .blog-content h2 {
    font-size: var(--fs-3xl);
    margin-block-start: var(--space-md);
    text-decoration: underline;
    text-decoration-color: var(--clr-primary-400);
    text-underline-offset: 4px;
  }

  .blog-content h3 {
    font-size: var(--fs-2xl);
    margin-block-start: var(--space-sm);
  }

  .blog-content :where(ol) {
    list-style: decimal;
    margin-inline-start: var(--space-md);
  }

  .blog-content :where(ul) {
    list-style: disc;
    margin-inline-start: var(--space-md);
    margin-block-start: var(--space-xs);
  }

  .blog-content :where(ol > li > p > strong:first-child, ul > li > p > strong:first-child) {
    display: block;
  }

  .blog-content p {
    margin-block-start: var(--space-xs);
    padding-inline-start: var(--space-xs);
  }

  /* ----- blur-up image loader ----- */

  .img-loader {
    --img-loader-src: none;

    background-image: var(--img-loader-src);
    background-size: cover;
    background-position: center;
    overflow: hidden;
  }

  .img-loader:not(.loaded) {
    background-blend-mode: overlay;
    animation: img-loader-pulse 1.5s infinite alternate;
  }

  .img-loader > img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    opacity: 0;
    transition: opacity var(--dur-fast) ease-in-out;
  }

  .img-loader.loaded > img {
    opacity: 1;
  }

  @keyframes img-loader-pulse {
    from { background-color: hsl(0 0% 0% / 0); }
    to { background-color: hsl(0 0% 0% / 0.3); }
  }

  .img-loader--fill {
    position: absolute;
    inset: 0;
  }

  .img-loader--contain > img {
    object-fit: contain;
  }

  .img-loader--top > img {
    object-position: top;
  }

  .img-loader--h-full {
    height: 100%;
  }

  /* ----- popups ----- */

  .finance-popup {
    position: fixed;
    bottom: 5rem;
    inset-inline: var(--space-xs);
    max-width: max-content;
    margin-inline: auto;
    padding: var(--space-sm);
    z-index: var(--z-popup);
    background-color: var(--clr-surface-light);
    color: var(--clr-text-invert);
    font-family: var(--ff-heading);
    box-shadow: var(--shadow-md);
    border: var(--size-rule) solid var(--clr-alert);
    animation: finance-popup-in var(--dur-popup) ease-out var(--delay-popup) both;
  }

  @keyframes finance-popup-in {
    from { opacity: 0; translate: 0 2em; }
    to { opacity: 1; translate: 0 0; }
  }

  .finance-popup__inner {
    position: relative;
    isolation: isolate;
  }

  .finance-popup__title {
    text-transform: uppercase;
    text-align: center;
    font-size: var(--fs-3xl);
    font-weight: var(--fw-bold);
  }

  .finance-popup__text {
    text-align: center;
    margin-block-end: var(--space-xs);
  }

  .finance-popup__cta {
    display: block;
    text-align: center;
    background-color: var(--clr-alert);
    color: var(--clr-white);
    font-family: var(--ff-heading);
    font-weight: var(--fw-bold);
    text-transform: uppercase;
    padding: var(--space-2xs) var(--space-md);
    font-size: var(--fs-sm);
  }

  .finance-popup__cta:hover {
    background-color: var(--clr-hover-mute);
    color: var(--clr-white);
  }

  .finance-popup__close {
    position: absolute;
    bottom: calc(100% - 10px);
    left: 100%;
    padding: var(--space-2xs);
    font-size: var(--fs-xl);
    line-height: 1;
  }

  .exit-dialog {
    /* Must not be `position: relative`. Author styles beat the UA sheet, so that
       overrides `dialog:modal { position: fixed }`, drops the dialog into normal
       flow at the end of <body>, and makes showModal() scroll the page to reach
       it. Fixed keeps it viewport-centred and still gives __close a containing
       block. height/max-height/overflow restore what dialog:modal supplied. */
    position: fixed;
    inset: 0;
    margin: auto;
    width: min(750px, 100%);
    height: fit-content;
    max-height: calc(100dvh - 2em);
    overflow: auto;
    padding: var(--space-lg);
    text-align: center;
    background-color: var(--clr-surface-light);
    color: var(--clr-text-invert);
    box-shadow: var(--shadow-md);
    border: var(--size-rule) solid var(--clr-alert);
  }

  /* Literal colour: ::backdrop does not inherit body's tokens. Mirrors
     hsl(0 0% 0% / .5). */
  .exit-dialog::backdrop {
    background-color: hsl(0 0% 0% / 0.5);
  }

  .exit-dialog__title {
    font-size: var(--fs-3xl);
    font-weight: var(--fw-black);
    color: var(--clr-primary-400);
  }

  .exit-dialog__subtitle {
    margin-block-end: var(--space-sm);
    font-size: var(--fs-3xl);
  }

  .exit-dialog__accent {
    color: var(--clr-primary-400);
    font-weight: var(--fw-bold);
  }

  .exit-dialog__points {
    margin-block: var(--space-xs);
  }

  .exit-dialog__actions {
    margin-block: var(--space-xs);
  }

  .exit-dialog__or {
    font-weight: var(--fw-bold);
    margin-inline: var(--space-2xs);
    text-transform: uppercase;
  }

  .exit-dialog__close {
    position: absolute;
    top: 0;
    right: 0;
    padding-inline: var(--space-xs);
    font-size: var(--fs-3xl);
    font-weight: var(--fw-bold);
    line-height: 1.2;
  }
}

/* =============================================================================
   PAGES — no longer here.
   Rules scoped to a single page live in their own stylesheet under
   assets/css/, at a path mirroring the view's path under app/views/:
   app/views/pages/about.html.php is dressed by assets/css/pages/about.css. A
   whole layout's chrome is named after the layout instead — layouts/auth.css,
   layouts/admin.css. Controllers name what a page needs in its `stylesheets`
   array and partials/head links them after this file.

   `pages` stays in the @layer statement above because those files declare
   `@layer pages` and sort into it. Do not delete the name.

   What is left in this file is the shared vocabulary: anything used by pages
   that share no controller and no layout, which is what `components` is for.
   ========================================================================== */

/* =============================================================================
   UTILITIES — single-purpose, last so they always win.
   Closed list. A fourteenth entry here is a missing component.
   ========================================================================== */

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

  .hide-scroll {
    -ms-overflow-style: none;
    scrollbar-width: none;
  }

  .hide-scroll::-webkit-scrollbar {
    width: 0;
  }

  .mask {
    mask-image: linear-gradient(transparent, hsl(0 0% 0% / 0.75));
    -webkit-mask-image: linear-gradient(transparent, hsl(0 0% 0% / 0.75));
  }

  /* The old rule set two disagreeing gradients; this is the -webkit value,
     the one that actually shipped. No call site at present. */
  .bg-mask {
    mask-image: linear-gradient(hsl(0 0% 0% / 0.3) 30%, hsl(0 0% 0%));
    -webkit-mask-image: linear-gradient(hsl(0 0% 0% / 0.3) 30%, hsl(0 0% 0%));
  }

  .active {
    color: var(--clr-primary-200);
    border-block-end-color: var(--clr-primary-400);
  }

  .md-up-only {
    display: none;
  }

  @media (min-width: 768px) {
    /* revert, not block: this also lands on <br>, whose line-breaking is
       intrinsic behaviour rather than a consequence of its display value. */
    .md-up-only {
      display: revert;
    }
  }

  @media (min-width: 768px) {
    .md-down-only {
      display: none;
    }
  }

  .center-block {
    margin-inline: auto;
  }

  .text-center {
    text-align: center;
  }

  .measure-2xs { max-width: var(--measure-2xs); }
  .measure-sm { max-width: var(--measure-sm); }
  .measure-md { max-width: var(--measure-md); }
  .measure-lg { max-width: var(--measure-lg); }

  .text-accent {
    color: var(--clr-primary-400);
  }

  .text-muted {
    color: var(--clr-text-muted);
  }
}

/* Appended page rules. Layer order comes from the @layer statement at the top
   of this file, so these land in `pages` regardless of position. */

/* =============================================================================
   FLASH NOTICE, and the one auth-named rule that is not auth-only
   The auth shell itself moved to assets/css/layouts/auth.css. What stayed is
   what turned out to be shared: .form-notice comes from partials/flash_notice,
   which layouts/main, layouts/sidebar and layouts/admin all render, and
   .auth-field__hint is used by account/show and dashboard/index as well as
   password_resets/edit — so it straddles layouts/auth and layouts/admin and
   neither of their files can own it.
   ------------------------------------------------------------------------- */

@layer components {
  /* ----- flash notice ----- */

  /* Mirrors .form-errors so the two read as a pair, in brand maroon rather than
     alert red — this is the "that worked" message. */
  .form-notice {
    margin-block-end: var(--space-xs);
    padding: var(--space-2xs) var(--space-xs);
    background-color: var(--clr-surface-light);
    color: var(--clr-text-invert);
    border-inline-start: var(--size-rule) solid var(--clr-primary-400);
    border-radius: var(--radius-sm);
    font-size: var(--fs-sm);
  }

  .form-notice__list {
    list-style: none;
  }

  .form-notice__list li + li {
    margin-block-start: var(--space-3xs);
  }

  /* Kept here, not in layouts/auth.css: account/show and dashboard/index use it
     too, and those render under layouts/admin. */
  .auth-field__hint {
    color: var(--clr-text-faint);
    font-size: var(--fs-xs);
  }
}

@layer components {
  /* In layouts/main there is no card to sit inside, so the notice constrains
     itself to the same container .wrapper uses. */
  .form-notice--page {
    width: min(var(--size-container), 100% - (var(--size-gutter) * 2));
    margin-inline: auto;
    margin-block: var(--space-xs);
  }
}
