/* ==========================================================================
   U Jabka — Soda design system: PRODUCT DETAIL (PR5)

   Page-scoped layout for resources/views/frontend/product-detail.php. Everything
   is scoped under `html.theme-soda` so an un-migrated page can never pick it up.

   Only layout and page-specific recipes live here. Buttons, panels, badges,
   cards, breadcrumb, inputs and empty states come from soda/components.css and
   are not restyled — a page agent that redefines a shared component is a defect.

   CSP: this file carries every dynamic-looking style. There is not one inline
   style attribute in the template, and no rule here depends on JS running.
   ========================================================================== */

/* ------------------------------------------------------------- page frame */

html.theme-soda .soda-detail {
    padding-top: clamp(1.6rem, 3vw, 2.6rem);
}

html.theme-soda .soda-section--tight {
    padding-block: clamp(2.6rem, 5vw, 4.5rem);
}

html.theme-soda .soda-detail__back {
    margin-bottom: clamp(1.4rem, 2.6vw, 2.2rem);
}

/* Two columns on desktop: media left, buybox right. The buybox sticks so the
   price and the add-to-cart control stay reachable while the gallery scrolls. */
html.theme-soda .soda-detail__grid {
    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: clamp(1.4rem, 3vw, 3rem);
    align-items: start;
}

@media (max-width: 980px) {
    html.theme-soda .soda-detail__grid {
        grid-template-columns: 1fr;
    }
}

@media (min-width: 981px) {
    html.theme-soda .soda-detail__buybox {
        position: sticky;
        top: clamp(5rem, 8vw, 7rem);
    }
}

/* ---------------------------------------------------------------- gallery */

html.theme-soda .soda-gallery {
    margin: 0;
}

/* 21st product-detail.md gallery frame, ported:
       `relative w-full overflow-hidden rounded-xl border`
   — the frame, its hairline and its 12px corner are the source's and stay.

   OWNER-DIRECTED DEVIATION (2026-09-03): THE PHOTOGRAPH IS THE OLD ONE.
   The source frames its picture `aspect-[4/5]` with `object-cover`, so the
   photo is cropped to a tall portrait box and bleeds to the frame's edge. The
   owner reviewed the transplant and asked for the proportion this page carried
   before it — "obrázek zmenšit" — so the two numbers that decide the picture's
   SIZE revert to the pre-transplant detail sheet (commit 1ca2635):

       aspect-ratio: 4 / 3
       padding:      clamp(1.2rem, 3vw, 2.4rem)

   Everything else the transplant established — the rounded-xl border frame,
   the dot controls, the page frame, the two-column grid — is untouched. */
html.theme-soda .soda-gallery__stage {
    position: relative;
    display: grid;
    /* An explicit minmax(0, 1fr) track is load-bearing: with an auto-sized row
       the photo's percentage height is circular, so a tall photo renders at its
       intrinsic size and overflows the frame it is supposed to sit inside. */
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr);
    place-items: center;
    aspect-ratio: 4 / 3;
    width: 100%;
    padding: clamp(1.2rem, 3vw, 2.4rem);
    overflow: hidden;
    background: transparent;
    border: 1px solid var(--line);          /* `border`                     */
    border-radius: var(--t21-radius-xl);    /* rounded-xl = .75rem          */
}

/* Fill the padded stage and LETTERBOX — the old rule, restored with the frame
   above. `object-fit: contain` is what makes the device sit inside the frame
   instead of being cropped by it, and the padding is what makes it read as
   smaller. `max-height: 100%` cannot substitute for the height here: the stage
   row is content-sized, so a percentage max-height resolves against an
   indefinite height and the photo overflows its own frame. */
html.theme-soda .soda-gallery__image {
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: center;
    filter: none;
}

/* On the plane the stage is a white surface and the imported renders arrive on
   white, so the drop shadow — drawn for a product floating on the dark ground —
   becomes a grey smudge around a rectangle that has no edge of its own. The
   same removal the catalogue tiles needed. */
html.theme-soda :is(.soda-plane, .soda-card-w, .soda-pg-section > .soda-container) .soda-gallery__image {
    filter: none;
}

/* Abstract device outline, used only when a product genuinely has no photo yet.
   Used units can never reach it: the public unit query requires a unit-scoped
   `products/…` image, so a unit without a photo is not addressable at all. */
html.theme-soda .soda-gallery__fallback {
    width: min(58%, 220px);
    height: auto;
    color: rgba(255, 255, 255, .13);
}

html.theme-soda .soda-gallery__tag {
    position: absolute;
    top: 1rem;
    left: 1rem;
    z-index: 1;
}

html.theme-soda .soda-gallery__caption {
    margin-top: .8rem;
    font-size: .78rem;
    color: var(--ink-3);
}

/* THE GALLERY CONTROLS ARE THE SOURCE'S DOTS:
       `h-2 w-2 rounded-full transition-colors`
       active   -> bg-primary
       inactive -> bg-muted-foreground/30 hover:bg-muted-foreground/50
   They stay REAL LINKS to the full-size photograph, so with soda/gallery.js
   blocked a dot still opens the picture — the no-JS contract the thumbnail
   strip carried is unchanged, only its presentation is the source's. */
html.theme-soda .soda-gallery__thumbs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--t21-2);                      /* gap-2 = .5rem                */
    margin: 0;
    padding: 0;
    list-style: none;
}

html.theme-soda .soda-gallery__thumb {
    display: block;
    width: var(--t21-size-2);               /* h-2 w-2 = .5rem              */
    height: var(--t21-size-2);
    padding: 0;
    /* NOT overflow:hidden — the dot's own hit-target pseudo-element below sits
       outside its 8px box and a clip here would delete it. */
    border: 0;
    border-radius: var(--t21-radius-full);  /* rounded-full                 */
    background: color-mix(in srgb, var(--ink-3) 30%, transparent);
    /* `transition-colors` — Tailwind's default 150ms / cubic-bezier(.4,0,.2,1). */
    transition: background-color .15s var(--t21-ease-in-out);
}

html.theme-soda .soda-gallery__thumb:hover {
    background: color-mix(in srgb, var(--ink-3) 50%, transparent);
    transform: none;
}

html.theme-soda .soda-gallery__thumb.is-active {
    background: var(--ink);                 /* bg-primary                   */
}

/* A 8px hit target is below the touch floor, so the dot keeps its size and
   grows its TARGET instead — the source's own geometry, reachable. */
html.theme-soda .soda-gallery__thumb::after {
    content: '';
    position: absolute;
    inset: -.5rem;
}

html.theme-soda .soda-gallery__thumbs > li {
    position: relative;
    display: flex;
}

/* ----------------------------------------------------------------- buybox */

html.theme-soda .soda-detail__title {
    font-family: var(--font-display);
    font-size: clamp(1.7rem, 3.1vw, 2.6rem);
    font-weight: 700;
    line-height: 1.04;
    letter-spacing: -.035em;
    margin: .7rem 0 0;
}

html.theme-soda .soda-detail__lead {
    margin: .7rem 0 0;
    font-size: .96rem;
    line-height: 1.6;
    color: var(--ink-2);
}

html.theme-soda .soda-detail__chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    margin: 1.2rem 0 0;
    padding: 0;
    list-style: none;
}

html.theme-soda .soda-detail__condition {
    margin: 1.3rem 0 0;
    font-size: .92rem;
    line-height: 1.62;
    color: var(--ink-2);
}

/* The §90 ZDPH used-goods notice is a legal statement a buyer has to be able
   to read, so it takes the token that carries the 14px floor rather than a bare
   .85rem, which rendered at 13.6px — under the floor the token system promises
   and the only reading copy on the storefront that was. */
html.theme-soda .soda-detail__vat-note {
    margin: 1.1rem 0 0;
    font-size: var(--text-small);
}

html.theme-soda .soda-detail__buy {
    margin-top: 1.6rem;
    padding-top: 1.4rem;
    border-top: 1px solid var(--line);
}

html.theme-soda .soda-detail__price {
    font-size: clamp(1.6rem, 3vw, 2.1rem);
}

html.theme-soda .soda-detail__form {
    display: block;
}

html.theme-soda .soda-detail__note {
    margin: 0;
    font-size: .82rem;
    color: var(--ink-3);
}

/* ------------------------------------------------ configuration switcher */

html.theme-soda .soda-configurator {
    display: grid;
    gap: 1.15rem;
    margin-top: 1.5rem;
    padding-top: 1.4rem;
    border-top: 1px solid var(--line);
}

html.theme-soda .soda-configurator__group {
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
}

html.theme-soda .soda-configurator__group legend {
    margin-bottom: .55rem;
    font-family: var(--font-display);
    font-size: .72rem;
    font-weight: 650;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--ink-2);
}

html.theme-soda .soda-configurator__options {
    display: flex;
    flex-wrap: wrap;
    gap: .55rem;
}

html.theme-soda .soda-config-option {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 42px;
    max-width: 100%;
    padding: .62rem .85rem;
    border: 1px solid var(--line);
    border-radius: var(--r-control);
    background: var(--panel);
    color: var(--ink-2);
    font-family: var(--font-display);
    font-size: .84rem;
    font-weight: 600;
    line-height: 1.25;
    text-align: center;
    overflow-wrap: anywhere;
    transition: border-color var(--dur) ease, background var(--dur) ease, color var(--dur) ease, transform var(--dur) var(--ease);
}

html.theme-soda a.soda-config-option:hover {
    border-color: var(--line-hi);
    background: var(--panel-hi);
    color: var(--ink);
    transform: translateY(-1px);
}

html.theme-soda a.soda-config-option:focus-visible {
    outline: 3px solid rgba(var(--accent-rgb), .38);
    outline-offset: 2px;
}

html.theme-soda .soda-config-option.is-selected {
    border-color: rgba(var(--accent-rgb), .7);
    background: rgba(var(--accent-rgb), .13);
    color: var(--ink);
    box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), .16);
}

html.theme-soda .soda-config-option.is-disabled {
    opacity: .42;
    cursor: not-allowed;
    text-decoration: line-through;
    text-decoration-thickness: 1px;
}

html.theme-soda .soda-detail__availability-note {
    margin: -.3rem 0 1rem;
    line-height: 1.5;
}

html.theme-soda .soda-detail__variant-form > .soda-label {
    display: block;
    margin-bottom: .45rem;
}

html.theme-soda .soda-detail__quantity-row {
    display: grid;
    grid-template-columns: 84px minmax(0, 1fr);
    gap: .65rem;
    align-items: stretch;
}

html.theme-soda .soda-detail__quantity-row .soda-input {
    min-width: 0;
    text-align: center;
}

@media (max-width: 420px) {
    html.theme-soda .soda-config-option {
        flex: 1 1 calc(50% - .55rem);
    }

    html.theme-soda .soda-detail__quantity-row {
        grid-template-columns: 72px minmax(0, 1fr);
    }
}

/* --------------------------------------------------------- battery meter */
/* Level names come straight from ProductAvailabilityService::batteryIndicator()
   (green >= 90, yellow >= 85, orange below). The thresholds are NOT duplicated
   here — this file only paints whichever level the server decided. */

html.theme-soda .soda-detail-battery {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    margin: 0;
    padding: .34rem .7rem;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    background: var(--panel);
    font-size: .78rem;
    color: var(--ink-2);
    font-variant-numeric: tabular-nums;
}

html.theme-soda .soda-detail-battery__dot {
    width: 8px;
    height: 8px;
    flex: none;
    /* Square, like every other marker in the system: Vesper's own list and
       button markers are tiny SQUARES (size-[0.139vw] bg-current), and a circle
       here was the last curved geometry left in the component layer. */
    border-radius: var(--r-mark);
    background: var(--ink-3);
}

html.theme-soda .soda-detail-battery--green .soda-detail-battery__dot { background: var(--success); }
html.theme-soda .soda-detail-battery--yellow .soda-detail-battery__dot { background: var(--warning); }
html.theme-soda .soda-detail-battery--orange .soda-detail-battery__dot { background: #fb923c; }

/* ---------------------------------------------------------------- trust */

/* WHERE THE GRADE SELECTOR USED TO LIVE. Until 2026-09-03 this file also
   carried a `.soda-detail-columns` two-pane band (`.soda-grade-nav` on the
   left, the trust panel on the right) that sat far below the buy card. The
   owner asked for the grade switcher to move INSIDE the product-detail card,
   beside a colour and a capacity switcher, so that band is gone and its rules
   with it — the switchers are now the configurator recipe further down this
   file, under `.t21-pdp__axes`.

   `.soda-grade-nav` and `.soda-grade` survive as CLASS HOOKS ONLY, on the
   jakost axis inside the card: scripts/test-soda-product-detail-mvp.php pins
   both (the used-unit page must render a grade selector, and a reachable other
   grade must be a real anchor to that unit), and the diagnostic's intent is
   exactly what the in-card switcher still does. They carry no rules of their
   own — the chip they sit on is a `.soda-config-option`, the same object the
   new-product branch uses for its axes. */

html.theme-soda .soda-detail-trust__title {
    font-family: var(--font-display);
    font-size: 1.05rem;
    font-weight: 600;
    letter-spacing: -.015em;
    margin: 0 0 .9rem;
}

html.theme-soda .soda-detail-trust__list {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: .7rem;
}

html.theme-soda .soda-detail-trust__list li {
    position: relative;
    padding-left: 1.5rem;
    font-size: .88rem;
    line-height: 1.55;
    color: var(--ink-2);
}

html.theme-soda .soda-detail-trust__list li::before {
    content: '';
    position: absolute;
    left: 0;
    top: .5rem;
    width: 8px;
    height: 8px;
    /* Square, like every other marker in the system: Vesper's own list and
       button markers are tiny SQUARES (size-[0.139vw] bg-current), and a circle
       here was the last curved geometry left in the component layer. */
    border-radius: var(--r-mark);
    background: var(--accent);
    opacity: .8;
}

/* -------------------------------------------------------- variant cards */

html.theme-soda .soda-variant-card {
    display: flex;
    flex-direction: column;
    gap: .7rem;
}

html.theme-soda .soda-variant-card__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .6rem;
}

html.theme-soda .soda-variant-card__title {
    font-family: var(--font-display);
    font-size: 1.04rem;
    font-weight: 600;
    letter-spacing: -.02em;
    margin: 0;
}

html.theme-soda .soda-variant-card__status {
    margin: 0;
}

html.theme-soda .soda-variant-card__note {
    margin: 0;
    font-size: .8rem;
    line-height: 1.5;
    color: var(--ink-3);
}

html.theme-soda .soda-variant-card__foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .8rem;
    margin-top: auto;
    padding-top: .9rem;
    border-top: 1px solid var(--line);
}

/* Each variant owns its own <form>: no shared state, no client-side price maths,
   and a quantity typed into one card can never leak into another. */
html.theme-soda .soda-variant-card__form {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
}

html.theme-soda .soda-variant-card__form .soda-input {
    padding: .5rem .6rem;
    font-size: .9rem;
}

/* ---------------------------------------------------------- empty branch */

html.theme-soda .soda-detail__empty h1 {
    font-family: var(--font-display);
    font-size: clamp(1.6rem, 3vw, 2.2rem);
    margin: 0 0 .7rem;
}

/* The CTA is inline-flex and .soda-empty is text-align: center, so it centres
   without a margin trick. */
html.theme-soda .soda-detail--empty {
    min-height: 42vh;
}

/* ------------------------------------------------------------- similar row */

html.theme-soda .soda-detail-similar .soda-card__media .soda-gallery__fallback {
    width: 62%;
}

html.theme-soda .soda-detail-similar .soda-detail-battery {
    margin-top: .6rem;
}


/* ============================================ THE VESPER PROPAGATION (§5)

   The product page is now the same composition as the catalogue: the dark
   Vesper ground carries the page, and the working content sits on white
   .soda-plane surfaces (components.css) that re-point the semantic tokens so
   every existing component reads light-on-white without being rewritten.

   THE DEVICE IS THE DOMINANT OBJECT, which is the brief's primary intent for
   this page. The media column is widened against the buy column and its image
   bleeds to the plane's edge instead of sitting inside a padded box, so the
   thing being sold is the largest thing on the screen.

   Structure is carried by HAIRLINES: one rule between the media and the buy
   column, one under each information block. No panels inside the plane, no
   second surface, no shadow.
   -------------------------------------------------------------------------- */

html.theme-soda .soda-detail,
html.theme-soda .soda-detail-similar,
html.theme-soda .soda-detail-variants {
    background: var(--vesper-void);
    color: #fff;

    /* Scoped for the same reason .soda-hero scopes its own: this ground is
       Vesper's, not the surface theme's, and must not turn ivory. */
    --ink: #ffffff;
    --ink-muted: rgba(255, 255, 255, .72);
    --ink-faint: rgba(255, 255, 255, .55);
    --ink-2: rgba(255, 255, 255, .72);
    --ink-3: rgba(255, 255, 255, .55);
    --line: rgba(255, 255, 255, .15);
    --line-hi: rgba(255, 255, 255, .3);
    --glass-border: rgba(255, 255, 255, .15);
    --panel: transparent;
    --panel-hi: rgba(255, 255, 255, .06);
    --hover-wash: rgba(255, 255, 255, .07);
    --focus: #ffffff;

    /*
     * BUTTON CHROME MUST BE SCOPED WITH THE INK, or it silently keeps the
     * SURFACE THEME's values while everything around it flips.
     *
     * Found by driving a real order through in a browser rather than by
     * reading the stylesheet: --btn-bg is rgba(255,255,255,.88) under the light
     * theme, so a plain .soda-btn on this dark ground painted a near-white pill
     * carrying the scope's white label — 1.0:1, invisible. tokens.css records
     * exactly this failure for the hero CTA; the same three tokens close it
     * here.
     *
     * --accent goes white for the same reason it goes ink on the plane: these
     * pages carry no brand colour, so the CTA's square tile is ink-on-white
     * like the hero's rather than an orange chip.
     */
    --btn-bg: rgba(0, 0, 0, .42);
    --btn-bg-hover: rgba(0, 0, 0, .68);
    --btn-border: rgba(255, 255, 255, .18);
    --accent: #ffffff;
    --accent-rgb: 255, 255, 255;
    --accent-ink: #000000;
}

/* base.css declares `color: var(--ink)` on every heading to beat the legacy
   sheet, and an explicit declaration beats the scope above. */
html.theme-soda .soda-detail-similar .soda-sec-title,
html.theme-soda .soda-detail-variants .soda-sec-title {
    color: #fff;
}

/* ---------------------------------------------------------- the buy plane */

html.theme-soda .soda-detail__grid {
    /* The device gets the larger share. */
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    gap: 0;
    align-items: stretch;
}

html.theme-soda .soda-detail__media {
    padding: 0;
    border: 0;
    border-right: 1px solid rgba(0, 0, 0, .15);
    background: transparent;
}

html.theme-soda .soda-detail__buybox {
    padding: 2.222vw;
    border: 0;
    background: transparent;
}

/* The title is the page's display moment, in the same face and weight as
   every other Vesper title. */
html.theme-soda .soda-detail__title {
    font-family: var(--font-display);
    font-size: clamp(2rem, 3.6vw, 3.4rem);
    font-weight: 300;
    line-height: var(--leading-title);
    letter-spacing: var(--tracking-title);
    color: #000;
}

/* ------------------------------------------------------------- card grids */

html.theme-soda .soda-detail-similar .soda-grid,
html.theme-soda .soda-detail-variants .soda-grid {
    gap: 0;
}

/* Cells are hairline-SEPARATED, the same object as the homepage's featured
   stock and the catalogue's listing — never individually bordered boxes. */
html.theme-soda .soda-detail-similar .soda-grid > *,
html.theme-soda .soda-detail-variants .soda-grid > * {
    border: 0;
    border-right: 1px solid rgba(0, 0, 0, .15);
    background: transparent;
    padding: 1.667vw;
}

html.theme-soda .soda-detail-similar .soda-grid > *:last-child,
html.theme-soda .soda-detail-variants .soda-grid > *:last-child {
    border-right: 0;
}

@media (max-width: 900px) {
    html.theme-soda .soda-detail__grid {
        grid-template-columns: 1fr;
    }

    html.theme-soda .soda-detail__media {
        border-right: 0;
        border-bottom: 1px solid rgba(0, 0, 0, .15);
    }

    html.theme-soda .soda-detail__buybox {
        padding: 1.5rem;
    }

    html.theme-soda .soda-detail-similar .soda-grid > *,
    html.theme-soda .soda-detail-variants .soda-grid > * {
        padding: 1.25rem;
        border-right: 0;
        border-bottom: 1px solid rgba(0, 0, 0, .15);
    }

    html.theme-soda .soda-detail-similar .soda-grid > *:last-child,
    html.theme-soda .soda-detail-variants .soda-grid > *:last-child {
        border-bottom: 0;
    }
}

/* ==========================================================================
   21ST EXACT TRANSPLANT — product-detail.md
   ==========================================================================

   Ported element by element from the supplied 21st source, not from a picture
   of it. Every number below is the Tailwind class the source actually carries,
   resolved through the --t21-* scale in tokens.css; where a value has no token
   it is written out with the class it translates beside it.

   WHAT THE SOURCE HAS THAT U JABKA DOES NOT, and is therefore NOT invented:
     - a star rating and a rating number (no rating authority exists here);
     - a marketplace SELLER with an avatar photo and "All listings" (U Jabka is
       a first-party shop — the block states that instead);
     - "Contact Seller" (mapped onto the real mailto affordance the used-unit
       page already carried);
     - "Find Similar" visual search (mapped onto the real similar-items block);
     - a per-product shipping cost (every delivery method in this checkout is
       free, so the suffix says so);
     - Favourite / Share ghost icon buttons (no favourites list, no share
       authority);
     - an inline "Read more" that truncates a long listing (nothing here is
       truncated, so the link is omitted rather than pointed at nothing).

   WHAT U JABKA HAS THAT THE SOURCE DOES NOT, and is therefore kept without a
   source slot: the canonical colour/capacity configurator, the quantity field,
   the paragraph 90 margin-scheme notice, the grade selector, the trust list
   and the variant cards. Those are business truth, not presentation.
   -------------------------------------------------------------------------- */

/* Source page frame: `w-full max-w-7xl mx-auto p-4 md:p-8`. The gutter cap is
   .soda-container's, kept so the frame cannot reach the viewport edge on a
   phone (and cannot cause a horizontal overflow). */
html.theme-soda .t21-pdp {
    width: 100%;
    /* `max-w-7xl` is flat in the source; the page's own p-4/md:p-8 is what
       holds it off the viewport edge, so no gutter clamp is added here. */
    max-width: var(--t21-max-7xl);
    margin-inline: auto;
    padding: var(--t21-4);                  /* p-4    = 1rem                */
}

@media (min-width: 768px) {
    html.theme-soda .t21-pdp {
        padding: var(--t21-8);              /* md:p-8 = 2rem                */
    }
}

/* -------------------------------------------------------------- breadcrumbs
   Source: `flex items-center text-sm text-muted-foreground mb-4`, with a
   `ChevronRight h-4 w-4 mx-1` between items. */
html.theme-soda .t21-pdp .t21-pdp__crumbs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0;
    margin: 0 0 var(--t21-4);               /* mb-4 = 1rem                  */
    padding: 0;
    list-style: none;
    font-size: var(--t21-fs-sm);            /* text-sm = .875rem / 1.25rem  */
    line-height: var(--t21-lh-sm);
    color: var(--ink-3);
}

html.theme-soda .t21-pdp .t21-pdp__crumbs > li {
    display: flex;
    align-items: center;
}

/* The component's own separator is a slash; the source's is a chevron glyph,
   so the generated one is switched off rather than doubled. */
html.theme-soda .t21-pdp .t21-pdp__crumbs li + li::before {
    content: none;
}

html.theme-soda .t21-pdp__crumb-sep {
    display: inline-flex;
    align-items: center;
    margin-inline: var(--t21-1);            /* mx-1 = .25rem                */
    color: var(--ink-3);
}

html.theme-soda .t21-pdp .t21-pdp__crumbs a {
    color: var(--ink-3);
    text-decoration: none;
    /* `hover:text-primary transition-colors` — Tailwind's 150ms default. */
    transition: color .15s var(--t21-ease-in-out);
}

html.theme-soda .t21-pdp .t21-pdp__crumbs a:hover {
    color: var(--ink);
}

/* ---------------------------------------------------------------- actions
   Source: `flex justify-between items-center mb-6`, a spacer on the left and
   ghost icon buttons on the right. The right pair has no U Jabka referent, so
   the row carries the real left-hand action this page already had. */
html.theme-soda .t21-pdp__actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--t21-6);            /* mb-6 = 1.5rem                */
}

html.theme-soda .t21-pdp__actions .soda-detail__back {
    margin-bottom: 0;
}

/* ------------------------------------------------------------------- main
   Source: `grid grid-cols-1 lg:grid-cols-2 gap-8 md:gap-12`. */
html.theme-soda .t21-pdp__main {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--t21-8);                      /* gap-8 = 2rem                 */
    align-items: start;
}

@media (min-width: 768px) {
    html.theme-soda .t21-pdp__main {
        gap: var(--t21-12);                 /* md:gap-12 = 3rem             */
    }
}

@media (min-width: 1024px) {
    html.theme-soda .t21-pdp__main {
        grid-template-columns: repeat(2, minmax(0, 1fr));  /* lg:grid-cols-2 */
    }
}

/* ---------------------------------------------------------------- gallery
   Source: `flex flex-col gap-4`. The plane's own media rules (a right-hand
   hairline, a sticky buy column) belonged to the two-pane layout this
   replaces and are switched off here. */
html.theme-soda .t21-pdp .t21-pdp__gallery {
    display: flex;
    flex-direction: column;
    gap: var(--t21-4);                      /* gap-4 = 1rem                 */
    padding: 0;
    border: 0;
    background: transparent;
}

html.theme-soda .t21-pdp .soda-gallery {
    margin: 0;
}

html.theme-soda .t21-pdp .soda-gallery__caption {
    margin-top: var(--t21-2);
    font-size: var(--t21-fs-sm);
    line-height: var(--t21-lh-sm);
    color: var(--ink-3);
}

/* Source: `flex items-center justify-between` under the frame. */
html.theme-soda .t21-pdp__gallery-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--t21-4);
}

/* shadcn Button `variant="outline" size="sm" className="gap-2"`:
   `h-9 rounded-md px-3 text-sm font-medium border bg-background`. */
html.theme-soda .t21-pdp__gallery-cta {
    display: inline-flex;
    align-items: center;
    gap: var(--t21-2);                      /* gap-2 = .5rem                */
    height: 2.25rem;                        /* h-9 — no token carries it    */
    padding-inline: var(--t21-3);           /* px-3 = .75rem                */
    border: 1px solid var(--line-hi);
    border-radius: var(--t21-radius-md);
    background: transparent;
    color: var(--ink);
    font-size: var(--t21-fs-sm);
    line-height: var(--t21-lh-sm);
    font-weight: 500;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color .15s var(--t21-ease-in-out);
}

html.theme-soda .t21-pdp__gallery-cta:hover {
    background: var(--hover-wash);
}

/* THE CROSS-FADE. product-detail.md wraps the frame in
   <AnimatePresence mode="wait"> with
     initial={{ opacity: 0, y: 20 }}
     animate={{ opacity: 1, y: 0 }}
     exit={{    opacity: 0, y: -20 }}
     transition={{ duration: 0.3 }}
   `mode="wait"` means the exit finishes before the entry starts, so a swap is
   two consecutive 300ms halves rather than a dissolve. soda/gallery.js drives
   it through the Web Animations API with exactly these keyframes; under
   prefers-reduced-motion it swaps the src with no animation at all. */

/* ---------------------------------------------------------------- details */
html.theme-soda .t21-pdp .t21-pdp__details {
    display: flex;
    flex-direction: column;
    padding: 0;
    border: 0;
    background: transparent;
    position: static;
}

/* `text-3xl md:text-4xl font-bold tracking-tight` */
html.theme-soda .t21-pdp .soda-detail__title {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--t21-fs-3xl);           /* text-3xl = 1.875rem / 2.25rem */
    line-height: var(--t21-lh-3xl);
    font-weight: 700;                       /* font-bold                    */
    letter-spacing: -.025em;                /* tracking-tight               */
    color: var(--ink);
}

@media (min-width: 768px) {
    html.theme-soda .t21-pdp .soda-detail__title {
        font-size: var(--t21-fs-4xl);       /* md:text-4xl = 2.25rem/2.5rem */
        line-height: var(--t21-lh-4xl);
    }
}

/* `<div className="mt-2">` holding `text-4xl font-bold` and a
   `text-sm text-muted-foreground ml-2` suffix. */
html.theme-soda .t21-pdp__price {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    margin-top: var(--t21-2);               /* mt-2 = .5rem                 */
}

html.theme-soda .t21-pdp .soda-detail__price {
    margin: 0;
    font-family: var(--font-display);
    font-size: var(--t21-fs-4xl);           /* text-4xl = 2.25rem / 2.5rem  */
    line-height: var(--t21-lh-4xl);
    font-weight: 700;                       /* font-bold                    */
    color: var(--ink);
    /* .soda-price contributes letter-spacing: -.02em. Neither source puts a
       tracking utility on its price span, so the ported slot sheds it -- the
       same shed already applied to the ported card title and badge. */
    letter-spacing: normal;
}

html.theme-soda .t21-pdp__price-suffix {
    margin-left: var(--t21-2);              /* ml-2 = .5rem                 */
    font-size: var(--t21-fs-sm);            /* text-sm                      */
    line-height: var(--t21-lh-sm);
    color: var(--ink-3);
}

/* -------------------------------------------------------------------- CTA
   Source: `flex gap-2 my-6` of `size="lg" className="flex-1 gap-2"` buttons.
   shadcn size="lg" is `h-11 rounded-md px-8`. */
html.theme-soda .t21-pdp__cta {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--t21-2);                      /* gap-2 = .5rem                */
    margin-block: var(--t21-6);             /* my-6  = 1.5rem               */
}

html.theme-soda .t21-pdp__cta-item {
    flex: 1 1 0;                            /* flex-1                       */
    min-width: 0;
}

html.theme-soda .t21-pdp .t21-pdp__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--t21-2);                      /* gap-2                        */
    width: 100%;
    min-height: 2.75rem;                    /* h-11 — no token carries it   */
    padding: 0 var(--t21-8);                /* px-8 = 2rem                  */
    border: 1px solid transparent;
    border-radius: var(--t21-radius-md);    /* rounded-md                   */
    background: var(--ink);
    color: #fff;
    font-family: var(--font-display);
    font-size: var(--t21-fs-sm);            /* text-sm font-medium          */
    line-height: var(--t21-lh-sm);
    font-weight: 500;
    text-align: center;
    text-decoration: none;
    /* shadcn's own `transition-colors` — 150ms on Tailwind's default curve. */
    transition: background-color .15s var(--t21-ease-in-out), color .15s var(--t21-ease-in-out);
}

html.theme-soda .t21-pdp .t21-pdp__btn:hover {
    background: color-mix(in srgb, var(--ink) 90%, #fff);
}

/* `variant="outline"`: `border border-input bg-background hover:bg-accent`. */
html.theme-soda .t21-pdp .t21-pdp__btn--outline {
    background: transparent;
    border-color: var(--line-hi);
    color: var(--ink);
}

html.theme-soda .t21-pdp .t21-pdp__btn--outline:hover {
    background: var(--hover-wash);
    color: var(--ink);
}

/* The source has no disabled state at all — it sells one listing that is always
   for sale. The plane's own disabled recipe (components.css) already answers
   this honestly on white, so only the cursor is stated here. */
html.theme-soda .t21-pdp .t21-pdp__btn[disabled] {
    cursor: not-allowed;
}

/* NO SOURCE SLOT. The quantity field is a real, existing control on the
   variant branch, so it joins the CTA row as its own flex child instead of
   being dropped; it keeps the source's control height so the row is level. */
html.theme-soda .t21-pdp__qty {
    display: flex;
    flex-direction: column;
    gap: var(--t21-1);
    flex: 0 0 auto;
}

html.theme-soda .t21-pdp__qty .soda-label {
    margin: 0;
    font-size: var(--t21-fs-xs);
    line-height: var(--t21-lh-xs);
    color: var(--ink-3);
    letter-spacing: normal;
    text-transform: none;
}

html.theme-soda .t21-pdp__qty .soda-input {
    width: 5rem;
    min-height: 2.75rem;
    border-radius: var(--t21-radius-md);
    font-size: var(--t21-fs-sm);
    line-height: var(--t21-lh-sm);
}

html.theme-soda .t21-pdp .t21-pdp__note {
    margin: 0 0 var(--t21-6);
    font-size: var(--t21-fs-sm);
    line-height: var(--t21-lh-sm);
    color: var(--ink-3);
}

/* ----------------------------------------------------------------- badges
   Source: `flex flex-wrap gap-2 mb-6` of
   `<Badge variant="secondary" className="text-sm font-normal py-1 px-3 gap-2">`
   with an optional `h-4 w-4` icon. shadcn Badge is `rounded-full border`;
   `variant="secondary"` is `border-transparent bg-secondary`. */
html.theme-soda .t21-pdp .t21-pdp__badges {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--t21-2);                      /* gap-2 = .5rem                */
    margin: 0 0 var(--t21-6);               /* mb-6  = 1.5rem               */
    padding: 0;
    list-style: none;
}

html.theme-soda .t21-pdp .t21-pdp__badge {
    display: inline-flex;
    align-items: center;
    gap: var(--t21-2);                      /* gap-2                        */
    padding: var(--t21-1) var(--t21-3);     /* py-1 px-3 = .25rem / .75rem  */
    border-radius: var(--t21-radius-full);  /* rounded-full                 */
    border: 1px solid transparent;          /* border-transparent           */
    background: var(--surface-2);           /* bg-secondary                 */
    color: var(--ink);
    font-family: inherit;
    font-size: var(--t21-fs-sm);            /* text-sm = .875rem / 1.25rem  */
    line-height: var(--t21-lh-sm);
    font-weight: 400;                       /* font-normal                  */
    letter-spacing: normal;
    text-transform: none;
}

/* The availability badge keeps the semantic state colours it already had —
   colour is never the only signal, every one of them carries its own words. */
html.theme-soda .t21-pdp .t21-pdp__badge.soda-badge--in-stock {
    background: color-mix(in srgb, var(--success) 16%, transparent);
    color: var(--success);
}

html.theme-soda .t21-pdp .t21-pdp__badge.soda-badge--on-order {
    background: color-mix(in srgb, var(--warning) 16%, transparent);
    color: var(--warning);
}

html.theme-soda .t21-pdp .t21-pdp__badge.soda-badge--sold-out {
    background: var(--surface-2);
    color: var(--ink-3);
}

/* ------------------------------------------------------------- description
   Source: `<p className="text-muted-foreground leading-relaxed">`. */
html.theme-soda .t21-pdp .t21-pdp__description {
    margin: 0;
    font-size: var(--t21-fs-base);          /* inherits text-base           */
    line-height: 1.625;                     /* leading-relaxed              */
    color: var(--ink-2);
}

html.theme-soda .t21-pdp .soda-detail__vat-note {
    margin-top: var(--t21-4);
}

/* -------------------------------------------------------------- foot block
   Source: `mt-8 pt-6 border-t` holding `flex justify-between items-center`. */
html.theme-soda .t21-pdp__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--t21-4);
    margin-top: var(--t21-8);               /* mt-8 = 2rem                  */
    padding-top: var(--t21-6);              /* pt-6 = 1.5rem                */
    border-top: 1px solid var(--line);      /* border-t                     */
}

html.theme-soda .t21-pdp__seller {
    display: flex;
    align-items: center;
    gap: var(--t21-4);                      /* gap-4 = 1rem                 */
}

/* The seller avatar uses the shipped U Jabka brand mark. */
html.theme-soda .t21-pdp__avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: var(--t21-size-12);              /* h-12 w-12 = 3rem             */
    height: var(--t21-size-12);
    border-radius: var(--t21-radius-full);
    background: var(--surface-2);
    color: var(--ink);
    font-family: var(--font-display);
    font-size: var(--t21-fs-lg);
    line-height: var(--t21-lh-lg);
    font-weight: 600;
}

html.theme-soda .t21-pdp__seller-name {
    margin: 0;
    font-size: var(--t21-fs-base);
    line-height: var(--t21-lh-base);
    font-weight: 600;                       /* font-semibold                */
    color: var(--ink);
}

/* The source's StarRating sits here. There is no rating authority in this
   shop, so the line states a fact instead of a number that would be invented.
   It keeps the rating's own type: `text-sm font-medium text-muted-foreground`. */
html.theme-soda .t21-pdp__seller-meta {
    display: flex;
    align-items: center;
    gap: var(--t21-2);
    margin: var(--t21-1) 0 0;
    font-size: var(--t21-fs-sm);
    line-height: var(--t21-lh-sm);
    font-weight: 500;
    color: var(--ink-3);
}

/* `<Button variant="link" className="text-primary">All listings &rarr;</Button>` */
html.theme-soda .t21-pdp__foot-link {
    flex: none;
    color: var(--ink);
    font-size: var(--t21-fs-sm);
    line-height: var(--t21-lh-sm);
    font-weight: 500;
    text-decoration: none;
    white-space: nowrap;
}

html.theme-soda .t21-pdp__foot-link:hover {
    text-decoration: underline;
}

/* --------------------------------------------------------------- the icons
   The inline lucide glyphs carry their pixel size as attributes so they are
   right with no stylesheet; these restate the same number in rem so they ride
   the artboard ladder exactly as `h-4 w-4` / `h-5 w-5` would. */
html.theme-soda .t21-pdp .soda-icon {
    flex: none;
}

html.theme-soda .t21-pdp .soda-icon--4 {
    width: var(--t21-size-4);               /* h-4 w-4 = 1rem               */
    height: var(--t21-size-4);
}

html.theme-soda .t21-pdp .soda-icon--5 {
    width: var(--t21-size-5);               /* h-5 w-5 = 1.25rem            */
    height: var(--t21-size-5);
}

/* The configurator and the battery meter keep their own recipes; only their
   spacing is refitted to the source's stack. */
html.theme-soda .t21-pdp .soda-configurator {
    margin-top: var(--t21-6);
}

html.theme-soda .t21-pdp .t21-pdp__badge.soda-detail-battery {
    padding: var(--t21-1) var(--t21-3);
    border-radius: var(--t21-radius-full);
    background: var(--surface-2);
    font-size: var(--t21-fs-sm);
    line-height: var(--t21-lh-sm);
}

/* ============================================== THE IN-CARD AXIS SWITCHERS

   OWNER-DIRECTED, NO SOURCE SLOT (2026-09-03). product-detail.md sells one
   marketplace listing and has no configuration axis at all, so nothing here is
   ported — it is the shop's own interaction, dressed in the recipe the source
   frame already carries.

   The owner asked for the jakost switcher to leave its own section far below
   the card and move INSIDE it, with barva and kapacita beside it, so that "the
   card is always the same and only the information changes — photo, price,
   availability". That is what these rules exist to make true:

     - the three axes sit in ONE `.soda-configurator`, in the same slot between
       the price and the CTA that the new-product branch already uses, so a used
       kus and a new product present their axes as the same object;
     - every option is a `.soda-config-option` — the chip the new-product
       configurator uses — so nothing about the shape changes between branches;
     - only the option's INNER stack is new: a used kus can say what each choice
       costs, how its battery reads and whether it is actually purchasable, and
       the grade nav's own facts had nowhere else to go once its section went.

   THE GEOMETRY IS FIXED PER CHIP, not per unit: label line, then a meta stack.
   Switching an axis therefore never reflows the card. */
html.theme-soda .t21-pdp__axes {
    /* .soda-configurator already draws the hairline above and sets the gap. */
    row-gap: var(--t21-5);
}

/* The chip is `.soda-config-option`; only the axis chips stack their content,
   so the new-product branch's single-label chips are untouched. */
html.theme-soda .t21-pdp .t21-pdp__opt {
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: var(--t21-1);
    min-width: 5.5rem;
    padding: var(--t21-2) var(--t21-3);
    text-align: left;
}

html.theme-soda .t21-pdp .t21-pdp__opt-label {
    font-family: var(--font-display);
    font-size: var(--t21-fs-sm);            /* text-sm                      */
    line-height: var(--t21-lh-sm);
    font-weight: 600;
    color: var(--ink);
}

/* The per-option facts the grade nav used to show, in the tighter slot:
   price first, then battery when the read model carries one, then the
   SERVER'S OWN availability label. Availability is the line that must survive
   a squeeze, so it is last in the stack and never abbreviated here. */
html.theme-soda .t21-pdp .t21-pdp__opt-meta {
    display: flex;
    flex-direction: column;
    gap: .1rem;
    min-width: 0;
    font-size: var(--t21-fs-xs);            /* text-xs = .75rem / 1rem      */
    line-height: var(--t21-lh-xs);
    font-weight: 400;
    color: var(--ink-3);
}

html.theme-soda .t21-pdp .t21-pdp__opt-meta strong {
    font-family: var(--font-display);
    font-size: var(--t21-fs-sm);
    line-height: var(--t21-lh-sm);
    font-weight: 600;
    color: var(--ink);
    letter-spacing: normal;
}

/* An unreachable value is a <span>, not an <a>: there is nothing to click and
   nothing to tab to.

   IT MUST STILL BE READABLE. `.soda-config-option.is-disabled` dims the whole
   chip to .42 and strikes every character in it — a recipe authored for a chip
   whose entire content is one word. Here the chip also carries the SERVER'S
   AVAILABILITY ANSWER, and at .42 on this plane that sentence lands near 1.8:1.
   So the strike moves onto the VALUE, which is the thing that is crossed out,
   and the words explaining why keep full contrast on a muted ground. */
html.theme-soda .t21-pdp .t21-pdp__opt.is-disabled {
    opacity: 1;
    background: var(--surface-2);
    color: var(--ink-3);
    text-decoration: none;
}

html.theme-soda .t21-pdp .t21-pdp__opt.is-disabled .t21-pdp__opt-label {
    color: var(--ink-2);
    text-decoration: line-through;
    text-decoration-thickness: 1px;
}

html.theme-soda .t21-pdp .t21-pdp__opt.is-disabled .t21-pdp__opt-meta strong {
    font-size: var(--t21-fs-xs);
    line-height: var(--t21-lh-xs);
    color: var(--ink-2);
}

@media (max-width: 420px) {
    /* .soda-config-option already goes two-up here; the axis chip inherits it
       and only needs its own floor removed so a long label can wrap. */
    html.theme-soda .t21-pdp .t21-pdp__opt {
        min-width: 0;
    }
}

/* ------------------------------------------------------------ trust block

   RE-HOMED, NOT DELETED (2026-09-03). "Ověřený kus od U Jabka" shared the grid
   with the grade switcher in the band this change removed. It is real trust
   copy about the kus on screen, not part of the switcher, so it moves into the
   page frame below the two columns and takes the source's own foot recipe
   (`mt-8 pt-6 border-t`) — the same rule the seller block below it uses. */
html.theme-soda .t21-pdp__trust {
    margin-top: var(--t21-8);               /* mt-8 = 2rem                  */
    padding-top: var(--t21-6);              /* pt-6 = 1.5rem                */
    border-top: 1px solid var(--line);      /* border-t                     */
    background: transparent;
}

@media (min-width: 768px) {
    /* Full page width for four short lines is a long thin column; two tracks
       keep the measure readable without changing a word. */
    html.theme-soda .t21-pdp__trust .soda-detail-trust__list {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        column-gap: var(--t21-8);
    }
}
