/* Card Grader — neutral theme, card-type agnostic (Pokemon, sports, TCG). 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. - Light and dark are separately selected steps, not an inverted flip. */ :root { color-scheme: light; --surface-1: #ffffff; --plane: #eef2fa; --ink: #101828; --ink-2: #475467; --muted: #7a8699; --hairline: #dfe6f2; --rule: #c3cede; --accent: #2f6fd0; --accent-2: #35c6a8; /* mark accent — fills only, never text on light */ --accent-soft: #dbe8fc; --good: #10a44a; --good-text: #077a35; --warning: #e8912f; --critical: #d63a3a; --header-1: #16224a; --header-2: #24407e; --header-3: #2f6fd0; --ring: rgba(16, 24, 40, .10); --shadow: 0 1px 2px rgba(16,24,40,.06), 0 8px 24px rgba(16,24,40,.10); --radius: 13px; } @media (prefers-color-scheme: dark) { :root:where(:not([data-theme="light"])) { color-scheme: dark; --surface-1: #141c2f; --plane: #0a0f1c; --ink: #ffffff; --ink-2: #b6c2d6; --muted: #8592a8; --hairline: #253150; --rule: #35446a; --accent: #4b8ee8; --accent-2: #45dcbb; --accent-soft: #1d3a66; --good: #22c55e; --good-text: #34d36a; --warning: #ffa64d; --critical: #ef5350; --header-1: #0d1530; --header-2: #17285a; --header-3: #1f4488; --ring: rgba(255,255,255,.12); --shadow: 0 1px 2px rgba(0,0,0,.45), 0 8px 28px rgba(0,0,0,.55); } } * { box-sizing: border-box; } body { margin: 0; background-color: var(--plane); background-image: radial-gradient(circle at 1px 1px, var(--hairline) 1px, transparent 0); background-size: 22px 22px; color: var(--ink); font: 15px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif; -webkit-font-smoothing: antialiased; } h1, h2, h3 { margin: 0; font-weight: 600; } h1 { font-size: 16px; letter-spacing: -.01em; } h2 { font-size: 15px; } h3 { font-size: 13px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); font-weight: 600; } main { max-width: 900px; margin: 0 auto; padding: 20px 24px 80px; display: flex; flex-direction: column; gap: 20px; } /* ------------------------------------------------------------- topbar */ .topbar { position: sticky; top: 0; z-index: 20; display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; padding: 13px 24px; background: linear-gradient(100deg, var(--header-1), var(--header-2) 55%, var(--header-3)); color: #fff; /* Holo-foil edge: the rainbow sweep you get tilting a refractor. Purely decorative and it encodes nothing, so it's free to be vivid here where no number lives. */ border-bottom: 3px solid transparent; border-image: linear-gradient(90deg, #ff5f8f, #ffb347, #ffe66d, #35c6a8, #4b8ee8, #a97bff, #ff5f8f) 1; } .topbar h1 { color: #fff; letter-spacing: .01em; } .topbar .btn { background: var(--accent-2); color: #06231d; border-color: transparent; font-weight: 600; } .topbar .btn:hover { filter: brightness(1.06); } .topbar .btn-quiet { background: rgba(255,255,255,.14); color: #fff; border-color: rgba(255,255,255,.38); font-weight: 500; } .topbar .btn-quiet:hover { background: rgba(255,255,255,.26); filter: none; } .brand { display: flex; align-items: center; gap: 11px; } /* Brand mark: a graded slab, drawn in plain CSS. A rounded card outline with a corner clipped and a check — "this one's been looked at" — rather than any single game's iconography, since this grades anything PSA does. */ .brand-mark { position: relative; flex: none; width: 26px; height: 26px; border-radius: 6px; background: linear-gradient(160deg, var(--accent-2), var(--accent)); box-shadow: inset 0 0 0 1.5px rgba(255,255,255,.4), 0 1px 4px rgba(0,0,0,.35); } .brand-mark::after { content: ''; position: absolute; left: 6px; top: 6px; width: 8px; height: 5px; border-left: 2px solid #06231d; border-bottom: 2px solid #06231d; transform: rotate(-45deg); } .topbar-actions { display: flex; gap: 8px; flex-wrap: wrap; } /* ------------------------------------------------------------ controls */ .btn { font: inherit; font-weight: 500; font-size: 14px; padding: 7px 14px; border-radius: 8px; cursor: pointer; background: var(--accent); color: #fff; border: 1px solid transparent; text-decoration: none; display: inline-block; line-height: 1.4; white-space: nowrap; } .btn:hover { filter: brightness(1.07); } .btn:active { transform: translateY(.5px); } .btn[disabled] { opacity: .5; cursor: default; filter: none; } .btn-quiet { background: var(--surface-1); color: var(--ink); border-color: var(--rule); } .btn-quiet:hover { background: var(--plane); filter: none; } .btn-danger { background: transparent; color: var(--critical); border-color: var(--critical); } .btn-danger:hover { background: var(--critical); color: #fff; filter: none; } .btn-sm { padding: 4px 10px; font-size: 13px; } .input, select, textarea { font: inherit; font-size: 14px; padding: 7px 10px; border: 1px solid var(--rule); border-radius: 8px; background: var(--surface-1); color: var(--ink); width: 100%; } .input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: -1px; border-color: transparent; } textarea { resize: vertical; min-height: 60px; } /* --------------------------------------------------------------- tiles */ .tile-value { font-size: 25px; font-weight: 700; letter-spacing: -.02em; } .tile-sub { font-size: 12px; color: var(--ink-2); margin-top: 4px; } .pos { color: var(--good-text); } .neg { color: var(--critical); } /* -------------------------------------------------------------- panels */ .panel { background: var(--surface-1); border: 1px solid var(--hairline); border-radius: var(--radius); padding: 16px 18px 18px; box-shadow: 0 1px 2px rgba(16,24,40,.04); } .panel-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; } .hint { font-size: 13px; color: var(--muted); } .search-status { margin-top: 10px; font-size: 13px; color: var(--ink-2); } /* --------------------------------------------------------------- table */ .table-scroll { overflow-x: auto; } .grid { width: 100%; border-collapse: collapse; font-size: 14px; } .grid th { text-align: left; font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); padding: 8px 10px; border-bottom: 1px solid var(--rule); white-space: nowrap; } .grid td { padding: 9px 10px; border-bottom: 1px solid var(--hairline); vertical-align: middle; } .grid tbody tr:hover { background: var(--accent-soft); } .num { text-align: right; font-variant-numeric: tabular-nums; } .cardcell { display: flex; align-items: center; gap: 10px; } .cardcell img, .cardcell .thumb-blank { width: 40px; height: 56px; object-fit: cover; border-radius: 4px; background: var(--plane); flex: none; } .thumb-blank { display: inline-block; border: 1px dashed var(--rule); background: repeating-linear-gradient(135deg, transparent 0 5px, var(--hairline) 5px 6px), var(--plane); } .cardcell-name { font-weight: 600; line-height: 1.25; } .cardcell-meta { font-size: 12px; color: var(--muted); } .dash { color: var(--muted); } /* --------------------------------------------------------------- pills */ .pill { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; padding: 3.5px 10px; border-radius: 99px; border: 1px solid var(--rule); color: var(--ink-2); white-space: nowrap; } .pill-grade { border-color: var(--good); color: var(--good-text); background: color-mix(in srgb, var(--good) 12%, transparent); } .pill-marginal { border-color: var(--warning); background: color-mix(in srgb, var(--warning) 14%, transparent); } .pill-raw { border-color: var(--rule); color: var(--muted); } .pill-critical { border-color: var(--critical); color: var(--critical); background: color-mix(in srgb, var(--critical) 12%, transparent); } .empty { text-align: center; color: var(--muted); padding: 28px 0 8px; font-size: 14px; } /* -------------------------------------------------------------- modal */ .scrim { position: fixed; inset: 0; z-index: 30; background: rgba(11,11,11,.32); } .modal { position: fixed; z-index: 40; top: 50%; left: 50%; transform: translate(-50%, -50%); width: min(560px, calc(100vw - 32px)); max-height: min(86vh, 900px); overflow-y: auto; background: var(--surface-1); border: 1px solid var(--hairline); border-radius: 14px; box-shadow: var(--shadow); padding: 20px 22px; } .close { background: none; border: none; cursor: pointer; font-size: 22px; color: var(--muted); line-height: 1; padding: 0 4px; } .close:hover { color: var(--ink); } .section { margin-bottom: 20px; } .section > h3 { margin-bottom: 10px; } .fields { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } .field { display: flex; flex-direction: column; gap: 4px; } .field.wide { grid-column: 1 / -1; } .field label { font-size: 12px; color: var(--ink-2); } .suffix { display: block; font-size: 11.5px; line-height: 1.45; color: var(--muted); } .drawer-actions { display: flex; gap: 8px; flex-wrap: wrap; padding-top: 14px; border-top: 1px solid var(--hairline); } .spacer { flex: 1; } .note { font-size: 12.5px; color: var(--ink-2); background: var(--plane); border: 1px solid var(--hairline); border-left: 3px solid var(--warning); border-radius: 6px; padding: 9px 11px; margin-top: 10px; } .note-flag { border-left-color: var(--critical); color: var(--critical); margin-top: 0; margin-bottom: 12px; } /* -------------------------------------------------------------- banner */ .banner { position: sticky; top: 57px; z-index: 15; padding: 10px 24px; font-size: 13.5px; background: var(--accent-soft); color: var(--ink); border-bottom: 1px solid var(--hairline); } .banner.err { background: var(--critical); color: #fff; } .banner ul { margin: 4px 0 0; padding-left: 18px; } /* ---------------------------------------------------------- grade slab */ /* Styled after the label on a graded slab, because that's the thing this whole app is estimating — it makes the number read as a verdict rather than as one more statistic on the page. */ .slab { display: flex; align-items: stretch; gap: 0; border-radius: 10px; overflow: hidden; border: 1px solid var(--rule); background: var(--surface-1); box-shadow: var(--shadow); max-width: 420px; } .slab-main { flex: 1; padding: 12px 14px; display: flex; flex-direction: column; justify-content: center; gap: 2px; } .slab-title { font-size: 13px; font-weight: 700; line-height: 1.25; } .slab-sub { font-size: 11.5px; color: var(--muted); } .slab-grade { flex: none; width: 104px; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 10px 8px; color: #fff; text-align: center; background: linear-gradient(150deg, var(--header-2), var(--header-3)); } .slab-grade .n { font-size: 34px; font-weight: 800; line-height: 1; letter-spacing: -.02em; } .slab-grade .word { font-size: 9.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; opacity: .85; margin-top: 3px; } /* Grade bands. Green for a card worth submitting, amber mid, red low — the same red reserved elsewhere for "distrust this", used here because a low grade is genuinely the bad outcome. */ .slab-10 .slab-grade, .slab-9 .slab-grade { background: linear-gradient(150deg, #0d7a3a, #10a44a); } .slab-8 .slab-grade, .slab-7 .slab-grade { background: linear-gradient(150deg, #1b6fbf, #2f6fd0); } .slab-6 .slab-grade, .slab-5 .slab-grade { background: linear-gradient(150deg, #b4700f, #e8912f); } .slab-low .slab-grade { background: linear-gradient(150deg, #9e2626, #d63a3a); } /* A 10 gets the foil treatment. Deliberately reserved for the top grade so it stays meaningful — every card shimmering would say nothing. */ .slab-10 .slab-grade { background: linear-gradient(140deg, #0d7a3a, #35c6a8 40%, #4b8ee8 70%, #a97bff); } .card-type-tag { display: inline-block; font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; padding: 2px 7px; border-radius: 4px; background: var(--accent-soft); color: var(--accent); border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent); } /* --------------------------------------------------------------- phone */ @media (max-width: 700px) { main { padding: 14px 12px 60px; } .topbar { padding: 10px 12px; } .fields { grid-template-columns: 1fr; } .grid { font-size: 13.5px; } }