/* HomeFind — app.css
 *
 * Single stylesheet organized with @layer. Design tokens are custom
 * properties; change the brand by editing the tokens layer only.
 *
 * The visual brief (docs/homefind_build.md §9): scratch-ticket glitz in the
 * chrome and the moments, spreadsheet discipline in the data. Jade ground,
 * gold foil accents, flamingo alerts. Price is the hero number. Tabular
 * numerals everywhere data columns must align — the least glamorous token
 * and the one that decides whether this is usable in daylight on a phone.
 */

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

@layer tokens {
  :root {
    --jade:       #0B6E5F;
    --jade-deep:  #063D35;
    --jade-dark:  #042923;
    --foil:       #E8B430;
    --foil-hi:    #FFE9A3;
    --flamingo:   #FF5E7A;
    --check:      #F7F3E8;
    --ink:        #10201D;
    --mint:       #8FE3C8;
    --muted:      rgb(247 243 232 / 55%);
    --line:       rgb(247 243 232 / 13%);

    --display: 'Big Shoulders Display', system-ui, sans-serif;
    --body:    'Space Grotesk', system-ui, sans-serif;

    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-6: 1.5rem;
    --space-8: 2rem;

    --radius: 14px;
    --shadow: 0 1px 0 rgb(255 255 255 / 7%) inset, 0 14px 32px rgb(0 0 0 / 40%);
    --maxw: 30rem;

    --tnum: "tnum" 1;
  }

  @font-face {
    font-family: 'Big Shoulders Display';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('/assets/fonts/big-shoulders-display.woff2') format('woff2');
  }
  @font-face {
    font-family: 'Space Grotesk';
    font-style: normal;
    font-weight: 300 700;
    font-display: swap;
    src: url('/assets/fonts/space-grotesk.woff2') format('woff2');
  }
}

@layer reset {
  *, *::before, *::after { box-sizing: border-box; }
  body, h1, h2, h3, h4, p, figure, blockquote, dl, dd { margin: 0; }
  img, svg, canvas { display: block; max-width: 100%; }
  button, input, select, textarea { font: inherit; color: inherit; }
  * { -webkit-tap-highlight-color: transparent; }
}

@layer base {
  html { color-scheme: dark; }
  body {
    font-family: var(--body);
    font-size: 1rem;
    line-height: 1.5;
    color: var(--check);
    background: var(--jade-dark);
    background-image:
      radial-gradient(ellipse 80% 50% at 50% -10%, rgb(232 180 48 / 14%), transparent 60%),
      repeating-linear-gradient(115deg, rgb(255 255 255 / 1.4%) 0 2px, transparent 2px 9px);
    background-attachment: fixed;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    overscroll-behavior-y: contain;
  }

  a { color: var(--foil); }

  :focus-visible { outline: 2px solid var(--foil); outline-offset: 2px; }

  .skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    background: var(--foil);
    color: var(--jade-dark);
    padding: var(--space-2) var(--space-4);
    z-index: 100;
  }
  .skip-link:focus { left: 0; }
}

@layer layout {
  .topbar {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    max-width: var(--maxw);
    width: 100%;
    margin: 0 auto;
    padding: var(--space-4) var(--space-4) 0;
  }
  .topbar__brand {
    font-family: var(--display);
    font-weight: 900;
    font-size: 1rem;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--foil);
    text-decoration: none;
    white-space: nowrap;
  }
  .topbar__brand em { font-style: normal; color: var(--check); opacity: 0.55; }

  /* Breadcrumb. The chevron is generated so the markup carries only the name,
     which keeps it out of the accessible name and out of a copied selection. */
  .topbar__crumb {
    font-family: var(--display);
    font-weight: 800;
    font-size: 0.85rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--check);
    opacity: 0.75;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .topbar__crumb::before {
    content: '\203A';
    margin-right: var(--space-2);
    opacity: 0.45;
    font-weight: 400;
  }
  .topbar__crumb:empty { display: none; }

  /* Only appears when the pull is late or failed; the normal reading lives in
     the menu. Sits next to the breadcrumb rather than claiming its own auto
     margin — two auto margins in one row split the free space between them and
     would strand this in the middle. */
  .topbar__stale {
    flex: 0 0 auto;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--jade-dark);
    background: var(--flamingo);
    border-radius: 100px;
    padding: 3px 8px;
  }

  .topbar__menu {
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    display: grid;
    place-items: center;
    background: none;
    border: 1px solid var(--line);
    border-radius: 9px;
    cursor: pointer;
    padding: 0;
  }
  .topbar__menu:hover { border-color: var(--flamingo); }
  .topbar__menu:focus-visible { outline: 2px solid var(--flamingo); outline-offset: 2px; }
  /* Three bars from one element: the box is the middle bar, the two
     pseudo-elements are the outer ones. */
  .topbar__bars,
  .topbar__bars::before,
  .topbar__bars::after {
    display: block;
    width: 16px;
    height: 2px;
    border-radius: 2px;
    background: var(--flamingo);
  }
  .topbar__bars { position: relative; }
  .topbar__bars::before, .topbar__bars::after { content: ''; position: absolute; left: 0; }
  .topbar__bars::before { top: -5px; }
  .topbar__bars::after { top: 5px; }

  /* Pushed to the right end of the row. The stale chip takes the same slot when
     it is showing, so the two sit side by side rather than fighting for it. */
  .account { position: relative; margin-left: auto; flex: 0 0 auto; }
  .account__btn {
    display: flex;
    align-items: center;
    gap: 6px;
    background: none;
    border: 1px solid var(--line);
    border-radius: 100px;
    color: var(--check);
    font-size: 0.78rem;
    padding: 5px 11px;
    cursor: pointer;
    opacity: 0.8;
    max-width: 9rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .account__btn:hover { opacity: 1; border-color: var(--flamingo); }
  .account__btn:focus-visible { outline: 2px solid var(--flamingo); outline-offset: 2px; }
  .account__caret {
    width: 0; height: 0;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 5px solid currentColor;
    opacity: 0.6;
    flex: 0 0 auto;
  }
  .account__btn[aria-expanded="true"] { border-color: var(--flamingo); opacity: 1; }
  .account__btn[aria-expanded="true"] .account__caret { transform: rotate(180deg); }

  .account__menu {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 50;
    min-width: 11rem;
    display: flex;
    flex-direction: column;
    background: var(--jade-deep);
    border: 1px solid var(--line);
    border-radius: 11px;
    padding: 5px;
    box-shadow: var(--shadow);
  }
  .account__item {
    text-align: left;
    background: none;
    border: none;
    color: var(--check);
    font-size: 0.82rem;
    padding: 9px 11px;
    border-radius: 7px;
    cursor: pointer;
    white-space: nowrap;
  }
  .account__item:hover { background: rgb(255 94 122 / 13%); color: var(--flamingo); }
  .account__item:focus-visible { outline: 2px solid var(--flamingo); outline-offset: -2px; }
  .account__item.is-active { color: var(--flamingo); font-weight: 700; }
  .account__item--out {
    margin-top: 4px;
    padding-top: 11px;
    border-top: 1px solid var(--line);
    border-radius: 0 0 7px 7px;
    opacity: 0.75;
  }

  .topbar__nav { display: flex; align-items: center; gap: var(--space-3); }
  .topbar__user { font-size: 0.8rem; opacity: 0.6; }
  .topbar__signout {
    background: none;
    border: 1px solid var(--line);
    color: var(--check);
    font-size: 0.75rem;
    padding: 5px 12px;
    border-radius: 100px;
    cursor: pointer;
    opacity: 0.7;
  }
  .topbar__signout:hover { opacity: 1; border-color: var(--foil); }

  .main {
    flex: 1;
    width: 100%;
    max-width: var(--maxw);
    margin: 0 auto;
    padding: var(--space-4) var(--space-4) 4rem;
  }

  .footer {
    max-width: var(--maxw);
    width: 100%;
    margin: 0 auto;
    padding: var(--space-4);
    font-size: 0.75rem;
    opacity: 0.35;
  }
}

@layer components {
  /* ---------- view tabs ---------- */
  /* Wrap, never scroll: a hidden-scrollbar horizontal row is unreachable
     with a mouse, which cost the Settings tab on first desktop test. */
  /* Collapsed by default and opened from the topbar. Eleven destinations wrapped
     to two rows and sat above every screen alongside the freshness bar, which
     cost roughly a third of a phone viewport before the first listing. */
  .views {
    background: var(--jade-deep);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: var(--space-3);
    margin: var(--space-3) 0 var(--space-4);
    box-shadow: var(--shadow);
  }
  .views__tabs {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
  }
  .views__foot {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
    margin-top: var(--space-3);
    padding-top: var(--space-3);
    border-top: 1px solid var(--line);
    font-size: 0.75rem;
  }
  .views__updated { opacity: 0.55; }
  .views__tab {
    flex: 0 0 auto;
    font-family: var(--display);
    font-weight: 800;
    font-size: 0.8rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--muted);
    background: none;
    border: 1px solid var(--line);
    border-radius: 100px;
    padding: 7px 14px;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s, background 0.15s;
  }
  .views__tab:hover { color: var(--check); }
  .views__tab.is-active {
    color: var(--jade-dark);
    background: var(--foil);
    border-color: var(--foil);
  }
  .views__tab .views__count {
    font-family: var(--body);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    margin-left: 5px;
    opacity: 0.75;
  }

  /* ---------- staleness banner ---------- */
  .staleness {
    font-size: 0.8rem;
    padding: var(--space-2) var(--space-3);
    border-radius: 9px;
    background: rgb(247 243 232 / 7%);
    opacity: 0.75;
  }
  .staleness.is-stale {
    background: rgb(255 94 122 / 14%);
    color: var(--flamingo);
    opacity: 1;
  }

  /* ---------- listing card (ticket) ---------- */
  .card {
    position: relative;
    background: var(--jade-deep);
    border-radius: var(--radius);
    margin-bottom: var(--space-4);
    overflow: hidden;
    box-shadow: var(--shadow);
  }
  /* perforated ticket edge */
  .card::before, .card::after {
    content: '';
    position: absolute;
    left: 0; right: 0;
    height: 9px;
    background-image: radial-gradient(circle at 5px 0, var(--jade-dark) 4.2px, transparent 4.4px);
    background-size: 14px 9px;
    z-index: 4;
    pointer-events: none;
  }
  .card::before { top: -1px; }
  .card::after { bottom: -1px; transform: rotate(180deg); }

  .card.is-dimmed { opacity: 0.55; }
  .card.is-archived { filter: saturate(0.4); }

  .card__photo {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    background: var(--jade-dark);
  }
  /* One line instead of a reserved 16:9 block. Every listing lacks a photo
     until GOOGLE_MAPS_KEY is set, and 300 placeholder tiles is most of a
     phone's scrolling spent on nothing. */
  .card__nophoto {
    padding: var(--space-3) var(--space-4);
    background: var(--jade-dark);
    color: var(--muted);
    font-size: 0.85rem;
    letter-spacing: 0.01em;
  }

  .card__face { padding: var(--space-4) var(--space-4) var(--space-4); }

  .card__addr {
    font-family: var(--display);
    font-weight: 800;
    font-size: 1.55rem;
    line-height: 1;
    letter-spacing: 0.005em;
    text-transform: uppercase;
  }
  .card__addr a { color: inherit; text-decoration: none; }
  .card__town {
    font-size: 0.72rem;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    opacity: 0.5;
    margin-top: 6px;
  }

  /* Price is the hero — treated the way a novelty check treats an amount. */
  .card__price {
    font-family: var(--display);
    font-weight: 900;
    font-size: 2.7rem;
    line-height: 1;
    color: var(--foil);
    font-variant-numeric: tabular-nums;
    font-feature-settings: var(--tnum);
    margin-top: var(--space-3);
  }
  .card__drop {
    display: inline-block;
    margin-left: 9px;
    vertical-align: 6px;
    font-family: var(--body);
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--flamingo);
    letter-spacing: 0.03em;
  }

  .card__specs {
    display: flex;
    gap: var(--space-4);
    margin-top: var(--space-3);
    font-size: 0.8rem;
    font-variant-numeric: tabular-nums;
    font-feature-settings: var(--tnum);
  }
  .card__specs div { opacity: 0.78; }
  .card__specs b { font-weight: 700; }
  .card__specs .dom {
    margin-left: auto;
    opacity: 0.42;
    font-size: 0.7rem;
    letter-spacing: 0.07em;
    text-transform: uppercase;
  }

  /* ---------- score zone: plain or scratch ---------- */
  .zone {
    position: relative;
    margin-top: var(--space-3);
    border-radius: 11px;
    overflow: hidden;
    background: var(--jade-dark);
  }
  .zone--scratch { height: 126px; }
  .zone__under {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: var(--space-3);
  }
  .zone--scratch .zone__under { position: absolute; inset: 0; }

  .score {
    font-family: var(--display);
    font-weight: 900;
    font-size: 3.2rem;
    line-height: 0.85;
    color: var(--foil);
    font-variant-numeric: tabular-nums;
    font-feature-settings: var(--tnum);
    text-shadow: 0 0 34px rgb(232 180 48 / 40%);
  }
  .score i {
    font-style: normal;
    font-size: 1.3rem;
    vertical-align: 14px;
    margin-left: 2px;
    opacity: 0.72;
  }
  .score.is-low { color: #8FA8A0; text-shadow: none; }

  .chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    justify-content: center;
  }
  .chip {
    font-size: 0.68rem;
    font-weight: 500;
    letter-spacing: 0.02em;
    padding: 4px 10px;
    border-radius: 100px;
    background: rgb(247 243 232 / 9%);
  }
  .chip--hit { color: var(--mint); background: rgb(143 227 200 / 11%); }
  .chip--miss { color: var(--flamingo); background: rgb(255 94 122 / 11%); opacity: 0.82; }
  .chip--dealbreaker { color: var(--jade-dark); background: var(--flamingo); font-weight: 700; }

  .zone canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    touch-action: none;
    cursor: grab;
    z-index: 2;
  }
  .zone canvas:active { cursor: grabbing; }
  .zone canvas.is-gone { display: none; }

  /* ---------- flags row ---------- */
  .card__flags {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-top: var(--space-3);
    font-size: 0.78rem;
  }
  .card__flag { opacity: 0.85; }
  .card__flag b { font-weight: 700; }
  .card__flag .stars { color: var(--foil); letter-spacing: 1px; }
  .card__notecount {
    margin-left: auto;
    background: none;
    border: none;
    color: var(--muted);
    font-size: 0.78rem;
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 3px;
  }

  /* ---------- actions ---------- */
  .card__acts {
    display: flex;
    gap: var(--space-2);
    padding: 0 var(--space-4) var(--space-4);
  }
  .card__acts button {
    flex: 1;
    font-size: 0.78rem;
    font-weight: 500;
    padding: 11px 0;
    border-radius: 9px;
    cursor: pointer;
    background: rgb(247 243 232 / 8%);
    color: var(--check);
    border: 1px solid var(--line);
    transition: background 0.16s, transform 0.12s;
  }
  .card__acts button:hover { background: rgb(247 243 232 / 15%); }
  .card__acts button:active { transform: scale(0.97); }
  .card__acts .is-on {
    background: var(--foil);
    color: var(--jade-dark);
    border-color: var(--foil);
    font-weight: 700;
  }
  .card__acts .act-reject.is-on {
    background: rgb(255 94 122 / 85%);
    border-color: var(--flamingo);
    color: #fff;
  }

  /* scratch cards reveal their actions only after the reveal */
  .card--scratch .card__acts,
  .card--scratch .card__flags {
    opacity: 0;
    max-height: 0;
    padding-top: 0;
    padding-bottom: 0;
    overflow: hidden;
    transition: opacity 0.34s ease 0.12s, max-height 0.34s ease, padding 0.34s ease;
  }
  .card--scratch.is-done .card__acts { opacity: 1; max-height: 70px; padding-bottom: var(--space-4); }
  .card--scratch.is-done .card__flags { opacity: 1; max-height: 40px; }

  .card__links {
    display: flex;
    /* Six items need about 398px and a 390px phone gives the card 358px, so
       without wrapping the last links are pushed off the card edge. Adding the
       Map link made an existing overflow worse rather than causing it. */
    flex-wrap: wrap;
    row-gap: 6px;
    gap: var(--space-2);
    padding: 0 var(--space-4) var(--space-4);
    font-size: 0.72rem;
  }
  .card__links a, .card__links button {
    color: var(--muted);
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 3px;
  }
  .card__links a:hover, .card__links button:hover { color: var(--foil); }

  /* ---------- empty states ---------- */
  .empty {
    text-align: center;
    padding: var(--space-8) var(--space-4);
    opacity: 0.6;
    font-size: 0.95rem;
    line-height: 1.6;
  }

  .bar {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
    padding-top: var(--space-2);
    border-top: 1px solid var(--line);
  }
  .bar__count {
    font-family: var(--display);
    font-weight: 800;
    font-size: 0.8rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    opacity: 0.55;
  }
  .bar__action {
    margin-left: auto;
    background: none;
    font-size: 0.78rem;
    font-weight: 500;
    color: var(--foil);
    border: 1px solid rgb(232 180 48 / 42%);
    padding: 7px 14px;
    border-radius: 100px;
    cursor: pointer;
    transition: background 0.18s, border-color 0.18s;
  }
  .bar__action:hover { background: rgb(232 180 48 / 11%); border-color: var(--foil); }

  /* ---------- environment badge ----------
     Marks every non-production environment, so a tab or a screenshot in a bug
     report identifies itself. Non-interactive and aria-hidden, so it cannot get
     in the way of the page.

     These rules were in the scaffold and were dropped when 3f75cb4 rewrote this
     file; the partial kept rendering, so the badge became unstyled text at the
     foot of the document rather than disappearing outright. Restored on the left
     because the back-to-top button now occupies the bottom right. */
  .env-badge {
    position: fixed;
    inset-block-end: calc(1rem + env(safe-area-inset-bottom, 0px));
    inset-inline-start: 1rem;
    z-index: 2000;
    pointer-events: none;
    display: flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.5rem 0.75rem;
    border-radius: 999px;
    background: var(--env-badge-color, var(--flamingo));
    color: #fff;
    font: 700 0.72rem/1 ui-monospace, SFMono-Regular, Menlo, monospace;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    box-shadow: 0 8px 20px -6px rgb(0 0 0 / 55%);
  }
  .env-badge__dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #fff;
    opacity: 0.85;
  }
  @media print {
    .env-badge { display: none; }
  }

  /* ---------- back to top ---------- */
  .totop {
    position: fixed;
    right: var(--space-4);
    /* Clears the iOS home indicator and any Android gesture bar; without the
       safe-area inset the button sits under them on a phone. */
    bottom: calc(var(--space-4) + env(safe-area-inset-bottom, 0px));
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--jade-deep);
    border: 1px solid rgb(232 180 48 / 42%);
    color: var(--foil);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    /* Under .detail (z-index 40) so the detail sheet covers it. */
    z-index: 30;
    box-shadow: var(--shadow);
    display: grid;
    place-items: center;
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 0.2s ease, transform 0.2s ease, border-color 0.16s;
  }
  .totop.is-on { opacity: 1; transform: translateY(0); }
  .totop:hover { border-color: var(--foil); background: rgb(232 180 48 / 14%); }
  .totop:focus-visible { outline: 2px solid var(--foil); outline-offset: 2px; }
  @media (prefers-reduced-motion: reduce) {
    .totop { transition: none; transform: none; }
    .totop.is-on { transform: none; }
  }

  .topbar__help {
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 1px solid var(--line);
    background: none;
    color: var(--flamingo);
    font-family: var(--display);
    font-weight: 800;
    font-size: 0.9rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.75;
    padding: 0;
  }
  .topbar__help:hover { opacity: 1; border-color: var(--flamingo); }
  .topbar__help:focus-visible { outline: 2px solid var(--flamingo); outline-offset: 2px; }
  .topbar__help.is-active { border-color: var(--flamingo); opacity: 1; }

  /* ---------- help centre ---------- */
  .help__title {
    font-family: var(--display);
    font-weight: 900;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    font-size: 1.3rem;
    margin-bottom: var(--space-3);
  }
  .help__list { list-style: none; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
  .help__list button {
    width: 100%;
    text-align: left;
    background: var(--jade-deep);
    border: 1px solid var(--line);
    border-radius: 11px;
    padding: var(--space-3);
    cursor: pointer;
    display: flex;
    flex-direction: column;
    gap: 3px;
  }
  .help__list button:hover { border-color: var(--flamingo); }
  .help__name { font-weight: 700; color: var(--check); }
  .help__sum { font-size: 0.8rem; opacity: 0.6; }
  .help__back {
    background: none;
    border: none;
    color: var(--flamingo);
    cursor: pointer;
    padding: 0 0 var(--space-2);
    font-size: 0.8rem;
  }
  .help__body { line-height: 1.65; }
  .help__body h3 {
    font-family: var(--display);
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font-size: 0.95rem;
    color: var(--foil);
    margin: var(--space-6) 0 var(--space-2);
  }
  .help__body h4 { font-size: 0.9rem; margin: var(--space-4) 0 var(--space-2); }
  .help__body p { margin-bottom: var(--space-3); }
  .help__body ul, .help__body ol { margin: 0 0 var(--space-3) 1.15rem; padding: 0; }
  .help__body li { margin-bottom: var(--space-2); }
  .help__body strong { color: var(--check); font-weight: 700; }
  .help__body code {
    font-size: 0.85em;
    background: var(--jade-dark);
    padding: 1px 5px;
    border-radius: 4px;
  }
  .help__body a[data-guide] { color: var(--flamingo); cursor: pointer; }
  .help__meta { font-size: 0.72rem; opacity: 0.45; margin-top: var(--space-6); }

  /* ---------- filter + sort controls ---------- */
  .controls {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin-bottom: var(--space-4);
    padding-bottom: var(--space-3);
    border-bottom: 1px solid var(--line);
  }
  .controls__row { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
  .controls__sort, .controls__num {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    opacity: 0.6;
  }
  .controls select {
    background: var(--jade-deep);
    border: 1px solid var(--line);
    border-radius: 7px;
    color: var(--check);
    padding: 5px 8px;
    font-size: 0.8rem;
    text-transform: none;
    letter-spacing: normal;
    opacity: 1;
  }
  .controls__dash { opacity: 0.4; font-size: 0.8rem; }
  .controls__num--bare { gap: 0; }
  .visually-hidden {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .controls__count {
    margin-left: auto;
    font-family: var(--display);
    font-weight: 800;
    font-size: 0.75rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    opacity: 0.55;
  }
  .controls__clear {
    background: none;
    border: 1px solid rgb(232 180 48 / 42%);
    color: var(--foil);
    border-radius: 100px;
    padding: 4px 11px;
    font-size: 0.72rem;
    cursor: pointer;
  }
  /* Town chips scroll sideways in their own track rather than wrapping into a
     tall block: a 5-mile circle spans a dozen towns, and letting them wrap
     pushed the first listing below the fold on a phone. */
  .controls__chips {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: thin;
    padding-bottom: 4px;
    margin: 0 calc(var(--space-4) * -1);
    padding-left: var(--space-4);
    padding-right: var(--space-4);
  }
  /* Named apart from the score chips on the cards. Both were called .chip, and
     this block sits later in the file, so it was overriding .chip--miss and
     .chip--hit — which is how the no-match badges lost their pink. */
  .townchip {
    flex: 0 0 auto;
    background: var(--jade-deep);
    border: 1px solid var(--line);
    color: var(--check);
    border-radius: 100px;
    padding: 5px 11px;
    font-size: 0.76rem;
    cursor: pointer;
    white-space: nowrap;
    transition: border-color 0.16s, background 0.16s;
  }
  .townchip:hover { border-color: var(--flamingo); }
  .townchip.is-on { border-color: var(--flamingo); background: rgb(255 94 122 / 15%); color: var(--flamingo); }
  .townchip__n { opacity: 0.5; font-variant-numeric: tabular-nums; margin-left: 3px; }

  /* ---------- detail sheet ---------- */
  .detail {
    position: fixed;
    inset: 0;
    background: rgb(4 41 35 / 88%);
    backdrop-filter: blur(3px);
    z-index: 40;
    overflow-y: auto;
    padding: var(--space-4);
  }
  .detail__inner {
    max-width: var(--maxw);
    margin: 0 auto;
    background: var(--jade-deep);
    border-radius: var(--radius);
    padding: var(--space-4);
    box-shadow: var(--shadow);
  }
  .detail__close {
    float: right;
    background: none;
    border: 1px solid var(--line);
    color: var(--check);
    border-radius: 100px;
    width: 34px;
    height: 34px;
    cursor: pointer;
  }
  .detail h2 {
    font-family: var(--display);
    font-weight: 800;
    text-transform: uppercase;
    font-size: 1.4rem;
    line-height: 1;
  }
  .detail h3 {
    font-family: var(--display);
    font-weight: 800;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    font-size: 0.85rem;
    margin: var(--space-4) 0 var(--space-2);
    opacity: 0.7;
  }

  .note {
    padding: var(--space-2) 0;
    border-bottom: 1px solid var(--line);
    font-size: 0.88rem;
  }
  .note__meta { font-size: 0.7rem; opacity: 0.5; margin-top: 3px; }
  .note--private .note__meta::after { content: ' · private'; color: var(--foil); }

  .notebox { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-3); }
  .notebox textarea {
    background: var(--jade-dark);
    border: 1px solid var(--line);
    border-radius: 9px;
    color: var(--check);
    padding: var(--space-2) var(--space-3);
    min-height: 70px;
    resize: vertical;
  }
  .notebox__row { display: flex; align-items: center; gap: var(--space-3); }
  .notebox__row label { font-size: 0.78rem; opacity: 0.7; display: flex; gap: 6px; align-items: center; }

  /* Enrichment renders visually distinct from RentCast data, always labeled
     advisory — an AI paragraph must never read as a structured field. */
  .enrich {
    margin-top: var(--space-3);
    border: 1px dashed rgb(232 180 48 / 45%);
    border-radius: 9px;
    padding: var(--space-3);
    font-size: 0.85rem;
  }
  .enrich__label {
    font-size: 0.65rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--foil);
    margin-bottom: var(--space-2);
  }
  .enrich__topic { margin-top: var(--space-2); }
  .enrich__topic b { text-transform: capitalize; }
  .enrich__sources { font-size: 0.7rem; opacity: 0.65; word-break: break-all; }

  /* ---------- price history ---------- */
  .history { font-variant-numeric: tabular-nums; font-feature-settings: var(--tnum); font-size: 0.85rem; }
  .history li { display: flex; justify-content: space-between; padding: 3px 0; opacity: 0.85; }

  /* ---------- forms (login, criteria) ---------- */
  .field { display: flex; flex-direction: column; gap: 5px; }
  .field__label { font-size: 0.72rem; letter-spacing: 0.1em; text-transform: uppercase; opacity: 0.6; }
  .field__input, .field select, .criteria-form input, .criteria-form select {
    background: var(--jade-dark);
    border: 1px solid var(--line);
    border-radius: 9px;
    color: var(--check);
    padding: 10px 12px;
  }

  .btn {
    background: rgb(247 243 232 / 10%);
    color: var(--check);
    border: 1px solid var(--line);
    border-radius: 9px;
    padding: 12px;
    font-weight: 500;
    cursor: pointer;
  }
  .btn--gold {
    background: var(--foil);
    color: var(--jade-dark);
    border-color: var(--foil);
    font-weight: 700;
  }
  .btn--gold:hover { background: var(--foil-hi); }
  .btn--danger { color: var(--flamingo); border-color: rgb(255 94 122 / 40%); background: none; }

  .login {
    max-width: 22rem;
    margin: 12vh auto 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
  }
  .login__title {
    font-family: var(--display);
    font-weight: 900;
    font-size: 3rem;
    line-height: 0.9;
    text-transform: uppercase;
  }
  .login__title em { font-style: normal; color: var(--foil); }
  .login__sub { opacity: 0.6; font-size: 0.9rem; }
  .login__form { display: flex; flex-direction: column; gap: var(--space-3); }
  .login__fallback summary { font-size: 0.8rem; opacity: 0.6; cursor: pointer; }
  .login__fallback { display: flex; flex-direction: column; gap: var(--space-3); }
  .login__hint { font-size: 0.75rem; opacity: 0.5; line-height: 1.5; }
  .login__error { color: var(--flamingo); font-size: 0.85rem; }

  /* ---------- criteria screen ---------- */
  .criteria-list { display: flex; flex-direction: column; gap: var(--space-2); }
  .criterion {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    background: var(--jade-deep);
    border-radius: 9px;
    padding: var(--space-2) var(--space-3);
    font-size: 0.85rem;
  }
  .criterion.is-inactive { opacity: 0.45; }
  .criterion__label { font-weight: 700; min-width: 0; overflow-wrap: anywhere; }
  /* The rule gets its own full-width line below the label and controls. A
     zip_code list renders as one unbroken 60-character token, and a flex child
     will not shrink below its content, so on a single line it drove the weight
     and both buttons past the edge of the 30rem column — the row looked
     truncated and the criterion below it was pushed out of view entirely. */
  .criterion__rule {
    opacity: 0.6;
    font-size: 0.75rem;
    font-variant-numeric: tabular-nums;
    flex: 1 0 100%;
    order: 10;
    min-width: 0;
    overflow-wrap: anywhere;
  }
  .criterion__weight {
    margin-left: auto;
    font-family: var(--display);
    font-weight: 800;
    color: var(--foil);
    font-size: 1rem;
  }
  .criterion__db {
    font-size: 0.6rem;
    letter-spacing: 0.1em;
    color: var(--jade-dark);
    background: var(--flamingo);
    border-radius: 100px;
    padding: 2px 7px;
    text-transform: uppercase;
    font-weight: 700;
  }
  .criterion button { background: none; border: none; color: var(--muted); cursor: pointer; }
  .criteria-form {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-2);
    background: var(--jade-deep);
    border-radius: var(--radius);
    padding: var(--space-3);
    margin-top: var(--space-4);
  }
  .criteria-form .span2 { grid-column: span 2; }
  .criteria-form label { font-size: 0.72rem; opacity: 0.7; display: flex; flex-direction: column; gap: 4px; }
  .criteria-form .row { flex-direction: row; align-items: center; gap: 8px; }

  /* ---------- chat (Ask David) ---------- */
  .chat { display: flex; flex-direction: column; gap: var(--space-3); }
  .chat__log { display: flex; flex-direction: column; gap: var(--space-2); }
  .msg {
    max-width: 88%;
    padding: var(--space-2) var(--space-3);
    border-radius: 12px;
    font-size: 0.9rem;
    white-space: pre-wrap;
  }
  .msg--user { align-self: flex-end; background: rgb(232 180 48 / 16%); }
  .msg--assistant { align-self: flex-start; background: var(--jade-deep); }
  .msg--assistant::before {
    content: 'DAVID';
    display: block;
    font-family: var(--display);
    font-weight: 800;
    font-size: 0.6rem;
    letter-spacing: 0.2em;
    color: var(--foil);
    margin-bottom: 4px;
  }
  .chat__composer { display: flex; gap: var(--space-2); }
  .chat__composer textarea {
    flex: 1;
    background: var(--jade-dark);
    border: 1px solid var(--line);
    border-radius: 9px;
    color: var(--check);
    padding: 10px 12px;
    min-height: 44px;
    max-height: 140px;
    resize: none;
  }
  .chat__spend { font-size: 0.7rem; opacity: 0.45; }

  .setting-range {
    display: flex;
    flex-direction: column;
    gap: 6px;
    font-size: 0.85rem;
    margin-top: var(--space-3);
  }
  .setting-range b { color: var(--foil); font-variant-numeric: tabular-nums; }
  .setting-range input[type="range"] { accent-color: var(--foil); width: 100%; }

  /* ---------- settings ---------- */
  .settings { display: flex; flex-direction: column; gap: var(--space-4); }
  .settings section {
    background: var(--jade-deep);
    border-radius: var(--radius);
    padding: var(--space-4);
  }
  .settings h3 {
    font-family: var(--display);
    font-weight: 800;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    font-size: 0.85rem;
    margin-bottom: var(--space-2);
  }
  .passkey-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: var(--space-2) 0;
    border-bottom: 1px solid var(--line);
    font-size: 0.85rem;
  }

  /* ---------- confetti ---------- */
  #confetti {
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 99;
    display: none;
  }

  .toast {
    position: fixed;
    left: 50%;
    bottom: 20px;
    transform: translateX(-50%);
    background: var(--foil);
    color: var(--jade-dark);
    font-weight: 700;
    font-size: 0.85rem;
    padding: 10px 18px;
    border-radius: 100px;
    z-index: 60;
    box-shadow: 0 8px 24px rgb(0 0 0 / 40%);
  }
  .toast--plain { background: var(--jade-deep); color: var(--check); font-weight: 500; }
}

@layer utilities {
  [hidden] { display: none !important; }
  .muted { opacity: 0.55; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation: none !important;
    transition-duration: 0.01ms !important;
  }
}
