diff --git a/CLAUDE.md b/CLAUDE.md index d059fa5..145ac85 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -290,6 +290,11 @@ Note: `align-items`, `justify-items`, `align-content`, `justify-content`, `place **DESIGN TOKENS**: All new styles must consume tokens from `tokens.css` — never hardcode colors, spacing, radii, shadows, or font sizes. Use `var(--token-name)` or `var(--token-name, fallback)`. Our token scale uses a 4px spacing base and major third (1.250) type scale. +**DARK-MODE TRAP — only reference vars that are REAL tokens.** A `var(--name, fallback)` where `--name` is **not** defined in `tokens.css` silently uses the light `fallback` in BOTH themes → looks fine in light, broken (light card / invisible text) in dark. This bit us repeatedly (wells, suggest cards, checksum table). The offenders were ad-hoc names like `--color-surface*`, `--color-border*`, `--color-text*`, `--text-color`, `--surface*` — none are tokens. **Use the real theme-aware tokens**: surfaces → `--surface-base` / `--surface-dim` / `--surface-container`; borders → `--border-light` / `--border-default` / `--border-color`; text → `--text-primary` / `--text-body` / `--text-muted` (all carry `:root` + `[data-theme="dark"]` values). Pre-commit grep gate (must be empty): +``` +grep -oE 'var\(\s*--(color-(surface|border|text)[a-z0-9-]*|surface(-[a-z]+)?|text-color)\s*,' make_post_sell/static/css/common.css +``` + **STYLEGUIDE**: When creating new UI components (buttons, wells, alerts, layout patterns, etc.), add a live example to `/styleguide` (`make_post_sell/templates/styleguide.j2`). Our styleguide is our single source of truth for our component library. If it's not in our styleguide, it doesn't exist as a pattern. **CSS MEDIA SIZING**: Never combine `width: 100%` with `max-height` on media elements (img, video). `width: 100%` forces our element to span our full container even when `max-height` constrains our rendered content, creating dead whitespace. Use `width: auto` + `max-width: 100%` + `max-height` instead — our element shrinks to match our actual content aspect ratio within both constraints. diff --git a/docs/tickets/mps-24.md b/docs/tickets/mps-24.md index 190164b..0b9037f 100644 --- a/docs/tickets/mps-24.md +++ b/docs/tickets/mps-24.md @@ -363,6 +363,27 @@ Tests (`test_functional.py::TestProductTagsSpa`): Deferred (occasional click, not the hot path): AJAX-ifying the "Suggest categories" link — still a full navigation by design. +**Phase 2.8r — systemic dark-mode token sweep** (shipped 2026-05-18): +after fixing the same dark-mode bug 4× one-surface-at-a-time (wells, +suggest cards, counts, checksum table) the operator asked for a +systemic pass. Root pattern: CSS referenced `var(--name, fallback)` +where `--name` is **not** a token in `tokens.css` (`--color-surface*`, +`--color-border*`, `--color-text*`, `--text-color`, `--surface*`), so +the light `fallback` applied in BOTH themes → dark broken. Swept all +53 occurrences in `common.css` to the real theme-aware tokens +(`--surface-base/-dim/-container`, `--border-default`, +`--text-primary/-body/-muted`), **keeping each fallback literal** +(comma-boundary sed; verified diff is exactly 53/53 var-name-only +swaps, no fallback/structure change, line count unchanged). Light +mode now uses canonical token values: identical where token==fallback +(`#fff`, off-whites); minor design-consistent nudges where they +differ (muted `#888→#666`, body `#333→#515151`, primary `#111→#333`, +borders → `#e0e0e0`). Dark mode fixed app-wide. Excluded (not the +bug / runtime-defined): `--shop-theme-*`, `--color-accent`, +`--pico-*`, `--primary-color`, the `--dark-*` family (dark fallbacks, +dark-only rules), and theme-neutral font/size/radius vars. CLAUDE.md +gains a "DARK-MODE TRAP" rule + pre-commit grep gate. + **Phase 2.8q — click-to-copy hashes + styled checksum table** (shipped 2026-05-18): operator: make the checksum hashes click-to-copy (they were unstyled, overflowing the column). New reusable diff --git a/make_post_sell/static/css/common.css b/make_post_sell/static/css/common.css index 129e558..7043f8d 100644 --- a/make_post_sell/static/css/common.css +++ b/make_post_sell/static/css/common.css @@ -1482,18 +1482,18 @@ a.tag-chip { display: inline-grid; place-items: center; padding: var(--space-1, 4px) var(--space-3, 12px); - border: 1px solid var(--color-border, #d1d5db); + border: 1px solid var(--border-default, #d1d5db); border-radius: var(--radius-pill, 999px); - background: var(--color-surface, #fff); - color: var(--color-text, #111); + background: var(--surface-base, #fff); + color: var(--text-primary, #111); font-size: var(--type-body-sm-size, 0.875rem); text-decoration: none; transition: background-color 150ms ease, border-color 150ms ease; } a.tag-chip:hover { - background: var(--color-surface-2, #f3f4f6); - border-color: var(--color-border-strong, #9ca3af); + background: var(--surface-container, #f3f4f6); + border-color: var(--border-default, #9ca3af); text-decoration: none; } @@ -1545,10 +1545,10 @@ li.tag-chip-removable { gap: var(--space-2, 8px); margin: 0 var(--space-2, 8px) var(--space-2, 8px) 0; padding: var(--space-1, 4px) var(--space-2, 8px) var(--space-1, 4px) var(--space-3, 12px); - border: 1px solid var(--color-border, #d1d5db); + border: 1px solid var(--border-default, #d1d5db); border-radius: var(--radius-pill, 999px); - background: var(--color-surface, #fff); - color: var(--color-text, #111); + background: var(--surface-base, #fff); + color: var(--text-primary, #111); font-size: var(--type-body-sm-size, 0.875rem); } @@ -1566,7 +1566,7 @@ button.tag-chip-removable-x { border: none; border-radius: var(--radius-pill, 999px); background: transparent; - color: var(--color-text-muted, #6b7280); + color: var(--text-muted, #6b7280); font-size: var(--type-body-size, 1rem); line-height: 1; cursor: pointer; @@ -1639,8 +1639,8 @@ form.serp-sort-form select { padding: var(--space-1, 4px) var(--space-2, 8px); border-radius: var(--radius-sm, 4px); border: 1px solid var(--border-color, #dee2e6); - background: var(--surface-color, #fff); - color: var(--text-color, #222); + background: var(--surface-base, #fff); + color: var(--text-body, #222); font-size: var(--type-body-sm-size, 0.875rem); } @media (max-width: 600px) { @@ -1719,7 +1719,7 @@ p.serp-list-price a { } p.serp-list-excerpt { margin: 0; - color: var(--text-color, #333); + color: var(--text-body, #333); font-size: var(--type-body-sm-size, 0.875rem); line-height: 1.5; /* No max-width — the excerpt fills the row body so the layout uses @@ -1870,7 +1870,7 @@ li.tag-list-item { align-items: center; gap: var(--space-3, 12px); padding: var(--space-2, 8px); - border: 1px solid var(--color-border, #e5e7eb); + border: 1px solid var(--border-default, #e5e7eb); border-radius: var(--radius-sm, 4px); } li.tag-list-item.tag-list-drop-target { @@ -1995,9 +1995,9 @@ div.tag-flash { div.tag-flash-toast { padding: var(--space-2, 8px) var(--space-3, 12px); border-radius: var(--radius-sm, 4px); - border: 1px solid var(--color-border, #d1d5db); - background: var(--color-surface-2, #f9fafb); - color: var(--color-text, #111); + border: 1px solid var(--border-default, #d1d5db); + background: var(--surface-container, #f9fafb); + color: var(--text-primary, #111); transition: opacity 400ms ease; } @@ -2090,7 +2090,7 @@ li.serp-rail-card { padding: var(--space-2, 8px); border: 1px solid var(--border-color, #e5e7eb); border-radius: var(--radius-sm, 4px); - background: var(--surface, #fff); + background: var(--surface-base, #fff); } a.serp-rail-thumb-link { display: block; @@ -2134,14 +2134,14 @@ span.serp-rail-card-price { details.facet-details { margin: var(--space-3, 12px) 0; padding: var(--space-3, 12px); - background: var(--surface, #fff); + background: var(--surface-base, #fff); border: 1px solid var(--border-color, #e5e7eb); border-radius: var(--radius-md, 8px); } details.facet-details summary.facet-details-summary { cursor: pointer; font-weight: 600; - color: var(--text-color, #333); + color: var(--text-body, #333); padding: var(--space-1, 4px) 0; } span.facet-details-active-mark { @@ -2182,7 +2182,7 @@ h2.facet-title { margin: 0; font-size: var(--type-body-size, 1rem); font-weight: 600; - color: var(--text-color, #333); + color: var(--text-body, #333); letter-spacing: 0.02em; } select.facet-select { @@ -2190,8 +2190,8 @@ select.facet-select { padding: var(--space-2, 8px); border: 1px solid var(--border-color, #d1d5db); border-radius: var(--radius-sm, 4px); - background: var(--surface, #fff); - color: var(--text-color, #333); + background: var(--surface-base, #fff); + color: var(--text-body, #333); } div.facet-price-range { display: grid; @@ -2211,8 +2211,8 @@ input.facet-price-input { padding: var(--space-2, 8px); border: 1px solid var(--border-color, #d1d5db); border-radius: var(--radius-sm, 4px); - background: var(--surface, #fff); - color: var(--text-color, #333); + background: var(--surface-base, #fff); + color: var(--text-body, #333); min-width: 0; } a.facet-clear-link { @@ -2240,7 +2240,7 @@ a.facet-tag { gap: var(--space-2, 8px); padding: var(--space-2, 8px) var(--space-3, 12px); border-radius: var(--radius-sm, 4px); - color: var(--text-color, #333); + color: var(--text-body, #333); text-decoration: none; transition: background-color 150ms ease; word-break: break-word; @@ -2318,7 +2318,7 @@ div.edit-page > section.well2 > form > h3:first-child { /* Pricing-mode fieldset on edit page — improved spacing. */ div.edit-page fieldset { - border: 1px solid var(--color-border, #ddd); + border: 1px solid var(--border-default, #ddd); border-radius: var(--radius-md, 8px); padding: var(--space-3, 12px) var(--space-4, 16px); margin: var(--space-3, 12px) 0; @@ -2327,7 +2327,7 @@ div.edit-page fieldset { div.edit-page fieldset legend { padding: 0 var(--space-2, 8px); font-weight: 600; - color: var(--color-text-muted, #666); + color: var(--text-muted, #666); } div.edit-page fieldset label[style*="display:block"], @@ -2346,7 +2346,7 @@ div.edit-page > section.product-title-and-description { Used in the upload/preview/thumbnail blocks of the edit page. */ .file-meta { margin: var(--space-1, 4px) 0; - color: var(--color-text-muted, #666); + color: var(--text-muted, #666); font-size: 0.9em; } @@ -2356,7 +2356,7 @@ div.edit-page > section.product-title-and-description { .file-meta-item + .file-meta-item::before { content: " · "; - color: var(--color-text-muted, #aaa); + color: var(--text-muted, #aaa); margin: 0 var(--space-1, 4px); } @@ -2371,13 +2371,13 @@ div.edit-page > section.product-title-and-description { font-size: 0.95rem; font-weight: 600; margin: 0 0 var(--space-2, 8px); - color: var(--color-text-primary, #333); + color: var(--text-primary, #333); } /* Form helper text — small tag below labels that doesn't break layout. */ .form-help { display: block; - color: var(--color-text-muted, #666); + color: var(--text-muted, #666); font-size: 0.85em; margin: var(--space-1, 4px) 0 var(--space-2, 8px); } @@ -2423,8 +2423,8 @@ div.edit-page > section.well2 > form > h3:first-child { gap: var(--space-3, 12px); margin-bottom: var(--space-3, 12px); padding-bottom: var(--space-3, 12px); - border-bottom: 1px solid var(--color-border, #eee); - color: var(--color-text-primary, #222); + border-bottom: 1px solid var(--border-default, #eee); + color: var(--text-primary, #222); } .edit-card-icon { @@ -2452,7 +2452,7 @@ div.edit-page > section.well2 > form > h3:first-child { .edit-permanent-link { text-align: right; margin: 0; - color: var(--color-text-muted, #666); + color: var(--text-muted, #666); font-size: 0.85em; } @@ -2467,7 +2467,7 @@ div.edit-page > section.well2 > form > h3:first-child { border-radius: var(--radius-pill, 999px); font-size: 0.85em; font-weight: 600; - background: var(--color-text-muted, #888); + background: var(--text-muted, #888); color: #fff; } @@ -2485,7 +2485,7 @@ div.edit-page > section.well2 > form > h3:first-child { } .edit-status-pill-private { - background: var(--color-text-muted, #888); + background: var(--text-muted, #888); } .edit-status-pill-unlisted { @@ -2535,10 +2535,10 @@ div.edit-page button.mps-submit-primary:disabled, bottom: var(--space-3, 12px); margin-top: var(--space-5, 20px); padding: var(--space-3, 12px) var(--space-4, 16px); - background: var(--surface, #fff); + background: var(--surface-base, #fff); border-radius: var(--radius-md, 8px); box-shadow: var(--elevation-3, 0 4px 12px rgba(0,0,0,0.07)); - border: 1px solid var(--color-border, #eee); + border: 1px solid var(--border-default, #eee); display: grid; grid-template-columns: 1fr auto; align-items: center; @@ -2547,7 +2547,7 @@ div.edit-page button.mps-submit-primary:disabled, } .edit-save-bar-status { - color: var(--color-text-muted, #666); + color: var(--text-muted, #666); font-size: 0.9em; } @@ -2841,7 +2841,7 @@ section.upload-product-and-preview { .upload-thumbnails-hint { margin: 0; - color: var(--color-text-muted, #666); + color: var(--text-muted, #666); text-align: right; max-width: 320px; } @@ -2864,7 +2864,7 @@ section.upload-product-and-preview { gap: var(--space-2, 8px); padding: var(--space-3, 12px); background: var(--surface-dim, #f9f9fa); - border: 1px solid var(--color-border, #eee); + border: 1px solid var(--border-default, #eee); border-radius: var(--radius-md, 8px); min-width: 0; } @@ -2874,7 +2874,7 @@ section.upload-product-and-preview { max-width: 100%; height: 140px; object-fit: contain; - background: var(--surface, #fff); + background: var(--surface-base, #fff); border-radius: var(--radius-sm, 4px); } @@ -5611,14 +5611,14 @@ textarea { padding: 10px 14px; align-items: center; text-align: left; - background: var(--surface-secondary, #f6f8fa); + background: var(--surface-dim, #f6f8fa); border: 1px solid var(--border-color, #dee2e6); border-radius: var(--radius-md, 8px); margin-top: 8px; } [data-theme="dark"] .watch-countdown { - background: var(--surface-secondary, #161b22); + background: var(--surface-dim, #161b22); border-color: var(--border-color, #7ab9ff); } @@ -5884,8 +5884,8 @@ textarea { padding: var(--space-1, 4px) var(--space-2, 8px); border-radius: var(--radius-sm, 4px); border: 1px solid var(--border-color, #dee2e6); - background: var(--surface-color, #fff); - color: var(--text-color, #222); + background: var(--surface-base, #fff); + color: var(--text-body, #222); font-size: var(--font-size-sm, 0.875rem); } @@ -6387,7 +6387,7 @@ html[data-color-filter="7"] { padding: var(--space-2, 8px); border: 1px solid var(--border-default, #ccc); border-radius: var(--radius-sm, 4px); - background: var(--surface-default, #fff); + background: var(--surface-base, #fff); color: var(--text-primary, #333); } @@ -6443,7 +6443,7 @@ html[data-color-filter="7"] { } .auction-stat-label { - color: var(--color-text-muted, #888); + color: var(--text-muted, #888); font-size: 0.85em; } @@ -6466,10 +6466,10 @@ html[data-color-filter="7"] { font-weight: bold; text-align: center; color: #fff; - background: var(--color-text-muted, #888); + background: var(--text-muted, #888); } -.auction-state-0 { background: var(--color-text-muted, #888); } /* Draft */ +.auction-state-0 { background: var(--text-muted, #888); } /* Draft */ .auction-state-1 { background: var(--color-info, #17a2b8); } /* Scheduled */ .auction-state-2 { background: var(--color-success, #28a745); } /* Active */ .auction-state-3 { background: var(--color-warning, #ffc107); color: #333; } /* Ended */ @@ -6480,8 +6480,8 @@ html[data-color-filter="7"] { .offer-state-1 { background: var(--color-success, #28a745); } /* Accepted */ .offer-state-2 { background: var(--color-primary, #5871ad); } /* Countered */ .offer-state-3 { background: var(--color-error, #dc3545); } /* Declined */ -.offer-state-4 { background: var(--color-text-muted, #888); } /* Expired */ -.offer-state-5 { background: var(--color-text-muted, #888); } /* Withdrawn */ +.offer-state-4 { background: var(--text-muted, #888); } /* Expired */ +.offer-state-5 { background: var(--text-muted, #888); } /* Withdrawn */ .offer-state-6 { background: var(--color-success, #28a745); } /* Paid */ .auction-flash { @@ -6511,7 +6511,7 @@ html[data-color-filter="7"] { .offer-event { padding: var(--space-2) 0; - border-bottom: 1px solid var(--color-border, #eee); + border-bottom: 1px solid var(--border-default, #eee); } .offer-event:last-child {