The UI had a good terracotta-on-dark system that wasn't applied
consistently — magic-number spacing, ad-hoc page headers, ~6 copied
panel surfaces, ~8 drifting label variants, and scattered accent use.
- Tokens: warm the neutral ramp, add spacing/radius/type/motion scales,
--accent-quiet + panel highlight. Terracotta hue unchanged.
- Primitives: .panel, .section-label, .page-header/.toolbar — collapse
the copied surfaces and label variants onto shared classes.
- Unify each filter-heavy page's display controls (group/sort/view,
select-all, count) into a workspace toolbar inside the filter panel,
so they read as one surface instead of floating above it.
- Labels: sentence-case, higher-contrast form labels; uppercase section
markers bumped faint -> muted.
- Accent hierarchy: reserve full terracotta for primary actions/active
state; demote decorative labels and the group-header underline.
- Responsive groundwork: reflow classes for the deck two-pane and nav
rail (stacks / icon-collapse at breakpoints), touch-target sizing.
Desktop unchanged in kind.
Shows type line, mana value/colors, price, per-format legality pills,
and ownership context (owned copies, decks it's in) when the caller
has that data — LibraryCard/DeckEntry rows do, bare CardRefs don't, so
the section just omits itself when absent.
The info tile sits beside the card art via flex-wrap and drops to its
own line on narrow viewports, rather than shrinking either face to
make room. Also shrinks a double-faced Battle's rotated front face
when it has a sibling back face, so it no longer renders at
full single-card size next to a much smaller back face.
Card previews were picking whichever printing happened to load first
during ingest (ORDER BY rowid over every printing, promos and foreign
versions included), so a card's default image was effectively random.
Capture the representative printing's images straight from the Oracle
Cards bulk pass instead, and prefer that over the old printings-table
guess, falling back gracefully on an older reference.db that predates
these columns.
Also add docs/printing-tracking-design.md, a design (not yet
implemented) for optionally tracking which specific printing/finish a
library or deck card is.
Real Battle cards are layout "transform" (they flip into a creature),
not "battle" as previously assumed — no shipped card actually uses
that layout, so the horizontal flag never got set for them. Detect
Battle orientation from the front face's type line instead.
Card Search browses the whole downloaded card universe (not just owned
cards), reusing the Library tab's filter/group/sort/list/tiles UI; results
show ownership and offer quick "own" and "add to deck" actions.
Battles, Planes, and Phenomena store their Scryfall image portrait-shaped
with the content itself rotated, so hover/click previews now detect this
(a new `horizontal` flag threaded through ingest and every card query, with
graceful fallback for a reference.db built before the column existed) and
rotate the image back into place. Single-faced and non-DFC cases are
verified fixed; a double-faced Battle's front face still needs another pass.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Suggestion scoring is fully offline (tribal/mechanic/archetype/mana-base
signals derived at ingest, no external synergy database), with an "unusual
picks" mode that surfaces underappreciated cards instead of staples. The
deck page's top panels now use a CSS grid so wide windows don't waste
horizontal space. Library's bulk add-to-deck can clobber existing deck
quantities, so it now offers an undo (snackbar + command palette, the
latter with no timeout) that restores each card's prior state exactly.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Threads Scryfall's per-format legalities through the reference db and adds a
deck-page indicator (structural rules + banned/restricted lists) that lists
violation reasons inline. Decks and selected library cards can now be
exported to/imported from plain-text decklists, with best-effort name
resolution and a report of anything that didn't match. Also adds a shuffle-
and-draw sample hand modal, and an Alt+/ command palette for jumping to a
tab, deck, or card without leaving the keyboard.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Prices come from Scryfall's prices.usd on printings, shown as a hover badge
on card tiles. The price is picked independently of whichever printing
supplies the display image (the cheapest known price across all printings),
since the display printing is often a promo/variant with no listed price.
The maybeboard lets a deck track cards under consideration without counting
them in deck analysis stats or library assignment totals. Cards move between
mainboard and maybeboard via a per-card toggle; maybeboarding the commander
clears commander status.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Threads a new produced_mana/produces_colorless field through the whole card
read path (ingest, library, filters, decks, search) so the deck view can
show what colors a deck's manabase actually produces, alongside its existing
color identity. Also adds a mana consumption bar (colored casting costs of
nonland spells) and stacks the mana curve histogram by color. Adds an
oracle-text substring filter to the library search, mirroring the existing
location filter. Rearranges the deck sidebar list into two rows (name, then
format chip + actions) so long names and action buttons no longer collide,
and removes the drop shadows from the commander hero panel/image.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Mirror the Library tab's multi-select: checkboxes on every row/tile,
a "Select all" toggle, and a bulk-action bar with a single "Remove
from deck" action (reuses CardTile's cornerLeft/selected support and
the existing .bulk-bar/.tile-select styling — no new CSS needed).
- Replace the deck table's plain number input (which only committed on
blur) and the tile view's static "in deck ×N" badge with the same
QtyStepper used in the Library tab, so bumping a card's count no
longer means removing it and re-adding it. Decrementing to 0 now
gets the same grace-period undo as the Library tab (dims the row for
5s, + brings it back) instead of deleting it from the deck instantly.
- QtyStepper's `warn` state now flags deck cards you don't own enough
copies of (scoped to cards you own at least one of, so every row in
the already-labeled "Not owned" section doesn't light up too).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Checkboxes on every row/tile plus a "Select all" (filtered-set-aware,
indeterminate-aware) toggle in the toolbar.
- A bulk-action bar appears once anything's selected: add to a deck
("Add 1" sets each selected card to 1 copy, "Add All" sets it to
however many you own — the latter is the one-click fix for bulk-adding
a stack of basic lands), set location, and adjust owned quantity by a
configurable delta. All reuse the same per-card commands the
single-card UI already calls, so behavior stays consistent (including
the existing grace-period undo on quantity_owned hitting 0).
- CardTile gains a `cornerLeft` slot and `selected` prop (ring highlight,
keeps the checkbox visible without hovering) to support this in tile
view without disturbing the existing top-right qty-stepper corner.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- New logomark: an original pirate-ship silhouette (hull, twin billowing
sails, swallow-tail pennant) in the terracotta brand gradient on a dark
square — a nod to the MTG card "Pirate Ship", not a reproduction of its
art. Source at src-tauri/icons/logo-source.svg; regenerate the full
platform icon set (desktop/Windows Store/iOS/Android) with
`cargo tauri icon src-tauri/icons/logo-source.svg`.
- Apply it in-app via a new inline ShipLogo component (App.tsx), replacing
the old "M" sidebar mark and "✦" empty-state mark with dark rounded
squares containing the ship glyph.
- Rename the app to lowercase "mtgc" everywhere: window title and
productName (tauri.conf.json), <title> (index.html), sidebar brand text,
empty-state heading.
- Rename the Tauri package/binary mtgc-app -> mtgc (and its lib crate
mtgc_app_lib -> mtgc_lib), so `cargo tauri build` now produces
target/release/mtgc; updated main.rs and every README reference.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Status gains reference_updated_at (sourced from reference.db's file
mtime, so it needs no separate persisted state) and the sidebar's
"Your library" panel shows it as a relative "Updated Xh ago" stamp
that self-refreshes every minute.
- Add a Location field to the Library tab's filters panel, wired to the
new LibraryFilter.location.
- Bump every font-size in the stylesheet up one step for a slightly
larger, easier-to-read UI overall.
- Fix the library/deck tile view's +/- quantity overlay permanently
covering the card art's own printed mana cost (top-right corner) —
it now only fades in on hover/focus, like the other row actions.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
LibraryFilter.location does a case-insensitive substring match against
the stored location (e.g. "Box 1"), mirroring the existing text filter.
Tested for substring/case-insensitivity and the empty-string no-op case.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- DeckView: rename/duplicate/delete deck via row-hover icon actions, with
a ConfirmDialog for delete and PromptDialog (with friendly name-
collision errors) for rename/duplicate.
- Add a shared IconButton (plus overlay/danger variants) and replace
every ad hoc close/remove button in the app with it: deck actions,
remove-card-from-deck (list and tile), clear-commander, the card-
preview close, and the ingest-progress dismiss.
- Fix native <select> (Group by, Format, In deck): only color/border were
overridden, leaving native OS chrome (height, arrow, popup) in place.
Drop appearance and draw a custom chevron so they match text inputs.
- Click-to-preview: show both faces of a double-faced card side by side
on wide viewports instead of requiring Flip, and size the preview
images larger overall.
- Sidebar footer: replace the plain "N cards" line with a "Your library"
panel (unique/copies/decks tiles + a WUBRG color-distribution bar),
polling get_library_stats while card data is loaded.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New LibraryStats (unique cards owned, total copies, deck count, and
per-color copy counts including colorless) via Catalog::library_stats,
tested against the fixture catalog.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New Catalog::rename_deck / duplicate_deck (duplicating format, commander,
notes, and every deck_cards row under a new name), with tests covering
the UNIQUE(name) collision cases the UI needs to surface as friendly
errors rather than raw SQL messages.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Fix keyboard-nav selection highlight (search results, deck list): the
Discord-styling rewrite dropped the --panel-2 CSS variable it relied
on, so ↑/↓ moved selection but rendered no visible highlight.
- Add click-to-preview: clicking a card thumbnail/tile now opens a
larger centered modal (list and tile views), with a flip button for
double-faced cards' back face. Hover preview is unchanged and clears
when a click-preview opens.
- Add a QtyStepper component (rounded [− N +] pill, with an `overlay`
variant for tile corners) and use it consistently for owned-copy
counts on Add Cards, and the Library list and tile views.
- Add matching +/- steppers to the Library views; decrementing to 0
dims the row for a 5s grace period (still fully interactive) before
it drops out, so an accidental removal can be undone with +.
- Topbar: fill remaining width with the library path (no more premature
truncation), add icons to Open/New Library and Download/Update card
data, and drop the trailing "…" from the library buttons.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Remember which library.db was last chosen (via a small config.json in
the app-data dir) so relaunching the app reopens the same file instead
of always defaulting to library.db.
- Fix set_library_path returning a hard error (and thus never updating
the topbar) whenever the reference catalog fails to reopen against the
new path — e.g. a stale reference.db schema. Picking a library file
and successfully reattaching the reference db are separate concerns;
the chosen path now always persists and is reported back, with the
catalog reopened best-effort.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add a back_image_uri column to printings, populated during ingest from
a card's second card_faces image (only present for transform/MDFC/
reversible cards — split/adventure cards share one combined image and
correctly get ""). Plumb it through CardRef across every query path
(search, library, filters, deck contents) via the same printing row,
using a shared deterministic ORDER BY so front/back always come from
one printing.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Exclude Scryfall Art Series cards (layout "art_series") from ingest —
they aren't playable cards and were polluting search results.
- Replace the coarse per-stage progress text with a byte-accurate,
weighted multi-segment progress bar (Index / Card data / Printings /
Indexing) that fills as one continuous bar instead of swapping per
stage; segment weights are computed from the real download sizes
reported by Scryfall's bulk-data index (the download responses
themselves are chunked with no Content-Length to rely on).
- Add a Cancel button, wired through a new CancelToken checked once per
parsed record so cancellation lands almost instantly.
- Fix a related correctness bug this surfaced: ingest used to delete the
existing reference.db before writing its replacement, so a cancelled
or crashed update left the app with no card database at all. It now
builds into a temp file and only atomically replaces reference.db on
full success.
- Split the topbar's single "Choose library…" action into separate
"Open Library…" (existing file) and "New Library…" (save-dialog for a
new file) buttons.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Lets you quickly correct duplicate-copy counts right after adding a
card, instead of navigating to the Library tab.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Restrict tauri.conf.json bundle targets to deb/rpm so `cargo tauri
build` no longer produces an AppImage (the README's AppImage mentions
were already dropped in the prior commit).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Tauri v2's Linux backend hard-depends on GTK3 + webkit2gtk-4.1; GTK4
support is tracked upstream (tauri#7335, tao#1104, wry#1228) but
unmerged with no ETA. Note this so it isn't re-investigated from
scratch later.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>