/**
 * TransferJet — the product page.
 *
 * Product-page-only rules live here. catalog.css is for the ones that are
 * deliberately cross-surface: the swatch ring fires on this page and in
 * layered navigation, the slider hover on this page and on the cart. Anything
 * that only ever renders under .catalog-product-view belongs in this file.
 *
 * Scoped on the body class throughout. The templates carry Hyvä's own class
 * names — .stock, .product-description, .additional-attributes — which are not
 * ours to claim, and .catalog-product-view keeps every rule off the other
 * pages that use them.
 */

/* ---------------------------------------------------------------------------
   Stock status as a pill.

   No template fork. stock-status.phtml already emits .stock plus .available
   or .unavailable and draws its dot with a ::before, which is the whole of
   what a pill needs. Overriding the utilities is cheaper than owning a copy of
   a file that will keep changing upstream.

   The utilities being beaten are before:bg-green-500 and friends, which
   compile to (0,1,1). These rules are (0,2,1), so no !important is required.

   Alignment first: upstream wraps the status in text-right and justifies the
   flex to the end, because in the default layout it sits opposite the alert
   links. Here it opens a left-aligned row.
   --------------------------------------------------------------------------- */

.catalog-product-view .stock {
    background: #e7f4ec;
    border-radius: 9999px;
    color: #14713a;
    display: inline-flex;
    font-size: 0.9375rem;
    font-weight: 700;
    justify-content: flex-start;
    letter-spacing: 0.02em;
    padding: 0.375rem 0.875rem;
    text-transform: uppercase;
}

.catalog-product-view .stock::before {
    background: #1a9e4b;
    height: 0.5625rem;
    width: 0.5625rem;
}

/* The pill and the count sit closer than Hyvä's gap-x-4 (16px) allows to read
   as separate facts — the count ends up looking like an overflow of the pill
   rather than its own statement. 21px separates them. Set here rather than
   swapped for a Tailwind utility because 21px is not on the spacing scale, and
   rounding to gap-6 would have been 24px chosen by what was available. */
.catalog-product-view .tj-stock-row {
    column-gap: 1.3125rem;
}

/* The count itself, matched to the pill in size and weight so the two read as
   one statement rather than a badge with a footnote. Not a pill: two filled
   shapes side by side would be a pair of badges, and only the first is a
   state. */
.catalog-product-view .tj-stock-qty {
    font-size: 0.9375rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}

/* SKU on its own line beneath the stock row, muted and a size down. It is a
   reference number, checked once by someone making sure they have the right
   part — it should be findable rather than noticed. */
.catalog-product-view .tj-sku {
    color: #6b6866;
    font-size: 0.875rem;
    margin-block: 0.5rem 1.25rem;
}

/* ---------------------------------------------------------------------------
   Configurable option labels.

   Two templates render these and they disagreed. The swatch branch of
   Magento_Swatches' renderer.phtml writes its legend at font-normal with a
   trailing colon and the selected value at font-medium beside it; the select
   branch — and the whole of ConfigurableProduct's configurable.phtml — writes
   its label at font-medium with no colon. So "Farge:" and "Dysekit intervall"
   came out at different weights on two products that are otherwise the same
   kind of thing.

   Levelled at font-medium. The colon stays where a value follows it and stays
   absent where none does, which is grammar rather than inconsistency — the
   select shows its own value, so there is nothing for a colon to introduce.

   In CSS rather than a fork. Both wrappers carry data-product-id, so one rule
   reaches all three branches, and the alternative was forking two templates
   that each carry a block of inline Alpine registration for a font weight.
   --------------------------------------------------------------------------- */

.catalog-product-view [data-product-id] legend {
    font-weight: 500;
}

/* ---------------------------------------------------------------------------
   Quantity and add to cart.

   Below sm the button takes whatever the quantity field leaves, so the label
   fits and the pair spans the card. The quantity keeps its own w-20 and is
   only told not to grow: it holds one or two digits, and a field that stretches
   with the viewport to hold "1" looks like an input waiting for something
   longer. Not restating the width here leaves one number for it, in the
   template where Hyvä set it.

   Matched on name rather than id. quantity.phtml writes id="qty[123]" with the
   product id in it, so there is no #qty to select. The input is also a direct
   child of this row — the template has no wrapper — so it is the flex item
   itself and takes flex: none directly.

   From sm the actions sit beside the price at their natural widths, which is
   Hyvä's own arrangement, so all of this stops.
   --------------------------------------------------------------------------- */

/* From lg the button sits beside the price at its natural width, and .btn's
   16px of inline padding leaves it looking narrow against a 28px price on a
   wide column. 20px is enough to settle it — 32px was tried first and made the
   button read as a panel rather than a control.

   lg rather than xl: that is where the label comes back — between md and lg it
   is hidden for the sidebar — so it is also where there is room to pad around
   it. Scoped to the id so .btn-primary keeps its shipped padding everywhere
   else. */
@media (min-width: 1024px) {
    .catalog-product-view #product-addtocart-button {
        padding-inline: 1.25rem;
    }
}

@media (max-width: 639px) {
    .catalog-product-view .tj-buybox__actions {
        width: 100%;
    }

    .catalog-product-view .tj-buybox__actions input[name="qty"] {
        flex: none;
    }

    .catalog-product-view .tj-buybox__actions #product-addtocart-button {
        flex: 1 1 auto;
        justify-content: center;
    }
}

/* Out of stock is grey, not red. Red is this site's colour for the one action
   that leaves the page, and an alert-coloured badge next to a disabled button
   reads as an error the customer caused. The dot goes with it — a coloured dot
   earns attention that "utsolgt" does not need, since there is nothing to do
   about it. */
.catalog-product-view .stock.unavailable {
    background: #f2f2f2;
    color: #6b6866;
}

.catalog-product-view .stock.unavailable::before {
    display: none;
}

/* ---------------------------------------------------------------------------
   Short description.

   Upstream gives it my-4. That reads as tight between a heading with a rule
   under it and the stock row, both of which are horizontal lines — 16px of air
   against two rules looks like less than 16px against nothing.

   Set as margin rather than added as padding. The template's my-4 is still
   there, and padding on top of it would leave two numbers to keep in step for
   one gap. (0,2,0) against the utility's (0,1,0).
   --------------------------------------------------------------------------- */

.catalog-product-view .product-description {
    margin-block: 1.5rem;
}

/* ---------------------------------------------------------------------------
   Specifications table.

   Striped, two columns at every width, filling the card.

   Three upstream decisions are undone here. The wrapper carries max-w-prose,
   which caps the table at 65ch no matter how wide the card is — sensible for
   running text, wrong for a two-column table that is the whole content of its
   card. Both cells carry w-1/2, which gives a label like "Anbefalt tennplugg"
   the same room as "B10ES". And the value is left-aligned, so on a wide row
   the two columns drift apart with nothing between them.

   So: full width, an even 50/50, and both columns set from the left.

   Right-aligning the values was tried first. In a card this wide it left a
   hand's width of nothing between "Sylinderklasse" and "70 cc" — the label and
   its answer ended up at opposite edges with the eye having to cross the gap
   for every row. Set from the left of an even split, the value sits a fixed
   distance from the label on every row, so the answers still form a column to
   run down but each one stays attached to its question. The value keeps its
   weight, which is what separates the two columns now that alignment does not.

   An earlier pass stacked the rows below md. That is now gone. Stacked, the
   label sat directly on top of its own value with no more separation than
   between one row and the next, and inside a 65ch cap it looked cramped rather
   than roomy. Two even columns hold on a phone without it.

   Striping on nth-child rather than :nth-of-type — every child of the table is
   a tr, and the rows are written straight into <table> with no <tbody>.
   --------------------------------------------------------------------------- */

.catalog-product-view #product-attributes {
    max-width: none;
}

.catalog-product-view .additional-attributes tr:nth-child(even) {
    background: #f7f7f7;
}

/* The borders came from the row above them. With alternating fills they draw a
   second line under every second band and the table starts to look ruled. */
.catalog-product-view .additional-attributes tr {
    border: 0;
}

.catalog-product-view .additional-attributes th,
.catalog-product-view .additional-attributes td {
    padding: 0.625rem 0.75rem;
}

.catalog-product-view .additional-attributes th,
.catalog-product-view .additional-attributes td {
    text-align: start;
    width: 50%;
}

.catalog-product-view .additional-attributes td {
    font-weight: 700;
}

/* ---------------------------------------------------------------------------
   Section headings.

   Flat icon, then the title. The tinted square was tried first and pulled more
   attention than a label should — a filled shape reads as a control, and it
   also sat apart from its own heading rather than with it, because 9px of
   padding inside the square plus the gap put 21px between glyph and text.

   Flat, the icon carries at 26px where it needed 22 inside a square, and sits
   12px from the text. Section headings are now distinguished from slider
   headings by position rather than by fill: a slider heading shares its row
   with the previous/next buttons, a section heading stands alone above a card.

   Flex on the h2 rather than an inline-block on the span, so the icon centres
   against the cap height of the text instead of the line box.

   Left at every width. Hyvä's h2 here is text-center md:text-left, which
   centres it on a phone — reasonable for a bare heading, odd once it carries
   an icon, because the pair floats in the middle of a full-width card whose
   contents are all set from the left. The slider headings never centred, so
   this also stops the two heading systems disagreeing below md.

   The 24px below the heading is Hyvä's mb-6. Against a card that begins
   immediately underneath it read as detached, so it is 16px here — enough to
   separate the heading from the border, not enough to orphan it. Set rather
   than added, at (0,2,0) against the utility's (0,1,0), so there is one number
   for the gap.
   --------------------------------------------------------------------------- */

.catalog-product-view .tj-section-title {
    align-items: center;
    display: flex;
    gap: 0.75rem;
    justify-content: flex-start;
    margin-block-end: 1rem;
    text-align: start;
}

.catalog-product-view .tj-section-title__icon {
    align-items: center;
    color: var(--color-primary);
    display: inline-flex;
    flex: none;
    justify-content: center;
}

/* ---------------------------------------------------------------------------
   Slider headings.

   Same icon, same red, no fill — the section headings dropped their tinted
   square for the same reason, and a filled square here would in any case face
   the previous/next buttons across a justify-between row and read as a third
   button.

   28px against the section headings' 24. The slider icon is measured against
   the 38px button box opposite it rather than against the 18px glyph inside
   it, so it needs the extra to hold the row.
   --------------------------------------------------------------------------- */

.catalog-product-view .tj-slider-heading__icon,
.checkout-cart-index .tj-slider-heading__icon {
    align-items: center;
    color: var(--color-primary);
    display: inline-flex;
    flex: none;
    justify-content: center;
}

/* Hidden below sm. "Kombineres ofte med" plus an icon plus two 38px buttons
   does not fit a 320px row, and of the three the arrows are the ones that have
   to survive — the heading says what the slider is, the icon only decorates
   it. The heading keeps its min-w-0 so it ellipsises rather than pushing the
   buttons off. */
@media (max-width: 639px) {
    .tj-slider-heading__icon {
        display: none;
    }
}

/* ---------------------------------------------------------------------------
   The three conditional links.

   Blue rather than red. Red on this page belongs to Legg i Kurv; these send
   the customer further down the same page, which is a smaller promise, and the
   reference uses blue for exactly these three.
   --------------------------------------------------------------------------- */

.tj-product-links {
    border-top: 1px solid #e5e3e1;
    margin-block-start: 2rem;
    padding-block: 1.75rem 0.5rem;
}

/* Each pair is a lead line and its link; the space between pairs has to beat
   the space inside one, or three questions and three answers read as six
   lines. 1.75rem against the 0.25rem inside. */
.tj-product-links__item + .tj-product-links__item {
    margin-block-start: 1.75rem;
}

.tj-product-links__lead {
    color: #1f1a16;
    margin-block-end: 0.25rem;
}

.tj-product-links__link {
    align-items: center;
    color: var(--color-secondary);
    display: flex;
    font-weight: 700;
    gap: 0.5rem;
}

.tj-product-links__link svg {
    flex: none;
}

.tj-product-links__link:hover {
    text-decoration: underline;
}

/* ---------------------------------------------------------------------------
   Gallery image captions.

   Hidden here rather than switched off in view.xml, and that is the whole
   reason this rule exists. An etc/view.xml was added to set gallery/caption to
   0 — the accessible way to do it, since turning the var off sends the static
   branch's alt back to the caption instead of emptying it. But adding the
   theme's first view.xml cost Hyvä's entire <media> block: swatch_image fell
   back to Magento_Swatches' own 30x20 and swatch_thumb to 110x90, which is why
   the swatches rendered as ovals rather than roundels. Confirmed by moving the
   file away and watching them return to 30x30. Every other image dimension
   Hyvä sets was going the same way, unnoticed.

   One caption is not worth that, so the file is gone and this hides the span.
   Do not add a theme view.xml again without working out why the merge fails.

   Both branches at once. gallery.phtml renders two — a static one and an
   Alpine one bound to imgCaption — and they share the same class string, so
   one selector reaches both without matching on the Alpine binding.

   The cost, stated plainly: on the static branch, line 195 empties alt when a
   caption is displayed, so an image that has a label now has no accessible
   name. Images with no label are unaffected — no span renders and alt already
   falls back to the product name — and on this catalogue labels are set on
   only a handful of images and not actively used. If they are ever used
   properly, this rule should be split so the static caption becomes sr-only
   and only the Alpine one is hidden; the Alpine branch carries the caption in
   :alt as well, so hiding that span loses nothing.
   --------------------------------------------------------------------------- */

#gallery span.absolute.bottom-2 {
    display: none;
}

/* ---------------------------------------------------------------------------
   Grouped products — the parts list.

   Every rule is scoped to .page-product-grouped, the body class Hyvä's grouped
   layout sets. product-view.css is loaded on every page, and tj-parts class
   names existing only on this one is not the same as saying so.

   Two columns come free: the grouped block sits inside the card's place in the
   product info grid, so the drawing is the gallery in the left column and this
   is the right. No new grid.

   Blue band, blue action, red reserved for Utsolgt.

   Red was tried in the band and on the link and read as alarm rather than
   direction — on a page of twenty positions a tinted band on each becomes
   stripes, and the colour stops meaning "this is the way through" once it is
   also the background. Blue is the site's link colour and this list is entirely
   links.

   A grey band was tried after that and is the version this replaced. It was
   argued for before the thumbnail had a frame; once that frame became a grey
   square inside every row, the panel was grey on grey on grey with nothing
   separating the band from the content it heads. The tint is what makes the
   band read as a header rather than as more of the same surface.
   --------------------------------------------------------------------------- */

.page-product-grouped .tj-parts__title {
    font-size: 1.25rem;
    font-weight: 700;
    margin-block-end: 0.875rem;
}

.page-product-grouped .tj-parts__list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    list-style: none;
    margin: 0;
    padding: 0;
}

.page-product-grouped .tj-parts__item {
    border: 1px solid #e5e3e1;
    border-radius: 10px;
    overflow: hidden;
}

/* The position band. POS and its number read as one unit; the note sits at the
   far end where it explains rather than competes. */
.page-product-grouped .tj-parts__pos {
    align-items: center;
    background: color-mix(in srgb, var(--color-secondary) 9%, #fff);
    border-block-end: 1px solid color-mix(in srgb, var(--color-secondary) 18%, #fff);
    display: flex;
    gap: 0.625rem;
    padding: 0.5625rem 0.875rem;
}

.page-product-grouped .tj-parts__pos-label {
    color: #6b6866;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.06em;
}

.page-product-grouped .tj-parts__pos-number {
    background: #fff;
    border: 1px solid color-mix(in srgb, var(--color-secondary) 30%, #fff);
    border-radius: 6px;
    font-weight: 700;
    min-width: 2rem;
    padding: 0.125rem 0.5rem;
    text-align: center;
}

.page-product-grouped .tj-parts__pos-note {
    color: #8a8785;
    font-size: 0.8125rem;
    margin-inline-start: auto;
    text-align: end;
}

/* Padding and gaps grew with the thumbnail. At 82px the old 14px row padding
   left the photo nearly touching the border, and the two text columns beside a
   taller image needed their own lines further apart to stay legible as pairs
   rather than as four stacked lines. */
.page-product-grouped .tj-parts__row {
    align-items: center;
    display: flex;
    gap: 1.125rem;
    padding: 1rem;
}

/* ---------------------------------------------------------------------------
   The thumbnail frame.

   A grey square in both states, so a row with a photo and a row without are
   the same shape and the list keeps its rhythm.

   mix-blend-mode: multiply is the mechanism carried over from _am-jet-extend.less
   and already used on the product cards — catalogue photos are cut out on white,
   so multiplied onto grey they sit on the panel instead of showing a white box
   inside it.

   The image is sized here rather than trusted to its width attribute. The block
   emits width="265" height="265" for product_base_image, which is the smallest
   id backed by the attribute grouped products actually load; 265 into a 56px box
   is generous but it is a resize Magento caches once.
   --------------------------------------------------------------------------- */

.page-product-grouped .tj-parts__thumb {
    align-items: center;
    aspect-ratio: 1;
    background: #f2f2f2;
    border-radius: 8px;
    display: flex;
    flex: none;
    justify-content: center;
    overflow: hidden;
    padding: 1px;
    width: 82px;
}

/* The inner radius is the outer one less the padding, so the photo's corners
   follow the frame instead of squaring off inside it. */
.page-product-grouped .tj-parts__thumb img {
    border-radius: 7px;
    height: auto;
    mix-blend-mode: multiply;
    width: 100%;
}

/* No photo. A slightly darker outline says "there is no picture" rather than
   leaving an empty grey square that reads as a loading state that never
   finished. Not multiplied — it is drawn, not photographed. */
.page-product-grouped .tj-parts__thumb.is-empty {
    color: #b8b5b3;
}

/* min-width: 0 so a long part name wraps inside its column instead of pushing
   the price and the link out of the row. */
.page-product-grouped .tj-parts__detail {
    min-width: 0;
}

.page-product-grouped .tj-parts__name {
    color: #1f1a16;
    display: block;
    font-size: 0.9375rem;
    font-weight: 700;
    line-height: 1.35;
}

.page-product-grouped .tj-parts__name:hover {
    text-decoration: underline;
}

.page-product-grouped .tj-parts__stock {
    align-items: center;
    display: flex;
    font-size: 0.875rem;
    gap: 0.375rem;
    margin-block-start: 0.5rem;
}

/* In stock gets a dot, out of stock a cross from the template. A dot is a
   state; a cross is a refusal, and it earns the extra weight. */
.page-product-grouped .tj-parts__stock.is-in {
    color: #14713a;
}

.page-product-grouped .tj-parts__stock.is-in::before {
    background: #1a9e4b;
    border-radius: 9999px;
    content: "";
    flex: none;
    height: 0.5rem;
    width: 0.5rem;
}

.page-product-grouped .tj-parts__stock.is-out {
    color: var(--color-primary);
}

.page-product-grouped .tj-parts__aside {
    align-items: flex-end;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-inline-start: auto;
    text-align: end;
}

/* ---------------------------------------------------------------------------
   Price inside a row.

   getProductPrice() returns Magento's full price markup, so a discounted part
   arrives as .special-price and .old-price with a "Spesialpris" / "Vanlig pris"
   label on each. Both are inline spans; they are stacked here.

   16px, not the product page's 28px — this is one line in a list of twenty, and
   the price should sit level with the part name rather than above it. 18px was
   tried first and still pulled first.

   The labels are hidden visually rather than removed, because "Vanlig pris" is
   the only thing distinguishing the two figures for anyone not seeing the line
   through the second one.
   --------------------------------------------------------------------------- */

.page-product-grouped .tj-parts__price .special-price,
.page-product-grouped .tj-parts__price .old-price {
    display: block;
}

.page-product-grouped .tj-parts__price .price-label {
    clip-path: inset(50%);
    height: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
    width: 1px;
}

.page-product-grouped .tj-parts__price .price {
    font-size: 1rem;
    font-weight: 700;
    white-space: nowrap;
}

.page-product-grouped .tj-parts__price .old-price .price {
    color: #8a8785;
    font-size: 0.8125rem;
    font-weight: 400;
    text-decoration: line-through;
}

.page-product-grouped .tj-parts__link {
    align-items: center;
    color: var(--color-secondary);
    display: flex;
    font-size: 0.9375rem;
    font-weight: 700;
    gap: 0.25rem;
    white-space: nowrap;
}

.page-product-grouped .tj-parts__link:hover {
    text-decoration: underline;
}

/* ---------------------------------------------------------------------------
   One column until lg.

   Hyvä's product hero splits at md, giving the drawing 42% of a 768px viewport
   — about 320px for an exploded diagram whose whole purpose is that the
   position numbers can be read. The parts list gets the remainder and wraps
   every name. Both halves are better full width until there is room for two.

   lg matches the boundary the rest of the theme uses: the filter drawer runs
   to lg, the sidebar appears at lg, the slider heading icons return at sm. This
   is grouped-only — a normal product page has a photograph rather than a
   technical drawing on the left, and 320px is enough for that.
   --------------------------------------------------------------------------- */

@media (max-width: 1023px) {
    .page-product-grouped .tj-product-hero {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Below sm the thumbnail and the aside column together leave the name about
   half the width. Stacked, the name and stock get the full line and the price
   and link sit beneath them. */
@media (max-width: 639px) {
    .page-product-grouped .tj-parts__row {
        display: grid;
        grid-template-columns: 82px minmax(0, 1fr);
        row-gap: 0.75rem;
    }

    .page-product-grouped .tj-parts__aside {
        align-items: flex-start;
        flex-direction: row;
        flex-wrap: wrap;
        grid-column: 1 / -1;
        justify-content: space-between;
        margin-inline-start: 0;
        text-align: start;
    }
}
