/* ---------------- Marketplace: seller "ของฉัน" page + upload wizard + buyer browse ----------------
   marketplace-plan.md §4/§8 steps 2-3. Reuses the app's existing tokens (--ink/--muted/--line/
   --card/--radius from styles/main.css) and existing component classes (.btn/.btn-black/
   .btn-outline/.admin-input/.content-title/.setup-banner) rather than redefining them — only
   classes genuinely new to the seller page/upload wizard live here. Also reuses .fullscreen-
   overlay/.ep-bar/.ep-title/.ep-body from main.css/exam.css for the wizard's overlay shell (see
   index.html #marketplace-upload-overlay), same as pricing.css/profile.css already do. */

/* .fullscreen-overlay itself has no background (main.css) — every overlay sets its own on the
   outer #<id>-overlay element (see #pricing-overlay/#profile-overlay/#legal-overlay). Missing
   this is what let the seller-dashboard panel show through behind the wizard. */
#marketplace-upload-overlay{ background:var(--paper); display:flex; flex-direction:column; }
#marketplace-upload-panel{ flex:1; display:flex; flex-direction:column; min-height:0; overflow-y:auto; -webkit-overflow-scrolling:touch; scroll-behavior:smooth; }

/* ---- Seller "ของฉัน" page (js/seller-dashboard.js) ---- */
.mkt-seller-wrap{ padding:4px 20px 100px; max-width:640px; margin:0 auto; }
.mkt-seller-header{ display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; margin:18px 0 16px; }
.mkt-seller-title{ font-size:var(--fs-xl); font-weight:800; }
.mkt-seller-sub{ font-size:var(--fs-sm); color:var(--muted); margin-top:2px; }

.mkt-wallet-card{ background:var(--card); border:1px solid var(--line); border-radius:var(--radius); padding:16px 18px; }
.mkt-wallet-row{ display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; }
.mkt-wallet-label{ font-size:var(--fs-sm); color:var(--muted); font-weight:600; display:flex; align-items:center; }
.mkt-wallet-amount{ font-size:var(--fs-2xl); font-weight:800; margin-top:2px; }
.mkt-wallet-note{ font-size:var(--fs-xs); color:var(--muted); line-height:1.6; margin-top:10px; }
.mkt-withdraw-mock-row{ display:flex; gap:8px; margin-top:12px; flex-wrap:wrap; }
.mkt-withdraw-mock-row .admin-input{ flex:1; min-width:140px; }

.mkt-empty-state{ font-size:var(--fs-sm); color:var(--muted); background:var(--card); border:1px dashed var(--line); border-radius:14px; padding:20px; text-align:center; animation:motionFadeUp 320ms cubic-bezier(.2,.8,.3,1) both; }
/* Round 11: plain static "กำลังโหลด…" text gave zero sense of progress. A soft opacity pulse
   (not a spinner — nothing here spins) is enough to read as "working" without implying a
   specific % complete that isn't actually known. */
.mkt-loading{ font-size:var(--fs-sm); color:var(--muted); padding:14px 0; animation:mktLoadingPulse 1.3s ease-in-out infinite; }
@keyframes mktLoadingPulse{ 0%,100%{ opacity:0.55; } 50%{ opacity:1; } }
@media (prefers-reduced-motion:reduce){
  .mkt-empty-state{ animation:none; }
  .mkt-loading{ animation:none; }
}

/* Round 11: #mkt-listings-list's innerHTML is fully replaced on every render (seller-dashboard.js
   renderInto()), same as #exam-results in exam.css — so a plain nth-child stagger here safely
   replays on every fresh render without needing any JS change, exactly like
   .exam-level-section's pattern. Capped at 6 explicit delays + one catch-all for the rest, same
   as the [data-motion="fade-up"] primitive in main.css, so a long list doesn't leave the last
   card waiting a silly-long time to appear. */
.mkt-listings-list{ display:flex; flex-direction:column; gap:12px; }
.mkt-listing-card{ background:var(--card); border:1px solid var(--line); border-radius:16px; padding:14px; transition:box-shadow 180ms ease; animation:motionFadeUp 340ms cubic-bezier(.2,.8,.3,1) both; }
.mkt-listings-list .mkt-listing-card:nth-child(1){ animation-delay:0ms; }
.mkt-listings-list .mkt-listing-card:nth-child(2){ animation-delay:35ms; }
.mkt-listings-list .mkt-listing-card:nth-child(3){ animation-delay:70ms; }
.mkt-listings-list .mkt-listing-card:nth-child(4){ animation-delay:105ms; }
.mkt-listings-list .mkt-listing-card:nth-child(5){ animation-delay:140ms; }
.mkt-listings-list .mkt-listing-card:nth-child(n+6){ animation-delay:175ms; }
@media (hover:hover){ .mkt-listing-card:hover{ box-shadow:0 8px 20px rgba(18,18,18,0.08); } }
@media (prefers-reduced-motion:reduce){ .mkt-listing-card{ animation:none; } }
.mkt-listing-top{ display:flex; gap:12px; }
.mkt-listing-cover{ flex:none; width:52px; height:68px; border-radius:8px; background:rgba(18,18,18,0.06) center/cover no-repeat; display:flex; align-items:center; justify-content:center; color:var(--muted); }
.mkt-listing-info{ flex:1; min-width:0; }
.mkt-listing-title-row{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.mkt-listing-title{ font-weight:700; font-size:var(--fs-base); }
.mkt-bundle-badge{ font-size:var(--fs-2xs); font-weight:700; background:var(--blue); color:var(--black); border-radius:999px; padding:2px 8px; white-space:nowrap; }
.mkt-listing-meta{ font-size:var(--fs-xs); color:var(--muted); margin-top:2px; }
.mkt-status-badge{ display:inline-block; margin-top:6px; font-size:var(--fs-xs); font-weight:700; padding:3px 9px; border-radius:999px; }
.mkt-status-pending{ background:rgba(var(--warning-rgb),0.25); color:var(--warning); }
.mkt-status-live{ background:rgba(var(--info-rgb),0.25); color:var(--info); }
.mkt-status-rejected{ background:rgba(var(--danger-rgb),0.12); color:var(--danger); }
.mkt-status-suspended{ background:rgba(18,18,18,0.08); color:var(--muted); }
.mkt-rejection-reason{ font-size:var(--fs-xs); color:var(--danger); margin-top:6px; line-height:1.5; }

.mkt-listing-actions{ display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap; margin-top:12px; padding-top:12px; border-top:1px solid var(--line); }
.mkt-price-edit{ display:flex; align-items:center; gap:6px; font-size:var(--fs-sm); color:var(--muted); flex-wrap:wrap; }
.mkt-price-input{ width:90px; padding:8px 10px; }
.mkt-listing-buttons{ display:flex; gap:8px; flex-wrap:wrap; }

.mkt-discount-row{ display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap; margin-top:8px; }
.mkt-discount-status{ font-size:var(--fs-xs); font-weight:700; display:inline-flex; align-items:center; gap:4px; padding:3px 9px; border-radius:999px; }
/* Round 11: an active discount is a time-limited state the seller specifically wants attention
   on ("this is currently costing me margin / currently driving sales") — a slow, low-amplitude
   glow on just the badge (not the whole card, which would be distracting in a scrolling list)
   signals "live/ongoing" the way a recording indicator does, without reading as an error or
   alert. Deliberately NOT used on -upcoming/-expired, which are informational, not urgent. */
.mkt-discount-active{ background:rgba(var(--info-rgb),0.25); color:var(--info); animation:mktDiscountGlow 2.2s ease-in-out infinite; }
@keyframes mktDiscountGlow{ 0%,100%{ box-shadow:0 0 0 0 rgba(var(--info-rgb),0.35); } 50%{ box-shadow:0 0 0 5px rgba(var(--info-rgb),0); } }
@media (prefers-reduced-motion:reduce){ .mkt-discount-active{ animation:none; } }
.mkt-discount-upcoming{ background:rgba(var(--warning-rgb),0.25); color:var(--warning); }
.mkt-discount-expired{ background:rgba(18,18,18,0.08); color:var(--muted); }
.mkt-discount-form{ margin-top:10px; background:rgba(18,18,18,0.03); border:1px solid var(--line); border-radius:12px; padding:12px 14px; }
.mkt-discount-form-hint{ font-size:var(--fs-xs); color:var(--muted); line-height:1.5; margin-bottom:10px; }
.mkt-discount-form-row{ display:flex; align-items:center; gap:8px; font-size:var(--fs-sm); margin-bottom:8px; flex-wrap:wrap; }
.mkt-discount-form-row .admin-input{ padding:7px 10px; }
.mkt-discount-price-input{ width:90px; }
.mkt-discount-start-input, .mkt-discount-end-input{ flex:1; min-width:180px; }
.mkt-discount-form-buttons{ display:flex; gap:8px; flex-wrap:wrap; margin-top:4px; }

.mkt-listing-files{ margin-top:12px; padding-top:12px; border-top:1px dashed var(--line); display:flex; flex-direction:column; gap:8px; }
.mkt-bundle-file-row{ display:flex; align-items:center; gap:8px; font-size:var(--fs-sm); }
.mkt-bundle-file-name{ flex:1; min-width:0; }
.mkt-sub-price-input{ width:90px; padding:6px 8px; font-size:var(--fs-sm); }

.mkt-sales-list{ display:flex; flex-direction:column; gap:8px; }
.mkt-sale-row{ display:flex; align-items:center; justify-content:space-between; background:var(--card); border:1px solid var(--line); border-radius:12px; padding:10px 14px; font-size:var(--fs-sm); transition:background 150ms ease; }
@media (hover:hover){ .mkt-sale-row:hover{ background:rgba(18,18,18,0.035); } }
.mkt-sale-amounts{ display:flex; flex-direction:column; align-items:flex-end; gap:2px; }
.mkt-sale-net{ font-weight:700; }

/* ---- Upload wizard (js/marketplace-upload.js) ---- */
.mkt-wizard-progress{ display:flex; justify-content:space-between; gap:4px; margin-bottom:22px; }
/* Round 11: opacity used to flip 0.4→1 with no transition, and the dot had no feedback at all
   when a step completed. Now both the fade and a "done" pop are animated — the pop reuses the
   shared motionPop keyframe from main.css so it's the exact same feel as the bookmark-heart
   toggle above, keeping the two most common "something just got confirmed" moments consistent. */
.mkt-wizard-step{ flex:1; display:flex; flex-direction:column; align-items:center; gap:6px; text-align:center; opacity:0.4; transition:opacity 220ms ease; }
.mkt-wizard-step.active, .mkt-wizard-step.done{ opacity:1; }
.mkt-wizard-step-dot{ width:26px; height:26px; border-radius:50%; background:rgba(18,18,18,0.08); display:flex; align-items:center; justify-content:center; font-size:var(--fs-xs); font-weight:700; transition:background 220ms ease, color 220ms ease; }
.mkt-wizard-step.active .mkt-wizard-step-dot{ background:var(--black); color:#fff; }
.mkt-wizard-step.done .mkt-wizard-step-dot{ background:var(--yellow); animation:motionPop 320ms var(--ease-pop); }
.mkt-wizard-step-label{ font-size:var(--fs-2xs); color:var(--muted); white-space:nowrap; }
@media (prefers-reduced-motion:reduce){ .mkt-wizard-step.done .mkt-wizard-step-dot{ animation:none; } }

.mkt-wizard-nav{ display:flex; justify-content:space-between; align-items:center; margin-top:24px; }

.mkt-mode-choice{ display:flex; flex-direction:column; gap:12px; }
/* Round 11: the two mode cards (single file / bundle) are the very first choice a seller makes
   in the wizard — worth the same hover-lift + border-color-ease treatment as .course-card gets,
   so picking one feels like a deliberate selection rather than a flat radio toggle. */
.mkt-mode-btn{ text-align:left; border:2px solid var(--line); background:var(--card); border-radius:16px; padding:18px; transition:border-color 180ms ease, transform 180ms var(--ease-pop), box-shadow 180ms ease; }
.mkt-mode-btn.selected{ border-color:var(--black); }
.mkt-mode-btn:active{ transform:scale(0.98); }
@media (hover:hover){ .mkt-mode-btn:not(.selected):hover{ border-color:rgba(18,18,18,0.35); box-shadow:0 6px 16px rgba(18,18,18,0.06); } }
.mkt-mode-btn-title{ font-weight:800; font-size:var(--fs-md); display:flex; align-items:center; }
.mkt-mode-btn-desc{ font-size:var(--fs-sm); color:var(--muted); margin-top:4px; }

/* Round 11: dropzone had no reaction to dragover at all — the label's own copy promises
   "ลาก-วางไฟล์ที่นี่" (drag-drop here) but no drag event listeners existed to back it up. Added
   the actual dragenter/dragover/dragleave/drop wiring in js/marketplace-upload.js (toggles this
   .dragover class + calls the same handleFilesPicked() the file-input change event already
   uses), and this rule gives that state a visible border/background/scale response instead of
   the drop target looking inert while a file is being dragged over it. */
.mkt-dropzone{ display:flex; flex-direction:column; align-items:center; gap:6px; border:2px dashed var(--line); border-radius:16px; padding:26px 16px; text-align:center; cursor:pointer; font-size:var(--fs-base); font-weight:600; transition:border-color 180ms ease, background 180ms ease, transform 180ms var(--ease-pop); }
.mkt-dropzone.dragover{ border-color:var(--black); background:rgba(18,18,18,0.04); transform:scale(1.01); }
.mkt-dropzone-sub{ font-size:var(--fs-xs); color:var(--muted); font-weight:400; }
.mkt-file-list{ display:flex; flex-direction:column; gap:10px; margin-top:14px; }
.mkt-file-row{ background:var(--card); border:1px solid var(--line); border-radius:12px; padding:10px 12px; display:flex; flex-direction:column; gap:6px; animation:motionFadeUp 260ms cubic-bezier(.2,.8,.3,1) both; }
.mkt-file-row-main{ display:flex; justify-content:space-between; gap:10px; font-size:var(--fs-sm); }
.mkt-file-name{ font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.mkt-file-status{ color:var(--muted); white-space:nowrap; }
.mkt-file-error{ color:var(--danger); }
.mkt-subtitle-input{ padding:8px 10px; font-size:var(--fs-sm); }
.mkt-file-row-actions{ display:flex; gap:8px; justify-content:flex-end; }
.mkt-file-move, .mkt-file-remove{ border:1px solid var(--line); background:transparent; border-radius:8px; padding:4px 9px; font-size:var(--fs-xs); transition:background 150ms ease, transform 120ms ease; }
.mkt-file-move:active, .mkt-file-remove:active{ transform:scale(0.92); background:rgba(18,18,18,0.06); }
@media (prefers-reduced-motion:reduce){ .mkt-file-row{ animation:none; } }

.mkt-field{ margin-bottom:18px; }
.mkt-field label{ display:block; font-size:var(--fs-sm); font-weight:700; color:var(--muted); margin-bottom:6px; }
.mkt-price-hint{ font-size:var(--fs-xs); color:var(--muted); margin-top:6px; }
.mkt-bundle-price-list{ display:flex; flex-direction:column; gap:8px; }
.mkt-bundle-price-row{ display:flex; align-items:center; justify-content:space-between; gap:10px; font-size:var(--fs-sm); }
.mkt-bundle-price-row .mkt-file-price-input{ width:100px; padding:8px 10px; }

.mkt-preview-canvas-wrap{ display:flex; gap:10px; overflow-x:auto; margin-top:12px; padding-bottom:4px; }
.mkt-preview-page{ position:relative; flex:none; border-radius:8px; overflow:hidden; border:1px solid var(--line); }
.mkt-preview-page canvas{ display:block; }
.mkt-preview-page-img{ display:block; max-height:260px; }
.mkt-cover-preview-img{ margin-top:10px; width:120px; aspect-ratio:3/4; object-fit:cover; border-radius:10px; border:1px solid var(--line); }

.mkt-review-card{ display:flex; gap:14px; background:var(--card); border:1px solid var(--line); border-radius:16px; padding:14px; margin-bottom:14px; animation:motionFadeUp 320ms cubic-bezier(.2,.8,.3,1) both; }
@media (prefers-reduced-motion:reduce){ .mkt-review-card{ animation:none; } }
.mkt-review-price{ font-size:var(--fs-md); font-weight:800; margin-top:6px; }
.mkt-review-desc{ font-size:var(--fs-sm); color:var(--muted); line-height:1.6; margin-bottom:14px; white-space:pre-wrap; }
.mkt-review-files{ display:flex; flex-direction:column; gap:6px; margin-bottom:18px; }
.mkt-review-file-row{ font-size:var(--fs-sm); display:flex; align-items:center; }
.mkt-checkbox-row{ display:flex; gap:10px; align-items:flex-start; font-size:var(--fs-sm); line-height:1.6; color:var(--ink); background:rgba(18,18,18,0.04); border-radius:12px; padding:12px 14px; }
.mkt-checkbox-row input{ margin-top:3px; flex:none; }

/* ---- Buyer browse + listing detail (js/marketplace.js) — marketplace-plan.md §8 step 3.
   Reuses .course-card/.exam-grid/.chip-row/.tag-row/.content-title (components.css/exam.css)
   for the grid + filters, and .mkt-preview-canvas-wrap/.mkt-preview-page/.ep-bar/.ep-title/
   .ep-body (above / main.css) for the detail overlay's preview — only classes genuinely new to
   this step live below. */
#marketplace-detail-overlay{ background:var(--paper); display:flex; flex-direction:column; }
#marketplace-detail-panel{ flex:1; display:flex; flex-direction:column; min-height:0; overflow-y:auto; -webkit-overflow-scrolling:touch; scroll-behavior:smooth; }
/* Round 34 — cart overlay, same shell as the detail overlay above. */
#marketplace-cart-overlay{ background:var(--paper); display:flex; flex-direction:column; }
#marketplace-cart-panel{ flex:1; display:flex; flex-direction:column; min-height:0; overflow-y:auto; -webkit-overflow-scrolling:touch; scroll-behavior:smooth; }

.mkt-market-card{ padding:12px; position:relative; }
/* Round 11: #mkt-market-grid is fully replaced on every renderMarketGrid() call (js/
   marketplace.js), same re-render-safe pattern as #mkt-listings-list above, so a nth-child
   stagger here is safe to replay on every filter-chip change too — which doubles as visible
   confirmation that the filter actually did something, not just a first-load nicety. Grid is
   2 columns (components.css .grid), so the delay step is halved per row rather than per item. */
#mkt-market-grid.grid .mkt-market-card{ animation:motionFadeUp 320ms cubic-bezier(.2,.8,.3,1) both; }
#mkt-market-grid.grid .mkt-market-card:nth-child(1),
#mkt-market-grid.grid .mkt-market-card:nth-child(2){ animation-delay:0ms; }
#mkt-market-grid.grid .mkt-market-card:nth-child(3),
#mkt-market-grid.grid .mkt-market-card:nth-child(4){ animation-delay:35ms; }
#mkt-market-grid.grid .mkt-market-card:nth-child(5),
#mkt-market-grid.grid .mkt-market-card:nth-child(6){ animation-delay:70ms; }
#mkt-market-grid.grid .mkt-market-card:nth-child(n+7){ animation-delay:105ms; }
@media (prefers-reduced-motion:reduce){ #mkt-market-grid.grid .mkt-market-card{ animation:none; } }
/* Round 11: `overflow:hidden` added so the cover-zoom-on-hover below doesn't spill a sliver of
   the enlarged image past the card's own rounded corners. */
.mkt-market-cover{ width:100%; aspect-ratio:3/4; border-radius:12px; background:rgba(18,18,18,0.06) center/cover no-repeat; display:flex; align-items:center; justify-content:center; color:var(--muted); margin-bottom:2px; overflow:hidden; transition:transform 260ms var(--ease-pop); }
@media (hover:hover){ .mkt-market-card:hover .mkt-market-cover{ transform:scale(1.045); } }
.mkt-market-seller{ font-size:var(--fs-2xs); color:var(--muted); display:flex; align-items:center; gap:4px; margin:2px 0 4px; }
.mkt-market-price{ font-size:var(--fs-md); font-weight:800; }
.mkt-price-strike{ font-size:var(--fs-xs); font-weight:600; color:var(--muted); text-decoration:line-through; margin-right:6px; }

/* Round 34 — "บันทึก/ถูกใจ" (wishlist heart) on the browse card, same circular icon-over-image
   treatment as most shopping apps use so it reads as tappable without competing with the cover
   image underneath it. */
.mkt-market-card .bookmark-btn{
  position:absolute; top:20px; right:20px; width:30px; height:30px; border-radius:999px;
  background:rgba(247,245,239,0.9); color:var(--muted); align-items:center; justify-content:center;
  box-shadow:0 1px 4px rgba(18,18,18,0.15);
}
.mkt-market-card .bookmark-btn .ic{ margin-right:0; }
.mkt-market-card .bookmark-btn.active{ color:var(--coral); }

.mkt-detail-cover{ width:120px; aspect-ratio:3/4; border-radius:12px; background:rgba(18,18,18,0.06) center/cover no-repeat; display:flex; align-items:center; justify-content:center; color:var(--muted); margin-bottom:12px; }
.mkt-detail-title-row{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.mkt-detail-title{ font-size:var(--fs-lg); font-weight:800; }
.mkt-detail-seller{ font-size:var(--fs-xs); color:var(--muted); display:flex; align-items:center; gap:5px; margin-top:4px; }

/* ---- Detail hero (cover + info side by side) + two-column body below — restyle to a
   book-detail-page layout: big cover on the left, title/seller/tagline/actions on the right,
   then a "รายละเอียด" (description/สารบัญ) column next to a compact "รายละเอียดไฟล์" side column.
   Stacks to one column under 720px since the overlay is used on phones too. ---- */
.mkt-detail-hero{ display:flex; gap:22px; align-items:flex-start; animation:motionFadeUp 360ms cubic-bezier(.2,.8,.3,1) both; }
@media (prefers-reduced-motion:reduce){ .mkt-detail-hero{ animation:none; } }
.mkt-detail-cover-lg{ flex:none; width:180px; aspect-ratio:3/4; border-radius:16px; background:rgba(18,18,18,0.06) center/cover no-repeat; display:flex; align-items:center; justify-content:center; color:var(--muted); box-shadow:0 10px 24px rgba(18,18,18,0.12); }
.mkt-detail-hero-info{ flex:1; min-width:0; padding-top:4px; }
.mkt-detail-tagline{ font-size:var(--fs-sm); color:var(--muted); font-style:italic; line-height:1.6; margin-top:10px; }
.mkt-detail-actions-row{ display:flex; align-items:center; gap:10px; margin-top:18px; flex-wrap:wrap; }
.mkt-detail-buy-pill{ width:auto; padding:12px 22px; border-radius:999px; font-size:var(--fs-base); }
/* Round 11: only had a background flip on :active with no transition timing at all — snapped
   instantly. Added an ease on background plus a scale-down on tap so the preview/share circular
   buttons in the detail hero feel as responsive as the primary buy button next to them. */
.mkt-icon-btn{ flex:none; width:40px; height:40px; border-radius:50%; border:1px solid var(--line); background:var(--card); display:flex; align-items:center; justify-content:center; color:var(--ink); transition:background 150ms ease, transform 120ms ease; }
.mkt-icon-btn:active{ background:rgba(18,18,18,0.06); transform:scale(0.9); }
/* Round 34 — cart item-count badge on the header's cart button. */
.mkt-cart-badge{
  position:absolute; top:-4px; right:-4px; min-width:18px; height:18px; padding:0 4px;
  border-radius:999px; background:var(--coral); color:#fff; font-size:10px; font-weight:700;
  display:flex; align-items:center; justify-content:center; line-height:1;
}

.mkt-detail-grid{ display:grid; grid-template-columns:1fr 220px; gap:28px; margin-top:32px; padding-top:24px; border-top:1px solid var(--line); }
.mkt-detail-col-side{ display:flex; flex-direction:column; gap:16px; }
.mkt-detail-side-block{ padding-bottom:14px; border-bottom:1px solid var(--line); }
.mkt-detail-side-block:last-child{ border-bottom:none; padding-bottom:0; }
.mkt-detail-side-label{ font-size:var(--fs-2xs); font-weight:700; color:var(--muted); text-transform:uppercase; letter-spacing:0.03em; margin-bottom:6px; }
.mkt-detail-side-value{ font-size:var(--fs-sm); line-height:1.6; }
.mkt-detail-side-price{ font-size:var(--fs-lg); font-weight:800; }

@media (max-width:720px){
  .mkt-detail-hero{ flex-direction:column; align-items:center; text-align:center; }
  .mkt-detail-cover-lg{ width:140px; }
  .mkt-detail-actions-row{ justify-content:center; }
  .mkt-detail-tagline{ text-align:left; }
  .mkt-detail-grid{ grid-template-columns:1fr; }
}
.mkt-detail-topics{ font-size:var(--fs-sm); color:var(--muted); margin-top:10px; display:flex; align-items:flex-start; gap:5px; line-height:1.6; }

.mkt-toc-list{ display:flex; flex-direction:column; gap:8px; margin-bottom:16px; }
.mkt-toc-row{ display:flex; align-items:center; justify-content:space-between; gap:10px; background:var(--card); border:1px solid var(--line); border-radius:12px; padding:10px 14px; font-size:var(--fs-sm); transition:background 150ms ease; }
@media (hover:hover){ .mkt-toc-row:hover{ background:rgba(18,18,18,0.045); } }
.mkt-toc-name{ flex:1; min-width:0; }
.mkt-toc-nosplit{ color:var(--muted); font-size:var(--fs-xs); white-space:nowrap; }
