/* Products page - B60 OS. Tokens only (--ds-*). */

.products-page {
    padding: 0;
}

/*
 * The page scrolls, not a strip inside it.
 *
 * The shared list-page rules make the list card fill what is left of the
 * screen and give #productsView its own scrollbar. Above the card sit the
 * section tabs and up to two banners, so on the 730px till what was left was
 * a strip a few rows tall -- and on a short window nothing at all -- while the
 * rest of the screen stood still. Same release as Inventory's lists: every
 * level takes its natural height and .page-content is the one scroller.
 * The card's clip goes too, because sticky column headings need visible
 * overflow on every ancestor up to the scroller.
 */
.page-content > .products-page {
    flex: 0 0 auto;
}

.products-page > .ds-list-card {
    flex: 0 0 auto;
    overflow: visible;
}

/* The stack's own 16px gap already spaces the sections; the 24px document
   rhythm from components.css came on top of it, 40px apart where 16 was
   meant. Same override as Inventory's. */
.page-content .products-page.ds-page-stack > * + * {
    margin-top: 0;
}

/* Specific enough to beat `.ds-list-card > #productsView`. */
.products-page > .ds-list-card > #productsView {
    flex: 0 0 auto;
    min-height: 0;
    overflow: visible;
}

.products-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ds-space-3);
    min-height: 40px;
}

.products-toolbar .page-search {
    flex: 1 1 220px;
    min-width: 180px;
    position: relative;
}

.products-toolbar .page-search svg {
    position: absolute;
    inset-inline-start: var(--ds-space-3);
    top: 50%;
    transform: translateY(-50%);
    width: 16px;
    height: 16px;
    color: var(--ds-text-tertiary);
    pointer-events: none;
}

.products-toolbar .page-search .ds-input {
    width: 100%;
    min-height: 40px;
    height: 40px;
    padding-inline-start: calc(var(--ds-space-3) + 20px);
}

.products-toolbar .ds-select,
.products-toolbar .ds-btn {
    width: auto;
    min-height: 40px;
    height: 40px;
    min-width: 140px;
    flex: 0 1 auto;
}

.products-toolbar .ds-btn {
    min-width: 0;
}

@media (max-width: 900px) {
    .products-toolbar .ds-select,
    .products-toolbar .ds-btn,
    .products-toolbar .page-search {
        flex: 1 1 100%;
        width: 100%;
        max-width: none;
        min-width: 0;
    }
}

.products-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ds-space-4);
    flex-wrap: wrap;
    margin-block-end: var(--ds-space-4);
}

.products-panel-header h3 {
    margin: 0;
}

/* #productsView has no padding so a table runs to the card edge; the cards
   need their own, or they sit on the card border. */
.products-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: var(--ds-space-3);
    padding: var(--ds-space-3);
}

.products-grid-card {
    display: flex;
    flex-direction: column;
    gap: var(--ds-space-2);
    padding: var(--ds-space-3);
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
    cursor: pointer;
    text-align: start;
    transition: border-color var(--ds-motion-hover) var(--ds-ease-standard),
                box-shadow var(--ds-motion-hover) var(--ds-ease-standard);
}

:where(.can-hover) .products-grid-card:hover {
    border-color: var(--ds-border-strong);
    box-shadow: var(--ds-shadow-card);
}

.products-grid-card.is-sold-out {
    opacity: 0.65;
}

.products-grid-card-thumb {
    width: 100%;
    aspect-ratio: 1;
    border-radius: var(--ds-radius-md);
    overflow: hidden;
    background: var(--ds-surface-alt);
    display: flex;
    align-items: center;
    justify-content: center;
}

.products-grid-card-thumb .ds-initials,
.products-table-thumb .ds-initials {
    width: 100%;
    height: 100%;
    background: var(--ds-surface-alt);
    color: var(--ds-text-secondary);
    box-shadow: inset 0 0 0 1px var(--ds-border);
    border-radius: var(--ds-radius-md);
}

.products-grid-card-thumb img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.products-grid-card-name {
    font-weight: var(--ds-fw-semibold);
    font-size: var(--ds-text-sm);
    color: var(--ds-text-primary);
    line-height: var(--ds-leading-tight);
}

.products-grid-card-meta {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--ds-space-2);
    font-size: var(--ds-text-xs);
}

/* Ink, not purple: purple marks what can be pressed, and a price cannot. */
.products-grid-card-price {
    font-family: var(--ds-font-mono);
    font-weight: var(--ds-fw-semibold);
    color: var(--ds-text-primary);
}

.products-grid-card-actions {
    display: flex;
    gap: var(--ds-space-2);
    margin-block-start: var(--ds-space-1);
}

.products-table-thumb {
    width: 40px;
    height: 40px;
    border-radius: var(--ds-radius-md);
    overflow: hidden;
    background: var(--ds-surface-alt);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.products-table-thumb img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.products-table-product {
    display: flex;
    align-items: center;
    gap: var(--ds-space-3);
}

.products-table-wrap {
    overflow-x: auto;
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
}

/* Any overflow but visible makes the wrap a scroller of its own, and a sticky
   heading then sticks to the wrap instead of to the page. Phones keep the
   sideways scroll: the table is wider than their screen. */
@media (min-width: 769px) {
    .products-page .products-table-wrap {
        overflow: visible;
    }
}

/* Headings stay while the page scrolls. The background stops rows showing
   through; -10px matches .page-content's top padding, as on Inventory. */
.products-page .products-table-wrap .ds-table thead th {
    position: sticky;
    top: -10px;
    z-index: 1;
    background: var(--ds-surface-alt);
}

.products-table-wrap .ds-table {
    width: 100%;
    margin: 0;
}

.products-table-wrap .ds-table .num {
    text-align: end;
    font-variant-numeric: tabular-nums;
}

.products-table-actions {
    display: flex;
    gap: var(--ds-space-2);
    justify-content: flex-end;
}

/* ─── Product editor modal ──────────────────────────────────────────────────
 *
 * Structure only; every control inside is still a plain ds-* component.
 * See the comment on Products.showProductModal for why the form is arranged
 * this way.
 */

.pm-form {
    display: flex;
    flex-direction: column;
    gap: var(--ds-space-4);
}

/*
 * The one rule that makes syncKindFields() work.
 *
 * Three parts of this form hide themselves by setting `.hidden = true` from
 * JS: the price field on a raw ingredient, the happy-hour row with it, and the
 * recipe editor on anything that is not made to order. None of them ever
 * actually disappeared. `[hidden]` is a UA rule of `display:none`, and every
 * one of those elements carries an author rule that sets display explicitly --
 * .ds-field is display:flex, .products-form-row is display:grid -- which wins
 * at equal specificity simply for being in an author stylesheet.
 *
 * So a raw ingredient asked for a sale price it does not have, and every single
 * product showed an ingredients editor whether or not it was made to order.
 * That is a good part of what made this form feel like it was showing
 * everything at once: it was.
 */
.pm-form [hidden] {
    display: none !important;
}

.pm-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
    gap: var(--ds-space-4);
    align-items: start;
}

.pm-col {
    display: flex;
    flex-direction: column;
    gap: var(--ds-space-4);
    min-width: 0;
}

.pm-section {
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
    background: var(--ds-surface);
    padding: var(--ds-space-4);
    display: flex;
    flex-direction: column;
    gap: var(--ds-space-3);
    min-width: 0;
}

.pm-section-head {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.pm-section-title {
    margin: 0;
    font-size: var(--ds-text-sm);
    font-weight: var(--ds-fw-semibold);
    color: var(--ds-text-primary);
    letter-spacing: 0.01em;
}

.pm-section-hint {
    margin: 0;
    font-size: var(--ds-text-xs);
    line-height: 1.45;
    color: var(--ds-text-tertiary);
}

/*
 * Title-row affordance: a section whose content is a list you add rows to.
 * The section title already names the list, so a lone button sits at the end;
 * a row that carries its own sub-label (bundle contents) spreads instead.
 */
.pm-section-action {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--ds-space-2);
}

.pm-section-action:has(.ds-label) {
    justify-content: space-between;
}

/* Inside the editor the three kind cards share the main column, not the full
   dialog, so they run tighter than the 88px standalone version. */
.pm-form .products-kind-grid {
    margin-block-start: 0;
    gap: var(--ds-space-2);
}

.pm-form .products-kind-card {
    min-height: 0;
    gap: var(--ds-space-1);
    padding: var(--ds-space-3) var(--ds-space-2);
}

/* In the side column the three kinds stack: a third of that column is too
   narrow for a title and its one-line hint. */
.pm-col-side .products-kind-grid {
    grid-template-columns: 1fr;
}

.pm-col-side .products-kind-card {
    padding: var(--ds-space-2) var(--ds-space-3);
}

.pm-radio-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ds-space-3) var(--ds-space-4);
}

.pm-req {
    color: var(--ds-danger);
    font-weight: var(--ds-fw-semibold);
}

.pm-legend {
    margin: 0;
    font-size: var(--ds-text-xs);
    color: var(--ds-text-tertiary);
}

/* The side column is narrow; its pickers need to be too. */
.pm-col-side .products-image-drop {
    padding: var(--ds-space-4) var(--ds-space-3);
}

.pm-col-side .products-image-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

/*
 * One column below 860px. The dialog itself is capped at 920px and the overlay
 * keeps 16px each side, so this is the point at which two columns stop having
 * room for a label and its input on one line.
 */
@media (max-width: 860px) {
    .pm-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .pm-col-side .products-image-grid {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

/* Modal / editor sub-panels */
.products-image-drop {
    border: 2px dashed var(--ds-border-strong);
    border-radius: var(--ds-radius-lg);
    padding: var(--ds-space-6) var(--ds-space-4);
    text-align: center;
    cursor: pointer;
    color: var(--ds-text-secondary);
    background: var(--ds-bg-inset);
    transition: border-color var(--ds-motion-hover) var(--ds-ease-standard),
                background-color var(--ds-motion-hover) var(--ds-ease-standard);
}

.products-image-drop.is-dragover {
    border-color: var(--ds-primary);
    background: var(--ds-primary-tint);
    color: var(--ds-primary);
}

.products-image-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--ds-space-2);
}

.products-image-option {
    cursor: pointer;
    border: 2px solid var(--ds-border);
    border-radius: var(--ds-radius-md);
    overflow: hidden;
    aspect-ratio: 1;
    transition: border-color var(--ds-motion-hover) var(--ds-ease-standard);
}

.products-image-option.is-selected {
    border-color: var(--ds-primary);
}

.products-editor-panel {
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
    padding: var(--ds-space-3);
    margin-block-end: var(--ds-space-3);
    background: var(--ds-bg-inset);
}

.products-editor-row {
    display: flex;
    gap: var(--ds-space-2);
    align-items: center;
    margin-block-end: var(--ds-space-2);
}

.products-combo-cost-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--ds-space-2) var(--ds-space-3);
    background: var(--ds-bg-inset);
    border-radius: var(--ds-radius-md);
    font-size: var(--ds-text-xs);
    margin-block-start: var(--ds-space-2);
}

.products-form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--ds-space-3);
}

@media (max-width: 640px) {
    .products-form-row {
        grid-template-columns: 1fr;
    }
}

.products-spinner {
    width: 40px;
    height: 40px;
    border: 3px solid var(--ds-border);
    border-top-color: var(--ds-primary);
    border-radius: 50%;
    animation: products-spin 1s linear infinite;
    margin-inline: auto;
}

@keyframes products-spin {
    to { transform: rotate(360deg); }
}

/* Item-type hint under a form field (next-up.md #40). Explains why the
   stock input is absent for a Made-to-Order product. */
.products-field-hint {
    font-size: var(--ds-text-xs);
    color: var(--ds-text-tertiary);
    margin-block-start: var(--ds-space-1);
    line-height: 1.4;
}

.products-kind-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--ds-space-3);
    margin-block-start: var(--ds-space-2);
}

@media (max-width: 720px) {
    .products-kind-grid {
        grid-template-columns: 1fr;
    }
}

.products-kind-card {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--ds-space-2);
    text-align: start;
    padding: var(--ds-space-3);
    min-height: 88px;
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
    background: var(--ds-bg-inset);
    color: var(--ds-text-primary);
    cursor: pointer;
    transition: border-color var(--ds-motion-hover) var(--ds-ease-standard),
                background-color var(--ds-motion-hover) var(--ds-ease-standard);
}

.products-kind-card.is-selected {
    border-color: var(--ds-primary);
    background: var(--ds-primary-tint);
}

.products-kind-card-title {
    font-size: var(--ds-text-sm);
    font-weight: var(--ds-fw-semibold);
}

.products-kind-card-hint {
    font-size: var(--ds-text-xs);
    color: var(--ds-text-secondary);
    line-height: 1.35;
}

.products-missing-recipe-banner {
    display: flex;
    flex-direction: column;
    gap: var(--ds-space-1);
    padding: var(--ds-space-3) var(--ds-space-4);
    border: 1px solid var(--ds-warning);
    border-radius: var(--ds-radius-lg);
    background: rgba(245, 158, 11, 0.12);
    color: var(--ds-text-primary);
    font-size: var(--ds-text-sm);
}

/* Both banners' buttons hug their label. Stretched, the Arabic one became a
   full-width bar that outweighed the page's own Add Product button. */
.products-missing-recipe-banner .ds-btn {
    align-self: flex-start;
}

.products-missing-recipe-banner #showMissingRecipesBtn {
    align-self: flex-start;
    margin-block-start: var(--ds-space-1);
}

/* Editor sections that disclose on demand (photo, POS display, happy hour,
   bundle, modifiers). Closed, they are one title row; the chevron says so. */
.pm-disclosure > summary {
    cursor: pointer;
    list-style: none;
    position: relative;
    padding-inline-end: 28px;
    min-height: 24px;
}

.pm-disclosure > summary::-webkit-details-marker {
    display: none;
}

.pm-disclosure > summary::after {
    content: '';
    position: absolute;
    inset-inline-end: 6px;
    top: 4px;
    width: 8px;
    height: 8px;
    border-right: 2px solid var(--ds-text-secondary);
    border-bottom: 2px solid var(--ds-text-secondary);
    transform: rotate(45deg);
    transition: transform var(--ds-duration-fast, 120ms) var(--ds-ease-standard);
}

.pm-disclosure[open] > summary::after {
    top: 8px;
    transform: rotate(-135deg);
}

.pm-disclosure > summary:focus-visible {
    outline: 2px solid var(--ds-primary);
    outline-offset: 4px;
    border-radius: var(--ds-radius-sm);
}

/* Wave 4 T-N: repeated inline styles lifted from products.js (styles only) */
.products-flex-1 { flex: 1; }
.products-text-xs-m0 {
    font-size: var(--ds-text-xs);
    margin: 0;
}
.products-text-xs { font-size: var(--ds-text-xs); }
.products-text-sm { font-size: var(--ds-text-sm); }
.products-mh-40 { min-height: 40px; }
.products-empty-hidden {
    display: none;
    text-align: center;
    padding: var(--ds-space-6);
}
.products-mb-3 { margin-block-end: var(--ds-space-3); }
.products-w-100 { width: 100px; }
.products-w-88 { width: 88px; }
.products-muted { color: var(--ds-text-tertiary); }
.products-cover-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* --- Product editor as a side panel (Products.showProductModal) -----------
 *
 * One column, because the panel is 640px. Read top to bottom it answers, in
 * order: what is it (photo, name, price, category), what kind of item is it,
 * and then -- folded until wanted -- cost and stock, how it shows on the till,
 * options and bundles. The groups below the item type are rows divided by a
 * hairline rather than boxes inside a box: the panel is already the box.
 */
.pm-panel {
    gap: var(--ds-space-5);
}

.pm-hero {
    display: grid;
    grid-template-columns: 168px minmax(0, 1fr);
    gap: var(--ds-space-5);
    align-items: start;
}

.pm-hero-fields {
    display: flex;
    flex-direction: column;
    gap: var(--ds-space-3);
    min-width: 0;
}

/* The photo as the till draws it: the canvas, the plate (--ds-plate) at inset 9%,
   the cut-out at inset 3% with its soft shadow (redesign.css, section 3). */
.pm-photo {
    display: flex;
    flex-direction: column;
    gap: var(--ds-space-2);
}

.pm-photo-well {
    position: relative;
    width: 100%;
    aspect-ratio: 1 / 1;
    border-radius: var(--ds-radius-lg);
    background: var(--ds-canvas);
}

.pm-photo-well::before {
    content: '';
    position: absolute;
    inset: 9%;
    border-radius: 50%;
    background: var(--ds-plate);
}

.pm-photo-well img {
    position: absolute;
    inset: 3%;
    width: 94%;
    height: 94%;
    object-fit: contain;
    filter: drop-shadow(0 6px 8px rgba(30, 27, 57, 0.16));
}

.pm-photo-drop {
    aspect-ratio: 1 / 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--ds-space-2);
    padding: var(--ds-space-3);
}

.pm-photo-drop > svg {
    opacity: 0.45;
}

.pm-photo-drop-title {
    font-size: var(--ds-text-sm);
    font-weight: var(--ds-fw-semibold);
    color: var(--ds-text-primary);
}

.pm-photo-drop .ds-file {
    justify-content: center;
    margin: 0;
}

/* "No file chosen" says nothing the empty plate does not. */
.pm-photo-drop .ds-file-name {
    display: none;
}

/* Two faces, one class (Products._syncPhotoState). !important because the
   upload code sets the drop zone's display inline while it works. */
.pm-photo.has-image .pm-photo-drop {
    display: none !important;
}

.pm-photo:not(.has-image) [data-needs-image] {
    display: none !important;
}

.pm-photo-actions {
    display: flex;
    flex-direction: column;
    gap: var(--ds-space-1);
}

.pm-photo-actions > .ds-btn {
    width: 100%;
}

.pm-photo-pair {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--ds-space-1);
}

.pm-photo-remove {
    color: var(--ds-danger);
}

/* Gallery and search results sit in the form's own flow, full width, and
   leave no gap behind while they are closed. */
.pm-photo-extra {
    display: contents;
}

.pm-panel .products-image-grid {
    grid-template-columns: repeat(5, minmax(0, 1fr));
}

/* Item type as one segmented row. The selected kind's hint is the line under
   it (#productKindHint); the per-card hints stay in the markup for the old
   layout's sake and are not shown here. */
.pm-kind-seg {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 4px;
    margin: 0;
    padding: 4px;
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
    background: var(--ds-bg-inset);
}

.pm-kind-seg .products-kind-card {
    min-height: 40px;
    padding: var(--ds-space-2) var(--ds-space-3);
    align-items: center;
    justify-content: center;
    text-align: center;
    border: 1px solid transparent;
    border-radius: var(--ds-radius-md);
    background: transparent;
}

.pm-kind-seg .products-kind-card.is-selected {
    border-color: var(--ds-primary);
    background: var(--ds-surface);
    color: var(--ds-primary);
}

.pm-kind-seg .products-kind-card-hint {
    display: none;
}

.pm-kind .products-field-hint {
    margin: 0;
}

.pm-panel > .pm-section,
.pm-panel > .pm-disclosure {
    padding: var(--ds-space-4) 0 0;
    border: 0;
    border-top: 1px solid var(--ds-border);
    border-radius: 0;
    background: transparent;
}

@media (max-width: 560px) {
    .pm-hero {
        grid-template-columns: minmax(0, 1fr);
    }
    .pm-hero-photo {
        width: 168px;
        margin-inline: auto;
    }
}

/* --- Edit many at once (Products._bulkBarHtml) ---------------------------- */
.products-tick-cell {
    width: 48px;
    text-align: center;
}

.products-tick-cell .ds-checkbox {
    width: 22px;
    height: 22px;
}

.products-table-wrap tr.is-ticked > td {
    background: var(--ds-primary-tint);
}

/* Pinned to the bottom of the screen while the list scrolls under it; it is
   the last thing in #productsView, so it settles under the table at the end. */
.products-bulk-bar {
    position: sticky;
    bottom: 12px;
    z-index: 2;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ds-space-3);
    margin: var(--ds-space-3) var(--ds-space-3) 0;
    padding: var(--ds-space-3) var(--ds-space-4);
    border: 1px solid var(--ds-border);
    border-radius: var(--ds-radius-lg);
    background: var(--ds-surface);
    box-shadow: var(--ds-shadow-modal);
}

.products-bulk-count {
    font-size: var(--ds-text-sm);
    font-weight: var(--ds-fw-semibold);
    color: var(--ds-text-primary);
}

.products-bulk-bar .ds-select {
    width: auto;
    min-width: 200px;
    min-height: 40px;
}

.products-bulk-spacer {
    flex: 1;
}

/* --- Product panel, round two: readable at a glance -----------------------
 *
 * The essentials (tile, name, price, category) sit on a lightly tinted block
 * with white fields on it, so "fill this" reads before anything else; the
 * photo column is the till tile itself; folded sections show their state.
 */
.pm-panel .pm-hero {
    padding: var(--ds-space-4);
    border: 1px solid color-mix(in srgb, var(--ds-primary) 12%, transparent);
    border-radius: 16px;
    background: color-mix(in srgb, var(--ds-primary) 4%, var(--ds-surface));
}

.pm-panel .pm-hero .ds-input,
.pm-panel .pm-hero .ds-select {
    background-color: var(--ds-surface);
}

/* Required fields read first: their labels are ink, the rest secondary. */
.pm-panel .ds-label:has(.pm-req) {
    font-weight: var(--ds-fw-semibold);
    color: var(--ds-text-primary);
}

/* The tile: canvas square, the plate, initials until there is a photo. */
.pm-panel .pm-photo-drop {
    position: relative;
    padding: 0;
    border: 1px dashed color-mix(in srgb, var(--ds-primary) 30%, transparent);
    border-radius: var(--ds-radius-lg);
    background: var(--ds-canvas);
}

.pm-panel .pm-photo-drop::before {
    content: '';
    position: absolute;
    inset: 9%;
    border-radius: 50%;
    background: var(--ds-plate);
}

:where(.can-hover) .pm-panel .pm-photo-drop:hover::before {
    background: var(--ds-plate-hover);
}

.pm-tile-initials {
    position: relative;
    font-size: 30px;
    font-weight: 700;
    color: var(--ds-primary-press, var(--ds-primary));
}

.pm-photo-drop-cam {
    position: absolute;
    inset-inline-end: 10px;
    bottom: 10px;
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--ds-primary);
    color: var(--ds-text-on-accent, #fff);
    box-shadow: 0 2px 6px rgba(30, 27, 57, 0.2);
}

/* The file picker stays in the page for keyboards and the drop handler;
   the tile itself is what you tap. */
.pm-panel .pm-photo-drop .ds-file {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

.pm-tile-text {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
    min-height: 40px;
    text-align: center;
}

.pm-tile-name {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 15px;
    font-weight: 600;
    color: var(--ds-text-primary);
}

.pm-tile-name.is-empty {
    color: var(--ds-text-tertiary);
    font-weight: 500;
}

.pm-tile-price {
    font-size: 14px;
    color: var(--ds-text-secondary);
    font-variant-numeric: tabular-nums;
}

.pm-photo.has-image [data-needs-no-image] {
    display: none !important;
}

/* Price with its currency inside the box. */
.pm-money {
    position: relative;
}

.pm-money .ds-input {
    padding-inline-end: 52px;
    font-variant-numeric: tabular-nums;
}

.pm-money-cur {
    position: absolute;
    inset-inline-end: 12px;
    top: 50%;
    transform: translateY(-50%);
    font-size: var(--ds-text-xs);
    font-weight: var(--ds-fw-semibold);
    color: var(--ds-text-tertiary);
    pointer-events: none;
}

/* Category with its colour. */
.pm-cat {
    position: relative;
}

.pm-cat-dot {
    position: absolute;
    inset-inline-start: 12px;
    top: 50%;
    width: 12px;
    height: 12px;
    margin-top: -8px;
    border-radius: 50%;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.12);
    pointer-events: none;
}

.pm-cat-dot.is-empty {
    display: none;
}

.pm-cat:has(.pm-cat-dot:not(.is-empty)) .ds-select {
    padding-inline-start: 32px;
}

/* Item type: icon and word, the chosen one filled. */
.pm-kind-seg .products-kind-card {
    flex-direction: row;
    gap: var(--ds-space-2);
}

.pm-kind-icon {
    display: inline-flex;
    opacity: 0.7;
}

.pm-kind-seg .products-kind-card.is-selected {
    border-color: color-mix(in srgb, var(--ds-primary) 45%, transparent);
    background: var(--ds-primary-tint);
    color: var(--ds-primary-press, var(--ds-primary));
}

.pm-kind-seg .products-kind-card.is-selected .pm-kind-icon {
    opacity: 1;
}

/* Folded sections: the state line, and an icon to scan the panel by. */
.pm-section-state {
    color: var(--ds-text-secondary);
    font-weight: var(--ds-fw-medium, 500);
}

.pm-section-state.is-empty {
    color: var(--ds-text-tertiary);
}

.pm-disclosure .pm-section-title {
    display: flex;
    align-items: center;
    gap: var(--ds-space-2);
}

.pm-disclosure:has([data-pm-state]) .pm-section-title::before {
    content: '';
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    background: var(--ds-primary);
    -webkit-mask: var(--pm-icon) center / contain no-repeat;
    mask: var(--pm-icon) center / contain no-repeat;
}

.pm-disclosure:has([data-pm-state="cost"]) {
    --pm-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Crect x='2' y='6' width='20' height='12' rx='2'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E");
}

.pm-disclosure:has([data-pm-state="till"]) {
    --pm-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Crect x='2' y='3' width='20' height='14' rx='2'/%3E%3Cline x1='8' y1='21' x2='16' y2='21'/%3E%3Cline x1='12' y1='17' x2='12' y2='21'/%3E%3C/svg%3E");
}

.pm-disclosure:has([data-pm-state="modifiers"]) {
    --pm-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Cline x1='4' y1='21' x2='4' y2='14'/%3E%3Cline x1='4' y1='10' x2='4' y2='3'/%3E%3Cline x1='12' y1='21' x2='12' y2='12'/%3E%3Cline x1='12' y1='8' x2='12' y2='3'/%3E%3Cline x1='20' y1='21' x2='20' y2='16'/%3E%3Cline x1='20' y1='12' x2='20' y2='3'/%3E%3Cline x1='1' y1='14' x2='7' y2='14'/%3E%3Cline x1='9' y1='8' x2='15' y2='8'/%3E%3Cline x1='17' y1='16' x2='23' y2='16'/%3E%3C/svg%3E");
}

.pm-disclosure:has([data-pm-state="bundle"]) {
    --pm-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Cpolyline points='12 2 2 7 12 12 22 7 12 2'/%3E%3Cpolyline points='2 17 12 22 22 17'/%3E%3Cpolyline points='2 12 12 17 22 12'/%3E%3C/svg%3E");
}

/* --- Folded sections: a card with an accent tab ----------------------------
 *
 * Each section is a card with an accent tab in its top corner holding the
 * arrow, so the tab reads as the button. The whole card is the summary
 * (negative margin over the padding), so the tab and the row both open it.
 */
.pm-panel > .pm-disclosure {
    --pm-tab: 40px;
    position: relative;
    padding: 16px var(--ds-space-4);
    border: 1px solid color-mix(in srgb, var(--ds-primary) 16%, var(--ds-border));
    border-radius: 18px;
    border-start-end-radius: 0;
    background: color-mix(in srgb, var(--ds-primary) 4%, var(--ds-surface));
    box-shadow: 0 1px 2px rgba(30, 27, 57, 0.05);
    transition: box-shadow var(--ds-duration-fast, 120ms) var(--ds-ease-standard),
        border-color var(--ds-duration-fast, 120ms) var(--ds-ease-standard);
}

/* Closed, the hidden body would still take a flex gap under the title. */
.pm-panel > .pm-disclosure:not([open]) {
    display: block;
}

.pm-panel > .pm-disclosure > summary {
    margin: -16px calc(-1 * var(--ds-space-4));
    padding: 16px var(--ds-space-4);
    padding-inline-end: calc(var(--pm-tab) + 12px);
    border-radius: inherit;
}

/* The tab: flush with the card's top and end edges, its inner corner round. */
.pm-panel > .pm-disclosure > summary::before {
    content: '';
    position: absolute;
    top: -1px;
    inset-inline-end: -1px;
    width: var(--pm-tab);
    height: var(--pm-tab);
    background: var(--ds-primary);
    border-end-start-radius: 16px;
}

/* The arrow: the same box as the tab, the chevron masked into its centre. */
.pm-panel > .pm-disclosure > summary::after {
    top: -1px;
    inset-inline-end: -1px;
    width: var(--pm-tab);
    height: var(--pm-tab);
    border: 0;
    background: var(--ds-text-on-accent, #fff);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") center / 16px 16px no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") center / 16px 16px no-repeat;
    transform: none;
    z-index: 1;
}

.pm-panel > .pm-disclosure[open] > summary::after {
    top: -1px;
    transform: rotate(180deg);
}

:where(.can-hover) .pm-panel > .pm-disclosure:hover {
    border-color: color-mix(in srgb, var(--ds-primary) 32%, var(--ds-border));
    box-shadow: 0 4px 12px rgba(30, 27, 57, 0.08);
}

/* Open: the card turns white; the arrow points up, to fold it back. */
.pm-panel > .pm-disclosure[open] {
    border-color: var(--ds-border);
    background: var(--ds-surface);
}

@media (prefers-reduced-motion: reduce) {
    .pm-panel > .pm-disclosure,
    .pm-panel > .pm-disclosure > summary::after {
        transition: none;
    }
}
