Add a Card Search tab and fix horizontal-card (Battle/Plane) preview orientation
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>
This commit is contained in:
@@ -1481,10 +1481,17 @@ tbody tr:hover {
|
||||
behind the dialog it's in. */
|
||||
z-index: 450;
|
||||
border-radius: 14px;
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow-lg);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
pointer-events: none;
|
||||
}
|
||||
.hover-card-img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.preview-modal-backdrop {
|
||||
position: fixed;
|
||||
@@ -1527,6 +1534,29 @@ tbody tr:hover {
|
||||
.preview-modal-img.active {
|
||||
display: block;
|
||||
}
|
||||
/* Horizontal cards (Battles/Planes/Phenomena, see `CardRef.horizontal`): the
|
||||
stored image is portrait-shaped with the content itself rotated. The
|
||||
wrapper's width/height (landscape) and the inner img's width/height
|
||||
(the same box transposed, pre-rotation) are computed in JS —
|
||||
`useRotatedPreviewBox` — and passed in as inline styles; this just
|
||||
positions/rotates the img to fill the wrapper exactly. */
|
||||
.preview-modal-img-rotated {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
/* Override `.preview-modal-img`'s portrait-oriented max-width/max-height —
|
||||
they'd otherwise clamp this wrapper's JS-computed (correctly landscape)
|
||||
inline width/height down, while the un-clamped rotated img inside stays
|
||||
at its full computed size and overflows, getting cut off by the
|
||||
`overflow: hidden` above instead of shrinking to fit. */
|
||||
max-width: none;
|
||||
max-height: none;
|
||||
}
|
||||
.preview-modal-rotate-img {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%) rotate(90deg);
|
||||
}
|
||||
/* Wide enough to show a double-faced card's front and back side by side —
|
||||
no flip needed. */
|
||||
@media (min-width: 860px) {
|
||||
@@ -1538,6 +1568,14 @@ tbody tr:hover {
|
||||
display: block;
|
||||
max-width: min(430px, 43vw);
|
||||
}
|
||||
/* A horizontal front face (e.g. a transformed Battle) shown side-by-side
|
||||
with its back face: keep using the JS-computed inline width/height
|
||||
(see `.preview-modal-img-rotated` above) rather than the narrower DFC
|
||||
column width, which would clamp the wrapper and crop the rotated image
|
||||
the same way the base max-width/max-height would. */
|
||||
.preview-modal-dfc .preview-modal-img-rotated {
|
||||
max-width: none;
|
||||
}
|
||||
.preview-modal-dfc .preview-modal-flip {
|
||||
display: none;
|
||||
}
|
||||
@@ -1707,6 +1745,16 @@ tbody tr:hover {
|
||||
font-size: 13px;
|
||||
color: var(--muted);
|
||||
}
|
||||
.sort-dir-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
padding: 0;
|
||||
font-size: 15px;
|
||||
}
|
||||
.view-toggle {
|
||||
display: inline-flex;
|
||||
background: var(--bg-input);
|
||||
|
||||
Reference in New Issue
Block a user