    @font-face {
      font-family: "Space Grotesk";
      font-style: normal;
      font-weight: 300 700;
      font-display: swap;
      src: url("/static/fonts/space-grotesk-latin.woff2") format("woff2");
    }

    :root {
      --display: "Space Grotesk", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
      --edge: inset 0 1px 0 rgba(255, 255, 255, 0.045);
      --shadow-tint: 0 14px 36px rgba(3, 10, 6, 0.42);
      --bg: #0a0d0b;
      --surface: #111814;
      --surface-2: #18241d;
      --border: #263a2e;
      /* 1.4.11: boundary cue for interactive controls. #4f6b5d is
         3.09:1 vs --surface (#111814) and 3.34:1 vs --bg (#0a0d0b);
         --border itself is only 1.48:1 / 1.61:1 and stays on
         decorative dividers, which are out of 1.4.11 scope. */
      --border-interactive: #4f6b5d;
      --text: #eef5ef;
      --muted: #93a89b;
      --accent: #3dd68c;
      --accent-soft: rgba(61, 214, 140, 0.14);
      --warn: #f0b429;
      --hot: #ff6b6b;
      --hot-soft: rgba(255, 107, 107, 0.14);
      --fresh-soft: rgba(61, 214, 140, 0.1);
      /* Wave 3 item 5: freshness ramp — 1-3h band, fits the neon-dark
         palette (blue between the brand-neon green and the dim/gray tail). */
      --ice: #5ec8f5;
      --ice-soft: rgba(94, 200, 245, 0.14);
      --shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
      --radius: 18px;
      --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
      --ease-spring: cubic-bezier(0.2, 0.9, 0.25, 1.08);
      --motion-fast: 160ms;
      --motion-base: 240ms;
      --safe-t: env(safe-area-inset-top, 0px);
      --safe-b: env(safe-area-inset-bottom, 0px);
      --safe-l: env(safe-area-inset-left, 0px);
      --safe-r: env(safe-area-inset-right, 0px);
      --header-h: 0px;
      --sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", system-ui, sans-serif;
      --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
    }

    * { box-sizing: border-box; }
    html, body { height: 100%; }
    body {
      margin: 0;
      background: var(--bg);
      color: var(--text);
      font-family: var(--sans);
      font-size: 16px;
      line-height: 1.4;
      -webkit-font-smoothing: antialiased;
      -webkit-tap-highlight-color: transparent;
      overscroll-behavior-y: contain;
    }
    /* Ambient atmosphere: faint money-green glow pooling at the top of the page */
    body::before {
      content: "";
      position: fixed;
      inset: 0;
      z-index: -1;
      pointer-events: none;
      background:
        radial-gradient(120% 60% at 50% -12%, rgba(61, 214, 140, 0.075), transparent 62%),
        radial-gradient(80% 44% at 88% -6%, rgba(61, 214, 140, 0.05), transparent 58%);
    }
    /* Film grain so large dark surfaces don't read as flat digital black */
    body::after {
      content: "";
      position: fixed;
      inset: 0;
      z-index: 60;
      pointer-events: none;
      opacity: 0.05;
      background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
      background-size: 140px 140px;
    }

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

    button,
    [role="button"],
    a.primary {
      -webkit-tap-highlight-color: transparent;
    }
    button:not(:disabled),
    [role="button"],
    a.primary {
      transition: transform var(--motion-fast) var(--ease-out),
        border-color var(--motion-fast) ease,
        background-color var(--motion-fast) ease,
        color var(--motion-fast) ease,
        opacity var(--motion-fast) ease;
    }
    button:not(:disabled):active,
    [role="button"]:active,
    a.primary:active {
      transform: scale(0.975);
    }

    a { color: var(--accent); text-decoration: none; }
    a:hover { text-decoration: underline; }

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

    /* —— App chrome —— */
    .app-header {
      position: sticky;
      top: 0;
      z-index: 40;
      padding: calc(6px + var(--safe-t)) 12px 6px;
      padding-left: calc(12px + var(--safe-l));
      padding-right: calc(12px + var(--safe-r));
      background: rgba(10, 13, 11, 0.94);
      backdrop-filter: blur(18px) saturate(1.2);
      -webkit-backdrop-filter: blur(18px) saturate(1.2);
      border-bottom: 1px solid rgba(38, 58, 46, 0.8);
    }

    .top-row {
      display: grid;
      grid-template-columns: minmax(0, 1fr) auto;
      align-items: center;
      column-gap: 8px;
      max-width: 1200px;
      margin: 0 auto;
    }

    .brand {
      display: flex;
      align-items: center;
      gap: 8px;
      min-width: 0;
    }

    .brand-copy {
      min-width: 0;
      overflow: hidden;
    }

    .brand-mark {
      width: 28px;
      height: 28px;
      border-radius: 8px;
      background: var(--surface-2);
      border: 1px solid var(--border);
      object-fit: cover;
      flex-shrink: 0;
    }

    .brand h1 {
      margin: 0;
      font-size: 15px;
      font-weight: 650;
      letter-spacing: -0.02em;
      line-height: 1.15;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .status-line {
      margin-top: 1px;
      display: flex;
      align-items: center;
      gap: 5px;
      min-width: 0;
      color: var(--muted);
      font-size: 11px;
      line-height: 1.2;
      white-space: nowrap;
    }
    #status-text {
      flex: 1 1 auto;
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    /* Item 6 (degraded-state honesty): active only while the header status
       is showing a degraded reason — see setStatusLineClickable in app.js. */
    .status-line.clickable {
      cursor: pointer;
    }
    .status-line.clickable:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 2px;
      border-radius: 4px;
    }

    .live-dot {
      width: 7px;
      height: 7px;
      border-radius: 50%;
      background: var(--accent);
      box-shadow: 0 0 0 0 rgba(61, 214, 140, 0.5);
      animation: pulse 1.8s ease-out infinite;
      flex-shrink: 0;
    }
    .live-dot.off { background: #5d7264; animation: none; box-shadow: none; }
    .live-dot.warn { background: var(--warn); animation: none; }

    @keyframes pulse {
      0% { box-shadow: 0 0 0 0 rgba(61, 214, 140, 0.45); }
      70% { box-shadow: 0 0 0 8px rgba(61, 214, 140, 0); }
      100% { box-shadow: 0 0 0 0 rgba(61, 214, 140, 0); }
    }

    .header-actions {
      display: flex;
      align-items: center;
      gap: 6px;
      flex-shrink: 0;
    }
    .app-header .header-actions .icon-btn {
      min-width: 36px;
      min-height: 36px;
      padding: 0 10px;
      border-radius: 10px;
      font-size: 12px;
      position: relative;
    }
    /* Keeps the compact 36px visual box but restores a 44x44pt touch target.
       The pseudo-element is transparent and out of flow, so header height and
       button spacing are unchanged. */
    .app-header .header-actions .icon-btn::after {
      content: "";
      position: absolute;
      top: 50%;
      left: 50%;
      width: 44px;
      height: 44px;
      min-width: 100%;
      min-height: 100%;
      transform: translate(-50%, -50%);
    }
    .app-header .settings-trigger {
      width: 36px;
      padding: 0;
    }
    .app-header .settings-trigger svg {
      width: 17px;
      height: 17px;
    }
    .app-header .settings-trigger .badge-dot {
      top: 6px;
      right: 6px;
    }
    .zip-btn {
      font-variant-numeric: tabular-nums;
      letter-spacing: 0.02em;
      min-width: 52px;
      font-weight: 700;
    }
    .zip-bar {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 8px;
      margin-top: 10px;
      transform-origin: top center;
      animation: zip-bar-in var(--motion-base) var(--ease-out) both;
    }
    .zip-bar[hidden] { display: none !important; }
    .zip-bar input {
      flex: 1 1 120px;
      min-height: 40px;
      min-width: 110px;
      border-radius: 12px;
      border: 1px solid var(--border);
      background: var(--surface);
      color: inherit;
      padding: 0 12px;
      font-size: 16px;
      font-weight: 650;
    }
    .zip-recent {
      flex: 1 1 100%;
      margin: 0 !important;
    }
    .zip-switch-status {
      flex: 1 1 100%;
      margin: 0;
      color: var(--muted);
      font-size: 12px;
      font-weight: 650;
    }
    .zip-switch-status[hidden] { display: none; }

    @keyframes zip-bar-in {
      from { opacity: 0; transform: translateY(-5px) scale(0.99); }
      to { opacity: 1; transform: translateY(0) scale(1); }
    }

    .radius-bar {
      display: none;
      align-items: center;
      gap: 10px;
      margin-top: 10px;
      padding: 8px 12px;
      border-radius: 14px;
      border: 1px solid var(--border);
      background: var(--surface);
    }
    .radius-bar label {
      font-size: 12px;
      font-weight: 700;
      letter-spacing: 0.02em;
      color: var(--muted);
      white-space: nowrap;
      flex-shrink: 0;
    }
    .radius-bar .radius-value {
      font-size: 14px;
      font-weight: 800;
      font-variant-numeric: tabular-nums;
      color: var(--accent, #3dd68c);
      min-width: 3.2em;
      text-align: right;
      flex-shrink: 0;
    }
    .radius-bar input[type="range"] {
      flex: 1 1 auto;
      min-width: 0;
      height: 28px;
      margin: 0;
      -webkit-appearance: none;
      appearance: none;
      background: transparent;
      cursor: pointer;
    }
    .radius-bar input[type="range"]::-webkit-slider-runnable-track {
      height: 6px;
      border-radius: 999px;
      background: linear-gradient(
        90deg,
        rgba(61, 214, 140, 0.35),
        rgba(61, 214, 140, 0.9)
      );
    }
    .radius-bar input[type="range"]::-webkit-slider-thumb {
      -webkit-appearance: none;
      appearance: none;
      width: 22px;
      height: 22px;
      margin-top: -8px;
      border-radius: 50%;
      border: 2px solid #062416;
      background: #3dd68c;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
    }
    .radius-bar input[type="range"]::-moz-range-track {
      height: 6px;
      border-radius: 999px;
      background: rgba(61, 214, 140, 0.45);
    }
    .radius-bar input[type="range"]::-moz-range-thumb {
      width: 22px;
      height: 22px;
      border-radius: 50%;
      border: 2px solid #062416;
      background: #3dd68c;
    }
    .field.radius-field input[type="range"] {
      width: 100%;
      margin-top: 8px;
    }
    .field.radius-field .radius-value {
      font-weight: 800;
      color: var(--accent, #3dd68c);
    }

    .icon-btn {
      min-width: 44px;
      min-height: 44px;
      padding: 0 12px;
      border-radius: 12px;
      border: 1px solid var(--border-interactive);
      background: var(--surface);
      color: var(--text);
      font-size: 13px;
      font-weight: 600;
      cursor: pointer;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 6px;
    }
    .icon-btn.primary {
      background: var(--accent);
      border-color: var(--accent);
      color: #062416;
    }
    .icon-btn:disabled { opacity: 0.45; cursor: wait; }
    .icon-btn .badge-dot {
      width: 7px;
      height: 7px;
      border-radius: 50%;
      background: var(--accent);
    }
    .icon-btn.has-filters .badge-dot { background: var(--warn); }
    .settings-trigger {
      position: relative;
      width: 44px;
      padding: 0;
    }
    .settings-trigger svg {
      width: 21px;
      height: 21px;
      stroke: currentColor;
    }
    .settings-trigger .badge-dot {
      position: absolute;
      top: 8px;
      right: 8px;
      width: 6px;
      height: 6px;
      box-shadow: 0 0 0 2px var(--surface);
    }

    /* Pull-to-refresh (iPhone swipe down) */
    .ptr {
      position: fixed;
      top: calc(8px + var(--safe-t));
      left: 50%;
      z-index: 45;
      transform: translate(-50%, -120%);
      min-width: 132px;
      padding: 8px 14px;
      border-radius: 999px;
      background: var(--surface);
      border: 1px solid var(--border);
      box-shadow: var(--shadow);
      color: var(--muted);
      font-size: 12px;
      font-weight: 650;
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 8px;
      opacity: 0;
      pointer-events: none;
      transition: opacity 0.15s ease;
    }
    .ptr.visible { opacity: 1; }
    .ptr.ready { color: var(--accent); border-color: rgba(61, 214, 140, 0.4); }
    .ptr.spinning .ptr-spinner {
      animation: ptr-spin 0.7s linear infinite;
    }
    .ptr-spinner {
      width: 14px;
      height: 14px;
      border-radius: 50%;
      border: 2px solid rgba(147, 168, 155, 0.35);
      border-top-color: var(--accent);
    }
    @keyframes ptr-spin {
      to { transform: rotate(360deg); }
    }
    .feed-shell {
      transition: transform 0.18s ease-out;
      will-change: transform;
    }
    .feed-shell.pulling { transition: none; }

    .summary {
      display: none;
      flex-wrap: wrap;
      gap: 6px;
    }

    .pill {
      display: inline-flex;
      align-items: center;
      gap: 5px;
      padding: 5px 10px;
      border-radius: 999px;
      background: var(--surface);
      border: 1px solid var(--border);
      color: var(--muted);
      font-size: 12px;
      font-weight: 600;
    }
    .pill strong { color: var(--text); font-weight: 700; }
    .pill.hot strong { color: var(--hot); }
    .pill.live strong { color: var(--accent); }

    #sort-chips .chip.is-loading::after {
      content: none;
    }

    .search-row {
      margin-top: 8px;
    }
    #search-row {
      display: flex;
      flex-direction: column;
      gap: 8px;
    }
    .search-row[hidden] { display: none; }
    .saved-search-rail {
      display: flex;
      flex-direction: column;
      gap: 8px;
    }
    #saved-search-chips[hidden],
    #saved-search-settings-chips:empty {
      display: none;
    }
    .chip.saved-search-chip {
      display: inline-flex;
      align-items: center;
      gap: 6px;
    }
    .chip.saved-search-chip .x {
      opacity: 0.7;
      font-weight: 800;
      margin-left: 2px;
    }
    .save-search-prompt {
      display: flex;
      align-items: center;
      gap: 8px;
      min-height: 40px;
      padding: 6px 8px 6px 12px;
      border-radius: 12px;
      border: 1px solid rgba(61, 214, 140, 0.4);
      background: var(--accent-soft);
    }
    .save-search-prompt[hidden] { display: none; }
    .save-search-prompt span {
      flex: 1;
      min-width: 0;
      color: var(--text);
      font-size: 13px;
      font-weight: 650;
      line-height: 1.3;
    }
    .save-search-prompt .primary,
    .save-search-prompt .ghost {
      flex: 0 0 auto;
      min-height: 32px;
      padding: 6px 12px;
      border-radius: 999px;
      font-size: 12px;
      font-weight: 750;
    }
    .save-search-prompt .primary {
      border: 1px solid var(--accent);
      background: var(--accent);
      color: #062416;
    }
    .save-search-prompt .ghost {
      border: 1px solid var(--border);
      background: transparent;
      color: var(--muted);
    }
    #saved-search-empty[hidden] { display: none; }

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

    .active-filters {
      display: flex;
      align-items: center;
      flex-wrap: wrap;
      gap: 6px;
      margin-top: 10px;
    }
    .active-filter,
    .filter-scope-note {
      min-height: 30px;
      padding: 5px 10px;
      border-radius: 999px;
      border: 1px solid rgba(61, 214, 140, 0.35);
      background: var(--accent-soft);
      color: var(--accent);
      font-size: 11px;
      font-weight: 720;
    }
    .active-filter {
      cursor: pointer;
    }
    .active-filter::after {
      content: " ×";
      color: currentColor;
      opacity: 0.72;
    }
    .filter-scope-note {
      border-color: var(--border);
      background: var(--surface);
      color: var(--muted);
    }

    .search {
      width: 100%;
      min-height: 36px;
      padding: 8px 12px 8px 36px;
      border-radius: 12px;
      border: 1px solid var(--border-interactive);
      background: var(--surface) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%238fa0b4' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='7' cy='7' r='4.5'/%3E%3Cpath d='M10.5 10.5L14 14'/%3E%3C/svg%3E") 12px center no-repeat;
      color: var(--text);
      font-size: 15px;
    }
    .search::placeholder { color: #6f8577; }

    .err {
      margin-top: 8px;
      padding: 10px 12px;
      border-radius: 12px;
      background: rgba(255, 107, 107, 0.1);
      border: 1px solid rgba(255, 107, 107, 0.28);
      color: #ffb4b4;
      font-size: 13px;
    }
    .err[hidden] { display: none; }

    .toast {
      margin-top: 8px;
      padding: 8px 12px;
      border-radius: 12px;
      background: var(--accent-soft);
      border: 1px solid rgba(61, 214, 140, 0.28);
      color: var(--accent);
      font-size: 12px;
      font-weight: 600;
      animation: toast-in var(--motion-base) var(--ease-out) both;
    }
    .toast[hidden] { display: none; }
    .toast.busy {
      background: rgba(240, 180, 41, 0.1);
      border-color: rgba(240, 180, 41, 0.32);
      color: #f5ca68;
    }
    @keyframes toast-in {
      from { opacity: 0; transform: translateY(-5px) scale(0.985); }
      to { opacity: 1; transform: translateY(0) scale(1); }
    }

    /* —— Feed —— */
    main {
      padding: 10px 20px calc(26px + var(--safe-b));
      padding-left: calc(20px + var(--safe-l));
      padding-right: calc(20px + var(--safe-r));
      max-width: 1240px;
      margin: 0 auto;
    }

    .view-chrome {
      margin-bottom: 10px;
    }

    .market-banner,
    .coverage-banner {
      display: grid;
      grid-template-columns: auto minmax(0, 1fr) auto;
      align-items: center;
      gap: 12px;
      margin: 0 0 12px;
      padding: 12px 14px;
      border: 1px solid rgba(61, 214, 140, 0.32);
      border-radius: 16px;
      background: linear-gradient(135deg, rgba(61, 214, 140, 0.12), rgba(24, 36, 29, 0.9));
      box-shadow: 0 12px 34px rgba(0, 0, 0, 0.18);
      opacity: 0;
      transform: translateY(-6px) scale(0.992);
      transition: opacity var(--motion-base) ease,
        transform var(--motion-base) var(--ease-out),
        border-color var(--motion-base) ease;
    }
    .market-banner[hidden],
    .coverage-banner[hidden] { display: none; }
    .market-banner.visible,
    .coverage-banner.visible {
      opacity: 1;
      transform: translateY(0) scale(1);
    }
    .market-banner-indicator {
      width: 20px;
      height: 20px;
      border-radius: 50%;
      border: 2px solid rgba(61, 214, 140, 0.24);
      border-top-color: var(--accent);
      animation: ptr-spin 0.8s linear infinite;
    }
    .market-banner-copy,
    .coverage-banner-copy { min-width: 0; }
    .market-banner-copy strong,
    .coverage-banner-copy strong {
      display: block;
      font-size: 13px;
      line-height: 1.25;
    }
    .market-banner-copy > span,
    .coverage-banner-copy > span {
      display: block;
      margin-top: 2px;
      color: var(--muted);
      font-size: 12px;
      line-height: 1.35;
    }
    .market-banner-action,
    .coverage-banner-action {
      min-height: 36px;
      padding: 0 10px;
      border-radius: 10px;
      border: 1px solid var(--border);
      background: rgba(10, 13, 11, 0.58);
      color: var(--text);
      font-size: 12px;
      font-weight: 720;
      cursor: pointer;
    }
    .market-progress {
      height: 3px;
      margin-top: 8px;
      overflow: hidden;
      border-radius: 999px;
      background: rgba(61, 214, 140, 0.13);
    }
    .market-progress span {
      display: block;
      width: 42%;
      height: 100%;
      border-radius: inherit;
      background: var(--accent);
      animation: market-progress 1.45s var(--ease-out) infinite;
      transform-origin: left center;
    }
    .market-progress.is-determinate span {
      /* Full-width bar scaled on the compositor — width transitions
         re-run layout on every frame. JS supplies a unitless 0-100. */
      width: 100%;
      animation: none;
      transform: scaleX(calc(var(--market-progress, 0) / 100));
      transition: transform 320ms var(--ease-out);
    }
    @keyframes market-progress {
      0% { transform: translateX(-115%) scaleX(0.55); opacity: 0.6; }
      48% { transform: translateX(90%) scaleX(1); opacity: 1; }
      100% { transform: translateX(245%) scaleX(0.7); opacity: 0.55; }
    }
    .coverage-banner {
      border-color: rgba(240, 180, 41, 0.28);
      background: linear-gradient(135deg, rgba(240, 180, 41, 0.1), rgba(24, 36, 29, 0.9));
    }
    .coverage-banner-indicator {
      width: 9px;
      height: 9px;
      border-radius: 50%;
      background: var(--warn);
      box-shadow: 0 0 0 5px rgba(240, 180, 41, 0.1);
    }
    /* 0.9.60: #coverage-banner is hard-fail only now, so it reads as a
       compact single line rather than a full card competing with the feed.
       #push-ack-banner keeps the shared .coverage-banner card styling. */
    #coverage-banner {
      grid-template-columns: auto minmax(0, 1fr) auto;
      gap: 8px;
      padding: 8px 12px;
    }
    #coverage-banner .coverage-banner-indicator {
      width: 7px;
      height: 7px;
      box-shadow: 0 0 0 4px rgba(240, 180, 41, 0.1);
    }
    #coverage-banner .coverage-banner-copy {
      display: flex;
      align-items: baseline;
      gap: 6px;
      min-width: 0;
    }
    #coverage-banner .coverage-banner-copy strong {
      flex: 0 0 auto;
      font-size: 12px;
    }
    #coverage-banner .coverage-banner-copy > span {
      margin-top: 0;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      font-size: 12px;
    }
    #coverage-banner .coverage-banner-action {
      min-height: 28px;
      padding: 0 8px;
      font-size: 11px;
    }

    .scan-copy {
      margin-bottom: 10px;
      padding: 4px 2px;
    }
    .scan-copy strong {
      display: block;
      font-size: 15px;
    }
    .scan-copy span {
      display: block;
      margin-top: 3px;
      color: var(--muted);
      font-size: 12px;
    }
    .skeleton {
      position: relative;
      overflow: hidden;
      background: var(--surface);
      border: 1px solid var(--border);
    }
    .skeleton::after {
      content: "";
      position: absolute;
      inset: 0;
      background: linear-gradient(100deg, transparent 20%, rgba(255, 255, 255, 0.055) 48%, transparent 76%);
      transform: translateX(-100%);
      animation: skeleton-sheen 1.35s ease-in-out infinite;
    }
    @keyframes skeleton-sheen { to { transform: translateX(100%); } }
    .run-skeleton {
      display: grid;
      grid-template-columns: 42px 88px minmax(0, 1fr) minmax(110px, auto);
      gap: 12px;
      min-height: 92px;
      margin-bottom: 8px;
      border-radius: 14px;
    }
    .feed-skeleton-grid {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 8px;
    }
    .feed-skeleton-card {
      aspect-ratio: 1;
      border-radius: 14px;
    }
    .summary.is-loading .pill {
      min-width: 76px;
      min-height: 30px;
      color: transparent;
      pointer-events: none;
    }

    .content-arrive {
      animation: content-arrive var(--motion-base) var(--ease-out) both;
    }
    @keyframes content-arrive {
      from { opacity: 0.58; transform: translateY(4px); }
      to { opacity: 1; transform: translateY(0); }
    }
    .view-toolbar {
      display: grid;
      grid-template-columns: minmax(0, 1fr) auto;
      align-items: center;
      gap: 8px;
      min-width: 0;
    }
    .view-updated {
      display: inline-flex;
      align-items: center;
      gap: 5px;
      color: var(--muted);
      font-size: 11px;
      line-height: 1;
      white-space: nowrap;
    }
    .view-updated::before {
      content: "";
      width: 6px;
      height: 6px;
      border-radius: 50%;
      background: var(--accent);
      flex-shrink: 0;
    }
    .view-timing {
      display: flex;
      flex-direction: column;
      align-items: flex-end;
      justify-content: center;
      gap: 2px;
      flex: 0 0 auto;
    }
    .run-countdown {
      color: var(--accent);
      font-size: 10.5px;
      font-weight: 700;
      white-space: nowrap;
    }
    .run-countdown[hidden] { display: none; }
    .view-timing:has(#run-countdown:not([hidden])) .view-updated {
      display: none;
    }

    .feed {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 6px;
    }

    .swipe-hint {
      display: none;
    }
    .swipe-hint[hidden] { display: none; }

    /* —— NEW stamp (0.9.70) — replaces the 0.9.66 "New since last open"
       band: viewer-relative newness is a per-card stamp now, not its own
       list. Solid accent pill so it pops against the photo scrim pills. */
    .card-stamp .new-stamp {
      background: var(--accent);
      color: #08110b;
      letter-spacing: 0.06em;
    }

    /* —— This hour’s top picks —— */
    .run-panel {
      display: flex;
      flex-direction: column;
      gap: 0;
      padding-bottom: 0;
      overscroll-behavior: contain;
    }
    .run-panel[hidden] { display: none !important; }
    .run-hero {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 16px;
      margin: 0 0 12px;
      padding: 0;
      border: 0;
      background: transparent;
    }
    .run-hero h2 {
      margin: 0;
      font-size: 13px;
      font-weight: 700;
      letter-spacing: -0.02em;
    }
    .run-hero .sub {
      margin: 0;
      font-size: 13px;
      color: var(--muted);
      font-weight: 600;
    }
    .run-stats { display: none; }
    .run-overview {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 20px;
      margin-bottom: 10px;
      padding: 11px 13px;
      border: 1px solid rgba(61, 214, 140, 0.22);
      border-radius: 16px;
      background: linear-gradient(135deg, rgba(61, 214, 140, 0.09), rgba(17, 24, 20, 0.78));
    }
    .run-overview-copy { min-width: 0; }
    .run-overview-copy strong {
      display: block;
      color: var(--text);
      font-size: 14px;
      line-height: 1.25;
    }
    .run-overview-copy span,
    .run-overview-value span {
      display: block;
      margin-top: 3px;
      color: var(--muted);
      font-size: 11px;
      line-height: 1.35;
    }
    .run-overview-value {
      flex: 0 0 auto;
      text-align: right;
      /* 0.9.56: hero is a real <button> now (tappable value drill-in) —
         zero its native chrome so it keeps reading as plain text. */
      border: 0;
      background: transparent;
      padding: 0;
      cursor: pointer;
    }
    .run-overview-value strong {
      display: block;
      color: var(--accent);
      font-size: 20px;
      line-height: 1;
      letter-spacing: -0.03em;
    }
    .run-chip {
      color: var(--accent);
      font-weight: 750;
      white-space: nowrap;
    }
    /* Stale-cache shield: old app.js still emitted Why essays and
       adjacent "Just found"+"Nearby" chips into the compact 4-col row. */
    .run-why,
    .run-reasons {
      display: none;
    }
    .hour-value {
      margin-top: 14px;
      padding-top: 12px;
      border-top: 1px solid var(--border);
    }
    .hour-value-head {
      display: flex;
      flex-direction: column;
      gap: 2px;
      margin-bottom: 8px;
      padding: 0 2px;
    }
    .hour-value-head strong {
      font-size: 13px;
      font-weight: 750;
    }
    .hour-value-head span,
    .hour-value-empty {
      color: var(--muted);
      font-size: 11px;
      font-weight: 600;
    }
    .hour-value-empty { margin: 0; }
    .run-list {
      display: grid;
      gap: 10px;
    }
    .run-stop {
      display: grid;
      grid-template-columns: minmax(0, 1fr) auto;
      overflow: hidden;
      touch-action: pan-y;
      border: 1px solid var(--border);
      border-radius: 20px;
      background: linear-gradient(145deg, rgba(20, 27, 36, 0.98), rgba(13, 18, 25, 0.98));
      box-shadow: 0 12px 34px rgba(0, 0, 0, 0.2);
      transition: border-color 0.18s ease, background 0.18s ease, box-shadow 0.18s ease, opacity 0.24s ease, transform 0.24s ease;
    }
    .run-stop.is-top-pick {
      border-color: rgba(61, 214, 140, 0.5);
      background: linear-gradient(145deg, rgba(61, 214, 140, 0.1), rgba(17, 24, 20, 0.98) 44%);
      box-shadow: 0 18px 42px rgba(0, 0, 0, 0.28), 0 0 0 1px rgba(61, 214, 140, 0.04) inset;
    }
    .run-stop.is-saved { border-color: rgba(232, 185, 35, 0.46); }
    .run-stop.is-removing {
      opacity: 0;
      transform: translateX(-16px) scale(0.985);
      pointer-events: none;
    }
    .run-stop-open {
      position: relative;
      display: grid;
      grid-template-columns: 40px 88px minmax(0, 1fr) minmax(128px, auto);
      grid-template-areas: "num thumb body value";
      gap: 12px;
      align-items: center;
      min-width: 0;
      min-height: 88px;
      padding: 8px 14px;
      border: 0;
      background: transparent;
      cursor: pointer;
      text-align: left;
      width: 100%;
      color: inherit;
      font: inherit;
      transition: background 0.16s ease;
    }
    .run-stop-open:hover { background: rgba(24, 36, 29, 0.72); }
    .run-stop-open:active { background: var(--surface-2); }
    .run-stop-open:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: -3px;
    }
    .hour-value-list .run-stop-open {
      grid-template-columns: 88px minmax(0, 1fr) minmax(128px, auto);
      grid-template-areas: "thumb body value";
    }
    .run-stop .num {
      grid-area: num;
      width: 38px;
      height: 38px;
      border-radius: 12px;
      display: grid;
      place-items: center;
      font-weight: 800;
      font-size: 14px;
      background: var(--surface);
      color: var(--accent);
      border: 1px solid var(--border);
    }
    .run-stop .thumb {
      grid-area: thumb;
      width: 88px;
      height: 68px;
      min-width: 88px;
      min-height: 68px;
      max-width: 88px;
      max-height: 68px;
      border-radius: 12px;
      overflow: hidden;
      contain: strict;
      isolation: isolate;
      background: #0a0d0b;
      flex: 0 0 auto;
    }
    .run-stop .thumb img {
      width: 100%;
      height: 100%;
      max-width: 100%;
      max-height: 100%;
      object-fit: cover;
      object-position: center;
      display: block;
      pointer-events: none;
      opacity: 0;
      transition: opacity 160ms ease-out;
    }
    .run-stop .thumb img.img-loaded { opacity: 1; }
    .run-stop .thumb .ph {
      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 8px;
      color: #75897c;
      font-size: 11px;
      font-weight: 700;
    }
    .run-stop .thumb .ph::before {
      content: "";
      width: 34px;
      height: 27px;
      border: 2px solid #566d5d;
      border-radius: 7px;
      background:
        radial-gradient(circle at 72% 28%, #75897c 0 3px, transparent 4px),
        linear-gradient(145deg, transparent 45%, #566d5d 46% 53%, transparent 54%) bottom / 100% 70% no-repeat;
      opacity: 0.7;
    }
    .run-stop .body { grid-area: body; min-width: 0; }
    .run-stop .title {
      margin: 0 0 5px;
      font-size: 17px;
      font-weight: 780;
      line-height: 1.25;
      display: -webkit-box;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
      overflow: hidden;
    }
    .run-stop .meta {
      font-size: 13px;
      color: var(--muted);
      font-weight: 600;
      display: flex;
      flex-wrap: wrap;
      gap: 6px;
    }
    .run-stop .meta > * {
      white-space: nowrap;
    }
    .run-stop .meta .freshness { color: var(--accent); }
    .run-stop .value-block {
      grid-area: value;
      text-align: right;
    }
    .run-stop .value-block strong {
      display: block;
      color: var(--accent);
      font-size: 18px;
      font-weight: 820;
      letter-spacing: -0.02em;
    }
    .run-stop .confidence {
      display: block;
      margin-top: 4px;
      color: var(--muted);
      font-size: 12px;
      font-weight: 650;
    }
    .run-stop .confidence.medium { color: #e1bb5f; }
    .run-stop .confidence.low { color: var(--muted); }
    .run-actions {
      display: flex;
      align-items: center;
      gap: 6px;
      padding: 10px 12px;
      border-left: 1px solid var(--border);
      background: rgba(10, 13, 11, 0.22);
    }
    .run-action {
      min-height: 38px;
      padding: 0 11px;
      border: 1px solid var(--border);
      border-radius: 10px;
      background: var(--surface);
      color: var(--muted);
      font-size: 12px;
      font-weight: 760;
      cursor: pointer;
    }
    .run-action:hover { border-color: #466353; color: var(--text); }
    .run-action.save[aria-pressed="true"] {
      border-color: rgba(232, 185, 35, 0.48);
      background: rgba(232, 185, 35, 0.1);
      color: #f0c94d;
    }
    .run-action.pass:hover {
      border-color: rgba(255, 122, 128, 0.38);
      color: #ffadb1;
    }
    .run-action:disabled { opacity: 0.5; cursor: wait; }
    .run-section-title {
      margin: 18px 2px 8px;
      font-size: 13px;
      font-weight: 800;
      color: var(--muted);
      letter-spacing: 0.02em;
      text-transform: uppercase;
    }
    .run-empty {
      padding: 28px 16px;
      text-align: center;
      border-radius: 16px;
      border: 1px dashed var(--border);
      color: var(--muted);
    }
    .run-empty h3 { margin: 0 0 6px; color: var(--text); font-size: 16px; }
    .run-empty p { margin: 0; font-size: 13px; font-weight: 600; }

    /* ADR 0010: map view. Own surface (see #map-panel in index.html), never
       populated by renderFeed(). Vector-layer colors live in app.js as
       literals mirroring these same --accent/--muted tokens (Leaflet's path
       options take real color values, not CSS custom properties). */
    .map-panel {
      display: flex;
      flex-direction: column;
      gap: 12px;
    }
    .map-panel[hidden] { display: none !important; }
    .map-hint {
      margin: 0;
      padding: 10px 13px;
      border: 1px solid var(--border);
      border-radius: 14px;
      background: var(--surface-2);
      color: var(--muted);
      font-size: 12px;
      font-weight: 600;
      line-height: 1.4;
    }
    .map-canvas {
      height: min(58vh, 520px);
      min-height: 320px;
      border-radius: var(--radius);
      overflow: hidden;
      border: 1px solid var(--border);
      background: var(--surface);
    }
    .map-canvas[hidden] { display: none !important; }
    .map-filter-chips { margin-bottom: 0; }
    .map-filter-chips[hidden] { display: none !important; }
    .map-filter-empty[hidden] { display: none !important; }
    .map-toolbar {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 10px;
    }
    .map-toolbar[hidden] { display: none !important; }
    .map-follow-note {
      color: var(--muted);
      font-size: 12px;
      font-weight: 600;
    }
    .map-empty, .map-offline { margin: 0; }
    .map-empty[hidden], .map-offline[hidden] { display: none !important; }

    /* Wave 3.5 item 3: compact preview card docked under the map. Reuses
       the freshness-ramp class names (age-hot/warm/neon/ice/dim/faded) as
       a modifier on the card root — same classification (freshnessBand()
       in app.js), a parallel color mapping here since .card's own rules
       are scoped to .card, not this component. */
    .map-preview {
      position: relative;
      display: flex;
      gap: 12px;
      padding: 12px 14px;
      border: 1px solid var(--border);
      border-radius: 16px;
      background: linear-gradient(145deg, rgba(20, 27, 36, 0.98), rgba(13, 18, 25, 0.98));
      box-shadow: 0 12px 34px rgba(0, 0, 0, 0.2);
    }
    .map-preview[hidden] { display: none !important; }
    .map-preview-skel {
      padding: 6px 2px;
      color: var(--muted);
      font-size: 13px;
      font-weight: 600;
    }
    .map-preview-close {
      position: absolute;
      top: 6px;
      right: 8px;
      border: 0;
      background: transparent;
      color: var(--muted);
      font-size: 18px;
      line-height: 1;
      cursor: pointer;
      padding: 4px;
    }
    .map-preview-close:hover { color: var(--text); }
    .map-preview-thumb {
      flex: 0 0 auto;
      width: 68px;
      height: 68px;
      border-radius: 12px;
      overflow: hidden;
      background: var(--surface-2);
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .map-preview-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
    .map-preview-thumb .ph { color: var(--muted); font-size: 10px; text-align: center; padding: 4px; }
    .map-preview-body { min-width: 0; flex: 1 1 auto; padding-right: 18px; }
    .map-preview-title {
      margin: 0 0 4px;
      color: var(--text);
      font-size: 14px;
      font-weight: 700;
      line-height: 1.25;
    }
    .map-preview-meta {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 8px;
      font-size: 11px;
      color: var(--muted);
      font-weight: 600;
    }
    .map-preview-value { color: var(--accent); }
    .map-preview.age-hot .map-preview-age { color: #ffb3b4; }
    .map-preview.age-warm .map-preview-age { color: var(--warn); }
    .map-preview.age-neon .map-preview-age { color: var(--accent); }
    .map-preview.age-ice .map-preview-age { color: var(--ice); }
    .map-preview.age-dim .map-preview-age,
    .map-preview.age-faded .map-preview-age { color: #8fa4b6; }
    .map-preview-address {
      margin: 6px 0 0;
      font-size: 11px;
      color: var(--muted);
      line-height: 1.4;
    }
    .map-preview-address strong { color: var(--text); }
    .map-preview-actions {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 12px;
      margin-top: 8px;
    }
    .map-route-check {
      display: inline-flex;
      align-items: center;
      gap: 6px;
      font-size: 12px;
      font-weight: 600;
      color: var(--muted);
      cursor: pointer;
    }
    .map-route-check input { accent-color: var(--accent); width: 15px; height: 15px; }

    /* Leaflet chrome recolored for the neon-dark shell — no new fonts/images,
       classes only (CSP style-src stays 'self', no unsafe-inline). */
    .leaflet-container {
      background: var(--surface);
      font-family: var(--sans);
    }
    /* Standard dark-raster trick, scoped to .leaflet-tile only — markers,
       rings, popups, and the attribution control live in separate panes
       and are untouched. Invert then hue-rotate 180deg restores natural
       hue relationships (water reads dark blue, not inverted-orange);
       brightness/contrast/saturate tuned down so roads and water stay
       legible against the dark shell instead of blowing out to white. */
    .leaflet-tile {
      filter: invert(1) hue-rotate(180deg) brightness(0.92) contrast(0.88) saturate(0.65);
    }
    .leaflet-control-zoom a {
      background: var(--surface-2);
      color: var(--text);
      border-color: var(--border) !important;
    }
    .leaflet-control-zoom a:hover { background: var(--surface); color: var(--accent); }
    .leaflet-control-attribution {
      background: rgba(17, 24, 20, 0.82);
      color: var(--muted);
      font-size: 10px;
    }
    .leaflet-control-attribution a { color: var(--accent); }
    .leaflet-popup-content-wrapper {
      background: var(--surface-2);
      color: var(--text);
      border-radius: 14px;
      box-shadow: var(--shadow);
    }
    .leaflet-popup-tip { background: var(--surface-2); }
    .leaflet-popup-close-button { color: var(--muted) !important; }

    /* Numbered stop pins: a solid filled pin means a confirmed address; a
       dashed-outline pin means a poster-stated corner — visually distinct,
       both carry the visit-order number (ADR 0010 honesty ladder). */
    .map-pin {
      width: 26px;
      height: 26px;
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 12px;
      font-weight: 800;
      box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
    }
    .map-pin-address {
      background: var(--accent);
      color: var(--bg);
      border: 2px solid rgba(255, 255, 255, 0.28);
    }
    .map-pin-corner {
      background: var(--surface-2);
      color: var(--accent);
      border: 2px dashed var(--accent);
    }
    /* Map freshness follow-up: pins wear the same freshness-ramp color
       tokens the feed card ramp uses (.card.age-* above) — a colored ring
       around the pin, address/corner fill underneath stays as-is.
       Undated/pending stops never get one of these classes (see
       freshnessBand()), so they keep the plain neutral pin look — unknown
       timing must never render as stale. */
    .map-pin.age-hot {
      box-shadow: 0 0 0 3px rgba(255, 107, 107, 0.55), 0 6px 16px rgba(0, 0, 0, 0.35);
    }
    .map-pin.age-warm {
      box-shadow: 0 0 0 3px rgba(240, 180, 41, 0.5), 0 6px 16px rgba(0, 0, 0, 0.35);
    }
    .map-pin.age-neon {
      box-shadow: 0 0 0 3px rgba(61, 214, 140, 0.45), 0 6px 16px rgba(0, 0, 0, 0.35);
    }
    .map-pin.age-ice {
      box-shadow: 0 0 0 3px rgba(94, 200, 245, 0.4), 0 6px 16px rgba(0, 0, 0, 0.35);
    }
    .map-pin.age-dim {
      box-shadow: 0 0 0 3px rgba(120, 148, 168, 0.35), 0 6px 16px rgba(0, 0, 0, 0.35);
    }
    .map-pin.age-faded {
      box-shadow: 0 0 0 3px rgba(120, 148, 168, 0.25), 0 6px 16px rgba(0, 0, 0, 0.35);
      filter: saturate(0.35) opacity(0.82);
    }
    /* Dashed-outline area ring: unmistakably not a pin — an approximate
       area, never a fabricated point (ADR 0001/0010). Wave 3.5 item 1: a
       distinct MUTED pill reading "N items" — never a bare number, and
       deliberately not neon-colored like the numbered stop pins, so the
       two number systems can never be mistaken for each other. */
    .map-area-label {
      min-width: 40px;
      padding: 2px 8px;
      border-radius: 999px;
      background: var(--surface-2);
      border: 1px dashed var(--border);
      color: var(--muted);
      font-size: 10px;
      font-weight: 700;
      text-align: center;
      white-space: nowrap;
    }
    .map-area-popup-body {
      display: flex;
      flex-direction: column;
      gap: 6px;
      font-size: 13px;
    }
    .map-area-popup-body strong { color: var(--text); font-size: 12px; }
    .map-area-popup-list {
      display: flex;
      flex-direction: column;
      gap: 2px;
      max-height: 160px;
      overflow-y: auto;
    }
    .map-area-popup-item {
      background: transparent;
      border: 0;
      padding: 4px 0;
      text-align: left;
      color: var(--accent);
      font-size: 13px;
      font-weight: 600;
      cursor: pointer;
    }
    .map-area-popup-item:hover { text-decoration: underline; }
    .map-area-popup-empty, .map-area-popup-more {
      color: var(--muted);
      font-size: 12px;
    }
    /* Map freshness follow-up: a ring whose freshest member posted within
       the last hour gets a hot tint — overrides the SVG path's own
       stroke/fill presentation attributes (CSP style-src 'self': a CSS
       class, never an inline style="" attribute). */
    .map-area-fresh {
      stroke: #ff6b6b !important;
      fill: #ff6b6b !important;
    }

    .chip[data-mode="run"].active {
      border-color: rgba(61, 214, 140, 0.55);
      background: var(--accent-soft);
      color: var(--accent);
    }
    .card-wrap {
      position: relative;
      border-radius: var(--radius);
      overflow: hidden;
      /* pan-y alone fights horizontal swipe on iOS; none while swiping via class */
      touch-action: pan-y;
      /* Photo-in-flow redesign: height is content-driven (photo + info),
         not forced square — the .feed grid's rows are auto by default. */
      -webkit-user-select: none;
      user-select: none;
      transition: opacity 0.35s ease, transform 0.4s cubic-bezier(0.22, 1, 0.36, 1),
        filter 0.35s ease, max-height 0.4s ease, margin 0.35s ease;
    }
    .card-wrap.is-swiping {
      touch-action: none;
      z-index: 3;
    }
    .card-wrap.is-exiting {
      pointer-events: none;
      z-index: 1;
    }
    .card-wrap.is-exiting-pass {
      opacity: 0;
      transform: scale(0.92);
      filter: grayscale(1) brightness(0.7);
    }
    .card-wrap .swipe-bg {
      position: absolute;
      inset: 0;
      /* Labels sit on the side that is revealed as the card slides away */
      z-index: 0;
      border-radius: var(--radius);
      opacity: 0;
      transition: opacity 0.18s ease, background 0.18s ease;
      pointer-events: none;
    }
    .card-wrap.is-swiping .swipe-bg,
    .card-wrap.swiping-pass .swipe-bg,
    .card-wrap.swiping-watch .swipe-bg {
      opacity: 1;
    }
    .card-wrap .swipe-bg .pass-label,
    .card-wrap .swipe-bg .watch-label {
      position: absolute;
      top: 50%;
      transform: translateY(-50%) scale(0.92);
      font-size: 13px;
      font-weight: 800;
      letter-spacing: 0.06em;
      text-transform: uppercase;
      opacity: 0.25;
      transition: opacity 0.16s ease, transform 0.16s ease;
    }
    /* Swipe left (card moves left) → reveal right edge = Pass */
    .card-wrap .swipe-bg .pass-label {
      right: 12px;
      color: #c9cfc9;
      text-shadow: 0 1px 8px rgba(0, 0, 0, 0.45);
    }
    /* Swipe right (card moves right) → reveal left edge = Watch / Unwatch */
    .card-wrap .swipe-bg .watch-label {
      left: 12px;
      color: #f0c14b;
      text-shadow: 0 1px 10px rgba(240, 193, 75, 0.35);
    }
    .card-wrap.is-watched-card .swipe-bg .watch-label {
      color: #f5d76e;
    }
    .card-wrap.is-watched-card .swipe-bg .watch-label::after {
      content: none;
    }
    .card-wrap.swiping-pass .swipe-bg {
      background: linear-gradient(90deg, transparent 20%, rgba(120, 128, 140, 0.38));
    }
    .card-wrap.swiping-watch .swipe-bg {
      background: linear-gradient(270deg, transparent 20%, rgba(240, 193, 75, 0.28));
    }
    .card-wrap.swiping-pass .pass-label {
      opacity: 1;
      transform: translateY(-50%) scale(1.05);
    }
    .card-wrap.swiping-watch .watch-label {
      opacity: 1;
      transform: translateY(-50%) scale(1.05);
    }

    /* Photo-first gallery tile: photo up top, info in normal flow below —
       height is content-driven, not a full-bleed photo overlay. */
    .card {
      position: relative;
      z-index: 1;
      /* Fills the .card-wrap grid track (grid items stretch by default) so
         cards with a 1-line title and cards with a 2-line title still end
         flush at the same row bottom — see .card-info's flex:1 below. */
      height: 100%;
      display: flex;
      flex-direction: column;
      padding: 0;
      border-radius: var(--radius);
      background: #0a0d0b;
      border: 2px solid var(--border-interactive);
      box-shadow: none;
      overflow: hidden;
      transition:
        border-color 0.28s cubic-bezier(0.22, 1, 0.36, 1),
        box-shadow 0.28s cubic-bezier(0.22, 1, 0.36, 1),
        filter 0.28s ease,
        opacity 0.28s ease,
        background 0.28s ease;
      -webkit-user-select: none;
      user-select: none;
      -webkit-touch-callout: none;
      touch-action: pan-y;
      will-change: transform, opacity, filter;
      transform: translate3d(0, 0, 0);
      backface-visibility: hidden;
      -webkit-backface-visibility: hidden;
    }
    .card:focus-visible {
      outline: 3px solid rgba(61, 214, 140, 0.78);
      outline-offset: -3px;
      border-color: var(--accent);
    }
    .card.is-dragging {
      transition: none !important;
      touch-action: none;
      box-shadow: 0 12px 28px rgba(0, 0, 0, 0.4);
    }
    .card.is-settling {
      transition:
        transform 0.42s cubic-bezier(0.22, 1.2, 0.36, 1),
        opacity 0.32s ease,
        filter 0.32s ease,
        border-color 0.32s ease,
        box-shadow 0.42s cubic-bezier(0.22, 1, 0.36, 1);
    }
    .card.is-committing {
      transition:
        transform 0.3s cubic-bezier(0.2, 0.85, 0.25, 1),
        opacity 0.3s ease,
        filter 0.3s ease,
        border-color 0.3s ease,
        box-shadow 0.3s ease;
    }
    /* Wave 3 item 5: the freshness ramp — cards wear their verified-source
       age (never discovery age, invariant 13; a pending/unknown listed
       time carries none of these classes, invariant 15). Border tint plus
       a slim inset left-edge line so the band reads even at a glance;
       watched/passed keep their own treatment and take priority. */
    .card.age-hot:not(.watched):not(.passed) {
      border-color: rgba(255, 107, 107, 0.5);
    }
    .card.age-warm:not(.watched):not(.passed) {
      border-color: rgba(240, 180, 41, 0.45);
    }
    .card.age-neon:not(.watched):not(.passed) {
      border-color: rgba(61, 214, 140, 0.35);
    }
    .card.age-ice:not(.watched):not(.passed) {
      border-color: rgba(94, 200, 245, 0.32);
    }
    .card.age-dim:not(.watched):not(.passed) {
      border-color: rgba(120, 148, 168, 0.28);
    }
    .card.age-faded:not(.watched):not(.passed) {
      border-color: rgba(120, 148, 168, 0.2);
      filter: saturate(0.35) opacity(0.82);
    }
    /* Watch = gold border */
    .card.watched {
      border-color: #e8b923;
      box-shadow:
        0 0 0 1px rgba(232, 185, 35, 0.45),
        0 0 18px rgba(240, 193, 75, 0.28),
        inset 0 0 0 1px rgba(255, 220, 120, 0.18);
    }
    .card.watched .watch-stamp {
      color: #f0c14b;
      pointer-events: auto;
      cursor: pointer;
      border: 1px solid rgba(240, 193, 75, 0.45);
      background: rgba(40, 32, 8, 0.85);
    }
    .card .watch-stamp.btn-unwatch {
      pointer-events: auto;
      cursor: pointer;
      z-index: 5;
      position: relative;
      justify-content: center;
      min-width: 24px;
      min-height: 24px;
      /* .card-stamp is a flex row that would otherwise stretch every child to
         the tallest one, growing the decorative NEW pill alongside the star. */
      align-self: center;
    }
    /* 2.5.8 wants 24x24; the control is sized to that above. It deliberately
       gets NO enlarged ::after overlay: the star sits on top of .card-open and
       the swipe surface, so a 44pt invisible target stole taps meant to open
       the card and blocked swipe-to-remove near the corner. The painted 24px
       control clears the success criterion; a bigger hit area here costs two
       primary gestures, which is the worse trade. */
    /* Pass = grayed out */
    .card.passed {
      border-color: rgba(120, 128, 140, 0.45);
      filter: grayscale(0.95) brightness(0.62);
      opacity: 0.55;
      box-shadow: none;
    }
    .card.passed .card-info,
    .card.passed .card-stamp {
      opacity: 0.75;
    }
    /* Stale save (0.9.53, item 4b): a watched row whose listing has gone
       past normal retention still renders — grayed with an honest age
       stamp ("· likely gone") — instead of silently vanishing from Saved.
       Still fully tappable; detail open keeps working. */
    .card.stale-saved {
      filter: grayscale(0.7) brightness(0.72);
      opacity: 0.7;
    }
    .card.watched.stale-saved {
      border-color: rgba(232, 185, 35, 0.24);
      box-shadow: none;
    }
    .card.stale-saved .card-info .age-stamp { color: var(--muted); }

    .card-photo {
      position: relative;
      width: 100%;
      aspect-ratio: 4 / 3;
      flex-shrink: 0;
      border-radius: var(--radius) var(--radius) 0 0;
      overflow: hidden;
      background: #0a0d0b;
      border: 0;
      padding: 0;
      pointer-events: none;
    }
    .card-photo img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
      background: #0a0d0b;
      opacity: 0;
      transition: opacity 160ms ease-out;
    }
    .card-photo img.img-loaded { opacity: 1; }
    .card-photo .ph {
      width: 100%;
      height: 100%;
      display: grid;
      place-items: center;
      color: #516657;
      font-size: 12px;
      font-weight: 600;
      background: var(--surface-2);
    }

    /* Info block: normal flow, below the photo, on solid --surface —
       replaces the old absolute gradient-scrim overlay. */
    .card-info {
      /* Grows to fill whatever height .card is stretched to (see .card
         height:100% above), so short 1-line titles don't leave the row's
         other cards looking taller. */
      flex: 1;
      padding: 12px 14px;
      background: var(--surface);
      border-radius: 0 0 var(--radius) var(--radius);
      display: flex;
      flex-direction: column;
      gap: 6px;
      min-width: 0;
    }
    .card-info .title {
      font-size: 15px;
      font-weight: 600;
      color: var(--text);
      text-shadow: none;
      line-height: 1.3;
    }

    .card-stamp {
      position: absolute;
      top: 6px;
      left: 6px;
      right: 6px;
      z-index: 3;
      display: flex;
      /* Only the NEW pill (left) and the saved star (right) live on the
         photo now — everything else moved into .card-info below. */
      gap: 4px;
      pointer-events: none;
    }
    .card-stamp span {
      display: inline-flex;
      align-items: center;
      min-height: 22px;
      padding: 2px 7px;
      border-radius: 8px;
      background: rgba(8, 11, 9, 0.72);
      backdrop-filter: blur(8px);
      -webkit-backdrop-filter: blur(8px);
      font-family: var(--mono);
      font-size: 11px;
      font-weight: 750;
      color: #eef5ef;
      white-space: nowrap;
    }
    .card-stamp .watch-stamp {
      margin-left: auto;
      color: var(--accent);
      border: 1px solid rgba(61, 214, 140, 0.35);
    }

    /* Directional drag stamps (0.9.53) — styled like .watch-stamp, opacity
       and scale driven from JS in proportion to drag progress. */
    .swipe-drag-stamp {
      position: absolute;
      top: 14px;
      z-index: 4;
      padding: 4px 10px;
      border-radius: 9px;
      font-family: var(--mono);
      font-size: 13px;
      font-weight: 800;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      pointer-events: none;
      opacity: 0;
      backdrop-filter: blur(6px);
      -webkit-backdrop-filter: blur(6px);
    }
    .swipe-drag-stamp-save {
      right: 12px;
      color: #f0c14b;
      border: 2px solid rgba(240, 193, 75, 0.85);
      background: rgba(40, 32, 8, 0.6);
      transform: rotate(10deg) scale(0.7);
    }
    .swipe-drag-stamp-pass {
      left: 12px;
      color: #c9d0d6;
      border: 2px solid rgba(160, 168, 178, 0.85);
      background: rgba(20, 22, 26, 0.6);
      transform: rotate(-10deg) scale(0.7);
    }

    .src { display: none; }
    .age { display: none; }

    .title {
      margin: 0;
      font-size: 12px;
      font-weight: 700;
      letter-spacing: -0.01em;
      line-height: 1.2;
      display: -webkit-box;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
      overflow: hidden;
      color: #fff;
      text-shadow: 0 1px 2px rgba(0,0,0,0.5);
    }

    /* Row 2: price/value/savings first, then age + drive time as quiet
       muted text — not pills — separated by thin middots. Each of
       "price · listed Xm" and "🚗 ~N min" is one .meta-group so a wrap
       between them never strands a trailing dot; the flex column-gap is
       the only separator between the two groups. */
    .meta-row {
      display: flex;
      flex-wrap: wrap;
      gap: 4px 10px;
      color: var(--muted);
      font-size: 13px;
      align-items: center;
    }
    .meta-row .meta-group {
      display: inline-flex;
      align-items: center;
      gap: 4px;
      white-space: nowrap;
    }
    .meta-row .meta-dot { color: var(--muted); opacity: 0.6; }
    .meta-row .age-stamp,
    .meta-row .mi-stamp {
      font-size: 13px;
      font-weight: 600;
      color: var(--muted);
      white-space: nowrap;
    }

    /* Row 3: secondary quiet pills — only rendered when a tag is present.
       margin-top: auto (its parent .card-info is a column flex that fills
       .card's stretched height) pins this row to the card's bottom edge so
       1- vs 2-line titles never throw off row alignment in the grid. */
    .tag-row {
      display: flex;
      flex-wrap: wrap;
      gap: 4px 6px;
      align-items: center;
      margin-top: auto;
    }
    .tag-row:empty { display: none; }

    .price-tag {
      font-family: var(--mono);
      font-weight: 700;
      color: var(--warn);
      font-size: 11px;
    }
    .value-tag {
      font-family: var(--mono);
      font-weight: 700;
      color: var(--accent);
      font-size: 11px;
    }
    /* Untruncated ("High/Medium/Low comp consistency" — never "confidence",
       0.9.15 audit invariant). "Medium comp consistency" doesn't fit a
       ~144px two-column phone card's content width on one line, so this
       pill wraps to two centered lines instead of truncating; a smaller
       radius keeps a wrapped pill reading as a soft rounded rect instead
       of a stretched oval. */
    .confidence-tag {
      display: inline-flex;
      align-items: center;
      max-width: 100%;
      padding: 2px 7px;
      border-radius: 10px;
      background: var(--surface-2);
      border: 1px solid var(--border);
      font-size: 10px;
      font-weight: 700;
      line-height: 1.25;
      text-align: center;
      white-space: normal;
      color: var(--muted);
    }
    .confidence-tag.high { color: var(--accent); }
    .confidence-tag.medium { color: #e1bb5f; }
    .safety-tag {
      display: inline-flex;
      align-items: center;
      padding: 2px 7px;
      border-radius: 999px;
      background: var(--surface-2);
      border: 1px solid var(--border);
      font-size: 10px;
      font-weight: 700;
      color: var(--warn);
    }
    .savings-tag {
      font-family: var(--mono);
      font-weight: 700;
      color: var(--accent);
      font-size: 11px;
    }
    /* 0.9.56: flip-card demand tag — only ever painted from a demand read
       already cached client-side (Wave 3b item 3), never a per-card fetch. */
    .demand-tag {
      display: inline-flex;
      align-items: center;
      padding: 2px 7px;
      border-radius: 999px;
      background: var(--surface-2);
      border: 1px solid var(--border);
      font-family: var(--mono);
      font-weight: 700;
      color: var(--muted);
      font-size: 10px;
    }
    /* Evidence grade (Wave 4 trust fix): grade A is the implicit product
       default and stays unlabeled; B/C ride next to the savings tag so a
       flip's trust level is never hidden. */
    .grade-tag {
      font-weight: 720;
      font-size: 10px;
      color: var(--muted);
      border: 1px solid var(--border);
      border-radius: 999px;
      padding: 1px 6px;
      white-space: nowrap;
    }
    .grade-tag.grade-b { color: var(--muted); }
    .grade-tag.grade-c { color: var(--warn); border-color: rgba(224, 168, 90, 0.5); }
    /* Heathrow 2026-08-23 test-drive: a confirmed poster-stated address is
       the most run-to-able signal on the card. Card redesign demotes it to
       the row-3 secondary tier alongside the other quiet pills — text only,
       never the address itself (ADR 0008). */
    .chip-confirmed-address {
      display: inline-flex;
      align-items: center;
      padding: 2px 8px;
      border-radius: 999px;
      background: rgba(61, 214, 140, 0.08);
      border: 1px solid rgba(61, 214, 140, 0.28);
      color: var(--muted);
      font-weight: 650;
      font-size: 10px;
      white-space: nowrap;
    }

    .card-quick-actions {
      position: absolute;
      left: 8px;
      right: 8px;
      bottom: 8px;
      z-index: 5;
      display: flex;
      gap: 6px;
      opacity: 0;
      transform: translateY(6px);
      pointer-events: none;
      transition: opacity 0.16s ease, transform 0.16s ease;
    }
    .card-quick-actions button {
      flex: 1;
      min-height: 34px;
      padding: 0 8px;
      border-radius: 9px;
      border: 1px solid rgba(255, 255, 255, 0.16);
      background: rgba(9, 13, 10, 0.92);
      color: var(--text);
      backdrop-filter: blur(10px);
      -webkit-backdrop-filter: blur(10px);
      font-size: 11px;
      font-weight: 760;
      cursor: pointer;
    }
    .card-quick-actions button:first-child {
      border-color: rgba(61, 214, 140, 0.4);
      color: var(--accent);
    }
    @media (hover: hover), (pointer: fine) {
      .card-wrap:hover .card-quick-actions,
      .card-wrap:focus-within .card-quick-actions {
        opacity: 1;
        transform: translateY(0);
        pointer-events: auto;
      }
    }
    /* 2.4.7 safety net: these buttons are meant to be untabbable, but if one
       ever does take keyboard focus it must be visible and clickable instead
       of an invisible, unreachable control. Not gated on hover, so it also
       covers touch devices with an attached keyboard. */
    .card-quick-actions:has(button:focus-visible) {
      opacity: 1;
      transform: translateY(0);
      pointer-events: auto;
    }

    .empty {
      text-align: center;
      padding: 56px 20px;
      color: var(--muted);
    }
    .empty h2 {
      margin: 0 0 8px;
      color: var(--text);
      font-size: 20px;
      letter-spacing: -0.02em;
    }
    .empty p { margin: 0 0 18px; font-size: 15px; }

    /* —— Filter sheet —— */
    .sheet-backdrop {
      position: fixed;
      inset: 0;
      z-index: 50;
      background: rgba(3, 8, 5, 0.62);
      opacity: 0;
      pointer-events: none;
      transition: opacity 0.2s ease;
    }
    .sheet-backdrop.open {
      opacity: 1;
      pointer-events: auto;
    }

    .sheet {
      position: fixed;
      left: 0;
      right: 0;
      bottom: 0;
      z-index: 51;
      max-height: min(88vh, 720px);
      overflow: auto;
      background: #0f1511;
      border-radius: 22px 22px 0 0;
      border: 1px solid var(--border);
      border-bottom: none;
      box-shadow: 0 -20px 50px rgba(0,0,0,0.45);
      padding: 10px 18px calc(20px + var(--safe-b));
      transform: translateY(110%);
      transition: transform 0.28s cubic-bezier(0.2, 0.8, 0.2, 1);
    }
    .sheet.open { transform: translateY(0); }

    .sheet-handle {
      width: 40px;
      height: 4px;
      border-radius: 999px;
      background: #38493d;
      margin: 4px auto 14px;
    }

    .sheet h2 {
      margin: 0 0 14px;
      font-size: 18px;
      letter-spacing: -0.02em;
    }
    .sheet-titlebar {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: 16px;
      margin-bottom: 18px;
    }
    .sheet-titlebar h2 { margin: 0; }
    .sheet-titlebar h2:focus { outline: none; }
    .sheet-result {
      margin: 4px 0 0;
      color: var(--accent);
      font-size: 12px;
      font-weight: 650;
    }
    .sheet-reset,
    .export-link {
      min-height: 36px;
      padding: 0;
      border: 0;
      background: transparent;
      color: var(--muted);
      font-size: 13px;
      font-weight: 650;
      cursor: pointer;
    }
    .settings-tabs {
      display: grid;
      grid-template-columns: repeat(4, minmax(0, 1fr));
      gap: 4px;
      margin: -2px 0 18px;
      padding: 4px;
      border: 1px solid var(--border);
      border-radius: 14px;
      background: rgba(10, 13, 11, 0.52);
    }
    .settings-tab {
      min-height: 40px;
      padding: 6px 7px;
      border: 0;
      border-radius: 10px;
      background: transparent;
      color: var(--muted);
      font-size: 12px;
      font-weight: 740;
      cursor: pointer;
      transition: background 0.18s ease-out, color 0.18s ease-out, box-shadow 0.18s ease-out;
    }
    .settings-tab.active {
      background: var(--surface-2);
      color: var(--text);
      box-shadow: inset 0 0 0 1px rgba(61, 214, 140, 0.22);
    }
    .settings-page { display: none; }
    .settings-page.active {
      display: block;
      animation: settings-page-in 180ms var(--ease-out) both;
    }
    @keyframes settings-page-in {
      from { opacity: 0.55; transform: translateY(3px); }
      to { opacity: 1; transform: translateY(0); }
    }
    .settings-section-heading {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      gap: 14px;
      margin-bottom: 16px;
    }
    .settings-section-heading h3 {
      margin: 0;
      color: var(--text);
      font-size: 16px;
      letter-spacing: -0.02em;
    }
    .settings-section-heading p {
      margin: 4px 0 0;
      color: var(--muted);
      font-size: 12px;
      line-height: 1.4;
    }
    .settings-section-heading .sheet-reset { flex: 0 0 auto; }
    .settings-group {
      margin-bottom: 14px;
      padding: 14px;
      border: 1px solid var(--border);
      border-radius: 16px;
      background: rgba(17, 24, 20, 0.62);
    }
    .settings-group > .field:last-child,
    .settings-group > .toggle:last-child { margin-bottom: 0; }
    .settings-group-title {
      margin: 0 0 10px;
      color: var(--muted);
      font-size: 11px;
      font-weight: 760;
      letter-spacing: 0.06em;
      text-transform: uppercase;
    }
    .source-overview {
      margin-bottom: 12px;
      padding: 14px;
      border: 1px solid rgba(61, 214, 140, 0.24);
      border-radius: 16px;
      background: linear-gradient(135deg, rgba(61, 214, 140, 0.08), rgba(17, 24, 20, 0.7));
    }
    .source-overview strong {
      display: block;
      font-size: 14px;
    }
    .source-overview p {
      margin: 5px 0 0;
      color: var(--muted);
      font-size: 12px;
      line-height: 1.4;
    }
    .source-status-list {
      display: grid;
      gap: 8px;
    }
    .source-status-card {
      display: grid;
      grid-template-columns: auto minmax(0, 1fr) auto;
      align-items: center;
      gap: 10px;
      min-height: 58px;
      padding: 10px 12px;
      border: 1px solid var(--border);
      border-radius: 14px;
      background: var(--surface);
    }
    .source-status-dot {
      width: 9px;
      height: 9px;
      border-radius: 50%;
      background: var(--accent);
      box-shadow: 0 0 0 4px rgba(61, 214, 140, 0.08);
    }
    .source-status-card.paused .source-status-dot {
      background: var(--warn);
      box-shadow: 0 0 0 4px rgba(240, 180, 41, 0.08);
    }
    .source-status-card.checking .source-status-dot {
      background: #68806f;
      box-shadow: none;
    }
    .source-status-card.disabled {
      opacity: 0.72;
    }
    .source-status-card.disabled .source-status-dot {
      background: var(--muted);
      box-shadow: none;
    }
    .source-status-copy { min-width: 0; }
    .source-status-copy strong,
    .source-status-copy span { display: block; }
    .source-status-copy strong { font-size: 13px; }
    .source-status-copy span {
      margin-top: 2px;
      color: var(--muted);
      font-size: 11px;
      line-height: 1.35;
    }
    .source-status-label {
      color: var(--accent);
      font-size: 11px;
      font-weight: 760;
    }
    .source-status-card.paused .source-status-label { color: var(--warn); }
    .source-status-card.checking .source-status-label { color: var(--muted); }
    .source-status-card.disabled .source-status-label { color: var(--muted); }
    .app-settings-card {
      display: flex;
      align-items: center;
      gap: 12px;
      margin-bottom: 14px;
      padding: 14px;
      border: 1px solid var(--border);
      border-radius: 16px;
      background: var(--surface);
    }
    .app-settings-card img {
      width: 48px;
      height: 48px;
      border-radius: 13px;
      border: 1px solid var(--border);
    }
    .app-settings-card strong,
    .app-settings-card span { display: block; }
    .app-settings-card strong { font-size: 15px; }
    .app-settings-card span {
      margin-top: 3px;
      color: var(--muted);
      font-size: 12px;
    }
    .settings-row {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 14px;
      min-height: 58px;
      padding: 10px 0;
      border-bottom: 1px solid var(--border);
    }
    .settings-row:last-child { border-bottom: 0; }
    .settings-row strong,
    .settings-row span { display: block; }
    .settings-row strong { font-size: 13px; }
    .settings-row span {
      margin-top: 2px;
      color: var(--muted);
      font-size: 11px;
      line-height: 1.35;
    }
    .settings-row-value {
      flex: 0 0 auto;
      color: var(--accent);
      font-size: 11px;
      font-weight: 760;
      text-align: right;
    }
    .settings-secondary {
      width: 100%;
      min-height: 44px;
      margin-top: 10px;
      border: 1px solid var(--border);
      border-radius: 12px;
      background: var(--surface-2);
      color: var(--text);
      font-weight: 720;
      cursor: pointer;
    }
    .location-fields {
      display: grid;
      grid-template-columns: minmax(120px, 0.7fr) minmax(220px, 1.3fr);
      gap: 12px;
    }

    .field {
      margin-bottom: 14px;
    }
    .field label {
      display: block;
      margin-bottom: 6px;
      color: var(--muted);
      font-size: 12px;
      font-weight: 650;
      text-transform: uppercase;
      letter-spacing: 0.04em;
    }
    .field input {
      width: 100%;
      min-height: 46px;
      padding: 10px 14px;
      border-radius: 12px;
      border: 1px solid var(--border);
      background: var(--surface);
    }

    .toggles {
      display: grid;
      gap: 8px;
      margin-bottom: 14px;
    }
    .toggle {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 12px;
      min-height: 48px;
      padding: 10px 14px;
      border-radius: 14px;
      border: 1px solid var(--border-interactive);
      background: var(--surface);
      cursor: pointer;
    }
    .toggle span { font-size: 15px; font-weight: 600; }
    .toggle input {
      width: 20px;
      height: 20px;
      accent-color: var(--accent);
    }
    /* 0.9.60: iOS-style switch for the master "Alerts" row — CSS only, the
       underlying checkbox input keeps its id and change handler. */
    .toggle.switch-row input {
      appearance: none;
      -webkit-appearance: none;
      position: relative;
      width: 46px;
      height: 28px;
      border-radius: 999px;
      /* Deliberately NOT --border-interactive: that token is in the accent's
         green family, which made the off state read as a dim on. */
      background: #3a4a42;
      transition: background var(--motion-fast) ease;
    }
    .toggle.switch-row input::after {
      content: "";
      position: absolute;
      top: 2px;
      left: 2px;
      width: 24px;
      height: 24px;
      border-radius: 50%;
      background: #fff;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.32);
      transition: transform var(--motion-fast) ease;
    }
    .toggle.switch-row input:checked {
      background: var(--accent);
    }
    .toggle.switch-row input:checked::after {
      transform: translateX(18px);
    }
    .push-row {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 12px;
    }
    .push-row label {
      margin-bottom: 0;
    }
    .push-row button {
      flex: 0 0 auto;
      min-height: 40px;
      padding: 0 16px;
      border-radius: 12px;
      border: 1px solid var(--accent);
      background: var(--accent);
      color: #062416;
      font-weight: 720;
      cursor: pointer;
    }
    .hint.hint-warn {
      color: var(--warn);
    }

    .chips {
      display: flex;
      flex-wrap: nowrap;
      gap: 6px;
      margin-bottom: 0;
      overflow-x: auto;
      -webkit-overflow-scrolling: touch;
      scrollbar-width: none;
      padding-bottom: 0;
    }
    .chips::-webkit-scrollbar { display: none; }
    #sort-chips {
      flex: 1 1 auto;
      width: auto;
      min-width: 0;
      max-width: 100%;
      gap: 0;
      margin-bottom: 0;
      border: 1px solid var(--border);
      border-radius: 10px;
      overflow: auto;
      padding: 0;
    }
    #sort-chips .chip {
      min-height: 32px;
      padding: 5px 12px;
      border: 0;
      border-right: 1px solid var(--border);
      border-radius: 0;
      background: transparent;
      font-size: 12px;
    }
    #sort-chips .chip:last-child { border-right: 0; }
    #sort-chips .chip:focus,
    #sort-chips .chip:focus-visible {
      outline: none;
    }
    .chip {
      flex: 0 0 auto;
      min-height: 34px;
      padding: 6px 12px;
      border-radius: 999px;
      border: 1px solid var(--border);
      background: var(--surface);
      color: var(--muted);
      font-size: 12px;
      font-weight: 700;
      cursor: pointer;
      white-space: nowrap;
      transition: background 0.15s var(--ease-out), color 0.15s ease;
    }
    /* Stable selected ring. Inset only — an outer glow clips inside
       overflow-x: auto and reads as the ring “turning off” on hover. */
    .chip.active {
      background: var(--accent-soft);
      border-color: rgba(61, 214, 140, 0.75);
      color: var(--accent);
      box-shadow: inset 0 0 0 1px rgba(61, 214, 140, 0.55);
    }
    .chip.active:hover {
      border-color: rgba(61, 214, 140, 0.75);
      color: var(--accent);
    }
    #source-chips { flex-wrap: wrap; }
    .chip.source-limited:not(.active) {
      opacity: 0.62;
      border-style: dashed;
    }
    .chip.alert-kw {
      background: var(--accent-soft);
      border-color: rgba(61, 214, 140, 0.45);
      color: var(--accent);
      gap: 6px;
      display: inline-flex;
      align-items: center;
    }
    .chip.alert-kw .x {
      opacity: 0.7;
      font-weight: 800;
      margin-left: 2px;
    }
    .hint {
      font-size: 13px;
      line-height: 1.4;
      color: var(--muted);
      margin: 0;
    }
    .hint-inline {
      font-size: 12px;
      font-weight: 550;
      color: var(--muted);
    }
    .alerts-block {
      margin-top: 4px;
    }
    .alerts-block input[type="text"] {
      width: 100%;
      min-height: 44px;
      border-radius: 12px;
      border: 1px solid var(--border);
      background: var(--surface);
      color: inherit;
      padding: 0 12px;
      font-size: 15px;
    }

    .sheet-actions {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 10px;
    }
    .sheet-actions button {
      min-height: 48px;
      border-radius: 14px;
      border: 1px solid var(--border);
      background: var(--surface);
      font-weight: 700;
      cursor: pointer;
    }
    .sheet-actions button.primary {
      background: var(--accent);
      border-color: var(--accent);
      color: #062416;
    }
    .freshness-segments {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      overflow: hidden;
      border: 1px solid var(--border);
      border-radius: 12px;
    }
    /* 0.9.60: #alert-mode-segments reuses .freshness-segments but only has
       2 modes (My words only / Every find) — the shared 3-column grid left
       a ghost third cell. */
    #alert-mode-segments {
      grid-template-columns: repeat(2, 1fr);
    }
    .freshness-segments button,
    .freshness-segments label {
      position: relative;
      min-height: 42px;
      display: grid;
      place-items: center;
      margin: 0;
      border: 0;
      border-right: 1px solid var(--border);
      background: transparent;
      color: var(--muted);
      font-size: 13px;
      font-weight: 700;
      text-transform: none;
      letter-spacing: 0;
      cursor: pointer;
    }
    .freshness-segments label:last-child { border-right: 0; }
    .freshness-segments input {
      position: absolute;
      width: 1px;
      height: 1px;
      opacity: 0;
      pointer-events: none;
    }
    .freshness-segments button.active,
    .freshness-segments label:has(input:checked) {
      color: var(--accent);
      background: var(--accent-soft);
    }
    .source-health {
      display: flex;
      align-items: center;
      gap: 7px;
      margin: 2px 0 0;
      color: var(--muted);
      font-size: 12px;
    }
    .source-health > span {
      width: 7px;
      height: 7px;
      border-radius: 50%;
      background: var(--accent);
    }
    .source-health.warn { color: var(--warn); }
    .source-health.warn > span { background: var(--warn); }
    .filter-disclosure {
      border-top: 1px solid var(--border);
    }
    .filter-disclosure > summary {
      min-height: 62px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 12px;
      list-style: none;
      cursor: pointer;
    }
    .filter-disclosure > summary::-webkit-details-marker { display: none; }
    .filter-disclosure > summary strong,
    .filter-disclosure > summary small { display: block; }
    .filter-disclosure > summary strong { font-size: 14px; }
    .filter-disclosure > summary small {
      margin-top: 2px;
      color: var(--muted);
      font-size: 12px;
      font-weight: 500;
    }
    .filter-disclosure[open] > summary > span:last-child { transform: rotate(90deg); }
    .disclosure-body {
      display: grid;
      gap: 10px;
      padding: 0 0 16px;
    }
    .disclosure-body .field { margin: 0; }
    .disclosure-body.toggles { margin: 0; }
    .compact-input-row {
      display: grid;
      grid-template-columns: 1fr auto;
      gap: 8px;
      margin: 0;
    }
    .sheet-footer[hidden] { display: none; }
    .sheet-footer {
      position: sticky;
      bottom: calc(-20px - var(--safe-b));
      display: grid;
      grid-template-columns: minmax(0, 1fr) minmax(150px, 1fr);
      align-items: center;
      gap: 14px;
      margin: 4px -2px 0;
      padding: 14px 2px calc(20px + var(--safe-b));
      border-top: 1px solid var(--border);
      background: #0f1511;
    }
    .sheet-footer .primary {
      min-height: 48px;
      border: 1px solid var(--accent);
      border-radius: 13px;
      background: var(--accent);
      color: #062416;
      font-weight: 760;
      cursor: pointer;
    }
    .settings-save-note {
      color: var(--muted);
      font-size: 11px;
      line-height: 1.35;
    }

    /* —— Full-screen listing detail card —— */
    .detail-viewer {
      width: 100vw;
      max-width: 100vw;
      height: 100dvh;
      max-height: 100dvh;
      margin: 0;
      padding: 0;
      border: 0;
      border-radius: 0;
      background: var(--bg);
      color: var(--text);
      overflow: hidden;
    }
    /* --dismiss-opacity: driven by the swipe-down drag handler (0.9.53) —
       the backdrop dims out as the sheet is dragged toward dismissal. */
    .detail-viewer::backdrop { background: #050706; opacity: var(--dismiss-opacity, 1); }
    .detail-viewer[open]::backdrop { animation: detail-backdrop-in var(--motion-base) ease both; }
    .detail-shell {
      position: relative;
      height: 100%;
      display: flex;
      flex-direction: column;
      min-height: 0;
    }
    .detail-viewer[open] .detail-shell {
      animation: detail-enter 280ms var(--ease-out) both;
    }
    .detail-viewer.closing .detail-shell {
      animation: detail-exit var(--motion-fast) ease both;
    }
    .detail-viewer.closing::backdrop {
      animation: detail-backdrop-out var(--motion-fast) ease both;
    }
    @keyframes detail-enter {
      from { opacity: 0; transform: translateY(14px) scale(0.995); }
      to { opacity: 1; transform: translateY(0) scale(1); }
    }
    @keyframes detail-exit {
      from { opacity: 1; transform: translateY(0) scale(1); }
      to { opacity: 0; transform: translateY(10px) scale(0.995); }
    }
    @keyframes detail-backdrop-in { from { opacity: 0; } to { opacity: 1; } }
    @keyframes detail-backdrop-out { from { opacity: 1; } to { opacity: 0; } }
    .detail-top {
      flex-shrink: 0;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 10px;
      padding: calc(4px + var(--safe-t)) 10px 4px;
      padding-left: calc(10px + var(--safe-l));
      padding-right: calc(10px + var(--safe-r));
      border-bottom: 1px solid var(--border);
      background: rgba(10, 13, 11, 0.94);
      backdrop-filter: blur(14px);
    }
    .detail-top h2 {
      margin: 0;
      font-size: 11px;
      font-weight: 700;
      letter-spacing: 0.04em;
      text-transform: uppercase;
      color: var(--muted);
    }
    .detail-close {
      min-width: 0;
      min-height: 26px;
      padding: 0 8px;
      border-radius: 7px;
      border: 1px solid var(--border);
      background: var(--surface);
      font-size: 11px;
      font-weight: 650;
      cursor: pointer;
    }
    /* Photo sheet only: the header floats over the photo on a scrim so the
       image starts at the very top edge — the value drill-in keeps the
       normal solid header row. */
    #photo-viewer .detail-top {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      z-index: 4;
      border-bottom: 0;
      background: linear-gradient(to bottom, rgba(5, 7, 6, 0.82), rgba(5, 7, 6, 0.35) 70%, transparent);
      backdrop-filter: none;
    }
    #photo-viewer .detail-close {
      background: rgba(8, 11, 9, 0.72);
      backdrop-filter: blur(10px);
      min-height: 30px;
      padding: 0 12px;
    }
    .detail-scroll {
      flex: 1;
      min-height: 0;
      overflow-y: auto;
      overscroll-behavior: contain;
      display: flex;
      flex-direction: column;
    }
    /* The stage flexes: tall (up to ~46vh) when the body below is short,
       shrinking toward 220px as detail content needs the room. Slides are
       full-bleed; the item is never cropped (contain) and the letterbox is
       filled by a blurred echo of the same photo. */
    .photo-stage {
      flex: 1 1 auto;
      min-height: 220px;
      max-height: min(46vh, 420px);
      position: relative;
      display: flex;
      background: #080b09;
    }
    .photo-rail {
      flex: 1 1 0%;
      min-height: 0;
      display: flex;
      align-items: stretch;
      gap: 2px;
      overflow-x: auto;
      overflow-y: hidden;
      overscroll-behavior-x: contain;
      scroll-snap-type: x mandatory;
      padding: 0;
      scrollbar-width: none;
      background: #080b09;
    }
    .photo-rail::-webkit-scrollbar { display: none; }
    .photo-slide {
      position: relative;
      flex: 0 0 100%;
      width: 100%;
      height: auto;
      min-height: 0;
      scroll-snap-align: center;
      overflow: hidden;
      background: #050706;
      display: grid;
      place-items: center;
    }
    /* Absolute so the slide's flex-stretch height is the sizing box — an
       in-flow img resolves height:100% against a grid track that grew to
       the image's intrinsic size and gets clipped. */
    .photo-slide img {
      position: absolute;
      inset: 0;
      z-index: 1;
      width: 100%;
      height: 100%;
      object-fit: contain;
      display: block;
    }
    .photo-slide .photo-blur {
      position: absolute;
      inset: 0;
      z-index: 0;
      width: 100%;
      height: 100%;
      object-fit: cover;
      filter: blur(28px) saturate(1.15) brightness(0.55);
      transform: scale(1.2);
    }
    /* 0.9.103: shimmer placeholder over the first slide's image box while
       it loads — reuses skeleton-sheen (see .skeleton) so the loading
       treatment reads the same everywhere; removed once the img fires
       load/error (or was already cached-complete), see renderGallery. */
    .photo-slide.photo-loading::after {
      content: "";
      position: absolute;
      inset: 0;
      z-index: 2;
      background: linear-gradient(100deg, transparent 20%, rgba(255, 255, 255, 0.07) 48%, transparent 76%);
      transform: translateX(-100%);
      animation: skeleton-sheen 1.35s ease-in-out infinite;
    }
    .photo-failed {
      color: var(--muted);
      font-size: 13px;
      padding: 20px;
      text-align: center;
    }
    .gallery-controls {
      position: absolute;
      left: 50%;
      bottom: 8px;
      z-index: 2;
      transform: translateX(-50%);
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 6px;
      padding: 4px 8px;
      border-radius: 999px;
      background: rgba(8, 11, 9, 0.62);
      backdrop-filter: blur(10px);
    }
    .gallery-controls[hidden] { display: none; }
    .photo-dots {
      display: flex;
      align-items: center;
      gap: 5px;
    }
    .photo-dots[hidden] { display: none; }
    .photo-dot {
      width: 6px;
      height: 6px;
      padding: 0;
      border: 0;
      border-radius: 999px;
      background: rgba(255, 255, 255, 0.38);
      cursor: pointer;
    }
    .photo-dot.active { background: var(--accent); }
    .photo-arrow {
      position: absolute;
      top: 50%;
      z-index: 2;
      transform: translateY(-50%);
      width: 30px;
      height: 44px;
      display: grid;
      place-items: center;
      border: 0;
      border-radius: 10px;
      background: rgba(8, 11, 9, 0.45);
      color: var(--text);
      font-size: 22px;
      line-height: 1;
      cursor: pointer;
      backdrop-filter: blur(8px);
    }
    .photo-arrow.prev { left: 6px; }
    .photo-arrow.next { right: 6px; }
    .photo-arrow[disabled] { opacity: 0.25; cursor: default; }
    .photo-arrow[hidden] { display: none; }
    .photo-count {
      text-align: center;
      color: var(--muted);
      font-size: 12px;
      font-weight: 650;
      font-variant-numeric: tabular-nums;
    }
    .photo-count[hidden] { display: none; }
    .viewer-status {
      display: none;
    }
    .detail-body {
      flex: 0 0 auto;
      padding: 8px 12px 8px;
      padding-left: calc(12px + var(--safe-l));
      padding-right: calc(12px + var(--safe-r));
    }
    .detail-title {
      margin: 0 0 4px;
      font-size: 15px;
      font-weight: 750;
      letter-spacing: -0.03em;
      line-height: 1.2;
      display: -webkit-box;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
      overflow: hidden;
    }
    .detail-chips {
      display: flex;
      flex-wrap: wrap;
      gap: 3px;
      margin-bottom: 6px;
      max-height: 44px;
      overflow: hidden;
    }
    .detail-chip {
      display: inline-flex;
      align-items: center;
      flex: 0 0 auto;
      gap: 3px;
      min-height: 20px;
      padding: 0 7px;
      border-radius: 999px;
      border: 1px solid var(--border);
      background: var(--surface);
      color: var(--muted);
      font-size: 10.5px;
      font-weight: 650;
      white-space: nowrap;
    }
    .detail-facts {
      display: grid;
      grid-template-columns: minmax(0, 1fr) auto;
      align-items: start;
      gap: 4px 10px;
      min-width: 0;
    }
    .detail-facts #ebay-body {
      min-width: 0;
      overflow: hidden;
    }
    .detail-facts #miles-body {
      min-width: min-content;
      max-width: none;
      text-align: right;
    }
    .detail-facts .detail-value-hero {
      flex-wrap: wrap;
      min-width: 0;
    }
    .detail-facts .detail-value-hero .sub {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    /* Stale-cache shield: old detail JS still injects the eBay essay and
       a wrapping confidence pill. Keep the compact hero, miles, and the
       short .detail-note / .detail-desc lines we actually want. */
    #photo-viewer .detail-confidence,
    #photo-viewer #ebay-body .detail-value-hero ~ .detail-trust,
    #photo-viewer #miles-body .detail-miles ~ .detail-trust {
      display: none;
    }
    .detail-note {
      margin: 2px 0 0;
      color: var(--muted);
      font-size: 11px;
      font-weight: 600;
      line-height: 1.35;
    }
    .detail-chip.live {
      background: var(--accent-soft);
      border-color: rgba(61, 214, 140, 0.35);
      color: var(--accent);
    }
    .detail-chip.hot {
      background: var(--hot-soft);
      border-color: rgba(255, 107, 107, 0.35);
      color: var(--hot);
    }
    /* Evidence grade (Wave 4): A stays the quiet default styling above;
       B is neutral, C leans warn — the trust ladder made visible. */
    .detail-chip.grade-b {
      color: var(--muted);
    }
    .detail-chip.grade-c {
      background: var(--hot-soft);
      border-color: rgba(224, 168, 90, 0.4);
      color: var(--warn);
    }
    .detail-chip.warn {
      background: rgba(240, 180, 41, 0.12);
      border-color: rgba(240, 180, 41, 0.35);
      color: var(--warn);
    }
    .detail-panel {
      border: 1px solid var(--border);
      border-radius: 12px;
      background: var(--surface);
      padding: 9px 12px;
      margin-bottom: 9px;
    }
    .detail-panel[hidden] { display: none; }
    .detail-panel h3 {
      margin: 0 0 4px;
      font-size: 10px;
      font-weight: 700;
      letter-spacing: 0.05em;
      text-transform: uppercase;
      color: var(--muted);
    }
    .detail-value-hero {
      display: flex;
      align-items: baseline;
      gap: 8px;
      flex-wrap: wrap;
    }
    .detail-value-hero .big {
      font-size: 18px;
      font-weight: 800;
      letter-spacing: -0.03em;
      color: var(--accent);
    }
    .detail-value-hero .sub {
      color: var(--muted);
      font-size: 11px;
      font-weight: 600;
    }
    .detail-confidence {
      display: inline-flex;
      align-items: center;
      flex: 0 0 auto;
      min-height: 22px;
      margin-left: 0;
      padding: 3px 9px;
      border-radius: 999px;
      border: 1px solid var(--border);
      background: var(--surface-2);
      color: var(--muted);
      font-size: 10px;
      font-weight: 760;
      white-space: nowrap;
    }
    .detail-confidence.high {
      border-color: rgba(61, 214, 140, 0.38);
      background: var(--accent-soft);
      color: var(--accent);
    }
    .detail-confidence.medium {
      border-color: rgba(225, 187, 95, 0.38);
      color: #e1bb5f;
    }
    .detail-range {
      display: none;
    }
    .detail-range div {
      border-radius: 11px;
      background: var(--surface-2);
      border: 1px solid var(--border);
      padding: 8px;
      text-align: center;
    }
    .detail-range .k {
      display: block;
      font-size: 10px;
      color: var(--muted);
      font-weight: 650;
      margin-bottom: 3px;
    }
    .detail-range .v {
      font-size: 14px;
      font-weight: 750;
    }
    .detail-trust {
      margin: 4px 0 0;
      font-size: 12px;
      color: var(--muted);
      line-height: 1.35;
    }
    .sample-bars {
      display: none;
    }
    .sample-bars span {
      flex: 1;
      min-width: 3px;
      border-radius: 3px 3px 1px 1px;
      background: rgba(61, 214, 140, 0.55);
    }
    /* 0.9.56: inline trend sparkline — eBay history next to the current
       figure, and the value drill-in's 7-day total-upside line. No axes,
       no libraries, current CSS colors only. */
    .market-spark { align-self: center; flex: 0 0 auto; }
    /* Price truth strip + demand read (dead-space fill below the
       description) — hand-rolled SVG only, no chart library. */
    .price-truth-row {
      display: flex;
      align-items: center;
      gap: 8px;
    }
    .price-truth-svg {
      flex: 1 1 auto;
      min-width: 0;
      width: 100%;
      height: 40px;
      display: block;
    }
    .price-truth-axis {
      display: flex;
      justify-content: space-between;
      margin-top: 2px;
      font-size: 10px;
      font-weight: 650;
      color: var(--muted);
    }
    .price-truth-mark {
      color: var(--accent);
      font-weight: 750;
    }
    /* 0.9.103: honest loading states for the price truth strip + demand
       band — skeletons reuse .skeleton's sheen (prefers-reduced-motion
       already disables it globally, see the media query below). */
    .price-truth-skel {
      height: 40px;
      border-radius: 8px;
    }
    .demand-skel-line {
      height: 12px;
      width: 78%;
      border-radius: 6px;
    }
    .demand-skel-line + .demand-skel-line {
      margin-top: 6px;
    }
    .demand-skel-line.short {
      width: 52%;
    }
    .panel-retry {
      display: inline;
      margin-left: 4px;
      border: 0;
      background: transparent;
      padding: 0;
      color: var(--accent);
      font-size: inherit;
      font-weight: 750;
      text-decoration: underline;
      text-underline-offset: 2px;
      cursor: pointer;
      min-height: 22px;
    }
    .demand-spark-row {
      display: flex;
      align-items: center;
      gap: 6px;
      margin-top: 4px;
    }
    /* 0.9.110: claim-window hero — predicted-moment line + elapsed-fraction
       bar, first thing in the demand panel. The fill is a full-width
       element scaled via transform (compositor-only, no layout thrash);
       global prefers-reduced-motion block above already zeroes the
       transition duration. */
    .claim-window {
      margin: 0 0 6px;
    }
    .claim-line {
      margin: 0;
      color: var(--text);
      font-weight: 650;
    }
    .claim-line.claim-past {
      color: var(--muted);
      font-weight: 500;
    }
    .claim-bar {
      margin-top: 6px;
      height: 6px;
      border-radius: 999px;
      background: rgba(61, 214, 140, 0.14);
      overflow: hidden;
    }
    .claim-bar-fill {
      width: 100%;
      height: 100%;
      border-radius: 999px;
      background: linear-gradient(90deg, rgba(61, 214, 140, 0.55), var(--accent));
      transform: scaleX(0);
      transform-origin: left;
      transition: transform 300ms ease;
    }
    /* 0.9.110: family pulse mini-bars ride the scarcity sentence's row. */
    .demand-family-row {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 10px;
    }
    .demand-family-row .detail-trust {
      flex: 1 1 auto;
    }
    .family-pulse-bars {
      flex: 0 0 auto;
      align-self: center;
    }
    .detail-miles {
      font-size: 13px;
      font-weight: 650;
      letter-spacing: -0.02em;
      color: var(--text);
      white-space: nowrap;
    }
    .detail-footer {
      flex-shrink: 0;
      display: grid;
      grid-template-columns: auto minmax(72px, 0.5fr) minmax(120px, 1fr);
      gap: 6px;
      padding: 6px 10px calc(8px + var(--safe-b));
      padding-left: calc(10px + var(--safe-l));
      padding-right: calc(10px + var(--safe-r));
      border-top: 1px solid var(--border);
      background: rgba(10, 13, 11, 0.96);
    }
    .detail-more { position: relative; }
    .detail-more > summary {
      list-style: none;
      min-width: 56px;
      min-height: 40px;
      padding: 0 10px;
      border-radius: 11px;
      border: 1px solid var(--border);
      background: var(--surface);
      display: grid;
      place-items: center;
      color: var(--muted);
      font-size: 12px;
      font-weight: 750;
      cursor: pointer;
    }
    .detail-more > summary::-webkit-details-marker { display: none; }
    .detail-more-menu {
      position: absolute;
      left: 0;
      bottom: calc(100% + 8px);
      z-index: 5;
      width: 168px;
      padding: 6px;
      border: 1px solid var(--border);
      border-radius: 14px;
      background: #0f1511;
      box-shadow: 0 16px 40px rgba(0, 0, 0, 0.42);
    }
    .detail-more-menu button {
      width: 100%;
      min-height: 42px;
      border: 0;
      border-radius: 9px;
      background: transparent;
      color: var(--text);
      text-align: left;
      padding: 0 12px;
      font-weight: 700;
      cursor: pointer;
    }
    .detail-more-menu button:hover,
    .detail-more-menu button:focus-visible { background: var(--surface-2); }
    .toast.undo {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 12px;
    }
    .toast.undo button {
      min-height: 36px;
      padding: 0 12px;
      border-radius: 10px;
      border: 1px solid rgba(61, 214, 140, 0.45);
      background: var(--accent-soft);
      color: var(--accent);
      font-weight: 750;
      cursor: pointer;
    }
    .detail-footer > a,
    .detail-footer > button {
      min-height: 40px;
      border-radius: 11px;
      border: 1px solid var(--border);
      background: var(--surface);
      font-weight: 750;
      display: grid;
      place-items: center;
      cursor: pointer;
      text-decoration: none;
      color: inherit;
    }
    .detail-footer > a.primary {
      background: var(--accent);
      border-color: var(--accent);
      color: #062416;
    }
    .photo-count {
      text-align: center;
      font-family: var(--mono);
      font-size: 12px;
      color: var(--muted);
    }
    .viewer-link {
      font-size: 13px;
      font-weight: 700;
    }
    .viewer-status {
      padding: 0 14px 10px;
      color: var(--muted);
      font-size: 12px;
    }

    /* —— Install banner (iOS) —— */
    .install-banner {
      position: fixed;
      left: 12px;
      right: 12px;
      bottom: calc(12px + var(--safe-b));
      z-index: 30;
      padding: 14px 14px 14px 16px;
      border-radius: 16px;
      background: #121c15;
      border: 1px solid rgba(61, 214, 140, 0.35);
      box-shadow: 0 12px 40px rgba(0,0,0,0.45);
      display: flex;
      align-items: flex-start;
      gap: 12px;
    }
    .install-banner[hidden] { display: none; }
    .install-banner strong {
      display: block;
      font-size: 14px;
      margin-bottom: 2px;
    }
    .install-banner p {
      margin: 0;
      color: var(--muted);
      font-size: 12px;
      line-height: 1.35;
    }
    .install-banner button {
      min-width: 36px;
      min-height: 36px;
      border: none;
      background: transparent;
      color: var(--muted);
      font-size: 18px;
      cursor: pointer;
      flex-shrink: 0;
    }

    /* —— Wider phones / tablets —— */
    @media (min-width: 540px) {
      .feed {
        gap: 10px;
      }
      .title { font-size: 13px; }
    }

    @media (min-width: 900px) {
      main {
        max-width: 1240px;
      }
      .feed {
        grid-template-columns: repeat(4, minmax(0, 1fr));
        gap: 12px;
      }
      .feed-skeleton-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
      .sheet-backdrop {
        background: rgba(3, 8, 5, 0.34);
      }
      .sheet {
        left: auto;
        right: max(20px, calc((100vw - 1200px) / 2));
        top: calc(72px + var(--safe-t));
        bottom: auto;
        width: min(520px, calc(100vw - 40px));
        max-height: calc(100dvh - 92px - var(--safe-t));
        padding: 20px 22px 20px;
        border: 1px solid var(--border);
        border-radius: 18px;
        box-shadow: 0 24px 70px rgba(0, 0, 0, 0.5);
        opacity: 0;
        pointer-events: none;
        transform: translateY(-10px) scale(0.985);
        transform-origin: top right;
        transition: opacity 0.18s ease, transform 0.2s ease;
      }
      .sheet.open {
        opacity: 1;
        pointer-events: auto;
        transform: translateY(0) scale(1);
      }
      .sheet-handle { display: none; }
      .sheet-footer {
        bottom: -20px;
        padding-bottom: 20px;
      }
      .photo-slide { height: min(36vh, 340px); }
    }

    @media (max-width: 899px) {
      main {
        padding-top: 8px;
        /* Density pass (Wave 3 item 2): cards win the viewport — outer
           gutters drop from 20px to 10px on phones, desktop untouched. */
        padding-left: calc(10px + var(--safe-l));
        padding-right: calc(10px + var(--safe-r));
      }
      .app-header {
        padding-left: calc(10px + var(--safe-l));
        padding-right: calc(10px + var(--safe-r));
      }
      .view-chrome { margin-bottom: 8px; }
      .view-toolbar {
        display: flex;
        flex-direction: row;
        flex-wrap: nowrap;
        align-items: center;
        gap: 6px;
      }
      .view-updated,
      .view-timing {
        display: none;
      }
      #sort-chips {
        flex: 0 1 auto;
        width: auto;
        max-width: 100%;
        margin-right: 0;
        border: 0;
        border-radius: 0;
        justify-content: flex-start;
        gap: 6px;
        padding: 2px;
        overflow-x: auto;
      }
      #sort-chips .chip {
        flex: 0 0 auto;
        min-width: 0;
        min-height: 32px;
        padding: 5px 11px;
        border: 1px solid var(--border);
        border-right-color: var(--border);
        border-radius: 999px;
        background: rgba(17, 24, 20, 0.72);
        font-size: 12px;
        scroll-snap-align: start;
      }
      #sort-chips .chip:last-child {
        border-right: 1px solid var(--border);
      }
      #sort-chips .chip.active {
        border-color: rgba(61, 214, 140, 0.75);
      }
      /* Ring/glow now comes from the base .chip.active rule (deliberate,
         stable, same on every breakpoint) — no mobile-only override left to
         drift out of sync with desktop. */
      .run-overview {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: center;
        gap: 14px;
        padding: 16px;
        border-radius: 20px;
        background: linear-gradient(135deg, rgba(61, 214, 140, 0.11), rgba(17, 24, 20, 0.94));
      }
      .run-overview-value {
        max-width: none;
        text-align: right;
      }
      .run-overview-copy strong { font-size: 15px; }
      .run-overview-copy span { font-size: 11px; }
      .run-overview-value strong { font-size: 18px; }
      .run-overview-value span { max-width: 102px; }
      .run-list { gap: 8px; }
      /* Save/Pass ride a slim right-hand column instead of their own
         full-width row — ~48px back per card, ~1.5 extra cards per
         screen. Swipe right/left stays the fast path. */
      .run-stop {
        grid-template-columns: minmax(0, 1fr) auto;
        border-radius: 14px;
        overflow: hidden;
        contain: layout paint;
        box-shadow: 0 8px 20px rgba(0, 0, 0, 0.18);
      }
      .run-stop-open {
        display: grid;
        grid-template-columns: 28px 56px minmax(0, 1fr) auto;
        grid-template-areas: "num thumb body value";
        gap: 8px;
        min-width: 0;
        min-height: 0;
        padding: 8px 10px;
        overflow: hidden;
        align-items: center;
        overscroll-behavior: contain;
      }
      .hour-value-list .run-stop-open {
        grid-template-columns: 56px minmax(0, 1fr) auto;
        grid-template-areas: "thumb body value";
      }
      .run-stop .num {
        grid-area: num;
        position: static;
        width: 28px;
        min-width: 28px;
        height: 28px;
        padding: 0;
        border-radius: 8px;
        background: var(--surface);
        box-shadow: none;
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        font-size: 12px;
      }
      .run-stop .num::before { content: none; }
      .run-stop .thumb {
        grid-area: thumb;
        position: relative;
        width: 56px;
        height: 56px;
        min-width: 56px;
        min-height: 56px;
        max-width: 56px;
        max-height: 56px;
        border-radius: 10px;
        overflow: hidden;
        contain: strict;
        background: #0a0d0b;
      }
      .run-stop .thumb::after { content: none; }
      .run-stop .thumb img {
        width: 56px;
        height: 56px;
        max-width: 56px;
        max-height: 56px;
      }
      .run-stop .thumb .ph { font-size: 11px; }
      .run-stop .body {
        grid-area: body;
        padding: 0;
        min-width: 0;
      }
      .run-stop .title {
        margin: 0 0 3px;
        font-size: 14px;
        line-height: 1.25;
        letter-spacing: -0.02em;
        -webkit-line-clamp: 2;
      }
      .run-stop .meta {
        gap: 4px 8px;
        font-size: 11px;
      }
      .run-stop .meta > * {
        white-space: nowrap;
      }
      .run-stop .value-block {
        grid-area: value;
        position: static;
        min-width: 3.75rem;
        max-width: 5rem;
        padding: 0;
        border: 0;
        border-radius: 0;
        background: transparent;
        box-shadow: none;
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        text-align: right;
      }
      .run-stop .value-block strong { font-size: 15px; }
      .run-stop .confidence {
        margin-top: 1px;
        color: var(--muted);
        font-size: 10px;
        letter-spacing: 0;
        opacity: 1;
      }
      .run-actions {
        flex-direction: column;
        justify-content: center;
        gap: 6px;
        padding: 6px 8px 6px 0;
        border-top: 0;
        border-left: 0;
        background: transparent;
      }
      .run-action {
        flex: 0 0 auto;
        min-height: 30px;
        min-width: 52px;
        padding: 0 8px;
        border-radius: 9px;
        font-size: 11px;
        text-align: center;
      }
      .run-action.save {
        border-color: rgba(61, 214, 140, 0.28);
        color: var(--text);
      }
      .run-skeleton {
        grid-template-columns: 34px 74px minmax(0, 1fr);
        min-height: 92px;
      }
      .location-fields { grid-template-columns: 1fr; gap: 0; }
    }

    @media (max-width: 420px) {
      .run-actions { padding-left: 0; }
      .settings-tab {
        padding: 5px 3px;
        font-size: 11px;
      }
      .sheet-footer { grid-template-columns: minmax(0, 0.8fr) minmax(150px, 1.2fr); }
      .market-banner,
      .coverage-banner {
        grid-template-columns: auto minmax(0, 1fr);
      }
      .market-banner-action,
      .coverage-banner-action {
        grid-column: 2;
        justify-self: start;
        min-height: 32px;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      *, *::before, *::after {
        scroll-behavior: auto !important;
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
      }
      button:not(:disabled):active,
      [role="button"]:active,
      a.primary:active { transform: none; }
      .card-photo img,
      .run-stop .thumb img { transition: none; }
    }

    @media (display-mode: standalone), (display-mode: fullscreen) {
      .install-banner { display: none !important; }
    }

    /* ————————————————————————————————————————————————————————————
       Identity layer (0.9.24) — CurbWorth street-HUD design pass.
       Additive overrides only: same selectors, later in the cascade,
       so component variants (.is-top-pick, .is-saved) keep priority.
       ———————————————————————————————————————————————————————————— */

    ::selection { background: rgba(61, 214, 140, 0.3); }

    /* Any range input without bespoke track styling (settings sheet radius)
       follows the accent instead of the browser's default blue */
    input[type="range"] { accent-color: var(--accent); }

    /* Display face: Space Grotesk for identity moments — brand, headings,
       and every money figure. Body/UI text stays on the system stack. */
    .brand h1,
    .run-stop .title,
    .detail-title,
    .sheet h2,
    .settings-section-heading h3,
    .empty h2,
    .run-empty h3,
    .run-overview-copy strong,
    .install-banner strong {
      font-family: var(--display);
      font-weight: 600;
      letter-spacing: -0.02em;
    }
    .run-stop .title { font-weight: 560; }
    .detail-title { font-weight: 600; letter-spacing: -0.03em; }

    .run-overview-value strong,
    .run-stop .value-block strong,
    .detail-value-hero .big,
    .detail-range .v,
    .detail-miles,
    .zip-btn,
    .run-stop .num {
      font-family: var(--display);
      font-variant-numeric: tabular-nums;
    }
    .run-overview-value strong { font-size: 24px; font-weight: 640; letter-spacing: -0.02em; }
    .run-stop .value-block strong { font-weight: 640; }
    .detail-value-hero .big { font-size: 18px; font-weight: 640; letter-spacing: -0.03em; }

    .chip,
    .settings-tab,
    .run-action {
      font-family: var(--display);
      font-weight: 540;
      letter-spacing: 0;
    }

    /* Header: brand lockup + animated HUD hairline along the bottom edge */
    .app-header::after {
      content: "";
      position: absolute;
      left: 0;
      right: 0;
      bottom: -1px;
      height: 1px;
      pointer-events: none;
      background: linear-gradient(90deg, transparent 12%, rgba(61, 214, 140, 0.55) 50%, transparent 88%);
      background-size: 220% 100%;
      animation: header-sweep 7s ease-in-out infinite alternate;
      opacity: 0.7;
    }
    @keyframes header-sweep {
      from { background-position: 0% 0; }
      to { background-position: 100% 0; }
    }
    .brand-mark { box-shadow: 0 0 0 1px rgba(61, 214, 140, 0.25), 0 4px 14px rgba(3, 10, 6, 0.5); }

    /* Hourly hero: glass panel with corner glow, value as the headline */
    .run-overview {
      position: relative;
      overflow: hidden;
      border-color: rgba(61, 214, 140, 0.28);
      background: linear-gradient(140deg, rgba(61, 214, 140, 0.13), rgba(17, 24, 20, 0.92) 58%);
      box-shadow: var(--shadow-tint), var(--edge);
    }
    .run-overview::after {
      content: "";
      position: absolute;
      inset: 0;
      pointer-events: none;
      background: radial-gradient(60% 130% at 100% 0%, rgba(61, 214, 140, 0.13), transparent 55%);
    }

    /* Top-5 cards: green-tinted glass, edge light, lift on hover */
    .run-stop {
      background: linear-gradient(150deg, rgba(21, 29, 24, 0.98), rgba(12, 17, 14, 0.98));
      box-shadow: var(--shadow-tint), var(--edge);
    }
    @media (hover: hover) and (pointer: fine) {
      .run-stop:hover {
        transform: translateY(-2px);
        border-color: rgba(61, 214, 140, 0.34);
        box-shadow: 0 22px 52px rgba(3, 10, 6, 0.52), var(--edge);
      }
    }
    .run-stop .num {
      background: rgba(61, 214, 140, 0.08);
      border-color: rgba(61, 214, 140, 0.24);
    }

    /* Staggered arrival for the ranked list */
    @keyframes stop-in {
      from { opacity: 0; transform: translateY(10px) scale(0.992); }
      to { opacity: 1; transform: translateY(0) scale(1); }
    }
    .run-list > .run-stop { animation: stop-in 0.42s var(--ease-out) backwards; }
    .run-list > .run-stop:nth-child(1) { animation-delay: 0.02s; }
    .run-list > .run-stop:nth-child(2) { animation-delay: 0.07s; }
    .run-list > .run-stop:nth-child(3) { animation-delay: 0.12s; }
    .run-list > .run-stop:nth-child(4) { animation-delay: 0.17s; }
    .run-list > .run-stop:nth-child(5) { animation-delay: 0.22s; }
    .run-list > .run-stop:nth-child(n + 6) { animation-delay: 0.26s; }

    /* Primary actions: money-green gradient with a hover brighten */
    .icon-btn.primary,
    .sheet-actions button.primary,
    .sheet-footer .primary,
    .detail-footer > a.primary {
      background: linear-gradient(165deg, #55e4a3, #2fbf78);
      border-color: rgba(61, 214, 140, 0.7);
      box-shadow: 0 8px 22px rgba(47, 191, 120, 0.24), inset 0 1px 0 rgba(255, 255, 255, 0.22);
    }
    @media (hover: hover) and (pointer: fine) {
      .icon-btn.primary:hover,
      .sheet-actions button.primary:hover,
      .sheet-footer .primary:hover,
      .detail-footer > a.primary:hover {
        background: linear-gradient(165deg, #63eaad, #36cc82);
        box-shadow: 0 10px 26px rgba(47, 191, 120, 0.32), inset 0 1px 0 rgba(255, 255, 255, 0.26);
      }
      .icon-btn:not(.primary):hover,
      .run-action:hover,
      .detail-close:hover,
      .gallery-controls button:hover {
        border-color: rgba(61, 214, 140, 0.34);
      }
      .chip:not(.active):hover {
        border-color: rgba(61, 214, 140, 0.3);
        color: var(--text);
      }
    }

    /* Search: quiet at rest, glows when it has your attention */
    .search {
      transition: border-color var(--motion-fast) ease, box-shadow var(--motion-fast) ease, background-color var(--motion-fast) ease;
    }
    .search:focus {
      outline: none;
      border-color: rgba(61, 214, 140, 0.5);
      background-color: var(--surface-2);
      box-shadow: 0 0 0 3px rgba(61, 214, 140, 0.13);
    }

    /* Comp histogram: give the live-ask bars a gradient and soft caps */
    .sample-bars span {
      border-radius: 4px 4px 2px 2px;
      background: linear-gradient(to top, rgba(61, 214, 140, 0.3), rgba(61, 214, 140, 0.85));
    }

    /* Detail sheet panels pick up the same edge light as the cards */
    .detail-panel { box-shadow: var(--edge); }
    .run-empty { background: radial-gradient(80% 100% at 50% 0%, rgba(61, 214, 140, 0.05), transparent 70%); }

    /* 0.9.58: former inline style="" attributes, converted to classes so
       CSP style-src can drop 'unsafe-inline'. */
    .chips-wrap { flex-wrap: wrap; }
    .detail-trust-lead { margin: 8px 0 0; }
    .detail-row-gap { margin-top: 6px; }
    .detail-row-gap-warn { margin-top: 6px; color: var(--warn); }
    .detail-map-links { margin-top: 8px; display: flex; gap: 8px; flex-wrap: wrap; }
    .detail-desc {
      margin: 8px 0 0;
      color: var(--text);
      font-size: 13px;
      font-weight: 500;
      line-height: 1.45;
    }
    .detail-desc[hidden] { display: none; }
    .grid-span { grid-column: 1 / -1; }
    .load-more-wrap { padding: 18px; }

    @media (max-width: 899px) {
      .run-overview-value strong { font-size: 18px; }
      .run-stop .value-block strong { font-size: 15px; }
      .run-stop:hover { transform: none; }
    }

    .field label {
      text-transform: none;
      letter-spacing: 0;
      font-size: 13px;
      font-weight: 650;
      color: var(--text);
    }
    .pulse-body { display: grid; gap: 10px; }
    .pulse-hero {
      padding: 16px;
      border-radius: 16px;
      border: 1px solid rgba(61, 214, 140, 0.28);
      background: linear-gradient(135deg, rgba(61, 214, 140, 0.12), rgba(17, 24, 20, 0.9));
    }
    .pulse-kicker {
      margin: 0 0 4px;
      color: var(--muted);
      font-size: 12px;
      font-weight: 650;
    }
    .pulse-big {
      margin: 0;
      color: var(--accent);
      font-family: var(--display);
      font-size: 32px;
      font-weight: 640;
      letter-spacing: -0.03em;
      font-variant-numeric: tabular-nums;
    }
    .pulse-sub { margin: 4px 0 0; color: var(--muted); font-size: 13px; }
    .pulse-card {
      padding: 14px;
      border-radius: 14px;
      border: 1px solid var(--border);
      background: var(--surface);
    }
    .pulse-card h3 {
      margin: 0 0 6px;
      font-size: 12px;
      font-weight: 750;
      color: var(--muted);
    }
    .pulse-lead { margin: 0; font-size: 16px; font-weight: 650; line-height: 1.3; }
    .pulse-stat {
      margin: 0;
      font-family: var(--display);
      font-size: 22px;
      font-weight: 640;
      color: var(--accent);
      font-variant-numeric: tabular-nums;
    }
    .pulse-meta { margin: 4px 0 0; color: var(--muted); font-size: 12px; }
    .pulse-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
    .pulse-mix-row {
      position: relative;
      display: flex;
      justify-content: space-between;
      gap: 8px;
      margin-top: 8px;
      padding: 8px 10px;
      font-size: 13px;
      font-weight: 650;
    }
    .pulse-mix-bar {
      position: absolute;
      left: 0;
      bottom: 0;
      height: 3px;
      border-radius: 99px;
      background: var(--accent);
    }
    .pulse-look { display: grid; gap: 6px; }
    .pulse-look-row {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: 2px;
      width: 100%;
      padding: 10px 0;
      border: 0;
      border-bottom: 1px solid var(--border);
      background: transparent;
      color: inherit;
      font: inherit;
      text-align: left;
      cursor: pointer;
    }
    .pulse-look-row:last-child { border-bottom: 0; }
    .pulse-look-row span { color: var(--muted); font-size: 12px; }

/* Privacy / Terms / Support links in Settings → Extras. App Store Connect
   carries the same URLs, but a customer looking for how to delete their
   data or reach a human should not have to leave the app to find them. */
.legal-links {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin: 0;
}

.legal-links a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

/* Countdown pause control and the demoted listing-detail caption.
   These carry no style="" attribute on purpose: the app serves
   `style-src 'self'` with no 'unsafe-inline', so an inline style
   attribute is blocked outright and the element renders unstyled. */
.run-countdown-row {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.run-countdown-toggle {
  min-width: 24px;
  min-height: 24px;
  padding: 0 4px;
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: 10.5px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
}

.viewer-caption {
  margin: 0;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}

/* The card's open affordance: a real <button> filling the photo area, so the
   quick actions inside the card are siblings rather than focusable children
   of an interactive element. No style="" on the element itself — the app
   serves `style-src 'self'` with no 'unsafe-inline', so an inline style is
   blocked outright and the photo would render unstyled. */
.card-open {
  position: absolute;
  inset: 0;
  padding: 0;
  margin: 0;
  border: 0;
  background: transparent;
  font: inherit;
  color: inherit;
  overflow: hidden;
  cursor: pointer;
}

.run-countdown-row[hidden] { display: none; }
