/* ==========================================================================
   Housing Market Ads Keyword Planner — site chrome
   --------------------------------------------------------------------------
   A hand-written translation of the Housing Market Ads marketing header and
   footer into plain CSS, for the static Express-served planner.

   SOURCE OF EVERY VALUE BELOW (nothing here is invented or eyeballed):
     sites/housing-market-ads/src/app/globals.css        colour tokens, themes
     packages/design-system/src/tokens.css               type/space/radii/motion
     packages/design-system/src/base.css                 .theme-art-on-* logic
     sites/housing-market-ads/src/components/site-header.tsx
     sites/housing-market-ads/src/components/site-footer.tsx
     packages/ui/src/{desktop-nav,mobile-nav,button,container,theme-toggle}.tsx

   Tailwind spacing was resolved as 1 unit = 0.25rem, and the breakpoints are
   the design system's own: sm 30rem, md 48rem, lg 64rem, xl 80rem.

   LOAD ORDER: this file must come AFTER css/styles.css. Several rules here
   deliberately re-point variables that styles.css defines, and a tie in
   specificity is broken by source order.

   CLASS NAMING: every chrome class is prefixed `hma-`, so nothing in this file
   can collide with the planner's own `.card`, `.primary`, `.section` and so
   on. The three unprefixed classes are `.theme-art-on-light`,
   `.theme-art-on-dark` (the platform's logo-swap contract, copied verbatim
   from the design system so the mechanism is identical) and `.hma-sr-only`.
   ========================================================================== */

/* ==========================================================================
   A. TOKENS
   --------------------------------------------------------------------------
   The DEFAULT (attribute-less) palette is DARK, matching
   sites/housing-market-ads/config/theme.ts — `DEFAULT_THEME = 'dark'`.
   A page whose theme script has not run yet, or whose visitor has JavaScript
   off, therefore gets the brand's own default rather than nothing.

   Both `html[data-theme='light']` and `html[data-theme='dark']` then redeclare
   the COMPLETE set. That completeness is the point: a token defined in one
   theme and missing from the other resolves to nothing after a toggle, and the
   page does not look broken — it looks empty. See CLAUDE.md and
   sites/housing-market-ads/src/components/__tests__/theme-switch.test.ts.

   Selector is `html[data-theme=...]` (0,1,1), not `[data-theme=...]` (0,1,0),
   so it beats a bare `:root` regardless of source order.
   ========================================================================== */

:root {
  /* ---- Structure (design system, theme-independent) --------------------- */
  --hma-font-sans:
    'Inter Variable', 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI',
    Roboto, 'Helvetica Neue', Arial, sans-serif;

  --spacing-gutter: clamp(1.25rem, 0.75rem + 2vw, 2.5rem);
  --container-wide: 82.5rem;

  --radius-card: 1rem;
  --radius-card-lg: 1.5rem;
  --radius-pill: 9999px;

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --duration-fast: 150ms;
  --duration-base: 250ms;

  /* ---- Colour — DARK, the brand default --------------------------------- */
  --color-bg: #05090f;
  --color-bg-subtle: #080d14;
  --color-surface: #0c131c;
  --color-surface-raised: #121b26;
  --color-hairline: rgb(255 255 255 / 9%);
  --color-hairline-strong: rgb(255 255 255 / 16%);
  --color-fg: #f2f6f8;
  --color-fg-muted: #93a1ae;
  --color-fg-subtle: #66737f;
  --color-accent: #00bfd0;
  --color-accent-hover: #22d3e4;
  --color-accent-pressed: #00a5b4;
  --color-accent-ink: #5ce0ee;
  --color-accent-contrast: #03131a;
  --color-accent-soft: rgb(0 191 208 / 12%);
  --color-accent-border: rgb(0 191 208 / 35%);
  --color-success: #34d399;
  --color-danger: #f87171;
  --shadow-card: 0 1px 2px rgb(0 0 0 / 40%), 0 12px 32px -16px rgb(0 0 0 / 60%);
  --shadow-accent-glow: 0 8px 30px -8px rgb(0 191 208 / 45%);

  color-scheme: dark;
}

html[data-theme='light'] {
  color-scheme: light;

  --color-bg: #ffffff;
  --color-bg-subtle: #f6f8fa;
  --color-surface: #ffffff;
  --color-surface-raised: #eef2f6;
  --color-hairline: #e4e8ed;
  --color-hairline-strong: #c8d0da;
  --color-fg: #0b2137;
  --color-fg-muted: #485765;
  --color-fg-subtle: #67737f;
  --color-accent: #00bfd0;
  --color-accent-hover: #00a5b4;
  --color-accent-pressed: #008c9a;
  --color-accent-ink: #0a5f6b;
  --color-accent-contrast: #03131a;
  --color-accent-soft: #e6f9fb;
  --color-accent-border: #a6e2ea;
  --color-success: #067647;
  --color-danger: #d92d20;
  --shadow-card: 0 1px 2px rgb(11 33 55 / 6%), 0 8px 24px -12px rgb(11 33 55 / 14%);
  --shadow-accent-glow: 0 8px 24px -10px rgb(0 191 208 / 42%);
}

html[data-theme='dark'] {
  color-scheme: dark;

  --color-bg: #05090f;
  --color-bg-subtle: #080d14;
  --color-surface: #0c131c;
  --color-surface-raised: #121b26;
  --color-hairline: rgb(255 255 255 / 9%);
  --color-hairline-strong: rgb(255 255 255 / 16%);
  --color-fg: #f2f6f8;
  --color-fg-muted: #93a1ae;
  --color-fg-subtle: #66737f;
  --color-accent: #00bfd0;
  --color-accent-hover: #22d3e4;
  --color-accent-pressed: #00a5b4;
  --color-accent-ink: #5ce0ee;
  --color-accent-contrast: #03131a;
  --color-accent-soft: rgb(0 191 208 / 12%);
  --color-accent-border: rgb(0 191 208 / 35%);
  --color-success: #34d399;
  --color-danger: #f87171;
  --shadow-card: 0 1px 2px rgb(0 0 0 / 40%), 0 12px 32px -16px rgb(0 0 0 / 60%);
  --shadow-accent-glow: 0 8px 30px -8px rgb(0 191 208 / 45%);
}

/* ==========================================================================
   B. SHARED PRIMITIVES
   ========================================================================== */

body {
  /* styles.css sets `font: 16px/1.45 Barlow…`, which is a shorthand and so
     also resets font-weight and font-family. Overriding the family alone here
     keeps its line-height and size for the planner's own content while the
     chrome (which sets its own sizes) renders in the brand face. */
  font-family: var(--hma-font-sans);
}

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

/* Skip link — the first focusable element on the page. The planner has never
   had one, so a keyboard user tabs through the whole navigation on every
   visit. Hidden until focused. */
.hma-skip {
  position: absolute;
  top: 1rem;
  left: 1rem;
  z-index: 200;
  padding: 0.75rem 1.25rem;
  border-radius: var(--radius-pill);
  background: var(--color-accent);
  color: var(--color-accent-contrast);
  font-size: 0.875rem;
  font-weight: 600;
  text-decoration: none;
}

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

/* One visible focus treatment for keyboard users, from base.css. */
.hma-header :focus-visible,
.hma-footer :focus-visible,
.hma-mobile-nav :focus-visible,
.hma-skip:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ---- Logo pair --------------------------------------------------------
   Copied from packages/design-system/src/base.css, mechanism and comments
   intact, because the failure it documents is real and silent.

   A raster logo has its ink baked in, so one file cannot serve both themes.
   Both are rendered and CSS hides one. The class names describe the
   BACKGROUND the file is FOR, never the colour of its ink — the legacy asset
   pair used the opposite convention (`hma-logo-dark.png` is the WHITE
   wordmark, for dark backgrounds), and that ambiguity is exactly how the
   wrong file gets shipped.

   The last two blocks cover the case where <html> carries no data-theme at
   all — the script has not run, or JavaScript is off. Without them NEITHER
   selector matches, nothing is hidden, and both logos render stacked. That
   shipped on nineteen 404 pages once already. */
html[data-theme='dark'] .theme-art-on-light,
html[data-theme='light'] .theme-art-on-dark {
  display: none;
}

html:not([data-theme]) .theme-art-on-light {
  /* The planner's default is dark, so the dark-background file is the one
     that shows when no choice has been applied yet. */
  display: none;
}

/* ---- Buttons (packages/ui/src/button.tsx) ------------------------------ */
.hma-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  border: 0;
  border-radius: var(--radius-pill);
  font-family: inherit;
  font-weight: 600;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition:
    transform var(--duration-fast) var(--ease-out),
    background-color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out),
    color var(--duration-fast) var(--ease-out);
}

.hma-btn:active {
  transform: translateY(1px);
}

.hma-btn--sm {
  height: 2.25rem;
  padding-inline: 1rem;
  font-size: 0.875rem;
}

.hma-btn--lg {
  height: 3.5rem;
  padding-inline: 2rem;
  font-size: 1rem;
}

.hma-btn--primary {
  background: var(--color-accent);
  color: var(--color-accent-contrast);
  box-shadow: var(--shadow-accent-glow);
}

.hma-btn--primary:hover {
  background: var(--color-accent-hover);
  color: var(--color-accent-contrast);
}

.hma-btn--secondary {
  border: 1px solid var(--color-hairline);
  background: var(--color-surface);
  color: var(--color-fg);
}

.hma-btn--secondary:hover {
  border-color: var(--color-accent-border);
  background: var(--color-surface-raised);
}

.hma-btn--ghost {
  background: transparent;
  color: var(--color-fg-muted);
}

.hma-btn--ghost:hover {
  background: var(--color-surface);
  color: var(--color-fg);
}

/* ==========================================================================
   C. HEADER
   Source: sites/housing-market-ads/src/components/site-header.tsx
   ========================================================================== */

.hma-header {
  position: sticky;
  top: 0;
  z-index: 100;
  border-bottom: 1px solid var(--color-hairline);
  /* color-mix rather than a second token: the template uses `bg-bg/80`, an
     80% alpha of the surface token, which cannot be written as a plain
     variable reference. */
  background: color-mix(in srgb, var(--color-bg) 80%, transparent);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
}

@supports not (backdrop-filter: blur(1px)) {
  /* Without the blur the 80% ground is simply see-through and the nav sits on
     top of the scrolling page. Fall back to opaque. */
  .hma-header {
    background: var(--color-bg);
  }
}

.hma-header__nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  height: 4rem;
  max-width: var(--container-wide);
  margin-inline: auto;
  padding-inline: var(--spacing-gutter);
}

.hma-header__lead {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-width: 0;
}

/* Eight pixels of slack at xl. In the template this exists because the header
   was 2px wider than the viewport at exactly 1024px, where the desktop nav
   and the language picker both arrive at once. */
@media (min-width: 80rem) {
  .hma-header__nav,
  .hma-header__lead {
    gap: 2rem;
  }
}

.hma-brand {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  text-decoration: none;
}

.hma-brand__img {
  display: block;
  height: 2rem;
  width: auto;
  max-width: none;
}

@media (min-width: 30rem) {
  .hma-brand__img {
    height: 2.25rem;
  }
}

/* ---- Desktop navigation (packages/ui/src/desktop-nav.tsx) -------------- */
.hma-nav {
  display: none;
  align-items: center;
  gap: 0.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* 74rem (1184px), NOT the design system's lg (1024px), and that is a
   measurement rather than a preference.

   At 1024 this row carries the logo, six nav items, Login, "Create Free
   Account" and the theme toggle: 1054px of content in 959px of content box.
   The nav then prints on top of Login and "How It Works" breaks over two
   lines.

   THE SAME THING HAPPENS ON housingmarketads.com ITSELF at that width —
   measured on the live site, lead scrollWidth 712 inside a 615px box, with
   "Resources" overlapping "Login" exactly as here. It is a real defect on the
   template, not something introduced by this translation, and it is written
   up in NOTES.md with the fix.

   Copying it would be the wrong kind of faithful, so the switch to the mobile
   panel happens 160px later, where the row genuinely fits. The measured
   minimum is 1152 — at which the lead sits 4px clear of the actions, close
   enough that a font substitution would reintroduce the overlap — so the gate
   is set 32px above it. From 1184 up every value in this header is the
   template's own. */
@media (min-width: 74rem) {
  .hma-nav {
    display: flex;
  }
}

.hma-nav__item {
  position: relative;
}

.hma-nav__link {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  height: 2.5rem;
  padding-inline: 1rem;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--color-fg-muted);
  font-family: inherit;
  font-size: 0.9375rem;
  font-weight: 500;
  /* Without this "How It Works" breaks across two lines the moment the row
     runs short of space, which is what happens between 1024 and 1280. */
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: color var(--duration-fast) var(--ease-out);
}

/* ---- Header actions ---------------------------------------------------- */
.hma-header__actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  /* Belt and braces: whatever the widths do, the nav can never print on top
     of Login. */
  flex-shrink: 0;
}

/* Wrapped rather than width-gating the buttons themselves: a button whose own
   rule sets `display:inline-flex` would beat a `display:none` of equal
   specificity depending on source order. The wrapper is not also setting
   display on the button, so the gate is unambiguous. */
.hma-header__cta {
  display: none;
  align-items: center;
  gap: 0.5rem;
}

@media (min-width: 30rem) {
  .hma-header__cta {
    display: flex;
  }
}

/* ---- Theme toggle (packages/ui/src/theme-toggle.tsx) ------------------- */
.hma-theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--color-fg-muted);
  cursor: pointer;
  transition:
    color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out);
}

.hma-theme-toggle:hover {
  border-color: var(--color-hairline-strong);
  color: var(--color-fg);
}

/* Which icon shows is decided by the SAME attribute the button writes, so the
   two can never disagree. Default (no attribute) is dark, so the sun — the
   action available — is the visible one. */
.hma-theme-toggle .hma-icon-moon {
  display: none;
}

html[data-theme='light'] .hma-theme-toggle .hma-icon-sun {
  display: none;
}

html[data-theme='light'] .hma-theme-toggle .hma-icon-moon {
  display: block;
}

/* ---- Mobile menu trigger (packages/ui/src/mobile-nav.tsx) -------------- */
.hma-burger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--color-fg);
  cursor: pointer;
}

@media (min-width: 74rem) {
  .hma-burger {
    display: none;
  }
}

.hma-burger svg {
  width: 1.5rem;
  height: 1.5rem;
}

.hma-burger .hma-icon-close {
  display: none;
}

.hma-burger[aria-expanded='true'] .hma-icon-open {
  display: none;
}

.hma-burger[aria-expanded='true'] .hma-icon-close {
  display: block;
}

/* ---- Mobile panel ------------------------------------------------------
   Rendered as a SIBLING of the header, never inside it. The header sets
   backdrop-filter, and a backdrop-filter ancestor becomes the containing
   block for `position: fixed` descendants — inside it, `top: 4rem; bottom: 0`
   resolves against the 64px header instead of the viewport and the panel
   collapses to a sliver. The React version solves this with a portal to
   document.body; static HTML solves it by simply being outside. */
.hma-mobile-nav {
  position: fixed;
  inset-inline: 0;
  top: 4rem;
  bottom: 0;
  z-index: 90;
  overflow-y: auto;
  overscroll-behavior: contain;
  border-top: 1px solid var(--color-hairline);
  background: var(--color-bg);
  padding: 1.5rem var(--spacing-gutter) 2.5rem;
}

.hma-mobile-nav[hidden] {
  display: none;
}

@media (min-width: 74rem) {
  .hma-mobile-nav {
    display: none;
  }
}

.hma-mobile-nav__list {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.hma-mobile-nav__list > li {
  border-bottom: 1px solid color-mix(in srgb, var(--color-hairline) 60%, transparent);
}

.hma-mobile-nav__link {
  display: block;
  padding-block: 1rem;
  color: var(--color-fg);
  font-size: 1.125rem;
  font-weight: 600;
  text-decoration: none;
}

.hma-mobile-nav__trigger {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  padding-block: 1rem;
  border: 0;
  background: transparent;
  color: var(--color-fg);
  font-family: inherit;
  font-size: 1.125rem;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}

.hma-mobile-nav__trigger svg {
  width: 1rem;
  height: 1rem;
  color: var(--color-fg-subtle);
  transition: transform var(--duration-fast) var(--ease-out);
}

.hma-mobile-nav__trigger[aria-expanded='true'] svg {
  transform: rotate(180deg);
}

.hma-mobile-nav__sublist {
  margin: 0;
  padding: 0 0 0.75rem 0.75rem;
  list-style: none;
}

.hma-mobile-nav__sublist[hidden] {
  display: none;
}

.hma-mobile-nav__sublink {
  display: block;
  padding-block: 0.625rem;
  color: var(--color-fg-muted);
  font-size: 0.9375rem;
  text-decoration: none;
}

.hma-mobile-nav__actions {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin-top: 2rem;
}

/* ==========================================================================
   D. FOOTER
   Source: sites/housing-market-ads/src/components/site-footer.tsx
           packages/ui/src/footer-contact.tsx
   ========================================================================== */

.hma-footer {
  border-top: 1px solid var(--color-hairline);
  background: var(--color-bg-subtle);
  color: var(--color-fg-muted);
}

.hma-footer__inner {
  width: 100%;
  max-width: var(--container-wide);
  margin-inline: auto;
  padding-inline: var(--spacing-gutter);
}

.hma-footer__main {
  display: grid;
  gap: 3rem;
  padding-block: 4rem;
}

@media (min-width: 64rem) {
  .hma-footer__main {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 3fr);
  }
}

.hma-footer__brand {
  max-width: 20rem;
}

.hma-footer__blurb {
  margin: 1.25rem 0 0;
  color: var(--color-fg-muted);
  font-size: 0.875rem;
  line-height: 1.625;
}

.hma-footer__social {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 1.5rem 0 0;
  padding: 0;
  list-style: none;
}

.hma-footer__social a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-pill);
  color: var(--color-fg-muted);
  text-decoration: none;
  transition:
    color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out);
}

.hma-footer__social a:hover {
  border-color: var(--color-accent-border);
  color: var(--color-accent);
}

.hma-footer__social svg {
  width: 1.125rem;
  height: 1.125rem;
}

.hma-footer__columns {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 1.5rem;
  row-gap: 2.5rem;
}

@media (min-width: 30rem) {
  .hma-footer__columns {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.hma-footer__title {
  margin: 0;
  color: var(--color-fg-subtle);
  font-family: inherit;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.hma-footer__links {
  display: grid;
  gap: 0.625rem;
  margin: 1rem 0 0;
  padding: 0;
  list-style: none;
}

/* break-words is not tidying. "Immobiliendienstleistungen" is 26 characters
   with nowhere to wrap, and in a two-column grid at 375px it pushed the whole
   document 5px wider than the viewport — the page scrolled sideways, in
   German only. Kept here even though this page is English-only, because the
   day it is translated is not the day anyone will remember to add it. */
.hma-footer__links a,
.hma-footer__contact a {
  color: var(--color-fg-muted);
  font-size: 0.875rem;
  text-decoration: none;
  overflow-wrap: break-word;
  transition: color var(--duration-fast) var(--ease-out);
}

.hma-footer__links a:hover {
  color: var(--color-accent);
}

.hma-footer__contact a:hover {
  color: var(--color-accent-ink);
}

/* `not-italic` is not cosmetic tidying: every browser's default stylesheet
   italicises <address>, which would leave one block of the footer in italics. */
.hma-footer__contact address {
  display: grid;
  gap: 0.625rem;
  margin-top: 1rem;
  color: var(--color-fg-muted);
  font-size: 0.875rem;
  font-style: normal;
}

.hma-footer__bottom {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  border-top: 1px solid var(--color-hairline);
  padding-block: 2rem;
}

@media (min-width: 30rem) {
  .hma-footer__bottom {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}

.hma-footer__bottom p {
  margin: 0;
  color: var(--color-fg-subtle);
  font-size: 0.875rem;
}

.hma-footer__bottom a {
  color: var(--color-fg-muted);
  text-decoration: none;
  text-underline-offset: 4px;
  transition: color var(--duration-fast) var(--ease-out);
}

.hma-footer__bottom a:hover {
  color: var(--color-accent);
  text-decoration: underline;
}

/* ==========================================================================
   E. BODY BRIDGE — required, not cosmetic
   --------------------------------------------------------------------------
   Chrome alone cannot carry a theme switch honestly. Without this section a
   visitor flipping to light gets a light header and footer wrapped around a
   page whose own tokens are still the planner's fixed light palette (fine by
   accident) — and flipping to DARK gets a dark header and footer wrapped
   around a blinding white tool. The switch would be visibly broken the first
   time anyone used it.

   So the planner's own variables are re-pointed at the brand tokens. They are
   var() references, which means they follow the theme automatically and there
   is exactly one definition of each colour on the page.

   The mapping is one-way and deliberate:
     --brand-dark is the planner's "readable accent on a light ground", which
     is what --color-accent-ink is for; mapping it to --color-accent would put
     4.0:1 cyan on white in several places.
   ========================================================================== */

:root {
  --brand: var(--color-accent);
  --brand-dark: var(--color-accent-ink);
  --brand-soft: var(--color-accent-soft);
  --brand-glow: var(--color-accent-hover);
  --ink: var(--color-fg);
  --text: var(--color-fg-muted);
  --muted: var(--color-fg-subtle);
  --line: var(--color-hairline);
  --surface: var(--color-surface);
  --page: var(--color-bg);
  --danger: var(--color-danger);
  --success: var(--color-success);
  --shadow: var(--shadow-card);
  /* Matches the chrome's container so the tool and the nav share one left
     edge. styles.css had 1180px; the platform container is 82.5rem. */
  --max: var(--container-wide);
}

/* styles.css hardcodes #fff, #f8fbfb, #00393f and friends in a dozen places
   instead of reading a token. Each one below was found by walking the file,
   not guessed, and each is a place where the page would half-switch — text
   going light while the panel behind it stayed white. */
body {
  background: var(--page);
  color: var(--text);
}

.hero {
  background: var(--surface);
  border-bottom-color: var(--line);
}

.card,
.choice,
.searchbox,
.suggestions,
.suggestion,
.selectbox select,
.secondary {
  background: var(--surface);
}

.choice {
  color: var(--text);
}

.suggestion:hover,
.suggestion.active {
  background: var(--brand-soft);
}

.preview {
  background: var(--page);
}

.step {
  background: var(--line);
}

.step.active {
  background: var(--brand);
}

.bar {
  background: var(--line);
}

.chip {
  border-color: var(--color-accent-border);
}

.note {
  background: var(--color-surface-raised);
  color: var(--color-fg);
}

.note h3 {
  color: var(--color-fg);
}

.note p {
  color: var(--color-fg-muted);
}

/* Checkboxes and radios are EXCLUDED. Painting a background on a native
   checkbox is enough to make some engines draw the box themselves, and the
   planner's eight property-type boxes rendered as solid dark squares in light
   mode when this rule caught them. `accent-color` in styles.css is the right
   tool for those and already does the job. */
input:not([type='checkbox']):not([type='radio']),
select,
textarea {
  color: var(--ink);
  background: var(--surface);
  border-color: var(--line);
}

/* The tool's own primary/ghost buttons, so they match the header's. Scoped
   away from the chrome, which uses .hma-btn and is untouched by this. */
.primary {
  background: var(--color-accent);
  color: var(--color-accent-contrast);
  box-shadow: var(--shadow-accent-glow);
}

.primary:hover {
  background: var(--color-accent-hover);
}

.ghost {
  background: var(--color-surface);
  color: var(--color-accent-ink);
}

.secondary {
  color: var(--color-accent-ink);
  border-color: var(--color-accent-border);
}

/* ---- OPTIONAL: gutter alignment ---------------------------------------
   styles.css pads the hero and main with a fixed 24px while the chrome uses
   the platform's fluid gutter, so at 1440px the tool sits 16px left of the
   nav above it. Delete this block if you would rather keep the tool's own
   measure. */
.hero-inner,
main {
  padding-inline: var(--spacing-gutter);
}

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

/* ==========================================================================
   Desktop dropdown panels
   --------------------------------------------------------------------------
   THESE HAD NO STYLES AT ALL. index.html has shipped `.hma-nav__panel` and
   `.hma-nav__child` since the chrome was added, chrome.js toggles their
   `hidden` attribute, and nothing in this file ever matched them — so opening
   Solutions or Resources on a desktop viewport dropped an unstyled block of
   run-together link text over the page. Found while adding the language
   picker, which uses the same contract.

   Positioned against `.hma-nav__item`, which already sets position: relative.
   ========================================================================== */
.hma-nav__panel {
  position: absolute;
  top: calc(100% + 0.5rem);
  /* inset-inline-start, not left: in Arabic the panel has to hang from the
     trigger's leading edge, which is the right one. */
  inset-inline-start: 0;
  z-index: 100;
  width: max-content;
  max-width: min(24rem, calc(100vw - 2 * var(--spacing-gutter)));
  padding: 0.5rem;
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-lg, 0.75rem);
  background: var(--color-bg-raised, var(--color-bg));
  box-shadow: 0 16px 32px rgb(0 0 0 / 35%);
}

.hma-nav__panel[hidden] {
  display: none;
}

.hma-nav__panel-list {
  display: grid;
  gap: 0.125rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.hma-nav__child {
  display: grid;
  gap: 0.125rem;
  padding: 0.625rem 0.75rem;
  border-radius: var(--radius-md, 0.5rem);
  color: var(--color-fg);
  text-decoration: none;
}

.hma-nav__child:hover,
.hma-nav__child:focus-visible {
  background: var(--color-bg-subtle, rgb(127 127 127 / 12%));
}

.hma-nav__child-title {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.9375rem;
  font-weight: 600;
}

.hma-nav__child-title svg {
  width: 0.75rem;
  height: 0.75rem;
}

.hma-nav__child-desc {
  color: var(--color-fg-subtle, var(--color-fg-muted));
  font-size: 0.8125rem;
  line-height: 1.35;
}

/* The panel of the LAST nav item would otherwise overflow the viewport on a
   1024–1280 desktop, where the nav row ends close to the right edge. */
.hma-nav__item:last-child .hma-nav__panel {
  inset-inline-start: auto;
  inset-inline-end: 0;
}

/* ==========================================================================
   Language picker
   --------------------------------------------------------------------------
   Seventeen real anchors behind a button, not a <select>. A crawler follows
   anchors and does not fire a change event, so the seventeen URLs the hreflang
   block declares are exactly the seventeen a visitor can click.

   It carries `data-nav-trigger`, so chrome.js's existing dropdown behaviour —
   click to open, Escape to close, focusout to close, one panel at a time —
   applies with no new JavaScript. It sits in `.hma-header__actions` rather
   than in `.hma-nav`, which is why chrome.js's outside-click handler also
   checks for `.hma-lang`.
   ========================================================================== */
.hma-lang {
  position: relative;
  flex-shrink: 0;
}

.hma-lang__trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  height: 2.25rem;
  padding-inline: 0.625rem;
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--color-fg-muted);
  font-family: inherit;
  font-size: 0.875rem;
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition:
    color var(--duration-fast) var(--ease-out),
    border-color var(--duration-fast) var(--ease-out);
}

.hma-lang__trigger:hover {
  border-color: var(--color-fg-muted);
  color: var(--color-fg);
}

.hma-lang__flag {
  /* An emoji flag inherits the surrounding font's metrics and lands a pixel
     or two low against Latin text. */
  font-size: 1rem;
  line-height: 1;
}

/* THE TRIGGER SHOWS THE FLAG AND THE CHEVRON, NEVER THE ENDONYM, AND THAT IS
   A MEASUREMENT RATHER THAN A PREFERENCE.

   sites/housing-market-ads/src/components/language-switch.tsx shows the
   endonym from xl up and hides it below. The same rule was tried here, at
   90rem and then at 98rem, and it does not work — because this header is
   capped at `max-width: 1320px` with 40px gutters, so the row has a content
   box of 1240px NO MATTER HOW WIDE THE WINDOW IS. Past 1320 a wider viewport
   buys nothing at all.

   Measured on 2026-09-06 with the endonym shown, the row overflowed that box
   in eight languages at every width above the breakpoint — Malay by 114px,
   German 95, Greek 91, Vietnamese 74, French 55, Spanish 44, Brazilian
   Portuguese 38, Indonesian 15. There is no breakpoint that fixes that; the
   space does not exist.

   So the label is dropped in every language rather than in eight of the
   seventeen, which would be one control behaving two ways. The endonym is
   still what identifies each choice: it names all seventeen inside the panel,
   and the button's accessible name is "Language: Deutsch" — languageLabel in
   src/render.js. */

.hma-lang__panel {
  inset-inline-start: auto;
  inset-inline-end: 0;
  max-height: min(26rem, calc(100vh - 6rem));
  overflow-y: auto;
}

.hma-lang__list {
  display: grid;
  gap: 0.125rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.hma-lang__link {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  border-radius: var(--radius-md, 0.5rem);
  color: var(--color-fg);
  font-size: 0.9375rem;
  text-decoration: none;
  white-space: nowrap;
}

.hma-lang__link:hover,
.hma-lang__link:focus-visible {
  background: var(--color-bg-subtle, rgb(127 127 127 / 12%));
}

/* The language already in force. Marked visually as well as with
   aria-current, so the list does not offer seventeen equal choices. */
.hma-lang__link[aria-current='true'] {
  background: var(--color-bg-subtle, rgb(127 127 127 / 12%));
  font-weight: 600;
}

/* Inside the mobile panel the links are plain rows in the existing sublist;
   only the flag alignment is borrowed. */
.hma-mobile-nav__sublink.hma-lang__link {
  border-radius: 0;
  background: none;
}

/* ==========================================================================
   Right-to-left
   --------------------------------------------------------------------------
   Arabic is one of the seventeen and <html dir="rtl"> is set for it. Only the
   handful of rules below were still using physical sides; everything else in
   this file was already logical or symmetric. The chevron is not mirrored —
   a downward chevron means "opens downward" in every script.
   ========================================================================== */
.hma-skip {
  /* Was `left: 1rem`, which put the skip link at the far end of an RTL page,
     where it is the last thing a right-to-left reader looks for. */
  inset-inline-start: 1rem;
  left: auto;
}

.hma-mobile-nav__trigger {
  text-align: start;
}


/* ==========================================================================
   The desktop navigation gate, per language
   --------------------------------------------------------------------------
   The 74rem gate above was measured against ENGLISH. Six nav items translated
   into German are wider than six nav items in English, and the row overlaps
   Login again — silently, in a language nobody on the team reads, which is
   the exact class of fault this whole exercise exists to remove.

   Measured on this page at 2026-09-06, with the tightened nav rhythm below and
   the flag-only language trigger, as the viewport width at which
   lead.scrollWidth + actions + gap + gutters stops overflowing:

     zh-Hans 928   ar  946   zh-Hant 959   hi 1029   th 1136
     km     1144   id 1148   en     1163   pt-BR 1169
     ---- 74rem = 1184px, where the nine above fit ----
     ja 1197   tr 1205   es 1242   fr 1249
     vi 1256   ms 1263   el 1277   de 1290
     ---- 84rem = 1344px, 54px clear of the worst case ----

   The eight below therefore switch to the mobile panel 160px later. English is
   untouched at 1163, so nothing that fits today stops fitting.

   Widening the gate rather than truncating the nav is deliberate: the mobile
   panel carries every nav item, both call-to-action buttons and all seventeen
   languages, so a visitor between the two gates loses a row, not a route.

   REDO THE MEASUREMENT if a nav item is added, renamed or retranslated. The
   numbers are font-dependent and there is no test that can check them without
   a browser; test/render.test.js only checks that this list and the base tier
   together name all seventeen locales exactly once.
   ========================================================================== */
@media (min-width: 74rem) and (max-width: 83.999rem) {
  html[lang='de'] .hma-nav,
  html[lang='el'] .hma-nav,
  html[lang='es'] .hma-nav,
  html[lang='fr'] .hma-nav,
  html[lang='ja'] .hma-nav,
  html[lang='ms'] .hma-nav,
  html[lang='tr'] .hma-nav,
  html[lang='vi'] .hma-nav {
    display: none;
  }

  html[lang='de'] .hma-burger,
  html[lang='el'] .hma-burger,
  html[lang='es'] .hma-burger,
  html[lang='fr'] .hma-burger,
  html[lang='ja'] .hma-burger,
  html[lang='ms'] .hma-burger,
  html[lang='tr'] .hma-burger,
  html[lang='vi'] .hma-burger {
    display: inline-flex;
  }

  /* The mobile panel is hidden by the same 74rem rule above, and it is what
     the burger opens. */
  html[lang='de'] .hma-mobile-nav:not([hidden]),
  html[lang='el'] .hma-mobile-nav:not([hidden]),
  html[lang='es'] .hma-mobile-nav:not([hidden]),
  html[lang='fr'] .hma-mobile-nav:not([hidden]),
  html[lang='ja'] .hma-mobile-nav:not([hidden]),
  html[lang='ms'] .hma-mobile-nav:not([hidden]),
  html[lang='tr'] .hma-mobile-nav:not([hidden]),
  html[lang='vi'] .hma-mobile-nav:not([hidden]) {
    display: block;
  }
}

/* The nav rhythm, tightened from 1rem to 0.75rem of inline padding on each of
   the six items — 48px across the row.

   THIS IS WHAT MAKES THE TRANSLATED NAV FIT AT ALL. With 1rem padding the
   German row needs 1258px and the Greek row 1245px inside a content box that
   is 1240px at its widest, so those two languages could not have shown a
   desktop navigation at any window size. 0.75rem brings German to 1210 and
   Greek to 1197, both clear of the box.

   Applied in every language rather than only in the nine that need it: the
   same control spaced two ways in one product is a worse outcome than four
   pixels. */
.hma-nav__link {
  padding-inline: 0.75rem;
}
