/* Stash workspace composition — ported from the approved prototype
   (123123/stash-proto-2_claud.html): character head, stat cards, toolbar
   (category tabs / search / sort), per-category sections with rows, empty
   states. Page CSS arranges controls and consumes --vt-* tokens only;
   shared ui-* components (ui-button) are never restyled here. */

/* --- workspace column: right of the sidebar, full remaining width --- */

.st-ws {
    grid-column: 2;
    min-width: 0;
    padding: clamp(18px, 3vw, 30px) clamp(16px, 3.4vw, 34px) 110px;
}

.vt-stash[data-sidebar-open="false"] .st-ws {
    grid-column: 1;
}

/* Lists container: row layout depends on real content width (open/collapsed
   sidebar changes it without a viewport change), hence container queries. */
.st-sections {
    container-type: inline-size;
    container-name: strows;
}

/* Client-side tab/search filtering toggles the hidden attribute; explicit
   display rules would otherwise override it. */
.st-row[hidden],
.st-sec[hidden] {
    display: none;
}

/* ---------- character head ---------- */

.st-title-row {
    display: flex;
    align-items: center;
    gap: 12px;
}

.st-plat-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    flex: none;
    border-radius: 10px;
    color: var(--vt-text-2);
    background: linear-gradient(155deg, var(--vt-panel-2), var(--vt-panel));
    box-shadow: inset 0 0 0 1px var(--vt-line);
}

.st-plat-mark svg {
    width: 18px;
    height: 18px;
}

.st-title {
    font-family: var(--vt-disp);
    font-size: clamp(24px, 3.4vw, 32px);
    line-height: 1.08;
    font-weight: 800;
    letter-spacing: -0.01em;
    margin: 0;
}

.st-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: 18px;
    flex-wrap: wrap;
}

.st-sub {
    font-size: 13px;
    color: var(--vt-text-2);
    margin: 6px 0 0;
}

.st-sub b {
    color: var(--vt-text);
    font-weight: 600;
}

.st-sub time {
    font-family: var(--vt-mono);
    font-size: 12px;
}

.st-head-actions {
    display: flex;
    gap: 10px;
    flex: none;
}

.st-none--empty .st-head-actions {
    justify-content: center;
    margin-top: 14px;
}

@media (max-width: 560px) {
    .st-head-actions {
        width: 100%;
    }

    .st-head-actions .ui-button {
        width: 100%;
        justify-content: center;
    }
}

/* ---------- stats: cards ---------- */

.st-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 10px;
    margin: 22px 0 28px;
}

.st-stat {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 13px 16px;
    background: var(--vt-panel);
    border: 1px solid var(--vt-line);
    border-radius: var(--vt-r-md);
    transition: border-color 0.15s, transform 0.15s;
}

.st-stat:hover {
    border-color: var(--vt-text-3);
}

.st-stat-ico {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    flex: none;
    border-radius: 10px;
}

.st-stat:nth-child(1) .st-stat-ico {
    color: var(--vt-blue-2);
    background: color-mix(in srgb, var(--vt-blue) 16%, transparent);
}

.st-stat:nth-child(2) .st-stat-ico {
    color: var(--vt-text-2);
    background: color-mix(in srgb, var(--vt-text-2) 14%, transparent);
}

.st-stat:nth-child(3) .st-stat-ico {
    color: var(--vt-yellow-2);
    background: color-mix(in srgb, var(--vt-yellow) 16%, transparent);
}

.st-stat:nth-child(4) .st-stat-ico {
    color: var(--vt-green);
    background: color-mix(in srgb, var(--vt-green) 16%, transparent);
}

.st-stat-copy {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.st-stat-label {
    font-family: var(--vt-mono);
    font-size: 10px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--vt-text-3);
    line-height: 1.3;
}

.st-stat-value {
    font-family: var(--vt-mono);
    font-size: 19px;
    font-weight: 600;
    color: var(--vt-text);
    line-height: 1.2;
}

.st-stat-value small {
    font-size: 11px;
    color: var(--vt-text-3);
    font-weight: 400;
    margin-left: 3px;
}

/* ---------- toolbar: categories + search/sort ---------- */

.st-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    align-items: center;
    margin: 0 0 22px;
}

.st-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.st-tab {
    font-family: var(--vt-mono);
    font-size: 12px;
    letter-spacing: 0.02em;
    color: var(--vt-text-2);
    background: var(--vt-panel);
    border: 1px solid var(--vt-line);
    border-radius: 999px;
    min-height: 34px;
    padding: 7px 14px;
    cursor: pointer;
    transition: border-color 0.15s, color 0.15s, background 0.15s, box-shadow 0.15s;
}

.st-tab small {
    color: var(--vt-text-3);
    margin-left: 5px;
    font-size: 11px;
}

.st-tab:hover {
    border-color: var(--vt-text-3);
    color: var(--vt-text);
}

.st-tab:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: 2px;
}

.st-tab.is-active {
    background: color-mix(in srgb, var(--vt-yellow) 14%, transparent);
    border-color: color-mix(in srgb, var(--vt-yellow) 55%, transparent);
    color: var(--vt-yellow-2);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--vt-yellow) 10%, transparent);
}

.st-tab.is-active small {
    color: var(--vt-yellow-2);
    opacity: 0.75;
}

.st-filters {
    display: flex;
    gap: 8px;
    margin-left: auto;
}

.st-search {
    position: relative;
}

.st-search svg {
    position: absolute;
    left: 11px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--vt-text-3);
    pointer-events: none;
}

.st-search input {
    font: inherit;
    font-size: 13px;
    color: var(--vt-text);
    background: var(--vt-bg-2);
    border: 1px solid var(--vt-line);
    border-radius: 9px;
    padding: 9px 12px 9px 34px;
    width: 220px;
    outline: none;
    transition: border-color 0.15s, box-shadow 0.15s;
}

.st-search input:focus {
    border-color: color-mix(in srgb, var(--vt-yellow) 45%, transparent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--vt-yellow) 10%, transparent);
}

.st-search input::placeholder {
    color: var(--vt-text-3);
}

.st-select {
    font: inherit;
    font-size: 13px;
    color: var(--vt-text-2);
    background: var(--vt-bg-2);
    border: 1px solid var(--vt-line);
    border-radius: 9px;
    padding: 9px 10px;
    cursor: pointer;
    transition: border-color 0.15s;
}

.st-select:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: 1px;
}

/* ---------- columns popover (Step 8) ----------
   Trigger styled like the sibling toolbar controls; the disclosure reuses
   .st-pop mechanics (one open at a time, outside-click / Esc close). */

.st-colwrap {
    position: relative;
}

.st-col-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font: inherit;
    font-size: 13px;
    color: var(--vt-text-2);
    background: var(--vt-bg-2);
    border: 1px solid var(--vt-line);
    border-radius: 9px;
    padding: 9px 12px;
    cursor: pointer;
    transition: border-color 0.15s, color 0.15s;
}

.st-col-btn svg {
    width: 14px;
    height: 14px;
    flex: none;
}

.st-col-btn:hover {
    color: var(--vt-text);
    border-color: var(--vt-text-3);
}

.st-col-btn:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: 1px;
}

.st-col-btn[aria-expanded="true"] {
    color: var(--vt-text);
    border-color: var(--vt-text-3);
}

.st-colpop {
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    min-width: 200px;
    padding: 8px;
}

/* ---------- category section header ---------- */

.st-sec {
    margin-bottom: 28px;
}

.st-sec-head {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
}

.st-sec-title {
    position: relative;
    padding-left: 14px;
    font-family: var(--vt-disp);
    font-size: 16px;
    font-weight: 700;
    letter-spacing: 0.01em;
    color: var(--vt-text);
    margin: 0;
}

.st-sec-title::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    translate: 0 -50%;
    width: 5px;
    height: 5px;
    border-radius: 2px;
    background: var(--vt-yellow);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--vt-yellow) 18%, transparent);
}

.st-sec--zero .st-sec-title {
    color: var(--vt-text-3);
}

.st-sec-count {
    font-family: var(--vt-mono);
    font-size: 10.5px;
    color: var(--vt-text-3);
    background: var(--vt-panel-2);
    border: 1px solid var(--vt-line);
    border-radius: 999px;
    padding: 2px 8px;
}

.st-sec-rule {
    flex: 1;
    height: 1px;
    background: linear-gradient(90deg, var(--vt-line-soft), transparent);
    align-self: center;
}

.st-list {
    display: flex;
    flex-direction: column;
    gap: 7px;
}

/* ---------- item row ---------- */
/* Wide layout is a flex row so hidden columns (Step 8 visibility classes)
   collapse without a grid-template combination per hidden-column subset;
   the narrow card layout below switches back to the prototype's grid. */

.st-row {
    position: relative;
    display: flex;
    align-items: center;
    column-gap: 10px;
    background: var(--vt-panel);
    border: 1px solid var(--vt-line);
    border-radius: var(--vt-r-md);
    padding: 10px 16px 10px 12px;
    transition: border-color 0.15s, background 0.15s, box-shadow 0.15s, transform 0.15s;
}

.st-row:hover {
    border-color: color-mix(in srgb, var(--vt-yellow) 28%, var(--vt-line));
    box-shadow: 0 10px 24px -14px rgba(0, 0, 0, 0.55);
}

.st-row--zero {
    border-style: dashed;
    background: transparent;
}

.st-row--zero .st-r-icon {
    box-shadow: inset 0 0 0 1px var(--vt-line-soft);
}

.st-row--zero .st-r-icon svg {
    opacity: 0.4;
}

.st-row--zero .st-r-name {
    color: var(--vt-text-2);
}

.st-r-icon {
    flex: none;
    height: 44px;
    width: 44px;
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 11px;
    background: radial-gradient(circle at 30% 22%, rgba(243, 244, 246, 0.09), transparent 72%), var(--vt-panel-2);
    box-shadow: inset 0 0 0 1px var(--vt-line);
}

.st-row[data-cat="weapons"] .st-r-icon {
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--vt-red) 30%, var(--vt-line));
}

.st-row[data-cat="armor"] .st-r-icon {
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--vt-blue) 32%, var(--vt-line));
}

.st-row[data-cat="ammo"] .st-r-icon {
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--vt-green) 32%, var(--vt-line));
}

.st-row[data-cat="star_boxes"] .st-r-icon {
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--vt-yellow) 38%, var(--vt-line));
}

.st-r-icon svg {
    height: 26px;
    width: auto;
    opacity: 0.95;
}

.st-r-main {
    flex: 3 1 220px;
    min-width: 0;
    display: flex;
    align-items: baseline;
}

.st-r-name {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    overflow: hidden;
    min-width: 0;
    font-size: 13.5px;
    font-weight: 600;
    line-height: 1.35;
    color: var(--vt-text);
}

.st-r-zero-tag {
    font-family: var(--vt-mono);
    font-size: 9.5px;
    color: var(--vt-text-3);
    border: 1px solid var(--vt-line);
    border-radius: 5px;
    padding: 1px 5px;
    letter-spacing: 0.06em;
    margin-right: 7px;
    vertical-align: 1px;
}

/* Legendary star badge (wiki-consistent repeated ★ presentation), driven by
   the hydration data — rows without a resolved star rank never render it. */
.st-r-star {
    flex: none;
    font-size: 10px;
    line-height: 1;
    letter-spacing: 0.12em;
    color: var(--vt-yellow);
    white-space: nowrap;
    margin-left: 8px;
}

.st-r-w {
    flex: none;
    font-family: var(--vt-mono);
    font-size: 12px;
    color: var(--vt-text-3);
    white-space: nowrap;
    text-align: right;
}

.st-r-w b {
    color: var(--vt-text-2);
    font-weight: 500;
}

.st-r-w2 {
    display: none;
    font-family: var(--vt-mono);
    font-size: 11px;
    color: var(--vt-text-3);
    margin-left: 8px;
    white-space: nowrap;
    flex: none;
}

/* On desktop the flags container dissolves: each cell is its own flex item
   sized like the prototype's flag columns. */
.st-r-flags {
    display: contents;
}

.st-r-flags > * {
    min-width: 0;
}

.st-c-sell,
.st-c-buy {
    flex: 1.15 1 172px;
}

/* Craft/show cells hold only the 32px toggle — no price chip needs room, so
   they collapse to their button and the freed width flows to the name. */
.st-c-craft,
.st-c-show {
    flex: 0 0 auto;
}

.st-r-cell {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    overflow: visible;
}

/* ---------- column visibility (Step 8, D4) ----------
   stash.js toggles one st-hide-* class per hidden column on #stash-workspace
   (persisted in localStorage); the rules below remove the cells from the
   visual grid of EVERY row at once — purely presentational, no data change.
   Specificity (3 classes) beats the container-query display overrides. */
.st-ws.st-hide-weight .st-r-w,
.st-ws.st-hide-weight .st-r-w2,
.st-ws.st-hide-sell .st-c-sell,
.st-ws.st-hide-buy .st-c-buy,
.st-ws.st-hide-craft .st-c-craft,
.st-ws.st-hide-show .st-c-show {
    display: none;
}

.st-flag {
    position: relative;
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 1px solid var(--vt-line-soft);
    border-radius: 9px;
    background: var(--vt-bg-2);
    color: var(--vt-text-3);
    font: inherit;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s, background 0.15s, transform 0.1s;
}

.st-flag:hover {
    color: var(--vt-text-2);
    border-color: var(--vt-line);
    transform: translateY(-1px);
}

.st-flag:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: 2px;
}

.st-flag svg {
    width: 15px;
    height: 15px;
    flex: none;
}

.st-flag.is-on--show {
    color: var(--vt-green);
    border-color: color-mix(in srgb, var(--vt-green) 42%, transparent);
    background: color-mix(in srgb, var(--vt-green) 11%, transparent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--vt-green) 10%, transparent);
}

/* Quantity-masked state of the show flag (tri-state eye): the same green
   "on" look plus a diagonal strike over the icon — "shown, but the exact
   amount is withheld". */
.st-flag.is-masked-qty::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: 19px;
    height: 2px;
    border-radius: 1px;
    background: currentColor;
    transform: translate(-50%, -50%) rotate(-45deg);
    pointer-events: none;
}

.st-flag.is-on--sell {
    color: var(--vt-yellow-2);
    border-color: color-mix(in srgb, var(--vt-yellow) 42%, transparent);
    background: color-mix(in srgb, var(--vt-yellow) 10%, transparent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--vt-yellow) 9%, transparent);
}

.st-flag.is-on--buy {
    color: var(--vt-blue-2);
    border-color: color-mix(in srgb, var(--vt-blue) 46%, transparent);
    background: color-mix(in srgb, var(--vt-blue) 12%, transparent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--vt-blue) 10%, transparent);
}

.st-flag.is-on--craft {
    color: var(--vt-text);
    border-color: color-mix(in srgb, var(--vt-text-2) 48%, transparent);
    background: color-mix(in srgb, var(--vt-text-2) 12%, transparent);
}

/* ---------- price chips + price popover (Step 7) ----------
   The chip shows the active mode ("Своя цена · 250", "за «...»"); clicking it
   opens the mode popover anchored to the sell/buy flag cell (prototype §2.6). */

.st-c-sell,
.st-c-buy {
    position: relative;
}

.st-price {
    font-family: var(--vt-mono);
    font-size: 11px;
    white-space: nowrap;
}

button.st-price {
    display: inline-block;
    font: inherit;
    color: inherit;
    cursor: pointer;
    background: color-mix(in srgb, currentColor 9%, transparent);
    border: 1px solid color-mix(in srgb, currentColor 22%, transparent);
    border-radius: 999px;
    padding: 5px 9px;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    transition: background 0.15s, border-color 0.15s;
}

button.st-price:hover {
    background: color-mix(in srgb, currentColor 16%, transparent);
}

button.st-price:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: 2px;
}

.st-price--sell {
    color: var(--vt-yellow-2);
}

.st-price--buy {
    color: var(--vt-blue-2);
}

.st-price small {
    opacity: 0.7;
}

.st-pop.st-ppop {
    /* double-class specificity: .st-pop's later align-items:center (qty
       popover base) must not shrink-to-fit the price editor panel */
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    padding: 10px;
    width: 300px;
    z-index: 70;
    /* Never leave the viewport: if the anchored panel would overflow (rows
       near the page bottom + tall barter results), the panel itself scrolls
       internally; overscroll-behavior stops the wheel from chaining into the
       page once the panel edge is reached. */
    max-height: calc(100vh - 24px);
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* Viewport-clamp flip (stash.js placePricePopover): when the panel would
   overflow downward and there is more room above the anchor cell, it opens
   upward instead. Left/right anchoring is inherited from the base rules. */
.st-pop.st-ppop.st-ppop--up {
    top: auto;
    bottom: calc(100% + 6px);
}

/* Price editor (Step 7 redesign): a vertical mode list, then the extra zone
   for the active mode (currency + amount for 'caps', quick chips + wiki
   search + stack size for 'item'), closed by a full-width Done button. */
/* The form is the popover's single flex child: an explicit full-width column
   so the mode list, extra zone and Done button always stack inside the 264px
   panel (.st-pop's later align-items:center would otherwise shrink-to-fit and
   overflow the anchor). */
.st-pop .st-price-form {
    /* .st-pop form (below) centers its items for the qty popover row; the
       price editor needs a full-width column, so it out-specifies it here. */
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    width: 100%;
    min-width: 0;
    margin: 0;
}

.st-pp-modes {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.st-pp-opt {
    font: inherit;
    font-size: 12.5px;
    color: var(--vt-text-3);
    text-align: left;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 8px;
    padding: 7px 10px;
    min-height: 32px;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s, background 0.15s;
}

.st-pp-opt:hover {
    color: var(--vt-text-2);
    border-color: var(--vt-text-3);
}

.st-pp-opt:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: 1px;
}

.st-pp-opt.is-active {
    color: var(--vt-text);
    border-color: var(--vt-line);
    background: color-mix(in srgb, var(--vt-blue) 14%, transparent);
}

.st-pp-extra {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--vt-line-soft);
}

/* The hidden attribute toggles zone visibility from JS; without this the
   display:flex above would override the UA [hidden] rule. */
.st-pp-extra[hidden] {
    display: none;
}

.st-pp-lbl {
    font-family: var(--vt-mono);
    font-size: 10px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--vt-text-3);
}

.st-pp-cur {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}

.st-pp-cur-btn {
    font: inherit;
    font-size: 11px;
    color: var(--vt-text-3);
    background: var(--vt-panel);
    border: 1px solid var(--vt-line);
    border-radius: 999px;
    padding: 4px 10px;
    min-height: 26px;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s, background 0.15s;
}

.st-pp-cur-btn:hover {
    color: var(--vt-text-2);
    border-color: var(--vt-text-3);
}

.st-pp-cur-btn:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: 1px;
}

.st-pp-cur-btn.is-active {
    color: var(--vt-text);
    border-color: color-mix(in srgb, var(--vt-blue) 55%, transparent);
    background: color-mix(in srgb, var(--vt-blue) 14%, transparent);
}

/* Amount stepper: the input sits between the −/+ buttons inside the shared
   .st-step frame, so it drops its own border/radius and fills the middle. */
.st-pp-amount-step {
    width: 100%;
}

/* One-letter unit mark of the active price currency ("Л" = Пупс "Лидер"),
   pinned between the input and the + button; JS swaps the letter on pick. */
.st-pp-cur-mark {
    flex: none;
    padding: 0 9px 0 7px;
    font-family: var(--vt-mono);
    font-size: 11px;
    font-weight: 600;
    color: var(--vt-text-3);
    user-select: none;
    pointer-events: none;
}

.st-pp-amount {
    flex: 1 1 auto;
    min-width: 0;
    height: 32px;
    text-align: center;
    font-family: var(--vt-mono);
    font-size: 14px;
    font-weight: 600;
    color: var(--vt-text);
    background: var(--vt-panel);
    border: 0;
    border-radius: 0;
    outline: none;
    -moz-appearance: textfield;
}

.st-pp-amount:focus {
    background: var(--vt-panel-2);
}

.st-pp-amount:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: -2px;
}

.st-pp-amount::-webkit-outer-spin-button,
.st-pp-amount::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.st-pp-quick {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    max-height: 120px;
    overflow-y: auto;
    /* The full in-stock list is scrollable: keep the wheel inside the chip
       zone once its edge is reached instead of scrolling the page. */
    overscroll-behavior: contain;
}

.st-pp-quick-btn {
    font: inherit;
    font-size: 11px;
    color: var(--vt-text-3);
    background: var(--vt-panel);
    border: 1px solid var(--vt-line);
    border-radius: 999px;
    padding: 4px 10px;
    min-height: 26px;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s, background 0.15s;
}

.st-pp-quick-btn:hover {
    color: var(--vt-text-2);
    border-color: var(--vt-text-3);
}

.st-pp-quick-btn:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: 1px;
}

.st-pp-quick-btn.is-active {
    color: var(--vt-text);
    border-color: color-mix(in srgb, var(--vt-blue) 55%, transparent);
    background: color-mix(in srgb, var(--vt-blue) 14%, transparent);
}

.st-pp-picked {
    display: flex;
    align-items: center;
    gap: 6px;
    min-height: 20px;
    font-size: 12.5px;
    color: var(--vt-text);
}

.st-pp-picked-dot {
    display: inline-flex;
    color: var(--vt-blue-2);
}

.st-pp-picked-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.st-pp-find {
    margin-bottom: 0;
}

/* double-class specificity: the later .st-results base (max-height 264px)
   would otherwise win the tie and let the results list grow past this cap. */
.st-results.st-pp-results {
    max-height: 180px;
    margin-bottom: 0;
    /* Same scroll-chaining guard as the quick chips: wheel over the results
       never scrolls the page. */
    overscroll-behavior: contain;
}

.st-pp-qty {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.st-pp-qty .st-step {
    flex: none;
}

.st-pp-done {
    font: inherit;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--vt-text);
    background: color-mix(in srgb, var(--vt-blue) 22%, transparent);
    border: 1px solid color-mix(in srgb, var(--vt-blue) 55%, transparent);
    border-radius: 8px;
    padding: 7px 10px;
    min-height: 32px;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
}

.st-pp-done:hover {
    background: color-mix(in srgb, var(--vt-blue) 32%, transparent);
    border-color: var(--vt-blue-2);
}

.st-pp-done:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: 1px;
}

/* quantity (static read-only control in this step) */
.st-r-qty {
    position: relative;
    flex: none;
    margin-left: auto;
    display: flex;
    justify-content: flex-end;
}

.st-qty-btn {
    /* min-width makes the pill wider than short values like "×5" — center the
       label on both axes so it never hugs the left edge. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--vt-mono);
    font-size: 14px;
    font-weight: 700;
    color: var(--vt-yellow-2);
    background: color-mix(in srgb, var(--vt-yellow) 9%, transparent);
    border: 1px solid color-mix(in srgb, var(--vt-yellow) 24%, transparent);
    border-radius: 999px;
    min-width: 52px;
    padding: 6px 12px;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s, transform 0.1s;
}

.st-qty-btn:hover {
    border-color: color-mix(in srgb, var(--vt-yellow) 45%, transparent);
    background: color-mix(in srgb, var(--vt-yellow) 15%, transparent);
}

.st-qty-btn:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: 2px;
}

.st-qty-btn--zero {
    color: var(--vt-text-3);
    font-size: 12px;
    font-weight: 600;
    background: transparent;
    border-style: dashed;
    border-color: var(--vt-line);
}

/* Public row with a fully masked stack (hide_quantity): the atom icon stands
   for "in stock" instead of a number. Neutral color — it must not read as a
   price or a count. */
.st-qty-btn--masked {
    color: var(--vt-text-2);
    background: transparent;
    border-color: var(--vt-line);
}

.st-qty-btn--masked .st-qty-masked-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.st-qty-btn--masked .st-qty-masked-icon svg {
    width: 15px;
    height: 15px;
}

/* ---------- quantity popover (Step 4): delete + −/input/+ stepper ---------- */

.st-pop {
    position: absolute;
    right: 0;
    top: calc(100% + 6px);
    z-index: 60;
    display: none;
    align-items: center;
    gap: 12px;
    background: var(--vt-bg-2);
    border: 1px solid var(--vt-line);
    border-radius: 10px;
    box-shadow: 0 16px 36px rgba(0, 0, 0, 0.5);
    padding: 8px;
}

.st-pop.is-open {
    display: flex;
}

/* Popover forms carry their own CSRF input; they behave as plain flex items. */
.st-pop form {
    display: flex;
    align-items: center;
    margin: 0;
}

.st-qty-form {
    display: flex;
    align-items: center;
    gap: 8px;
}

.st-step {
    display: flex;
    align-items: center;
    border: 1px solid var(--vt-line);
    border-radius: 8px;
    overflow: hidden;
}

.st-step-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 32px;
    padding: 0;
    background: var(--vt-panel);
    border: 0;
    color: var(--vt-text-2);
    cursor: pointer;
    transition: color 0.15s;
}

.st-step-btn:hover {
    color: var(--vt-text);
}

.st-step-btn:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: -2px;
}

.st-qty-input {
    width: 74px;
    height: 32px;
    text-align: center;
    font-family: var(--vt-mono);
    font-size: 14px;
    font-weight: 600;
    color: var(--vt-text);
    background: var(--vt-panel);
    border: 0;
    outline: none;
    -moz-appearance: textfield;
}

.st-qty-input::-webkit-outer-spin-button,
.st-qty-input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.st-qty-input:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: -2px;
}

.st-qty-save {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    flex: none;
    padding: 0;
    border: 1px solid color-mix(in srgb, var(--vt-blue) 46%, transparent);
    border-radius: 8px;
    background: color-mix(in srgb, var(--vt-blue) 12%, transparent);
    color: var(--vt-blue-2);
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}

.st-qty-save:hover {
    background: color-mix(in srgb, var(--vt-blue) 22%, transparent);
    color: var(--vt-text);
}

.st-qty-save:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: 2px;
}

.st-pop-sep {
    width: 1px;
    height: 20px;
    background: var(--vt-line);
    flex: none;
}

.st-del {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    flex: none;
    padding: 0;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--vt-red);
    cursor: pointer;
    transition: background 0.15s;
}

.st-del:hover {
    background: color-mix(in srgb, var(--vt-red) 12%, transparent);
}

.st-del:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: -2px;
}

/* ---------- empty states / no search results ---------- */

.st-none {
    border: 1px dashed var(--vt-line);
    border-radius: var(--vt-r-lg);
    padding: 40px 24px;
    text-align: center;
    color: var(--vt-text-3);
    font-size: 13px;
    background: var(--vt-panel);
}

.st-none b {
    display: block;
    font-family: var(--vt-disp);
    font-size: 15px;
    color: var(--vt-text-2);
    margin-bottom: 4px;
}

.st-none--empty .st-head-actions {
    justify-content: center;
}

/* ---------- sidebar: character nav buttons (badge + name) ---------- */

.vt-stash-char-nav {
    display: flex;
    width: 100%;
    align-items: center;
    gap: 8px;
    min-height: 44px;
    font: inherit;
    font-size: 13.5px;
    font-weight: 600;
    color: var(--vt-text-2);
    background: var(--vt-panel);
    border: 1px solid var(--vt-line);
    border-radius: 10px;
    padding: 8px 12px;
    /* right room for the eye toggle + kebab menu button (absolute overlays
       in the wrap), see .vt-stash-char-eye below */
    padding-inline-end: 96px;
    cursor: pointer;
    text-align: left;
    transition: border-color 0.15s, color 0.15s, background 0.15s;
}

.vt-stash-char-nav:hover {
    border-color: var(--vt-text-3);
    color: var(--vt-text);
}

.vt-stash-char-nav:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: 1px;
}

.vt-stash-char-nav.is-active {
    border-color: color-mix(in srgb, var(--vt-yellow) 50%, transparent);
    color: var(--vt-yellow-2);
    background: color-mix(in srgb, var(--vt-yellow) 8%, transparent);
}

.vt-stash-char-nav .vt-stash-character-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow-wrap: anywhere;
}

.vt-stash-char-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    min-width: 22px;
    height: 22px;
    padding: 0 5px;
    font-family: var(--vt-mono);
    font-size: 11px;
    font-weight: 700;
    color: var(--vt-text-2);
    background: var(--vt-panel-2);
    border: 1px solid var(--vt-line);
    border-radius: 7px;
}

.vt-stash-char-nav.is-active .vt-stash-char-badge {
    color: var(--vt-yellow-2);
    border-color: color-mix(in srgb, var(--vt-yellow) 40%, transparent);
}

/* ---------- sidebar: character eye toggle (P3.3) ----------
   "Show to others" toggle on the character row, left of the kebab menu —
   the same overlay pattern as the platform Share button. The form posts the
   character publish endpoint and swaps #stash-overview; the button reuses
   the workspace .st-flag visual language (is-on--show = green eye). */
.vt-stash-char-eye {
    position: absolute;
    top: 0;
    right: 49px;
    z-index: 6;
    height: 46px;
    display: inline-flex;
    align-items: center;
}

/* 44x44 touch target (rule 3.17): the visual button stays compact, the
   pseudo-element grows the hit area like the kebab menu button */
.vt-stash-char-eye .st-flag::after {
    content: "";
    position: absolute;
    inset: -6px;
}

/* ---------- sidebar: kebab menus (platform rename / character manage) ----------
   The vertical-dots button at the end of a platform or character row opens a
   compact popover (rename form, plus the character delete). The button lives
   in an absolute wrap overlaying the row's reserved padding-inline-end zone,
   so it never toggles the platform <details>; stash.js toggles .is-open — one
   menu at a time, outside click and Esc close it. */

.vt-stash-nav-item,
.vt-stash-char-item {
    position: relative;
}

/* The sidebar is the inline-size container for its popovers: .vt-stash-menu
   sizes itself against the real sidebar width via cqw units (a plain
   percentage would resolve against the 36px button wrap, not the column). */
.vt-stash-sidebar {
    container-type: inline-size;
}

.vt-stash-menu-wrap {
    position: absolute;
    display: inline-flex;
    align-items: center;
    right: 7px;
    z-index: 6;
}

/* platform row: overlay the first row (the <summary>) of the details block */
.vt-stash-nav-item > .vt-stash-menu-wrap {
    top: 1px;
    height: 44px;
}

/* share toggle (D7) sits left of the management kebab. This file loads
   after stash.css, so the base .vt-stash-menu-wrap offset above would win
   the cascade against stash.css's equal-specificity --share rule and stack
   both buttons on the same spot; re-assert the offset with a compound
   selector. */
.vt-stash-nav-item > .vt-stash-menu-wrap.vt-stash-menu-wrap--share {
    right: 47px;
}

/* The share popover anchors right:0 to its wrap, so the extra 40px offset
   above also shifts the whole 300px menu left — past the viewport's left
   edge at narrow widths. Shift the popover back so its right edge lines up
   with the management menu (the kebab never overflows). Compound selector:
   the plain-class base .vt-stash-menu rule later in this file would
   otherwise override an equal-specificity offset. */
.vt-stash-menu.vt-stash-share-menu {
    right: -40px;
}

/* character row: overlay the nav button (min-height 44px + 2px borders) */
.vt-stash-char-item > .vt-stash-menu-wrap {
    top: 0;
    height: 46px;
}

.vt-stash-menu-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 36px;
    height: 36px;
    padding: 0;
    border: none;
    border-radius: 9px;
    background: transparent;
    color: var(--vt-text-3);
    cursor: pointer;
    transition: color 0.15s, background 0.15s;
}

/* 44x44 touch target (rule 3.17): the button stays visually compact, the
   pseudo-element grows the hit area into the row's reserved zone */
.vt-stash-menu-btn::after {
    content: "";
    position: absolute;
    inset: -4px;
}

.vt-stash-menu-btn:hover,
.vt-stash-menu-btn[aria-expanded="true"] {
    color: var(--vt-blue-2);
    background: color-mix(in srgb, var(--vt-blue) 12%, transparent);
}

.vt-stash-menu-btn:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: 1px;
}

/* Published platform (D7): the share toggle itself carries the state in the
   workspace .st-flag visual language (is-on--show = green eye), so the owner
   can see "this platform is public" without opening the menu. Declared after
   the hover/expanded rules so the green state wins the equal-specificity
   cascade while the menu is open too. */
.vt-stash-menu-btn.is-published,
.vt-stash-menu-btn.is-published:hover,
.vt-stash-menu-btn.is-published[aria-expanded="true"] {
    color: var(--vt-green);
    background: color-mix(in srgb, var(--vt-green) 12%, transparent);
}

.vt-stash-menu {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 30;
    display: none;
    /* The popovers right-align near the sidebar's edge, so the sidebar
       column itself is the real width budget (100cqw): on desktop the
       column is clamp(240px, 25%, 340px) and a fixed 300px menu overflows
       the viewport's left edge on ~1000-1250px screens. Full 300px wherever
       the column affords it. */
    width: min(300px, calc(100cqw - 8px));
    padding: 12px;
    background: var(--vt-bg-2);
    border: 1px solid var(--vt-line);
    border-radius: 10px;
    box-shadow: 0 16px 36px rgba(0, 0, 0, 0.5);
}

.vt-stash-menu.is-open {
    display: grid;
    gap: 10px;
}

/* Character kebab popover: the character row sits indented inside the
   platform <details>, so its right-aligned 300px menu lands ~20px left of
   the platform menus' column and pokes past the viewport's left edge.
   Shift the popover back onto the platform menu column. */
.vt-stash-char-item > .vt-stash-menu-wrap .vt-stash-menu {
    right: -16px;
}

/* An open menu must stack above every sibling row's kebab wrap: each wrap
   creates its own stacking context (z-index 6), so the menu's own z-index 30
   cannot escape it. Without this, the next row's kebab (same z-index, later
   in DOM order) paints OVER the open menu's check/delete buttons — clicking
   "Rename" toggles the NEXT row's menu instead of submitting the form. */
.vt-stash-menu-wrap:has(> .vt-stash-menu.is-open) {
    z-index: 40;
}

.vt-stash-menu-form {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 8px;
    align-items: center;
}

.vt-stash-menu-form .ui-input {
    width: 100%;
    min-width: 0;
    height: 38px;
}

.vt-stash-menu-remove .ui-button {
    width: 100%;
    justify-content: center;
}

/* ---------- adaptive: rows rebuild into two lines by content width ---------- */

@container strows (max-width: 900px) {
    .st-row {
        display: grid;
        grid-template-columns: 42px minmax(0, 1fr) auto;
        grid-template-areas:
            "icon main qty"
            "icon flags flags";
        row-gap: 10px;
    }

    .st-r-icon {
        grid-area: icon;
    }

    .st-r-main {
        grid-area: main;
    }

    .st-r-w {
        display: none;
    }

    .st-r-w2 {
        display: inline;
    }

    .st-r-flags {
        display: flex;
        grid-area: flags;
        align-items: center;
        gap: 6px;
        flex-wrap: wrap;
        justify-content: flex-start;
    }

    .st-r-cell {
        overflow: visible;
    }

    /* Wide-layout flag flex sizing does not apply inside the card's flag row
       (172px bases would force one cell per line). */
    .st-c-sell,
    .st-c-buy,
    .st-c-craft,
    .st-c-show {
        flex: 0 1 auto;
    }

    /* The price popover anchors to the left edge of the flag cell when the
       row is narrow (prototype §2.6 behavior); at phone widths it becomes a
       bottom sheet so a mid-row anchor can never push it past the viewport. */
    .st-ppop {
        right: auto;
        left: 0;
    }

    .st-r-qty {
        grid-area: qty;
        align-self: start;
    }
}

@container strows (max-width: 420px) {
    .st-row {
        padding: 12px;
    }

    .st-r-icon {
        width: 38px;
        height: 38px;
    }

    .st-r-icon svg {
        height: 22px;
    }
}

@media (max-width: 1023px) {
    .st-ws {
        grid-column: 1;
    }

    .st-filters {
        margin-left: 0;
        width: 100%;
    }

    .st-search {
        flex: 1;
    }

    .st-search input {
        width: 100%;
    }
}

@media (max-width: 560px) {
    .st-toolbar {
        gap: 10px;
    }

    .st-filters {
        flex-wrap: wrap;
    }

    .st-select {
        flex: 1;
    }
}

/* Full-size touch targets on mobile (rule 3.17). */
@media (max-width: 767px) {
    .st-tab {
        min-height: 44px;
    }

    .st-select {
        min-height: 44px;
    }

    .st-search input {
        min-height: 44px;
    }

    .st-col-btn {
        min-height: 44px;
    }

    .st-flag {
        width: 44px;
        height: 44px;
    }

    .st-qty-btn {
        min-height: 44px;
    }

    /* Quantity popover controls grow to full touch targets too (rule 3.17). */
    .st-pop {
        gap: 10px;
    }

    .st-step-btn {
        width: 44px;
        height: 44px;
    }

    .st-qty-input {
        width: 84px;
        height: 44px;
    }

    .st-qty-save {
        width: 44px;
        height: 44px;
    }

    .st-del {
        width: 44px;
        height: 44px;
    }

    /* Price popover controls grow to full touch targets too (rule 3.17). */
    .st-ppop {
        gap: 10px;
    }

    /* The price editor docks as a bottom sheet on phones: a fixed full-width
       panel above the footer-safe area, immune to mid-row anchor positions. */
    .st-ppop {
        position: fixed;
        left: 12px;
        right: 12px;
        top: auto;
        bottom: 12px;
        width: auto;
        z-index: 690;
    }

    .st-pp-opt,
    .st-pp-cur-btn,
    .st-pp-quick-btn,
    .st-pp-done {
        min-height: 44px;
    }

    .st-pp-amount,
    .st-pp-search {
        height: 44px;
    }
}

/* ---------- add-item modal (Step 5) ----------
   Scrim div wrapper per design-system rule 3.17.1 (no native <dialog>),
   ported from the approved prototype; consumes --vt-* tokens only. The modal
   lives outside #stash-overview, so it survives every HTMX overview swap. */

.st-scrim {
    position: fixed;
    inset: 0;
    z-index: 900;
    background: rgba(4, 7, 14, 0.68);
    backdrop-filter: blur(5px);
    display: none;
    align-items: flex-start;
    justify-content: center;
    padding: 9vh 16px 16px;
}

.st-scrim.is-open {
    display: flex;
}

.st-modal {
    width: min(560px, 100%);
    max-height: calc(100dvh - 18vh);
    overflow-y: auto;
    background: var(--vt-panel);
    border: 1px solid var(--vt-line);
    border-radius: var(--vt-r-lg);
    box-shadow: 0 30px 70px rgba(0, 0, 0, 0.55);
    padding: 20px 22px 18px;
    animation: st-modal-pop 0.18s cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes st-modal-pop {
    from {
        opacity: 0;
        transform: translateY(10px) scale(0.98);
    }
    to {
        opacity: 1;
        transform: none;
    }
}

.st-modal-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 14px;
    margin-bottom: 14px;
}

.st-modal-title {
    font-family: var(--vt-disp);
    font-size: 19px;
    font-weight: 800;
}

.st-modal-sub {
    font-size: 12.5px;
    color: var(--vt-text-2);
    margin-top: 3px;
}

.st-x {
    width: 36px;
    height: 36px;
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--vt-line);
    border-radius: 9px;
    background: transparent;
    color: var(--vt-text-2);
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s;
}

.st-x:hover {
    color: var(--vt-text);
    border-color: var(--vt-text-3);
}

.st-x:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: 2px;
}

.st-field-label {
    font-family: var(--vt-mono);
    font-size: 10px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--vt-text-3);
    display: block;
    margin: 0 0 7px;
}

.st-find {
    position: relative;
    margin-bottom: 10px;
}

.st-find-mark {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--vt-text-3);
    display: inline-flex;
}

.st-find input {
    font: inherit;
    font-size: 14px;
    color: var(--vt-text);
    background: var(--vt-bg-2);
    border: 1px solid var(--vt-line);
    border-radius: 10px;
    padding: 10px 12px 10px 38px;
    width: 100%;
    min-height: 44px;
    outline: none;
    transition: border-color 0.15s;
}

.st-find input:focus {
    border-color: color-mix(in srgb, var(--vt-blue) 45%, transparent);
}

.st-results {
    border: 1px solid var(--vt-line-soft);
    border-radius: 10px;
    overflow: hidden;
    margin-bottom: 14px;
    max-height: 264px;
    overflow-y: auto;
}

/* The hidden attribute toggles visibility from JS; explicit display rules
   would otherwise override it. */
.st-results[hidden] {
    display: none;
}

.st-result {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    min-height: 44px;
    text-align: left;
    font: inherit;
    background: none;
    border: 0;
    border-top: 1px solid var(--vt-line-soft);
    padding: 10px 12px;
    cursor: pointer;
    color: var(--vt-text);
    transition: background 0.15s;
}

.st-result:first-child {
    border-top: 0;
}

.st-result:hover,
.st-result.is-active {
    background: rgba(255, 255, 255, 0.045);
}

.st-result:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: -2px;
}

.st-result-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 13.5px;
    font-weight: 600;
}

.st-result-type {
    flex: none;
    margin-left: auto;
    font-family: var(--vt-mono);
    font-size: 10.5px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--vt-text-3);
    text-align: right;
}

.st-picked {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin: -4px 0 12px;
    padding: 9px 12px;
    border: 1px solid color-mix(in srgb, var(--vt-yellow) 40%, transparent);
    border-radius: 10px;
    background: color-mix(in srgb, var(--vt-yellow) 7%, transparent);
}

.st-picked[hidden] {
    display: none;
}

.st-picked-name {
    font-size: 13.5px;
    font-weight: 700;
    color: var(--vt-text);
}

.st-picked-type {
    margin-left: auto;
    font-family: var(--vt-mono);
    font-size: 10.5px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--vt-text-3);
}

.st-hint {
    font-size: 12px;
    color: var(--vt-text-3);
    line-height: 1.45;
    margin: 0 0 10px;
}

.st-hint b {
    color: var(--vt-text-2);
    font-weight: 600;
}

.st-step--modal {
    width: 100%;
    justify-content: center;
}

.st-error {
    font-size: 12.5px;
    color: var(--vt-red);
    margin: 12px 0 0;
}

.st-error[hidden] {
    display: none;
}

.st-add-tabs {
    display: flex;
    gap: 8px;
    margin-bottom: 14px;
}

.st-add-tab {
    flex: 1;
    min-height: 44px;
    font: inherit;
    font-size: 13px;
    font-weight: 700;
    color: var(--vt-text-2);
    background: transparent;
    border: 1px solid var(--vt-line);
    border-radius: 10px;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s, background 0.15s;
}

.st-add-tab:hover {
    color: var(--vt-text);
    border-color: var(--vt-text-3);
}

.st-add-tab:focus-visible {
    outline: 2px solid var(--vt-blue-2);
    outline-offset: 2px;
}

.st-add-tab.is-active {
    color: var(--vt-text);
    border-color: color-mix(in srgb, var(--vt-yellow) 45%, transparent);
    background: color-mix(in srgb, var(--vt-yellow) 7%, transparent);
}

.st-bulk-textarea,
.st-bulk-select {
    font: inherit;
    font-size: 14px;
    color: var(--vt-text);
    background: var(--vt-bg-2);
    border: 1px solid var(--vt-line);
    border-radius: 10px;
    padding: 10px 12px;
    width: 100%;
    min-height: 44px;
    outline: none;
    transition: border-color 0.15s;
}

.st-bulk-textarea {
    resize: vertical;
    font-family: var(--vt-mono);
    font-size: 13px;
    line-height: 1.5;
}

.st-bulk-textarea:focus,
.st-bulk-select:focus {
    border-color: color-mix(in srgb, var(--vt-yellow) 45%, transparent);
}

.st-buffer {
    margin-bottom: 4px;
}

.st-buffer-row {
    display: flex;
    gap: 10px;
    align-items: stretch;
}

.st-bulk-select {
    flex: 1;
    min-width: 0;
    cursor: pointer;
}

.st-buffer-row .ui-button {
    flex: none;
}

.st-modal-foot {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    margin-top: 18px;
}

@media (max-width: 480px) {
    .st-scrim {
        padding: 6vh 12px 12px;
    }

    .st-modal {
        padding: 16px 14px 14px;
    }

    /* Full touch targets on small screens (rule 3.17). */
    .st-x {
        width: 44px;
        height: 44px;
    }

    .st-modal-foot {
        flex-direction: column-reverse;
    }

    .st-modal-foot .ui-button {
        width: 100%;
        justify-content: center;
    }
}

@media (prefers-reduced-motion: reduce) {
    .st-modal {
        animation: none;
    }
}

/* Full-text tooltip ([data-tip]): chips truncate long barter/price names
   with ellipsis, this shared tip shows the complete terms — positioned by
   stash.js above the target (below when there is no room), clamped to the
   viewport, hidden on scroll/resize. Shown on hover/focus for pointers,
   tap-toggled on touch-only devices. */
.st-tip {
    position: fixed;
    z-index: 90;
    max-width: min(320px, calc(100vw - 16px));
    padding: 6px 10px;
    border-radius: 8px;
    background: var(--vt-panel);
    border: 1px solid var(--vt-line);
    color: var(--vt-text-2);
    font-family: var(--vt-sans);
    font-size: 12px;
    line-height: 1.45;
    text-align: center;
    box-shadow: 0 8px 24px rgb(0 0 0 / 40%);
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.15s;
}

.st-tip.is-open {
    opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
    .st-tip {
        transition: none;
    }
}
