diff --git a/static/icon.svg b/static/icon.svg index bb5ae46..32fc46a 100644 --- a/static/icon.svg +++ b/static/icon.svg @@ -1,9 +1,12 @@ - + card sealed inside. Kept in step with .brand-mark in style.css. + White field with the brand red label band, per the light theme. --> + + - - + stroke="#1c2b45" stroke-width="5"/> + + diff --git a/static/index.html b/static/index.html index aa253d9..580165e 100644 --- a/static/index.html +++ b/static/index.html @@ -6,13 +6,13 @@ Card Grader - + - + diff --git a/static/manifest.json b/static/manifest.json index ed155c0..25bc78b 100644 --- a/static/manifest.json +++ b/static/manifest.json @@ -6,8 +6,8 @@ "scope": "__BASE__/", "display": "standalone", "orientation": "portrait", - "background_color": "#0a0f1c", - "theme_color": "#16224a", + "background_color": "#eef0f4", + "theme_color": "#ffffff", "icons": [ { "src": "__BASE__/static/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any" }, { "src": "__BASE__/static/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any" }, diff --git a/static/style.css b/static/style.css index 06e61a6..937af26 100644 --- a/static/style.css +++ b/static/style.css @@ -1,56 +1,64 @@ -/* Card Grader — "collector-grade" dark theme. +/* Card Grader — slab-house theme: silver ground, red accent, black text. Card-type agnostic (Pokemon, sports, TCG). - Committed dark, not a dark *mode*. The light palette was removed rather - than kept as a fallback: this is one deliberate look, and a half-tended - second palette is how a design drifts out of sync with itself. Phones in - light mode get this same design, which is the intent. + Committed light, not a light *mode*. A single deliberate look; a + half-tended second palette is how a design drifts out of sync with + itself. Phones in dark mode get this same design, which is the intent. - Colour discipline (carried over from the light theme, still true): + Colour discipline: - Grade severities ride a lightness ladder (none -> minor -> moderate -> major), so the table still reads as escalating severity in greyscale. - - Red is reserved for "you should distrust this number" (unmeasurable - edges, a low grade) — never decorative. + - Red is the BRAND here, so it can no longer also mean "distrust this + number". Severity red is therefore a distinctly darker, browner red + (--critical) than the brand's (--brand), and severity is never carried + by colour alone — the pills and chips carry a word too. - Foil/holo treatment is reserved for a 10. Every card shimmering would say nothing. */ :root { - color-scheme: dark; + color-scheme: light; - /* Ground is nearly black with a blue cast — a neutral grey ground makes - the card thumbnails look washed, since most slabs and holos are cool. */ - --ground: #06090f; - --surface-1: #0e1522; - --surface-2: #141d2e; /* raised: modal, slab body, hover */ - --ink: #eef3fb; - --ink-2: #aab8cf; - --muted: #7e8da6; - --hairline: #1c2740; - --rule: #2a3852; + /* Ground is a faint cool grey rather than pure white — slab labels, card + thumbnails and the panels all sit ON something, and pure white leaves + nothing for a white label to separate from. */ + --ground: #eef0f4; + --surface-1: #ffffff; + --surface-2: #f4f6f9; /* raised: modal insets, slab body, hover */ + --ink: #10141c; + --ink-2: #47505f; + --muted: #6b7484; + --hairline: #e2e6ec; + --rule: #ccd2dc; - --accent: #4d9bff; - --accent-2: #3ddcc0; - --accent-soft: rgba(77, 155, 255, .14); + /* PSA-style red. Used for brand chrome and primary actions. */ + --brand: #c8102e; + --brand-dark: #a20d25; + --brand-soft: rgba(200, 16, 46, .09); - /* Label chrome only — the red band on a slab label, never a severity. - Deliberately deeper than --critical (#f2555a) so the two don't read as - the same signal: this one is decoration on a physical-looking object, - that one means "distrust this number". */ - --slab-red: #c8102e; - --slab-face: #eceef2; + --accent: var(--brand); + --accent-2: #1c2b45; /* deep navy — the label's text/secondary tone */ + --accent-soft: var(--brand-soft); + + /* Slab label tokens. On a light ground the label is near-white and + separates by its border and shadow rather than by being lighter than + everything else, which is how a real label sits on a page. */ + --slab-red: var(--brand); + --slab-face: #f7f8fa; --slab-ink: #0c111a; --slab-ink-2: #5a6474; - --slab-rule: #b9c0cc; + --slab-rule: #c2c8d2; - --good: #23c55e; - --good-text: #4ade80; - --warning: #f5a33c; - --critical: #f2555a; + --good: #16853f; + --good-text: #127034; + --warning: #a86200; + /* Deliberately darker and browner than --brand so a severity red never + reads as the brand red sitting next to it. */ + --critical: #8f1d1d; - --ring: rgba(255, 255, 255, .12); - --shadow-sm: 0 1px 2px rgba(0, 0, 0, .5); - --shadow: 0 2px 6px rgba(0, 0, 0, .5), 0 16px 40px rgba(0, 0, 0, .55); - --shadow-lg: 0 4px 12px rgba(0, 0, 0, .55), 0 28px 70px rgba(0, 0, 0, .65); + --ring: rgba(16, 20, 28, .12); + --shadow-sm: 0 1px 2px rgba(16, 20, 28, .08); + --shadow: 0 1px 2px rgba(16, 20, 28, .06), 0 6px 18px rgba(16, 20, 28, .08); + --shadow-lg: 0 2px 6px rgba(16, 20, 28, .08), 0 18px 44px rgba(16, 20, 28, .14); --radius: 14px; --radius-lg: 18px; @@ -65,13 +73,13 @@ body { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; - /* Two broad, very low-opacity glows instead of the old dot grid. A tiled - pattern reads as "utility dashboard"; soft light on a dark ground reads - as depth. Fixed so it doesn't slide around under the content. */ + /* A single very faint warm-red wash at the top, so the ground isn't a + flat slab of grey but doesn't compete with the content either. The + dark theme's two coloured glows were far too strong to survive on a + light ground — they read as stains rather than depth. */ background-color: var(--ground); background-image: - radial-gradient(900px 600px at 12% -8%, rgba(77, 155, 255, .10), transparent 60%), - radial-gradient(760px 520px at 92% 4%, rgba(61, 220, 192, .07), transparent 62%); + radial-gradient(1100px 520px at 50% -12%, rgba(200, 16, 46, .06), transparent 70%); background-attachment: fixed; background-repeat: no-repeat; min-height: 100vh; @@ -105,10 +113,10 @@ main { .topbar { position: relative; /* containing block for the holo edge below */ - background: rgba(8, 12, 20, .82); - -webkit-backdrop-filter: blur(14px) saturate(1.4); - backdrop-filter: blur(14px) saturate(1.4); - border-bottom: 1px solid var(--hairline); + background: rgba(255, 255, 255, .88); + -webkit-backdrop-filter: blur(14px) saturate(1.3); + backdrop-filter: blur(14px) saturate(1.3); + border-bottom: 1px solid var(--rule); } /* The bar spans the viewport, but its CONTENTS line up with the page column — the logo sitting hard against a 3440px screen edge while the @@ -125,25 +133,20 @@ main { number lives — but dialled back from the original full-strength stripe, which was the loudest thing on an otherwise restrained page. */ .topbar::after { - content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 1.5px; + content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; background: linear-gradient(90deg, #ff5f8f, #ffb347, #ffe66d, #3ddcc0, #4d9bff, #a97bff, #ff5f8f); - opacity: .5; + opacity: .8; /* light ground needs more of it than dark did to register */ } .topbar h1 { - color: #fff; font-size: 16px; font-weight: 600; letter-spacing: -.005em; + color: var(--ink); font-size: 16px; font-weight: 700; letter-spacing: -.005em; } -.topbar .btn { - background: var(--accent-2); color: #04231d; - border-color: transparent; font-weight: 650; -} -.topbar .btn:hover { filter: brightness(1.08); } -.topbar .btn-quiet { - background: rgba(255, 255, 255, .07); color: var(--ink); - border-color: rgba(255, 255, 255, .16); font-weight: 550; -} -.topbar .btn-quiet:hover { background: rgba(255, 255, 255, .13); filter: none; } +/* The header's buttons inherit the page's button styling now. On the dark + theme they needed their own palette to stay legible against the bar; + against a white bar they don't, and overriding them only made the header + inconsistent with every other control. */ +.topbar .btn-quiet:hover { background: var(--surface-2); filter: none; } .brand { display: flex; align-items: center; gap: 11px; } @@ -152,12 +155,15 @@ main { checkmark it replaced: that read as a generic app badge and said nothing about grading. Thin strokes and no glow keep it legible at 22px. */ .brand-mark { flex: none; width: 18px; height: 27px; display: block; } -.brand-mark .mark-case { stroke: var(--accent); } -.brand-mark .mark-label { fill: var(--accent-2); } +/* Case in the label's navy, label band in brand red — the same two-tone + relationship a real slab label has, and it keeps the mark legible + against a white bar where an all-red mark would shout. */ +.brand-mark .mark-case { stroke: var(--accent-2); } +.brand-mark .mark-label { fill: var(--brand); } /* .48, not the .34 this started at — below roughly .45 the card window stops separating from the case interior at topbar size and the mark collapses into an empty outline. Checked by rendering it at 42px. */ -.brand-mark .mark-card { fill: var(--accent); opacity: .48; } +.brand-mark .mark-card { fill: var(--accent-2); opacity: .48; } .topbar-actions { display: flex; gap: 9px; flex-wrap: wrap; } @@ -170,15 +176,15 @@ main { .btn { font: inherit; font-weight: 600; font-size: 14.5px; padding: 9px 17px; border-radius: 9px; cursor: pointer; - background: var(--accent); - color: #04121f; + background: var(--brand); + color: #fff; border: 1px solid transparent; text-decoration: none; display: inline-block; line-height: 1.4; white-space: nowrap; - box-shadow: 0 1px 2px rgba(0, 0, 0, .35); + box-shadow: var(--shadow-sm); transition: filter .13s ease, transform .13s ease, background .13s ease; } -.btn:hover { filter: brightness(1.08); } +.btn:hover { background: var(--brand-dark); filter: none; } .btn:active { transform: translateY(1px); } .btn[disabled] { opacity: .45; cursor: default; filter: none; box-shadow: none; } .btn:focus-visible, .close:focus-visible { @@ -186,10 +192,10 @@ main { } .btn-quiet { - background: var(--surface-2); color: var(--ink); + background: var(--surface-1); color: var(--ink); border-color: var(--rule); box-shadow: var(--shadow-sm); } -.btn-quiet:hover { background: #1a2439; filter: none; } +.btn-quiet:hover { background: var(--surface-2); filter: none; } .btn-danger { background: transparent; color: var(--critical); @@ -205,7 +211,7 @@ main { padding: 9px 12px; border: 1px solid var(--rule); border-radius: 10px; - background: #0a1120; + background: var(--surface-1); color: var(--ink); width: 100%; transition: border-color .13s ease, box-shadow .13s ease; @@ -213,8 +219,8 @@ main { .input::placeholder, textarea::placeholder { color: var(--muted); } .input:focus, select:focus, textarea:focus { outline: none; - border-color: var(--accent); - box-shadow: 0 0 0 3px var(--accent-soft); + border-color: var(--brand); + box-shadow: 0 0 0 3px var(--brand-soft); } textarea { resize: vertical; min-height: 64px; } @@ -227,11 +233,12 @@ textarea { resize: vertical; min-height: 64px; } /* -------------------------------------------------------------- panels */ +/* The dark theme lit each panel with a top white-gradient highlight; on a + white surface that's invisible, so panels separate from the ground by + border and shadow instead. */ .panel { position: relative; - background: - linear-gradient(180deg, rgba(255, 255, 255, .035), transparent 120px), - var(--surface-1); + background: var(--surface-1); border: 1px solid var(--hairline); border-radius: var(--radius-lg); padding: 22px 24px 24px; @@ -277,7 +284,7 @@ textarea { resize: vertical; min-height: 64px; } .cardcell img, .cardcell .thumb-blank { width: 46px; height: 64px; object-fit: cover; border-radius: 6px; background: var(--surface-2); flex: none; - box-shadow: 0 2px 8px rgba(0, 0, 0, .55), inset 0 0 0 1px rgba(255, 255, 255, .07); + box-shadow: 0 1px 3px rgba(16, 20, 28, .18), inset 0 0 0 1px rgba(16, 20, 28, .08); } .thumb-blank { display: inline-block; @@ -345,7 +352,7 @@ textarea { resize: vertical; min-height: 64px; } .scrim { position: fixed; inset: 0; z-index: 30; - background: rgba(3, 5, 10, .68); + background: rgba(16, 20, 28, .42); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); } @@ -354,9 +361,7 @@ textarea { resize: vertical; min-height: 64px; } top: 50%; left: 50%; transform: translate(-50%, -50%); width: min(600px, calc(100vw - 28px)); max-height: min(88vh, 940px); overflow-y: auto; - background: - linear-gradient(180deg, rgba(255, 255, 255, .04), transparent 140px), - var(--surface-1); + background: var(--surface-1); border: 1px solid var(--rule); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); @@ -399,7 +404,9 @@ textarea { resize: vertical; min-height: 64px; } .note { font-size: 13px; line-height: 1.55; color: var(--ink-2); background: var(--surface-2); border: 1px solid var(--hairline); - border-left: 3px solid var(--accent); + /* Navy, not the brand red: this box is instruction, and now that red is + the brand colour an informational red bar would read as an alert. */ + border-left: 3px solid var(--accent-2); border-radius: 8px; padding: 12px 14px; margin-top: 14px; } .note-warn { border-left-color: var(--warning); } @@ -413,13 +420,15 @@ textarea { resize: vertical; min-height: 64px; } .banner { padding: 12px 24px; font-size: 13.5px; - background: color-mix(in srgb, var(--accent) 22%, var(--ground)); + background: var(--brand-soft); color: var(--ink); - border-bottom: 1px solid var(--hairline); + border-bottom: 1px solid var(--rule); + box-shadow: inset 3px 0 0 var(--brand); } .banner.err { - background: color-mix(in srgb, var(--critical) 82%, #000); + background: var(--critical); color: #fff; + box-shadow: none; } .banner ul { margin: 5px 0 0; padding-left: 18px; }