/* Storages Viewer: one table of everything owned across synced storages (columns
   described in render_possessions, app/pages/). Self-contained per-page
   stylesheet; rules that look identical to loot-tracker.css/purchase-goals.css
   are intentionally duplicated. */

.pm-section {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 18px 20px; margin-bottom: 22px;
}

/* Export icon and its popup (pm_share_icon_btn in app/pages/; toggle script
   below it), duplicated from .loot-share-* in loot-tracker.css. top: 32px and no
   `transform` on .pm-share-wrap: a transform creates a stacking context that
   walls off the card's z-index, and the wrap inherits .page-title's 22px/1.5
   font-size, whose invisible strut the 32px clears (see
   .loot-share-wrap/.loot-share-card). */
.pm-share-wrap {
  position: relative; display: inline-block; vertical-align: middle; margin-left: 8px;
}
.pm-share-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  cursor: pointer;
  line-height: 1;
  color: var(--text-faint);
  transition: color 0.15s ease;
  position: relative;
  top: -2px;
}
.pm-share-icon-btn:hover { color: var(--text-dim); }
.pm-share-icon-btn.open { color: var(--gold); }
.pm-share-card {
  position: absolute; top: 32px; left: 50%; transform: translateX(-50%); z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 280px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 5px 6px;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.35);
}
/* Author display outranks the browser's [hidden] rule (same as
   .loot-share-card[hidden] in loot-tracker.css). */
.pm-share-card[hidden] { display: none; }
.pm-share-generate-btn {
  height: 28px;
  padding: 0 10px;
  font-size: 15px; letter-spacing: 0.03em; text-transform: uppercase;
  color: var(--text-dim);
  background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--radius);
  cursor: pointer;
}
.pm-share-generate-btn:hover { border-color: var(--gold-dim); color: var(--text); }
.pm-share-generate-btn:disabled { cursor: default; opacity: 0.6; }
.pm-share-generate-btn.action-failed { border-color: var(--red); color: var(--red); }
.pm-share-link-btn {
  height: 28px;
  padding: 0 10px;
  font-size: 15px;
  font-family: inherit;
  color: var(--text-dim);
  background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--radius);
  cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pm-share-link-btn:hover { border-color: var(--gold-dim); color: var(--text); }
.pm-share-popup-hint { margin: 0; font-size: 13px; color: var(--text-faint); text-align: center; }

/* Controls row: search, then location filters, at the same height. A vertical
   rule separates the two groups. Sorting is on the column headers
   (.pm-sort-header). */

.pm-controls-row {
  display: flex; align-items: center; flex-wrap: wrap; gap: 14px;
  margin-bottom: 16px;
}
.pm-control-group { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.pm-control-group + .pm-control-group {
  padding-left: 14px; border-left: 1px solid var(--border);
}
/* flex-basis decides when the row wraps. At 220px the settings cog wrapped onto
   its own line just above the phone breakpoint (~700px); 150px keeps it on the
   row. */
.pm-search-group { flex: 1 1 150px; min-width: 150px; position: relative; }
/* 32px height matches .pm-filter-btn so the search box and location buttons line
   up. Right padding leaves room for the CLEAR button. */
.pm-search-group .loot-search { width: 100%; height: 32px; padding: 0 46px 0 10px; font-size: 13px; box-sizing: border-box; }
/* Overlays the search box's right edge; shown only while there is text
   (updateSearchClear). */
.pm-search-clear {
  position: absolute; top: 50%; right: 10px; transform: translateY(-50%);
  background: none; border: none; padding: 0; margin: 0;
  font-size: 10.5px; letter-spacing: 0.03em; text-transform: uppercase;
  color: var(--text-faint); cursor: pointer;
}
.pm-search-clear:hover { color: var(--text); }
.pm-location-group { flex: 0 1 auto; }

/* Same look as .sort-btn in purchase-goals.css (duplicated). Multi-select: each
   button toggles independently and all start on. 25px is the site-wide button
   height (.loot-sort-tab in loot-tracker.css); align-items: center on
   .pm-controls-row/.pm-control-group centers it against the 32px search box. */
.pm-filter-btn {
  height: 25px; padding: 0 10px; box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 10.5px; letter-spacing: 0.03em; text-transform: uppercase;
  color: var(--text-dim);
  background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--radius);
  cursor: pointer;
  text-align: center;
}
.pm-filter-btn:hover { border-color: var(--gold-dim); color: var(--text); }
.pm-filter-btn.active { border-color: var(--gold); color: var(--gold); }
/* Opts out of .pm-filter-btn's uppercase transform so "PoH" keeps its mixed case
   (_POSSESSION_LOCATION_GROUPS in app/pages/). */
.pm-filter-btn-cased { text-transform: none; }

/* Settings cog and checkbox dropdown; same relationship as
   .tracker-menu-wrap/#setupMenu in purchase-goals.css, but 32px high and
   right-anchored since it sits at the row's far right. */
.pm-settings-wrap { position: relative; }
.pm-settings-btn {
  width: 32px; height: 32px; box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--radius);
  color: var(--text-dim); cursor: pointer;
}
.pm-settings-btn:hover { border-color: var(--gold-dim); color: var(--text); }
/* Active (menu open) look matches .pm-filter-btn.active; setSettingsMenuOpen
   keeps it in sync on every close path. */
.pm-settings-btn.active { border-color: var(--gold); color: var(--gold); }
.pm-settings-menu {
  position: absolute; top: 38px; right: 0; z-index: 5;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  min-width: 190px; max-height: 320px; overflow-y: auto;
  flex-direction: column; padding: 6px 0;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.35);
  /* Stops scroll chaining into the page past the list bounds (same as
     .mm-suggestions in mindmaps.css). */
  overscroll-behavior: contain;
}
/* Same small/gray/all-caps look as .pm-filter-btn; one row per raw storage key
   (render_possessions), all checked by default. PoH opts out of the uppercase
   transform like .pm-filter-btn-cased. */
.pm-settings-item {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 14px; cursor: pointer;
  color: var(--text-dim); font-size: 10.5px; letter-spacing: 0.03em; text-transform: uppercase;
}
.pm-settings-item:hover { background: var(--panel-2); color: var(--text); }
.pm-settings-item input[type="checkbox"] { flex-shrink: 0; }
.pm-settings-item-cased { text-transform: none; }

/* Table */

.pm-row {
  display: grid;
  grid-template-columns: minmax(180px, 2fr) 110px 130px 130px 84px;
  align-items: center;
  gap: 10px;
  padding: 8px 6px;
}
/* Left gutter for the pin button (.pm-pin-btn) so it does not overlap the
   icon/name. */
.pm-row { padding-left: 26px; }
/* Each data row sits in a .pm-row-wrap (rowHtml in the script), so the row
   border keys off the wrapper. The row after .pm-pinned-divider (not a wrap)
   gets no border, so there is no doubled line. */
/* content-visibility: auto skips layout/paint for off-screen rows; with hundreds
   to thousands of rows, laying out all of them on every rebuild
   (filter/sort/search) was the dominant render cost. contain-intrinsic-size
   reserves the row's real height (see the shared .pm-row/.pm-row-header padding)
   so scroll height does not jump. */
.pm-row-wrap {
  position: relative;
  content-visibility: auto;
  contain-intrinsic-size: auto 46px;
}
.pm-row-wrap + .pm-row-wrap { border-top: 1px solid var(--border); }
/* Gap between the pinned group and the rest: extra margin and a gold-tinted line
   for a deliberate section break. Only rendered when both groups have rows
   (renderTable). */
.pm-pinned-divider { margin: 6px 0 10px; border-top: 1px solid var(--gold-dim); }
/* Pin toggle: a thumbtack outline (PIN_GLYPH in the script), absolutely
   positioned in the left gutter reserved by .pm-row's padding-left, since it is
   a sibling of the row's <a>, not a grid child. Hidden until row hover
   (.pm-row-wrap:hover) unless already pinned. Unpinned is --text-dim and turns
   gold on hover; pinned is the reverse. .pinned:hover (two classes) outranks the
   plain :hover rule regardless of source order. */
.pm-pin-btn {
  position: absolute; left: 1px; top: 50%; transform: translateY(-50%);
  width: 20px; height: 20px; padding: 0; margin: 0;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; border-radius: var(--radius);
  cursor: pointer;
  color: var(--text-dim);
  opacity: 0; pointer-events: none;
  transition: opacity 0.12s, color 0.12s;
}
.pm-pin-btn svg { display: block; }
.pm-row-wrap:hover .pm-pin-btn { opacity: 1; pointer-events: auto; }
.pm-pin-btn:hover { color: var(--gold); }
.pm-pin-btn.pinned { opacity: 1; pointer-events: auto; color: var(--gold); }
.pm-pin-btn.pinned:hover { color: var(--text-dim); }
/* Each data row is an <a class="pm-row"> linking to the item's wiki page
   (rowHtml); .pm-row-header is a non-clickable div, hence the `a` scoping.
   Resets color/text-decoration against myscape.css's global a rule. */
a.pm-row { color: inherit; text-decoration: none; cursor: pointer; }
/* Whole-row background highlight, like .loot-npc-box/.loot-item-box :hover in
   loot-tracker.css. text-decoration: none is repeated because myscape.css's
   a:hover underline would otherwise win on a.pm-row:hover. */
a.pm-row:hover { background-color: rgb(51, 51, 54); text-decoration: none; }

.pm-row-header {
  /* Resets padding-left to 6px, restated here because the earlier .pm-row {
     padding-left: 26px } rule ties on specificity and would misalign ITEM
     against the icon/name column. Larger font so the filter funnel icon does not
     dwarf the label. */
  padding: 0 6px 10px 26px;
  font-size: 12px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-faint);
}
.pm-row-header .pm-col-qty,
.pm-row-header .pm-col-ge,
.pm-row-header .pm-col-ha,
.pm-row-header .pm-col-tradeable { text-align: center; }

/* Header cell holding the sort button and the separate filter funnel button
   (.pm-filter-icon-btn), so a click on one never triggers the other. This
   wrapper is the grid item carrying the .pm-col-* width class (header markup in
   render_possessions). */
.pm-header-cell { display: flex; align-items: center; gap: 4px; min-width: 0; position: relative; }
.pm-header-cell.pm-col-qty,
.pm-header-cell.pm-col-ge,
.pm-header-cell.pm-col-ha,
.pm-header-cell.pm-col-tradeable { justify-content: center; }

/* Sort <button> reset to the row's text styling; hugs its text now that it
   shares the cell with the filter button. Active column is gold (text + arrow). */
.pm-sort-header {
  background: none; border: none; padding: 0; margin: 0; font: inherit;
  color: inherit; letter-spacing: inherit; text-transform: inherit;
  cursor: pointer;
}
.pm-sort-header:hover { color: var(--text); }
.pm-sort-header.active { color: var(--gold); }
.pm-sort-arrow { display: inline-block; }

/* Funnel icon opening that column's filter popover (.pm-filter-popover);
   separate click target with its own stopPropagation (wireFilterPopovers) so
   filtering never also sorts. Gray at rest, gold when the column is filtered or
   the popover is open. */
.pm-filter-icon-btn {
  flex: 0 0 auto; width: 15px; height: 15px; padding: 0; margin: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: none; border-radius: 3px;
  color: var(--text-faint); cursor: pointer;
}
.pm-filter-icon-btn svg { display: block; }
.pm-filter-icon-btn:hover { color: var(--text); }
.pm-filter-icon-btn.active { color: var(--gold); }

/* Shared by the ITEM header cell and each row's icon+name cell; a plain div
   since the whole row is the link. */
.pm-col-image { display: flex; align-items: center; gap: 10px; min-width: 0; }
/* Nudges the ITEM header right so it reads as centered over the 26px icon column
   instead of flush-left; scoped to the header cell so data rows are untouched. */
.pm-col-image.pm-header-cell { padding-left: 6px; }

/* Per-column filter popovers */
/* Anchored under the header cell whose funnel opened it, same panel recipe as
   .pm-settings-menu; right-anchored on the three right-hand columns so it does
   not spill off the table's right edge. */
.pm-filter-popover {
  position: absolute; top: 22px; left: 0; z-index: 6;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  min-width: 210px; padding: 12px; display: flex; flex-direction: column; gap: 10px;
  text-transform: none; letter-spacing: normal;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.35);
}
.pm-col-ge .pm-filter-popover,
.pm-col-ha .pm-filter-popover,
.pm-col-tradeable .pm-filter-popover { left: auto; right: 0; }
.pm-filter-popover-label {
  font-size: 10.5px; letter-spacing: 0.03em; text-transform: uppercase; color: var(--text-faint);
}
/* Segmented control: all options visible, current one picked out; same recipe as
   .mm-segment-group/.mm-segment-btn in mindmaps.css (duplicated). Dividers come
   from the group's background showing through a 1px gap, simpler with flex-wrap.
   The 7-option operator group wraps to two rows because each segment's min-width
   forces it; 2-option groups split the width evenly. */
.pm-segment-group {
  display: flex; flex-wrap: nowrap; gap: 1px;
  background: var(--border); border: 1px solid var(--border); border-radius: var(--radius);
  overflow: hidden;
}
.pm-segment-btn {
  flex: 1 1 0; background: #100e0b; border: none;
  color: var(--text-dim); font-family: inherit; font-size: 10.5px; letter-spacing: 0.02em;
  padding: 7px 4px; cursor: pointer; text-align: center; text-transform: uppercase;
}
.pm-segment-btn:hover { color: var(--text); }
.pm-segment-btn.active { background: var(--panel-2); color: var(--gold); }

/* Quantity/GE/HA 7-way operator picker on one row. The six comparison symbols
   use the system font: RuneScapePlain11 has no glyphs for "≥"/"≤"/"≠" and draws
   ">"/"<"/"=" thin and small. The system font's default line-height is taller
   than the pixel font's, so line-height is set explicitly to keep the buttons as
   tall as the item/tradeable segmented controls (7px padding, 8px line box).
   BETWEEN is a word and keeps the pixel font, sized to its label. */
.pm-segment-group[data-role="op"] .pm-segment-btn {
  flex: 0 0 36px; width: 36px; padding: 7px 2px;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, sans-serif;
  font-size: 12px; line-height: 8px;
}
.pm-segment-group[data-role="op"] .pm-segment-btn[data-segment-value="between"] {
  flex: 0 0 auto; width: auto; padding: 7px 14px;
  font-family: inherit; font-size: 10.5px;
}

/* No explicit width: .pm-filter-popover only has a 210px min-width, so it
   shrink-wraps to its widest row (the operator row). align-self: flex-start on
   that row stops the default align-items: stretch from widening it and leaving
   dead space past BETWEEN. */
.pm-segment-group[data-role="op"] {
  align-self: flex-start;
}

/* GE/HA Stack/Single toggle, left of the Value field (or the Min/Max pair) so it
   costs no row. 28px matches the input height (not the 22px segmented controls);
   flex centering on each button gives an exact match regardless of font metrics. */
.pm-filter-value-row { display: flex; align-items: center; gap: 6px; }
.pm-filter-value-row .pm-filter-input { flex: 1 1 auto; min-width: 0; }
.pm-filter-value-row .pm-segment-group {
  flex: 0 0 auto; height: 28px; box-sizing: border-box;
}
.pm-filter-value-row .pm-segment-group .pm-segment-btn {
  flex: 0 0 auto; height: 100%; box-sizing: border-box;
  display: flex; align-items: center; justify-content: center;
  padding: 0 10px; font-size: 10.5px;
}
.pm-filter-input {
  height: 28px; padding: 0 8px; box-sizing: border-box; width: 100%;
  font-size: 13px; color: var(--text); font-family: inherit;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--radius);
}
.pm-filter-input:focus { outline: none; border-color: var(--gold-dim); }
.pm-filter-input-pair { display: flex; align-items: center; gap: 6px; }
.pm-filter-input-pair .pm-filter-input { flex: 1 1 0; min-width: 0; }
.pm-filter-input-pair-sep { color: var(--text-faint); font-size: 11px; flex: 0 0 auto; }
/* The Between Min/Max pair is a flex child of .pm-filter-value-row like the
   Value input it swaps with (filterPopoverHtml in app/pages/), sharing the row
   with the Stack/Single toggle and keeping the popover height constant. flex: 1
   1 auto matches the Value input's rule. */
.pm-filter-value-row .pm-filter-input-pair { flex: 1 1 auto; min-width: 0; }
.pm-filter-popover-actions { display: flex; gap: 8px; margin-top: 2px; }
.pm-filter-popover-actions button {
  flex: 1 1 auto; height: 28px; box-sizing: border-box;
  font-size: 10.5px; letter-spacing: 0.03em; text-transform: uppercase;
  border-radius: var(--radius); cursor: pointer;
}
/* Same fill/hover recipe as button.primary in myscape.css. */
.pm-filter-apply-btn { background: var(--gold); border: 1px solid var(--gold); color: #221c10; }
.pm-filter-apply-btn:hover { background: #ffab42; border-color: #ffab42; }
.pm-filter-clear-btn { background: var(--panel-2); border: 1px solid var(--border); color: var(--text-dim); }
.pm-filter-clear-btn:hover { border-color: var(--red); color: var(--red); }
/* Save View popover's "Cancel" shares .pm-filter-clear-btn with Clear but is not
   destructive, so hover is a gold border only (text stays at the resting color,
   so Cancel is not emphasized). Two-class selector outranks
   .pm-filter-clear-btn:hover regardless of source order, and `color` must be
   restated: omitting it would let Clear's `color: var(--red)` hover rule win. */
.pm-filter-clear-btn.pm-view-cancel-btn:hover { border-color: var(--gold-dim); color: var(--text-dim); }
/* Save View popover's Save/Cancel use the 25px site-wide button height
   (.loot-sort-tab in loot-tracker.css); scoped to .pm-view-save-popover so the
   column filter's Apply/Clear (same base class) stay at 28px. They sit on their
   own row below the name input. */
.pm-view-save-popover .pm-filter-popover-actions button { height: 25px; }

/* Saved views strip (drag-and-drop reorderable, above the table headers;
   PossessionView in app/models.py, saved-views section of render_possessions'
   script) */
.pm-views-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin-bottom: 14px; position: relative;
}
.possessions-share #pmViewsRow { display: none; }

/* "SNAPSHOT AS OF: <date> <time> (LOCAL)" line above "Shared by <name>"
   (banner_markup in render_storages_share, app/pages/); same as
   .loot-share-range in loot-tracker.css. */
.pm-share-asof { text-align: center; margin: 0 0 4px; }

/* Drag-and-drop shape of the .tracker-icon-btn row in purchase-goals.css
   (wireSetupIconDrag, reused as wireViewChipDrag). Always draggable, no
   custom-mode gate. */
/* 25px site-wide button height (.loot-sort-tab in loot-tracker.css);
   .pm-views-row's align-items: center keeps this and .pm-view-add-btn aligned
   though their padding differs slightly. */
.pm-view-chip {
  height: 25px; padding: 0 6px 0 10px; box-sizing: border-box;
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--text-dim);
  background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--radius);
  cursor: grab;
}
.pm-view-chip:hover { border-color: var(--gold-dim); color: var(--text); }
.pm-view-chip.active { border-color: var(--gold); color: var(--gold); }
.pm-view-chip.dragging { opacity: 0.4; cursor: grabbing; }
.pm-view-chip-name {
  max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  text-transform: uppercase;
}
.pm-view-delete {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; padding: 0; margin: 0;
  background: none; border: none; color: var(--text-faint); cursor: pointer;
  font-size: 13px; line-height: 1;
}
.pm-view-delete:hover { color: var(--red); }
.pm-view-add-btn {
  height: 25px; padding: 0 10px; box-sizing: border-box;
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; letter-spacing: 0.03em; text-transform: uppercase; color: var(--text-dim);
  background: none; border: 1px dashed var(--border); border-radius: var(--radius);
  cursor: pointer;
}
.pm-view-add-btn:hover { border-color: var(--gold-dim); color: var(--gold); }
.pm-view-save-popover {
  position: absolute; top: 36px; left: 0; z-index: 6;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  min-width: 220px; padding: 12px; display: flex; flex-direction: column; gap: 10px;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.35);
}
/* RuneLite CDN canvas padding: size bump plus recentering translate (see
   .loot-item-box-icon in loot-tracker.css). .pm-icon-blank (no-icon placeholder;
   rowHtml) matches the size so rows stay aligned. */
.pm-row-icon {
  width: 30px; height: 30px; object-fit: contain; image-rendering: pixelated; flex: 0 0 auto;
  transform: translate(5.5%, -1%);
}
.pm-icon-blank { width: 30px; height: 30px; }
.pm-row-name {
  font-size: 13px; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.pm-col-qty { text-align: center; }
/* Scoped to data rows: QUANTITY's header button also carries .pm-col-qty, and
   without scoping its font-size/color would override the header styling at equal
   specificity. */
.pm-row:not(.pm-row-header) .pm-col-qty {
  font-size: 13px; color: var(--text); font-variant-numeric: tabular-nums;
}

.pm-col-ge, .pm-col-ha { text-align: center; }
/* The "each" line renders only when qty > 1 (valueCell in the script); otherwise
   it is omitted so the single line is centered by .pm-row's align-items: center.
   When present, zero gap plus min-height keeps the pair tight. */
.pm-value-cell { display: flex; flex-direction: column; gap: 0; }
.pm-value-stack { font-size: 12.5px; color: var(--text); font-variant-numeric: tabular-nums; line-height: 1.2; }
.pm-value-stack.pm-value-none { color: var(--text-faint); }
.pm-value-each { font-size: 10px; color: var(--text-faint); font-variant-numeric: tabular-nums; line-height: 1.2; min-height: 12px; }
/* The "~" marks a derived (non-GE) value (valueCell). RuneScapePlain11's tilde
   sits high in its em-box and drags the line up a few px; an inline-block with
   line-height: 1 isolates it. */
.pm-derived-mark { display: inline-block; line-height: 1; vertical-align: baseline; }

.pm-col-tradeable { text-align: center; }
.pm-badge {
  display: inline-block; padding: 2px 10px; border-radius: var(--radius);
  font-size: 10px; letter-spacing: 0.04em; text-transform: uppercase;
  border: 1px solid transparent;
}
.pm-badge-yes { background: rgba(111, 174, 90, 0.14); border-color: var(--green); color: var(--green); }
.pm-badge-no { background: rgba(192, 90, 76, 0.14); border-color: var(--red); color: var(--red); }

/* Compact columns from 800px down: between 700 and ~800px (zoomed-in desktop)
   the full grid overflows the panel and "Tradeable?" sticks out. */
@media (max-width: 800px) {
  .pm-row {
    grid-template-columns: minmax(140px, 1.6fr) 80px 96px 96px 66px;
    gap: 6px;
  }
  .pm-row-name { font-size: 12px; }
}

/* Landing page preview (render_landing_storages_preview, app/pages/). Same
   container treatment as the other previews (.landing-loot-preview in
   loot-tracker.css): viewport-capped, clipped, bottom feather. max-width 900px
   matches them. */
.landing-storages-preview {
  width: 100%;
  max-width: 900px;
  margin: 0 auto;
  /* Fixed height (not max-height) so the bottom feather stays at the same screen
     position however much content is inside; see .landing-loot-preview in
     loot-tracker.css. */
  height: calc(100vh - 80px);
  height: calc(100svh - 80px);
  overflow: hidden;
  position: relative;
}
/* Unconditional; no --clipped modifier (see .landing-loot-preview::after in
   loot-tracker.css). */
.landing-storages-preview::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 15%;
  background: linear-gradient(to bottom, transparent, var(--bg));
  pointer-events: none;
}

/* Hide the reused body's heading rather than strip it (_possessions_panel_markup
   stays untouched); the tagline replaces it. */
.landing-storages-preview .page-title { display: none; }

/* Landing-preview hero row: character first (left), tagline wrap second; mirrors
   .purchase-preview-hero/-tagline-wrap/-char in purchase-goals.css (see also
   .loot-preview-hero in loot-tracker.css and render_landing_storages_preview's
   hero_markup). */
.storages-preview-hero {
  display: flex;
  align-items: flex-end;
}
.storages-preview-tagline-wrap {
  flex: 1 1 auto;
  align-self: stretch;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
}
.storages-preview-tagline {
  margin: 0;
  max-width: 100%;
  min-width: 0;
  text-align: center;
  font-size: 30px;
  line-height: 1.25;
  font-weight: 400;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.storages-preview-tagline-gold { color: var(--gold); }
.storages-preview-tagline-white { color: var(--text); }

/* Fixed height: 157px matches
   .loot-preview-char/.purchase-preview-char/.mindmap-preview-char so all preview
   characters are the same height despite differing source aspect ratios; width
   follows. */
.storages-preview-char {
  flex: 0 0 auto;
  height: 157px;
  line-height: 0;
}
/* Two classes beat myscape.css's .landing-anchor picture img (one class, two
   elements). */
.landing-storages-preview .storages-preview-char img {
  display: block;
  height: 100%;
  max-height: none;
  width: auto;
  max-width: none;
}


/* Phone layout (site breakpoint 700px). Scoped with body:not(.phone-off) so the
   homepage preview is untouched. The section is max 320px wide and centered; the
   five-column table becomes one compact card per item. */
@media (max-width: 700px) {
  body:not(.phone-off) .pm-section {
    max-width: 320px; margin-left: auto; margin-right: auto;
    padding: 14px 12px; box-sizing: border-box;
  }

  /* Controls: search on its own full-width row; the location buttons
     (wrapping) with the settings gear beside them underneath. */
  body:not(.phone-off) .pm-controls-row { gap: 10px; align-items: flex-start; margin-bottom: 14px; }
  body:not(.phone-off) .pm-control-group + .pm-control-group { padding-left: 0; border-left: none; }
  body:not(.phone-off) .pm-search-group { flex: 1 1 100%; min-width: 0; }
  body:not(.phone-off) .pm-search-group .loot-search { height: 40px; font-size: 16px; padding-right: 54px; }
  body:not(.phone-off) .pm-location-group { flex: 1 1 0; min-width: 0; }
  body:not(.phone-off) .pm-filter-btn { height: 32px; }
  body:not(.phone-off) .pm-settings-wrap { flex: 0 0 auto; }
  body:not(.phone-off) .pm-settings-btn { width: 32px; height: 32px; }
  body:not(.phone-off) .pm-settings-menu { top: 38px; right: 0; max-width: calc(100vw - 48px); }

  body:not(.phone-off) .pm-views-row { gap: 8px; }
  body:not(.phone-off) .pm-view-chip, body:not(.phone-off) .pm-view-add-btn { height: 32px; }
  body:not(.phone-off) .pm-view-save-popover {
    left: 0; right: 0; min-width: 0; width: auto; box-sizing: border-box;
  }

  /* Header: the five sort buttons + filter funnels wrap into three
     columns; every popover opens under the whole header block, full
     width, instead of under its own (narrow, off-center) cell. */
  body:not(.phone-off) .pm-row.pm-row-header {
    position: relative;
    display: grid; grid-template-columns: repeat(3, auto); justify-content: space-between;
    gap: 2px 6px; padding: 0 0 8px;
    font-size: 11px;
  }
  body:not(.phone-off) .pm-row-header .pm-header-cell { position: static; justify-content: flex-start; padding-left: 0; text-align: left; min-height: 30px; }
  body:not(.phone-off) .pm-row-header .pm-sort-header { font-size: 11px; }
  body:not(.phone-off) .pm-row-header .pm-filter-icon-btn { width: 26px; height: 30px; display: inline-flex; align-items: center; justify-content: center; }
  body:not(.phone-off) .pm-filter-popover,
  body:not(.phone-off) .pm-col-ge .pm-filter-popover,
  body:not(.phone-off) .pm-col-ha .pm-filter-popover,
  body:not(.phone-off) .pm-col-tradeable .pm-filter-popover {
    top: 100%; left: 0; right: 0; min-width: 0; width: auto; box-sizing: border-box; margin-top: -6px;
  }

  /* Operator row of the Quantity/GE/HA filter: six symbols, then BETWEEN
     on its own row, so it fits the popover instead of running off it. */
  body:not(.phone-off) .pm-segment-group[data-role="op"] { flex-wrap: wrap; align-self: stretch; }
  body:not(.phone-off) .pm-segment-group[data-role="op"] .pm-segment-btn { flex: 1 1 0; width: auto; padding: 9px 2px; }
  body:not(.phone-off) .pm-segment-group[data-role="op"] .pm-segment-btn[data-segment-value="between"] { flex: 1 1 100%; padding: 8px 14px; }

  /* Export popup: anchored to the title row, no wider than it, so it
     can't run off the right edge. */
  body:not(.phone-off) .page-title:has(.pm-share-wrap) { position: relative; }
  body:not(.phone-off) .pm-share-wrap { position: static; }
  body:not(.phone-off) .pm-share-card { top: calc(100% + 6px); width: min(280px, 100%); box-sizing: border-box; }

  /* Rows: icon + name + TRADEABLE badge on top, QTY / GE / HA beneath
     with small labels (the column headers are no longer above them). */
  body:not(.phone-off) .pm-row:not(.pm-row-header) {
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr) minmax(0, 1fr);
    grid-template-areas: "img img trade" "qty ge ha";
    gap: 6px 8px; align-items: start;
    padding: 8px 0 8px 28px;
  }
  body:not(.phone-off) .pm-row:not(.pm-row-header) > .pm-col-image { grid-area: img; align-self: center; }
  body:not(.phone-off) .pm-row:not(.pm-row-header) > .pm-col-tradeable { grid-area: trade; text-align: right; align-self: center; }
  body:not(.phone-off) .pm-row:not(.pm-row-header) > .pm-col-qty { grid-area: qty; text-align: left; }
  body:not(.phone-off) .pm-row:not(.pm-row-header) > .pm-col-ge { grid-area: ge; text-align: left; }
  body:not(.phone-off) .pm-row:not(.pm-row-header) > .pm-col-ha { grid-area: ha; text-align: left; }
  body:not(.phone-off) .pm-row:not(.pm-row-header) > .pm-col-qty::before,
  body:not(.phone-off) .pm-row:not(.pm-row-header) > .pm-col-ge::before,
  body:not(.phone-off) .pm-row:not(.pm-row-header) > .pm-col-ha::before {
    display: block; font-size: 9px; letter-spacing: 0.05em; color: var(--text-faint); margin-bottom: 1px;
  }
  body:not(.phone-off) .pm-row:not(.pm-row-header) > .pm-col-qty::before { content: 'QTY'; }
  body:not(.phone-off) .pm-row:not(.pm-row-header) > .pm-col-ge::before { content: 'GE'; }
  body:not(.phone-off) .pm-row:not(.pm-row-header) > .pm-col-ha::before { content: 'HA'; }
  body:not(.phone-off) .pm-row-name { font-size: 13px; }
  body:not(.phone-off) .pm-row-wrap { contain-intrinsic-size: auto 76px; }
  body:not(.phone-off) .pm-value-stack, body:not(.phone-off) .pm-row:not(.pm-row-header) > .pm-col-qty { font-size: 12px; }
}

/* Phone browsers can inflate small text block by block; each item card opts out
   so the 9px QTY / GE / HA / TRADE? labels stay the same size. */
@media (max-width: 700px) {
  body:not(.phone-off) .pm-row:not(.pm-row-header) {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
  }
}

/* Touch: no hover, so the pin button is always showing (dim until pinned). */
@media (hover: none) {
  body:not(.phone-off) .pm-pin-btn {
    opacity: 0.5; pointer-events: auto;
    width: 26px; height: 44px; left: 0; top: 50%;
  }
  body:not(.phone-off) .pm-pin-btn.pinned { opacity: 1; }
}


/* Scroll cue wrappers (wireScrollCue in the page script). Transparent to layout
   on desktop; the phone block below makes them scrolling strips with an edge
   fade and a gold chevron. */
.pm-loc-wrap, .pm-loc-scroll { display: contents; }
.pm-views-wrap { position: relative; }
.pm-scroll-arrow { display: none; }

/* Registered so the fade widths can be transitioned. */
@property --pm-fade-l { syntax: '<length>'; inherits: false; initial-value: 0px; }
@property --pm-fade-r { syntax: '<length>'; inherits: false; initial-value: 0px; }

@media (max-width: 700px) {
  body:not(.phone-off) .pm-loc-wrap { display: block; position: relative; width: 100%; min-width: 0; }
  body:not(.phone-off) .pm-loc-scroll,
  body:not(.phone-off) .pm-views-row {
    display: flex; flex-wrap: nowrap; gap: 6px;
    overflow-x: auto; overflow-y: hidden;
    scrollbar-width: none; -webkit-overflow-scrolling: touch;
    -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--pm-fade-l), #000 calc(100% - var(--pm-fade-r)), transparent);
    mask-image: linear-gradient(to right, transparent, #000 var(--pm-fade-l), #000 calc(100% - var(--pm-fade-r)), transparent);
    transition: --pm-fade-l 0.25s ease, --pm-fade-r 0.25s ease;
  }
  body:not(.phone-off) .pm-views-row { gap: 8px; }
  body:not(.phone-off) .pm-loc-scroll::-webkit-scrollbar,
  body:not(.phone-off) .pm-views-row::-webkit-scrollbar { display: none; }
  body:not(.phone-off) .pm-loc-scroll > *, body:not(.phone-off) .pm-views-row > * { flex: 0 0 auto; }
  body:not(.phone-off) .pm-loc-wrap.can-scroll-left .pm-loc-scroll,
  body:not(.phone-off) .pm-views-wrap.can-scroll-left .pm-views-row { --pm-fade-l: 44px; }
  body:not(.phone-off) .pm-loc-wrap.can-scroll-right .pm-loc-scroll,
  body:not(.phone-off) .pm-views-wrap.can-scroll-right .pm-views-row { --pm-fade-r: 44px; }
  body:not(.phone-off) .pm-scroll-arrow {
    display: block; position: absolute; top: 50%;
    width: 9px; height: 9px; margin-top: -5px;
    border-top: 2px solid var(--gold); border-right: 2px solid var(--gold);
    pointer-events: none; opacity: 0; transition: opacity 0.25s ease;
  }
  body:not(.phone-off) .pm-views-wrap .pm-scroll-arrow { top: 16px; }
  body:not(.phone-off) .pm-scroll-arrow--right { right: 6px; transform: rotate(45deg); }
  body:not(.phone-off) .pm-scroll-arrow--left { left: 6px; transform: rotate(-135deg); }
  body:not(.phone-off) .pm-loc-wrap.can-scroll-right .pm-scroll-arrow--right,
  body:not(.phone-off) .pm-views-wrap.can-scroll-right .pm-scroll-arrow--right,
  body:not(.phone-off) .pm-loc-wrap.can-scroll-left .pm-scroll-arrow--left,
  body:not(.phone-off) .pm-views-wrap.can-scroll-left .pm-scroll-arrow--left { opacity: 1; }

  /* The location buttons are one scrolling row now: gear beside it,
     vertically centered with the buttons. */
  body:not(.phone-off) .pm-controls-row { align-items: center; }
  body:not(.phone-off) .pm-views-row { margin-bottom: 0; padding-bottom: 14px; }

  /* Rows: QTY / GE / HA / TRADE? on one line beneath the name, TRADE? as plain
     green/red text. The pin moves to the card's top-right corner, so the left
     gutter is not needed. */
  body:not(.phone-off) .pm-row:not(.pm-row-header) {
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 0.75fr);
    grid-template-areas: "img img img pin" "qty ge ha trade";
    gap: 6px 6px;
    padding: 8px 0;
  }
  body:not(.phone-off) .pm-row:not(.pm-row-header) > .pm-col-tradeable { grid-area: trade; text-align: left; align-self: start; }
  body:not(.phone-off) .pm-row:not(.pm-row-header) > .pm-col-tradeable::before {
    content: 'TRADE?'; display: block; font-size: 9px; letter-spacing: 0.05em; color: var(--text-faint); margin-bottom: 1px;
  }
  body:not(.phone-off) .pm-badge, body:not(.phone-off) .pm-badge-yes, body:not(.phone-off) .pm-badge-no {
    display: block; padding: 0; border: none; background: none; border-radius: 0;
    font-size: 12px; line-height: 1.2; letter-spacing: 0.04em;
  }
  body:not(.phone-off) .pm-pin-btn {
    left: auto; right: 0; top: 6px; transform: none;
    width: 34px; height: 34px;
  }
}
@media (hover: none) {
  body:not(.phone-off) .pm-pin-btn { width: 34px; height: 34px; left: auto; top: 6px; }
}


/* Header labels: full names on desktop, short ones on a phone so all
   five fit on one line. */
.pm-hl-short { display: none; }
@media (max-width: 700px) {
  body:not(.phone-off) .pm-hl-full { display: none; }
  body:not(.phone-off) .pm-hl-short { display: inline; }
  body:not(.phone-off) .pm-row.pm-row-header {
    grid-template-columns: repeat(5, auto);
    justify-content: space-between;
    gap: 0 2px;
  }
  body:not(.phone-off) .pm-row-header .pm-header-cell { gap: 0; }
  body:not(.phone-off) .pm-row-header .pm-filter-icon-btn { width: 20px; }
}


/* Phone: the pin sits in a left gutter beside the QTY / GE / HA / TRADE?
   row (the icon + name line above it stays flush left). */
@media (max-width: 700px) {
  body:not(.phone-off) .pm-row:not(.pm-row-header) {
    grid-template-columns: 28px minmax(0, 0.85fr) minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 0.75fr);
    grid-template-areas: "img img img img img" ". qty ge ha trade";
  }
  body:not(.phone-off) .pm-pin-btn {
    left: 0; right: auto; top: auto; bottom: 8px; transform: none;
    width: 28px; height: 34px;
  }
}
/* An absurdly large stack's number wraps inside its column instead of
   running into the next one. */
@media (max-width: 700px) {
  body:not(.phone-off) .pm-value-stack, body:not(.phone-off) .pm-row:not(.pm-row-header) > .pm-col-qty { overflow-wrap: anywhere; }
}
@media (hover: none) {
  body:not(.phone-off) .pm-pin-btn { left: 0; right: auto; top: auto; bottom: 8px; width: 28px; height: 34px; }
}
