/* MarketBot theme. Dark, high-contrast, tabular data first. */

:root {
  --bg:        #0e1014;
  --surface:   #161922;
  --surface-2: #1c202b;
  --surface-3: #232837;
  --border:    #272c39;
  --border-2:  #333a4b;
  --text:      #e7eaf1;
  --muted:     #8a93a8;
  --accent:    #5b8cff;
  --accent-dim:#2b3f73;
  --success:   #35c98a;
  --warn:      #f2a93b;
  --danger:    #f0554a;
  --radius:    10px;
}

* { box-sizing: border-box; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 14px;
  line-height: 1.5;
  margin: 0;
  padding-bottom: 4rem;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
code {
  background: var(--surface-3); color: #cbd3e6;
  padding: .1em .4em; border-radius: 4px; font-size: .88em;
}
.num { font-variant-numeric: tabular-nums; }
.muted { color: var(--muted); }
.small { font-size: .82rem; }

/* ---------- layout ---------- */
.wrap { max-width: 1400px; margin: 0 auto; padding: 0 1.25rem; }

.topbar {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 50;
}
.topbar-inner {
  display: flex; align-items: center; gap: 1.5rem;
  max-width: 1400px; margin: 0 auto; padding: 0 1.25rem; min-height: 56px;
}
.brand {
  font-weight: 650; font-size: 1rem; color: var(--text);
  letter-spacing: -.01em; white-space: nowrap;
}
.brand:hover { text-decoration: none; }
.brand .dot { color: var(--accent); }

.nav { display: flex; gap: .25rem; flex: 1; flex-wrap: wrap; }
.nav a {
  color: var(--muted); padding: .45rem .7rem; border-radius: 7px;
  font-weight: 500; white-space: nowrap;
}
.nav a:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
.nav a.on { background: var(--accent-dim); color: #dbe6ff; }

.userpick {
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border-2); border-radius: 7px;
  padding: .35rem .6rem; font-size: .85rem;
}

.page-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; margin: 1.75rem 0 1rem;
}
.page-head h1 { font-size: 1.15rem; font-weight: 620; margin: 0; letter-spacing: -.01em; }
.page-head .sub { color: var(--muted); font-size: .85rem; }

/* ---------- cards ---------- */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 1rem 1.1rem;
}
.card h2 { font-size: .95rem; font-weight: 600; margin: 0 0 .75rem; }

.grid { display: grid; gap: 1rem; }
.grid.cols-4 { grid-template-columns: repeat(4, 1fr); }
.grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
/* Grid and flex children are min-width:auto by default, so one wide table inside a card
   pushes its whole column past the viewport instead of scrolling within it. This is what
   made the dashboard and settings pages overflow on a phone. */
.grid > *, .stack > * { min-width: 0; }
@media (max-width: 1000px) { .grid.cols-4 { grid-template-columns: repeat(2, 1fr); }
                             .grid.cols-2 { grid-template-columns: 1fr; } }
@media (max-width: 560px)  { .grid.cols-4 { grid-template-columns: 1fr; } }

.stat .label { color: var(--muted); font-size: .78rem; text-transform: uppercase;
               letter-spacing: .05em; margin-bottom: .3rem; }
.stat .value { font-size: 1.7rem; font-weight: 620; line-height: 1.1; }
.stat .foot  { color: var(--muted); font-size: .78rem; margin-top: .3rem; }

/* ---------- tables ---------- */
.table-wrap { overflow-x: auto; border-radius: var(--radius); border: 1px solid var(--border); }
table { width: 100%; border-collapse: collapse; background: var(--surface); }
thead th {
  background: var(--surface-2); color: var(--muted);
  font-size: .74rem; text-transform: uppercase; letter-spacing: .05em;
  font-weight: 600; text-align: left; padding: .6rem .8rem;
  border-bottom: 1px solid var(--border); white-space: nowrap;
}
tbody td { padding: .55rem .8rem; border-bottom: 1px solid var(--border); vertical-align: middle; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: var(--surface-2); }
tbody tr.dim { opacity: .45; }
.truncate { max-width: 30rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* sortable column headings */
thead th a.sortlink {
  color: inherit; text-decoration: none; display: inline-block;
  font: inherit; letter-spacing: inherit; white-space: nowrap;
}
thead th a.sortlink:hover { color: var(--text); text-decoration: none; }
thead th a.sortlink.on { color: var(--accent); }
.empty { padding: 2rem 1rem; text-align: center; color: var(--muted); }

/* ---------- category tiles ----------
   The Listings page opens on these: one tile per category with its live count. Clicking
   one drills into that category's items. */
.tiles {
  display: grid; gap: .7rem; margin-bottom: 1.25rem;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
}
.tile {
  display: flex; flex-direction: column; gap: .15rem;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: .85rem .95rem;
  color: var(--text); text-decoration: none;
  transition: border-color .12s, background .12s;
}
.tile:hover { border-color: var(--accent-dim); background: var(--surface-2); text-decoration: none; }
.tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* The tile you drilled into stays highlighted, so the row doubles as a category switcher. */
.tile.on { border-color: var(--accent); background: rgba(91,140,255,.09); }

.tile-name  { font-weight: 550; font-size: .88rem; }
.tile-count { font-size: 1.85rem; font-weight: 650; line-height: 1.15; letter-spacing: -.02em; }
.tile-foot  { display: flex; align-items: center; gap: .4rem; min-height: 1.3rem; }
.tile-age   { color: var(--muted); font-size: .76rem; }
.tiles-empty { margin: -.5rem 0 1.25rem; }

/* Drilled into a category: the tiles become a one-row switcher that scrolls sideways,
   so the items start near the top of the screen rather than below the full grid. */
.tiles.compact {
  display: flex; gap: .4rem; overflow-x: auto; margin-bottom: .9rem;
  padding-bottom: .25rem; scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.tiles.compact::-webkit-scrollbar { display: none; }
.tiles.compact .tile {
  flex: none; flex-direction: row; align-items: baseline; gap: .4rem;
  padding: .4rem .75rem; border-radius: 999px; white-space: nowrap;
}
.tiles.compact .tile-name  { font-size: .82rem; }
.tiles.compact .tile-count { font-size: .95rem; font-weight: 620; color: var(--muted); }
.tiles.compact .tile.on .tile-count { color: var(--accent); }
.tiles.compact .tile-foot  { display: none; }

/* ---------- item list ----------
   Marketplace gives us no thumbnails — the collector only ever captured each card's
   aria-label — so price carries the visual weight an image normally would. */
.ilist {
  border: 1px solid var(--border); border-radius: var(--radius);
  overflow: hidden; background: var(--surface);
}
.irow {
  position: relative; display: flex; align-items: center; gap: .9rem;
  padding: .6rem .9rem; border-bottom: 1px solid var(--border);
  transition: background .12s;
}
.irow:last-child { border-bottom: 0; }
.irow:hover { background: var(--surface-2); }
.irow:focus-within { background: var(--surface-2); box-shadow: inset 2px 0 0 var(--accent); }
.irow.gone { opacity: .5; }
.irow.copy { background: var(--surface-2); }

/* The whole row is one hit area; the ×N button sits above it on z-index so it stays
   independently clickable. */
.irow-hit { position: absolute; inset: 0; z-index: 1; }
.irow-hit:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.irow-price {
  flex: 0 0 5.5rem; text-align: right;
  font-size: 1.05rem; font-weight: 650; letter-spacing: -.01em;
}
.irow-price.free { color: var(--success); }

.irow-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: .1rem; }
.irow-title {
  font-weight: 500; line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.irow:hover .irow-title { color: #fff; }
.irow-meta {
  display: flex; align-items: center; gap: .4rem; flex-wrap: wrap;
  color: var(--muted); font-size: .78rem;
}
.irow-meta .dotsep { opacity: .5; }

.irow-actions { display: flex; align-items: center; gap: .5rem; flex: none; }
.irow-actions .pill { position: relative; z-index: 2; }
.irow-go { color: var(--muted); font-size: 1rem; }
.irow:hover .irow-go { color: var(--accent); }

/* Screen readers only — the row's link text, which the styled content paints over. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- pills ---------- */
.pill {
  display: inline-block; padding: .15rem .5rem; border-radius: 999px;
  font-size: .74rem; font-weight: 600; letter-spacing: .02em;
  border: 1px solid transparent; white-space: nowrap;
}
.pill.ok      { background: rgba(53,201,138,.14);  color: var(--success); border-color: rgba(53,201,138,.3); }
.pill.warn    { background: rgba(242,169,59,.14);  color: var(--warn);    border-color: rgba(242,169,59,.3); }
.pill.bad     { background: rgba(240,85,74,.14);   color: var(--danger);  border-color: rgba(240,85,74,.3); }
.pill.neutral { background: var(--surface-3);      color: var(--muted);   border-color: var(--border-2); }
.pill.info    { background: rgba(91,140,255,.14);  color: var(--accent);  border-color: rgba(91,140,255,.3); }

/* Duplicate-group badge on Listings. It is a <button>, so reset the UA styles the
   other pills never need. */
.pill.dupes {
  background: var(--surface-3); color: var(--muted); border-color: var(--border-2);
  font-family: inherit; line-height: inherit; cursor: pointer;
}
.pill.dupes:hover { color: var(--text); border-color: var(--accent); }
.pill.dupes.on    { background: rgba(91,140,255,.14); color: var(--accent);
                    border-color: rgba(91,140,255,.3); }
tbody tr.copy     { background: var(--surface-2); }
.copy-mark        { color: var(--muted); padding-left: .35rem; }

/* ---------- forms ---------- */
label.field { display: block; margin-bottom: .8rem; }
label.field > span { display: block; color: var(--muted); font-size: .78rem;
                     margin-bottom: .25rem; font-weight: 500; }
input[type=text], input[type=email], input[type=number], input[type=search], select, textarea {
  width: 100%; background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border-2); border-radius: 7px;
  padding: .45rem .6rem; font-size: .875rem; font-family: inherit;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(91,140,255,.15);
}
.hint { color: var(--muted); font-size: .76rem; margin-top: .25rem; }

.btn {
  display: inline-block; background: var(--surface-3); color: var(--text);
  border: 1px solid var(--border-2); border-radius: 7px;
  padding: .45rem .85rem; font-size: .85rem; font-weight: 550;
  cursor: pointer; font-family: inherit; white-space: nowrap;
}
.btn:hover { background: var(--border-2); text-decoration: none; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.primary:hover { background: #4a7ce8; }
.btn.danger  { color: var(--danger); border-color: rgba(240,85,74,.35); background: transparent; }
.btn.danger:hover { background: rgba(240,85,74,.12); }
.btn.sm { padding: .25rem .55rem; font-size: .78rem; }

/* Google sign-in button. White with the official mark, per Google's branding rules —
   deliberately not themed to the dark UI. */
.btn.google {
  display: flex; align-items: center; justify-content: center; gap: .6rem;
  width: 100%; background: #fff; color: #1f1f1f; border-color: #dadce0;
  font-weight: 600; text-decoration: none;
}
.btn.google:hover { background: #f5f6f7; border-color: #c8ccd0; }
.btn.google svg { flex: none; }

/* "or" rule between the Google button and the password form */
.authdivider {
  display: flex; align-items: center; gap: .75rem;
  margin: 1.1rem 0; color: var(--muted); font-size: .78rem;
}
.authdivider::before, .authdivider::after {
  content: ''; flex: 1; height: 1px; background: var(--border-2);
}
.btn:disabled { opacity: .45; cursor: not-allowed; }

.toolbar { display: flex; gap: .6rem; flex-wrap: wrap; align-items: flex-end; margin-bottom: 1rem; }
.toolbar .grow { flex: 1; min-width: 12rem; }

/* Search is always visible; everything else folds into a disclosure so the listings
   start near the top of the screen instead of below eleven controls. */
.searchbar { display: flex; gap: .6rem; align-items: center; margin-bottom: .6rem; }
.searchbar input[type=search] { flex: 1; min-width: 0; }

.filters { margin-bottom: 1rem; }
.filters > summary {
  display: flex; align-items: center; gap: .5rem; cursor: pointer;
  color: var(--muted); font-size: .85rem; font-weight: 550;
  padding: .4rem 0; list-style: none; user-select: none;
}
.filters > summary::-webkit-details-marker { display: none; }
.filters > summary::before {
  content: '▸'; display: inline-block; transition: transform .12s; font-size: .8em;
}
.filters[open] > summary::before { transform: rotate(90deg); }
.filters > summary:hover { color: var(--text); }
.filters .toolbar { margin-bottom: 0; padding-top: .3rem; }

/* ---------- category picker ---------- */
.cats { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: .6rem; }
.cat input { position: absolute; opacity: 0; pointer-events: none; }
.cat label {
  display: flex; align-items: center; gap: .65rem; cursor: pointer;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 9px; padding: .7rem .85rem; transition: border-color .12s, background .12s;
}
.cat label:hover { border-color: var(--border-2); background: var(--surface-2); }
.cat input:checked + label {
  border-color: var(--accent); background: rgba(91,140,255,.09);
}
.cat input:focus-visible + label { box-shadow: 0 0 0 3px rgba(91,140,255,.25); }
.cat .box {
  width: 18px; height: 18px; border-radius: 5px; flex: 0 0 18px;
  border: 1.5px solid var(--border-2); background: var(--surface-2);
  display: grid; place-items: center;
}
.cat input:checked + label .box { background: var(--accent); border-color: var(--accent); }
.cat .box svg { opacity: 0; width: 12px; height: 12px; }
.cat input:checked + label .box svg { opacity: 1; }
.cat .name { flex: 1; font-weight: 520; }
.cat .count { color: var(--muted); font-size: .78rem; font-variant-numeric: tabular-nums; }

.savebar {
  position: sticky; bottom: 0; margin-top: 1rem;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: .75rem 1rem; display: flex; align-items: center;
  justify-content: space-between; gap: 1rem; flex-wrap: wrap;
}
.savebar .summary { color: var(--muted); font-size: .85rem; }
.savebar .summary strong { color: var(--text); }

/* ---------- auth pages ---------- */
.authwrap { min-height: 100vh; display: grid; place-items: center; padding: 2rem 1.25rem; }
.authcard {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 14px; padding: 1.75rem; width: 100%; max-width: 22rem;
}
.authbrand { font-size: 1.25rem; font-weight: 650; letter-spacing: -.02em; }
.authbrand .dot { color: var(--accent); }
.authsub { color: var(--muted); font-size: .85rem; margin: .2rem 0 1.25rem; }
input[type=password] {
  width: 100%; background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border-2); border-radius: 7px;
  padding: .45rem .6rem; font-size: .875rem; font-family: inherit;
}

.who { display: flex; align-items: center; gap: .6rem; white-space: nowrap; }
.who .name { color: var(--muted); font-size: .85rem; }

/* ---------- misc ---------- */
.banner {
  border-radius: var(--radius); padding: .75rem 1rem; margin-bottom: 1rem;
  border: 1px solid transparent; font-size: .87rem;
}
.banner.ok   { background: rgba(53,201,138,.1); border-color: rgba(53,201,138,.3); color: #9fe7c6; }
.banner.warn { background: rgba(242,169,59,.1); border-color: rgba(242,169,59,.3); color: #f6d9a6; }
.stack > * + * { margin-top: 1rem; }

/* ==========================================================================
   Mobile
   ==========================================================================
   The desktop layout is built around wide tables, which is the wrong shape for a
   phone. Three things change, in this order of impact:

   1. The top bar stops wrapping into a tall column and becomes an identity row
      plus a horizontally scrollable nav strip. Unstyled it consumed the entire
      first screen and pushed "Sign out" off the right edge.
   2. Tables stop being tables. Each row becomes a card and each cell prints its
      column name from data-label, so nothing depends on horizontal scrolling.
   3. Controls grow to a thumb-friendly size and inputs go to 16px, below which
      iOS Safari zooms the page whenever a field takes focus.
   ========================================================================== */

@media (max-width: 820px) {
  .wrap { padding: 0 .9rem; }

  .topbar-inner {
    flex-wrap: wrap; gap: .4rem .75rem; padding: .5rem .9rem; min-height: 0;
  }
  .brand { order: 1; }
  .who   { order: 2; margin-left: auto; gap: .45rem; }
  /* Long names must not shove the sign-out button off-screen. */
  .who .name { max-width: 46vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* One scrolling strip rather than a wrapped block of links. */
  .nav {
    order: 3; flex-basis: 100%; flex-wrap: nowrap; overflow-x: auto;
    gap: .15rem; padding-bottom: .1rem;
    scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .nav::-webkit-scrollbar { display: none; }

  .page-head { margin: 1.1rem 0 .85rem; }

  /* 16px is the threshold: anything smaller and iOS Safari zooms on focus and the
     user is left scrolled sideways on a page that otherwise fits. */
  input[type=text], input[type=email], input[type=number], input[type=search],
  input[type=password], select, textarea {
    font-size: 16px; padding: .55rem .65rem;
  }
  /* Tap targets. Keyed off width rather than (pointer: coarse) alone — pointer
     detection is unreliable (it does not report coarse under emulation, and a touch
     laptop reports both), and at this width we are on a phone regardless. */
  .btn, .nav a, .brand {
    min-height: 40px; display: inline-flex; align-items: center; justify-content: center;
  }
  .btn { padding: .5rem 1rem; font-size: .9rem; }
  .btn.sm { padding: .4rem .75rem; font-size: .82rem; }
  .btn.google { min-height: 44px; }
  .cat label { min-height: 44px; }
  /* The duplicate badge sits inline in a sentence, so it gets a usable target without
     being inflated to full button height. */
  .pill.dupes { min-height: 32px; display: inline-flex; align-items: center;
                padding: .15rem .65rem; }
  /* A default checkbox renders around 13px, which is not tappable. */
  input[type=checkbox] { width: 20px; height: 20px; }
  .card { padding: .9rem; }
}

/* Touch screens wider than a phone — tablets, touch laptops — get the same sizing. */
@media (pointer: coarse) and (min-width: 821px) {
  .btn, .nav a { min-height: 40px; display: inline-flex; align-items: center; }
  .cat label { min-height: 44px; }
}

@media (max-width: 700px) {
  /* Rows become cards. thead is dropped and each cell carries its own label, so no
     column is hidden behind a sideways scroll the way it is on the desktop layout. */
  .table-wrap { overflow: visible; border: 0; border-radius: 0; background: none; }
  table, thead, tbody, tr, td { display: block; width: 100%; }
  table { background: none; }
  thead { display: none; }

  tbody tr {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); margin-bottom: .6rem; padding: .3rem 0;
  }
  tbody tr:hover { background: var(--surface); }
  tbody tr:last-child td { border-bottom: 0; }

  tbody td {
    display: grid; grid-template-columns: 6.5rem minmax(0, 1fr);
    gap: .5rem .7rem; align-items: start;
    padding: .35rem .85rem; border-bottom: 0;
  }
  tbody td::before {
    content: attr(data-label);
    color: var(--muted); font-size: .72rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: .04em; padding-top: .12rem;
  }
  /* Action cells carry no label, so they get the full width for their buttons. */
  tbody td:not([data-label]) { grid-template-columns: minmax(0, 1fr); padding-top: .55rem; }
  tbody td:not([data-label])::before { content: none; }
  tbody td .btn { width: 100%; text-align: center; }
  /* Paired actions (Pause/Delete, Approve/Deny, Open/Not interested) sit side by side
     rather than stacking. */
  tbody td.wt-actions, tbody td.req-actions, tbody td.mt-actions {
    grid-template-columns: 1fr 1fr; gap: .5rem; align-items: center;
  }

  /* Titles wrap instead of being clipped — there is no second column competing now. */
  .truncate { max-width: none; white-space: normal; overflow: visible; }
  /* The row is already a bordered card, so the empty-state cell must not add a second. */
  .empty { padding: 1.5rem 1rem; }

  /* Filter bar: search on its own line, the narrow number fields paired up. */
  .toolbar { display: grid; grid-template-columns: 1fr 1fr; gap: .55rem; align-items: end; }
  .toolbar > * { min-width: 0 !important; width: auto !important; }
  .toolbar .grow, .toolbar .tb-cat, .toolbar .tb-sub { grid-column: 1 / -1; }
  .toolbar label { grid-column: 1 / -1; }
  .toolbar .btn, .toolbar button { width: 100%; }

  /* Two tiles per row keeps the whole category set glanceable without scrolling. */
  .tiles { grid-template-columns: 1fr 1fr; gap: .55rem; }
  .tile { padding: .7rem .75rem; }
  .tile-count { font-size: 1.5rem; }
  .tiles.compact { display: flex; }
  .tiles.compact .tile { padding: .4rem .7rem; }

  /* Price above the title rather than beside it — a fixed price column would leave the
     title barely any room at 390px. */
  .irow { flex-wrap: wrap; gap: .15rem .6rem; padding: .7rem .8rem; }
  .irow-price { flex: none; text-align: left; order: 1; font-size: 1.05rem; }
  .irow-actions { order: 2; margin-left: auto; }
  .irow-main { order: 3; flex-basis: 100%; }
  .irow-title { white-space: normal; }

  .savebar { padding: .7rem .85rem; }
  .savebar .btn { width: 100%; }
}

/* Genuinely tiny screens only — the label column stops earning its keep below about
   340px. This deliberately does NOT catch 375/390/393px, which is where most iPhones
   sit: stacking there doubled the height of every card for no gain. */
@media (max-width: 340px) {
  tbody td { grid-template-columns: minmax(0, 1fr); gap: .1rem; }
  tbody td::before { padding-top: 0; }
}

/* .cat label is a flex row of checkbox + name + count; the tap-target rules above must
   not re-centre its contents. */
.cat label { justify-content: flex-start; }
