/* oboae-inspired with breathing room + modal preview */

/* ---- Tokens ---- */
:root {
  --bg: #faf9f5;
  --surface: #ffffff;
  --surface-2: #f1efe9;
  --text: #1a1a1a;
  --text-2: #6a6a6a;
  --text-3: #a3a3a3;
  --line: #e6e2d6;
  --line-strong: #1a1a1a;
  --accent: #c8392f;
  --gap: 18px;
  --side: 56px;
  --radius: 0px;
  --transition: 240ms cubic-bezier(.2,.7,.2,1);
}
[data-theme="dark"] {
  --bg: #0e0e0e;
  --surface: #161616;
  --surface-2: #1c1c1c;
  --text: #f0efe9;
  --text-2: #a8a6a0;
  --text-3: #6a6a6a;
  --line: #232320;
  --line-strong: #f0efe9;
  --accent: #ee5d4a;
}

/* ---- Reset ---- */
* { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: "Courier Prime", "Courier New", "JetBrains Mono",
               ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
  font-size: 13px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
/* Lock the main grid while the sidebar is open so wheel/touchpad scrolls
   never reach it. `scrollbar-gutter: stable` keeps a placeholder for the
   scrollbar so the grid doesn't jump horizontally when the bar disappears. */
body.has-sidebar {
  overflow: hidden;
  scrollbar-gutter: stable;
}
a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }
button, input, select { font: inherit; color: inherit; background: none; border: none; }

/* ---- Top bar ---- */
.topbar {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(250, 249, 245, 0.92);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--line);
}
[data-theme="dark"] .topbar { background: rgba(14, 14, 14, 0.88); }
.topbar-inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 28px var(--side) 22px;
  gap: 16px;
}
.brand {
  display: flex;
  align-items: baseline;
  gap: 14px;
  min-width: 0;
}
.brand h1 {
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0.06em;
  text-transform: lowercase;
  white-space: nowrap;
}
.brand .meta {
  font-size: 11px;
  color: var(--text-3);
  letter-spacing: 0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-variant-numeric: tabular-nums;
}
.brand .meta .sep { margin: 0 6px; opacity: 0.6; }

/* Brand title and logo are anchors back to home — keep them visually
   identical to the previous spans, just with a subtle hover lift. */
.brand-link { color: inherit; text-decoration: none; cursor: pointer; }
.brand-link:hover h1 { opacity: 0.7; }
a.logo-mark { text-decoration: none; color: inherit; cursor: pointer; transition: opacity var(--transition); }
a.logo-mark:hover { opacity: 0.7; }

.logo-mark {
  width: 22px;
  height: 22px;
  border: 1px solid var(--text);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  margin: 0 auto;
}

.theme-toggle {
  justify-self: end;
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: var(--text-2);
  transition: var(--transition);
}
.theme-toggle:hover { color: var(--text); }

/* ---- Filter bar (3-tier hierarchy) ----
   Tier 1 — search-row: primary search + sort + apply  (visually heaviest)
   Tier 2 — chip-row:   quick toggles (new 24h, ♥ favorites)  (light pills)
   Tier 3 — deep filters: collapsible site/brand/category/size sections
*/
.filters {
  border-bottom: 1px solid var(--line);
}

/* Tier 1 — primary action row */
.search-row {
  display: flex;
  align-items: stretch;
  border-bottom: 1px solid var(--line);
  padding: 0 var(--side);
}
.search-row > * + * { border-left: 1px solid var(--line); }

.search-input {
  flex: 1 1 280px;
  min-width: 200px;
  padding: 16px 22px;
  font-size: 13px;
  letter-spacing: 0.02em;
}
.search-input::placeholder { color: var(--text-3); text-transform: lowercase; }
.search-input:focus { outline: none; background: var(--surface-2); }

.sort-select {
  padding: 16px 36px 16px 22px;
  font-size: 12px;
  cursor: pointer;
  appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'><path fill='%23999' d='M6 8L2 4h8z'/></svg>");
  background-repeat: no-repeat;
  background-position: right 16px center;
  background-size: 8px;
  min-width: 130px;
}
.sort-select:hover { background-color: var(--surface-2); }

.btn-primary, .btn-ghost {
  font-size: 12px;
  cursor: pointer;
  letter-spacing: 0.06em;
  text-transform: lowercase;
  transition: var(--transition);
  padding: 16px 22px;
}
.btn-primary { background: var(--text); color: var(--bg); }
.btn-primary:hover { opacity: 0.85; }
.btn-ghost { color: var(--text-2); }
.btn-ghost:hover { background: var(--surface-2); color: var(--text); }

/* deep filters wrapper */
.deep-filters {
  padding: 4px var(--side) 4px;
}
.deep-filters-title {
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: lowercase;
  color: var(--text-3);
  padding: 12px 0 0;
  display: flex;
  align-items: baseline;
  gap: 12px;
}
.filters-toggle-all {
  background: transparent;
  border: 0;
  padding: 0;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: var(--text-2);
  cursor: pointer;
  transition: color var(--transition);
}
.filters-toggle-all:hover { color: var(--text); }

/* Topbar nav links (right side) */
.topbar-nav {
  display: flex;
  align-items: center;
  gap: 16px;
  justify-self: end;
}
.topbar-nav a {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: lowercase;
  color: var(--text-2);
  border-bottom: 1px solid transparent;
  padding-bottom: 1px;
  transition: var(--transition);
}
.topbar-nav a:hover { color: var(--text); border-bottom-color: var(--text-2); }
.nav-label--mobile { display: none; }

/* ---- Saved filter presets ---- */
.presets {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px var(--side) 6px;
  border-top: 1px solid var(--line);
  font-size: 11px;
}
.presets-label {
  color: var(--text-3);
  letter-spacing: 0.08em;
  text-transform: lowercase;
  flex-shrink: 0;
}
.presets-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.preset-chip {
  display: inline-flex;
  align-items: center;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  overflow: hidden;
  transition: border-color var(--transition);
}
.preset-chip:hover { border-color: var(--text-2); }
.preset-link {
  padding: 4px 12px;
  color: var(--text);
  letter-spacing: 0.04em;
  text-transform: lowercase;
}
.preset-link:hover { color: var(--accent); }
.preset-del {
  /* Collapsed: padding stays 0 so the box is truly zero-sized and doesn't
     bake invisible right-side whitespace into the chip. Padding shows up
     only on hover, alongside the width/opacity reveal. */
  padding: 0;
  color: var(--text-3);
  font-size: 10px;
  cursor: pointer;
  opacity: 0;
  width: 0;
  transition: opacity var(--transition),
              width var(--transition),
              padding var(--transition),
              color var(--transition);
  overflow: hidden;
}
.preset-chip:hover .preset-del {
  opacity: 1;
  width: auto;
  padding: 4px 8px;
}
.preset-del:hover { color: var(--accent); }
.preset-save {
  padding: 4px 12px;
  border: 1px dashed var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--text-2);
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: lowercase;
  cursor: pointer;
  transition: var(--transition);
}
.preset-save:hover { border-color: var(--text-2); color: var(--text); }

/* Inline save: the input is zero-width by default and grows to push the
   button rightward when activated. We animate width/padding/opacity so the
   transition reads as "input appears in the button's spot, button slides
   right" rather than a popup. */
.preset-save-form {
  display: inline-flex;
  align-items: center;
  gap: 0;
}
.preset-save-input {
  width: 0;
  padding: 4px 0;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  font-size: 11px;
  letter-spacing: 0.04em;
  outline: none;
  opacity: 0;
  margin-right: 0;
  transition: width 240ms cubic-bezier(.2,.6,.2,1),
              padding 240ms cubic-bezier(.2,.6,.2,1),
              opacity 200ms ease,
              margin-right 240ms cubic-bezier(.2,.6,.2,1);
}
.preset-save-input::placeholder { color: var(--text-3); }
.preset-save-form[data-state="active"] .preset-save-input {
  width: 160px;
  padding: 4px 12px;
  opacity: 1;
  margin-right: 6px;
}
.preset-save-form[data-state="active"] .preset-save {
  /* Active = confirm intent: switch from dashed (placeholder) to solid. */
  border-style: solid;
  border-color: var(--text-2);
  color: var(--text);
}

/* ---- Site filter ---- */
.site-filter { width: 100%; }
.site-filter summary {
  list-style: none;
  cursor: pointer;
  /* L/R intentionally zero — the parent .deep-filters provides var(--side)
     gutters on both sides, so summary content lines up flush with the
     topbar brand, the deep-filters-title, and the product grid edges. */
  padding: 14px 0;
  font-size: 11px;
  color: var(--text-2);
  letter-spacing: 0.06em;
  text-transform: lowercase;
  user-select: none;
  border-top: 1px solid var(--line);
  transition: background var(--transition);
}
.site-filter summary::-webkit-details-marker { display: none; }
.site-filter summary::before {
  content: "[ + ] ";
  margin-right: 4px;
}
.site-filter[open] summary::before { content: "[ − ] "; }
.site-filter summary:hover { background: var(--surface-2); color: var(--text); }

.site-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 0 16px;
  padding: 12px 0 20px;
  border-top: 1px dashed var(--line);
}
.site-checkbox {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  font-size: 11px;
  color: var(--text-2);
  cursor: pointer;
  transition: color var(--transition);
}
.site-checkbox:hover { color: var(--text); }
.site-checkbox input { accent-color: var(--text); width: 11px; height: 11px; }
.site-checkbox em { color: var(--text-3); font-style: normal; font-variant-numeric: tabular-nums; }

/* "only" shortcut: hidden until the row is hovered, then reveals next to
   the count. Clicking narrows the facet to this single value via JS — see
   pickOnly() in index.html. */
.site-checkbox { position: relative; }
.site-checkbox .only-link {
  margin-left: auto;
  padding-left: 8px;
  font-size: 9px;
  letter-spacing: 0.12em;
  text-transform: lowercase;
  color: var(--text-3);
  opacity: 0;
  transition: opacity var(--transition), color var(--transition);
}
.site-checkbox:hover .only-link { opacity: 1; }
.site-checkbox .only-link:hover { color: var(--accent); }

.price-range {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 22px 20px;
  border-top: 1px dashed var(--line);
}
.price-range input[type="number"] {
  width: 110px;
  padding: 7px 10px;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 4px;
  color: var(--text);
}
.price-range input[type="number"]:focus {
  outline: none;
  border-color: var(--text);
}
.price-range-sep { color: var(--text-3); font-size: 11px; }
.price-range-apply {
  padding: 7px 14px;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: lowercase;
}

/* ---- Unified action buttons (heart + cart) ----
   One ruleset shared between card overlays and the sidebar actions row.
   Card variant: absolute-positioned overlay revealed on hover.
   Sidebar variant: static, always visible. */
.fav-btn, .cart-btn {
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  line-height: 1;
  color: var(--text-2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 0;
  cursor: pointer;
  padding: 0;
  transition: opacity var(--transition), color var(--transition), border-color var(--transition);
}
.fav-btn:hover, .cart-btn:hover {
  color: var(--text);
  border-color: var(--text-2);
}

/* Heart: outline always, fills with color when active — the SHAPE never
   changes between states, only the fill flips. Stroke kept thin for a
   delicate look that pairs with the rest of the line-weight aesthetic. */
.fav-btn svg {
  width: 18px;
  height: 18px;
  display: block;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.fav-btn.is-fav { color: var(--accent); }
.fav-btn.is-fav svg { fill: currentColor; }

/* Sidebar buttons take the page background just like card overlays so
   the visual treatment is identical between the grid and the sidebar. */
.sidebar-actions .fav-btn,
.sidebar-actions .cart-btn {
  background: var(--bg);
}

/* Cart bag (only rendered when in cart). */
.cart-btn svg {
  width: 18px;
  height: 18px;
  display: block;
  fill: currentColor;
}
.cart-btn.is-in-cart { color: var(--text); }

/* Card overlay placement + hover-reveal. Buttons take the *page* background
   (not the card surface) so they feel like the page reaching through the
   card rather than a solid sticker on top of the image. */
.card .fav-btn,
.card .cart-btn,
.card .dislike-btn {
  position: absolute;
  bottom: 10px;
  z-index: 4;
  opacity: 0;
  background: var(--bg);
}
.card .fav-btn  { right: 10px; }
.card .cart-btn { right: 56px; }   /* 10px gap + 36px wide button */
.card .dislike-btn {
  right: 102px;
  width: 36px;
  height: 36px;
  padding: 0;
  color: var(--text-2);
  border: 1px solid var(--line);
  background: var(--bg);
  cursor: pointer;
  font-size: 20px;
}
.card:hover .fav-btn,
.card:hover .cart-btn,
.card:hover .dislike-btn,
.card .fav-btn.is-fav,
.card .cart-btn.is-in-cart { opacity: 1; }

.dislike-popover {
  position: absolute;
  right: 92px;
  bottom: 50px;
  z-index: 6;
  display: none;
  min-width: min(220px, calc(100% - 16px));
  padding: 6px;
  border: 1px solid var(--line);
  background: var(--surface);
  box-shadow: 0 12px 32px -8px rgba(0,0,0,.18);
}
.dislike-popover.is-open { display: flex; flex-direction: column; }
.dislike-popover button {
  overflow: hidden;
  padding: 9px 10px;
  border: 0;
  background: transparent;
  color: var(--text);
  cursor: pointer;
  font-size: 11px;
  text-align: left;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dislike-popover button:hover { background: var(--surface-2); }
.dislike-popover button:disabled { color: var(--text-3); cursor: wait; }

/* Empty-state copy in the folder popover when no user folders exist. */
.fav-popover .folder-empty {
  padding: 8px 4px;
  font-size: 11px;
  color: var(--text-3);
  text-align: center;
}

/* Folder navigation chips shown on /?favs=1 above the grid. */
.fav-folder-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 14px 22px;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}
.fav-folder-nav .folder-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 6px 12px;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--text-2);
  border: 1px solid var(--line);
  border-radius: 4px;
  text-decoration: none;
  transition: var(--transition);
}
.fav-folder-nav .folder-chip:hover {
  color: var(--text);
  border-color: var(--text-2);
}
.fav-folder-nav .folder-chip.is-active {
  color: var(--bg);
  background: var(--text);
  border-color: var(--text);
}
.fav-folder-nav .folder-chip em {
  font-style: normal;
  color: var(--text-3);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
}
.fav-folder-nav .folder-chip.is-active em { color: var(--bg); opacity: 0.6; }

/* Topbar nav count badge (cart). */
.topbar-nav .nav-badge {
  font-style: normal;
  font-size: 10px;
  padding: 1px 6px;
  margin-left: 2px;
  border-radius: 10px;
  background: var(--text);
  color: var(--bg);
  font-variant-numeric: tabular-nums;
}
.logout-form { display: inline-flex; }
.logout-form button {
  padding: 0;
  border: 0;
  color: var(--text-2);
  cursor: pointer;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
}
.logout-form button:hover { color: var(--text); }

/* ---- Authentication ---- */
.auth-page {
  display: grid;
  min-height: 100dvh;
  place-items: center;
  padding: 24px;
  background: var(--bg);
}
.auth-card {
  width: min(420px, 100%);
  padding: 32px;
  border: 1px solid var(--line);
  background: var(--surface);
}
.auth-brand { color: var(--text-2); font-size: 12px; letter-spacing: .06em; }
.auth-card h1 { margin: 30px 0 8px; font-size: 24px; font-weight: 400; }
.auth-card > p { margin: 0 0 24px; color: var(--text-3); font-size: 12px; line-height: 1.6; }
.auth-error { margin-bottom: 16px; padding: 10px 12px; border: 1px solid var(--accent); color: var(--accent); font-size: 11px; }
.auth-form { display: grid; gap: 16px; }
.auth-form label { display: grid; gap: 7px; color: var(--text-2); font-size: 10px; letter-spacing: .08em; text-transform: lowercase; }
.auth-form input { width: 100%; padding: 12px; border: 1px solid var(--line); background: var(--bg); color: var(--text); font: inherit; font-size: 16px; }
.auth-form input:focus { outline: none; border-color: var(--text); }
.auth-form .btn-primary { margin-top: 6px; padding: 13px; cursor: pointer; }

/* (heart styles unified above with .fav-btn, .cart-btn block) */

/* ---- Favorite folder popover ---- */
.fav-popover {
  position: absolute;
  bottom: 50px;
  right: 8px;
  z-index: 5;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: 0 12px 32px -8px rgba(0,0,0,0.18);
  min-width: 200px;
  padding: 6px;
  display: none;
  flex-direction: column;
  gap: 2px;
}
.fav-popover.is-open { display: flex; }
.fav-popover-title {
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: lowercase;
  color: var(--text-3);
  padding: 6px 10px 4px;
}
.fav-popover button {
  text-align: left;
  padding: 8px 10px;
  font-size: 12px;
  color: var(--text);
  cursor: pointer;
  background: transparent;
  border: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.fav-popover button:hover { background: var(--surface-2); }
.fav-popover button.is-active { color: var(--accent); }
.fav-popover button.is-active::after { content: "♥"; }
.fav-popover .new-folder {
  display: flex;
  gap: 4px;
  padding: 6px 4px 4px;
  border-top: 1px solid var(--line);
  margin-top: 4px;
}
.fav-popover .new-folder input {
  flex: 1;
  padding: 6px 8px;
  font-size: 12px;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--line);
  font-family: inherit;
}
.fav-popover .new-folder input:focus { outline: none; border-color: var(--text-2); }
.fav-popover .new-folder button {
  padding: 6px 12px;
  background: var(--text);
  color: var(--bg);
  font-size: 11px;
}

/* sidebar action heart — overrides .fav-btn absolute positioning */
.sidebar-fav-wrap { position: relative; display: inline-flex; }
#sidebar-fav.fav-btn {
  position: relative;
  bottom: auto; right: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  font-size: 18px;
  line-height: 1;
  padding-top: 3px;     /* nudge ♥ glyph onto optical center */
  opacity: 1;
  background: transparent;
  border: 1px solid var(--line);
  color: var(--text-2);
  border-radius: 0;
}
#sidebar-fav.fav-btn:hover { color: var(--text); border-color: var(--text-2); transform: none; }
#sidebar-fav.fav-btn.is-fav {
  background: var(--accent-soft, rgba(200,57,47,.1));
  color: var(--accent);
  border-color: var(--accent);
}
#sidebar-fav-popover {
  bottom: calc(100% + 6px);   /* anchor above the button (inside the bottom bar) */
  top: auto;
  right: 0;
}

/* ---- Cross-site duplicate panel ---- */
.sidebar-dups {
  margin-top: 6px;
  padding-top: 8px;
  border-top: 1px dashed var(--line);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.sidebar-dups .dup-title {
  font-size: 9px;
  letter-spacing: 0.12em;
  text-transform: lowercase;
  color: var(--text-3);
  padding: 2px 0 4px;
}
.sidebar-dups .dup-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 4px 0;
  font-size: 11px;
  color: var(--text-2);
  border-bottom: 1px dotted transparent;
  transition: var(--transition);
}
.sidebar-dups .dup-row:hover {
  color: var(--text);
  border-bottom-color: var(--text-3);
}
.sidebar-dups .dup-site {
  letter-spacing: 0.04em;
  text-transform: lowercase;
}
.sidebar-dups .dup-price {
  font-variant-numeric: tabular-nums;
}

/* ---- Similar products (3-col grid, below detail; aside scrolls to it) ---- */
.sidebar-similar {
  flex: 0 0 auto;
  padding: 12px 14px 16px;
  border-top: 1px solid var(--line);
  background: var(--surface);
}
.sidebar-similar .sim-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 0 0 8px;
}
.sidebar-similar .sim-title {
  font-size: 9px;
  letter-spacing: 0.12em;
  text-transform: lowercase;
  color: var(--text-3);
}
.sidebar-similar .sim-soldout-toggle {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 9px;
  letter-spacing: 0.04em;
  text-transform: lowercase;
  color: var(--text-2);
  cursor: pointer;
  user-select: none;
}
.sidebar-similar .sim-soldout-toggle input {
  width: 11px;
  height: 11px;
  margin: 0;
  cursor: pointer;
  accent-color: var(--text);
}
/* Hide-toggle on: drop sold-out cards from the rail entirely. */
.sidebar-similar.hide-soldout .sim-card--soldout { display: none; }
.sidebar-similar .sim-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}
.sidebar-similar .sim-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 4px;
  text-decoration: none;
  color: var(--text);
  transition: var(--transition);
  cursor: pointer;
  min-width: 0;
}
/* Match the main grid: lift the card, soften-shadow the thumb, gently
   zoom the image. Keeps the visual language identical between contexts. */
.sidebar-similar .sim-card:hover {
  transform: translateY(-2px);
}
.sidebar-similar .sim-card:hover .sim-thumb {
  box-shadow: 0 6px 18px -8px rgba(0, 0, 0, 0.18);
}
.sidebar-similar .sim-card:hover .sim-thumb img {
  transform: scale(1.03);
}
.sidebar-similar .sim-thumb {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  background: var(--surface-2, #f4f4f4);
  overflow: hidden;
  border-radius: var(--radius);
  transition: box-shadow var(--transition);
}
.sidebar-similar .sim-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 700ms cubic-bezier(.2, .6, .2, 1);
}
.sidebar-similar .sim-meta {
  display: flex;
  flex-direction: column;
  gap: 1px;
  font-size: 10px;
  line-height: 1.25;
}
.sidebar-similar .sim-name {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: var(--text-2);
}
.sidebar-similar .sim-foot {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 9px;
  color: var(--text-3);
}
.sidebar-similar .sim-price {
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
/* Visual-match badge sits on top of the thumbnail. */
.sidebar-similar .sim-badge {
  position: absolute;
  top: 3px;
  left: 3px;
  padding: 1px 4px;
  font-size: 8px;
  line-height: 1;
  background: rgba(255, 255, 255, 0.88);
  border-radius: 2px;
  letter-spacing: 0;
}
.sidebar-similar .sim-badge--strong { color: #c08800; }
.sidebar-similar .sim-badge--mid    { color: #806020; }
.sidebar-similar .sim-badge--weak   { color: var(--text-3); }

/* Sold-out similar items: dim the thumbnail and stamp a compact badge,
   mirroring the main grid's .thumb--soldout / .soldout-badge treatment. */
.sidebar-similar .sim-card--soldout .sim-thumb img {
  opacity: 0.45;
  filter: grayscale(0.35);
}
.sidebar-similar .sim-card--soldout .sim-name,
.sidebar-similar .sim-card--soldout .sim-price { opacity: 0.55; }
.sidebar-similar .sim-soldout {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: rgba(0, 0, 0, 0.72);
  color: #fff;
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.12em;
  padding: 3px 7px;
  border-radius: 2px;
  z-index: 4;
  pointer-events: none;
  text-transform: uppercase;
  white-space: nowrap;
}


/* ---- Sidebar header price line ---- */
.sidebar-price {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 4px;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.sidebar-price .price-old {
  color: var(--text-3);
  text-decoration: line-through;
  font-size: 11px;
}
.sidebar-price .price-now--sale {
  color: var(--accent);
  font-weight: 700;
}
.sidebar-price .pct {
  background: var(--accent);
  color: #fff;
  font-size: 10px;
  padding: 2px 6px;
  letter-spacing: 0.04em;
}
.sidebar-price .price-orig {
  flex-basis: 100%;
  font-size: 10px;
  color: var(--text-3);
}

/* ---- Sparkline in sidebar header (compact) ---- */
/* Toast — brief confirmation shown after liking or adding to cart. One
   shared element; messages replace each other. */
#app-toast {
  position: fixed;
  bottom: 32px;
  left: 50%;
  z-index: 2000;
  padding: 9px 18px;
  background: var(--text);
  color: var(--bg);
  font-size: 12px;
  letter-spacing: 0.04em;
  border-radius: 4px;
  box-shadow: 0 8px 24px -6px rgba(0, 0, 0, 0.32);
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, 12px);
  transition: opacity 180ms ease, transform 180ms ease;
}
#app-toast.is-visible {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* Floating "search" button shown when the user drags-selects text inside the
   sidebar. Sits above the iframe stacking context so it stays visible while
   the proxied page renders below. */
#search-pill {
  position: fixed;
  z-index: 1000;
  padding: 6px 12px;
  font-family: inherit;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: lowercase;
  background: var(--text);
  color: var(--bg);
  border: none;
  border-radius: 4px;
  box-shadow: 0 6px 20px -6px rgba(0, 0, 0, 0.35);
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  transition: opacity 120ms;
}
#search-pill[hidden] { display: none; }
#search-pill:hover { opacity: 0.85; }

.sidebar-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin-top: 6px;
  font-size: 11px;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.sidebar-meta .meta-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
}
.sidebar-meta .meta-key {
  color: var(--text-3);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: lowercase;
}

.sidebar-spark {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 2px;
  color: var(--text-2);
}
.sidebar-spark svg { color: inherit; height: 22px; }
.sidebar-spark-meta {
  font-size: 10px;
  letter-spacing: 0.04em;
  color: var(--text-3);
}

/* ---- Gallery ---- */
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 36px var(--gap);
  padding: 32px var(--side);
}
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: transparent;
  cursor: pointer;
  transition: var(--transition);
}
.card:hover { transform: translateY(-2px); }
.card:hover .thumb { box-shadow: 0 6px 18px -8px rgba(0,0,0,0.18); }

.thumb {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  background: var(--surface-2);
  overflow: hidden;
  border-radius: var(--radius);
  transition: box-shadow var(--transition);
}

/* ---- Card info (below the image) ---- */
.card-info {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 4px 0;
  font-variant-numeric: tabular-nums;
}
.card-site {
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: lowercase;
  color: var(--text-3);
}
.card-name {
  font-size: 12px;
  line-height: 1.45;
  color: var(--text);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.card-price {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
  font-size: 12px;
  margin-top: 2px;
}
.card-price .price-old {
  color: var(--text-3);
  text-decoration: line-through;
  font-size: 11px;
}
.card-price .price-now {
  color: var(--text);
}
.card-price .price-now--sale {
  color: var(--accent);
  font-weight: 700;
}
.card-price .price-orig {
  flex-basis: 100%;
  font-size: 10px;
  color: var(--text-3);
}
.card-price .price-none {
  color: var(--text-3);
  font-size: 11px;
}
.thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 700ms cubic-bezier(.2,.6,.2,1);
}
.card:hover .thumb img { transform: scale(1.03); }
.thumb-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: var(--text-3);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: lowercase;
}

/* Hover overlay carries name + price + site */
.overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 16px;
  background: linear-gradient(180deg, rgba(0,0,0,0) 40%, rgba(0,0,0,0.6) 100%);
  color: #fff;
  opacity: 0;
  transition: opacity var(--transition);
  pointer-events: none;
}
.card:hover .overlay { opacity: 1; }
.overlay-top {
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: lowercase;
}
.overlay-bottom {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.overlay-name {
  font-size: 12px;
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.overlay-price {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.price-old {
  text-decoration: line-through;
  opacity: 0.6;
  font-size: 11px;
}
.price-now--sale { color: #ff8a78; font-weight: 700; }
.price-orig {
  opacity: 0.6;
  font-size: 10px;
}

.discount-badge {
  position: absolute;
  top: 10px;
  left: 10px;
  background: var(--accent);
  color: #fff;
  font-size: 10px;
  padding: 3px 7px;
  letter-spacing: 0.05em;
  font-variant-numeric: tabular-nums;
  z-index: 3;
}

/* SOLD OUT: centered badge on a dimmed thumbnail. The img keeps its
   transform-on-hover behaviour; we just lower its opacity via the parent
   modifier so the badge remains crisp on top. */
.thumb--soldout img { opacity: 0.45; filter: grayscale(0.35); }
.soldout-badge {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: rgba(0, 0, 0, 0.72);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  padding: 6px 14px;
  border-radius: 2px;
  z-index: 4;
  pointer-events: none;
  text-transform: uppercase;
}
/* Dim the info area of sold cards so the eye still parses them as "out". */
.card:has(.thumb--soldout) .card-name,
.card:has(.thumb--soldout) .card-price { opacity: 0.55; }

/* ---- Sticky compact filter summary ----
   Pinned under the topbar; only rendered visible when the main filter form
   has scrolled above the viewport (JS toggles .is-visible). --topbar-h is
   set at runtime to match the actual header height. */
.filter-summary {
  position: sticky;
  top: var(--topbar-h, 80px);
  z-index: 95;
  background: rgba(250, 249, 245, 0.94);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--line);
  /* Slide out of the way and skip pointer events so the topbar still works
     when the summary is "hidden" (it remains in the layout to keep the
     observer logic simple, but visually it's tucked behind the topbar). */
  transform: translateY(calc(-100% - 4px));
  opacity: 0;
  pointer-events: none;
  transition: transform 220ms cubic-bezier(.2,.6,.2,1), opacity 180ms ease;
}
[data-theme="dark"] .filter-summary { background: rgba(14, 14, 14, 0.9); }
.filter-summary.is-visible,
/* Server-rendered when a non-search facet (sites/brands/categories/sizes/
   price) is actively narrowing — kept separate from .is-visible so the
   scroll-driven IntersectionObserver can never toggle it back off. */
.filter-summary.force-visible {
  transform: translateY(0);
  opacity: 1;
  pointer-events: auto;
}
/* Manual collapse: hide the whole filter form and force the summary into
   the visible state. The summary's existing 220ms transform/opacity
   transition (above) handles the slide-in animation so it lands exactly
   like the scroll-induced state. */
html.filters-collapsed form.filters { display: none; }
html.filters-collapsed .filter-summary {
  transform: translateY(0);
  opacity: 1;
  pointer-events: auto;
}
.filter-summary-inner {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px var(--side);
  overflow-x: auto;
  white-space: nowrap;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: lowercase;
  color: var(--text-2);
}
.fs-chip {
  padding: 4px 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  font-size: 10px;
  flex: 0 0 auto;
}
.fs-empty { color: var(--text-3); font-style: italic; }
.fs-spacer { flex: 1 1 auto; min-width: 12px; }
.fs-count {
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
  flex: 0 0 auto;
}
.fs-edit {
  padding: 4px 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
  font-size: 10px;
  letter-spacing: 0.08em;
  color: var(--text-2);
  transition: var(--transition);
  flex: 0 0 auto;
}
.fs-edit:hover { background: var(--surface-2); color: var(--text); }

/* Grid toolbar: right-aligned sort + soldout toggle sitting just above the
   first product row. Always rendered so sort/soldout stay reachable in
   every view (main/favs/cart) without scrolling back to the filter form. */
.grid-toolbar {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 18px;
  /* Symmetric vertical padding so the gap above the toolbar (toolbar →
     boundary above) matches the gap below (toolbar → first product row).
     Pair with `.grid-toolbar + .grid { padding-top: 0 }` so the grid does
     not add its own top padding on top of the toolbar's bottom. */
  padding: 16px var(--side);
}
.grid-toolbar + .grid { padding-top: 0; }
.grid-toolbar .sort-select {
  /* Drop the left border the filter-row inherits from .search-row > * + *.
     Inside the grid toolbar the select is standalone, not part of a row. */
  border-left: 0;
  padding: 6px 28px 6px 10px;
}

.filter-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 4px 0;
  font-size: 11px;
  letter-spacing: 0.05em;
  text-transform: lowercase;
  color: var(--text-2);
  cursor: pointer;
  user-select: none;
}
.filter-toggle input { cursor: pointer; accent-color: var(--text); }

.recommendation-insights {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 11px var(--side);
  overflow-x: auto;
  border-bottom: 1px solid var(--line);
  color: var(--text-3);
  font-size: 10px;
  letter-spacing: .04em;
  white-space: nowrap;
}
.recommendation-insights .insights-title { color: var(--text); font-weight: 700; }
.recommendation-insights strong { color: var(--text-2); font-weight: 700; }

.recommendation-reasons {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 7px;
}
.recommendation-reasons span {
  padding: 3px 6px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-2);
  font-size: 8px;
  line-height: 1;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

/* ---- Pagination ---- */
.pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 4px;
  padding: 32px var(--side) 56px;
  border-top: 1px solid var(--line);
  margin-top: 24px;
}
.pagination .btn-ghost {
  padding: 12px 20px;
}
.page-info {
  margin: 0 18px;
  color: var(--text-3);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.06em;
  text-transform: lowercase;
}

/* ---- Empty / Footer ---- */
.empty {
  text-align: center;
  padding: 120px 24px;
  color: var(--text-3);
  font-size: 12px;
  letter-spacing: 0.04em;
}
.footer {
  text-align: center;
  padding: 32px 24px;
  color: var(--text-3);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: lowercase;
  border-top: 1px solid var(--line);
}

/* ---- Sidebar (in-page browser preview) ---- */
.sidebar-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(20, 20, 18, 0);
  z-index: 199;
  pointer-events: none;
  transition: background var(--transition);
}
.sidebar-backdrop.is-open {
  background: rgba(20, 20, 18, 0.18);
  pointer-events: auto;
}

.sidebar {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 58vw;
  min-width: 480px;
  max-width: 900px;
  background: var(--surface);
  border-left: 1px solid var(--line);
  box-shadow: -16px 0 48px -8px rgba(0, 0, 0, 0.18);
  transform: translateX(100%);
  transition: transform 320ms cubic-bezier(.2,.7,.2,1);
  z-index: 200;
  display: flex;
  flex-direction: column;
  /* The aside itself scrolls so the similar-products grid below the detail
     panel is reachable without compressing the iframe preview. */
  overflow-y: auto;
  /* `none` stops three failure modes:
     1. Scroll chaining — wheel/touchpad scrolls reaching the sidebar's top
        or bottom no longer bleed into the main grid behind it.
     2. Rubber-band overscroll — the sidebar's bottom/top no longer
        rubber-bands open into a blank area on macOS.
     `contain` only stops chaining — must use `none` to also kill the
     own-element rubber-band. */
  overscroll-behavior: none;
}
[data-theme="dark"] .sidebar {
  box-shadow: -16px 0 48px -8px rgba(0, 0, 0, 0.6);
}
.sidebar.is-open {
  transform: translateX(0);
}

.sidebar-toolbar {
  display: flex;
  justify-content: flex-end;
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  flex-shrink: 0;
  /* Stays in view while the aside scrolls down to the similar-products
     grid so the close button is always reachable. */
  position: sticky;
  top: 0;
  z-index: 10;
}

.sidebar-detail {
  display: flex;
  align-items: center;            /* vertically center info + actions */
  gap: 16px;
  padding: 14px 18px;
  border-top: 1px solid var(--line);
  background: var(--surface);
  flex-shrink: 0;
}
.sidebar-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  line-height: 1.3;
}
.sidebar-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
.sidebar-actions .btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 36px;
  padding: 4px 18px 0;          /* nudge text down — Korean glyphs sit high */
  font-size: 12px;
  letter-spacing: 0.04em;
  text-align: center;
  line-height: 1;
}
.sidebar-site {
  font-size: 10px;
  color: var(--text-3);
  letter-spacing: 0.1em;
  text-transform: lowercase;
}
.sidebar-name {
  font-size: 12px;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.icon-btn {
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--text-2);
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
  /* Heart/✕/↗ glyph metrics sit slightly above the geometric center
     of the box; nudge content down to look optically centered. */
  padding-top: 2px;
  transition: var(--transition);
  flex-shrink: 0;
  text-decoration: none;
}
.icon-btn:hover {
  color: var(--text);
  border-color: var(--text-2);
}

.sidebar-frame-wrap {
  position: relative;
  /* Lock to the original "remaining viewport" size so the iframe doesn't
     shrink when the similar-products grid is rendered below the detail
     panel. The aside scrolls instead. 200px ≈ toolbar + detail height. */
  flex: 0 0 calc(100vh - 200px);
  background: var(--surface-2);
  overflow: hidden;
}
.sidebar-iframe {
  width: 100%;
  height: 100%;
  border: 0;
  background: var(--surface);
  /* Hide-then-fade-in keeps the previous product's iframe contents from
     bleeding through the brief moment between src reassignment and the
     new page's first paint. */
  opacity: 1;
  transition: opacity 180ms ease-out;
}
.sidebar-iframe.loading {
  opacity: 0;
}
.sidebar-loading {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-3);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: lowercase;
  background: var(--surface-2);
  pointer-events: none;
  opacity: 0;
  /* Fade-out is gentle, but show is instant — otherwise the half-faded
     overlay reveals the prior iframe's render during a product switch. */
  transition: opacity 220ms ease-out;
}
.sidebar-loading.is-visible {
  opacity: 1;
  transition: none;
}

.sidebar-fallback {
  position: absolute;
  inset: 0;
  display: none;
  flex-direction: column;
  align-items: stretch;
  background: var(--surface);
  z-index: 2;
  overflow-y: auto;
}
.sidebar-fallback.is-visible { display: flex; }
.fb-image {
  width: 100%;
  flex: 1;
  background: var(--surface-2);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.fb-image img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
.fb-image .fb-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: var(--text-3);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: lowercase;
}
.fb-note {
  font-size: 11px;
  color: var(--text-2);
  line-height: 1.7;
  padding: 14px 18px;
  background: var(--surface);
  border-top: 1px solid var(--line);
  text-align: center;
}

.sidebar-hint {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 8px 14px;
  background: linear-gradient(180deg, rgba(0,0,0,0) 0%, var(--bg) 100%);
  font-size: 10px;
  color: var(--text-3);
  letter-spacing: 0.06em;
  text-transform: lowercase;
  display: flex;
  justify-content: space-between;
  align-items: center;
  pointer-events: none;
}
[data-theme="dark"] .sidebar-hint {
  background: linear-gradient(180deg, rgba(0,0,0,0) 0%, var(--surface) 100%);
}
.sidebar-hint a {
  pointer-events: auto;
  color: var(--text-2);
  border-bottom: 1px dotted var(--text-3);
  padding-bottom: 1px;
}
.sidebar-hint a:hover { color: var(--text); }

/* The sidebar is a pure fixed overlay — it never reflows the grid behind it.
   Page content stays exactly where it was; the sidebar slides in on top. */

/* ---- Responsive ---- */
@media (max-width: 1100px) {
  :root { --side: 32px; --gap: 14px; }
}
@media (max-width: 900px) {
  :root { --side: 24px; --gap: 12px; }
  .grid { grid-template-columns: repeat(2, 1fr); }
  .brand .meta { display: none; }
  .modal { grid-template-columns: 1fr; max-height: calc(100vh - 32px); }
  .modal-body { padding: 24px; }
}
@media (max-width: 540px) {
  :root { --side: 14px; --gap: 8px; }

  .topbar-inner {
    grid-template-columns: 1fr;
    gap: 8px;
    padding: 12px var(--side) 0;
  }
  .brand { min-height: 30px; padding-right: 40px; align-items: center; }
  .logo-mark { display: none; }
  .topbar-nav {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    justify-self: stretch;
    gap: 0;
    border-top: 1px solid var(--line);
  }
  .topbar-nav a {
    min-width: 0;
    padding: 9px 3px 10px;
    text-align: center;
    font-size: 9px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .logout-form {
    display: block;
    border-left: 1px solid var(--line);
    border-top: 1px solid var(--line);
  }
  .logout-form button { width: 100%; padding: 9px 3px 10px; font-size: 9px; }
  .nav-label--desktop { display: none; }
  .nav-label--mobile { display: inline; }
  .topbar-nav a + a { border-left: 1px solid var(--line); }
  .topbar-nav a:nth-child(n + 4) { border-top: 1px solid var(--line); }
  .topbar-nav a:nth-child(4) { border-left: 0; }
  .theme-toggle {
    position: absolute;
    top: 12px;
    right: var(--side);
    width: 30px;
    height: 30px;
  }

  .search-row { flex-wrap: wrap; padding: 0 var(--side); }
  .search-row > * + * { border-left: 0; }
  .search-input {
    flex: 1 0 100%;
    min-width: 0;
    padding: 14px 10px;
    border-bottom: 1px solid var(--line);
  }
  .search-row .btn-primary,
  .search-row .btn-ghost {
    display: block;
    flex: 1 1 50%;
    padding: 12px;
    text-align: center;
  }
  .search-row .btn-ghost { border-left: 1px solid var(--line); }

  .presets {
    align-items: flex-start;
    flex-direction: column;
    gap: 8px;
    padding-top: 12px;
  }
  .presets-list { width: 100%; }
  .preset-save-form { max-width: 100%; }
  .preset-save-form[data-state="active"] .preset-save-input {
    width: min(150px, 42vw);
  }

  .site-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 12px; }
  .site-checkbox { min-width: 0; }
  .site-checkbox > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .site-checkbox .only-link { opacity: 1; }
  .price-range {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    padding: 14px 0 20px;
  }
  .price-range input[type="number"] { width: 100%; min-width: 0; }
  .price-range-apply { grid-column: 1 / -1; border: 1px solid var(--line); }

  .grid-toolbar {
    justify-content: space-between;
    gap: 10px;
    padding: 12px var(--side);
  }
  .grid-toolbar .sort-select { min-width: 0; max-width: 48vw; }
  .grid { gap: 24px var(--gap); padding: 16px var(--side) 24px; }
  .grid-toolbar + .grid { padding-top: 0; }
  .card-info { padding: 9px 2px 0; }
  .card-name { font-size: 11px; }
  .card-price { gap: 5px; font-size: 11px; }
  .card .fav-btn,
  .card .cart-btn,
  .card .dislike-btn { opacity: 1; }

  .pagination {
    gap: 2px;
    padding: 24px var(--side) 40px;
  }
  .pagination .btn-ghost { padding: 10px 12px; }
  .page-info { margin: 0 6px; }

  .sidebar {
    width: 100%;
    min-width: 0;
    max-width: none;
    border-left: 0;
  }
  .sidebar-toolbar {
    order: 0;
    height: auto;
    padding: 8px 12px;
    border-bottom: 1px solid var(--line);
    background: var(--surface);
    pointer-events: auto;
  }
  .sidebar-toolbar .icon-btn {
    background: var(--surface);
  }
  .sidebar-detail {
    order: 2;
    align-items: stretch;
    flex-direction: column;
    gap: 12px;
    padding: 18px 58px 16px 18px;
    border-top: 0;
    border-bottom: 1px solid var(--line);
  }
  .sidebar-name {
    white-space: normal;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }
  .sidebar-actions { width: 100%; }
  .sidebar-actions .btn-primary { flex: 1; }
  .sidebar-frame-wrap {
    order: 1;
    flex-basis: min(56dvh, 520px);
    min-height: 360px;
  }
  .sidebar-similar { order: 3; }
  .sidebar-similar .sim-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .modal-backdrop { padding: 0; }
  .modal { max-height: 100vh; }
}

/* Touch devices have no reliable hover state. Keep primary card actions
   discoverable even on larger touch screens such as tablets. */
@media (hover: none), (pointer: coarse) {
  .card .fav-btn,
  .card .cart-btn,
  .card .dislike-btn,
  .site-checkbox .only-link { opacity: 1; }
  .card:hover { transform: none; }
  .card:hover .thumb img { transform: none; }
}

@media (max-width: 360px) {
  .topbar-nav .nav-badge { display: none; }
}
