/*
 * Flathunt — the design system. Direction: "calma precisa".
 *
 * A data-dense tool that feels airy (Linear/Things/Stripe lineage). The one idea
 * everything derives from: SPACE ORGANIZES, NOT CHROME. We get calm-at-density by
 * structuring with whitespace + alignment (not boxes/fills), an almost-monochrome
 * palette where COLOR MEANS EXACTLY ONE THING, and hierarchy by TYPE WEIGHT.
 *
 * Single Propshaft-served stylesheet, organized into cascade layers so the
 * cascade is predictable regardless of source order:
 *
 *   tokens      — design tokens on :root (color, type, space, radius, shadow, motion)
 *   base        — reset-ish element baselines, body, links, focus, motion guard
 *   components  — every UI component, built only from tokens
 *   utilities   — small helpers (must win over components)
 *
 * Everything derives from the tokens — never raw hex/px in components.
 *
 * Two naming planes coexist on purpose:
 *   - the SPEC tokens (--accent, --green, --bg, --ink, …) are the canonical
 *     vocabulary from the design spec §3; new components compose with these;
 *   - the legacy --c-* / --status-* aliases (kept for the large existing
 *     component library below) are REMAPPED onto the spec tokens here, so every
 *     existing component restyles to the new palette for free while later phases
 *     migrate markup to the canonical names.
 */

@layer tokens, base, components, utilities;

/* ===========================================================================
   FONTS — Inter only, self-hosted variable woff2. (Fraunces dropped: the new
   direction is hierarchy-by-weight, no display serif.) Referenced by bare
   filename (app/assets/fonts is on the Propshaft load path).
   =========================================================================== */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/assets/inter-latin-wght-normal-1f021a24.woff2") format("woff2");
}
@font-face {
  font-family: "Inter";
  font-style: italic;
  font-weight: 100 900;
  font-display: swap;
  src: url("/assets/inter-latin-wght-italic-7c529059.woff2") format("woff2");
}

/* ===========================================================================
   TOKENS  (spec §3)
   =========================================================================== */
@layer tokens {
  :root {
    /* ---- COLOR = MEANING (five colours, five meanings) ----------------- */
    /* navigation: new, selected, links, primary action */
    --accent:        #2563EB;   /* cobalt — confident, far from every status hue */
    --accent-hover:  #1D4FD7;
    --accent-tint:   #E7EDFD;   /* accent backgrounds (selected row, pill) */
    /* confidence / verified / success */
    --green:         #2E9E6E;
    --green-bg:      #E7F6EF;
    /* in-progress / checking / warning */
    --amber:         #C98800;
    --amber-bg:      #FBF1DC;
    /* danger / discard / dealbreaker */
    --red:           #D5475F;
    --red-bg:        #FCE9EC;

    /* ---- SURFACES & TEXT (greys; everything non-meaningful) ------------ */
    --bg:            #F7F8FA;   /* page background — lets white cards float = airy */
    --surface:       #FFFFFF;   /* cards, table, panel, sidebar */
    --surface-2:     #F2F3F5;   /* hover fill, insets, neutral pill bg */
    --line:          #EEEFF2;   /* hairlines, borders */
    --input-border:  #E1E3EA;   /* input borders (slightly stronger than line) */
    --ink:           #15181E;   /* headings, strong data */
    --text:          #3D424C;   /* body */
    --muted:         #6B7280;   /* secondary, labels, captions — 4.8:1 on white (WCAG AA) */
    --faint:         #B8BCC4;   /* placeholder, disabled, "–" */

    /* ---- LEGACY ALIASES → spec tokens --------------------------------- */
    /* The component library below is written against these names; remapping
       them here repaints the whole app to "calma precisa" without touching the
       (working, tested) component selectors or the views. */
    --c-paper:         var(--bg);
    --c-surface:       var(--surface);
    --c-surface-2:     var(--surface-2);
    --c-surface-3:     var(--surface-2);

    --c-ink:           var(--ink);
    --c-text:          var(--text);
    --c-text-muted:    var(--muted);
    --c-text-subtle:   var(--faint);

    --c-border:        var(--line);
    --c-border-strong: var(--input-border);

    --c-accent:        var(--accent);
    --c-accent-hover:  var(--accent-hover);
    --c-accent-deep:   var(--accent-hover);
    --c-accent-tint:   var(--accent-tint);
    --c-accent-tint-2: #E0E0FB;          /* a touch denser than --accent-tint */
    --c-on-accent:     #FFFFFF;
    --c-focus:         rgba(37, 99, 235, 0.30);

    /* primary == accent (some reaction styles reference --c-primary*). */
    --c-primary:       var(--accent);
    --c-primary-tint:  var(--accent-tint);

    --c-gold:          #C98800;          /* shortlist star — reuses amber */
    --c-success:       var(--green);
    --c-success-tint:  var(--green-bg);
    --c-warning:       var(--amber);
    --c-warning-tint:  var(--amber-bg);
    --c-danger:        var(--red);
    --c-danger-tint:   var(--red-bg);

    /* ---- Status / pipeline whisper palette ---------------------------- */
    /* Confidence is the hero status (green/amber/grey). Contact/outcome are a
       secondary whisper — neutral grey except the two meaningful endpoints
       (secured → green, discarded → muted). Per spec §5, no decorative colour. */
    --status-seen:            var(--muted);
    --status-seen-tint:       var(--surface-2);
    --status-interested:      var(--muted);
    --status-interested-tint: var(--surface-2);
    --status-contacted:       var(--muted);
    --status-contacted-tint:  var(--surface-2);
    --status-replied:         var(--amber);
    --status-replied-tint:    var(--amber-bg);
    --status-visit:           var(--accent);
    --status-visit-tint:      var(--accent-tint);
    --status-applied:         var(--accent);
    --status-applied-tint:    var(--accent-tint);
    --status-secured:         var(--green);
    --status-secured-tint:    var(--green-bg);
    --status-discarded:       var(--faint);
    --status-discarded-tint:  var(--surface-2);

    /* ---- TYPOGRAPHY — Inter only, hierarchy by WEIGHT ------------------ */
    --font-sans:  "Inter", ui-sans-serif, -apple-system, "Segoe UI", Roboto, system-ui, sans-serif;
    /* No display serif anymore: --font-serif aliases the sans stack so any
       legacy `font-family: var(--font-serif)` renders in Inter. */
    --font-serif: var(--font-sans);
    --serif-settings: normal;
    /* Mono numerals are the signature: every figure (price, €/m², m², counts)
       reads as a precision instrument. System stack — same one the URL cells
       already use, so nothing new to vendor. */
    --font-mono:  ui-monospace, "SF Mono", "JetBrains Mono", "Cascadia Code", Menlo, Consolas, monospace;

    /* Data-dense scale (base 13.5px): 11 · 12.5 · 13.5(base) · 15 · 17 · 20 · 24 · 30. */
    --text-xs:   0.6875rem;  /* 11   — eyebrows, column headers, micro-meta */
    --text-2xs:  0.78125rem; /* 12.5 — small captions */
    --text-sm:   0.84375rem; /* 13.5 — base alias for "small" usages */
    --text-base: 0.84375rem; /* 13.5 — body & table data (the working size) */
    --text-md:   0.9375rem;  /* 15 */
    --text-lg:   1.0625rem;  /* 17 */
    --text-xl:   1.25rem;    /* 20   — section titles */
    --text-2xl:  1.5rem;     /* 24 */
    --text-3xl:  1.875rem;   /* 30   — price hero / page titles */
    --weight-normal: 400;
    --weight-medium: 500;
    --weight-semibold: 600;
    --weight-bold: 700;      /* pills / badges */

    /* ---- SPACE  (4 · 8 · 12 · 16 · 24 · 32 · 48) ---------------------- */
    --space-1:  4px;
    --space-2:  8px;
    --space-3:  12px;
    --space-4:  16px;
    --space-5:  20px;
    --space-6:  24px;
    --space-8:  32px;
    --space-10: 40px;
    --space-12: 48px;
    --space-16: 64px;

    /* ---- RADIUS  (inputs/buttons 10 · cards/table/panel 14–16 · pill) -- */
    --radius-xs: 6px;
    --radius-sm: 8px;
    --radius-md: 10px;   /* inputs, buttons */
    --radius-lg: 14px;   /* cards, table, panel */
    --radius-xl: 16px;
    --radius-pill: 999px;

    /* ---- SHADOW  (xs rest · sm hover · lg panel/menus) ---------------- */
    --shadow-xs: 0 1px 2px rgba(20, 24, 30, 0.05);
    --shadow-sm: 0 2px 6px rgba(20, 24, 30, 0.07);
    --shadow-md: 0 6px 16px rgba(20, 24, 30, 0.10);
    --shadow-lg: 0 12px 32px rgba(20, 24, 30, 0.14);

    /* ---- MOTION  (120–160ms ease-out) -------------------------------- */
    --ease: cubic-bezier(0.2, 0, 0, 1);
    --dur-fast: 120ms;
    --dur: 160ms;

    /* ---- LAYOUT ------------------------------------------------------- */
    --container: 1120px;
    --page-pad: var(--space-6);
    --header-h: 56px;            /* sticky app-header height (anchor for sticky offsets) */
    --focus-offset: 2px;

    /* ---- Overlay drawer (the recap detail) ---------------------------- */
    --panel-w: 27.5rem;         /* ~440px per spec §6 */
    --scrim: rgba(20, 24, 30, 0.16);

    /* ---- Recap table column widths (tokenized so head/body/candidate share) */
    --col-check:     1.75rem;   /* compare / select checkbox */
    --col-flag:      1.5rem;    /* shortlist marker */
    --col-reactions: 5.5rem;
    --col-price:     6.5rem;
    --col-status:    10rem;     /* confidence pill + contextual whisper */
  }
}

/* ===========================================================================
   BASE
   =========================================================================== */
@layer base {
  *, *::before, *::after { box-sizing: border-box; }

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

  body {
    margin: 0;
    font-family: var(--font-sans);
    font-size: var(--text-base);
    line-height: 1.5;
    color: var(--c-text);
    background: var(--c-paper);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
  }

  /* Hierarchy by WEIGHT, not colour or serif. Headings ≥20px get the optical
     tightening from spec §3. */
  h1, h2, h3, h4 {
    color: var(--ink);
    font-family: var(--font-sans);
    line-height: 1.2;
    font-weight: var(--weight-semibold);
    margin: 0;
  }
  h1 { font-size: var(--text-2xl); letter-spacing: -0.01em; }
  h2 { font-size: var(--text-xl); letter-spacing: -0.01em; }
  h3 { font-size: var(--text-lg); }
  h4 { font-size: var(--text-md); }

  p { margin: 0; }

  /* Numbers are always tabular AND monospaced — the signature. Every figure
     (price, €/m², m², counts) reads as a precision instrument. */
  .num,
  [class*="price"],
  table .num {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
  }

  a {
    color: var(--accent);
    text-decoration: none;
    transition: color var(--dur-fast) var(--ease);
  }
  a:hover { color: var(--accent-hover); }

  strong, b { font-weight: var(--weight-semibold); }

  /* Soft violet-halo focus ring (spec §8). */
  :focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: var(--focus-offset);
    border-radius: var(--radius-xs);
  }
  :focus:not(:focus-visible) { outline: none; }

  ::placeholder { color: var(--faint); }

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

/* ===========================================================================
   COMPONENTS
   =========================================================================== */
@layer components {

  /* --- App shell: fixed sidebar + scrolling main --------------------- */
  .svg-defs { position: absolute; }

  .app-shell { min-height: 100dvh; }
  .app-shell-auth { display: flex; align-items: stretch; }
  .app-main { flex: 1; min-width: 0; }

  /* Eyebrow labels (uppercase micro-titles) stay in the sans face even when the
     element is an <h2>, so the serif is reserved for true display text. */
  .section-legend,
  .form-section > legend,
  .dash-card-title,
  .detail-section-title,
  .show-section > h2,
  .inline-form-title,
  .picker-eyebrow {
    font-family: var(--font-sans);
    font-variation-settings: normal;
    letter-spacing: 0.06em;
  }
  /* --- Sidebar ------------------------------------------------------- */
  :root { --sidebar-w: 236px; --sidebar-rail: 54px; }

  .sidebar {
    position: sticky;
    top: 0;
    align-self: flex-start;
    height: 100dvh;
    width: var(--sidebar-w);
    flex: none;
    display: flex;
    flex-direction: column;
    padding: var(--space-3) var(--space-2);
    background: var(--surface);
    border-right: 1px solid var(--line);
    transition: width var(--dur) var(--ease);
  }

  .sidebar-brand {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-1) var(--space-2) var(--space-3);
  }
  .sidebar-wordmark {
    font-size: var(--text-lg);
    font-weight: var(--weight-bold);
    letter-spacing: -0.01em;
    color: var(--ink);
    white-space: nowrap;
  }
  .sidebar-wordmark:hover { color: var(--ink); }
  .sidebar-wordmark b { color: var(--accent); font-weight: var(--weight-bold); }
  .sidebar-collapse {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--faint);
    cursor: pointer;
    transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
  }
  .sidebar-collapse:hover { background: var(--surface-2); color: var(--muted); }

  .sidebar-new {
    height: auto;
    padding: var(--space-2) var(--space-3);
    margin: 0 var(--space-1) var(--space-2);
    width: calc(100% - 2 * var(--space-1));
    font-size: var(--text-base);
  }

  .sidebar-nav { display: flex; flex-direction: column; overflow-y: auto; overflow-x: hidden; }
  .sidebar-group {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--muted);
    font-weight: var(--weight-bold);
    padding: var(--space-3) var(--space-3) var(--space-1);
    white-space: nowrap;
  }
  .sidebar-item {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    color: var(--text);
    font-weight: var(--weight-medium);
    white-space: nowrap;
    transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
  }
  .sidebar-item:hover { background: var(--surface-2); color: var(--ink); }
  .sidebar-item.is-active { background: var(--accent-tint); color: var(--accent); }
  .sidebar-icon-wrap { position: relative; display: inline-flex; flex: none; }
  .sidebar-icon { width: 17px; height: 17px; color: var(--muted); }
  .sidebar-item:hover .sidebar-icon { color: var(--ink); }
  .sidebar-item.is-active .sidebar-icon { color: var(--accent); }
  .sidebar-label { flex: 1; overflow: hidden; text-overflow: ellipsis; }
  .sidebar-count {
    flex: none;
    font-size: var(--text-xs);
    font-weight: var(--weight-bold);
    color: var(--accent);
    background: var(--accent-tint);
    border-radius: var(--radius-pill);
    padding: 1px var(--space-2);
    font-variant-numeric: tabular-nums;
  }
  /* Collapsed: the rail shows an accent dot on inboxes with pending work. */
  .sidebar-dot {
    display: none;
    position: absolute;
    top: -2px;
    right: -2px;
    width: 7px;
    height: 7px;
    border-radius: var(--radius-pill);
    background: var(--accent);
    border: 1.5px solid var(--surface);
  }

  .sidebar-spacer { flex: 1; }

  .sidebar-account { margin-top: var(--space-2); border-top: 1px solid var(--line); }
  .sidebar-account-summary {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-2);
    list-style: none;
    cursor: pointer;
    border-radius: var(--radius-sm);
  }
  .sidebar-account-summary::-webkit-details-marker { display: none; }
  .sidebar-account-summary:hover { background: var(--surface-2); }
  .sidebar-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 26px;
    height: 26px;
    border-radius: var(--radius-pill);
    background: var(--accent);
    color: var(--c-on-accent);
    font-size: var(--text-2xs);
    font-weight: var(--weight-bold);
  }
  .sidebar-account-email {
    font-size: var(--text-2xs);
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* --- Collapsed rail (icons only) ----------------------------------- */
  .app-shell.is-collapsed .sidebar { width: var(--sidebar-rail); }
  .app-shell.is-collapsed .sidebar-label { display: none; }
  .app-shell.is-collapsed .sidebar-brand { justify-content: center; padding-inline: 0; }
  .app-shell.is-collapsed .sidebar-wordmark { display: none; }
  .app-shell.is-collapsed .sidebar-collapse { transform: rotate(180deg); }
  .app-shell.is-collapsed .sidebar-new { justify-content: center; padding-inline: 0; }
  .app-shell.is-collapsed .sidebar-group { text-align: center; padding-inline: 0; color: transparent; height: var(--space-2); overflow: hidden; }
  .app-shell.is-collapsed .sidebar-item { justify-content: center; padding-inline: 0; }
  .app-shell.is-collapsed .sidebar-count { display: none; }
  .app-shell.is-collapsed .sidebar-item-inbox .sidebar-dot { display: block; }
  .app-shell.is-collapsed .sidebar-account-summary { justify-content: center; }

  /* Top-bar dropdown menus (Account). */
  .app-menu { position: relative; }
  .app-menu > summary { list-style: none; cursor: pointer; user-select: none; }
  .app-menu > summary::-webkit-details-marker { display: none; }
  .app-menu-list {
    position: absolute;
    left: 0;
    top: calc(100% + var(--space-2));
    min-width: 11rem;
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: var(--space-2);
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    z-index: 30;
  }
  /* Opens above the trigger — must follow .app-menu-list to win on source order
     (equal specificity), otherwise the base `top` reasserts and the menu drops
     downward off the bottom of the viewport. The account menu lives at the foot
     of the sidebar, so it always opens upward. */
  .app-menu-list-up { top: auto; bottom: calc(100% + var(--space-1)); }
  .app-menu-link {
    display: block;
    width: 100%;
    text-align: left;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius-sm);
    color: var(--c-text);
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
  }
  .app-menu-link:hover { background: var(--c-surface-2); color: var(--c-ink); }
  .app-menu-link.is-active { background: var(--c-accent-tint); color: var(--c-accent-deep); }
  .app-menu-button { border: 0; background: transparent; font: inherit; cursor: pointer; }
  .app-menu form { margin: 0; }
  .app-menu-email {
    display: block;
    padding: var(--space-2) var(--space-3) var(--space-3);
    margin-bottom: var(--space-1);
    border-bottom: 1px solid var(--c-border);
    color: var(--c-text-muted);
    font-size: var(--text-xs);
    word-break: break-all;
  }
  .app-menu-locale {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
  }
  .app-menu-locale-label {
    color: var(--c-text-muted);
    font-size: var(--text-xs);
  }
  .app-menu-locale-options {
    display: inline-flex;
    gap: 2px;
    padding: 2px;
    background: var(--c-surface-2);
    border-radius: var(--radius-pill);
  }
  .app-menu-locale-option {
    border: 0;
    cursor: pointer;
    padding: 2px var(--space-2);
    border-radius: var(--radius-pill);
    background: transparent;
    color: var(--c-text-muted);
    font: inherit;
    font-size: var(--text-2xs);
    font-weight: var(--weight-medium);
  }
  .app-menu-locale-option:hover { color: var(--c-ink); }
  .app-menu-locale-option.is-active {
    background: var(--c-surface);
    color: var(--c-ink);
    box-shadow: var(--shadow-sm);
  }
  .app-menu-locale form { margin: 0; }

  /* --- Breadcrumbs ---------------------------------------------------- */
  .breadcrumbs { margin-bottom: var(--space-4); }
  .breadcrumbs ol {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    list-style: none;
    margin: 0;
    padding: 0;
    font-size: var(--text-sm);
    color: var(--c-text-muted);
  }
  .breadcrumbs li { display: flex; align-items: center; gap: var(--space-2); }
  .breadcrumbs li + li::before {
    content: "/";
    color: var(--c-text-subtle);
  }
  .breadcrumbs a { color: var(--c-text-muted); }
  .breadcrumbs a:hover { color: var(--c-accent); }
  .breadcrumbs [aria-current="page"] { color: var(--c-ink); font-weight: var(--weight-medium); }

  .container {
    max-width: var(--container);
    margin-inline: auto;
    padding: var(--space-8) var(--page-pad) var(--space-16);
  }

  /* --- Page header ---------------------------------------------------- */
  .page-header {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--space-4);
    margin-bottom: var(--space-6);
  }
  .page-header .page-title {
    margin: 0;
    font-size: var(--text-3xl);
    font-weight: var(--weight-semibold);
    letter-spacing: -0.01em;
    line-height: 1.1;
  }
  .page-eyebrow {
    display: block;
    font-family: var(--font-sans);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--c-accent);
    margin-bottom: var(--space-2);
  }
  .page-subtitle { color: var(--c-text-muted); margin-top: var(--space-2); font-size: var(--text-md); max-width: 52ch; }
  .page-header .actions { flex: none; }

  /* --- Flashes -------------------------------------------------------- */
  .flash {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    border: 1px solid var(--c-border);
    margin-bottom: var(--space-4);
    font-size: var(--text-base);
  }
  .flash-notice { background: var(--c-success-tint); border-color: color-mix(in oklch, var(--c-success) 35%, var(--c-border)); color: var(--c-ink); }
  .flash-alert  { background: var(--c-danger-tint);  border-color: color-mix(in oklch, var(--c-danger) 35%, var(--c-border));  color: var(--c-ink); }

  /* --- Buttons -------------------------------------------------------- */
  /* Flat, calm buttons. Meaning carried by fill (primary=accent, danger=red),
     never by gradient/chrome. md = 40px, sm = 32px; radius 10. */
  .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    height: 40px;
    padding: 0 var(--space-4);
    border-radius: var(--radius-md);
    border: 1px solid var(--input-border);
    background: var(--surface);
    color: var(--ink);
    font: inherit;
    font-size: var(--text-base);
    font-weight: var(--weight-semibold);
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    text-decoration: none;
    transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease),
                color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
  }
  .btn:hover { text-decoration: none; background: var(--surface-2); }
  .btn-sm { height: 32px; padding: 0 var(--space-3); font-size: var(--text-2xs); }

  /* Primary: solid accent — the one action the eye should find first. */
  .btn-primary {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--c-on-accent);
  }
  .btn-primary:hover {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
    color: var(--c-on-accent);
  }

  .btn-secondary {
    background: var(--surface);
    border-color: var(--input-border);
    color: var(--ink);
  }
  .btn-secondary:hover { background: var(--surface-2); color: var(--ink); }

  .btn-ghost {
    background: transparent;
    border-color: transparent;
    color: var(--muted);
  }
  .btn-ghost:hover { background: var(--surface-2); color: var(--ink); }

  .btn-danger {
    background: var(--surface);
    border-color: color-mix(in srgb, var(--red) 35%, var(--line));
    color: var(--red);
  }
  .btn-danger:hover { background: var(--red-bg); color: var(--red); border-color: color-mix(in srgb, var(--red) 35%, var(--line)); }

  .btn[disabled], .btn:disabled { opacity: 0.5; cursor: not-allowed; }

  /* A bare text button (e.g. button_to that should look like a link) */
  .link-button {
    display: inline-flex;
    align-items: center;
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    font: inherit;
    color: var(--c-accent);
    cursor: pointer;
  }
  .link-button:hover { color: var(--c-accent-hover); text-decoration: underline; }

  .actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }

  /* --- Inputs / selects / textareas ----------------------------------- */
  .field { margin-bottom: var(--space-4); }
  .field > label,
  .field-label {
    display: block;
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    color: var(--c-text-muted);
    margin-bottom: var(--space-1);
  }

  .input,
  input[type="text"],
  input[type="url"],
  input[type="number"],
  input[type="email"],
  input[type="password"],
  input[type="date"],
  input[type="search"],
  input[type="tel"],
  input[type="time"],
  input[type="datetime-local"],
  input[type="month"],
  input[type="week"],
  textarea,
  select {
    width: 100%;
    min-height: 40px;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--input-border);
    border-radius: var(--radius-md);
    background: var(--surface);
    color: var(--ink);
    font: inherit;
    font-size: var(--text-base);
    transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
  }
  textarea { min-height: 6rem; padding: var(--space-3) var(--space-3); line-height: 1.6; resize: vertical; }

  /* Custom select chevron (native arrow removed) so selects match the inputs. */
  select {
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    padding-right: var(--space-10);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238A8F99' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right var(--space-3) center;
    background-size: 1.1rem;
  }

  input:hover, textarea:hover, select:hover { border-color: var(--muted); }

  /* Soft violet halo: accent border + 3px --accent-tint ring (spec §8). */
  input:focus, textarea:focus, select:focus {
    outline: none;
    background: var(--surface);
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-tint);
  }
  input[aria-invalid="true"], textarea[aria-invalid="true"], select[aria-invalid="true"],
  .field-invalid input, .field-invalid textarea, .field-invalid select {
    border-color: var(--red);
  }
  input[aria-invalid="true"]:focus, textarea[aria-invalid="true"]:focus, select[aria-invalid="true"]:focus {
    box-shadow: 0 0 0 3px var(--red-bg);
  }
  input::placeholder, textarea::placeholder { color: var(--faint); }

  /* Errors block */
  .errors {
    background: var(--c-danger-tint);
    border: 1px solid color-mix(in oklch, var(--c-danger) 35%, var(--c-border));
    color: var(--c-ink);
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-md);
    margin-bottom: var(--space-5);
  }
  .errors ul { margin: 0; padding-left: var(--space-5); }

  /* Aligned field rows */
  .field-row { display: flex; gap: var(--space-4); }
  .field-row .field { flex: 1; margin-bottom: var(--space-4); }
  .field-checkbox { display: flex; align-items: center; gap: var(--space-2); }
  .field-checkbox label { margin: 0; font-weight: var(--weight-normal); color: var(--c-text); }
  .field-checkbox input[type="checkbox"] { width: auto; min-height: 0; accent-color: var(--c-accent); }

  /* Entity forms read best in a single, comfortable column — never stretched to
     the full page width (a 1100px-wide URL field is not premium). */
  .stacked-form { max-width: 44rem; }

  /* --- Form sections (4 titled blocks) -------------------------------- */
  .form-section {
    border: 1px solid var(--c-border);
    border-radius: var(--radius-lg);
    background: var(--c-surface);
    padding: var(--space-5) var(--space-6);
    margin: 0 0 var(--space-5);
    box-shadow: var(--shadow-xs);
  }
  .form-section > legend,
  .section-legend {
    float: left;
    width: 100%;
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--c-text-muted);
    padding: 0 0 var(--space-3);
    margin-bottom: var(--space-4);
    border-bottom: 1px solid var(--c-border);
  }
  .form-section > legend + * { clear: both; }

  /* The Essential section is the hero — its eyebrow reads in accent, and a quiet
     caption sits inline to the right ("the minimum to save"). */
  .legend-hero { color: var(--c-accent); }
  .legend-caption {
    float: right;
    text-transform: none;
    letter-spacing: 0;
    font-weight: var(--weight-regular);
    color: var(--muted);
    font-size: var(--text-2xs);
  }

  /* The "you can already save" reassurance, just under the Essential section. */
  .form-savehint {
    margin: calc(var(--space-5) * -1 + var(--space-2)) 0 var(--space-5);
    font-size: var(--text-2xs);
    color: var(--green);
  }

  /* Price-type segmented control: two radio chips reading as one pill switch.
     The checked option fills with accent-tint via :has(:checked) — no JS. */
  .segmented {
    display: inline-flex;
    border: 1px solid var(--input-border);
    border-radius: var(--radius-pill);
    overflow: hidden;
  }
  .segmented-option {
    display: inline-flex;
    cursor: pointer;
  }
  .segmented-option + .segmented-option { border-left: 1px solid var(--line); }
  .segmented-option > span {
    padding: var(--space-2) var(--space-4);
    font-size: var(--text-2xs);
    font-weight: var(--weight-medium);
    color: var(--muted);
    transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
  }
  .segmented-option:hover > span { background: var(--surface-2); color: var(--ink); }
  .segmented-option:has(input:checked) > span {
    background: var(--accent-tint);
    color: var(--accent);
    font-weight: var(--weight-semibold);
  }
  .segmented-option:has(input:focus-visible) > span { outline: 2px solid var(--c-accent); outline-offset: -2px; }

  /* --- Pipeline status (degraded disclosure) ------------------------- */
  /* De-emphasized: a quiet inset card showing the defaults, with an "Adjust ⌄"
     toggle that reveals the three selects + dealbreaker/discard fields. */
  .form-status {
    background: var(--surface-2);
    border-radius: var(--radius-md);
    padding: var(--space-3) var(--space-4);
    margin: 0 0 var(--space-5);
  }
  .form-status-summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
  }
  .form-status-label { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--text); }
  .form-status-defaults { display: block; font-size: var(--text-2xs); color: var(--muted); margin-top: var(--space-1); }
  .form-status-toggle {
    flex: none;
    border: none;
    background: none;
    font: inherit;
    font-size: var(--text-2xs);
    font-weight: var(--weight-semibold);
    color: var(--accent);
    cursor: pointer;
  }
  .form-status-toggle:hover { color: var(--accent-hover); }
  .form-status-fields { margin-top: var(--space-4); }
  .form-status-fields[hidden] { display: none; }

  /* --- Sticky action bar (the Save fix) ------------------------------- */
  .form-actions {
    position: sticky;
    bottom: 0;
    z-index: 10;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin: var(--space-5) 0 0;
    padding: var(--space-4) var(--space-5);
    background: color-mix(in oklch, var(--c-surface) 92%, transparent);
    backdrop-filter: saturate(1.4) blur(10px);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
  }
  .form-actions .spacer { flex: 1; }

  /* Clear the sticky action bar: the last fieldset must never sit under it.
     Reserve space equal to the bar height (~ padding + button height). */
  form:has(> .form-actions) .form-section:last-of-type { margin-bottom: var(--space-16); }
  form:has(> .form-actions) .form-section .field,
  form:has(> .form-actions) .form-section .chip-field { scroll-margin-bottom: var(--space-16); }

  /* --- Chips ---------------------------------------------------------- */
  /* Impressions read as a compact grid, not a long single-column stack. */
  .chip-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: var(--space-4) var(--space-5);
  }
  .chip-grid .chip-field { margin-bottom: 0; }

  .chip-field .chip-group { display: flex; flex-wrap: wrap; gap: var(--space-2); }
  /* Option chip: quiet outline when unset; selected = accent-tint + accent text
     (spec §8). No fill noise — meaning carried only by the selected state. */
  .chip {
    display: inline-flex;
    align-items: center;
    padding: var(--space-1) var(--space-3);
    min-height: 30px;
    border-radius: var(--radius-pill);
    border: 1px solid var(--input-border);
    background: var(--surface);
    color: var(--text);
    font: inherit;
    font-size: var(--text-2xs);
    font-weight: var(--weight-medium);
    cursor: pointer;
    transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease),
                color var(--dur-fast) var(--ease);
  }
  .chip:hover { background: var(--surface-2); border-color: var(--muted); color: var(--ink); }

  .chip.is-selected {
    background: var(--accent-tint);
    border-color: color-mix(in srgb, var(--accent) 35%, var(--line));
    color: var(--accent);
    font-weight: var(--weight-semibold);
  }
  /* Boolean tri-state — three explicit chips: – / Yes / No (spec §8). Each chip
     carries its own selected tint: Yes = green, No = red, – = quiet accent. The
     base .chip / .chip.is-selected rules above provide the unset + accent look. */
  .chip-bool.chip-yes.is-selected {
    background: var(--green-bg);
    border-color: color-mix(in srgb, var(--green) 30%, var(--line));
    color: var(--green);
  }
  .chip-bool.chip-no.is-selected {
    background: var(--red-bg);
    border-color: color-mix(in srgb, var(--red) 30%, var(--line));
    color: var(--red);
  }

  /* --- Reactions ------------------------------------------------------ */
  .cell-reactions { display: flex; align-items: center; gap: var(--space-1); }
  .reaction-face { font-size: var(--text-md); line-height: 1; cursor: default; }
  .reaction-set { display: inline-flex; gap: var(--space-1); align-items: center; }
  .reaction-btn {
    background: none;
    border: 1px solid var(--c-border);
    border-radius: var(--radius-sm);
    padding: var(--space-1) var(--space-2);
    font-size: var(--text-md);
    cursor: pointer;
    transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
  }
  .reaction-btn:hover { background: var(--c-surface-2); }
  .reaction-btn.is-active { background: var(--c-primary-tint); border-color: var(--c-primary); }

  /* Form reaction picker: radio chips that save with the main form. The label
     reuses .reaction-btn; the checked radio drives the active style via :has. */
  .reaction-picker { display: inline-flex; gap: var(--space-1); align-items: center; }
  .reaction-picker .reaction-btn { display: inline-flex; align-items: center; }
  .reaction-picker .reaction-btn:has(input:checked) { background: var(--c-primary-tint); border-color: var(--c-primary); }
  .reaction-picker .reaction-btn:has(input:focus-visible) { outline: 2px solid var(--c-primary); outline-offset: 1px; }

  /* --- Shortlist (T4.3) ----------------------------------------------- */
  /* Row marker: a gold star in its own dedicated slot (cell-shortlist). */
  .cell-shortlist { display: flex; align-items: center; justify-content: center; }
  .shortlist-flag {
    color: var(--c-gold);
    font-size: var(--text-md);
    line-height: 1;
  }
  /* The shortlist column header star is muted (it's a label, not a value). */
  .recap-head .center[aria-label] { color: var(--c-text-subtle); }
  /* Panel toggle: a star button; off = quiet outline, on = gold-tinted. */
  /* Shortlist toggle in the panel status line — a pill that matches the axis
     pills (the .axis-pill wrapper resets margins; this is the button itself). */
  .shortlist-toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-pill);
    font-size: var(--text-2xs);
    font-weight: var(--weight-bold);
    line-height: 1;
    cursor: pointer;
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    color: var(--c-text-muted);
  }
  .shortlist-toggle:hover { background: var(--c-surface-2); }
  .shortlist-toggle .shortlist-star { color: var(--c-border-strong); line-height: 1; }
  .shortlist-toggle.is-on {
    background: var(--c-warning-tint);
    border-color: var(--c-gold);
    color: var(--c-ink);
  }
  .shortlist-toggle.is-on .shortlist-star { color: var(--c-gold); }

  /* --- Badges --------------------------------------------------------- */
  .status-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 2px var(--space-2);
    border-radius: var(--radius-pill);
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
    background: var(--c-surface-2);
    color: var(--c-text-muted);
    white-space: nowrap;
  }
  .status-badge::before {
    content: "";
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--dot, var(--c-text-subtle));
    flex: none;
  }
  /* Confidence — the HERO status signal (spec §5). A bold colour pill: verified
     green, checking amber, raw neutral grey. Colour-on-tint, weight 700. */
  .confidence-raw      { background: var(--surface-2); --dot: var(--muted); color: var(--muted); font-weight: var(--weight-bold); }
  .confidence-checking { background: var(--amber-bg);  --dot: var(--amber); color: var(--amber); font-weight: var(--weight-bold); }
  .confidence-verified { background: var(--green-bg);  --dot: var(--green); color: var(--green); font-weight: var(--weight-bold); }

  /* Outcome — a secondary whisper: neutral except the two endpoints
     (secured → green, discarded → muted/struck). */
  .outcome-active    { background: var(--surface-2);            --dot: var(--muted);  color: var(--muted); }
  .outcome-discarded { background: var(--status-discarded-tint); --dot: var(--faint);  color: var(--muted); text-decoration: line-through; }
  .outcome-secured   { background: var(--green-bg);             --dot: var(--green);  color: var(--green); font-weight: var(--weight-semibold); }

  /* Recap whisper: the contextual secondary status beside the confidence pill
     (contact status when active, else Discarded/Secured). Small + muted; the
     "secured" variant is the only one that earns colour (spec §5). */
  .whisper {
    font-size: var(--text-xs);
    color: var(--muted);
    margin-left: var(--space-2);
    white-space: nowrap;
  }
  .whisper.is-won { color: var(--green); font-weight: var(--weight-semibold); }

  /* Tag chip: free user tag (#near-work) */
  .tag-chip {
    display: inline-flex;
    align-items: center;
    padding: 1px var(--space-2);
    border-radius: var(--radius-pill);
    font-size: var(--text-xs);
    background: var(--c-accent-tint);
    color: var(--c-accent-deep);
    white-space: nowrap;
  }
  .listing-tags { display: flex; flex-wrap: wrap; gap: var(--space-1); padding: var(--space-2) var(--space-3); }
  .cell-tags    { display: flex; flex-wrap: wrap; gap: var(--space-1); align-items: center; }

  /* Warm/cold: a faint word after the price (`incl.` / `cold`), not a dot. It
     informs more than a coloured dot would (spec §5). */
  .price-temp {
    color: var(--faint);
    font-weight: var(--weight-normal);
    font-size: var(--text-xs);
    margin-left: var(--space-1);
  }

  /* Dealbreaker chip */
  .dealbreaker {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px; height: 20px;
    border-radius: var(--radius-sm);
    background: var(--c-danger-tint);
    color: var(--c-danger);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    cursor: help;
  }

  /* --- Recap controls + collapsible filter rail ---------------------- */
  /* Filters live in a rail that is CLOSED by default so the table gets the full
     width to be scanned. A toggle (with a count of active filters) opens it; the
     open/closed state is remembered client-side (filter-rail controller). */
  .recap-controls {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
  }
  .filter-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.25rem;
    height: 1.25rem;
    padding: 0 var(--space-1);
    border-radius: var(--radius-pill);
    background: var(--c-accent);
    color: var(--c-on-accent);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    font-variant-numeric: tabular-nums;
  }
  .filter-rail-body { display: none; }
  .filter-rail.is-open .filter-rail-body { display: block; }
  .filter-caret { font-size: 0.7em; opacity: 0.65; transition: transform var(--dur-fast) var(--ease); }
  .filter-rail.is-open .filter-caret { transform: rotate(180deg); }

  .recap-filters {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    align-items: end;
    gap: var(--space-3) var(--space-4);
    padding: var(--space-5);
    margin-bottom: var(--space-5);
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xs);
  }
  .recap-filters .filter-field { margin: 0; min-width: 0; }
  .recap-filters .filter-field-full { grid-column: 1 / -1; }
  .recap-filters .filter-field-full input[type="search"] {
    width: 100%;
    min-width: 0;
    height: 38px;
    min-height: 38px;
    padding: var(--space-2) var(--space-3);
    font-size: var(--text-sm);
  }
  .recap-filters label {
    display: block;
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
    color: var(--c-text-muted);
    margin-bottom: var(--space-1);
  }
  .recap-filters select,
  .recap-filters input[type="number"] {
    width: 100%;
    min-width: 0;
    height: 38px;
    min-height: 38px;
    padding: var(--space-1) var(--space-3);
    font-size: var(--text-sm);
  }
  .recap-filters select { padding-right: var(--space-8); background-position: right var(--space-2) center; }

  /* Result count + clear-filters row above the table. */
  .recap-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-3);
  }
  .recap-count {
    font-size: var(--text-sm);
    color: var(--c-text-muted);
    font-variant-numeric: tabular-nums;
  }
  .recap-toolbar-actions {
    display: flex;
    align-items: center;
    gap: var(--space-3);
  }
  /* Shortlist destination: a pill that toggles the shortlisted filter and always
     shows the account's shortlisted count. Quiet when off, gold-accented when the
     recap is filtered to the shortlist. */
  .shortlist-pill {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-3);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-pill);
    background: var(--c-surface);
    color: var(--c-text-muted);
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    text-decoration: none;
    font-variant-numeric: tabular-nums;
    transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
  }
  .shortlist-pill:hover { background: var(--c-surface-2); color: var(--c-ink); text-decoration: none; }
  .shortlist-pill .shortlist-pill-star { color: var(--c-border-strong); line-height: 1; }
  .shortlist-pill.is-on {
    background: var(--c-warning-tint);
    border-color: var(--c-gold);
    color: var(--c-ink);
  }
  .shortlist-pill.is-on .shortlist-pill-star { color: var(--c-gold); }

  /* --- Recap layout: table + overlay drawer --------------------------- */
  /* The table is ALWAYS full-width and rock-steady. The detail arrives as a
     fixed overlay drawer (see .recap-panel) over a scrim — it never steals
     width from the table, so a user's eye never loses its place mid-triage. */
  .recap-layout { position: relative; }
  .recap-results { min-width: 0; }

  /* Scrim behind the drawer — a gentle focus wash, shown (pure CSS) the moment a
     detail loads. Crucially `pointer-events: none`: the table stays LIVE under
     it, so the user can flip from row to row (the drawer swaps content) without
     closing first. Close is explicit: the × control or Escape. */
  .drawer-scrim {
    position: fixed;
    inset: 0;
    z-index: 55;
    pointer-events: none;
    background: var(--scrim);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--dur) var(--ease), visibility var(--dur) var(--ease);
  }
  .recap-layout:has(.listing-detail) .drawer-scrim,
  .recap-layout:has(.candidate-detail) .drawer-scrim { opacity: 1; visibility: visible; }

  /* --- Recap table (CSS grid so each row is one <a>) ------------------ */
  .recap-table {
    display: grid;
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    font-size: var(--text-base);
  }
  .recap-head,
  .recap-row {
    display: grid;
    grid-template-columns:
      var(--col-check)      /* compare / select checkbox */
      var(--col-flag)       /* shortlist marker */
      var(--col-reactions)  /* reactions */
      var(--col-price)      /* price */
      minmax(8rem, 1.3fr)   /* city (never truncates) */
      var(--col-status)     /* confidence pill + whisper */
      minmax(6rem, 1fr)     /* portal */
      minmax(0, 1fr);       /* tags */
    align-items: center;
    gap: var(--space-3);
    padding: 0 var(--space-5);
  }
  .recap-head {
    height: 40px;
    background: var(--c-surface-2);
    border-bottom: 1px solid var(--c-border);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--c-text-muted);
  }
  .recap-head a { color: var(--c-text-muted); display: inline-flex; align-items: center; gap: var(--space-1); }
  .recap-head a:hover { color: var(--c-ink); }
  .recap-head .is-sorted { color: var(--c-ink); font-weight: var(--weight-semibold); }
  .recap-head .sort-indicator { color: var(--c-accent); font-size: 0.95em; line-height: 1; }
  /* num columns: keep label + arrow flush-right next to the label */
  .recap-head .num a { justify-content: flex-end; }
  .recap-head .center a { justify-content: center; }

  /* Generous, airy rows even at density (spec §1). Hairline only — no zebra,
     no vertical rules. */
  .recap-row {
    min-height: 48px;
    color: var(--text);
    text-decoration: none;
    border-bottom: 1px solid var(--line);
    cursor: pointer;
    transition: background var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease);
  }
  .recap-row:last-child { border-bottom: none; }
  .recap-row:hover { background: var(--surface-2); text-decoration: none; color: var(--text); }
  /* Keyboard focus ring (j/k navigation) — distinct from click selection. */
  .recap-row.is-focused { outline: 2px solid var(--accent); outline-offset: -2px; }

  /* Recently added — a small `nuevo` accent tag is the canonical signal (rendered
     in markup); a quiet accent left edge reinforces it. */
  .recap-row.is-new { box-shadow: inset 2px 0 0 var(--accent); }

  /* Selected row = accent-tint + 2px accent left edge (spec §5). */
  .recap-row.is-selected {
    position: relative;
    z-index: 1;
    background: var(--accent-tint);
    box-shadow: inset 2px 0 0 var(--accent);
  }
  .recap-row.is-selected .cell-city { color: var(--ink); }

  /* Only DISCARDED rows recede (~0.45) — they're dead. `Sin revisar` rows stay
     full strength: they're pending work, never hidden (spec §3, §5). */
  .recap-row.is-dimmed { opacity: 0.45; }
  .recap-row.is-dimmed:hover { opacity: 1; }
  /* In the dense table the status colour IS the message — drop the redundant
     dot here (it stays in the roomy detail drawer). */
  .recap-row .status-badge { padding-inline: var(--space-2); }
  .recap-row .status-badge::before { display: none; }
  .recap-row .cell { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .recap-table .num { text-align: right; font-variant-numeric: tabular-nums; }
  .recap-table .center { text-align: center; }
  /* City must stay legible — never ellipsize the name */
  .recap-row .cell-city {
    color: var(--c-ink);
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    overflow: visible;
    text-overflow: clip;
  }
  .recap-row .cell-portal { color: var(--c-text-muted); }
  /* Price: bold, tabular, ink (the headline number of the row). */
  /* Price is the anchor of the row: a touch larger, bold, the figure the eye lands on. */
  .recap-row .price { font-size: var(--text-md); font-weight: var(--weight-bold); letter-spacing: -0.01em; color: var(--ink); font-variant-numeric: tabular-nums; }

  /* --- Candidate queue (title-led list + overlay drawer) ----------------
     The flat's NAME leads, with location · portal beneath; then the figures you
     compare — price (mono anchor) and size — aligned right, plus status, seen,
     and row actions. Reuses the recap overlay drawer (keyed on .candidate-detail). */
  .candidate-table {
    background: var(--surface);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xs);
    overflow: hidden;
  }
  .candidate-head,
  .candidate-row {
    display: grid;
    grid-template-columns: 1.5rem minmax(0, 1fr) 6.5rem 8.5rem 5.5rem 3.5rem 1.75rem;
    gap: var(--space-4);
    align-items: center;
  }
  .candidate-head {
    padding: var(--space-3) var(--space-5);
    font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.06em;
    font-weight: var(--weight-semibold); color: var(--muted);
    border-bottom: 1px solid var(--line);
  }
  .candidate-head .num { text-align: right; }
  .candidate-row {
    padding: var(--space-3) var(--space-5);
    border-bottom: 1px solid var(--line);
    cursor: pointer;
  }
  .candidate-row:last-child { border-bottom: none; }
  .candidate-row:hover { background: var(--surface-2); }
  .candidate-row.is-selected { background: var(--accent-tint); box-shadow: inset 2px 0 0 var(--accent); }
  .cand-check { width: 15px; height: 15px; accent-color: var(--accent); align-self: start; margin-top: 3px; }
  .cand-main { display: block; min-width: 0; text-decoration: none; color: inherit; }
  .cand-main:hover { text-decoration: none; color: inherit; }
  .cand-title {
    display: block; font-size: var(--text-md); font-weight: var(--weight-semibold);
    color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .cand-meta {
    display: block; font-size: var(--text-2xs); color: var(--muted); margin-top: 3px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .cand-meta .meta-sep { margin: 0 var(--space-1); color: var(--faint); }
  .loc-city { color: var(--text); font-weight: var(--weight-semibold); }
  .cand-price { font-family: var(--font-mono); font-weight: var(--weight-bold); color: var(--ink); font-size: var(--text-md); text-align: right; }
  /* Review column: the AI verdict pill (links to the review) or a quiet "Unreviewed". */
  .cand-review-link { text-decoration: none; }
  .cand-review-link:hover .status-badge { filter: brightness(0.97); }
  .cand-unreviewed { font-size: var(--text-2xs); color: var(--muted); }
  .cand-seen { color: var(--muted); font-size: var(--text-2xs); text-align: right; }

  /* Row 3-dot actions menu (open ad / promote / approve / reject) — a no-JS
     <details> dropdown; the cell allows overflow so the menu isn't clipped. */
  .cand-actions { overflow: visible; display: flex; justify-content: center; }
  .row-actions { position: relative; }
  .row-actions > summary {
    list-style: none;
    cursor: pointer;
    padding: 0 var(--space-1);
    color: var(--c-text-subtle);
    border-radius: var(--radius-sm);
    line-height: 1.4;
  }
  .row-actions > summary::-webkit-details-marker { display: none; }
  .row-actions > summary:hover,
  .row-actions[open] > summary { color: var(--c-ink); background: var(--c-surface-2); }
  .row-actions-menu {
    position: absolute;
    right: 0;
    top: calc(100% + var(--space-1));
    z-index: 30;
    display: flex;
    flex-direction: column;
    min-width: 9rem;
    padding: var(--space-1);
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
  }
  .row-actions-menu form { margin: 0; }
  .row-action {
    display: block;
    width: 100%;
    text-align: left;
    padding: var(--space-1) var(--space-2);
    border: 0;
    background: transparent;
    color: var(--c-text);
    font: inherit;
    cursor: pointer;
    border-radius: var(--radius-sm);
  }
  .row-action:hover { background: var(--c-surface-2); color: var(--c-ink); }
  .row-action:disabled { color: var(--c-text-subtle); cursor: default; background: transparent; }
  .row-action-danger { color: var(--c-danger); }
  .row-action-danger:hover { background: var(--c-danger-tint); color: var(--c-danger); }

  /* Triage status badges — distinct from listing statuses. */
  .status-candidate-new       { background: var(--status-seen-tint);      --dot: var(--status-seen); }
  .status-candidate-kept      { background: var(--c-success-tint, var(--status-secured-tint)); --dot: var(--c-success); }
  .status-candidate-dismissed { background: var(--status-discarded-tint); --dot: var(--status-discarded); color: var(--c-text-subtle); }
  .status-candidate-promoted  { background: var(--c-accent-tint);         --dot: var(--c-accent); }

  /* Review verdict badges — colour by meaning (reuses the status-badge dot). */
  .verdict-clear          { background: var(--c-success-tint); --dot: var(--c-success); color: color-mix(in oklch, var(--c-success) 70%, var(--c-ink)); }
  .verdict-worth_checking { background: var(--c-warning-tint); --dot: var(--c-warning); }
  .verdict-dealbreaker    { background: var(--c-danger-tint);  --dot: var(--c-danger);  color: var(--c-danger); }
  /* Fallbacks when there's no verdict: in-progress, completed-without-verdict, failed. */
  .verdict-progress       { background: var(--c-surface-2);    --dot: var(--c-text-subtle); color: var(--c-text-muted); }
  .verdict-reviewed       { background: var(--c-surface-2);    --dot: var(--c-accent); color: var(--c-text); }
  .verdict-failed         { background: var(--status-discarded-tint); --dot: var(--status-discarded); color: var(--c-text-subtle); }

  /* --- Scraping health panel (candidates queue) ----------------------- */
  .scrape-health { margin-bottom: var(--space-4); }
  .scrape-health-title {
    font-size: var(--text-xs); text-transform: uppercase; letter-spacing: .04em;
    color: var(--c-text-subtle); margin: 0 0 var(--space-2);
  }
  .scrape-health-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-2); }
  .scrape-health-item {
    display: inline-flex; align-items: center; gap: var(--space-2);
    padding: var(--space-1) var(--space-3); border-radius: var(--radius-pill);
    background: var(--c-surface-2); font-size: var(--text-xs);
  }
  .scrape-health-portal { font-weight: 600; }
  .scrape-health-meta { color: var(--c-text-subtle); }
  .scrape-health-error { color: var(--c-danger); max-width: 28ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* Badge colours by health, reusing the status-badge dot. */
  .health-ok         { background: var(--c-success-tint); --dot: var(--c-success); }
  .health-suspicious { background: var(--c-warning-tint); --dot: var(--c-warning); }
  .health-failing    { background: var(--c-danger-tint);  --dot: var(--c-danger); color: var(--c-danger); }
  .health-never_run  { background: var(--c-surface-2);    --dot: var(--c-text-subtle); color: var(--c-text-muted); }


  /* --- Reviews master-detail (list + drawer) -------------------------------
     The inbox is now the recap pattern: a scannable hairline list (no boxes)
     beside a right overlay drawer. Each row carries the verdict (pill + gist)
     and a direct link to the original ad, so you triage without opening. */
  .review-list {
    background: var(--surface);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xs);
    overflow: hidden;
  }
  .review-row {
    display: grid;
    grid-template-columns: 1.4rem minmax(0, 1fr) auto;
    gap: var(--space-4);
    align-items: center;
    padding: var(--space-3) var(--space-5);
    border-bottom: 1px solid var(--line);
  }
  .review-row:last-child { border-bottom: none; }
  .review-row:hover { background: var(--surface-2); }
  .review-row.is-selected { background: var(--accent-tint); box-shadow: inset 2px 0 0 var(--accent); }
  /* Cleared reviews read as done; the eye skips past them. */
  .review-row.is-reviewed { opacity: 0.55; }
  .review-row.is-reviewed:hover { opacity: 1; }
  .review-row-check { width: 15px; height: 15px; accent-color: var(--accent); align-self: start; margin-top: 3px; }

  .review-row-main { display: block; min-width: 0; text-decoration: none; color: inherit; }
  .review-row-main:hover { text-decoration: none; color: inherit; }
  .review-row-title {
    display: block;
    font-size: var(--text-md);
    font-weight: var(--weight-semibold);
    color: var(--ink);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .review-row-reason {
    display: block;
    font-size: var(--text-2xs);
    color: var(--text);
    margin-top: 3px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .review-row-reason.is-error { color: var(--red); }
  .review-row-meta { display: block; font-size: var(--text-xs); color: var(--muted); margin-top: 4px; }
  .review-row-meta .price { font-family: var(--font-mono); color: var(--text); font-weight: var(--weight-semibold); }
  .review-row-meta .meta-sep { margin: 0 var(--space-1); color: var(--faint); }

  .review-row-aside { display: inline-flex; align-items: center; gap: var(--space-3); }
  /* Direct hop to the original ad — sits beside the verdict pill. */
  .review-row-open {
    display: inline-flex; align-items: center; justify-content: center;
    width: 1.75rem; height: 1.75rem;
    border: 1px solid var(--input-border); border-radius: var(--radius-sm);
    color: var(--accent); font-size: var(--text-md); text-decoration: none;
    transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
  }
  .review-row-open:hover { background: var(--accent-tint); border-color: var(--accent); }

  /* Drawer header for a review: the verdict is the hero. */
  .review-detail-verdict { margin-top: var(--space-3); }
  .review-detail-verdict .status-badge { font-size: var(--text-sm); padding: 4px var(--space-3); }
  .review-detail-title {
    font-size: var(--text-md);
    font-weight: var(--weight-semibold);
    color: var(--ink);
    line-height: 1.35;
    margin-top: var(--space-3);
  }
  .review-detail-meta { font-size: var(--text-2xs); color: var(--muted); margin-top: var(--space-2); }
  .review-detail-meta .price { font-family: var(--font-mono); color: var(--text); font-weight: var(--weight-semibold); }
  .review-detail-sectlabel {
    font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.07em;
    font-weight: var(--weight-semibold); color: var(--muted);
    margin: var(--space-5) 0 var(--space-2);
  }
  /* Quiet reassurance under the decision buttons: no need to mark it read. */
  .review-decide-hint { margin-top: var(--space-2); font-size: var(--text-2xs); color: var(--muted); }

  /* Rendered markdown body on the review detail page. */
  .review-prose { color: var(--c-text); }
  .review-prose h1, .review-prose h2, .review-prose h3 { color: var(--c-ink); margin: var(--space-4) 0 var(--space-2); }
  .review-prose p { margin: 0 0 var(--space-3); }
  .review-prose ul, .review-prose ol { margin: 0 0 var(--space-3) var(--space-5); }
  .review-prose li { margin-bottom: var(--space-1); }
  .review-prose code { background: var(--c-surface-2); padding: 1px 4px; border-radius: var(--radius-sm); font-size: 0.9em; }

  .candidate-detail .detail-external-link { margin: var(--space-4) 0 0; }
  .payload-list dt { text-transform: none; }
  .payload-raw {
    white-space: pre-wrap;
    word-break: break-word;
    font-size: var(--text-xs);
    background: var(--c-surface-2);
    padding: var(--space-3);
    border-radius: var(--radius-sm);
  }

  /* Compare selection (T4.2): a quiet checkbox per row + a sticky action bar. */
  .cell-compare { display: flex; align-items: center; justify-content: center; }
  .compare-check { cursor: pointer; accent-color: var(--c-accent); }
  .compare-bar {
    position: sticky;
    bottom: 0;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    background: var(--c-surface);
    border-top: 1px solid var(--c-border);
    box-shadow: 0 -4px 12px rgba(20, 24, 30, 0.06);
  }
  .compare-bar[hidden] { display: none; }
  .compare-bar-label { font-size: var(--text-sm); color: var(--c-text); margin-right: auto; }
  /* Compare link is shown but inert when the 2–4 constraint isn't met. */
  .compare-bar .is-disabled { opacity: 0.45; pointer-events: none; }

  /* The unified selection bar (Analyze / Discard / Compare): a sticky, prominent
     page-level action bar. Spans the recap layout with a clear accent edge so it
     stands out the moment a selection exists. A disabled action (e.g. Compare
     outside 2–4) dims rather than vanishes, so the bar layout stays stable. */
  .selection-bar {
    grid-column: 1 / -1;
    z-index: 5;
    border-top: 2px solid var(--c-accent);
  }
  .selection-bar-form { display: contents; }
  .selection-bar .btn:disabled { opacity: 0.45; pointer-events: none; }
  /* Select-all sits in the recap head's first column, aligned with the row checks. */
  .select-all-check { cursor: pointer; }

  /* Analyze opens a small menu (native <details>) to pick the country context
     before running. The bar is sticky at the bottom, so the panel opens upward. */
  .analyze-menu { position: relative; display: inline-block; }
  .analyze-menu > summary { list-style: none; cursor: pointer; }
  .analyze-menu > summary::-webkit-details-marker { display: none; }
  .analyze-menu__panel {
    position: absolute;
    right: 0;
    bottom: calc(100% + var(--space-2));
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    min-width: 15rem;
    padding: var(--space-4);
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    z-index: 10;
  }
  .analyze-menu__field { display: flex; flex-direction: column; gap: var(--space-1); }
  .analyze-menu__label { font-size: var(--text-sm); color: var(--c-text-muted); }
  .analyze-menu__panel .select { width: 100%; }

  /* Distance: plain muted text appended to the city (`· Center`), not a dot. */
  .cell-city .dist {
    color: var(--muted);
    font-size: var(--text-sm);
    font-weight: var(--weight-normal);
  }
  /* "New" (recently added) — a small accent tag next to the city. */
  .cell-city .new-tag {
    font-size: var(--text-xs);
    letter-spacing: 0.05em;
    text-transform: uppercase;
    font-weight: var(--weight-bold);
    color: var(--accent);
    background: var(--accent-tint);
    padding: 1px var(--space-1);
    border-radius: var(--radius-sm);
  }

  .recap-empty,
  .empty-state {
    text-align: center;
    padding: var(--space-12) var(--space-6);
    color: var(--c-text-muted);
    background: var(--c-surface);
    border: 1px dashed var(--c-border-strong);
    border-radius: var(--radius-lg);
  }
  .empty-state .empty-line { font-size: var(--text-md); color: var(--c-text); margin-bottom: var(--space-4); }

  /* --- Detail drawer (overlay) ---------------------------------------- */
  /* The Turbo frame IS the drawer shell: always present, pinned to the right
     edge, slid off-screen until it holds a detail — so opening a listing never
     reflows or shrinks the table. Slides in over the scrim (pure CSS :has). */
  .recap-panel {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(var(--panel-w), 94vw);
    z-index: 60;
    display: flex;
    flex-direction: column;
    background: var(--c-surface);
    border-left: 1px solid var(--c-border);
    box-shadow: var(--shadow-lg);
    transform: translateX(101%);
    visibility: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    transition: transform var(--dur) var(--ease), visibility 0s linear var(--dur);
  }
  .recap-panel:has(.listing-detail),
  .recap-panel:has(.candidate-detail) {
    transform: none;
    visibility: visible;
    transition: transform var(--dur) var(--ease), visibility 0s;
  }
  /* The empty hint lives in the (off-screen) drawer frame; never shown. */
  .recap-panel-empty { display: none; }

  .listing-detail { padding: 0; }
  .listing-detail-standalone { padding: 0; overflow: hidden; }
  .listing-detail-header {
    position: sticky;
    top: 0;
    z-index: 2;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-5) var(--space-5) var(--space-4);
    background: color-mix(in oklch, var(--c-surface) 90%, transparent);
    backdrop-filter: saturate(1.3) blur(8px);
    border-bottom: 1px solid var(--c-border);
  }
  /* The listing panel restructures its header (eyebrow+close on one line, then
     price hero, then the reaction control); the candidates panel keeps the
     default flex header. */
  .listing-detail:not(.candidate-detail) > .listing-detail-header { display: block; }
  .listing-detail:not(.candidate-detail) > .listing-detail-header .detail-title { min-width: 0; display: flex; flex-direction: column; gap: var(--space-3); }
  .listing-detail-header .detail-title { min-width: 0; display: flex; flex-direction: column; gap: var(--space-2); }
  .detail-head-top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); }
  .detail-head-top .detail-eyebrow { color: var(--c-text-muted); }

  /* Default eyebrow (candidates) stays accent. */
  .detail-eyebrow {
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--c-accent);
  }
  /* Listing title (candidates panel) — the URL/title line. */
  .listing-detail-header h1 {
    font-family: var(--font-sans);
    font-variation-settings: normal;
    font-size: var(--text-base);
    font-weight: var(--weight-medium);
    letter-spacing: 0;
    word-break: break-word;
    margin: 0;
  }
  .listing-detail-header h1 a { color: var(--c-text-muted); }
  .listing-detail-header h1 a:hover { color: var(--c-accent); }

  /* Price as hero + both partners' reaction faces. */
  .detail-priceline { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-3); }
  .detail-price {
    font-size: var(--text-3xl);
    font-weight: var(--weight-semibold);
    color: var(--ink);
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    line-height: 1;
  }
  .detail-price-unit { font-size: var(--text-2xs); font-weight: var(--weight-medium); color: var(--faint); margin-left: var(--space-1); }
  .detail-faces { font-size: var(--text-lg); display: inline-flex; align-items: center; gap: var(--space-1); }

  /* "Your reaction" segmented control (reuses the .reaction-set). */
  .detail-react { display: flex; align-items: center; gap: var(--space-2); }
  .detail-react-label {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--c-text-muted);
  }

  /* Close control for the overlay drawer (hidden on the standalone show page). */
  .drawer-close {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    padding: 0;
    border: 1px solid var(--c-border);
    border-radius: var(--radius-md);
    background: var(--c-surface);
    color: var(--c-text-muted);
    font-size: var(--text-xl);
    line-height: 1;
    cursor: pointer;
    transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
  }
  .drawer-close:hover { background: var(--c-surface-2); color: var(--c-ink); }
  .listing-detail-standalone .drawer-close { display: none; }

  /* Editable status line: the three axis pills + the shortlist toggle, all on
     one row directly under the header. */
  .listing-detail-status {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-5);
    border-bottom: 1px solid var(--c-border);
  }

  /* The axis pill IS the control: a <select> visually rendered as a status pill
     with a chevron, auto-submitting on change. Colour reuses the .confidence-*,
     .contact-*, .outcome-* badge tints. */
  .axis-pill { display: inline-flex; margin: 0; }
  .axis-pill select {
    appearance: none;
    height: auto;
    min-height: 0;
    border: none;
    cursor: pointer;
    font-size: var(--text-2xs);
    font-weight: var(--weight-bold);
    line-height: 1;
    padding: var(--space-1) var(--space-6) var(--space-1) var(--space-3);
    border-radius: var(--radius-pill);
    background-color: var(--surface-2);
    color: var(--c-text);
    background-position: right var(--space-2) center;
    background-size: 0.85em;
  }
  .axis-pill select:focus {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
    box-shadow: none;
    /* The base select:focus uses the `background` shorthand, which would wipe the
       chevron + pill tint; restore the chevron image here (tint stays on the
       per-variant rules below, which also re-assert on :focus). */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238A8F99' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right var(--space-2) center;
    background-size: 0.85em;
  }
  .axis-pill.confidence-raw      select, .axis-pill.confidence-raw      select:focus { background-color: var(--surface-2); color: var(--muted); }
  .axis-pill.confidence-checking select, .axis-pill.confidence-checking select:focus { background-color: var(--amber-bg);  color: var(--amber); }
  .axis-pill.confidence-verified select, .axis-pill.confidence-verified select:focus { background-color: var(--green-bg);  color: var(--green); }
  .axis-pill.contact-uncontacted select, .axis-pill.contact-uncontacted select:focus { background-color: var(--surface-2); color: var(--c-text); }
  .axis-pill.outcome-active      select, .axis-pill.outcome-active      select:focus { background-color: var(--surface-2); color: var(--muted); }
  .axis-pill.outcome-discarded   select, .axis-pill.outcome-discarded   select:focus { background-color: var(--status-discarded-tint); color: var(--muted); }
  .axis-pill.outcome-secured     select, .axis-pill.outcome-secured     select:focus { background-color: var(--green-bg);  color: var(--green); }

  .listing-detail-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--c-border);
  }
  /* The listing panel's action area stacks the button row over the portal
     caption; the candidates panel keeps the default single-row layout. */
  .listing-detail:not(.candidate-detail) > .listing-detail-actions { flex-direction: column; align-items: stretch; }
  .detail-action-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
  .detail-action-discard { margin-left: auto; }
  .detail-action-meta { margin: 0; font-size: var(--text-xs); color: var(--c-text-muted); }

  .listing-detail-body { padding: var(--space-5); }

  /* Your note — the first body block, highlighted accent card with a date. */
  .detail-note {
    border: 1px solid color-mix(in srgb, var(--accent) 22%, var(--line));
    background: var(--accent-tint);
    border-radius: var(--radius-md);
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-4);
  }
  .detail-note-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-1); }
  .detail-note-label {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--accent);
    font-weight: var(--weight-bold);
  }
  .detail-note-date { font-size: var(--text-xs); color: var(--c-text-muted); }
  .detail-note-body { margin: 0; font-size: var(--text-sm); color: var(--ink); line-height: 1.55; white-space: pre-wrap; }
  .detail-note-add { display: inline-flex; margin-bottom: var(--space-4); font-size: var(--text-sm); }

  /* Footer: added-by · seen-on. */
  .detail-foot {
    display: flex;
    justify-content: space-between;
    gap: var(--space-3);
    margin-top: var(--space-5);
    padding-top: var(--space-3);
    border-top: 1px solid var(--line);
    font-size: var(--text-xs);
    color: var(--faint);
  }

  /* AI verdict card — the model's opinion, distinct from the user's Status. */
  .verdict-card {
    margin-bottom: var(--space-5);
    padding: var(--space-4);
    border: 1px solid var(--c-border);
    border-left: 3px solid var(--c-border-strong);
    border-radius: var(--radius-md);
    background: var(--c-surface-2);
  }
  .verdict-card-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
  }
  .verdict-eyebrow {
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--c-text-muted);
  }
  .verdict-card-text { font-size: var(--text-sm); color: var(--c-text); margin: 0 0 var(--space-2); }
  .verdict-card-text:last-child { margin-bottom: 0; }
  .verdict-card-clear          { border-left-color: var(--c-success); }
  .verdict-card-worth_checking { border-left-color: var(--c-warning); }
  .verdict-card-dealbreaker    { border-left-color: var(--c-danger); background: var(--c-danger-tint); }
  .verdict-card-progress       { border-left-color: var(--c-text-subtle); }

  /* Definition list inside the panel / show page */
  .detail-list {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: var(--space-2) var(--space-4);
    margin: 0 0 var(--space-5);
  }
  .detail-list dt { color: var(--c-text-muted); font-size: var(--text-sm); }
  .detail-list dd { margin: 0; color: var(--c-ink); }
  .detail-list dd .num,
  .price-value { font-variant-numeric: tabular-nums; }

  .detail-section-title {
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--c-text-muted);
    margin: var(--space-5) 0 var(--space-3);
  }

  /* Impressions grid: ✓ / ✗ / – */
  .impressions-grid {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: var(--space-2) var(--space-4);
    margin: 0 0 var(--space-4);
  }
  .impressions-grid .impr-label { color: var(--c-text-muted); font-size: var(--text-sm); }
  .impressions-grid .impr-value { color: var(--c-ink); }
  .check-yes { color: var(--c-success); font-weight: var(--weight-semibold); }
  .check-no  { color: var(--c-danger);  font-weight: var(--weight-semibold); }
  .check-na  { color: var(--c-text-subtle); }

  .detail-prose { white-space: pre-wrap; color: var(--c-text); margin-bottom: var(--space-4); }

  /* --- Cards / content blocks (country / city pages) ------------------ */
  .card {
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-lg);
    padding: var(--space-5);
    box-shadow: var(--shadow-xs);
  }
  .show-section { margin-bottom: var(--space-8); }
  /* Refined section label — matches the form fieldset legends for cohesion */
  .show-section > h2 {
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--c-text-muted);
    padding-bottom: var(--space-2);
    margin-bottom: var(--space-4);
    border-bottom: 1px solid var(--c-border);
  }

  /* Conclusions card: distinct, inviting, editable-in-place */
  .conclusions-card {
    background: var(--c-surface-2);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-lg);
    padding: var(--space-5);
  }
  .conclusions {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
  }
  .conclusions p { margin: 0; flex: 1; white-space: pre-wrap; color: var(--c-ink); }
  .conclusions-form { margin: 0; }
  .conclusions-form .field { margin-bottom: var(--space-3); }
  .conclusions-form textarea { background: var(--c-surface); }

  /* --- Sources list --------------------------------------------------- */
  .sources-list { list-style: none; padding: 0; margin: 0 0 var(--space-4); display: grid; gap: var(--space-3); }
  .source {
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-md);
    background: var(--c-surface);
    box-shadow: var(--shadow-xs);
  }
  .source-head { display: flex; align-items: baseline; gap: var(--space-3); }
  .source-label { font-weight: var(--weight-semibold); color: var(--c-ink); }
  .source-date { font-size: var(--text-sm); color: var(--c-text-muted); }
  .source-actions { margin-left: auto; display: inline-flex; align-items: baseline; gap: var(--space-3); }
  .source-portal { margin: var(--space-1) 0 0; font-size: var(--text-sm); color: var(--c-text-muted); }
  .source-conclusion { margin: var(--space-2) 0 0; white-space: pre-wrap; }

  /* --- Generic data table (countries / cities / portals) -------------- */
  .data-table {
    width: 100%;
    border-collapse: collapse;
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-xs);
    font-size: var(--text-base);
  }
  .data-table th, .data-table td {
    text-align: left;
    vertical-align: top;
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--c-border);
  }
  .data-table thead th { vertical-align: middle; }
  .data-table thead th {
    background: var(--c-surface-2);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--c-text-muted);
    height: 40px;
    padding-block: 0;
  }
  .data-table tbody tr:last-child td { border-bottom: none; }
  .data-table tbody tr { transition: background var(--dur-fast) var(--ease); }
  .data-table tbody tr:hover { background: var(--c-surface-2); }
  .data-table tbody a { color: var(--c-ink); font-weight: var(--weight-medium); }
  .data-table tbody a:hover { color: var(--c-accent); }
  .data-table .num { text-align: right; font-variant-numeric: tabular-nums; }
  .data-table .nowrap { white-space: nowrap; }
  .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; border-radius: var(--radius-lg); }
  .table-wrap .data-table { border-radius: 0; }

  /* --- Saved searches (under Portals) -------------------------------- */
  .saved-searches { margin-top: var(--space-8); }
  .saved-searches .section-title {
    margin: 0;
    font-size: var(--text-xl);
    font-weight: var(--weight-semibold);
    letter-spacing: -0.01em;
  }
  /* The URL is the column that matters: show it whole and monospaced so it's
     easy to read and compare against the one copied from the portal. */
  .saved-searches-table .url-cell { max-width: 0; width: 40%; }
  .url-link {
    font-family: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
    font-size: var(--text-2xs);
    word-break: break-all;
    line-height: 1.4;
  }
  .form-hint { color: var(--c-text-muted); font-size: var(--text-sm); margin: 0 0 var(--space-4); }
  .url-input {
    font-family: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
    font-size: var(--text-sm);
  }

  /* --- Inline creation (+ new portal / + new city) -------------------- */
  .field-with-inline-new { display: flex; align-items: stretch; gap: var(--space-2); }
  .field-with-inline-new select { flex: 1; }
  .btn-inline-new { white-space: nowrap; }
  #inline_portal_form:empty,
  #inline_city_form:empty { display: none; }
  .inline-form {
    margin-top: var(--space-3);
    padding: var(--space-4);
    border: 1px solid color-mix(in oklch, var(--c-accent) 30%, var(--c-border));
    border-radius: var(--radius-md);
    background: var(--c-accent-tint);
  }
  .inline-form-title {
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--c-text-muted);
    margin: 0 0 var(--space-3);
  }
  .inline-form .field:last-of-type { margin-bottom: var(--space-3); }
  .inline-form-actions { display: flex; align-items: center; gap: var(--space-3); }

  /* --- Plain helpers reused across show pages ------------------------- */
  .plain-list { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--space-1); }

  /* Section header with a trailing action (e.g. "View in full recap"). */
  .section-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-3);
  }
  .section-header h2 { margin: 0; }

  /* Context list (country show: per-city name + count + conclusion snippet). */
  .context-list { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--space-1); }
  .context-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-2) 0;
    border-bottom: 1px solid var(--c-border);
  }
  .context-row:last-child { border-bottom: none; }
  .context-main { display: flex; align-items: baseline; gap: var(--space-3); min-width: 0; }
  .context-name { font-weight: var(--weight-medium); flex: none; }
  .context-snippet {
    color: var(--c-text-muted);
    font-size: var(--text-sm);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .context-count { color: var(--c-text-muted); font-size: var(--text-sm); flex: none; }

  /* T4.5: the city's running conclusion surfaced in the listing panel. */
  .city-note {
    display: block;
    margin-top: var(--space-2);
    padding: var(--space-2) var(--space-3);
    background: var(--c-surface-2);
    border-radius: var(--radius-sm);
    font-size: var(--text-sm);
    color: var(--c-text-muted);
  }
  .city-note-label {
    font-weight: var(--weight-semibold);
    color: var(--c-text);
    margin-right: var(--space-1);
  }

  /* --- Dashboard: action-led landing ("needs you" → "where we stand") ----
     No card grid, no hero-metric tiles. Space and hairlines organise; the
     shortlist (the finalists) is the heart of the page. */
  .dashboard { max-width: 60rem; }
  .dash-block { margin-top: var(--space-10); }
  .dash-block:first-child { margin-top: var(--space-2); }
  .dash-h2 {
    font-size: var(--text-lg);
    font-weight: var(--weight-semibold);
    color: var(--ink);
    letter-spacing: -0.01em;
    margin: 0 0 var(--space-4);
  }
  .dash-block-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: var(--space-4); }
  .dash-block-head .dash-h2 { margin: 0; }
  .dash-block-link { font-size: var(--text-2xs); color: var(--accent); }

  /* Needs you — doorways, not tiles: a big mono count, a label, a routing CTA. */
  .dash-needs { display: flex; flex-wrap: wrap; gap: var(--space-10); }
  .dash-need { display: flex; flex-direction: column; gap: 3px; text-decoration: none; }
  .dash-need-n { font-size: var(--text-3xl); font-weight: var(--weight-bold); color: var(--accent); line-height: 1; letter-spacing: -0.02em; }
  .dash-need-label { font-size: var(--text-base); color: var(--text); }
  .dash-need-cta { font-size: var(--text-2xs); color: var(--muted); transition: color var(--dur-fast) var(--ease); }
  .dash-need:hover .dash-need-cta { color: var(--accent); }
  .dash-caught-up { font-size: var(--text-md); color: var(--green); }

  /* The shortlist — a hairline list of the finalists (recap lineage). */
  .dash-shortlist { background: var(--surface); border-radius: var(--radius-lg); box-shadow: var(--shadow-xs); overflow: hidden; }
  .dash-sl-row {
    display: grid;
    grid-template-columns: 4.5rem 6.5rem minmax(0, 1fr) auto;
    gap: var(--space-4);
    align-items: center;
    padding: var(--space-3) var(--space-5);
    border-bottom: 1px solid var(--line);
    text-decoration: none;
  }
  .dash-sl-row:last-child { border-bottom: none; }
  .dash-sl-row:hover { background: var(--surface-2); }
  .dash-sl-faces { font-size: 17px; display: inline-flex; gap: var(--space-1); }
  .dash-sl-price { font-family: var(--font-mono); font-weight: var(--weight-bold); color: var(--ink); font-size: var(--text-md); text-align: right; }
  .dash-sl-place { color: var(--ink); font-weight: var(--weight-medium); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .dash-sl-place .dist { color: var(--muted); font-weight: var(--weight-normal); }

  /* Where we stand — three quiet columns, separated by space (no boxes). */
  .dash-stand { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-8) var(--space-10); }
  .dash-stand-h3 {
    font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.07em;
    font-weight: var(--weight-semibold); color: var(--muted); margin: 0 0 var(--space-2);
  }
  .dash-stand-line {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--space-3); padding: 7px 0; border-bottom: 1px solid var(--line);
    text-decoration: none; font-size: var(--text-2xs);
  }
  .dash-stand-line:last-child { border-bottom: none; }
  .dash-stand-line .lab { color: var(--text); display: inline-flex; align-items: center; gap: 6px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .dash-stand-line:hover .lab { color: var(--ink); }
  .dash-stand-line .val { font-family: var(--font-mono); color: var(--ink); white-space: nowrap; }
  .dash-stand-line .val .sub { color: var(--muted); margin-left: var(--space-2); }
  .dash-stand-line .val .sub-median { color: var(--faint); font-size: var(--text-xs); }

  @media (max-width: 820px) {
    .dash-stand { grid-template-columns: 1fr; gap: var(--space-6); }
    .dash-needs { gap: var(--space-6); }
  }

  /* --- Compare (T4.2): column per listing ----------------------------- */
  .compare-table-wrap { overflow-x: auto; }
  .compare-table {
    border-collapse: collapse;
    width: 100%;
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    font-size: var(--text-sm);
  }
  .compare-table th,
  .compare-table td {
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--c-border);
    text-align: left;
    vertical-align: top;
  }
  .compare-table tbody tr:last-child th,
  .compare-table tbody tr:last-child td { border-bottom: none; }
  .compare-table thead th {
    background: var(--c-surface-2);
    color: var(--c-ink);
  }
  .compare-table .compare-field {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--c-text-muted);
    font-weight: var(--weight-semibold);
    white-space: nowrap;
    background: var(--c-surface-2);
  }
  .compare-table .compare-col { min-width: 9rem; }
  .compare-table .num { text-align: right; font-variant-numeric: tabular-nums; }

  /* --- Auth pages (sign in / passwords) ------------------------------- */
  .auth-shell { max-width: 24rem; margin: var(--space-16) auto; padding-inline: var(--page-pad); }
  .auth-brand { text-align: center; margin-bottom: var(--space-6); }
  .auth-wordmark {
    font-family: var(--font-sans);
    font-size: var(--text-3xl);
    font-weight: var(--weight-bold);
    letter-spacing: -0.01em;
    color: var(--ink);
  }
  .auth-tagline { margin-top: var(--space-2); color: var(--c-text-muted); font-size: var(--text-md); }
  .auth-card {
    padding: var(--space-8);
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
  }
  .auth-card h1 { font-size: var(--text-lg); margin-bottom: var(--space-5); }
  .auth-card .field { margin-bottom: var(--space-4); }
  .auth-card .btn { width: 100%; }
  .auth-links { margin-top: var(--space-4); text-align: center; font-size: var(--text-sm); }

  @media (max-width: 640px) {
    .recap-panel { width: 100vw; border-left: none; }
  }

  /* "Already have this flat?" — URL duplicate check above the recap. */
  .url-check {
    background: var(--c-surface-2);
    border: 1px solid var(--c-border);
    border-radius: var(--radius-md);
    padding: var(--space-4);
    margin-bottom: var(--space-4);
  }
  .url-check-heading { margin: 0; font-size: var(--text-md); }
  .url-check-intro { margin: var(--space-2) 0 var(--space-3); color: var(--c-text-muted); font-size: var(--text-sm); }
  .url-check-form { display: flex; gap: var(--space-3); flex-wrap: wrap; }
  .url-check-input { flex: 1 1 22rem; }
  .url-check-result {
    margin: var(--space-3) 0 0;
    padding: var(--space-3);
    border-radius: var(--radius-sm);
    font-size: var(--text-sm);
  }
  .url-check-result.is-match { background: var(--c-warning-tint); border: 1px solid var(--c-warning); }
  .url-check-result.is-new { background: var(--c-success-tint); border: 1px solid var(--c-success); }
  .url-check-link { margin-left: var(--space-2); font-weight: 600; }

  /* Autofill: the URL-first "paste a link, we pre-fill" step on New listing. */
  .autofill-step { max-width: 44rem; }
  .autofill-heading { margin: 0; font-size: var(--text-lg); }
  .autofill-intro { margin: var(--space-2) 0 var(--space-4); color: var(--c-text-muted); }
  .autofill-form { display: flex; gap: var(--space-3); flex-wrap: wrap; align-items: center; }
  .autofill-input { flex: 1 1 24rem; }
  .autofill-manual { display: inline-block; margin-top: var(--space-4); }
  .autofill-loading { display: none; margin: var(--space-3) 0 0; color: var(--c-text-muted); font-size: var(--text-sm); }
  .autofill-note {
    margin: 0 0 var(--space-4); padding: var(--space-3);
    border-radius: var(--radius-sm); font-size: var(--text-sm);
    background: var(--c-warning-tint); border: 1px solid var(--c-warning);
  }
  /* Turbo flags the frame busy while we fetch — reveal the hint, dim the step. */
  turbo-frame#listing_new[aria-busy="true"] .autofill-loading { display: block; }
  turbo-frame#listing_new[aria-busy="true"] .autofill-step { opacity: 0.6; pointer-events: none; }
}

/* ===========================================================================
   UTILITIES
   =========================================================================== */
@layer utilities {
  .muted { color: var(--c-text-muted); }

  /* Visually hidden but available to screen readers (e.g. an icon-only column). */
  .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;
  }
  .subtle { color: var(--c-text-subtle); }
  .num { font-variant-numeric: tabular-nums; }
  .stack-sm > * + * { margin-top: var(--space-2); }
  /* Standalone "back" link under a show card. */
  .page-back { margin-top: var(--space-4); }
  .visually-hidden {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }
}

/* Documents section — two-column layout (you | partner). Tokenized for cohesion. */
.documents-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(22rem, 1fr));
  gap: var(--space-6);
  align-items: start;
}
.documents-column-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: 32px; /* keep panels aligned whether or not the column has an Edit button */
  margin-bottom: var(--space-3);
}
.documents-owner {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  min-width: 0;
}
.documents-owner h2 {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  letter-spacing: -0.01em;
  color: var(--c-ink);
  overflow-wrap: anywhere;
}
/* "You" marker: neutral, never cobalt — cobalt is reserved for navigation. */
.owner-tag {
  flex: none;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--c-text-muted);
  background: var(--c-surface-2);
  padding: 2px var(--space-2);
  border-radius: var(--radius-pill);
}

/* One calm surface per person; Profile and Documents are sections inside it,
   divided by space and a single hairline — not two stacked cards. */
.documents-panel { padding: var(--space-5); }
.doc-section + .doc-section {
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: 1px solid var(--c-border);
}
.doc-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}
.doc-section-label {
  margin: 0 0 var(--space-3);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--c-text-muted);
}
.doc-section-head .doc-section-label { margin-bottom: 0; }

.profile-details {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--space-1) var(--space-4);
  margin: 0;
}
.profile-details dt { font-weight: var(--weight-medium); color: var(--c-text-muted); }
.profile-details dd { margin: 0; color: var(--c-ink); }

/* Empty states teach what belongs here, not just "nothing". */
.doc-empty {
  margin: 0;
  color: var(--c-text-muted);
  font-size: var(--text-base);
  line-height: 1.5;
  max-width: 36ch;
}

.document-list { list-style: none; margin: 0; padding: 0; }
.document-list-item {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--c-border);
}
.document-list-item:last-child { border-bottom: none; }
.document-link { font-weight: var(--weight-medium); }
.document-meta { color: var(--c-text-muted); font-size: var(--text-xs); }
.document-list-item .badge-private { margin-left: auto; }
/* ===========================================================================
   ASSISTANT (chat)
   =========================================================================== */
.page-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}
.page-head h1 { margin: 0 0 var(--space-1); }

/* ===========================================================================
   ASSISTANT — master-detail (conversation list + transcript thread)
   The drafting desk: a recognizable list on the left, the open conversation on
   the right. No bubbles — turns are a quiet transcript; drafts are artifacts.
   =========================================================================== */

/* Break the assistant out of the centered, padded container so the two panes
   fill the viewport and scroll internally, like a mail client. */
.container:has(.assistant-shell) {
  max-width: none;
  padding: 0;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.assistant-shell {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: clamp(264px, 26vw, 344px) minmax(0, 1fr);
}

/* --- Master: the conversation list --------------------------------- */
.assistant-list {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--c-surface);
  border-right: 1px solid var(--c-border);
}
.assistant-list-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-5) var(--space-5) var(--space-4);
  border-bottom: 1px solid var(--c-border);
}
.assistant-list-head h1 {
  margin: 0;
  font-size: var(--text-xl);
  font-weight: var(--weight-semibold);
  letter-spacing: -0.01em;
  color: var(--c-ink);
}
.assistant-list-head p { margin: var(--space-1) 0 0; font-size: var(--text-2xs); color: var(--c-text-muted); max-width: 32ch; }
.assistant-list-head .btn-primary { display: inline-flex; align-items: center; gap: var(--space-1); flex-shrink: 0; }

.assistant-convs { flex: 1; min-height: 0; overflow-y: auto; }
.conv {
  display: block;
  padding: var(--space-3) var(--space-5);
  border-bottom: 1px solid var(--c-border);
  text-decoration: none;
  color: inherit;
}
.conv:hover { background: var(--c-surface-2); text-decoration: none; color: inherit; }
.conv.is-active { background: var(--c-accent-tint); }
.conv-top { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); }
.conv-title {
  min-width: 0;
  font-weight: var(--weight-semibold);
  font-size: var(--text-base);
  color: var(--c-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.conv.is-active .conv-title { color: var(--c-accent-deep); }
.conv-time { flex-shrink: 0; font-size: var(--text-xs); color: var(--c-text-muted); }
.conv-snip {
  display: block;
  margin-top: 3px;
  font-size: var(--text-2xs);
  color: var(--c-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.conv.is-active .conv-snip { color: var(--c-text); }
.conv-flat {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 6px;
  font-size: var(--text-xs);
  color: var(--c-text-muted);
}
.conv-flat-pin { color: var(--c-accent); font-size: 0.7em; }
.conv.is-active .conv-flat { color: var(--c-text); }
.assistant-convs-empty { padding: var(--space-5); color: var(--c-text-muted); font-size: var(--text-sm); }

/* --- Detail: the thread -------------------------------------------- */
.assistant-thread { display: flex; flex-direction: column; min-height: 0; background: var(--c-paper); }
.assistant-thread-empty { align-items: center; justify-content: center; }

.thread-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-6);
  border-bottom: 1px solid var(--c-border);
  background: var(--c-surface);
}
.thread-back {
  display: none;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-md);
  color: var(--c-text-muted);
  flex-shrink: 0;
}
.thread-back:hover { background: var(--c-surface-2); color: var(--c-ink); }
.thread-title {
  flex: 0 1 auto;
  min-width: 0;
  margin: 0 0 0 -6px;
  padding: 4px 6px;
  border: 0;
  background: none;
  font-family: inherit;
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
  color: var(--c-ink);
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border-radius: var(--radius-sm);
}
.thread-title:hover { background: var(--c-surface-2); }
.thread-title[hidden] { display: none; }
.thread-flat {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex-shrink: 0;
  padding: 3px 9px;
  border-radius: var(--radius-pill);
  background: var(--c-surface-2);
  color: var(--c-text-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  text-decoration: none;
}
.thread-flat:hover { background: var(--c-accent-tint); color: var(--c-accent-deep); }
.iconbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: 1px solid var(--c-border-strong);
  border-radius: var(--radius-md);
  background: var(--c-surface);
  color: var(--c-text-muted);
  cursor: pointer;
}
.iconbtn:hover { background: var(--c-surface-2); color: var(--c-ink); }

/* Header actions: pencil (rename) + trash (delete), pushed to the right. The
   pencil is the first direct button; the delete is a button_to form. */
.thread-action { flex-shrink: 0; }
.thread-head > button.thread-action { margin-left: auto; }
.thread-head > form.button_to { margin: 0; flex-shrink: 0; }

/* Inline rename: the title swaps for this form in place. Hidden via [hidden]
   until the rename controller reveals it (and reset, so flex doesn't unhide). */
.thread-rename { display: flex; flex: 1; min-width: 0; align-items: center; gap: var(--space-2); margin: 0; }
.thread-rename[hidden] { display: none; }
.thread-rename input {
  flex: 1;
  min-width: 0;
  height: 34px;
  padding: 0 var(--space-3);
  border: 1px solid var(--c-border-strong);
  border-radius: var(--radius-md);
  font: inherit;
  font-size: var(--text-sm);
  color: var(--c-ink);
}
.thread-rename input:focus { outline: none; border-color: var(--c-accent); box-shadow: 0 0 0 3px var(--c-focus); }
/* While renaming, clear the flat chip and action buttons so the editor is calm. */
.thread-head:has(.thread-rename:not([hidden])) .thread-flat,
.thread-head:has(.thread-rename:not([hidden])) .thread-action,
.thread-head:has(.thread-rename:not([hidden])) > form.button_to { display: none; }

.thread-flow { flex: 1; min-height: 0; overflow-y: auto; padding: var(--space-6) var(--space-6) var(--space-4); }
.thread-turns { max-width: 46rem; margin: 0 auto; display: flex; flex-direction: column; }
.thread-turns:empty::before {
  content: attr(data-empty-hint);
  display: block;
  margin-top: var(--space-8);
  text-align: center;
  color: var(--c-text-muted);
  font-size: var(--text-sm);
  line-height: 1.6;
}

/* --- One turn (direction D: asymmetric transcript, no bubbles) ------ */
.turn { padding: var(--space-4) 0; border-bottom: 1px solid var(--c-border); }
.turn:last-child { border-bottom: none; }
.turn-user { text-align: right; }
.turn-who {
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-text-muted);
  margin-bottom: var(--space-2);
}
.turn-user .turn-who { color: var(--c-accent); }
.turn-content { color: var(--c-ink); line-height: 1.6; overflow-wrap: anywhere; }
.turn-user .turn-content { color: var(--c-text); }
.turn-content > :first-child { margin-top: 0; }
.turn-content > :last-child { margin-bottom: 0; }
.turn-content p { margin: 0 0 var(--space-2); }
.turn-content ul,
.turn-content ol { margin: 0 0 var(--space-2); padding-left: var(--space-5); }
.turn-content h1,
.turn-content h2,
.turn-content h3 { margin: var(--space-3) 0 var(--space-2); font-size: var(--text-md); }
.turn-content pre {
  background: var(--c-surface-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  overflow-x: auto;
}
.turn-content code { font-family: var(--font-mono); font-size: 0.92em; }
.turn-content a { color: var(--c-accent); }

.turn-copy {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: var(--space-2);
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-sm);
  background: var(--c-surface);
  color: var(--c-text-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--dur) var(--ease), color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.turn:hover .turn-copy,
.turn:focus-within .turn-copy { opacity: 1; }
.turn-copy:hover { color: var(--c-ink); background: var(--c-surface-2); }
.turn.is-copied .turn-copy { opacity: 1; color: var(--c-success); border-color: var(--c-success); }

/* --- Draft artifact (the assistant marks something as sendable) ----- */
.draft {
  margin: var(--space-3) 0 var(--space-1);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.draft-head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--c-accent-tint);
  border-bottom: 1px solid var(--c-accent-tint-2);
}
.draft-kind {
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-accent-deep);
}
.draft-lang {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--c-accent-deep);
  background: var(--c-surface);
  border-radius: var(--radius-pill);
  padding: 2px 9px;
}
.draft-copy {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--c-accent);
  border-radius: var(--radius-sm);
  background: var(--c-accent);
  color: var(--c-on-accent);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  cursor: pointer;
}
.draft-copy:hover { background: var(--c-accent-hover); border-color: var(--c-accent-hover); }
.draft.is-copied .draft-copy { background: var(--c-success); border-color: var(--c-success); }
.draft-body { padding: var(--space-4); color: var(--c-ink); line-height: 1.6; }
.draft-body > :first-child { margin-top: 0; }
.draft-body > :last-child { margin-bottom: 0; }
.draft-body p { margin: 0 0 var(--space-2); }
.draft-gloss {
  padding: var(--space-3) var(--space-4);
  border-top: 1px dashed var(--c-border);
  color: var(--c-text-muted);
  font-size: var(--text-2xs);
  font-style: italic;
  line-height: 1.55;
}
.draft-gloss p { margin: 0 0 var(--space-2); }
.draft-gloss > :last-child { margin-bottom: 0; }

/* --- Composer ------------------------------------------------------- */
.composer { padding: var(--space-3) var(--space-6) var(--space-5); background: var(--c-paper); }
.composer-field {
  max-width: 46rem;
  margin: 0 auto;
  display: flex;
  align-items: flex-end;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-2) var(--space-2) var(--space-3);
  background: var(--c-surface);
  border: 1px solid var(--c-border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
}
.composer-field:focus-within { border-color: var(--c-accent); box-shadow: 0 0 0 3px var(--c-focus); }
.composer-input {
  flex: 1;
  border: 0;
  resize: none;
  background: none;
  font: inherit;
  color: var(--c-ink);
  line-height: 1.5;
  min-height: 1.6rem;
  max-height: 40vh;
  padding: var(--space-2) 0;
  outline: none;
}
.composer-send { flex-shrink: 0; }

/* --- Thinking indicator (between send and first streamed token) -----
   The assistant turn arrives empty, then tokens stream in. While it's empty,
   show a quiet pulsing label; it disappears the instant content lands. */
.turn-content:empty::after {
  content: attr(data-thinking);
  color: var(--c-text-subtle);
  font-size: var(--text-sm);
  animation: thinking-pulse 1.4s var(--ease) infinite;
}
@keyframes thinking-pulse { 0%, 100% { opacity: 0.4; } 50% { opacity: 1; } }

/* --- Empty thread (no conversation selected) ------------------------ */
.assistant-empty { max-width: 30rem; text-align: center; padding: var(--space-6); }
.assistant-empty h2 { margin: 0 0 var(--space-2); font-size: var(--text-xl); color: var(--c-ink); }
.assistant-empty p { margin: 0 0 var(--space-5); color: var(--c-text-muted); line-height: 1.6; }

/* --- Responsive: collapse to one pane ------------------------------- */
@media (max-width: 860px) {
  .assistant-shell { grid-template-columns: 1fr; }
  .assistant-shell.has-thread .assistant-list { display: none; }
  .assistant-shell:not(.has-thread) .assistant-thread { display: none; }
  .thread-back { display: inline-flex; }
}
@media (prefers-reduced-motion: reduce) {
  .turn-copy { transition: none; }
  .turn-content:empty::after { animation: none; }
}

/* === The Log =========================================================== */
/* Reuses the assistant master-detail shell; only the detail pane and the
   entry-form internals are Log-specific. */
.log-detail { overflow-y: auto; }
.log-detail-meta { display: flex; flex-direction: column; line-height: 1.3; min-width: 0; flex: 1; }
.log-detail-author { font-weight: var(--weight-semibold); color: var(--c-ink); }
.log-detail-time { font-size: var(--text-xs); color: var(--c-text-muted); }
.log-detail-body { padding: var(--space-6); max-width: 60ch; }
.log-prose { color: var(--c-text); line-height: 1.7; white-space: normal; }
.log-prose p { margin: 0 0 var(--space-3); }

.log-refs { margin-top: var(--space-6); padding-top: var(--space-5); border-top: 1px solid var(--c-border); }
.log-refs-label { margin: var(--space-4) 0 var(--space-2); font-size: var(--text-xs); font-weight: var(--weight-semibold); text-transform: uppercase; letter-spacing: 0.04em; color: var(--c-text-muted); }
.log-refs-label:first-child { margin-top: 0; }
.log-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-2); }
.log-chip {
  display: inline-flex; align-items: center;
  padding: 2px var(--space-2);
  border: 1px solid var(--c-border); border-radius: var(--radius-pill, 999px);
  font-size: var(--text-xs); color: var(--c-text); text-decoration: none;
}
.log-chip:hover { background: var(--c-surface-2); text-decoration: none; }

/* --- The entry form -------------------------------------------------- */
.log-form { display: flex; flex-direction: column; gap: var(--space-5); }
.log-field-label { display: block; font-weight: var(--weight-semibold); color: var(--c-ink); margin-bottom: var(--space-1); }
.log-field-hint { margin: 0 0 var(--space-2); font-size: var(--text-xs); color: var(--c-text-muted); }
.log-textarea { width: 100%; resize: vertical; }
.log-select { width: 100%; }
.log-fieldset { border: none; padding: 0; margin: 0; }
.log-checks { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); }
.log-check { display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--text-sm); }
.log-form-actions { display: flex; gap: var(--space-3); align-items: center; }

/* Private pill — a neutral grey pill with a line-icon lock. Emoji is reserved
   for reactions, so the lock is an SVG, not 🔒. */
.badge-private {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--c-text-muted);
  background: var(--c-surface-2);
  padding: 2px var(--space-2);
  border-radius: var(--radius-pill);
  white-space: nowrap;
}
.badge-icon { flex: none; }

/* Document show: the body is the document — give it readable prose width. */
.document-body {
  max-width: 70ch;
  line-height: 1.6;
  color: var(--c-text);
}
.document-body p { margin: 0 0 var(--space-3); }
.document-body p:last-child { margin-bottom: 0; }
.document-files-section { margin-top: var(--space-6); }
.document-files { list-style: none; margin: 0; padding: 0; }
.document-files li {
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--c-border);
}
.document-files li:last-child { border-bottom: none; }
.document-files img {
  display: block;
  margin-top: var(--space-2);
  border-radius: var(--radius-sm);
}

/* ===========================================================================
   SCRAPE PICKER (native <dialog>) + TOASTS
   =========================================================================== */

/* The "Run now" picker: a modal tree of country → city → search checkboxes. */
.picker {
  width: min(560px, calc(100vw - var(--space-8)));
  max-height: min(80vh, 720px);
  padding: var(--space-6);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  background: var(--c-surface);
  color: var(--c-text);
  box-shadow: var(--shadow-lg);
}
.picker::backdrop { background: rgba(20, 24, 30, 0.35); }
.picker-dismiss { position: absolute; top: var(--space-3); right: var(--space-3); margin: 0; }
.picker-close {
  border: 0; background: transparent; cursor: pointer;
  font-size: var(--text-lg); line-height: 1; color: var(--c-text-muted);
  padding: var(--space-1) var(--space-2); border-radius: var(--radius-sm);
}
.picker-close:hover { background: var(--c-surface-2); color: var(--c-ink); }
.picker-title { margin: 0 0 var(--space-1); color: var(--c-ink); font-size: var(--text-lg); }
.picker-hint { margin: 0 0 var(--space-4); color: var(--c-text-muted); font-size: var(--text-sm); }
.picker-form { display: flex; flex-direction: column; gap: var(--space-3); }

.picker-all {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--c-surface-2); border-radius: var(--radius-md);
  font-weight: 600; color: var(--c-ink); cursor: pointer;
}
.picker-tree {
  display: flex; flex-direction: column; gap: var(--space-4);
  max-height: 46vh; overflow-y: auto;
  padding-right: var(--space-2);
}
.picker-country { display: flex; flex-direction: column; gap: var(--space-2); }
.picker-group {
  display: flex; align-items: center; gap: var(--space-2);
  cursor: pointer; color: var(--c-ink);
}
.picker-group-country { font-weight: 600; }
.picker-group-city { font-weight: 500; padding-left: var(--space-4); color: var(--c-text); }
.picker-city { display: flex; flex-direction: column; gap: var(--space-1); }
.picker-leaves { display: flex; flex-direction: column; gap: var(--space-1); }

/* Leaf row: nested under its city (or country, when nationwide). */
.picker-leaf {
  display: flex; align-items: baseline; gap: var(--space-2);
  padding: var(--space-1) var(--space-2) var(--space-1) var(--space-8);
  border-radius: var(--radius-sm); cursor: pointer;
}
.picker-leaf:hover { background: var(--c-surface-2); }
.picker-country > .picker-leaves > .picker-leaf { padding-left: var(--space-4); }
.picker-leaf-name { color: var(--c-text); }
.picker-leaf-url {
  font-size: var(--text-xs); color: var(--c-text-subtle);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.picker input[type="checkbox"] { accent-color: var(--c-accent); cursor: pointer; }
.picker-empty { margin: 0 0 var(--space-4); color: var(--c-text-muted); }
.picker-actions {
  display: flex; justify-content: flex-end; gap: var(--space-2);
  margin-top: var(--space-2); padding-top: var(--space-3);
  border-top: 1px solid var(--c-border);
}

/* Toast tray: stacked, fixed bottom-right, self-dismissing. */
.toasts {
  position: fixed; bottom: var(--space-5); right: var(--space-5);
  z-index: 50; display: flex; flex-direction: column; gap: var(--space-2);
  max-width: min(360px, calc(100vw - var(--space-8)));
}
.toast {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--c-surface); color: var(--c-ink);
  border: 1px solid var(--c-border); border-left: 3px solid var(--c-accent);
  border-radius: var(--radius-md); box-shadow: var(--shadow-md);
  animation: toast-in var(--dur) var(--ease);
}
.toast-success { border-left-color: var(--c-success); }
.toast-message { font-size: var(--text-sm); margin-right: auto; }
.toast-close {
  border: 0; background: transparent; cursor: pointer; line-height: 1;
  color: var(--c-text-muted); font-size: var(--text-base);
}
.toast-close:hover { color: var(--c-ink); }
@keyframes toast-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .toast { animation: none; } }

/* ===========================================================================
   THE BRAIN  —  read-only view of the prompts behind every LLM surface
   =========================================================================== */
/* A calm catalogue: one card per prompt, the Brain itself featured first. The
   card is the link (like Portals/Documents). These are read-only here — the
   prompts are files under app/prompts/, edited in the repo. */
.prompts {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: var(--space-4);
}

.prompt-card {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-5);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  text-decoration: none; color: inherit;
  transition: border-color .12s ease, box-shadow .12s ease, transform .12s ease;
}
.prompt-card:hover {
  border-color: var(--input-border);
  box-shadow: var(--shadow-sm);
  transform: translateY(-1px);
}

/* The Brain is the source every other prompt leans on — span the row and tint it
   so it reads as the root, not a sibling. */
.prompt-card-brain {
  grid-column: 1 / -1;
  background: var(--accent-tint);
  border-color: transparent;
}

.prompt-card-title {
  margin: 0; font-size: var(--text-md); font-weight: 600; color: var(--ink);
}
.prompt-card-when { margin: 0; color: var(--text); font-size: var(--text-sm); }
.prompt-card-meta { margin: 0; font-size: var(--text-xs); }

/* Show page: the "what is this / when does it run" panel above the prompt. */
.prompt-explain {
  display: flex; flex-direction: column; gap: var(--space-2);
  margin-bottom: var(--space-4);
}
.prompt-explain p { margin: 0; }

/* The prompt itself, read-only: shown verbatim, generous and legible, so prose
   in markdown stays readable. */
.prompt-readonly-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3);
  margin-bottom: var(--space-3);
}
.prompt-readonly-label {
  font-size: var(--text-2xs); font-weight: 600;
  letter-spacing: .02em; text-transform: uppercase; color: var(--muted);
}
.prompt-readonly-source { font-size: var(--text-xs); }
.prompt-body {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--text-sm); line-height: 1.6;
  white-space: pre-wrap; word-wrap: break-word;
  color: var(--text);
}
