/**
 * TransferJet — product cards.
 *
 * Outlined white cards built from two surfaces: a grey band carrying the photo
 * and a white band carrying the text, divided by a rule. In grid the band runs
 * along the top; in list it runs down the left edge and carries the mark as
 * well. On hover a grid card's band darkens while the card lifts, takes a red
 * border and a shadow. A list row has no hover at all.
 *
 * This is a deliberate divergence from speedoptions.no rather than a port that
 * drifted. SpeedTheme's card has no border at all: the grey is the card, and
 * the whole thing goes white on hover. Tried that way, a grid of nine grey
 * grounds read as a slab — it works on the reference because that page carries
 * far less furniture, where ours already has the finder panel, the category
 * tiles and the outlined filter card above the grid.
 *
 * What is kept from the reference is the mechanism, which is smaller than it
 * looks. From SpeedTheme's _am-jet-extend.less:
 *
 *     .product-item .product-image-wrapper { mix-blend-mode: multiply; }
 *     .product-photo-wrapper__shadebackground        { background-color: <grey>; }
 *     .product-photo-wrapper__shadebackground:hover  { background-color: <white>;
 *                                                      transition: background-color 0.3s ease-in-out; }
 *
 * So the grey belongs to the photo panel, not the card, and one property
 * transitions. The 0.3s is taken from there rather than this theme's usual 0.2,
 * because the panel change is the visible part of the gesture and everything
 * else has to match its speed or the hover splits into two events.
 *
 * The direction is reversed from the reference: the band darkens instead of
 * fading to white. Fading to white is a gesture a tile can make because it has
 * a white card to disappear into; a band that reaches the card's edges has no
 * such ground, and going white would just delete the surface.
 */

/* The grey band behind the photo.
 *
   Flush to the card's edges rather than inset within its padding. The card had
   a white margin around a grey box around a white-ground photograph, which is
   three surfaces to say one thing; the card's padding moved into the two bands
   and the middle one went away.

   mix-blend-mode still multiplies the white out of the cut-out shot, so it sits
   on the grey without a box around it — the whole catalogue is cut-out on
   white, which is what makes that safe. It lives on the image rather than here:
   applied to the band it multiplies the band's own grey against the card. */
/* 1.5rem from lg up, matching the lower band's horizontal padding below, so the
   photo and the text start from the same edge. At the widest layout — a 96rem
   container less its own padding, less a 240px sidebar and a 32px gap, three
   columns with a 24px gutter — a card is 389px and the photo box lands at
   341px. */
.tj-product-panel {
    background-color: #fafafa;
    padding: 1.5rem;
}

/* The photo's box is square, so a card's height stops depending on how wide its
   column is. Magento renders the image at a fixed width from view.xml and
   preflight gives it max-width:100% with height:auto, which stops it
   overflowing a narrow column but never upscales it and never centres it —
   filling a square box and containing the image settles both without touching
   view.xml, which is 360x360 already.

   Contained rather than covered: these are parts, and cropping one to fill a
   box is not a thing a parts catalogue may do. */
.tj-photo-box {
    display: block;
    position: relative;
    width: 100%;
    aspect-ratio: 1 / 1;
    /* Never larger than the file behind it. category_page_grid renders at
       360x360, so a box wider than that is asking a 360px raster to cover 525px
       of card — which object-contain will happily do, softly. The cap holds the
       box at 1:1 and centres it; below 360 nothing changes, which is every
       multi-column width.

       Tied to view.xml's category_page_grid. If that size is ever raised — and
       the cards are large enough now that it is worth revisiting — this number
       moves with it. Note that adding etc/view.xml to this theme is what cost
       the entire <media> block once before, so that is a change to make
       carefully, not casually. */
    max-width: 360px;
    margin-inline: auto;
}

.tj-photo-box img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    mix-blend-mode: multiply;
}

/* The card itself carries no padding any more — the bands do, and they need to
   reach its edges. Set through .card's own variables rather than by overriding
   its padding, so the component keeps deciding how padding is applied.

   The card does NOT clip. An earlier version put overflow:hidden here so the
   radius would cut the band's corners, and it cost the photographs their
   sharpness: clipping a rounded corner over content carrying mix-blend-mode
   forces an offscreen composite, which the browser rasterises once at a lower
   resolution. The hover's translateY then promoted the card to its own layer and
   it was re-rasterised properly, so the photo was soft at rest and sharp under
   the pointer — a hover doing something it was never asked to do.

   The bands carry their own corners instead, one rem less the card's border, so
   there is nothing to clip and nothing to composite.

   The stroke moves off gray-300 (#d1d5dc), which is blue-tinted, onto the
   theme's own --color-border (#dfdedd): every other grey on the card is warm,
   and the mismatch is a good part of why a grid of them read as muddy. */
.product-item {
    --card-px: 0;
    --card-py: 0;
    --card-radius: 1rem;
    --card-stroke: var(--color-border);
    /* The bands round themselves to this. Inside the border, so the grey meets
       the stroke along its whole length instead of cutting the corner early. */
    --card-inner-radius: calc(1rem - 1px);
}

/* Grid: the band caps the top, the white band caps the bottom. */
.tj-product-panel {
    border-start-start-radius: var(--card-inner-radius);
    border-start-end-radius: var(--card-inner-radius);
}

.product-item .product-info {
    border-end-start-radius: var(--card-inner-radius);
    border-end-end-radius: var(--card-inner-radius);
}

/* The white band. Spacing inside it is set per element below rather than by a
   flex gap, because the mark, the name and the price each want a different
   amount and a single gap cannot give it to them. */
.product-item .product-info {
    background-color: #fff;
    border-block-start: 1px solid var(--color-border);
    gap: 0;
    padding: 1.25rem 1.5rem 1.5rem;
}

@media (max-width: 1023px) {
    .tj-product-panel {
        padding: 0.75rem;
    }
}

/* Below sm the grid is a single column and the card is the full width of the
   page, so the photograph gets nearly all of it: 0.5rem and 0.625rem leaves a
   309px box in a 327px card at 375. The whole numbers are the point — 0.5rem is
   8px and 0.625rem is 10px, where an intermediate value would land between
   device pixels and soften an edge the photo does not need softened.

   The text keeps its own 1.25rem, so the photo deliberately runs wider than the
   text beneath it. The bands share an edge from lg up, where the card is small
   enough relative to the page for that alignment to read; at full width the
   photo wants the room more than the alignment is worth. */
@media (max-width: 639px) {
    .tj-product-panel {
        padding: 0.5rem 0.625rem;
    }

    .product-item .product-info {
        padding: 1.25rem 1.25rem 1.25rem;
    }
}

/* Hover, only where there is a pointer. Without this guard a tap on a phone
   leaves the card stuck lifted and red-bordered until something else is
   tapped — which is the whole reason one card design works at every width. */
@media (hover: hover) {
    /* The band is not in this list any more, and neither is background-color.
       The hover used to darken the photo band as well, which is the gesture the
       reference makes — but the band carries blended content and its own rounded
       corners, so animating its background put a composited surface into the
       same 0.3s as the card's transform and it could flicker. The lift, the red
       border and the shadow say everything the darkening said, on the card
       itself rather than on the one part of it the compositor is fussy about. */
    .product-item {
        transition-duration: 0.3s;
        transition-property: border-color, box-shadow, transform;
        transition-timing-function: ease-in-out;
    }

    /* Hovered via the li, not the card.
     *
       The card lifts 2px, and a card that moves is a card that can move out
       from under the pointer: near its bottom edge the hover ends, the card
       drops back, the hover resumes, and it oscillates. The li is the grid cell
       and does not move, so the pointer never leaves the thing being hovered
       while the thing being animated slides beneath it.
     *
       The selector is the card's direct parent, whatever it is, rather than li
       specifically: list.phtml wraps cards in <li>, but the cross-sell and
       related blocks use their own templates and need not. Hover propagates to
       ancestors, so hovering the card matches its parent too. */
    :hover > .product-item {
        border-color: var(--color-primary);
        box-shadow: 0 6px 18px rgb(0 0 0 / 0.12);
        /* The lift also raises the card above its neighbours, so the shadow is
           not clipped by the next card's border. */
        transform: translateY(-2px);
    }

}

/* The colour changes still carry the hover for anyone who has asked for less
   movement; only the lift goes. */
@media (prefers-reduced-motion: reduce) {
    :hover > .product-item {
        transform: none;
    }
}

/* ---------------------------------------------------------------------------
   The name block.

   Left-aligned, and a minimum of two lines so every card reserves the same
   space for its name whether or not it wraps. Without the floor a one-line name
   pulls its price up a line and only the button stays level, so the row reads
   as nine independent cards rather than as a grid.
   --------------------------------------------------------------------------- */

/* Size and leading are the template's text-lg — untouched. The weight is set
   here because the template's font-semibold asked for 600, and this theme ships
   Roboto at 400, 500 and 700 only: 600 was synthesised by the browser, which
   renders differently across engines. There is no 600 to generate either —
   Roboto 2.137 has 100, 300, 400, 500, 700 and 900 and nothing between — so the
   choice is 500 or 700, and 500 left the name reading as body copy. In list it
   sat at the same weight as the description directly beneath it, which is the
   one place the name has to win.

   The two-line floor is gone. It reserved a second line on every card to level
   a wrap that mostly stopped happening once names lost their brand prefix, and
   the price carries the pin now, so there is nothing left for it to level. */
/* The weight goes on the link, not on the block. .tj-product-name is a div and
   the name is the <a class="product-item-link"> inside it; the theme's base sets
   `a { font-weight: var(--link-font-weight) }` at 400, applied to the anchor
   itself, which beats anything inherited from a parent whatever the specificity.
   So a weight set on the div never reached the text — not the 700 tried here,
   and not the template's original font-semibold either. The name has rendered at
   400 from the beginning.

   500 rather than 700. It is a real face, it separates the name from the
   description beneath it in list, and it leaves the price — which the price-box
   sets bolder — as the heaviest thing in the card. 700 would have the name and
   the price arguing over which is the card's subject. */
.tj-product-name {
    margin-block-end: 0.5rem;
    text-align: left;
}

.tj-product-name .product-item-link {
    font-weight: 500;
}

/* The price pins to the bottom and the action follows it, so a row lines up on
   the number it is scanned by. mt-auto was on the actions row before, which
   lined up the buttons and left each card's slack between its own price and its
   own button — the most conspicuous place it could fall. */
.tj-card-price {
    margin-block-start: auto;
    padding-block-start: 0.25rem;
}

/* ---------------------------------------------------------------------------
   The unavailable state.

   A disabled secondary button rather than a line of text: every card then ends
   in the same shape, so a row lines up whether or not something is in stock.

   Identical at every width: the state means the same thing on a phone as on a
   desktop, so it is not softened on one.
   --------------------------------------------------------------------------- */

/* The two states share every dimension through the rule below. Only the surface
   differs here.
 *
   Filled, and nothing outlining it. The border was what made this read as a box
   inside a box: a card is already a frame, and a second one drawn 18px inside it
   on the only element that is not a photograph or a line of text announces
   itself as a component rather than a state. Without it the control is a slab,
   which is what a disabled thing should look like.

   #ebeae9 rather than the band's #fafafa. Against the white band #fafafa is
   1.04:1 — it does not survive being borderless, because the fill is now the
   only thing describing the shape. #ebeae9 is 1.20:1, and it is already in the
   palette as the footer's copyright bar rather than a grey invented for this.
   One step back is #f2f2f2 at 1.12:1, the search pill and the cart's icon-only
   controls, if this now reads heavy.

   The border stays declared at 1px transparent: with box-sizing:border-box a
   bordered control and an unbordered one at the same height differ by 2px
   inside, and Legg i Kurv has one.

   #6b6866 for the label, back from #78716c, which came to 4.29:1 on this fill
   and did not clear 4.5. This is 4.60:1, and it is the grey the finder's
   disabled dropdowns already use.

   700, matching Legg i Kurv: the two are the same control in two states, and a
   lighter weight made the unavailable one look like a caption. */
.tj-product-unavailable {
    background: #ebeae9;
    border-color: transparent;
    color: #6b6866;
    /* Hyvä's .btn already sets this; matching it keeps the two states
       consistent when a card is dragged over or text is selected. */
    user-select: none;
}

/* The price above carries the pin, and the actions row sits directly beneath
   it, so the pair lands at the bottom of the card together. Both states need
   the full width for that to read as one control rather than as something
   floating in the row.
 *
   .product-info is deliberately not in this chain. The template's wrapper is
   `flex flex-wrap items-center`, and where that intermediate element differs the
   wrapper stayed flex: the unavailable span still filled, because width:100%
   comes from its own class, while the button was centred as a flex item and
   picked up an offset from the row. Requiring only .product-item keeps the rule
   inside a card while surviving the markup difference. */
.tj-card-actions {
    display: block;
    padding-block-start: 0.875rem;
}

/* One shape for both states.
 *
   Matched by an explicit height rather than by matching padding: Legg i Kurv
   carries a 14px icon inside its line box, so at equal padding it comes out
   taller than a text-only control. A fixed height with the contents centred
   settles it.
 *
   Both need a border for the same reason — with box-sizing: border-box, a
   bordered control and an unbordered one at the same height differ by 2px
   inside. The primary's border is its own red, so it is invisible.
 *
   0.9375rem is a step up from the .text-sm the template asks for, which was
   small for the card's primary action. */
/* Not scoped to .products-grid.
 *
   item.phtml renders in four places — the category grid, the category list, and
   the upsell and related sliders on the product page, which use
   Magento_Catalog::product/slider/product-slider.phtml. Scoped to the grid, the
   unavailable control kept its colours but lost its height, width and centring
   in the sliders, so it rendered as a small grey label and its card came out
   shorter than the others.
 *
   Neither selector can reach outside a product card: .tj-product-unavailable is
   ours and only item.phtml emits it, and the other needs a .product-item
   ancestor. List mode overrides both further down. */
.tj-card-actions > .btn,
.tj-product-unavailable {
    align-items: center;
    border-radius: 6px;
    border-style: solid;
    border-width: 1px;
    box-sizing: border-box;
    display: flex;
    font-size: 0.9375rem;
    font-weight: 700;
    gap: 0.5rem;
    height: 46px;
    justify-content: center;
    padding-block: 0;
    text-align: center;
    width: 100%;
}

/* Transparent, not red.
 *
   The border exists only so this control and the bordered unavailable one have
   identical geometry — at border-box, 1px of border is 1px whatever its colour,
   and a transparent border still occupies its space. Painting it
   --color-primary drew a ring: btn-primary darkens its background on hover
   while this rule held the border at the lighter base red, so the edge stayed
   visibly lighter than the fill. */
.tj-card-actions > .btn {
    border-color: transparent;
}

/* Taller below lg, where these are thumb targets rather than pointer ones. */
@media (max-width: 1023px) {
    .tj-card-actions > .btn,
    .tj-product-unavailable {
        height: 50px;
    }
}

/* ---------------------------------------------------------------------------
   The grid.

   Rows need more separation than columns: a card's bottom edge meets the next
   card's top edge with nothing between them, where columns are already
   separated by the cards' own side padding as well as the gap.

   Cards fill their column. list.phtml gives the item `grow`, which does nothing
   in a grid container, so without this a short card sits at content width
   instead of matching its row.
   --------------------------------------------------------------------------- */

/* Not scoped to .page-products: the same card and the same grid render in the
   cross-sell and related blocks on the cart and product pages, which are not
   category pages and were left with the template's own tighter gap. */
.products-grid .grid {
    column-gap: 1.5rem;
    row-gap: 2rem;
}

/* Tighter on a phone: gutters come out of the same row as the cards, so every
   pixel of gap is a pixel the photograph does not get, and two columns already
   read as separate without as much help. */
@media (max-width: 1023px) {
    .products-grid .grid {
        column-gap: 1rem;
        row-gap: 1.5rem;
    }
}

/* Cards fill their cell in both directions.
 *
   list.phtml wraps each card in <li class="flex flex-col">. The li stretches to
   the row's height, because grid items stretch by default — but the card inside
   is a flex child at content height, so a card with a one-line name stopped
   short of its neighbours. height:100% fills the li, and the price's own
   mt-auto then pins the price and the button beneath it to the bottom of the
   full height rather than to the bottom of the content.
 *
   width:100% for the same reason horizontally: the template gives the item
   `grow`, which does nothing here. */
/* Not scoped to .products-grid.
 *
   This is what makes cards in a row the same height, and without it the price's
   mt-auto has nothing to absorb: margin-top:auto resolves to whatever free space
   the card has, so a short card computes 0 and a stretched one computes a real
   value. That is the offset above the price — mt-auto working correctly on cards
   that were never the same height to begin with.
 *
   The sliders are the case that exposed it. In the category grid the li already
   stretches, so scoping this to .products-grid looked harmless; in
   product-slider.phtml the track cell stretches too but the card inside did not
   fill it, and the cards sized to their content instead. */
.product-item {
    height: 100%;
    width: 100%;
}

/* ---------------------------------------------------------------------------
   List mode.

   The card is horizontal here: photo left, information right. Three of the grid
   rules above had to be scoped away from it, and the rest of this block undoes
   what the shared markup does that only suits a column.
   --------------------------------------------------------------------------- */

/* The band runs down the left edge instead of along the top, which is the same
   two surfaces turned ninety degrees. flex-direction is forced rather than left
   to the template's md:flex-row: list is a desktop view in practice, and one
   layout that degrades is better than a second one written for a width nobody
   reaches.

   A fixed width rather than the template's md:w-2/6, which is a proportion and
   grew the photograph with the viewport until it led a row whose other content
   did not. The min() gives way if a row is ever forced narrow, rather than
   holding 200px against a name with nowhere left to wrap. */
.products-list .product-item {
    flex-direction: row;
}

/* List: the band caps the left edge and the text column the right, which is the
   grid's pair of rules turned ninety degrees. Both corners of each are set
   explicitly, because each element inherits the other axis from the grid rules
   above. */
.products-list .tj-product-panel {
    border-start-start-radius: var(--card-inner-radius);
    border-start-end-radius: 0;
    border-end-start-radius: var(--card-inner-radius);
    align-self: stretch;
    border-inline-end: 1px solid var(--color-border);
    flex-shrink: 0;
    padding: 1.25rem 1rem 1rem;
    width: min(200px, 34%);
}

/* Greyscale unconditionally in list, not inside the hover query below. That
   query keys the greyscale on hover capability because colour arriving on hover
   is what makes it a response rather than decoration — but a list row has no
   hover to respond with, so on a phone the marks came through at full colour and
   stayed there while the same rows on a desktop were grey. One appearance at
   every width is the honest answer for a view with no gesture. */
.products-list .tj-brand-mark {
    filter: grayscale(1);
    opacity: 0.8;
}

/* The mark rides in the band, centred over the photo. The inset above it is
   1.25rem, the same as the grid card's, so the mark sits the same distance from
   the top of its band in both views rather than each having its own number.
 *
   That gives up the centre-line alignment with the name across the divider,
   which 0.8125rem was chosen for: 13px plus half the 2.375rem mark row landed on
   32px, and so did the text column's 18px plus half a 1.75rem line box. It was
   exact and it still read high, because the mark is centred inside a row taller
   than any mark in it, so the ink sat above the line the maths was aligning. One
   inset across both views is the more useful rule. */
.products-list .tj-brand-mark {
    justify-content: center;
    margin-block-end: 0.5rem;
}

/* 1.5rem at the top, against the band's 1.25rem, so the name sits level with the
   mark across the divider rather than above it.
 *
   The two columns cannot share a top inset and line up, because the mark is
   centred inside a 2.375rem row and the name is a line of text: 20px of band
   plus half of 38px puts the mark's centre at 39px, while 20px of text padding
   plus half of a 1.75rem line box would put the name's at 34px. 24px of text
   padding puts it at 38px, one pixel off the mark and close enough that nothing
   reads as misaligned.
 *
   This is the third attempt at the pair and the first to move the text rather
   than the band. Moving the band aligned the arithmetic but left the mark
   looking high, because the ink sits centred in a row taller than any mark in
   it; moving the text aligns what is actually visible. */
.products-list .product-item .product-info {
    border-block-start: 0;
    border-start-end-radius: var(--card-inner-radius);
    border-end-start-radius: 0;
    border-end-end-radius: var(--card-inner-radius);
    padding: 1.5rem 1.25rem 1.25rem;
}

/* No pin in list. Pinning the price earns its keep in a grid, where it lines a
   row of cards up on the number they are scanned by. A single-column list has
   nothing to line up against, and the row's height comes from the band rather
   than from the text, so all the free space collected in one gap between the
   name and the price — most visible on a phone, where the description is hidden
   and there is nothing else in the column at all. */
.products-list .tj-card-price {
    margin-block-start: 0;
}

/* The short description renders in list mode only — list.phtml passes
   show_description true there and false in grid. Dropped once the row is narrow
   enough that the template would have stacked it: four lines of spec beside a
   band in a 480px row is strained, and the product page carries the full list
   anyway. Not clamped at desktop, where cutting a spec list mid-point reads as
   a rendering fault rather than a summary. */
@media (max-width: 767px) {
    .products-list .product-description {
        display: none;
    }
}

/* And the action sizes itself to its label rather than spanning the whole
   information column, which at this width is several hundred pixels of red for
   one control. */
.products-list .tj-card-actions > .btn,
.products-list .tj-product-unavailable {
    display: inline-flex;
    width: auto;
}

.products-list .tj-product-unavailable {
    align-items: center;
    border-radius: 6px;
    height: 46px;
    justify-content: center;
    padding-inline: 1.25rem;
}

/* No hover on a list row: no lift, no darkening, and no colour returning to the
   mark. A row is a surface for scanning, and the gesture belongs to a card you
   are choosing between, not to a line you are reading down. Written as
   overrides because the rules above match on the card's parent, which a list
   row has too. */
@media (hover: hover) {
    .products-list :hover > .product-item {
        border-color: var(--card-stroke);
        box-shadow: none;
        transform: none;
    }


    .products-list :hover > .product-item .tj-brand-mark {
        filter: grayscale(1);
        opacity: 0.8;
    }
}

/* ---------------------------------------------------------------------------
   Slider navigation.

   product-slider.phtml gives its prev and next buttons `btn btn-secondary p-2`.
   btn-secondary sets --btn-stroke and --btn-hover-color from
   --color-primary-lighter (#e92939), which is the brightest red in the palette
   and louder than anything else on the page.

   Overriding the variables on these two buttons only moves them to
   --color-primary (#c11422), the red used everywhere else. Nothing else that
   uses btn-secondary is touched, and the button's own size, border width and
   states are left alone.
   --------------------------------------------------------------------------- */

.product-slider [data-prev],
.product-slider [data-next],
[data-slider] [data-prev],
[data-slider] [data-next] {
    --btn-stroke: var(--color-primary);
    --btn-hover-stroke: var(--color-primary);
    --btn-hover-color: var(--color-primary);
}

/* ---------------------------------------------------------------------------
   Grid gutter.

   list.phtml sets gap-4. The product sliders were on the same 16px through
   --snap-gap in components/slider.css, and both are now 24px — the cards sit
   in a narrower band inside a slider and read tighter at the same number, but
   letting the two diverge would mean two spacing systems for one card.

   Here rather than in a fork of list.phtml: the whole template would have to
   be copied to change one utility class.
   --------------------------------------------------------------------------- */

.page-products .products.wrapper > ul.grid {
    gap: 1.5rem;
}

/* ---------------------------------------------------------------------------
   The brand mark.

   Above the name, whose leading manufacturer segment it replaces. See
   item.phtml: the name is only shortened where this renders.

   The image carries its own width and height from the manifest, sized by the
   same area rule as the product page at a smaller scale. An earlier version set
   a height here and capped the width in CSS instead, which made the compact
   marks small, clipped the wide ones, and — because object-contain centres what
   it clips — left every clipped mark floating in the middle of its box rather
   than flush against the name below it.

   The row is a fixed height because a grid levels across cards: a tall badge in
   one card and a long wordmark in the next must reserve the same space or the
   prices beneath them stop lining up.

   2.375rem is no longer the manifest's own ceiling. CARD_H_MAX came down to 34
   while this stayed at 38, because the two being equal meant the squat marks
   filled the row edge to edge while the wordmarks sat at 20 to 31 inside it —
   same reserved box, and the compact ones read heavy for it. The gap is now
   deliberate: nothing reaches the row's height, and every mark has air above and
   below it without the row or the card changing size.
   --------------------------------------------------------------------------- */

.tj-brand-mark {
    align-items: center;
    display: flex;
    height: 2.375rem;
    /* 18px below, against 20px of band padding above. The progression has run
       16/4, 12/10, 16/14 and now 20/18: the mark wants to sit in its own space
       rather than belong to the photo above it or the name below, and once the
       marks came down to a 34px cap there was room to give it that. */
    margin-block-end: 1.125rem;
}

.tj-brand-mark img {
    display: block;
}

/* Greyscale only where there is a pointer, so a phone shows the marks in colour.
   Keyed on hover capability rather than width because the reason is the hover
   itself: a grid of twenty logos at full colour competes with twenty product
   photos, and the colour arriving on hover is what makes it a response rather
   than decoration. With no hover to restore it, there is nothing to mute.

   Hovered via the card's parent, matching the block above — the li does not
   move, so the pointer never leaves it while the card slides beneath. */
@media (hover: hover) {
    .tj-brand-mark {
        filter: grayscale(1);
        opacity: 0.8;
        transition-property: filter, opacity;
        transition-duration: 0.1s;
    }

    :hover > .product-item .tj-brand-mark {
        filter: grayscale(0);
        opacity: 0.9;
    }
}
