/* ══ THE JOB BOARD'S SHEET ══════════════════════════════════════════════ 14 Oct 2026 (rp139) ══
   Moved out of browse-tradesperson.html whole, in its place in the cascade, so the board and the trade's Saved
   jobs (saved-tradesperson.html) draw the same card, the same grid and the same frame from one sheet. Sir, 14 Oct
   2026: Saved's cards should look "exactly like it does on the search results page". Nothing in it changed in the
   move but the one picture's address (relative to this file now).

   rp143 (14 Oct 2026): Sir, of the board: "browse-tradesperson should look exactly like the results page on the search
   page. So the cards look slightly different ... it just needs to look exactly the same." This sheet was Find a
   trade's sheet with a trade theme laid over it (5 Sep: a navy masthead and bar, the ground half a tone down, navy
   "evening" cards with a navy caption band). The theme is taken off, so the board and Saved are Find a trade's page
   and card: the cream masthead over the photograph, the cream bar, the square photograph with its caption on the
   page under it. What stays is what is true of jobs and not of listings: the green payment protection chip, a job's
   own words where it has no photographs, and "For tradespeople" said in the bar. Find a trade's later fixes to the
   shared card come across (the chip box, the kept bookmark, the distance chip, the score's count). */
  :root {
    /* Norm-derived type stack. Libre Caslon stands in for Adobe Caslon
       until the licence decision is made; Inter for all sans. */
    --serif: 'Libre Caslon Text', Georgia, 'Times New Roman', serif;
    --serif-display: 'Libre Caslon Display', 'Libre Caslon Text', Georgia, serif;
    --sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

    --cream: #FAF8F3;
    --cream-2: #F3EFE4;
    --cream-3: #EFE8D4;
    --navy: #0A1628;
    --navy-2: #152238;
    --navy-3: #1C2D45;
    --ink: #1B2638;

    /* ONE left edge for this page. The masthead was at 51px while the filter
       bar and the grid were at 26px, so the wordmark sat indented relative to
       everything under it. Every band now reads from this. */
    --edge: clamp(16px, 1.6vw, 28px);
    --muted: #636976;
    --line: #E6E0D0;
    --line-2: #D8CFB8;
    --green: #0F5A4F;
    --green-2: #0B3F37;
    --gold: #83632C;
    --gold-soft: #D4A943;
    --danger: #C0392B;
  }
  * { box-sizing: border-box; }
  :focus-visible { outline: 2px solid var(--green); outline-offset: 2px; border-radius: 2px; }
  :focus:not(:focus-visible) { outline: none; }
  input:focus, textarea:focus, select:focus { border-color: var(--green); box-shadow: 0 0 0 3px rgba(15,90,79,0.08); }
  * { transition: background-color 200ms ease, color 200ms ease, border-color 200ms ease, box-shadow 200ms ease; }
  html, body { margin: 0; padding: 0; }
  html { scroll-behavior: smooth; scrollbar-width: thin; scrollbar-color: #D8CFB8 transparent; }
  *::-webkit-scrollbar { width: 8px; height: 8px; }
  *::-webkit-scrollbar-track { background: transparent; }
  *::-webkit-scrollbar-thumb { background: #D8CFB8; border-radius: 8px; border: 2px solid transparent; background-clip: padding-box; }
  *::-webkit-scrollbar-thumb:hover { background: #C8BFA0; background-clip: padding-box; }
  *::-webkit-scrollbar-corner { background: transparent; }
  body {
    background: var(--cream);
    color: var(--ink);
    font-family: var(--sans);
    font-weight: 400;
    -webkit-font-smoothing: antialiased;
    font-feature-settings: "ss01", "cv11";
  }
  a { color: inherit; text-decoration: none; }
  button { font-family: inherit; cursor: pointer; border: 0; background: none; }

  .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }

  /* ── Topbar ── */
  /* Masthead, brand-identity 3.2a. 74px, and ONE type size across the whole
     row: the wordmark was 24px Caslon against 13px nav links, which is the
     thing Norm never does. */
  .topbar {
    position: sticky; top: 0; z-index: 100;
    height: 74px;
    background: rgba(250,248,243,0.94);
    backdrop-filter: blur(14px) saturate(1.15);
    -webkit-backdrop-filter: blur(14px) saturate(1.15);
    border-bottom: 1px solid var(--line);
  }
  .topbar-inner {
    position: relative; height: 100%;
    padding: 0 var(--edge);
    display: flex; align-items: center; justify-content: space-between;
  }

  .brand { display: flex; align-items: center; gap: 11px; }
  .brand { display: inline-flex; align-items: center; gap: 11px; }
  .brand .mark { width: 16px; height: 16px; flex: none; }
  .brand .word {
    font-family: var(--sans); font-size: 11px; font-weight: 500;
    letter-spacing: .26em; text-transform: uppercase; color: var(--navy); line-height: 1;
  }
  /* Centred on the viewport, as on the homepage. Safe to absolutely centre
     because the nav and the compact pill are never visible together. */
  .nav {
    position: absolute; left: 50%; transform: translateX(-50%);
    display: flex; gap: 30px; align-items: center;
  }
  .nav > a {
    position: relative; font-family: var(--sans); font-size: 11px; font-weight: 400;
    letter-spacing: 2px; text-transform: uppercase; color: var(--navy);
    opacity: .88; transition: opacity 180ms ease;
  }
  .nav > a::after { content: ''; position: absolute; bottom: -6px; left: 0; right: 0; height: 1px; background: var(--navy); transform: scaleX(0); transform-origin: center; transition: transform .28s cubic-bezier(.25,.1,.25,1); }
  .nav > a:hover { opacity: 1; }
  .nav > a:hover::after { transform: scaleX(1); }
  .nav > a.nav-accent { color: var(--gold, #83632C); opacity: 1; font-weight: 600; }
  .nav > a.nav-accent:hover { color: #c49b35; }

  /* Auth buttons */
  .cta-row { display: flex; gap: 10px; align-items: center; }
  .btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    padding: 11px 20px; border-radius: 10px; font-size: 14px; font-weight: 500;
    border: 1px solid transparent; transition: all 180ms ease;
  }
  .btn-primary { background: transparent; color: var(--navy); border: 1.5px solid var(--navy); }
  .btn-primary:hover { background: var(--navy); color: var(--cream); transform: translateY(-1px); }
  .btn-ghost { background: transparent; color: var(--navy); border-color: var(--line); }
  .btn-ghost:hover { border-color: var(--navy); }

  /* Auth icons */
  .topbar-right { display: flex; gap: 18px; align-items: center; }
  .icon-button { position: relative; background: none; border: none; cursor: pointer; padding: 0; width: 38px; height: 38px; display: flex; align-items: center; justify-content: center; border-radius: 8px; transition: background 160ms; }
  .icon-button:hover { background: var(--cream-2); }
  .icon-button svg { width: 20px; height: 20px; stroke: var(--ink); stroke-width: 1.8; fill: none; }
  .icon-badge { position: absolute; top: 2px; right: 2px; width: 16px; height: 16px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 9px; font-weight: 700; color: white; border: 2px solid rgba(250,248,243,0.92); }
  .icon-badge.green { background: var(--green); }
  .icon-badge.gold { background: var(--gold-soft);  color: var(--navy, #0A1628); }
  .avatar-btn { display: flex; align-items: center; gap: 6px; cursor: pointer; border: none; background: none; padding: 4px; border-radius: 24px; transition: background 180ms; }
  .avatar-btn:hover { background: rgba(10,22,40,0.05); }
  .avatar-btn .av-img { width: 36px; height: 36px; border-radius: 50%; background: linear-gradient(135deg, var(--green), var(--green-2)); display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 600; color: white; border: 2px solid transparent; transition: border-color 200ms; overflow: hidden; flex-shrink: 0; }
  .avatar-btn:hover .av-img { border-color: var(--green); }
  .avatar-btn .av-img img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
  .avatar-btn .av-chevron { width: 14px; height: 14px; stroke: var(--muted); fill: none; stroke-width: 2.2; transition: transform 180ms, stroke 180ms; }
  .avatar-btn:hover .av-chevron { stroke: var(--navy); }
  .pd-av img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }

  /* Profile drawer */
  .profile-overlay { position: fixed; inset: 0; background: rgba(10,22,40,0.3); z-index: 200; opacity: 0; pointer-events: none; transition: opacity 250ms ease; }
  .profile-overlay.open { opacity: 1; pointer-events: auto; }
  .profile-drawer { position: fixed; top: 0; right: -340px; width: 320px; height: 100vh; background: var(--cream); border-left: 1px solid var(--line); z-index: 201; transition: right 300ms cubic-bezier(0.25,0.8,0.25,1); display: flex; flex-direction: column; overflow-y: auto; }
  .profile-drawer.open { right: 0; }
  .pd-head { display: flex; align-items: center; gap: 14px; padding: 24px 20px 20px; border-bottom: 1px solid var(--line); }
  .pd-av { width: 44px; height: 44px; border-radius: 50%; overflow: hidden; flex-shrink: 0; background: linear-gradient(135deg, var(--green), var(--green-2)); display: flex; align-items: center; justify-content: center; font-size: 15px; font-weight: 600; color: white; }
  .pd-info { flex: 1; }
  .pd-name { font-size: 15px; font-weight: 600; color: var(--navy); }
  .pd-role { font-size: 12px; color: var(--muted); margin-top: 2px; }
  .pd-close { width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; border-radius: 8px; cursor: pointer; transition: background 160ms; background: none; border: none; }
  .pd-close:hover { background: var(--cream-2); }
  .pd-close svg { width: 18px; height: 18px; stroke: var(--ink); fill: none; stroke-width: 2; }
  .pd-nav { padding: 12px 8px; flex: 1; display: flex; flex-direction: column; gap: 2px; }
  .pd-nav a { display: flex; align-items: center; gap: 12px; padding: 11px 14px; border-radius: 8px; font-size: 14px; font-weight: 500; color: var(--ink); opacity: 0.78; transition: all 140ms; text-decoration: none; }
  .pd-nav a:hover { background: var(--cream-2); opacity: 1; }
  .pd-nav a.active { background: var(--cream-2); opacity: 1; font-weight: 600; }
  .pd-nav a svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 1.8; flex-shrink: 0; }
  .pd-divider { height: 1px; background: var(--line); margin: 6px 14px; }
  .pd-foot { display: flex; gap: 8px; padding: 16px 20px; border-top: 1px solid var(--line); }
  .pd-foot a { display: flex; align-items: center; gap: 8px; padding: 10px 14px; border-radius: 8px; font-size: 13px; font-weight: 500; color: var(--muted); transition: all 140ms; flex: 1; text-decoration: none; }
  .pd-foot a:hover { background: var(--cream-2); color: var(--navy); }
  .pd-foot a svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 1.8; }

  /* Notifications dropdown */
  .dropdown { position: absolute; top: calc(100% + 8px); right: -12px; background: #fff; border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 12px 40px -8px rgba(10,22,40,0.15); min-width: 340px; opacity: 0; pointer-events: none; transform: translateY(4px); transition: all 200ms ease; z-index: 150; }
  .dropdown.active { opacity: 1; pointer-events: auto; transform: translateY(0); }
  .notifications-header { display: flex; align-items: center; justify-content: space-between; padding: 16px 18px 12px; border-bottom: 1px solid var(--line); }
  .notifications-header h3 { font-size: 15px; font-weight: 600; margin: 0; }
  .notifications-header a { font-size: 12px; color: var(--green); font-weight: 500; }
  .notification-item { padding: 14px 18px; border-bottom: 1px solid rgba(10,22,40,0.04); cursor: pointer; transition: background 140ms; }
  .notification-item:hover { background: var(--cream-2); }
  .notification-item.unread { background: rgba(15,90,79,0.03); }
  .notification-title { font-size: 13px; font-weight: 600; color: var(--navy); margin-bottom: 3px; }
  .notification-text { font-size: 12px; color: var(--muted); line-height: 1.4; }
  .notification-time { font-size: 11px; color: var(--muted); opacity: 0.7; margin-top: 4px; }
  .notifications-footer { padding: 12px 18px; text-align: center; }
  .notifications-footer a { font-size: 13px; color: var(--green); font-weight: 500; }

  /* ── Hero (compact search band) ── */
  .hero-wrap {
    position: relative; overflow: hidden;
  }
  .hero {
    position: relative; overflow: visible;
    padding: 32px 48px;
    z-index: 10;
  }
  .hero-bg {
    position: absolute; inset: 0;
    background: var(--navy);
    z-index: 0;
  }
  .hero-bg::before {
    content: '';
    position: absolute; inset: 0;
    background: url('../hero-blueprint.svg') center center / 100% auto repeat-x;
    opacity: 0.45;
    pointer-events: none;
  }
  .hero-bg::after {
    content: '';
    position: absolute; inset: 0;
    background: linear-gradient(180deg, transparent 0%, var(--navy) 100%);
    pointer-events: none;
  }
  .hero-inner {
    position: relative; z-index: 1;
    max-width: 900px; margin: 0 auto; width: 100%;
  }
  .hero-search-wrap {
    display: flex; align-items: stretch; gap: 10px;
  }
  .hero-search {
    display: flex; align-items: stretch; flex: 1;
    background: #fff; border: 1px solid #D0CCC4;
    border-radius: 12px;
  }
  .hero-search-field {
    flex: 1; display: flex; align-items: center; gap: 12px;
    padding: 16px 20px; position: relative;
  }
  .hero-search-field + .hero-search-field {
    border-left: 1px solid #D0CCC4;
  }
  .hero-search-field svg { width: 18px; height: 18px; stroke: var(--muted); fill: none; stroke-width: 2; flex-shrink: 0; }
  .hero-search-field input {
    flex: 1; border: 0; outline: none; background: transparent;
    font-family: inherit; font-size: 15px; color: var(--navy); font-weight: 500;
  }
  .hero-search-field input::placeholder { color: #9CA3AF; font-weight: 400; }
  .loc-detect {
    background: none; border: none; cursor: pointer; padding: 4px;
    display: flex; align-items: center; justify-content: center;
    opacity: 0.4; transition: opacity 180ms;
  }
  .loc-detect:hover { opacity: 0.8; }
  .loc-detect svg { width: 16px; height: 16px; stroke: var(--green); fill: none; stroke-width: 2; }
  .hero-search-btn {
    background: #fff;
    color: var(--green);
    padding: 0 20px; font-size: 15px; font-weight: 600;
    border: 1.5px solid var(--green); cursor: pointer; white-space: nowrap;
    flex-shrink: 0; border-radius: 12px;
    aspect-ratio: 1; width: auto;
    transition: background 180ms, color 180ms;
    display: flex; align-items: center; justify-content: center;
  }
  .hero-search-btn svg { width: 20px; height: 20px; stroke: var(--green); fill: none; stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; transition: stroke 180ms; }
  .hero-search-btn:hover { background: var(--green); color: #fff; }
  .hero-search-btn:hover svg { stroke: #fff; }

  /* Search autocomplete dropdown */
  .search-dropdown {
    position: absolute; top: 100%; left: 0; right: 0; z-index: 200;
    background: #fff; border: 1px solid var(--line);
    border-top: none; border-radius: 0 0 10px 10px;
    box-shadow: 0 8px 24px -4px rgba(10,22,40,0.12);
    max-height: 320px; overflow-y: auto;
    display: none;
  }
  .search-dropdown.visible { display: block; }
  .search-dropdown-item {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 16px; cursor: pointer;
    font-size: 14px; color: var(--navy);
    transition: background 120ms;
  }
  .search-dropdown-item:hover,
  .search-dropdown-item.active { background: var(--cream-2); }
  .search-dropdown-item svg {
    width: 16px; height: 16px; stroke: var(--muted); fill: none; stroke-width: 2; flex-shrink: 0;
  }
  .search-dropdown-item .sdi-cat {
    font-size: 11px; color: var(--muted); margin-left: auto; font-weight: 500;
  }
  .search-dropdown-item mark {
    background: transparent; color: var(--green); font-weight: 600;
  }
  .search-dropdown-head {
    padding: 8px 16px 4px; font-size: 11px; font-weight: 600;
    letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--muted); border-top: 1px solid var(--line);
  }
  .search-dropdown-head:first-child { border-top: none; }

  /* ── Stats strip ── */
  .stats-strip {
    background: var(--cream); padding: 22px 0 20px;
    border-bottom: 1px solid var(--line);
    position: relative; overflow: hidden;
  }
  .stats-inner {
    max-width: 1400px; margin: 0 auto;
    display: grid; grid-template-columns: repeat(4, 1fr);
    gap: 0; position: relative;
  }
  .stat-item {
    display: flex; align-items: center; gap: 14px;
    padding: 20px 24px;
    border-right: 1px solid rgba(250,248,243,0.08);
  }
  .stat-item:last-child { border-right: none; }
  .stat-icon {
    width: 40px; height: 40px; border-radius: 8px;
    background: rgba(212,169,67,0.1); display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
  }
  .stat-icon svg { width: 20px; height: 20px; stroke: var(--gold-soft); fill: none; stroke-width: 1.8; }
  /* This strip used to sit ON the dark hero, so its type was cream. The hero
     is now the homepage photograph and the strip sits on the page beneath it,
     where cream on cream is invisible. Inverted to ink. */
  .stat-num { font-family: var(--serif-display); font-size: 20px; color: var(--navy); line-height: 1.1; }
  .stat-label { font-size: 12px; color: var(--muted); }

  /* ── Results layout ── */

  .results-wrapper {
    max-width: 1760px; margin: 0 auto;
    display: block;                 /* filters moved into the top bar */
    padding: 26px var(--edge) 64px;
  }

  /* ── Filters ── */
  .filters {
    position: sticky; top: 70px; height: fit-content;
    max-height: calc(100vh - 90px); overflow-y: auto;
  }
  .filters-head {
    display: flex; align-items: center; justify-content: space-between;
    margin-bottom: 20px;
  }
  .filters-head h3 { font-size: 16px; font-weight: 600; color: var(--navy); margin: 0; }
  .filters-head a { font-size: 13px; color: var(--muted); transition: color 180ms ease; }
  .filters-head a:hover { color: var(--green); }

  .f-group { margin-bottom: 8px; }
  .f-group h4 {
    font-size: 13px; font-weight: 600; color: var(--navy); margin: 0;
    cursor: pointer; display: flex; align-items: center;
    user-select: none; padding: 10px 0;
    transition: color 180ms ease;
  }
  .f-group h4:hover { color: var(--green); }
  .f-group h4 .chevron {
    width: 16px; height: 16px; margin-left: auto; stroke: var(--muted);
    fill: none; stroke-width: 2; transition: transform 200ms ease;
  }
  .f-group.open h4 .chevron { transform: rotate(180deg); }
  .f-group .f-body { max-height: 0; overflow: hidden; transition: max-height 250ms ease; }
  .f-group.open .f-body { max-height: 500px; }
  .f-options { padding: 4px 0 8px; }

  .f-check {
    display: flex; align-items: center; gap: 10px;
    cursor: pointer; font-size: 13px; color: var(--ink);
    padding: 6px 4px; border-radius: 6px; transition: background 150ms ease;
  }
  .f-check:hover { background: var(--cream-2); }
  .f-check input[type="checkbox"] {
    -webkit-appearance: none; appearance: none;
    width: 18px; height: 18px; border: 1.5px solid var(--line-2); border-radius: 4px;
    cursor: pointer; position: relative; flex-shrink: 0;
    transition: all 150ms ease; background: white;
  }
  .f-check input[type="checkbox"]:checked { background: var(--green); border-color: var(--green); }
  .f-check input[type="checkbox"]:checked::after {
    content: ''; position: absolute; left: 4px; top: 1px;
    width: 6px; height: 10px; border: solid white; border-width: 0 2px 2px 0;
    transform: rotate(45deg);
  }
  .f-check .f-label { flex: 1; }
  .show-more { font-size: 13px; color: var(--green); cursor: pointer; padding: 4px; display: flex; align-items: center; gap: 4px; }
  .show-more:hover { text-decoration: underline; }
  .show-more svg { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 2; }

  .f-divider { height: 1px; background: var(--line); margin: 4px 0; }

  /* ── Results column ── */
  .results-column {}
  .results-header {
    margin-bottom: 24px;
  }
  .results-header h2 {
    font-family: var(--serif-display); font-size: 28px; font-weight: 400;
    color: var(--navy); margin: 0 0 4px 0; letter-spacing: -0.01em;
  }
  .results-meta {
    display: flex; align-items: center; justify-content: space-between;
  }
  .results-count { font-size: 14px; color: var(--muted); }
  .sort-wrap { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); }
  .custom-select { position: relative; min-width: 160px; }
  .custom-select-trigger {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    padding: 7px 12px; border: 1px solid var(--line); border-radius: 8px;
    background: white; cursor: pointer; font-family: inherit; font-size: 13px;
    color: var(--navy); font-weight: 500; transition: border-color 180ms, box-shadow 180ms;
    user-select: none;
  }
  .custom-select-trigger:hover { border-color: var(--line-2); }
  .custom-select.open .custom-select-trigger { border-color: var(--green); box-shadow: 0 0 0 3px rgba(15,90,79,0.08); }
  .custom-select-trigger .cs-chevron {
    width: 14px; height: 14px; stroke: var(--muted); fill: none; stroke-width: 2;
    transition: transform 200ms ease; flex-shrink: 0;
  }
  .custom-select.open .custom-select-trigger .cs-chevron { transform: rotate(180deg); }
  .custom-select-options {
    position: absolute; top: calc(100% + 4px); left: 0; right: 0;
    background: white; border: 1px solid var(--line); border-radius: 8px;
    box-shadow: 0 8px 24px rgba(10,22,40,0.1); z-index: 60;
    opacity: 0; pointer-events: none; transform: translateY(-4px);
    transition: all 180ms ease; overflow: hidden;
  }
  .custom-select.open .custom-select-options { opacity: 1; pointer-events: auto; transform: translateY(0); }
  .custom-select-option {
    padding: 9px 12px; font-size: 13px; color: var(--ink); cursor: pointer;
    display: flex; align-items: center; justify-content: space-between;
    transition: background 120ms;
  }
  .custom-select-option:hover { background: var(--cream-2); }
  .custom-select-option.selected { font-weight: 600; color: var(--green); }
  .custom-select-option.selected::after {
    content: ''; width: 14px; height: 14px; flex-shrink: 0;
    background: url('data:image/svg+xml;utf8,<svg viewBox="0 0 24 24" fill="none" stroke="%230F5A4F" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><polyline points="20 6 9 17 4 12"/></svg>') center/contain no-repeat;
  }



  /* ================= HERO, ported verbatim from index.html =================
     Same component, same code. If the homepage hero changes, this must
     change with it, that is the point of it being identical. */
  /* ---------- full-screen hero ---------- */
  .nm-hero{
    position:relative; height:100vh; min-height:620px;
    overflow:hidden; background:var(--navy);
  }
  .nm-media{position:absolute;inset:0}
  .nm-media img{
    position:absolute; inset:0; width:100%; height:100%;
    object-fit:cover; object-position:center 55%;
    opacity:0; transition:opacity 1.4s ease;
  }
  .nm-media img.on{opacity:1}
  .nm-scrim{
    position:absolute; inset:0; pointer-events:none;
    background:
      linear-gradient(to bottom,
        rgba(10,22,40,.52) 0%,
        rgba(10,22,40,.12) 18%,
        rgba(10,22,40,.10) 44%,
        rgba(10,22,40,.66) 82%,
        rgba(10,22,40,.86) 100%);
  }

  /* ---------- the foot block: kicker, search, caption ---------- */
  .nm-foot{
    position:absolute; left:0; right:0; bottom:92px; z-index:5;
    text-align:center; padding:0 40px;
  }
  .nm-sub{
    font-family:var(--sans); font-size:12px; font-weight:400;
    letter-spacing:.04em; color:rgba(255,255,255,.72);
    margin:22px auto 0; max-width:60ch;
  }

  /* ---------- the search ---------- */
  .nm-search{position:relative;max-width:720px;margin:0 auto}
  .nm-search-row{
    display:flex; align-items:stretch;
    background:rgba(250,248,243,.95);
    backdrop-filter:blur(14px) saturate(150%);
    -webkit-backdrop-filter:blur(14px) saturate(150%);
    border-radius:999px; padding:7px 7px 7px 10px;
    box-shadow:0 18px 44px -14px rgba(10,22,40,.5), inset 0 1px 0 rgba(255,255,255,.7);
  }
  .nm-field{position:relative;display:flex;align-items:center;flex:1;min-width:0}
  .nm-field > svg{width:16px;height:16px;flex:none;fill:none;stroke:var(--muted);stroke-width:1.7;margin:0 10px 0 12px}
  .nm-field input{
    width:100%; border:0; background:transparent; outline:none;
    font-family:var(--serif); font-size:16px; color:var(--ink); padding:15px 8px;
  }
  .nm-field input::placeholder{color:#A3A9B3}
  .nm-div{width:1px;background:var(--line-2);margin:12px 4px}
  .nm-field-loc{flex:0 0 208px}
  .nm-field-loc .loc-detect{background:none;border:0;cursor:pointer;padding:8px;display:grid;place-items:center;flex:none}
  .nm-field-loc .loc-detect svg{width:15px;height:15px;margin:0;fill:none;stroke:var(--green);stroke-width:1.7}
  .nm-go{
    flex:none; border:0; border-radius:999px; cursor:pointer;
    background:var(--navy); color:var(--cream); padding:0 30px;
    font-family:var(--sans); font-size:10.5px; font-weight:500;
    letter-spacing:.2em; text-transform:uppercase; transition:background .25s ease;
  }
  .nm-go:hover{background:var(--navy-2)}

  /* the autocomplete opens UPWARD here, since the bar sits at the foot */
  .nm-search .search-dropdown{
    position:absolute; bottom:calc(100% + 12px); top:auto; left:0; right:0; z-index:30;
    background:var(--cream); border:1px solid var(--line); border-radius:14px;
    box-shadow:0 -18px 46px -14px rgba(10,22,40,.34);
    max-height:320px; overflow-y:auto; text-align:left; display:none;
  }
  .nm-search .search-dropdown.visible,
  .nm-search .search-dropdown.open,
  .nm-search .search-dropdown.show{display:block}

  .nm-search{position:relative;max-width:720px;margin:0 auto}
  .nm-search-row{
    display:flex; align-items:stretch;
    background:rgba(250,248,243,.95);
    backdrop-filter:blur(14px) saturate(150%);
    -webkit-backdrop-filter:blur(14px) saturate(150%);
    border-radius:999px; padding:7px 7px 7px 10px;
    box-shadow:0 18px 44px -14px rgba(10,22,40,.5), inset 0 1px 0 rgba(255,255,255,.7);
  }
  .nm-field{position:relative;display:flex;align-items:center;flex:1;min-width:0}
  .nm-field > svg{width:16px;height:16px;flex:none;fill:none;stroke:var(--muted);stroke-width:1.7;margin:0 10px 0 12px}
  .nm-field input{
    width:100%; border:0; background:transparent; outline:none;
    font-family:var(--serif); font-size:16px; color:var(--ink); padding:15px 8px;
  }
  .nm-field input::placeholder{color:#A3A9B3}
  .nm-div{width:1px;background:var(--line-2);margin:12px 4px}
  .nm-field-loc{flex:0 0 208px}
  .nm-field-loc .loc-detect{background:none;border:0;cursor:pointer;padding:8px;display:grid;place-items:center;flex:none}
  .nm-field-loc .loc-detect svg{width:15px;height:15px;margin:0;fill:none;stroke:var(--green);stroke-width:1.7}
  .nm-go{
    flex:none; border:0; border-radius:999px; cursor:pointer;
    background:var(--navy); color:var(--cream); padding:0 30px;
    font-family:var(--sans); font-size:10.5px; font-weight:500;
    letter-spacing:.2em; text-transform:uppercase; transition:background .25s ease;
  }
  .nm-go:hover{background:var(--navy-2)}

  /* ── SEGMENT HIGHLIGHT ──────────────────────────────────────────────
     The Airbnb search-bar behaviour Sir pointed at: hovering a segment
     fills it as a pill rather than only moving the caret.

     THE DIVIDER HAS TO GET OUT OF THE WAY. A 1px rule sitting flush against
     a filled pill reads as a seam through the fill. So the divider adjacent
     to the active segment fades. It takes two selectors because the divider
     sits BETWEEN the two fields: the sibling combinator handles the case
     where the field before it is active, and :has() handles the field after.
     Where :has() is unsupported the divider simply stays, which is untidy
     rather than broken.

     FILL, NOT ELEVATION. Airbnb lifts the active segment on a white card with
     a shadow; this identity signals state by fill everywhere else, so hover
     is a soft navy tint and focus is solid white. Same information, one less
     idiom to explain. */
  .nm-field{ border-radius:999px; transition:background .18s ease; }
  .nm-field:hover{ background:rgba(10,22,40,.055); }
  .nm-field:focus-within{ background:#fff; }
  .nm-div{ transition:opacity .18s ease; }
  .nm-field:hover + .nm-div,
  .nm-field:focus-within + .nm-div{ opacity:0; }
  .nm-div:has(+ .nm-field:hover),
  .nm-div:has(+ .nm-field:focus-within){ opacity:0; }
  @media (prefers-reduced-motion: reduce){
    .nm-field, .nm-div{ transition:none; }
  }

  /* the autocomplete opens UPWARD here, since the bar sits at the foot */
  .nm-search .search-dropdown{
    position:absolute; bottom:calc(100% + 12px); top:auto; left:0; right:0; z-index:30;
    background:var(--cream); border:1px solid var(--line); border-radius:14px;
    box-shadow:0 -18px 46px -14px rgba(10,22,40,.34);
    max-height:320px; overflow-y:auto; text-align:left; display:none;
  }
  .nm-search .search-dropdown.visible,
  .nm-search .search-dropdown.open,
  .nm-search .search-dropdown.show{display:block}

  /* ---------- slide dots ---------- */
  .nm-dots{
    position:absolute; left:0; right:0; bottom:30px; z-index:5;
    display:flex; justify-content:center; gap:9px;
  }
  .nm-dots button{
    width:5px;height:5px;padding:0;border:0;border-radius:50%;cursor:pointer;
    background:rgba(246,240,222,.34); transition:background .3s ease;
  }
  .nm-dots button.on{background:var(--nm-cream)}

  /* the only deliberate divergence: results need to be visible, so the hero
     is a band rather than a full screen */
  .nm-hero--results { height: clamp(340px, 46vh, 480px); min-height: 0; }
  /* centred in the image band rather than sitting at its foot, on the
     homepage the search hangs low because the hero is a full screen; here the
     band is short, so the middle is where the eye lands */
  .nm-hero--results .nm-foot { top: 50%; bottom: auto; transform: translateY(-50%); }
  .nm-hero--results .nm-dots { bottom: 16px; }
  @media (max-width: 640px){ .nm-hero--results { height: clamp(300px, 52vh, 420px); } }
  /* THE PHOTOGRAPH RUNS UP BEHIND THE BAR.                       5 Oct 2026
     Sir: on this page the header's colour "is just not making sense ... the
     background needs to be stretched a little bit further upwards so it
     touches the edge of the screen, above and behind the header". The bar is
     navy glass (hyyryn-glass.css, .hy-glass-dark), and the band started
     under it, so the glass had only the page's cream to show through and read
     as a grey strip. The band now starts at the top of the screen, the same
     height again as the bar taller, so nothing below it moves and the search
     stays in the middle of the part you can see. */
  /* rp143: taken off with the navy glass masthead. The board's hero now starts under the cream masthead, as
     Find a trade's does. */



  /* ── Type: the measured Norm caption ──
     Adobe Caslon Pro 20px / 24px / 0.2px on inigo.com and themodernhouse.com,
     all four caption lines at ONE size. We were at 17px, which read as a
     footnote next to photography this large. */
  .rc-name, .rc-sub, .rc-price, .rc-meta,
  .feat-name, .feat-sub, .feat-price, .feat-meta {
    font-family: var(--serif) !important;
    font-size: 20px !important; line-height: 24px !important;
    letter-spacing: 0.2px !important; font-weight: 400 !important;
  }
  .feat-cap div { font-size: 20px; line-height: 24px; }

  /* count reads as a label, the way "431 HOMES FOR SALE" does */
  .results-count {
    font-family: var(--sans); font-size: 10.5px; font-weight: 600;
    letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted);
  }
  .pg-num, .pg-arrow { font-size: 11px; letter-spacing: 0.06em; }

  /* ── Rating: a face and five stars, no count ── */
  .rc-rate { display: flex; align-items: center; justify-content: flex-end; gap: 8px; margin-top: 5px; }
  .rc-av {
    width: 26px; height: 26px; border-radius: 50%; object-fit: cover;
    flex: none; border: 1px solid var(--line);
  }
  .rc-stars {
    position: relative; display: inline-block; white-space: nowrap;
    font-size: 13px; line-height: 1; letter-spacing: 1.5px;
    color: var(--line-2);                 /* the empty track */
  }
  .rc-stars-fill {
    position: absolute; left: 0; top: 0; overflow: hidden;
    white-space: nowrap; color: var(--gold-soft);
    width: var(--pct, 100%);              /* a true partial star, not a rounded one */
  }
  .feat-rate { justify-content: flex-end; }


  /* ── Compact search in the masthead (same swap as the homepage) ── */
  .nav { transition: opacity .26s ease, visibility 0s linear .26s; visibility: visible; }
  .nm-mini {
    position: absolute; left: 50%; top: 50%;
    transform: translate(-50%,-50%);
    width: min(430px, 34vw);
    display: flex; align-items: center; height: 40px; padding: 0 5px 0 15px;
    background: #fff; border: 1px solid var(--line); border-radius: 999px;
    box-shadow: 0 1px 2px rgba(10,22,40,.04), 0 10px 26px -18px rgba(10,22,40,.45);
    opacity: 0; visibility: hidden; pointer-events: none;
    transition: opacity .3s ease, visibility 0s linear .3s;
  }
  .nm-mini-icon { width: 15px; height: 15px; flex: none; fill: none; stroke: var(--muted); stroke-width: 1.7; stroke-linecap: round; margin-right: 10px; }
  .nm-mini input { min-width: 0; border: 0; background: none; outline: none; padding: 0;
    font-family: var(--sans); font-size: 13px; color: var(--ink); }
  .nm-mini input::placeholder { color: var(--muted); opacity: .75; }
  .nm-mini #miniQ { flex: 1 1 auto; }
  .nm-mini #miniLoc { flex: 0 0 84px; }
  .nm-mini-div { width: 1px; height: 18px; background: var(--line); margin: 0 12px; flex: none; }
  .nm-mini-go { flex: none; width: 32px; height: 32px; margin-left: 8px; display: grid; place-items: center;
    cursor: pointer; background: var(--navy); border: 0; border-radius: 50%; transition: background .2s ease; }
  .nm-mini-go svg { width: 15px; height: 15px; fill: none; stroke: var(--cream); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
  .nm-mini-go:hover { background: #0E1E34; }

  .topbar.compact .nav { opacity: 0; visibility: hidden; pointer-events: none;
    transition: opacity .22s ease, visibility 0s linear .22s; }
  .topbar.compact .nm-mini {
    opacity: 1; visibility: visible; pointer-events: auto;
    transition: opacity .3s ease .06s, visibility 0s linear 0s;
  }
  .topbar .nm-acct { margin-left: auto; }
  @media (prefers-reduced-motion: reduce) { .nav, .nm-mini { transition: none; } }
  @media (max-width: 1080px) { .nav { display: none; } }
  @media (max-width: 720px)  { .nm-mini { display: none; } }

  /* ── Bigger cards: two across, not three ──
     The images were ~460px wide at three across. Two gives ~700px, which is
     what makes the photography carry the page the way it does on the homepage. */
  /* Three across. Gutters deliberately tight, with the page margins pulled
     in as well, the images get the width instead of the whitespace. */
  .results-list { grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
    column-gap: clamp(14px, 1.5vw, 24px) !important; row-gap: 46px !important; }
  .feat-row { grid-template-columns: repeat(3, 1fr) !important;
    gap: clamp(14px, 1.5vw, 24px) !important; }

  /* ── Caption type: matched to the homepage category cards ──
     name  = Caslon Text 700, uppercase, .13em   (index .tr-name)
     sub   = Caslon Text 400, 14px               (index .tr-desc)
     price = Caslon Text 400, 17px, green
     Same voice on both pages, so a click from home does not change register. */
  .rc-name, .feat-name {
    font-family: var(--serif) !important; font-weight: 700 !important;
    font-size: 17px !important; line-height: 1.35 !important;
    letter-spacing: .13em !important; text-transform: uppercase;
    color: var(--navy) !important;
  }
  .rc-sub, .feat-sub {
    font-family: var(--serif) !important; font-weight: 400 !important;
    font-size: 14px !important; line-height: 1.6 !important;
    letter-spacing: normal !important; color: var(--muted) !important;
  }
  .rc-price, .feat-price {
    font-family: var(--serif) !important; font-weight: 400 !important;
    font-size: 17px !important; line-height: 1.35 !important;
    letter-spacing: normal !important; color: var(--green) !important;
  }
  .rc-caption, .feat-cap { padding-top: 18px; }
  .rc-left, .feat-cap > div:first-child { display: flex; flex-direction: column; gap: 4px; }

  @media (max-width: 900px) {
    .results-list { grid-template-columns: repeat(2, minmax(0,1fr)) !important; }
    .feat-row { grid-template-columns: repeat(2, 1fr) !important; }
  }


  /* ── THE MARK CAME OFF THE PHOTOGRAPH ──
     Sir: the three Hyyryn arches on the featured cards look amateur.

     He is right, and the file argued itself into it: the comment here read
     "this is the only place the mark appears on a photograph". A rule with
     one exception written next to it is a rule that has already been broken.
     s20 says the arch never goes on a photograph, and three of them shrinking
     away in a corner is the mark used as a rating device, which is not a
     convention any reader knows.

     It also could not work: gold at .5 over photographs that run from a
     near-white kitchen to a near-black circuit board is invisible on one and
     glowing on the other, which is why it carried a drop-shadow to survive
     both. And it pulsed, so the one animated thing in the results was a
     decoration carrying no information.

     WHAT REPLACES IT IS WORDS. A paid position is a disclosure, and the
     professional way to disclose is to write it: the row says what it is and
     that these trades passed the same checks. That is also what the CMA and
     the ASA expect of paid placement, which a watermark does not satisfy. */

  /* ── Pagination ── */
  .pager {
    display: flex; align-items: center; justify-content: center; gap: 4px;
    margin-top: 56px; padding-top: 30px; border-top: 1px solid var(--line);
  }
  .pg-num, .pg-arrow {
    min-width: 34px; height: 34px; padding: 0 8px;
    display: inline-flex; align-items: center; justify-content: center;
    font-family: var(--sans); font-size: 12px; color: var(--ink);
    text-decoration: none; border: 1px solid transparent;
    transition: border-color 160ms ease, color 160ms ease;
  }
  .pg-num:hover, .pg-arrow:hover { border-color: var(--line-2); }
  .pg-num.is-current { border-color: var(--navy); color: var(--navy); font-weight: 600; }
  .pg-arrow { font-size: 15px; color: var(--muted); }
  .pg-arrow[aria-disabled="true"] { opacity: .35; pointer-events: none; }
  .pg-gap { padding: 0 4px; color: var(--muted); font-size: 12px; }

  /* ── Hover map ──
     Fixed, bottom-right, above the page but below the masthead. Pointer
     events off so it can never swallow a click meant for a card. */
  /* Positioned per-card in JS: the map's CENTRE lands on the card's top-right
     corner, so exactly its bottom-left quadrant (a quarter of its area) sits
     over the card and the other three quarters hang outside. */
  /* SLIDES OUT OF THE CARD'S RIGHT EDGE. It originally centred on the card's
     top-right corner, which put a quarter of it over the save icon. Sitting it
     above the card fixed that but read as a detached tooltip. Emerging
     sideways ties it to the card it belongs to and still touches nothing.

     The motion is a horizontal SLIDE, not a fade-up: it starts tucked 22px
     back, behind the card's right edge, and travels out from under it. That
     overlap during the transition is the point, it is what makes the panel
     look like it came FROM the card rather than appearing beside it. */
  /* Right-hand column: there is no room to the right, so it emerges from the
     LEFT edge instead and travels the other way. Mirrored, not clamped: a
     clamped panel would sit on top of the card it describes. */

  /* ── Face pins, as on the service page coverage map ──
     Same idea as .tp-pin over there: a face, not a teardrop, with a small
     diamond tail so it still reads as a pin. Scaled DOWN hard, because that
     map is full width and this one is 260x148: 44px pins would have covered
     most of the tiles. 30px for neighbours, 38px for the hovered trade.

     No hover card here, unlike the service page. The panel is pointer-events
     none by design, so a pin could never be hovered anyway; building one would
     be dead markup. */
  .hm-pin { position: relative; width: 30px; height: 30px; }
  .hm-face {
    width: 30px; height: 30px; border-radius: 50%; overflow: hidden;
    border: 2px solid #fff; background: var(--cream-2);
    box-shadow: 0 1px 3px rgba(10,22,40,.28), 0 6px 14px -6px rgba(10,22,40,.45);
  }
  .hm-face img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .hm-pin::after {
    content: ''; position: absolute; bottom: -4px; left: 50%; margin-left: -4px;
    width: 8px; height: 8px; background: #fff; transform: rotate(45deg);
    box-shadow: 2px 2px 4px rgba(10,22,40,.18);
  }
  /* TWO INDEPENDENT AXES, which is the whole point of this arrangement:
       COLOUR = status. Gold ring means FEATURED, i.e. a paid position, and
                nothing else on the map is ever gold.
       SIZE + HALO = state. Bigger with a neutral navy halo means the card you
                are hovering.
     Keeping them separate means a featured trade you are not hovering still
     reads as featured, and an ordinary trade you ARE hovering never borrows
     the gold that signals payment. Gold was previously doing both jobs, so a
     hovered ordinary trade looked promoted. */
  .hm-pin.is-feat .hm-face { border-color: var(--gold-soft); }
  .hm-pin.is-feat::after   { background: var(--gold-soft); }

  .hm-pin.is-on { width: 38px; height: 38px; }
  .hm-pin.is-on .hm-face {
    width: 38px; height: 38px;
    box-shadow: 0 0 0 3px rgba(10,22,40,.22), 0 2px 8px rgba(10,22,40,.42);
  }
  .hm-pin.is-on::after { bottom: -5px; margin-left: -5px; width: 10px; height: 10px; }
  .result-card, .feat-card { z-index: 1; }
  .result-card:hover, .feat-card:hover { z-index: 2; }

  /* ── Filter bar (The Modern House) ───────────────────────────────
     Three zones on one hairline row: search left, section name centred
     on the VIEWPORT, filters as plain words right. The filters keep the
     exact same checkbox DOM as the old sidebar, so the filtering JS is
     untouched, only where they live has changed. */
  .tmh-bar {
    position: sticky; top: 0; z-index: 60;
    display: flex; align-items: center; gap: 24px;
    padding: 13px var(--edge);
    background: rgba(250,248,243,0.96);
    backdrop-filter: blur(14px) saturate(1.1);
    -webkit-backdrop-filter: blur(14px) saturate(1.1);
    border-bottom: 1px solid var(--line);
  }
  .tmh-search {
    display: flex; align-items: center; gap: 8px; flex: 0 0 auto;
    border: 1px solid var(--line-2); padding: 7px 10px 7px 12px;
  }
  .tmh-search input {
    border: 0; background: none; outline: none; width: 150px;
    font-family: var(--serif); font-size: 14px; color: var(--ink);
  }
  .tmh-search input::placeholder { color: var(--muted); }
  .tmh-search button { background: none; border: 0; padding: 0; cursor: pointer; display: grid; place-items: center; }
  .tmh-search svg { width: 15px; height: 15px; fill: none; stroke: var(--navy); stroke-width: 1.7; stroke-linecap: round; }

  .tmh-filters { display: flex; align-items: center; gap: 22px; margin-left: auto; }
  .tmh-bar { justify-content: space-between; }
  .tmh-filters .f-group { position: relative; margin: 0; }
  .tmh-filters .f-group h4 {
    display: flex; align-items: center; gap: 5px; margin: 0; cursor: pointer;
    font-family: var(--sans); font-size: 10.5px; font-weight: 600;
    letter-spacing: 0.12em; text-transform: uppercase; color: var(--navy);
    white-space: nowrap; transition: opacity 160ms ease;
  }
  .tmh-filters .f-group h4:hover { color: var(--navy); opacity: .62; }
  .tmh-filters .f-group h4 .chevron { width: 11px; height: 11px; stroke: currentColor; fill: none; stroke-width: 2; }
  .tmh-filters .f-group.open h4 .chevron { transform: rotate(180deg); }
  /* the panel: a plain sheet, opened on click, same markup as before */
  .tmh-filters .f-group .f-body {
    position: absolute; top: calc(100% + 13px); right: 0; z-index: 70;
    min-width: 216px; max-height: 0; overflow: hidden;
    background: #fff; border: 1px solid var(--line);
    box-shadow: 0 20px 44px -22px rgba(10,22,40,0.4);
    transition: max-height 220ms ease, opacity 180ms ease;
    opacity: 0; padding: 0 16px;
  }
  .tmh-filters .f-group.open .f-body { max-height: 340px; overflow-y: auto; opacity: 1; padding: 14px 16px; }

  /* ── Featured row ── */
  /* ── THE ROW IS A BAND, NOT A SET OF BADGED CARDS ──
     With the watermark gone the row needed to say it is different some other
     way, and the house has one: give a block its own ground. A tinted band
     the full width of the page, hairline ruled at both edges, so the featured
     row sits ON something rather than wearing something.

     THE GROUND IS `--cream-2`, one step off the page, which is the same
     relationship the docket paper has to the quote page. Any stronger and it
     competes with the photographs; any weaker and it is not a band.

     THE BLEED IS THE TOKEN, NOT A VIEWPORT UNIT, and the first attempt
     proved why. `margin-inline: calc(50% - 50vw)` put a 10px horizontal
     scrollbar on the page: `100vw` includes the scrollbar gutter, so the band
     measured 1223 inside a 1213px document. Measured, not guessed:
     scrollWidth 1224 against clientWidth 1213, band left -5, width 1223.
     The card's left edge moved 20 to 40 as well, so the padding calc was
     wrong in the same breath.

     `.results-wrapper` is padded with `var(--edge)`, so the band pulls out by
     exactly that and puts it back as its own padding. It reaches the wrapper's
     edges, resolves to the SAME EXPRESSION the wrapper uses so the two cannot
     drift apart, and involves no viewport unit at all. Measured after: card
     left back to 20, scrollWidth equal to clientWidth at every width. */
  /* DEPTH BY RECESSION, NOT ELEVATION, and gold as a line rather than a field.
     Sir asked whether 3D would work, and whether a gold glass tint would.

     NOT ELEVATION. Lifting the paid cards toward the reader on a page whose
     whole job is comparison puts the bought slots physically in front of the
     earned ones. That is the wrong emphasis before it is a style question,
     and a tilted card with a drop shadow is furniture: this site's one piece
     of 3D is the index lintel falling onto its posts, which is mass being
     placed, not a box floating.

     RECESSION INSTEAD. The band is cut INTO the sheet: a hairline of shadow
     across the top inner edge and the faintest lift off the bottom, so the
     paper reads as stepped down rather than stuck on. Two inset shadows, no
     perspective, no transform, nothing to paint on scroll.

     GOLD AS A LINE, NOT A TINT. Gold already means one thing on this site and
     the label is already wearing it, so the band takes a 2px gold rule at its
     head and nothing else. A gold FIELD was the other option and it fails
     twice: gold at low opacity over cream goes muddy rather than warm, and a
     tinted ground behind photographs competes with the photographs, which are
     the only thing on these cards a homeowner actually wants to look at.

     AND THE RESTRAINT IS THE POINT. This band is a paid-placement disclosure.
     The more it is dressed up, the more it reads as something the platform is
     proud of rather than something it is declaring. */
  .featured {
    position: relative;
    margin: 4px 0 42px;
    margin-inline: calc(var(--edge) * -1);
    padding: 30px var(--edge) 34px;
    background: var(--cream-2);
    border-top: 2px solid var(--gold);
    border-bottom: 1px solid var(--line);
    /* A CUT EDGE IS A HARD LINE PLUS A FALLOFF, which is s4.1's whole point:
       the seam shadow exists so an edge reads as CUT and not as a colour
       change. The first attempt was falloff only, at `10px -8px`, and on
       cream against cream that is a colour change. Nothing to see.

       Four layers, and each one is doing a job a real recess does:
         1  a crisp dark line at the top, the cut itself
         2  the shadow the near wall throws down into the recess
         3  a pale lip along the bottom, the light catching the far edge
            as the surface steps back up
         4  a shallower shadow rising off that lip
       Take away 1 and 3 and it is a gradient; they are what make it a step. */
    box-shadow:
      inset 0  1px 0     rgba(10, 22, 40, .13),
      inset 0  16px 18px -14px rgba(10, 22, 40, .30),
      inset 0 -1px 0     rgba(255, 255, 255, .60),
      inset 0 -12px 14px -13px rgba(10, 22, 40, .16);
  }
  /* the disclosure. Serif, because it is a sentence and not a label, and
     muted because it is a footnote to the row rather than a claim of its
     own. Capped at 62 characters of measure so it never runs the full band. */
  .feat-note {
    max-width: 62ch; margin: -14px auto 24px;
    text-align: center;
    font-family: var(--serif); font-size: 13px; line-height: 1.6;
    color: var(--muted);
  }
  .feat-label, .all-label {
    display: block; text-align: center; margin-bottom: 22px;
    font-family: var(--sans); font-size: 10px; font-weight: 600;
    letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted);
  }
@media (max-width: 760px) { .feat-label, .all-label { font-size: 10.5px; } }  /* rp200 phone floor, was 10px */
  /* the one gold thing on the page: featured is the only paid-for position */
  .feat-label { color: var(--gold); }
  .all-label { margin: 8px 0 20px; }
  .feat-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(18px, 2.4vw, 34px); }
  .feat-card { display: block; text-decoration: none; color: inherit; }
  /* these are <span>s inside an <a>; without display:block they stay inline
     and the caption escapes the card, which is what put the ALL SERVICES
     rule on top of the featured captions. */
  .feat-img { display: block; position: relative; overflow: hidden; aspect-ratio: 3 / 2; background: var(--cream-2); }
  /* stacked and cross-faded, exactly as .result-img, the same slideshow drives both */
  .feat-img img {
    position: absolute; inset: 0; width: 100%; height: 100%;
    object-fit: cover; display: block; opacity: 0;
    transition: opacity 420ms ease;
  }
  .feat-img img.active { opacity: 1; }
  .feat-img .slide-dots {
    position: absolute; bottom: 12px; left: 50%; transform: translateX(-50%);
    display: flex; gap: 5px; z-index: 3; opacity: 0; transition: opacity 250ms;
  }
  .feat-card:hover .feat-img .slide-dots { opacity: 1; }
  @media (prefers-reduced-motion: reduce) { .feat-img img { transition: none; } }
  .feat-cap { display: flex; justify-content: space-between; gap: 16px; padding-top: 14px; }
  .all-label { clear: both; }
  .feat-cap div { font-family: var(--serif); font-size: 17px; line-height: 1.4; }
  .feat-name { color: var(--navy); }
  .feat-sub, .feat-meta { color: var(--muted); }
  /* s22 · navy, not green. Sir on the trade profile: "the prices are the
     wrong colour". Green marks a thing Hyyryn has CHECKED; a price is not
     checked, it is quoted. Same defect, different page. */
  .feat-price { color: var(--navy); text-align: right; }
  /* THE ARROWS MOVE INTO THE HEADER, and the measurement is what moved them.
     They were `left: -6px` and `right: -6px`, six pixels OUTSIDE `.featured`,
     which worked only while `.featured` was inset by the wrapper's padding.
     The band is flush to that edge now, so the next arrow's right edge landed
     at 1276 in a 1270px document: a 6px horizontal scrollbar, and the only
     offending element on the page.

     Rather than tuck them back into a 20px gutter where a 34px control does
     not fit, they go where a carousel's controls belong on a page like this:
     the top right of the band, level with the label, inside the padding.
     A pair of controls reads as a control; an arrow floating in the margin
     reads as an artefact. */
  .feat-arrow {
    position: absolute; top: 22px; z-index: 3; width: 30px; height: 30px;
    display: grid; place-items: center; background: none; cursor: pointer;
    border: 1px solid var(--line-2); border-radius: 50%;
    transition: border-color 160ms ease, background-color 160ms ease;
  }
  .feat-arrow:hover { border-color: var(--navy); background: rgba(255,255,255,.5); }
  .feat-arrow:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
  .feat-prev { left: auto; right: calc(var(--edge) + 38px); }
  .feat-next { right: var(--edge); }
  .feat-arrow svg { width: 16px; height: 16px; fill: none; stroke: var(--navy); stroke-width: 1.8; }

  /* ── Grid: three across, flag on the image ── */
  .rc-flag {
    position: absolute; top: 0; left: 0; z-index: 3;
    padding: 7px 12px; text-align: left;
    background: rgba(250,248,243,0.92);
    font-size: 9.5px; letter-spacing: 0.14em; color: var(--navy);
  }
  .result-card { position: relative; }

  @media (max-width: 1100px) {
    .feat-row { grid-template-columns: repeat(2, 1fr); }
  }
  @media (max-width: 720px) {
    .tmh-bar { flex-wrap: wrap; gap: 12px; }
    .tmh-filters { margin-left: 0; gap: 14px; flex-wrap: wrap; }
    .tmh-filters .f-group .f-body { right: auto; left: 0; }
    .feat-row, .results-list { grid-template-columns: 1fr !important; }
  }

  /* ── Result cards: the Inigo pattern ──────────────────────────────
     Measured off inigo.com/all-homes: two across, 3:2 photography with
     square corners, and a caption in two columns underneath, name and
     place hard left, price and rating hard right, all one serif size.
     No card, no border, no shadow, no pills. The photograph does the
     selling and the type stays out of its way.

     ONE DEPARTURE: Inigo sets its price in italic. The identity forbids
     italics anywhere, so emphasis here is by COLOUR and position. */
  .results-list {
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
    column-gap: clamp(14px, 1.5vw, 24px); row-gap: 46px;
  }
  .result-card {
    display: block; background: none; border: 0; border-radius: 0;
    overflow: visible; text-decoration: none; color: inherit; cursor: pointer;
  }
  .result-card:hover { transform: none; box-shadow: none; }

  /* the flag sits ABOVE the image, centred, the way Inigo marks NEW */
  .rc-flag {
    display: block; text-align: center; padding: 0 0 9px;
    font-family: var(--sans); font-size: 10px; font-weight: 600;
    letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted);
  }

  .result-img {
    position: relative; overflow: hidden; border-radius: 0;
    aspect-ratio: 3 / 2; min-height: 0; background: var(--cream-2);
  }
  .result-img img {
    position: absolute; inset: 0; width: 100%; height: 100%;
    object-fit: cover; display: block; opacity: 0;
    transition: opacity 420ms ease;
  }
  @media (prefers-reduced-motion: reduce) { .result-img img { transition: none; } }
  .result-img img.active { opacity: 1; }

  .slide-dots {
    position: absolute; bottom: 14px; left: 50%; transform: translateX(-50%);
    display: flex; gap: 5px; z-index: 2; opacity: 0; transition: opacity 250ms;
  }
  .result-card:hover .slide-dots { opacity: 1; }
  .slide-dot { width: 6px; height: 6px; border-radius: 50%; background: rgba(255,255,255,0.5); transition: all 250ms; }
  .slide-dot.active { background: #fff; width: 16px; border-radius: 3px; }

  /* save: no chrome, appears on hover only */
  .result-fav {
    position: absolute; top: 12px; right: 12px; z-index: 3;
    width: 30px; height: 30px; display: flex; align-items: center; justify-content: center;
    background: none; border: 0; cursor: pointer;
    opacity: 0; transition: opacity 200ms ease, transform 180ms ease;
  }
  .result-card:hover .result-fav { opacity: 1; }
  .result-fav:hover { transform: scale(1.12); }
  .result-fav svg { width: 19px; height: 19px; fill: none; stroke: #fff; stroke-width: 1.8;
    filter: drop-shadow(0 1px 3px rgba(10,22,40,.5)); }
  .result-fav.active svg { fill: var(--gold-soft); stroke: var(--gold-soft); }

  /* caption: two columns, one type size, 16px below the image */
  .rc-caption {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 20px; padding-top: 16px;
  }
  .rc-left { min-width: 0; }
  .rc-right { text-align: right; flex: none; }
  .rc-name, .rc-sub, .rc-price, .rc-meta {
    font-family: var(--serif); font-size: 19px; font-weight: 400;
    line-height: 1.35; letter-spacing: 0.01em;
  }
  .rc-name  { color: var(--navy); }
  .rc-sub   { color: var(--muted); }
  .rc-price { color: var(--green); }
  .rc-meta  { color: var(--muted); }
  .result-card:hover .rc-name { text-decoration: underline; text-underline-offset: 3px; }

  @media (max-width: 900px) {
    .results-list { grid-template-columns: 1fr; row-gap: 40px; }
    .rc-name, .rc-sub, .rc-price, .rc-meta,
    .feat-name, .feat-sub, .feat-price { font-size: 17px !important; line-height: 22px !important; }
  }
  @media (max-width: 560px) {
    .rc-caption { flex-direction: column; gap: 6px; }
    .rc-right { text-align: left; }
  }


  /* ── Pagination ── */
  .paginate {
    display: flex; align-items: center; justify-content: center; gap: 4px;
    margin: 48px 0 0; padding: 24px 0; border-top: 1px solid var(--line);
  }
  .page-btn {
    width: 40px; height: 40px; display: flex; align-items: center; justify-content: center;
    border: none; border-radius: 8px; font-size: 14px; font-weight: 500;
    cursor: pointer; transition: all 180ms ease;
    background: transparent; color: var(--muted);
  }
  .page-btn:hover { background: var(--cream-2); color: var(--navy); }
  .page-btn.active {
    background: var(--navy); color: white;
    box-shadow: 0 2px 8px rgba(10,22,40,0.15);
  }
  .page-btn.nav {
    width: auto; padding: 0 16px; gap: 6px;
    font-weight: 600; color: var(--navy);
  }
  .page-btn.nav:hover { background: var(--cream-2); }
  .page-btn.dots { cursor: default; color: var(--line-2); letter-spacing: 2px; }
  .page-btn.dots:hover { background: transparent; }
  .page-info {
    font-size: 13px; color: var(--muted); margin: 0 12px;
  }

  /* ── Footer ── */
  .footer { background: var(--navy); color: white; padding: 48px 32px 32px; margin-top: 0; }
  .footer-inner { max-width: 1400px; margin: 0 auto; }
  .footer-top { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr 1fr; gap: 48px; margin-bottom: 48px; padding-bottom: 48px; border-bottom: 1px solid rgba(255,255,255,0.1); }
  .footer-col h5 { font-size: 13px; font-weight: 600; margin: 0 0 14px 0; text-transform: uppercase; letter-spacing: 0.05em; }
  .footer-col a { display: block; font-size: 13px; color: rgba(255,255,255,0.7); margin-bottom: 8px; transition: color 180ms ease; }
  .footer-col a:hover { color: white; }
  .brand-big { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
  .brand-big .mark { width: 32px; height: 32px; }
  .brand-big .word { font-family: var(--serif-display); font-size: 28px; letter-spacing: -0.01em; }
  .tag-line { font-size: 13px; color: rgba(255,255,255,0.6); font-style: italic; }
  .bottom-row { display: flex; justify-content: space-between; align-items: center; font-size: 12px; color: rgba(255,255,255,0.5); }
  .bottom-row a { color: rgba(255,255,255,0.7); transition: color 180ms ease; }
  .bottom-row a:hover { color: white; }

  /* ── Responsive ── */
  @media (max-width: 1024px) {
    .results-wrapper { grid-template-columns: 1fr; }
    .stats-inner { grid-template-columns: repeat(2, 1fr); }
    .stat-item:nth-child(2) { border-right: none; }
  }
  @media (max-width: 768px) {
    .hero { padding: 24px 16px; }
    .hero-search-wrap { flex-direction: column; gap: 8px; }
    .hero-search { flex-direction: column; }
    .hero-search-field + .hero-search-field { border-left: none; border-top: 1px solid #D0CCC4; }
    .hero-search-btn { border-radius: 12px; padding: 14px; width: 100%; aspect-ratio: auto; }
    .stats-inner { grid-template-columns: 1fr; }
    .stat-item { border-right: none; border-bottom: 1px solid rgba(250,248,243,0.08); }
    .stat-item:last-child { border-bottom: none; }
    .footer-top { grid-template-columns: 1fr; gap: 32px; }
  }
@keyframes pageExit {
  from { opacity: 1; transform: translateX(0); }
  to   { opacity: 0; transform: translateX(18px); }
}
body.page-exit {
  animation: pageExit 0.3s cubic-bezier(0.25, 0.1, 0.25, 1) both;
  pointer-events: none;
}

  /* =====================================================================
     THE TRADE CARD, ported from mason-set/results.html   ·  24 Aug 2026
     ---------------------------------------------------------------------
     WHAT THIS DOES NOT TOUCH, and that is the important half. `.result-card`,
     `.result-img`, `.slide-dot` and `.result-fav` all stay exactly where they
     were, because four separate scripts on this page reach for them: the
     filters and the sort (`querySelectorAll('.result-card')`), the three-image
     carousel (`.result-img img` and `.slide-dot`), the favourites, and the map
     pins (`.result-card[data-lat]`). Every data attribute is untouched. What
     is replaced is the caption, and what is added is the reveal.

     EVERY NEW CLASS IS `tc-`, DELIBERATELY. This page already owns `.rc-flag`,
     `.rc-rate`, `.rc-stars` and `.rc-av`, and the log records four class
     collisions in a single session with the note "grep the class before
     claiming it". So nothing here is called `rc-` anything.

     Tokens only, and only tokens this page actually declares. The mason file
     leans on --stone, --ease and the code-money pair, none of which exist
     here, so the curves are written out and the chips are built from --navy,
     --cream and --line-2.
     ===================================================================== */
  .tc { position: relative; display: block; text-decoration: none; color: inherit; }
  /* Square, and rounded, which is the change you actually see first. */
  .tc .result-img { aspect-ratio: 1 / 1; border-radius: 14px; overflow: hidden; }
  .tc .result-img img { filter: saturate(.82) contrast(.97);
    transition: opacity 420ms ease, transform 420ms cubic-bezier(.25, .1, .25, 1); }
  .tc:hover .result-img img.active { transform: scale(1.05); }
  @media (prefers-reduced-motion: reduce) { .tc .result-img img { transition: none; }
    .tc:hover .result-img img.active { transform: none; } }

  /* The flag was a centred label sitting ABOVE the card. It is a chip in the
     corner of the photograph now, which is where a placement badge belongs:
     on the thing it is describing. */
  .tc-flag { position: absolute; top: 12px; left: 12px; z-index: 3; line-height: 0; }
  .tc-chip { display: inline-flex; align-items: center; padding: 5px 11px; border-radius: 999px;
    font-family: var(--sans); font-size: 9px; font-weight: 500; letter-spacing: .14em;
    text-transform: uppercase; line-height: 1; white-space: nowrap; }
@media (max-width: 760px) { .tc-chip { font-size: 10.5px; } }  /* rp200 phone floor, was 9px */
  .tc-chip-navy { background: var(--navy); color: var(--cream); }
  /* Plain, NOT green. Green on this site means a thing checked, and neither
     "fast response" nor "new pro" is a check of anything. */
  .tc-chip-plain { background: rgba(250, 248, 243, .93); color: var(--navy);
    box-shadow: inset 0 0 0 1px var(--line-2);
    -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }

  .tc-cap { display: flex; align-items: flex-start; justify-content: space-between;
    gap: 14px; margin-top: 14px; }
  .tc-cap h3 { margin: 0; font-family: var(--serif); font-weight: 700; font-size: 15.5px;
    letter-spacing: .11em; text-transform: uppercase; color: var(--navy); line-height: 1.35; }
  .tc:hover .tc-cap h3 { text-decoration: underline; text-underline-offset: 3px; }
  /* Sir, 24 Aug: the card title is set in the wordmark's own face. HYYRYN is
     Inter 500 uppercase at 11px / .26em; this is that treatment scaled up, so
     the title belongs with the mark, the labels and the pills rather than with
     Caslon. Caslon keeps the reading text, the trade names and the numbers.
     This rule sits AFTER .tc-cap h3 deliberately: same specificity, later wins,
     and the original stays readable above it. */
  .tc-cap h3 { font-family: var(--sans); font-weight: 500; font-size: 13px;
    letter-spacing: .20em; }
  .tc-p { font-family: var(--serif); font-size: 16px; color: var(--navy);
    white-space: nowrap; font-variant-numeric: tabular-nums; }
  .tc-p small { display: block; font-family: var(--sans); font-size: 8.5px; font-weight: 500;
    letter-spacing: .13em; text-transform: uppercase; color: var(--muted);
    text-align: right; margin-bottom: 3px; }
@media (max-width: 760px) { .tc-p small { font-size: 10.5px; } }  /* rp200 phone floor, was 8.5px */

  /* EVERYTHING ELSE WAITS FOR THE POINTER, inside the card's own footprint.
     A max-height tween, because a card cannot tween to a height it does not
     know; 180px is measured against the tallest reveal, not guessed. */
  .tc-more { max-height: 0; overflow: hidden; opacity: 0;
    transition: max-height 320ms cubic-bezier(.16, 1, .3, 1), opacity 200ms cubic-bezier(.25, .1, .25, 1); }
  /* RETIRED 24 Aug: the whole card used to open the panel the instant the
     pointer touched any part of it, including the photograph. Replaced by the
     .tc-txt rule below, which asks for the text strip and half a second. */
  /* Touch has no hover, so the reveal is simply open there rather than
     unreachable. */
  @media (hover: none) { .tc-more { max-height: 180px; opacity: 1; } }
  @media (prefers-reduced-motion: reduce) { .tc-more { transition: none; } }

  .tc-who { display: flex; align-items: center; gap: 12px; margin-top: 10px; }
  .tc-who-t { min-width: 0; }
  .tc-face { width: 38px; height: 38px; flex: none; border-radius: 50%; object-fit: cover;
    filter: saturate(.82) contrast(.97);
    box-shadow: 0 0 0 1px var(--line), 0 1px 3px rgba(10, 22, 40, .20); }
  .tc-place { margin: 0; font-family: var(--serif); font-size: 14px; color: var(--ink); }

  /* FIVE STARS FROM ONE MASK. The empty ground is --line-2, the filled bar is
     a child at --pc wide in --gold, and the star shapes mask the PARENT, so
     both layers clip in one pass. That is what buys a true fractional fill:
     4.7 is 94 per cent of the bar, not a rounded-up fifth star. The gold is
     #83632C because decisions/rejected.md already settled that, after #B8941F
     measured 2.71 on cream. */
  .tc-rate { display: flex; align-items: center; gap: 7px; margin-top: 4px; }
  .tc-stars { position: relative; flex: none; width: 72px; height: 12px;
    background: var(--line-2);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 72 12' fill='black'%3E%3Cpath d='M6 .7 7.65 4.55 11.8 4.88 8.63 7.6 9.6 11.65 6 9.48 2.4 11.65 3.37 7.6 .2 4.88 4.35 4.55Z' transform='translate(0 0)'/%3E%3Cpath d='M6 .7 7.65 4.55 11.8 4.88 8.63 7.6 9.6 11.65 6 9.48 2.4 11.65 3.37 7.6 .2 4.88 4.35 4.55Z' transform='translate(15 0)'/%3E%3Cpath d='M6 .7 7.65 4.55 11.8 4.88 8.63 7.6 9.6 11.65 6 9.48 2.4 11.65 3.37 7.6 .2 4.88 4.35 4.55Z' transform='translate(30 0)'/%3E%3Cpath d='M6 .7 7.65 4.55 11.8 4.88 8.63 7.6 9.6 11.65 6 9.48 2.4 11.65 3.37 7.6 .2 4.88 4.35 4.55Z' transform='translate(45 0)'/%3E%3Cpath d='M6 .7 7.65 4.55 11.8 4.88 8.63 7.6 9.6 11.65 6 9.48 2.4 11.65 3.37 7.6 .2 4.88 4.35 4.55Z' transform='translate(60 0)'/%3E%3C/svg%3E") left center/72px 12px no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 72 12' fill='black'%3E%3Cpath d='M6 .7 7.65 4.55 11.8 4.88 8.63 7.6 9.6 11.65 6 9.48 2.4 11.65 3.37 7.6 .2 4.88 4.35 4.55Z' transform='translate(0 0)'/%3E%3Cpath d='M6 .7 7.65 4.55 11.8 4.88 8.63 7.6 9.6 11.65 6 9.48 2.4 11.65 3.37 7.6 .2 4.88 4.35 4.55Z' transform='translate(15 0)'/%3E%3Cpath d='M6 .7 7.65 4.55 11.8 4.88 8.63 7.6 9.6 11.65 6 9.48 2.4 11.65 3.37 7.6 .2 4.88 4.35 4.55Z' transform='translate(30 0)'/%3E%3Cpath d='M6 .7 7.65 4.55 11.8 4.88 8.63 7.6 9.6 11.65 6 9.48 2.4 11.65 3.37 7.6 .2 4.88 4.35 4.55Z' transform='translate(45 0)'/%3E%3Cpath d='M6 .7 7.65 4.55 11.8 4.88 8.63 7.6 9.6 11.65 6 9.48 2.4 11.65 3.37 7.6 .2 4.88 4.35 4.55Z' transform='translate(60 0)'/%3E%3C/svg%3E") left center/72px 12px no-repeat; }
  .tc-stars i { position: absolute; inset: 0 auto 0 0; width: var(--pc); background: var(--gold); }
  .tc-rate b { font-family: var(--serif); font-size: 13px; color: var(--navy);
    font-variant-numeric: tabular-nums; }

  .tc-acts { display: flex; gap: 10px; margin-top: 14px; }
  .tc-pill { height: 30px; padding: 0 13px; border-radius: 999px;
    border: 1px solid var(--line-2); background: transparent;
    font-family: var(--sans); font-size: 10px; font-weight: 500; letter-spacing: .1em;
    text-transform: uppercase; color: var(--navy);
    display: inline-flex; align-items: center;
    transition: background 160ms cubic-bezier(.25, .1, .25, 1); }
@media (max-width: 760px) { .tc-pill { font-size: 10.5px; } }  /* rp200 phone floor, was 10px */
  .tc:hover .tc-pill:hover { background: rgba(10, 22, 40, .05); }


  /* ---------------------------------------------------------------
     SQUARE, 24 AUG. The corner radius is gone and the well is a true
     1:1 on both card types, so a row of three reads as three squares
     rather than three nearly-squares. The featured band now runs the
     same component as the grid: same caption, same hidden reveal,
     same navy price. `.feat-cap`, `.feat-name`, `.feat-sub` and
     `.feat-price` have no elements left and their rules are dead.
     --------------------------------------------------------------- */
  .tc .result-img, .tc .feat-img { border-radius: 0; aspect-ratio: 1 / 1; }
  .tc .feat-img img { transition: opacity 420ms ease, transform 420ms cubic-bezier(.25, .1, .25, 1); }
  .tc:hover .feat-img img.active { transform: scale(1.05); }
  @media (prefers-reduced-motion: reduce) { .tc:hover .feat-img img.active { transform: none; } }

  /* FINER STARS, and the empty half recedes. Five solid geometric stars at
     12px were the least editorial thing on a page set in Libre Caslon. They
     are 10px now in a 60px bar, and the unspent portion moved from --line-2 to
     --line so the gold is what the eye lands on rather than the gaps. */
  .tc-stars { width: 60px; height: 10px; background: var(--line);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 10' fill='black'%3E%3Cpath d='M5 .58 6.375 3.79 9.83 4.07 7.19 6.33 8 9.71 5 7.9 2 9.71 2.81 6.33 .17 4.07 3.63 3.79Z' transform='translate(0 0)'/%3E%3Cpath d='M5 .58 6.375 3.79 9.83 4.07 7.19 6.33 8 9.71 5 7.9 2 9.71 2.81 6.33 .17 4.07 3.63 3.79Z' transform='translate(12.5 0)'/%3E%3Cpath d='M5 .58 6.375 3.79 9.83 4.07 7.19 6.33 8 9.71 5 7.9 2 9.71 2.81 6.33 .17 4.07 3.63 3.79Z' transform='translate(25 0)'/%3E%3Cpath d='M5 .58 6.375 3.79 9.83 4.07 7.19 6.33 8 9.71 5 7.9 2 9.71 2.81 6.33 .17 4.07 3.63 3.79Z' transform='translate(37.5 0)'/%3E%3Cpath d='M5 .58 6.375 3.79 9.83 4.07 7.19 6.33 8 9.71 5 7.9 2 9.71 2.81 6.33 .17 4.07 3.63 3.79Z' transform='translate(50 0)'/%3E%3C/svg%3E") left center/60px 10px no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 10' fill='black'%3E%3Cpath d='M5 .58 6.375 3.79 9.83 4.07 7.19 6.33 8 9.71 5 7.9 2 9.71 2.81 6.33 .17 4.07 3.63 3.79Z' transform='translate(0 0)'/%3E%3Cpath d='M5 .58 6.375 3.79 9.83 4.07 7.19 6.33 8 9.71 5 7.9 2 9.71 2.81 6.33 .17 4.07 3.63 3.79Z' transform='translate(12.5 0)'/%3E%3Cpath d='M5 .58 6.375 3.79 9.83 4.07 7.19 6.33 8 9.71 5 7.9 2 9.71 2.81 6.33 .17 4.07 3.63 3.79Z' transform='translate(25 0)'/%3E%3Cpath d='M5 .58 6.375 3.79 9.83 4.07 7.19 6.33 8 9.71 5 7.9 2 9.71 2.81 6.33 .17 4.07 3.63 3.79Z' transform='translate(37.5 0)'/%3E%3Cpath d='M5 .58 6.375 3.79 9.83 4.07 7.19 6.33 8 9.71 5 7.9 2 9.71 2.81 6.33 .17 4.07 3.63 3.79Z' transform='translate(50 0)'/%3E%3C/svg%3E") left center/60px 10px no-repeat; }
  .tc-rate { gap: 8px; }
  .tc-rate b { font-size: 13px; letter-spacing: .01em; }


  /* ---------------------------------------------------------------
     ONE BAND, NOT TWO.  24 Aug
     A white breadcrumb strip sat above the sticky filter bar and the
     words "Search results" appeared in both of them, once as a trail
     and once as a title. The trail has moved into the bar and taken
     the title's place, because the last crumb IS the title: the band
     now says where you are and what you can narrow, and it sticks
     while you scroll. `.results-bar`, `.results-bar-inner` and
     `.breadcrumb` have no elements left; their rules are dead.
     --------------------------------------------------------------- */
  .tmh-crumb { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
  .tmh-crumb a { font-family: var(--sans); font-size: 10.5px; font-weight: 600;
    letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
    transition: color 180ms cubic-bezier(.25, .1, .25, 1); }
  .tmh-crumb a:hover { color: var(--navy); }
  .tmh-crumb span { color: var(--line-2); font-size: 13px; }
  /* The last crumb carries the weight the title used to, so nothing is lost by
     deleting the title. */
  .tmh-crumb b { font-family: var(--serif-display); font-weight: 400; font-size: 19px;
    color: var(--navy); letter-spacing: .01em; white-space: nowrap; }
  @media (max-width: 720px) { .tmh-crumb b { font-size: 16px; } .tmh-crumb a { font-size: 9.5px; }
@media (max-width: 760px) { .tmh-crumb a { font-size: 10.5px; } }  /* rp200 phone floor, was 9.5px */ }


  /* =====================================================================
     THE PANEL ASKS FOR HALF A SECOND          ·  24 Aug 2026
     ---------------------------------------------------------------------
     The trigger is the TEXT STRIP, not the card. Crossing a photograph on
     the way somewhere else should not open anything, and the strip is the
     only part of the card that is about the words.

     The delay is a transition-delay, not a timer. CSS already knows how long
     the pointer has been inside a rule's subject; a setTimeout would have to
     be cleared on leave, on scroll, on blur and on the card being filtered
     out of the grid, and each of those is a place to leak one. Opening waits
     500ms. Closing does not wait at all, which is the asymmetry every
     hover-intent control wants: slow to commit, quick to let go.

     A keyboard user gets no delay. There is no accidental focus to protect
     against, so waiting would only be a wait.
     ===================================================================== */
  .tc-txt { position: relative; }

  /* The affordance. A chevron the width of a word, sitting in the band the
     panel will fill, aligned to the title above it so it reads as belonging
     to this card's text rather than floating in the gap. */
  .tc-hint { display: block; height: 20px; overflow: hidden; opacity: 1;
    transition: opacity 200ms cubic-bezier(.25, .1, .25, 1),
                height 260ms cubic-bezier(.16, 1, .3, 1); }
  .tc-hint svg { display: block; width: 13px; height: 13px; margin-top: 5px;
    fill: none; stroke: var(--muted); stroke-width: 1.5;
    stroke-linecap: round; stroke-linejoin: round; }

  @media (hover: hover) and (pointer: fine) {
    .tc-txt:hover .tc-more {
      max-height: 180px; opacity: 1;
      transition-delay: 500ms;
    }
    .tc-txt:hover .tc-hint { height: 0; opacity: 0; transition-delay: 500ms; }

    /* Focus is deliberate, so it opens at once. */
    .tc-txt:focus-within .tc-more { max-height: 180px; opacity: 1; transition-delay: 0ms; }
    .tc-txt:focus-within .tc-hint { height: 0; opacity: 0; transition-delay: 0ms; }
  }

  /* Touch has no hover and no pointer to wait for, so the panel is simply
     open and the chevron would be a promise about nothing. */
  @media (hover: none) { .tc-hint { display: none; } }

  /* §23, both ways: no tween, and the open state still declared. */
  @media (prefers-reduced-motion: reduce) {
    .tc-hint { transition: none; }
    .tc-txt:hover .tc-more, .tc-txt:focus-within .tc-more { transition-delay: 0ms; }
    .tc-txt:hover .tc-hint, .tc-txt:focus-within .tc-hint { transition-delay: 0ms; }
  }

/* ══ THE BOARD IS FIND A TRADE'S PAGE ═════════════════════  14 Oct 2026 (rp143) ══
   Sir: the board "should look exactly like the results page". The trade theme of 5 Sep (a navy masthead and bar,
   the ground half a tone down, navy "evening" cards with a navy caption band under the photograph) is taken off:
   the board is Find a trade's cream page, its cream bar and its card. What a job has that a listing does not stays,
   in Find a trade's own dress.

   THE ROLE, SAID IN WORDS, because nothing else on the page says it now: "For tradespeople" before the trail, in
   the gold the site uses for a label on cream (--gold, 5.6:1). */
body.trade .tmh-crumb:before{
  content:'For tradespeople';
  margin-right:14px; padding-right:14px;
  border-right:1px solid var(--line-2);
  font-family:var(--sans); font-size:9.5px; font-weight:600;
  letter-spacing:.17em; text-transform:uppercase; color:var(--gold);
  white-space:nowrap;
}
@media (max-width:900px){ body.trade .tmh-crumb:before{margin-right:10px; padding-right:10px} }
@media (max-width:640px){ body.trade .tmh-crumb:before{content:'Trade'} }
/* the sentence that stands in for a filter the platform cannot answer yet, in the bar's own muted ink */
.tmh-bar .f-none{
  margin:0; align-self:center;
  font-family:var(--serif); font-size:13px; color:var(--muted);
}

/* THE PROTECTED CHIP. It sits beside the card's own flag rather than replacing it: the flag says what is unusual
   about THIS job and this says what is true of ALL of them. Green, because green is a check on this site and
   payment protection is a thing the platform has done. Find a trade's chip in every other respect. */
.tc-chip-prot{
  display:inline-flex; align-items:center; gap:5px;
  background:var(--green); color:var(--cream);
}
/* the shield at the chip's own text size, so the chip is Find a trade's 19px and not 21 */
.tc-chip-prot svg{width:9px; height:9px; fill:currentColor; stroke:none; flex:none}
.tc-flag{display:flex; gap:6px; flex-wrap:wrap}
.feat-img .tc-flag{position:absolute; top:12px; left:12px; z-index:3}

/* Find a trade's later fixes to the shared card: a kept bookmark shows without the pointer; the distance chip; a
   score's count */
.result-fav.active { opacity: 1; }
.tc-chip + .tc-chip-dist { margin-left: 6px; }
.tc-rate .tc-n { font-family: var(--sans); font-size: 11.5px; color: var(--muted, #636976); }


/* A POSTED JOB WITH NO PHOTOGRAPHS. The frame stays, so the grid does not
   stagger, and the ground says plainly that there is nothing to look at rather
   than showing a broken image or a stock photograph of somebody else's work. */
.result-img.is-nopix,
.feat-img.is-nopix{
  display:grid; place-items:center;
  /* --navy at 88% over --cream-2, resolved (rp143): Find a trade's colour-mix, written as the rgb() it computes to,
     because color-mix computes to color(srgb ...), which the gate cannot read, and it then measured the job's own
     words as cream on cream. With the evening card gone, the well is the words' only ground. */
  background:rgb(38,48,63);
}
.result-img.is-nopix:after{
  content:attr(data-shots); font-family:var(--sans); font-size:11px;
  font-weight:500; letter-spacing:.16em; text-transform:uppercase;
  color:rgba(250,248,243,.62);
}


  /* ══ AN EMPTY BOARD SAYS SO ═══════════════════════════════  6 Sep 2026 ══
     Sir cut this board to one job so that deleting it could be watched. That
     makes empty a state a reader will actually reach, and an empty state is
     part of the page rather than what is left when the page has nothing. It
     sits on the same ground as a card, at the same width, so the column does
     not collapse to a line of grey text where a listing was a moment ago. */
  .board-empty {
    grid-column: 1 / -1;
    padding: clamp(38px, 5vw, 66px) clamp(24px, 4vw, 48px);
    border: 1px solid var(--line);
    background: var(--cream);
    text-align: center;
  }
  .be-t {
    font-family: var(--serif); font-size: clamp(21px, 2vw, 26px);
    color: var(--navy); margin: 0;
  }
  .be-s {
    font-family: var(--sans); font-size: 14px; line-height: 1.65;
    color: var(--muted); margin: 10px auto 0; max-width: 44ch;
  }
  /* The remaining cells of a short row. Quieter than a card and on the same
     ground, so the row reads as a row rather than as a card and a hole. */
  .board-more {
    display: grid; align-content: center; justify-items: center;
    text-align: center; padding: clamp(30px, 4vw, 54px) clamp(18px, 2.4vw, 34px);
    border-left: 1px solid var(--line);
  }
  .bm-t {
    font-family: var(--serif); font-size: clamp(17px, 1.5vw, 20px);
    color: var(--navy); margin: 0;
  }
  .bm-s {
    font-family: var(--sans); font-size: 12.5px; line-height: 1.6;
    color: var(--muted); margin: 8px 0 0; max-width: 30ch;
  }
  @media (max-width: 900px) { .board-more { display: none; } }
  /* A grid or a flex box outranks the `hidden` attribute, so each of these
     has to be told again. */
  .featured[hidden] { display: none; }
  .pager[hidden], .feat-arrow[hidden] { display: none; }

  /* ══ THE PHONE PASS ═══════════════════════════════════════  6 Sep 2026 ══
     Sir asked for the 375 overflow. Three real causes, each one measured to
     the element rather than guessed at, and one that looked guilty and was
     not: the account drawer is `position:fixed`, so it hangs off the right
     without adding a pixel to the document, and `service.html` carries the
     same drawer at 375 with no overflow at all. It was never the drawer.

     1 · THE SEARCH BUTTON. `.nm-search-row` is 295 wide and the button is
         116, on a row that will not wrap. Two fields, a rule and a button
         cannot sit on 295px of phone, so below 560 the row becomes a column:
         the divider goes, the location field takes its own line, and the
         button spans. Nothing is hidden; it is the same four things stacked.

     2 · THE FILTER PANEL. It is absolutely positioned inside its own group,
         and under 720 the sheet already flipped from `right:0` to `left:0`.
         That is the right move for the FIRST group and the wrong one for the
         last: at 375 the last group starts at 281 and a 216px panel off its
         left edge ends at 497. The panel now hangs off the BAR rather than
         the group, spanning it, which is where a filter sheet belongs on a
         phone anyway.

     3 · THE ACTION LINK. `.ev-act` is a nowrap flex row, so a 143px link on
         a line that had 90px left pushed the page out by 52. It wraps. */
  @media (max-width: 560px) {
    .nm-search-row { flex-wrap: wrap; }
    .nm-search-row .nm-div { display: none; }
    .nm-search-row .nm-field,
    .nm-search-row .nm-field-loc { flex: 1 1 100%; min-width: 0; }
    .nm-search-row .nm-go { width: 100%; padding: 15px 0; }
  }
  @media (max-width: 720px) {
    /* The sheet resolves against the bar, so `.f-group` gives up being the
       containing block for the length of this breakpoint. */
    .tmh-filters { position: relative; }
    .tmh-filters .f-group { position: static; }
    .tmh-filters .f-group .f-body {
      right: 0; left: 0; min-width: 0; width: auto;
    }
  }

/* ══ ONE LOGOTYPE, IN THE FOOTER TOO ═══════════════════════════  7 Sep 2026 ══
   The masthead sets HYYRYN in Inter 500, uppercase, .26em of tracking; the
   footer set Hyyryn in Libre Caslon Display, sentence case, no tracking. A
   logotype is one thing or it is not a logotype, and the masthead's is the one
   on every page and on the Facebook Page. Scaled by the masthead's own ratio,
   16 to 11 in the head and 20 to 13.5 in the foot, with literal fallbacks
   because ten of these pages declare no tokens at all. Appended at the end so
   it wins on order without editing a rule in place. */
.footer .brand-big{gap:13px}
.footer .brand-big .mark{width:20px; height:20px}
.footer .brand-big .word{
  font-family:var(--sans, Inter, system-ui, sans-serif); font-size:13.5px; font-weight:500;
  letter-spacing:.26em; text-transform:uppercase; line-height:1;
  color:var(--cream, #FAF8F3); margin-right:-.26em;
}

/* `[hidden]` is a UA rule at the lowest weight there is, so any author
   `display` beats it and an element a script hides stays on the page. */
[hidden] { display: none !important; }


/* ══ BUTTONS AND ICONS TAKE NAVY ══════════════════════════════ 11 Sep 2026 ══
   Sir: keep the buttons and icon navy just like the homeowner dashboard.

   These four pages define the green as their GENERAL ACCENT and spend it on
   everything: avatars, focus rings, breadcrumbs, links, the search button, the
   checkbox tick, the open state of a select. The homeowner dashboard spends
   navy on all of those and keeps green for one thing only.

   §22 says colour is placed by meaning and never to even out a page, and the
   code is three wide: green is money that completed the protection loop or a
   thing checked, navy is the platform's own guarantee, gold is waiting. An
   accent green on a breadcrumb is not a meaning, it is a house style, and it
   costs the green that IS a meaning its whole signal.

   WHAT STAYS GREEN, and it is the whole of what should be: a completed step
   and its dot, a filled progress bar, a state pill, a job pill reading
   complete or funded, a system line about money arriving, a Gas Safe or
   certification mark, and the protected chip. Everything else is navy.

   Additive, at the end of the sheet, so later wins and the whole pass is
   reversible by deleting one block. Generated from the page's own green-
   bearing rules rather than written by hand, so nothing was missed and
   nothing was invented. */
:focus-visible { outline: 2px solid var(--navy); }
input:focus, textarea:focus, select:focus { border-color: var(--navy); box-shadow: 0 0 0 3px rgba(10,22,40,0.08); }
.icon-badge.green { background: var(--navy); }
.avatar-btn .av-img { background: linear-gradient(135deg, var(--navy-3), var(--navy)); }
.avatar-btn:hover .av-img { border-color: var(--navy); }
.pd-av { background: linear-gradient(135deg, var(--navy-3), var(--navy)); }
.notifications-header a { color: var(--navy); }
.notification-item.unread { background: rgba(10,22,40,0.03); }
.notifications-footer a { color: var(--navy); }
.loc-detect svg { stroke: var(--navy); }
.hero-search-btn { color: var(--navy); border: 1.5px solid var(--navy); }
.hero-search-btn svg { stroke: var(--navy); }
.hero-search-btn:hover { background: var(--navy); }
.search-dropdown-item mark { color: var(--navy); }
.filters-head a:hover { color: var(--navy); }
.f-group h4:hover { color: var(--navy); }
.f-check input[type="checkbox"]:checked { background: var(--navy); border-color: var(--navy); }
.show-more { color: var(--navy); }
.custom-select.open .custom-select-trigger { border-color: var(--navy); box-shadow: 0 0 0 3px rgba(10,22,40,0.08); }
.custom-select-option.selected { color: var(--navy); }
.nm-field-loc .loc-detect svg { stroke: var(--navy); }
.nm-field-loc .loc-detect svg { stroke: var(--navy); }
.rc-price, .feat-price { color: var(--navy) !important; }
.rc-price { color: var(--navy); }

/* ══ THE LABEL FLOOR IS 9.5px ═════════════════════════════════ 11 Sep 2026 ══
   Sir: make sure all figures and text shown in tabs are readable.

   Six labels on these pages render at 8.5px, "Budget", "miles", "to Hyyryn",
   "5%", a full point under the site's own label spec, which Mason's measured
   values put at 9.5px, weight 500, .17em, uppercase, and calls the single
   most-copied-wrong value on the site. Under 9px nothing is a label any more,
   it is a watermark.

   The tracking is what makes a small label legible rather than the size, so
   the size goes up and the rest of the spec comes with it. */
.mn-d small, .js-pie-k, .js-pie-k b,
.jd-c small, .rs-meta-item small, .ps-num small { font-size: 9.5px; letter-spacing: .14em; }
/* rp143: not the card's "Budget". The card is Find a trade's card, "From" over the price at its size there. */

/* ══ JUST POSTED SITS ON THE PAGE ═════════════════════════════════════  14 Oct 2026 (rp144) ══
   Sir: "I don't like the slight container around the cards. The just posted container ... can be removed. The cards
   can just be on the background ... just like the all job section where there's no container around it."
   The recess of 4 Sep (a --cream-2 field, a gold rule at its head, four inset shadows) was drawn for a band of PAID
   placements, to say "this row is different". Nothing on this board is paid for; the row is the three newest jobs.
   So it is a section of the page like All jobs: its label, its sentence, the same cards on the same ground, and its
   two arrows level with the label at the right edge of the column. */
.featured {
  margin: 4px 0 56px; padding: 0;
  background: none; border: 0; box-shadow: none;
}
.feat-arrow { top: -8px; }
.feat-prev { right: 38px; }
.feat-next { right: 0; }

/* rp157 (17 Oct 2026, the launch-day pass): the bookmark that saves a job appears on hover, and a phone has no hover,
   so on a phone a trade could not see how to save a job from the board or from Saved. Touch screens show it. */
@media (hover: none) { .result-fav { opacity: 1; } }
