:root { --bg: #f6f5f1; --surface: #ffffff; --surface-2: #f0eee8; --border: #dedad0; --text: #1f1d27; --text-muted: #625e6e; --accent: #5b3fd0; --accent-hover: #4a30b5; --accent-soft: #ece8fc; --on-accent: #ffffff; --focus: #5b3fd0; --warn-bg: #fdf5e2; --warn-border: #ecd59a; --warn-text: #6b4e0a; --error-bg: #fdecea; --error-border: #f0bcb6; --error-text: #8a1f14; /* card-source markers */ --src-input: #8c8799; --src-synergy: #5b3fd0; --src-staple: #c07a12; --src-basic: #3d8a5c; /* mana */ --mana-W: #f3ecd2; --mana-U: #a9d3ee; --mana-B: #8e8288; --mana-R: #f1a488; --mana-G: #9bd0ae; --mana-C: #d8d4cc; --mana-ink: #1f1d27; --radius: 10px; --shadow: 0 1px 2px rgb(20 16 40 / 6%), 0 4px 16px rgb(20 16 40 / 6%); color-scheme: light; font-family: Inter, ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; font-size: 15px; line-height: 1.5; color: var(--text); background: var(--bg); -webkit-font-smoothing: antialiased; } @media (prefers-color-scheme: dark) { :root { --bg: #15141b; --surface: #1e1c26; --surface-2: #272431; --border: #363243; --text: #ece9f2; --text-muted: #a39eb2; --accent: #9d86ff; --accent-hover: #b3a0ff; --accent-soft: #2d2648; --on-accent: #15141b; --focus: #b3a0ff; --warn-bg: #2e2612; --warn-border: #5c4a1c; --warn-text: #f0d48f; --error-bg: #34181a; --error-border: #6a2b2c; --error-text: #ffb4ab; --src-input: #8a8499; --src-synergy: #9d86ff; --src-staple: #e0a040; --src-basic: #62b784; --shadow: 0 1px 2px rgb(0 0 0 / 30%), 0 4px 16px rgb(0 0 0 / 25%); color-scheme: dark; } } * { box-sizing: border-box; } body { margin: 0; background: var(--bg); color: var(--text); } a { color: var(--accent); } :focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; } h1, h2, h3 { line-height: 1.2; margin: 0; } /* ---------- layout ---------- */ /* Full-height column so a short page's footer sits at the bottom of the window. */ .app { max-width: 1440px; margin: 0 auto; padding: 28px 24px 0; min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; } .site-header { margin-bottom: 20px; } .site-header h1 { font-size: 1.75rem; letter-spacing: -0.01em; } .site-header p { margin: 6px 0 0; color: var(--text-muted); max-width: 62ch; } .layout { margin-bottom: 28px; display: grid; grid-template-columns: minmax(320px, 400px) minmax(0, 1fr); gap: 20px; align-items: start; } .panel { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); } .input-panel { padding: 20px; display: flex; flex-direction: column; gap: 14px; position: sticky; top: 16px; } .results-panel { padding: 20px 24px; min-height: 480px; } /* Below the content, or at the bottom of the window when the content is shorter than the window: margin-top: auto takes up the leftover height of the full-height .app column. */ .site-footer { margin-top: auto; padding: 10px 0 16px; color: var(--text-muted); font-size: 0.85rem; } @media (max-width: 960px) { .app { padding: 20px 16px 0; } .layout { margin-bottom: 20px; } .site-footer { font-size: 0.78rem; padding: 8px 0; } .layout { grid-template-columns: minmax(0, 1fr); } .input-panel { position: static; } .results-panel { padding: 16px; min-height: 0; } } /* ---------- form ---------- */ .field { display: flex; flex-direction: column; gap: 6px; } .field label, .label-row label { font-weight: 600; font-size: 0.9rem; } .label-row { display: flex; justify-content: space-between; align-items: baseline; } .hint { color: var(--text-muted); font-size: 0.82rem; margin: 0; } input[type='text'], input[type='number'], textarea { font: inherit; color: var(--text); background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 9px 11px; width: 100%; } input[aria-invalid='true'] { border-color: var(--error-text); } textarea { resize: vertical; min-height: 180px; font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-size: 0.85rem; line-height: 1.55; } ::placeholder { color: var(--text-muted); opacity: 0.8; } .partner { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; } .partner .field { width: 100%; } .options { border-top: 1px solid var(--border); padding-top: 10px; } .options summary { cursor: pointer; font-weight: 600; font-size: 0.9rem; } .options[open] > * + * { margin-top: 10px; } .field-inline { flex-direction: row; align-items: center; justify-content: space-between; } .field-inline input { width: 96px; } .toggle { display: flex; align-items: center; gap: 8px; font-size: 0.9rem; cursor: pointer; } .toggle input { accent-color: var(--accent); width: 16px; height: 16px; } /* ---------- buttons ---------- */ .btn { font: inherit; font-weight: 600; font-size: 0.9rem; border-radius: 8px; padding: 8px 14px; border: 1px solid transparent; cursor: pointer; white-space: nowrap; } .btn:disabled { opacity: 0.6; cursor: progress; } .btn-primary { background: var(--accent); color: var(--on-accent); } .btn-primary:hover:not(:disabled) { background: var(--accent-hover); } .btn-secondary { background: var(--surface); border-color: var(--border); color: var(--text); } .btn-secondary:hover:not(:disabled) { background: var(--surface-2); } .btn-link { background: none; border: none; padding: 2px 0; color: var(--accent); font-weight: 500; align-self: flex-start; } .btn-link:hover { text-decoration: underline; } .btn-block { width: 100%; padding: 11px 14px; font-size: 1rem; } .chip { font: inherit; font-size: 0.82rem; background: var(--surface); border: 1px solid var(--border); color: var(--text); border-radius: 999px; padding: 2px 10px; cursor: pointer; } .chip:hover { border-color: var(--accent); color: var(--accent); } /* ---------- combobox ---------- */ .combobox { position: relative; } .combobox-list { position: absolute; top: 100%; left: 0; right: 0; z-index: 20; margin: 4px 0 0; padding: 4px; list-style: none; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; box-shadow: var(--shadow); max-height: 320px; overflow-y: auto; } .combobox-list li { padding: 7px 9px; border-radius: 6px; cursor: pointer; display: flex; flex-direction: column; gap: 2px; } .combobox-list li.active { background: var(--accent-soft); } .option-name { font-weight: 500; display: flex; gap: 6px; align-items: center; } .option-meta { display: flex; gap: 8px; align-items: center; color: var(--text-muted); font-size: 0.8rem; } .option-type { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* ---------- notices ---------- */ .notice { border-radius: 8px; padding: 10px 12px; font-size: 0.88rem; margin: 0; } .notice p { margin: 0; font-weight: 600; } .notice-warn { background: var(--warn-bg); border: 1px solid var(--warn-border); color: var(--warn-text); list-style: none; display: flex; flex-direction: column; gap: 2px; margin-bottom: 14px; } .notice-error { background: var(--error-bg); border: 1px solid var(--error-border); color: var(--error-text); } .unresolved { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; } .unresolved li { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; } .unresolved-name { font-weight: 600; display: flex; gap: 8px; align-items: baseline; } .line-no { font-weight: 500; font-size: 0.78rem; opacity: 0.8; } .suggestions { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; } .notice-error .btn-link { color: var(--error-text); font-size: 0.82rem; } /* ---------- empty state ---------- */ .empty { min-height: 420px; display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; color: var(--text-muted); gap: 12px; } .empty h2 { color: var(--text); font-size: 1.2rem; } .steps { text-align: left; max-width: 46ch; margin: 0; padding-left: 1.2em; display: flex; flex-direction: column; gap: 6px; } .spinner { width: 28px; height: 28px; border: 3px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.8s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } .is-stale { opacity: 0.55; transition: opacity 0.15s; pointer-events: none; } @media (max-width: 960px) { .empty { min-height: 0; padding: 12px 0; } } /* ---------- deck ---------- */ .deck-header { display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; align-items: flex-start; margin-bottom: 14px; } .deck-header h2 { font-size: 1.3rem; } .deck-stats { display: flex; gap: 14px; margin: 6px 0 0; color: var(--text-muted); font-size: 0.9rem; } .deck-stats strong { color: var(--text); font-variant-numeric: tabular-nums; } .deck-actions { display: flex; gap: 8px; flex-wrap: wrap; } .deck-toolbar { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px 20px; padding: 10px 0; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); margin-bottom: 14px; } .legend { display: flex; flex-wrap: wrap; gap: 6px 16px; list-style: none; margin: 0; padding: 0; font-size: 0.85rem; color: var(--text-muted); } .legend li { display: flex; align-items: center; gap: 6px; } .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; } .dot-input { background: var(--src-input); } .dot-synergy { background: var(--src-synergy); } .dot-staple { background: var(--src-staple); } .dot-basic { background: var(--src-basic); } .commander-row { display: flex; flex-wrap: wrap; gap: 4px 24px; margin-bottom: 14px; } .commander-row .card-row { font-weight: 600; min-width: 0; max-width: 100%; } .groups { columns: 3 260px; column-gap: 28px; } .group { break-inside: avoid; margin-bottom: 18px; } .group h3 { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); padding-bottom: 4px; border-bottom: 1px solid var(--border); margin-bottom: 4px; } .group h3 .count { font-variant-numeric: tabular-nums; margin-left: 4px; color: var(--text); } .group ul { list-style: none; margin: 0; padding: 0; } .card-row { display: flex; align-items: center; gap: 8px; padding: 3px 0; min-height: 28px; font-size: 0.9rem; } .qty { font-variant-numeric: tabular-nums; color: var(--text-muted); min-width: 1.2em; text-align: right; } .card-name { color: var(--text); text-decoration: none; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .card-name:hover { color: var(--accent); text-decoration: underline; } .source-input .card-name { color: var(--text-muted); } .commander-row .card-name { color: var(--text); flex: 0 1 auto; /* natural width, but shrinks (with ellipsis) on narrow screens */ } .tag { font-size: 0.7rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; padding: 1px 6px; border-radius: 4px; background: var(--accent-soft); color: var(--accent); } .tag-warn { background: var(--warn-bg); color: var(--warn-text); } /* Outlined, not filled like .tag/.tag-warn -- this flags a secondary fact about the card (it's also a staple) alongside its primary source dot, not a replacement for it. */ /* ---------- mana symbols ---------- */ .mana-cost { display: inline-flex; gap: 2px; align-items: center; flex: none; } .mana-face { display: inline-flex; gap: 2px; align-items: center; } .mana-sep { color: var(--text-muted); font-size: 0.75rem; margin: 0 2px; } .pip { width: 15px; height: 15px; border-radius: 50%; display: inline-grid; place-items: center; font-size: 0.64rem; font-weight: 700; color: var(--mana-ink); box-shadow: inset 0 0 0 1px rgb(0 0 0 / 18%); } .pip-W { background: var(--mana-W); } .pip-U { background: var(--mana-U); } .pip-B { background: var(--mana-B); } .pip-R { background: var(--mana-R); } .pip-G { background: var(--mana-G); } .pip-C { background: var(--mana-C); } .pip-W.pip-hybrid-U { background: linear-gradient(135deg, var(--mana-W) 50%, var(--mana-U) 50%); } .pip-W.pip-hybrid-B { background: linear-gradient(135deg, var(--mana-W) 50%, var(--mana-B) 50%); } .pip-W.pip-hybrid-R { background: linear-gradient(135deg, var(--mana-W) 50%, var(--mana-R) 50%); } .pip-W.pip-hybrid-G { background: linear-gradient(135deg, var(--mana-W) 50%, var(--mana-G) 50%); } .pip-U.pip-hybrid-B { background: linear-gradient(135deg, var(--mana-U) 50%, var(--mana-B) 50%); } .pip-U.pip-hybrid-R { background: linear-gradient(135deg, var(--mana-U) 50%, var(--mana-R) 50%); } .pip-U.pip-hybrid-G { background: linear-gradient(135deg, var(--mana-U) 50%, var(--mana-G) 50%); } .pip-B.pip-hybrid-R { background: linear-gradient(135deg, var(--mana-B) 50%, var(--mana-R) 50%); } .pip-B.pip-hybrid-G { background: linear-gradient(135deg, var(--mana-B) 50%, var(--mana-G) 50%); } .pip-R.pip-hybrid-G { background: linear-gradient(135deg, var(--mana-R) 50%, var(--mana-G) 50%); } /* ---------- card text preview ---------- */ .card-preview { position: fixed; z-index: 50; pointer-events: none; max-height: 70vh; overflow: hidden; padding: 12px 14px; border-radius: 10px; border: 1px solid var(--border); background: var(--surface); box-shadow: 0 8px 30px rgb(0 0 0 / 22%); font-size: 0.85rem; line-height: 1.45; } .preview-face + .preview-face { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); } .preview-title { display: flex; justify-content: space-between; align-items: center; gap: 8px; font-weight: 600; } .preview-type { color: var(--text-muted); font-size: 0.8rem; margin: 2px 0 6px; } .card-preview p { margin: 0 0 6px; } .preview-price { margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--border); color: var(--text-muted); font-size: 0.8rem; } .preview-price strong { color: var(--text); } .preview-stats { text-align: right; font-weight: 700; font-variant-numeric: tabular-nums; margin-top: 4px; } .card-preview p:last-child { margin-bottom: 0; } .card-preview p .pip { width: 14px; height: 14px; vertical-align: -2px; margin: 0 1px; } @media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 2s; } } /* ---------- lock & ban ---------- */ .toolbar-right { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 18px; } .lock-status { font-size: 0.85rem; color: var(--text-muted); } .lock-status .btn-link { font-size: 0.85rem; } .row-actions { display: inline-flex; gap: 2px; flex: none; } .icon-btn { display: inline-grid; place-items: center; width: 24px; height: 24px; padding: 0; border: 1px solid transparent; border-radius: 6px; background: none; color: var(--text-muted); cursor: pointer; } .icon-btn:hover:not(:disabled) { background: var(--surface-2); color: var(--text); } .icon-btn:disabled { cursor: default; opacity: 0.45; } .lock-btn.is-on { color: var(--accent); opacity: 1; } .lock-mark { display: none; color: var(--accent); flex: none; } /* Pointer devices: actions float over the row's right edge on hover/focus (so they never squeeze card names), and a lock mark shows next to the name instead. Touch devices keep the actions in the row. */ @media (hover: hover) and (pointer: fine) { .card-row { position: relative; } .row-actions { display: none; position: absolute; right: 0; top: 0; bottom: 0; align-items: center; padding-left: 12px; background: linear-gradient(to right, transparent, var(--surface) 12px); } .card-row:hover .row-actions, .card-row:focus-within .row-actions { display: inline-flex; } .lock-mark { display: inline-flex; } } .card-row.is-locked .card-name { font-weight: 600; } .card-row.is-new { animation: flash-new 2.5s ease-out; border-radius: 6px; } @keyframes flash-new { 0%, 30% { background: var(--accent-soft); } 100% { background: transparent; } } @media (prefers-reduced-motion: reduce) { .card-row.is-new { animation: none; background: var(--accent-soft); } } /* ---------- ban list ---------- */ .ban-list .field label { font-weight: 500; font-size: 0.85rem; } .count-badge { display: inline-block; margin-left: 8px; padding: 0 7px; border-radius: 999px; background: var(--surface-2); color: var(--text-muted); font-size: 0.78rem; font-weight: 600; } .ban-add { display: flex; align-items: flex-end; gap: 8px; } .ban-add .combobox { flex: 1; min-width: 0; } .ban-add .btn { padding: 9px 14px; } .ban-message { color: var(--warn-text); } .ban-items { list-style: none; margin: 0; padding: 0; max-height: 260px; overflow-y: auto; border: 1px solid var(--border); border-radius: 8px; } .ban-items li { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 4px 6px 4px 10px; font-size: 0.88rem; } .ban-items li + li { border-top: 1px solid var(--border); } .ban-item-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); text-decoration: none; } .ban-item-name:hover { color: var(--accent); text-decoration: underline; } .ban-items .icon-btn { flex: none; font-size: 1.05rem; line-height: 1; } .ban-items .icon-btn:hover { color: var(--error-text); } .ban-btn:hover:not(:disabled), .ban-btn.is-on { color: var(--error-text); } .card-row.is-banned .card-name { color: var(--text-muted); text-decoration: line-through; } .ban-mark { color: var(--error-text); } .status-sep { margin: 0 8px; opacity: 0.5; } /* ---------- prices ---------- */ .price { flex: none; width: 4.4em; /* fits "$1,630" / "$29.76" */ text-align: right; font-size: 0.78rem; font-variant-numeric: tabular-nums; color: var(--text-muted); } .price-high { color: var(--text); font-weight: 600; } /* ---------- export menu ---------- */ .menu-wrap { position: relative; } .menu { position: absolute; right: 0; top: calc(100% + 4px); z-index: 30; width: max-content; min-width: 240px; max-width: min(320px, calc(100vw - 32px)); margin: 0; padding: 4px; list-style: none; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; box-shadow: var(--shadow); } .menu-item { display: flex; flex-direction: column; gap: 1px; width: 100%; padding: 7px 10px; border: none; border-radius: 6px; background: none; color: var(--text); font: inherit; text-align: left; cursor: pointer; } .menu-item:hover, .menu-item:focus-visible { background: var(--accent-soft); outline: none; } .menu-item-label { font-weight: 600; font-size: 0.9rem; } .menu-item-hint { color: var(--text-muted); font-size: 0.78rem; } .visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } /* Hand-editing the deck */ .add-card { margin: 4px 0 10px; } .add-card-row { display: flex; align-items: flex-end; gap: 8px; max-width: 460px; } .add-card-row .combobox { flex: 1; min-width: 0; } .add-card-row .btn { padding: 9px 14px; } .add-card-message { min-height: 1.2em; margin: 4px 0 0; } .deck-size-hint { margin: 4px 0 0; color: var(--warn-text); font-size: 0.88rem; } .remove-btn, .qty-btn { font-size: 1.05rem; line-height: 1; } .remove-btn:hover:not(:disabled) { color: var(--error-text); }