/* ============================================================================================
   Shopping List page - a structural port of the original standalone tool (jita-shopping-list.html)
   the user built and asked to have integrated: same panels, same table/fit-box/stepper/favorites-
   grid layout, same spacing and density. Buttons/inputs/badges deliberately do NOT get their own
   custom look here - they reuse the site's own real components (.btn-glass, .lp-chip-btn,
   .field-box, .field-line, .nav-tab, .lp-badge, .pill-check, all already defined in styles.css and
   available on this page via body.page-calc) so this page is built from the exact same visual
   material as the Calculator/Ledger/Invention/LP Store instead of a parallel approximation of it.
   What's left here is only what those shared components don't already cover: the panel/fit-box
   containers themselves (recolored onto --glass-fill/--glass-shadow/--radius-card, the same recipe
   body.page-calc .lp-card already uses), the qty stepper, the totals grid, and table typography -
   genuinely new shapes the rest of the site has no equivalent for. Every selector is scoped under
   .jsl so none of it can collide with or be overridden by the rest of the site's rules.
   ============================================================================================ */

.jsl {
  --jsl-border: rgba(255,255,255,0.08);
  --jsl-glow: rgba(var(--accent-rgb),0.45);
  --jsl-gold: var(--cost);
  --jsl-gold-rgb: var(--cost-rgb);
  --jsl-dim: var(--text-mute);
  --jsl-bright: var(--text);
  --jsl-red: var(--red);
  color: var(--text-soft);
  width: 100%;
}
.jsl, .jsl *, .jsl *::before, .jsl *::after { box-sizing: border-box; }
.jsl ::-webkit-scrollbar { width: 5px; }
.jsl ::-webkit-scrollbar-thumb { background: var(--jsl-glow); border-radius: 3px; }

/* ---- tab content visibility - the actual show/hide behind slSwitchTab(). Losing this rule
   (while keeping the .nav-tab button styling) is what made Wishlist/Favorites render permanently
   stacked under the Shopping List content instead of swapping in - the buttons still toggled
   .active correctly, but nothing was listening for it. ---- */
.jsl .jtab-content { display: none; }
.jsl .jtab-content.active { display: block; }

/* ---- layout - no max-width cap at all now: the page fills the full window instead of floating
   in a capped-width column with unused gutters on either side. Three real columns: the left rail
   (bulk-input forms), the middle (single-item add + the list itself, absorbing whatever space is
   left), and a tall right rail (Favorite Items) - its own column, not another wide panel stacked
   in the middle, mirroring how the left rail sits beside everything else rather than between other
   panels. ---- */
.jsl .cols { display: grid; grid-template-columns: minmax(480px, 560px) 1fr minmax(520px, 620px); gap: 20px; align-items: start; }
@media (max-width: 1900px) { .jsl .cols { grid-template-columns: minmax(480px, 560px) 1fr; } }
@media (max-width: 1100px) { .jsl .cols { grid-template-columns: 1fr; } }
.jsl .row { display: flex; align-items: center; gap: 10px; margin-top: 10px; flex-wrap: wrap; }

/* ---- panels: the same glass-fill/glass-shadow/radius-card recipe body.page-calc .lp-card
   already uses everywhere else, so a panel here reads as the same physical material as the rest
   of the site instead of a flatter, sharper-edged approximation of it. ---- */
.jsl .panel { background: var(--glass-fill); box-shadow: var(--glass-shadow); border-radius: var(--radius-card); margin-bottom: 18px; overflow: hidden; }
.jsl .ph { display: flex; align-items: center; gap: 10px; padding: 18px 24px 12px; flex-wrap: wrap; }
.jsl .pt { font-size: 14px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text); }
.jsl .pb { font-family: 'IBM Plex Mono', monospace; font-size: 11px; color: var(--jsl-dim); letter-spacing: 0.05em; margin-left: auto; }
.jsl .pd { padding: 6px 24px 22px; font-size: 13.5px; }
/* Reported directly: the left column's stack of primary actions (Import Fitting, Add All to List,
   Deducting Stock), each full-width and each using .btn-glass's solid accent-gradient fill, added
   up to an overbearing wall of green. Narrowed to content-width instead of stretching the row -
   #deduct-stock-mode specifically needs !important since it's a shared component
   (js/config.js's updateDeductStockButtonVisual, also used by the Calculator/Ledger) that
   re-applies its own hardcoded w-full class on every toggle; this only touches its width on this
   page, not the shared function itself. */
.jsl #deduct-stock-mode { width: auto !important; }

/* Reported directly: buttons across this page read as too small/fiddly to hit - the shared
   .lp-chip-btn pill (view/remove/export/import/etc.) is deliberately compact everywhere else on
   the site (a lot of them sit in dense toolbars), but this page's own action buttons carry more
   weight (they're often the only way to do something, not one of many toolbar icons), so they get
   a page-scoped size bump here rather than changing the shared component sitewide. */
.jsl .lp-chip-btn { padding: 7px 14px; font-size: 12.5px; }
.jsl .lp-chip-btn svg { width: 14px; height: 14px; }

/* ---- control chip: a small bordered, icon-led widget for a standalone numeric setting (Min
   Spread, Hauler Capacity) - reported directly as feeling too basic as a bare label+input row.
   Gives each one its own visual weight (icon, caption label, live value) instead of disappearing
   into the surrounding row of plain text and buttons. ---- */
.jsl .ctrl-chip { display: inline-flex; align-items: center; gap: 10px; background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.08); border-radius: var(--radius-btn); padding: 7px 12px; transition: border-color .15s ease; }
.jsl .ctrl-chip:focus-within { border-color: rgba(var(--accent-rgb),0.45); }
.jsl .ctrl-chip-icon { width: 20px; height: 20px; color: var(--accent); stroke: currentColor; fill: none; flex-shrink: 0; }
.jsl .ctrl-chip-label { display: block; font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--jsl-dim); margin-bottom: 2px; white-space: nowrap; }
.jsl .ctrl-chip-value { display: flex; align-items: baseline; gap: 3px; }
.jsl .ctrl-chip-value input[type=number] { background: transparent !important; border: none !important; padding: 0 !important; color: var(--text); font-family: 'IBM Plex Mono', monospace; font-weight: 700; font-size: 14px !important; outline: none; }
.jsl .ctrl-chip-value .fs { margin: 0; }
.jsl .ctrl-chip .btn-glass { margin-left: 2px; }

/* ---- text fields: reuse the site's own .field-box (primary, filled) and .field-line (secondary,
   invisible-until-focus) recipes directly via those classes in the markup - these rules only add
   the layout properties (width/resize/min-height) those shared classes don't set themselves. ---- */
.jsl textarea { width: 100%; resize: vertical; min-height: 105px; line-height: 1.65; padding: 10px 12px; font-size: 13.5px !important; }
.jsl input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; }
.jsl select { width: 100%; font-size: 13px !important; }
.jsl input[type=text] { font-size: 13.5px !important; }

/* ---- qty stepper - no equivalent component exists elsewhere on the site. ---- */
.jsl .qty { display: inline-flex; align-items: center; background: rgba(255,255,255,0.05); border-radius: var(--radius-input); flex-shrink: 0; }
.jsl .qty button { background: none; border: none; color: var(--jsl-dim); width: 30px; height: 34px; cursor: pointer; font-size: 17px; transition: color .15s ease; }
.jsl .qty button:hover { color: var(--accent); }
.jsl .qty input[type=number] { background: none !important; border: none !important; color: var(--text); font-family: 'IBM Plex Mono', monospace; font-size: 13.5px; width: 54px; text-align: center; outline: none; padding: 0 !important; }
.jsl .qty.qty-sm input[type=number] { width: 40px; }
.jsl .qty.qty-sm button { width: 28px; height: 32px; font-size: 16px; }

/* ---- autocomplete dropdown (shared by all three search boxes) ---- */
.jsl .acw { position: relative; }
.jsl .acd { position: fixed; background: #14161a; border: 1px solid var(--glass-border); z-index: 200; max-height: 320px; overflow-y: auto; border-radius: var(--radius-btn); box-shadow: 0 10px 30px rgba(0,0,0,0.5); }
.jsl .acr { display: flex; align-items: center; gap: 10px; padding: 8px 14px; cursor: pointer; border-bottom: 1px solid rgba(255,255,255,0.05); font-size: 13.5px; }
.jsl .acr:hover, .jsl .acr.hi { background: rgba(var(--accent-rgb),0.12); }
.jsl .acr img { width: 28px; height: 28px; flex-shrink: 0; object-fit: contain; border-radius: var(--radius-sm); }
.jsl .acn { color: var(--text); }

/* ---- item tables ---- */
.jsl table.jtable { width: 100%; border-collapse: collapse; font-size: 15px; table-layout: fixed; }
.jsl table.jtable th { font-family: 'IBM Plex Mono', monospace; font-size: 12px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--jsl-dim); padding: 9px 12px; text-align: left; border-bottom: 1px solid var(--jsl-border); }
.jsl table.jtable td { padding: 10px 12px; border-bottom: 1px solid rgba(255,255,255,0.05); vertical-align: middle; overflow: hidden; }
.jsl table.jtable tbody tr:last-child td { border-bottom: none; }
.jsl table.jtable tbody tr:hover td { background: rgba(255,255,255,0.025); }
.jsl .tn { color: var(--text); font-weight: 400; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jsl .tm { font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; color: var(--jsl-dim); margin-top: 2px; }
.jsl .tp { font-family: 'IBM Plex Mono', monospace; color: var(--cost); text-align: right; white-space: nowrap; }
.jsl .tv { font-family: 'IBM Plex Mono', monospace; color: var(--text-soft); text-align: right; white-space: nowrap; }

/* ---- fit box - same left-border-marks-identity idea body.page-calc .lp-job-card already uses
   for build status, applied here to mark "this is a fit" instead. ---- */
.jsl .fb { background: var(--glass-fill); box-shadow: var(--glass-shadow); border-radius: var(--radius-card); border-left: 3px solid var(--jsl-gold); margin-bottom: 12px; overflow: hidden; }
.jsl .fh { padding: 12px 16px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; cursor: pointer; user-select: none; transition: background .15s ease; }
.jsl .fh:hover { background: rgba(255,255,255,0.03); }
.jsl .fn { font-size: 17px; font-weight: 700; color: var(--cost); letter-spacing: 0.01em; }
.jsl .fs { font-family: 'IBM Plex Mono', monospace; font-size: 12px; color: var(--jsl-dim); }
.jsl .collapse-icon { color: var(--cost); margin-right: 2px; transition: transform .2s; display: inline-flex; flex-shrink: 0; }
.jsl .collapse-icon svg { width: 12px; height: 12px; }
.jsl .fb.collapsed .collapse-icon { transform: rotate(-90deg); }
.jsl .fb.collapsed .fb-body { display: none; }

/* ---- panel-level minimize, requested directly for Favorite Items and Already Have - any panel
   with this button just hides everything but its own header when collapsed, reusing the exact
   same chevron/rotate language .fb's own collapse already uses rather than inventing a second
   visual for "this is collapsible." ---- */
.jsl .panel.collapsed > *:not(.ph) { display: none; }
.jsl .panel-collapse-btn { flex-shrink: 0; }
.jsl .panel.collapsed .panel-collapse-btn .collapse-icon { transform: rotate(-90deg); }
/* Reported directly: the table's right edge (icons, the qty stepper, the Remove button) was
   getting silently clipped whenever the column was narrower than the table's own fixed-width
   columns - .panel/.fb's own overflow:hidden (needed for their rounded corners) was swallowing the
   overflow instead of showing it. A dedicated scroll container around just the table fixes this
   properly: the table can now scroll horizontally within its own box instead of being clipped, and
   the panel's rounded corners are untouched since this overflow lives one level further in. */
.jsl .fb-body, .jsl .sl-table-wrap { overflow-x: auto; }
.jsl .ship-row { background: rgba(var(--jsl-gold-rgb),0.07); }
.jsl .ship-row .tn { color: var(--cost); }
.jsl .ship-badge { font-family: 'IBM Plex Mono', monospace; font-size: 9.5px; color: var(--cost); letter-spacing: 0.06em; margin-left: 4px; }

/* ---- totals grid ---- */
.jsl .tots { display: grid; grid-template-columns: repeat(3,1fr); gap: 1px; background: var(--jsl-border); }
.jsl .tc { background: #111318; padding: 16px 20px; }
.jsl .tl { font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--jsl-dim); margin-bottom: 5px; }
.jsl .tv2 { font-size: 27px; font-weight: 700; color: var(--text); line-height: 1; }
.jsl .ts { font-family: 'IBM Plex Mono', monospace; font-size: 11.5px; color: var(--jsl-dim); margin-top: 4px; }
.jsl .hb { margin-top: 7px; height: 4px; background: rgba(255,255,255,0.08); border-radius: 2px; overflow: hidden; }
.jsl .hf { height: 100%; transition: width .4s; background: var(--accent); }
.jsl .hf.warn { background: var(--cost); }
.jsl .hf.over { background: var(--red); }
.jsl .tots-divider { height: 28px; display: flex; align-items: center; justify-content: center; gap: 12px; background: rgba(255,255,255,0.02); padding: 0 20px; }
.jsl .tots-divider::before, .jsl .tots-divider::after { content: ''; flex: 1; height: 1px; background: linear-gradient(90deg, transparent, var(--jsl-glow)); }
.jsl .tots-divider::after { background: linear-gradient(90deg, var(--jsl-glow), transparent); }
.jsl .tots-divider span { font-family: 'IBM Plex Mono', monospace; font-size: 9px; letter-spacing: 0.3em; color: var(--jsl-dim); white-space: nowrap; }

/* ---- empty state ---- */
.jsl .empty { text-align: center; padding: 34px 20px; color: var(--jsl-dim); font-size: 13.5px; }
.jsl .empty .ic { margin-bottom: 10px; opacity: .35; display: flex; justify-content: center; color: var(--text-mute); }
.jsl .empty .ic svg { width: 28px; height: 28px; }

.jsl .hint { font-size: 12.5px; color: var(--jsl-dim); line-height: 1.6; margin-top: 8px; }
.jsl .hint b { color: var(--accent); font-weight: 600; }
.jsl .divider-label { font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--jsl-dim); padding: 12px 4px 7px; }

/* ---- price toggle ---- */
.jsl .ptoggle { display: inline-flex; background: rgba(255,255,255,0.05); border-radius: var(--radius-input); overflow: hidden; flex-shrink: 0; }
.jsl .ptoggle button { background: none; border: none; color: var(--jsl-dim); font-family: 'IBM Plex Mono', monospace; font-size: 11px; font-weight: 700; letter-spacing: 0.05em; padding: 7px 13px; cursor: pointer; transition: all .15s; }
.jsl .ptoggle button.on { background: rgba(var(--accent-rgb),0.18); color: var(--accent); }

/* ---- pull list - a checklist of what's already owned (at whatever location/can is currently
   selected in Check Against My Stock) that still needs to physically go in the hauler. Checking a
   row just dims/strikes it - nothing is removed, so it's safe to click around while sorting a can
   by hand without losing your place. ---- */
.jsl .pull-row { display: flex; align-items: center; gap: 10px; padding: 8px 18px; border-bottom: 1px solid rgba(255,255,255,0.06); cursor: pointer; transition: background .15s ease; font-size: 13px; }
.jsl .pull-row:last-child { border-bottom: none; }
.jsl .pull-row:hover { background: rgba(255,255,255,0.03); }
.jsl .pull-row img { width: 26px; height: 26px; border-radius: 3px; flex-shrink: 0; }
.jsl .pull-check { width: 18px; height: 18px; border-radius: 4px; border: 1.5px solid rgba(255,255,255,0.25); flex-shrink: 0; display: flex; align-items: center; justify-content: center; color: #06110a; transition: background .15s ease, border-color .15s ease; }
.jsl .pull-check svg { width: 12px; height: 12px; stroke: currentColor; stroke-width: 3; fill: none; }
.jsl .pull-row-done .pull-check { background: var(--accent); border-color: var(--accent); }
.jsl .pull-row-done .tn { text-decoration: line-through; opacity: 0.5; }
.jsl .pull-qty { font-family: 'IBM Plex Mono', monospace; font-size: 12px; color: var(--jsl-dim); flex-shrink: 0; }


/* ---- favorites grid - sub-cards within a panel, so they get the flatter .fo-card-weight
   surface (same literal fill body.page-calc .fo-card uses) rather than full glass, keeping the
   hierarchy readable: panel = glass, cards-within-a-panel = flat. ---- */
.jsl .fav-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px,1fr)); gap: 12px; padding: 4px 22px 18px; }
.jsl .fav-card { background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.07); border-radius: var(--radius-btn); display: flex; align-items: center; gap: 14px; padding: 14px; transition: border-color .15s; position: relative; }
.jsl .fav-card:hover { border-color: rgba(255,255,255,0.16); }
/* Reported directly: the fit name was cut off with "..." and unreadable - wraps instead of
   truncating now, and the card grows to fit instead of forcing everything onto one line. */
.jsl .fav-label { font-size: 14.5px; font-weight: 600; color: var(--text); overflow-wrap: break-word; }
.jsl .fav-sub { font-family: 'IBM Plex Mono', monospace; font-size: 11px; color: var(--jsl-dim); margin-top: 3px; overflow-wrap: break-word; }
.jsl .fav-plus { flex-shrink: 0; width: 34px; height: 34px; display: flex; align-items: center; justify-content: center; background: rgba(var(--accent-rgb),0.14); color: var(--accent); cursor: pointer; transition: background .15s; border-radius: var(--radius-sm); font-weight: 700; font-size: 19px; }
.jsl .fav-plus:hover { background: rgba(var(--accent-rgb),0.28); }
/* Wishlist-only: how many copies of a fit (or units of a legacy item entry) are queued to add -
   an icon-corner badge instead of a permanent on-card stepper, so the card stays the same single
   row Favorites uses (no stepper to make room for). */
.jsl .fav-count-badge { position: absolute; bottom: -4px; right: -4px; background: var(--jsl-gold); color: #1a1400; font-family: 'IBM Plex Mono', monospace; font-size: 11px; font-weight: 800; padding: 1px 6px; border-radius: 999px; line-height: 1.4; box-shadow: 0 1px 4px rgba(0,0,0,0.5); }

/* ---- quick-favorites panel (Shopping List tab, its own right-hand column) - a narrow, tall rail
   of your favorited single items/modules, separate from the full Favorites tab (which also
   handles fits and whole saved lists, and needs a tab switch to reach). Each entry is its own
   two-line row (name on top, qty stepper + Add underneath) rather than a one-click chip - reported
   directly: clicking a favorite should let you say how many, not silently add exactly 1. ---- */
.jsl .qfav-filters { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.jsl .qfav-filter { background: rgba(255,255,255,0.05); border: none; border-radius: 999px; padding: 5px 12px; font-size: 11px; font-weight: 700; letter-spacing: 0.03em; color: var(--jsl-dim); cursor: pointer; transition: background .15s ease, color .15s ease; }
.jsl .qfav-filter:hover { color: var(--text); }
.jsl .qfav-filter.active { background: rgba(var(--accent-rgb),0.18); color: var(--accent); }
.jsl .qfav-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px; margin-top: 10px; }
.jsl .qfav-card { display: flex; align-items: center; gap: 10px; background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.07); border-radius: var(--radius-btn); padding: 10px 30px 10px 12px; cursor: pointer; transition: background .15s ease, border-color .15s ease; position: relative; }
.jsl .qfav-card:hover { background: rgba(var(--accent-rgb),0.1); border-color: rgba(var(--accent-rgb),0.3); }
.jsl .qfav-card img { width: 32px; height: 32px; border-radius: var(--radius-sm); flex-shrink: 0; }
.jsl .qfav-card .tn { flex: 1; min-width: 0; font-size: 13.5px; }
.jsl .qfav-remove { position: absolute; top: 6px; right: 6px; opacity: 0; transition: opacity .15s ease; padding: 2px 5px !important; }
.jsl .qfav-card:hover .qfav-remove { opacity: 1; }

/* ---- quick-favorites qty popup - "click the item, then say how many" instead of a stepper +
   button sitting under every single row. ---- */
.jsl .qfav-popup { background: var(--glass-fill); box-shadow: 0 20px 50px rgba(0,0,0,0.6); border-radius: var(--radius-card); width: 340px; max-width: 90vw; overflow: hidden; }
.jsl .qfav-popup-body { padding: 20px; text-align: center; }
.jsl .qfav-popup-body img { width: 48px; height: 48px; border-radius: var(--radius-sm); margin: 0 auto 10px; display: block; }
.jsl .qfav-popup-body .qty { margin: 14px auto 0; }
.jsl .qfav-popup-body .qty input[type=number] { width: 70px; font-size: 16px; }
.jsl .qfav-popup-body .qty button { width: 34px; height: 38px; font-size: 18px; }

/* ---- fit popup body ---- */
.jsl .fit-popup-body { font-family: 'IBM Plex Mono', monospace; font-size: 12.5px; color: var(--text-soft); line-height: 1.8; white-space: pre-wrap; background: rgba(0,0,0,0.2); }
