/*
 * LimitedHub - Cart / order summary page styles.
 *
 * Own stylesheet, same reasoning as marketplace/, admin/, marketplace/product/
 * and marketplace/author/. The shared "chrome" below (tokens, reset, navbar,
 * mobile menu, account popover, auth modal, buttons, footer) is copied
 * from css/style.css - if you change one of those there, mirror the
 * change here too. The `.cart-*` block at the very end is specific to
 * this page.
 */

:root {
  /* Tells the browser to render its OWN native UI (select dropdown popups,
     scrollbars, date pickers, etc.) using a dark palette instead of the
     OS/browser default light one - without this, a <select>'s closed box
     picks up our dark .auth-input/.sell-select/etc styling just fine, but
     the popup list of <option>s that appears on click is native browser
     chrome and ignored our CSS entirely, showing up as a jarring white
     dropdown on an otherwise all-dark page. */
  color-scheme: dark;
  --bg: #08080a;
  --border: #1e1e26;
  --border-soft: #16161c;
  --accent: #ff9d2e;
  --accent-dim: #7a4d1c;
  --text: #f4f2ee;
  --text-dim: #8c8b96;
  --text-faint: #55555f;
  --glass-bg: rgba(15, 15, 19, 0.55);
  --avatar-empty: #2b2b33;
  --avatar-empty-ring: #38383f;
  --danger: #ff6b5e;
  --ok: #34d399;
  --font-display: 'Rubik', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-premium: cubic-bezier(0.16, 1, 0.3, 1);
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-display);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ---------- custom scrollbar ---------- */

html {
  scrollbar-width: thin;
  scrollbar-color: var(--accent-dim) var(--bg);
  scroll-behavior: smooth;
}

section[id] {
  scroll-margin-top: 90px;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

::-webkit-scrollbar {
  width: 11px;
  height: 11px;
}

::-webkit-scrollbar-track {
  background: var(--bg);
}

::-webkit-scrollbar-thumb {
  background-color: var(--accent-dim);
  border: 3px solid var(--bg);
  border-radius: 999px;
  transition: background-color 0.2s var(--ease);
}

::-webkit-scrollbar-thumb:hover {
  background-color: var(--accent);
}

::-webkit-scrollbar-corner {
  background: var(--bg);
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition: none !important;
    animation: none !important;
  }
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  font-family: inherit;
  color: inherit;
  background: none;
  border: none;
  cursor: pointer;
}

.stage {
  position: relative;
  min-height: 100vh;
  width: 100%;
  background-color: var(--bg);
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
  background-size: 44px 44px;
  background-attachment: fixed;
  display: flex;
  flex-direction: column;
}

/* Grid pattern folded directly into .stage's own background instead of
   a separate .stage::before pseudo-element (that's what used to bleed
   through card backgrounds - see git history/DEPLOY notes). A box's own
   background always paints behind its own content, no matter what -
   there's no stacking-context/z-index class of bug possible here at
   all, which is strictly more robust than the earlier z-index:-1 patch.
   Known, accepted tradeoff: background-attachment: fixed can silently
   fall back to scroll behavior on some older mobile Safari versions -
   there the grid just scrolls with the page instead of staying pinned;
   harmless, and still strictly better than the bug this replaces. Same
   change mirrored into every page's own css/style.css copy - see
   build.js's header comment for why there's no single shared
   stylesheet. */

/* ---------- NAVBAR (glass) ---------- */

.navbar {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--glass-bg);
  /* blur radius cut from 22px to 12px - this bar sits sticky at the top
     of every page, so the browser re-computes this blur on every scroll
     frame the whole time you scroll; blur cost roughly scales with the
     radius squared, so this is a large, continuous saving in exchange for
     a barely-noticeable difference in how "frosted" it looks. Originally
     applied only to marketplace/author/css/style.css (Sept 2026) but
     never mirrored to the other copies of this shared chrome - every
     other page kept paying the full 22px cost on every scroll frame
     ever since, which is what made scrolling feel noticeably less smooth
     site-wide compared to that one page. */
  backdrop-filter: blur(12px) saturate(140%);
  -webkit-backdrop-filter: blur(12px) saturate(140%);
  border-bottom: 1px solid var(--border);
}

.nav-inner {
  width: 100%;
  padding: 0 clamp(24px, 5vw, 72px);
  height: 68px;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 24px;
}

/* logo */

.logo {
  display: inline-flex;
  align-items: center;
  justify-self: start;
  outline-offset: 6px;
  padding: 4px 0;
}

.logo:focus-visible {
  outline: 1px solid var(--accent);
}

.logo-mark {
  display: block;
  height: 22px;
  width: auto;
  flex: none;
  transition: transform 0.25s var(--ease), filter 0.25s var(--ease);
  filter: drop-shadow(0 0 0 rgba(255, 157, 46, 0));
}

.logo:hover .logo-mark {
  transform: translateY(-1px) scale(1.04);
  filter: drop-shadow(0 0 14px rgba(255, 157, 46, 0.35));
}

.logo:active .logo-mark {
  transform: translateY(0) scale(0.98);
}

/* center nav */

.nav-links {
  list-style: none;
  display: flex;
  align-items: center;
  gap: clamp(4px, 1.4vw, 20px);
  margin: 0;
  padding: 0;
  justify-self: center;
}

.nav-link {
  position: relative;
  display: inline-block;
  padding: 9px 13px 11px;
  font-size: 0.81rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-dim);
  transition: color 0.25s var(--ease), letter-spacing 0.25s var(--ease);
}

.nav-link-label {
  display: inline-block;
  transition: transform 0.25s var(--ease);
}

.nav-link::after {
  content: '';
  position: absolute;
  left: 13px;
  right: 13px;
  bottom: 5px;
  height: 2px;
  background: var(--accent);
  opacity: 0;
  transform: scaleX(0);
  transform-origin: center;
  transition: transform 0.25s var(--ease), opacity 0.25s var(--ease);
}

.nav-link:hover,
.nav-link:focus-visible {
  color: var(--text);
  letter-spacing: 0.055em;
}

.nav-link:hover .nav-link-label,
.nav-link:focus-visible .nav-link-label {
  transform: translateY(-1px);
}

.nav-link:hover::after,
.nav-link:focus-visible::after {
  opacity: 0.5;
  transform: scaleX(1);
}

.nav-link:focus-visible {
  outline: none;
}

.nav-link.is-active {
  color: var(--text);
  font-weight: 700;
}

.nav-link.is-active::after {
  opacity: 1;
  transform: scaleX(1);
}

/* avatar + name */

.nav-right {
  justify-self: end;
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
}

/* cart icon (shared across all pages) */

.cart-btn {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  flex: none;
  border-radius: 50%;
  color: var(--text-dim);
  transition: background-color 0.25s var(--ease), color 0.25s var(--ease);
}

.cart-btn:hover {
  background-color: rgba(255, 255, 255, 0.045);
  color: var(--text);
}

.cart-btn:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 3px;
}

/* .cart-btn sets its own `display: flex` for layout (icon centering),
   which - being an ordinary author-stylesheet class rule - always wins
   over the browser's own `[hidden] { display: none }` default, since
   author rules beat UA rules regardless of selector specificity. Without
   this, any button/link carrying .cart-btn while also `hidden` (e.g. the
   notification bell before js/notifications.js decides whether to show
   it - see #notifBtn) renders anyway, as an empty circle, for every
   visitor including signed-out ones. */
.cart-btn[hidden] {
  display: none;
}

.cart-icon {
  width: 19px;
  height: 19px;
}

.cart-badge {
  position: absolute;
  top: 1px;
  right: 1px;
  min-width: 15px;
  height: 15px;
  padding: 0 3px;
  border-radius: 999px;
  background: var(--accent);
  color: #06070a;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 700;
  line-height: 15px;
  text-align: center;
}

.cart-badge[hidden] {
  display: none;
}

/* hamburger (mobile only) */

.hamburger-btn {
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  flex: none;
  border-radius: 50%;
  transition: background-color 0.25s var(--ease);
}

.hamburger-btn:hover {
  background-color: rgba(255, 255, 255, 0.045);
}

.hamburger-btn:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 3px;
}

.hamburger-line {
  display: block;
  width: 19px;
  height: 1.5px;
  background: var(--text);
  transition: transform 0.22s var(--ease), opacity 0.22s var(--ease);
}

.hamburger-btn[aria-expanded='true'] .hamburger-line:nth-child(1) {
  transform: translateY(6.5px) rotate(45deg);
}

.hamburger-btn[aria-expanded='true'] .hamburger-line:nth-child(2) {
  opacity: 0;
}

.hamburger-btn[aria-expanded='true'] .hamburger-line:nth-child(3) {
  transform: translateY(-6.5px) rotate(-45deg);
}

/* mobile dropdown menu */

.mobile-menu {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  background: var(--glass-bg);
  /* same 22px -> 12px cut as .navbar above, same reason - mobile GPUs feel
     a large blur radius even more than desktop does. Missed in the first
     propagation pass since that one only matched the .navbar block; caught
     on the follow-up full-site re-check. */
  backdrop-filter: blur(12px) saturate(140%);
  -webkit-backdrop-filter: blur(12px) saturate(140%);
  border-bottom: 1px solid var(--border);
  padding: 0 clamp(24px, 5vw, 72px);
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-height 0.28s var(--ease), opacity 0.2s var(--ease);
}

.mobile-menu.is-open {
  max-height: 320px;
  opacity: 1;
  padding-top: 6px;
  padding-bottom: 14px;
}

.mobile-link {
  padding: 14px 4px;
  border-radius: 6px;
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--text-dim);
  border-bottom: 1px solid var(--border-soft);
  transition: color 0.2s var(--ease), background-color 0.2s var(--ease);
}

.mobile-link:last-child {
  border-bottom: none;
}

.mobile-link:hover {
  color: var(--text);
  background-color: rgba(255, 255, 255, 0.04);
}

.mobile-link.is-active {
  color: var(--text);
  font-weight: 700;
}

.mobile-link:active {
  color: var(--accent);
}

.account-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 10px 4px 4px;
  border-radius: 20px;
  transition: background-color 0.25s var(--ease);
}

.account-btn:hover {
  background-color: rgba(255, 255, 255, 0.045);
}

.account-btn:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 3px;
}

.avatar-ring {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  overflow: hidden;
  border: 1px solid var(--avatar-empty-ring);
  background: var(--avatar-empty);
  transition: border-color 0.25s var(--ease), background 0.25s var(--ease), transform 0.25s var(--ease);
}

.account-btn:hover .avatar-ring {
  border-color: var(--accent-dim);
  transform: scale(1.06);
}

.avatar-glyph {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--text-faint);
}

.avatar-photo {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: none;
}

.avatar-ring[data-photo='1'] .avatar-glyph {
  display: none;
}

.avatar-ring[data-photo='1'] .avatar-photo {
  display: block;
}

.stage[data-auth='in'] .avatar-glyph {
  color: var(--accent);
  font-weight: 600;
}

.account-name {
  font-size: 0.83rem;
  font-weight: 600;
  color: var(--text);
  display: none;
  transition: color 0.25s var(--ease);
}

.account-btn:hover .account-name {
  color: var(--accent);
}

/* state: logged in */

.stage[data-auth='in'] .avatar-ring {
  border-color: var(--accent-dim);
  background: linear-gradient(145deg, rgba(255, 157, 46, 0.22) 0%, rgba(255, 157, 46, 0.03) 100%);
}

.stage[data-auth='in'] .account-name {
  display: inline;
}

/* popover */

.popover {
  position: absolute;
  top: calc(100% + 12px);
  right: 0;
  width: 248px;
  background: #101014;
  border: 1px solid var(--border);
  box-shadow: 0 20px 40px -12px rgba(0, 0, 0, 0.6);
  padding: 18px;
  opacity: 0;
  transform: translateY(-6px);
  pointer-events: none;
  transition: opacity 0.16s var(--ease), transform 0.16s var(--ease);
}

.popover.is-open {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.popover-eyebrow {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0 0 10px;
}

.popover-title {
  font-size: 1rem;
  font-weight: 700;
  margin: 0 0 6px;
}

.popover-body {
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--text-dim);
  margin: 0 0 16px;
}

.popover-user {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
}

.popover-avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: linear-gradient(145deg, #3a2c1a 0%, #1c1610 100%);
  border: 1px solid var(--accent-dim);
  flex: none;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.popover-avatar-initial {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--accent);
}

.popover-avatar-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: none;
}

.popover-avatar[data-photo='1'] .popover-avatar-initial {
  display: none;
}

.popover-avatar[data-photo='1'] .popover-avatar-photo {
  display: block;
}

.popover-user-name {
  display: block;
  font-size: 0.85rem;
  font-weight: 600;
}

.popover-user-email {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  color: var(--text-faint);
}

.popover-btn {
  width: 100%;
  padding: 10px 12px;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: center;
  transition: background 0.15s var(--ease), color 0.15s var(--ease), border-color 0.15s var(--ease);
}

.popover-btn:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 2px;
}

.popover-btn.primary {
  background: var(--accent);
  color: #1a1104;
  border: 1px solid var(--accent);
}

.popover-btn.primary:hover {
  background: #ffb257;
}

.popover-btn.ghost {
  background: transparent;
  color: var(--text-dim);
  border: 1px solid var(--border);
  margin-top: 8px;
}

.popover-btn.ghost:hover {
  color: var(--text);
  border-color: var(--text-faint);
}

.popover-menu {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-bottom: 4px;
}

.popover-link {
  display: block;
  padding: 8px 6px;
  font-size: 0.8rem;
  color: var(--text-dim);
  border-radius: 2px;
  transition: color 0.15s var(--ease), background 0.15s var(--ease);
}

.popover-link[hidden] {
  display: none;
}

.popover-link:disabled {
  color: var(--text-faint);
  cursor: default;
  pointer-events: none;
}

.popover-link:hover {
  color: var(--text);
  background: var(--border-soft);
}

.popover-link.is-accent {
  color: var(--accent);
  font-weight: 600;
}

.popover-link.is-accent:hover {
  background: rgba(255, 157, 46, 0.1);
}

.popover-divider {
  height: 1px;
  background: var(--border);
  margin: 10px 0;
  border: none;
}

/* ---------- AUTH MODAL (login / register) ---------- */

.auth-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(6, 5, 4, 0.5);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  opacity: 0;
  /* visibility (not just opacity/pointer-events) matters here: this class
     is reused by every modal on the site, including the always-present
     sign-in modal's hCaptcha widget. A third-party iframe (hCaptcha's
     checkbox) can re-assert its own `pointer-events: auto` internally,
     which un-does an ancestor's `pointer-events: none` for that iframe
     specifically - opacity/pointer-events alone were not enough to stop
     the CLOSED sign-in modal's captcha from still being clickable through
     whatever modal was actually open on top of it (both share this exact
     class, position and z-index). `visibility: hidden` has no such
     escape hatch - a descendant cannot un-hide itself - so it closes that
     gap for every .auth-overlay on the site, not just this one page.
     Delayed via the transition below so the existing opacity fade-out
     still plays in full before the element actually stops being
     interactive/hit-testable. */
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.22s var(--ease), visibility 0s linear 0.22s;
}

.auth-overlay.is-open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity 0.22s var(--ease), visibility 0s linear 0s;
}

.auth-modal {
  width: 100%;
  max-width: 400px;
  background: #121216;
  border: 1px solid var(--border);
  border-radius: 22px;
  box-shadow: 0 30px 70px -20px rgba(0, 0, 0, 0.75);
  padding: 30px 30px 28px;
  position: relative;
  transform: translateY(10px) scale(0.98);
  transition: transform 0.3s var(--ease);
}

.auth-modal--tall {
  max-height: min(88vh, 720px);
  overflow-y: auto;
}

.auth-overlay.is-open .auth-modal {
  transform: translateY(0) scale(1);
}

.auth-close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-faint);
  font-size: 1.2rem;
  line-height: 1;
  border-radius: 50%;
  transition: color 0.2s var(--ease), background-color 0.2s var(--ease);
}

.auth-close:hover {
  color: var(--text);
  background-color: rgba(255, 255, 255, 0.06);
}

/* brand row */

.auth-brand {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 4px 0 24px;
}

.auth-brand-logo {
  height: 30px;
  width: auto;
  display: block;
}

/* segmented pill switch */

.auth-switch {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  background: #1a1a20;
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 4px;
}

.auth-switch-thumb {
  position: absolute;
  top: 4px;
  left: 4px;
  width: calc(50% - 4px);
  height: calc(100% - 8px);
  background: #f1efe8;
  border-radius: 9px;
  transform: translateX(0);
  transition: transform 0.32s var(--ease);
  will-change: transform;
}

.auth-modal[data-mode='signup'] .auth-switch-thumb {
  transform: translateX(100%);
}

.auth-switch-btn {
  position: relative;
  z-index: 1;
  padding: 13px 12px;
  font-family: var(--font-mono);
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-align: center;
  color: var(--text-dim);
  transition: color 0.25s var(--ease);
}

.auth-switch-btn.is-active {
  color: #14141a;
}

.auth-switch-btn:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 2px;
  border-radius: 8px;
}

/* heading + copy */

.auth-panel {
  margin-top: 22px;
}

.auth-heading {
  font-family: var(--font-display);
  font-size: 1.7rem;
  font-weight: 800;
  line-height: 1.18;
  margin: 0 0 8px;
  white-space: nowrap;
}

.auth-heading-accent {
  color: var(--accent);
  font-style: italic;
  font-weight: 800;
}

.auth-subcopy {
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text-dim);
  margin: 0 0 22px;
}

/* form */

.auth-form {
  display: flex;
  flex-direction: column;
}

.auth-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

.auth-label {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin: 12px 0 6px;
}

.auth-label-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 12px 0 6px;
}

.auth-label-row .auth-label {
  margin: 0;
}

.auth-forgot-link {
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--text-faint);
  transition: color 0.2s var(--ease);
}

.auth-forgot-link:hover {
  color: var(--accent);
}

.auth-forgot-link:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

.auth-input {
  width: 100%;
  padding: 12px 14px;
  background: #18181e;
  border: 1px solid transparent;
  border-radius: 10px;
  color: var(--text);
  font-family: var(--font-display);
  font-size: 0.88rem;
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}

.auth-input::placeholder {
  color: var(--text-faint);
}

.auth-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(255, 157, 46, 0.14);
}

/* Chrome/Edge/Safari autofill (a saved email/password, address or payment
   autofill) forcibly repaints an input's background AND text color with
   its own yellow/light-blue styling the moment it's autofilled - this
   completely ignores .auth-input's own `background`/`color` above, and a
   real `background-color` override on `:-webkit-autofill` gets ignored
   by the browser too (this is the "browser overrides our style" bug
   people notice on login/signup/checkout forms). The fix is the standard
   trick: an inset box-shadow big enough to cover the whole field is NOT
   one of the properties the browser locks, so painting our own dark
   color that way (instead of `background-color`) actually sticks, and
   `-webkit-text-fill-color` forces the text back to our own color too.
   The absurdly long `transition` delay defeats Chrome's own animation
   that reveals the yellow tint after a short delay. Applies everywhere
   .auth-input is used (login/signup, checkout, profile editing, "Start a
   Project", tutorials/add, etc.) since they all share this one class. */
.auth-input:-webkit-autofill,
.auth-input:-webkit-autofill:hover,
.auth-input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--text);
  -webkit-box-shadow: 0 0 0 1000px #18181e inset;
  box-shadow: 0 0 0 1000px #18181e inset;
  transition: background-color 600000s 0s, color 600000s 0s;
}

/* Belt-and-suspenders for the <select> popup on top of `color-scheme: dark`
   above (root of the file) - explicit dark colors on every <option> site-
   wide, in case a browser only partially dark-themes the native dropdown. */
select option {
  background: #18181e;
  color: var(--text);
}

.auth-textarea {
  min-height: 110px;
  resize: vertical;
  font-family: var(--font-display);
  line-height: 1.5;
}

.freelancer-guidelines {
  background: #18181e;
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 16px 18px;
  margin-bottom: 18px;
}

.freelancer-guidelines p {
  font-size: 0.84rem;
  color: var(--text-dim);
  margin: 0 0 10px;
}

.freelancer-guidelines-list {
  margin: 0 0 10px;
  padding-left: 18px;
  font-size: 0.82rem;
  color: var(--text-dim);
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.freelancer-guidelines-note {
  font-size: 0.76rem;
  color: var(--text-faint);
  margin: 0 !important;
}

/* show/hide password */

.auth-password-wrap {
  position: relative;
}

.auth-password-wrap .auth-input {
  padding-right: 46px;
}

.auth-password-toggle {
  position: absolute;
  top: 50%;
  right: 4px;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 8px;
  color: var(--text-faint);
  transition: color 0.2s var(--ease), background-color 0.2s var(--ease);
}

.auth-password-toggle:hover {
  color: var(--text-dim);
  background-color: rgba(255, 255, 255, 0.06);
}

.auth-password-toggle:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 2px;
}

.auth-password-toggle.is-visible {
  color: var(--accent);
}

.icon-eye {
  display: block;
  width: 18px;
  height: 18px;
  background-color: currentColor;
  -webkit-mask: url('/assets/icons/eye.svg') no-repeat center / contain;
  mask: url('/assets/icons/eye.svg') no-repeat center / contain;
}

.auth-password-toggle.is-visible .icon-eye {
  -webkit-mask-image: url('/assets/icons/eye-slash.svg');
  mask-image: url('/assets/icons/eye-slash.svg');
}

.auth-error {
  font-size: 0.78rem;
  line-height: 1.4;
  color: var(--danger);
  background: rgba(255, 107, 94, 0.08);
  border: 1px solid rgba(255, 107, 94, 0.25);
  border-radius: 8px;
  padding: 9px 11px;
  margin-top: 12px;
}

.auth-success {
  font-size: 0.78rem;
  line-height: 1.4;
  color: var(--ok);
  background: rgba(52, 211, 153, 0.08);
  border: 1px solid rgba(52, 211, 153, 0.25);
  border-radius: 8px;
  padding: 9px 11px;
  margin-top: 12px;
}

.auth-submit {
  margin-top: 18px;
  padding: 13px 16px;
  border-radius: 12px;
  background: var(--accent);
  color: #1a1104;
  font-size: 0.83rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  box-shadow: 0 16px 32px -12px rgba(255, 157, 46, 0.5);
  transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease), filter 0.2s var(--ease);
}

.auth-submit-arrow {
  transition: transform 0.2s var(--ease);
}

.auth-submit:hover {
  filter: brightness(1.05);
  transform: translateY(-1px);
  box-shadow: 0 20px 38px -12px rgba(255, 157, 46, 0.6);
}

.auth-submit:hover .auth-submit-arrow {
  transform: translateX(3px);
}

.auth-submit:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 2px;
}

.auth-submit:disabled {
  opacity: 0.6;
  cursor: default;
  transform: none;
}

/* google */

.auth-divider {
  height: 1px;
  background: var(--border);
  margin: 20px 0 16px;
}

.auth-google-btn {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 11px 16px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: #18181e;
  color: var(--text);
  font-size: 0.85rem;
  font-weight: 600;
  transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease);
}

.auth-google-btn:hover {
  background: #1e1e25;
  border-color: var(--text-faint);
}

.auth-google-btn:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 2px;
}

.google-icon {
  flex: none;
  display: block;
}

/* footer lines */

.auth-legal {
  margin: 14px 0 0;
  font-size: 0.72rem;
  line-height: 1.5;
  color: var(--text-faint);
  text-align: center;
}

.auth-legal a {
  color: var(--text-dim);
  text-decoration: underline;
}

.auth-legal a:hover {
  color: var(--text);
}

.auth-consent-row {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 4px 0 2px;
  font-size: 0.72rem;
  line-height: 1.5;
  color: var(--text-faint);
  cursor: pointer;
}

.auth-consent-checkbox {
  flex-shrink: 0;
  width: 15px;
  height: 15px;
  margin-top: 2px;
  accent-color: var(--accent);
  cursor: pointer;
}

.auth-consent-row a {
  color: var(--text-dim);
  text-decoration: underline;
}

.auth-consent-row a:hover {
  color: var(--text);
}

@media (max-width: 480px) {
  .auth-modal {
    padding: 24px 20px 24px;
    border-radius: 18px;
  }

  .auth-row {
    grid-template-columns: 1fr;
  }
}

/* ---------- shared: wide modal + custom select dropdown ----------
   Added for the "Start a Project" modal (partials/project-inquiry-modal.html,
   see js/site-forms.js) - a full-width modifier and a from-scratch <select>
   re-skin, both promoted to shared chrome since the project inquiry modal
   is injected on every page. If you change one of these, mirror the
   change in every other page's own copy (same rule as the rest of this
   "shared chrome" block - see the comment at the top of this file). */

.auth-modal--wide {
  max-width: 600px;
}

/* A native <select>'s closed box happily takes .auth-input's dark
   styling, but its OPEN popup is OS/browser chrome - `color-scheme: dark`
   (root of this file) gets it part of the way, but the browser still
   paints its own blue highlight on the hovered/selected row and there is
   no CSS hook to change that. So any <select> that opts into this (see
   enhanceSelect() in js/site-forms.js) gets visually hidden via
   `.select-native` below - it stays in the DOM as the real source of
   truth for .value - and a fully custom trigger button + option list is
   layered on top instead, themed with our own accent color. */
.select-native {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.select-wrap {
  position: relative;
}

.select-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  text-align: left;
  cursor: pointer;
}

.select-value {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.select-value--placeholder {
  color: var(--text-faint);
}

.select-arrow {
  flex: none;
  width: 8px;
  height: 8px;
  border-right: 1px solid var(--text-dim);
  border-bottom: 1px solid var(--text-dim);
  transform: rotate(45deg) translateY(-3px);
  transition: transform 0.2s var(--ease), border-color 0.2s var(--ease);
}

.select-wrap.is-open .select-arrow {
  transform: rotate(-135deg) translateY(1px);
  border-color: var(--accent);
}

.select-list {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 6px);
  z-index: 20;
  background: #18181e;
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 6px;
  max-height: 220px;
  overflow-y: auto;
  box-shadow: 0 20px 40px -12px rgba(0, 0, 0, 0.6);
}

.select-option {
  padding: 9px 10px;
  border-radius: 7px;
  font-family: var(--font-display);
  font-size: 0.88rem;
  color: var(--text);
  cursor: pointer;
}

.select-option:hover,
.select-option.is-active {
  background: rgba(255, 157, 46, 0.14);
}

.select-option[aria-selected='true'] {
  color: var(--accent);
  font-weight: 600;
}

/* ---------- shared: "Start a Project" modal extras ----------
   Added back alongside the modal itself (partials/project-inquiry-modal.html,
   js/site-forms.js) when "Start a Project" reverted from its own page back
   to a popup. Mirrors the "success panel" pattern already used elsewhere
   (tutorials/add's .admin-gate, the old /start-project page's
   .sp-success-panel) but under its own class names since this modal is
   shared on every page and shouldn't depend on the admin-only .admin-gate
   styling. If you change one of these, mirror the change in every other
   page's own copy (same rule as the rest of this "shared chrome" block). */

/* .auth-form sets `display: flex`, which (being an author-stylesheet rule)
   otherwise wins over the browser's own `[hidden] { display: none }` -
   without this, `someForm.hidden = true` on anything carrying .auth-form
   silently does nothing. */
.auth-form[hidden] {
  display: none;
}

.project-success-panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 180px;
  text-align: center;
  color: var(--text-dim);
  border: 1px solid rgba(52, 211, 153, 0.3);
  border-radius: 16px;
  background: rgba(52, 211, 153, 0.05);
  padding: 32px 24px;
}

.project-success-panel[hidden] {
  display: none;
}

.project-success-panel-title {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--text);
  margin: 0;
}

.project-success-panel-text {
  font-size: 0.9rem;
  line-height: 1.5;
  margin: 0;
  max-width: 420px;
}

.project-optional {
  text-transform: none;
  font-weight: 400;
  color: var(--text-faint);
  letter-spacing: 0;
}

/* ---------- main content / hero ---------- */

.main-content {
  flex: 1;
}

@media (max-width: 720px) {
  .nav-links {
    display: none;
  }
  .nav-inner {
    grid-template-columns: auto 1fr;
  }
  .account-name {
    display: none !important;
  }
  .hamburger-btn {
    display: flex;
  }
  .popover {
    width: min(280px, calc(100vw - 48px));
  }
}

/* ---------- buttons (shared, copied from css/style.css) ---------- */

.hero-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 16px 26px;
  border-radius: 10px;
  overflow: hidden;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  transition: transform 0.2s var(--ease), background-color 0.2s var(--ease), border-color 0.2s var(--ease), filter 0.2s var(--ease), box-shadow 0.2s var(--ease);
}

.hero-btn[hidden] {
  display: none;
}

.hero-btn::before {
  content: '';
  position: absolute;
  top: 0;
  left: -60%;
  width: 40%;
  height: 100%;
  background: linear-gradient(120deg, transparent, rgba(255, 255, 255, 0.35), transparent);
  transform: skewX(-20deg);
  transition: left 0.65s var(--ease-premium);
  pointer-events: none;
}

.hero-btn:hover::before {
  left: 130%;
}

.hero-btn.primary {
  background: var(--accent);
  color: #1a1104;
  box-shadow: 0 20px 40px -18px rgba(255, 157, 46, 0.55);
}

.hero-btn.primary:hover {
  transform: translateY(-1px);
  filter: brightness(1.06);
  box-shadow: 0 24px 46px -16px rgba(255, 157, 46, 0.65);
}

.hero-btn-arrow {
  transition: transform 0.2s var(--ease);
}

.hero-btn.primary:hover .hero-btn-arrow {
  transform: translateX(3px);
}

.hero-btn.outline {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
}

.hero-btn.outline:hover {
  border-color: var(--text-faint);
  background: rgba(255, 255, 255, 0.03);
}

.hero-btn:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 2px;
}

/* ---------- footer ---------- */

.footer {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: #000000;
  border-top: 1px solid var(--border);
  padding: 40px clamp(24px, 5vw, 72px) 0;
}

.footer-inner {
  position: relative;
  z-index: 1;
  width: 100%;
}

.footer-top {
  display: grid;
  grid-template-columns: minmax(220px, 320px) 1fr;
  gap: 48px;
  padding-bottom: 32px;
}

.footer-brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 13px;
}

.footer-logo {
  display: inline-flex;
  align-items: center;
  gap: 9px;
}

.footer-logo-mark {
  width: 22px;
  height: 22px;
  object-fit: contain;
}

.footer-logo-word {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 0.98rem;
  letter-spacing: -0.01em;
  color: var(--text);
}

.footer-tagline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 0.82rem;
  line-height: 1.6;
  color: var(--text-faint);
  margin: 0;
  max-width: 300px;
}

.footer-social {
  display: flex;
  gap: 8px;
  margin-top: 2px;
}

.footer-social-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  border: 1px solid var(--border);
  color: var(--text-faint);
  transition: border-color 0.25s var(--ease), color 0.25s var(--ease), transform 0.25s var(--ease-premium);
}

.footer-social-link:hover {
  border-color: var(--accent-dim);
  color: var(--accent);
  transform: translateY(-2px);
}

.footer-social-link svg {
  width: 14px;
  height: 14px;
}

.footer-links {
  display: grid;
  grid-template-columns: repeat(3, minmax(110px, 150px));
  gap: 28px;
  justify-content: end;
}

.footer-col {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}

.footer-col-title {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin: 0 0 4px;
}

.footer-link {
  font-family: var(--font-display);
  font-size: 0.82rem;
  color: var(--text-faint);
  transition: color 0.2s var(--ease), transform 0.2s var(--ease-premium);
}

.footer-link:hover {
  color: var(--text);
  transform: translateX(2px);
}

.footer-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 16px 0;
  border-top: 1px solid var(--border);
  flex-wrap: wrap;
}

.footer-copyright,
.footer-signature {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--text-faint);
  margin: 0;
}

.footer-watermark {
  display: block;
  text-align: center;
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(1.8rem, 5vw, 3.2rem);
  line-height: 1;
  letter-spacing: -0.01em;
  color: transparent;
  -webkit-text-stroke: 1px var(--border);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.025), transparent 90%);
  -webkit-background-clip: text;
  background-clip: text;
  pointer-events: none;
  user-select: none;
  margin-top: 2px;
  padding-bottom: 14px;
  overflow: hidden;
  white-space: nowrap;
}

@media (max-width: 900px) {
  .footer-top {
    grid-template-columns: 1fr;
    gap: 40px;
  }
  .footer-links {
    justify-content: start;
    grid-template-columns: repeat(3, minmax(100px, 1fr));
    gap: 24px;
  }
  .footer-brand {
    max-width: 420px;
  }
}

@media (max-width: 560px) {
  .footer {
    padding-top: 36px;
  }
  .footer-links {
    grid-template-columns: repeat(2, 1fr);
  }
  .footer-bottom {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }
}


/* ---------- sell page (specific to this page) ---------- */

.sell-page {
  /* Widened from 860px - the redesigned "Add Item" page reuses the real
     product page's own two-column .pd-layout (1180px, see
     marketplace/product/css/style.css), so this needs to match or the
     layout below would get squeezed and wrap wrong. The gate states
     (.sell-gate) and header still look fine centered at this width. */
  padding: 32px clamp(24px, 5vw, 72px) 100px;
  max-width: 1180px;
  margin: 0 auto;
}

.sell-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-dim);
  margin-bottom: 28px;
  transition: color 0.2s var(--ease), transform 0.2s var(--ease);
}

.sell-back:hover {
  color: var(--accent);
  transform: translateX(-2px);
}

.sell-head {
  margin-bottom: 32px;
}

.sell-title {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(1.6rem, 3vw, 2.2rem);
  margin: 0 0 10px;
  color: var(--text);
}

.sell-subcopy {
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--text-dim);
  max-width: 560px;
  margin: 0;
}

/* gate states: signed out / not a freelancer / just submitted -
   same visual language as .admin-gate in admin/css/style.css. */

.sell-gate {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 280px;
  text-align: center;
  color: var(--text-dim);
  border: 1px solid var(--border);
  border-radius: 16px;
  /* Bumped from 0.02 - at that strength the whole card barely read as a
     card at all against the page's near-black background. */
  background: rgba(255, 255, 255, 0.05);
  padding: 40px 24px;
}

.sell-gate-title {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--text);
  margin: 0;
}

.sell-gate-text {
  font-size: 0.9rem;
  line-height: 1.5;
  margin: 0;
  max-width: 420px;
}

.sell-gate-btn {
  margin-top: 6px;
}

.sell-success-panel {
  border-color: rgba(52, 211, 153, 0.3);
  background: rgba(52, 211, 153, 0.05);
}

.sell-success-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 6px;
}

.sell-gate[hidden],
.sell-form-card[hidden] {
  display: none;
}

/* modal-body field layout (Category/File Details/etc. - the outer page
   itself is no longer a bordered form card, see .ai-builder below) */

.sell-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.sell-row-3 {
  grid-template-columns: 1fr 1fr 1fr;
}

.sell-optional {
  text-transform: none;
  font-weight: 400;
  color: var(--text-faint);
  letter-spacing: 0;
}

.sell-select {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238c8b96' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 11px;
  padding-right: 36px;
  cursor: pointer;
}

.sell-select option {
  background: #0e0e12;
  color: var(--text);
}

.sell-textarea {
  min-height: 120px;
  resize: vertical;
  line-height: 1.5;
  font-family: var(--font-display);
}

.sell-textarea-small {
  min-height: 72px;
}

.sell-hint {
  font-size: 0.76rem;
  color: var(--text-faint);
  line-height: 1.5;
  margin: 6px 0 0;
}

.sell-note {
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--text-dim);
  background: var(--border-soft);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  margin: 20px 0 0;
}

.lh-upload-btn-compact {
  padding: 5px 10px;
  font-size: 0.72rem;
}

@media (max-width: 720px) {
  .sell-row,
  .sell-row-3 {
    grid-template-columns: 1fr;
  }
}

/* ================= Add Item redesign: product-preview style =================
   The page below no longer looks like a form - it looks like the actual
   product page this listing will become, empty. Every section is a small
   dashed placeholder paired with the same pencil-icon edit button as
   marketplace/author (.au-section-edit-btn/.au-section-modal, copied
   below from marketplace/author/css/style.css - mirror any change made
   there over here too). Clicking a placeholder or its pencil opens a
   small modal that edits an in-memory `draft` object and re-renders just
   that one section - see js/main.js. Nothing is saved to Supabase until
   "Submit for Review". */

/* No `.ai-builder { display: block }` here on purpose - a <div> is
   already block by default, and an explicit rule (even redundant) beats
   the UA stylesheet's `[hidden] { display: none }`, which broke every
   showOnly(sellSuccessPanel)/showOnly(sellGateEditDenied)/etc call: the
   `hidden` attribute got set correctly, but this element stayed visually
   on screen (and in the tab order) underneath whichever gate/panel was
   actually meant to be showing. Confirmed via getComputedStyle(), not
   just the DOM's own .hidden property, which still read true either way. */

/* ---- reused, unmodified copies of the real product page's own .pd-*
   classes (marketplace/product/css/style.css) so a filled-in section
   looks exactly like the listing it's about to become. ---- */

.pd-preview {
  max-width: 640px;
  margin: 0 auto 30px;
}

.pd-thumbs {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: 14px;
}

.pd-thumb {
  flex: none;
  width: 64px;
  height: 64px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background-color: #16161c;
  background-size: cover;
  background-position: center;
}

.pd-layout {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 48px;
  align-items: start;
}

.pd-description-col {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.pd-image {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: 18px;
  border: 1px solid var(--border);
  background: linear-gradient(155deg, #1a1a20 0%, #0c0c10 62%);
  background-size: cover;
  background-position: center;
  overflow: hidden;
  transition: border-color 0.2s var(--ease);
}

.pd-image:hover {
  border-color: var(--accent-dim);
}

.pd-image-grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.06) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.06) 1px, transparent 1px);
  background-size: 30px 30px;
  -webkit-mask-image: radial-gradient(circle at 50% 55%, black, transparent 72%);
  mask-image: radial-gradient(circle at 50% 55%, black, transparent 72%);
  opacity: 0.7;
}

.pd-image-shine {
  position: absolute;
  inset: 0;
  background: radial-gradient(480px circle at var(--mx, 50%) var(--my, 40%), rgba(255, 255, 255, 0.08), transparent 60%);
  opacity: 0;
  transition: opacity 0.3s var(--ease);
  pointer-events: none;
}

.pd-image:hover .pd-image-shine {
  opacity: 1;
}

.pd-info {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.pd-category {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0;
}

.pd-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.pd-tag {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-dim);
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--border);
}

@media (max-width: 900px) {
  .pd-layout {
    grid-template-columns: 1fr;
  }
}

/* ---- "empty page copy" placeholder + pencil pattern used for every
   section below the photo hero. ---- */

.ai-section {
  margin-bottom: 26px;
}

.ai-editable-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.ai-section-label {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0 0 8px;
  display: block;
}

.ai-required-dot {
  color: var(--accent);
}

.ai-placeholder-btn {
  /* flex:1 (not inline-flex/shrink-to-fit) so every row's box stretches
     to the column's full width, whether it's still an empty dashed
     placeholder or already filled in - otherwise a short value like
     "3D Models" sits in a tiny box next to a long one like a delivery
     URL, and the two columns look ragged instead of lined up. The pencil
     button next to it keeps its own fixed size (.au-section-edit-btn is
     flex: none). */
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  box-sizing: border-box;
  align-items: center;
  gap: 8px;
  border: 1px dashed var(--border);
  border-radius: 10px;
  padding: 9px 14px;
  color: var(--text-faint);
  font-size: 0.85rem;
  font-family: var(--font-display);
  background: transparent;
  cursor: pointer;
  text-align: left;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease), background-color 0.2s var(--ease);
}

.ai-placeholder-btn:hover {
  border-color: var(--accent-dim);
  color: var(--accent);
  background: rgba(255, 157, 46, 0.08);
}

.ai-placeholder-btn .ai-plus {
  font-size: 1rem;
  line-height: 1;
  flex: none;
}

/* once a section has real content, it stops looking like a form field and
   starts looking like plain page copy - still the same clickable button
   underneath. */
.ai-placeholder-btn.ai-filled {
  display: block;
  border-style: solid;
  border-color: var(--border);
  color: var(--text);
  background: rgba(255, 255, 255, 0.03);
  white-space: normal;
  line-height: 1.5;
}

.ai-placeholder-btn.ai-filled:hover {
  border-color: var(--accent-dim);
  background: rgba(255, 157, 46, 0.06);
}

.ai-placeholder-btn.ai-filled-title {
  border: none;
  background: none;
  padding: 2px 0;
  font-weight: 900;
  font-size: clamp(1.4rem, 2.6vw, 2rem);
  color: var(--text);
}

.ai-placeholder-btn.ai-filled-title:hover {
  color: var(--accent);
  background: none;
}

.ai-placeholder-btn.ai-filled-category {
  border: none;
  background: none;
  padding: 2px 0;
}

.ai-placeholder-btn.ai-filled-category:hover {
  background: none;
}

.ai-placeholder-btn.ai-filled-category:hover .pd-category {
  color: var(--text);
}

.ai-placeholder-btn.ai-filled-price {
  border: none;
  background: none;
  padding: 2px 0;
  font-family: var(--font-mono);
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--accent);
}

.ai-placeholder-btn.ai-filled-price:hover {
  color: var(--text);
  background: none;
}

.ai-placeholder-btn .pd-tags {
  pointer-events: none;
}

/* ---- hero photo area: reuses .pd-image itself, this just adds the
   dashed empty-state prompt shown until at least one photo is added. ---- */

.ai-photo-hero {
  cursor: pointer;
}

.ai-photo-hero:not(.ai-has-photo) {
  border-style: dashed;
}

.ai-photo-empty {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  color: var(--text-faint);
  transition: color 0.2s var(--ease);
}

.ai-photo-hero:hover .ai-photo-empty {
  color: var(--accent);
}

.ai-photo-empty-icon {
  width: 34px;
  height: 34px;
}

.ai-photo-empty-icon svg {
  width: 100%;
  height: 100%;
}

.ai-photo-empty strong {
  font-size: 0.95rem;
  color: inherit;
}

.ai-photo-empty span {
  font-size: 0.78rem;
  font-family: var(--font-mono);
}

.ai-photo-hint {
  margin: 10px 0 0;
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--text-faint);
}

.ai-photo-hero.ai-has-photo .ai-photo-empty {
  display: none;
}

.ai-photo-edit-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  background: rgba(8, 8, 10, 0.72);
}

/* ---- submit bar + progress ---- */

.ai-submit-bar {
  margin-top: 40px;
  padding-top: 28px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  text-align: center;
}

.ai-submit-bar .hero-btn[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}

.ai-progress-note {
  font-size: 0.8rem;
  color: var(--text-dim);
  margin: 0;
}

.ai-progress-note strong {
  color: var(--accent);
}

.ai-progress-note.is-ready strong {
  color: var(--ok);
}

/* ================= copied from marketplace/author/css/style.css:
   the small section-scoped modal + pencil button + info tip + photo-grid
   picker. Mirror any change made there over here too. ================= */

.au-section-edit-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 7px;
  border: 1px solid var(--border);
  color: var(--text-faint);
  background: transparent;
  flex: none;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease), background-color 0.2s var(--ease);
}

.au-section-edit-btn:hover {
  border-color: var(--accent-dim);
  color: var(--accent);
  background: rgba(255, 157, 46, 0.1);
}

/* Clicking a placeholder or pencil to open its modal used to leave that
   button focused underneath the blurred backdrop - the browser's default
   focus ring, seen through backdrop-filter, looked like a glowing stray
   outline behind the modal. main.js now blurs the trigger as soon as the
   modal opens, and these rules keep a real focus ring for keyboard users
   (:focus-visible) while never showing the plain-click one. */
.ai-placeholder-btn:focus,
.au-section-edit-btn:focus,
.ai-photo-hero:focus {
  outline: none;
}

.ai-placeholder-btn:focus-visible,
.au-section-edit-btn:focus-visible,
.ai-photo-hero:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.au-section-edit-btn[hidden] {
  display: none;
}

.au-section-edit-btn svg {
  width: 13px;
  height: 13px;
}

.au-section-modal {
  /* focus() lands here on open (see openSectionModal() in js/main.js) so
     the trigger button isn't left focused behind the blur - the modal
     itself doesn't need its own visible ring for that. */
  outline: none;
  max-width: 640px;
  max-height: min(88vh, 760px);
  overflow-y: auto;
  will-change: transform;
}

/* "Edit photos" only (openSectionModal()'s 4th argument, see
   openPhotosModal()) - team feedback that the default 640px width made
   same-looking thumbnails too hard to tell apart. Wider tiles need a
   wider grid, so .pa-grid's own minmax() column size isn't touched here;
   this just gives it more room to lay more/bigger columns out in. */
.au-section-modal--photos {
  max-width: 880px;
}

.au-section-modal-title {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 800;
  color: var(--text);
  margin: 0 0 16px;
}

.au-section-modal-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 16px;
}

.au-section-modal-body .auth-label {
  /* Matched to .pe-info-tip-btn's 20px so a plain label (e.g. Subcategory,
     License) sits at the same height as a label-row carrying an info-tip
     icon (e.g. Category, Price) - otherwise the icon's 20px pushes that
     row taller and the two side-by-side fields land at different y. */
  margin-top: 4px;
  min-height: 20px;
  display: flex;
  align-items: center;
}

.au-section-modal-body .auth-label-row {
  margin-top: 4px;
  min-height: 20px;
}

.au-section-textarea {
  min-height: 160px;
  resize: vertical;
  line-height: 1.5;
  font-family: var(--font-display);
}

.au-section-hint {
  font-size: 0.76rem;
  color: var(--text-faint);
  line-height: 1.5;
  margin: 6px 0 0;
}

.au-section-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  flex-wrap: wrap;
}

.pe-info-tip {
  position: relative;
  display: inline-flex;
  align-items: center;
  margin-left: 6px;
  vertical-align: middle;
}

.pe-info-tip-btn {
  /* Bumped from 16px/0.62rem (the exact copy from marketplace/author) -
     at that size it read as barely-there next to this page's own larger
     section labels, and was fiddly to actually click. */
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 1px solid var(--text-faint);
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
}

.pe-info-tip-btn:hover,
.pe-info-tip-btn:focus-visible,
.pe-info-tip.is-open .pe-info-tip-btn {
  border-color: var(--accent);
  color: var(--accent);
  outline: none;
}

.pe-info-tip-bubble {
  position: absolute;
  bottom: calc(100% + 8px);
  right: 0;
  left: auto;
  transform: translateY(4px);
  width: max-content;
  max-width: min(230px, 65vw);
  background: #1c1c22;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 10px;
  font-size: 0.72rem;
  line-height: 1.45;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  color: var(--text-dim);
  box-shadow: 0 12px 30px -10px rgba(0, 0, 0, 0.6);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.16s var(--ease), transform 0.16s var(--ease);
  z-index: 5;
}

.pe-info-tip-btn:hover + .pe-info-tip-bubble,
.pe-info-tip-btn:focus-visible + .pe-info-tip-bubble,
.pe-info-tip.is-open .pe-info-tip-bubble {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

@media (max-width: 480px) {
  .pe-info-tip-bubble {
    max-width: 68vw;
    font-size: 0.7rem;
  }
}

/* Info tips whose field sits near the top of a modal (Category, Price &
   License, ...) used to pop their bubble upward straight into the
   modal's own title, then get sliced off by .au-section-modal's
   overflow-y: auto - the top half of the tip text was simply gone. Those
   bubbles are now built as ONE shared element appended to <body> and
   positioned with `position: fixed` from the button's real screen
   coordinates (see positionInfoTipBubble() in js/main.js), so they sit
   above the modal instead of being clipped by it, and flip to open
   below the button when there isn't room above. */
.pe-info-tip-bubble--floating {
  position: fixed;
  left: 0;
  top: 0;
  right: auto;
  bottom: auto;
  transform: none;
  /* .auth-overlay itself sits at z-index: 200 - this has to clear that
     (and the modal inside it) since the bubble is appended straight to
     <body>, as a sibling of the overlay, not a descendant of the modal. */
  z-index: 250;
}

.pe-info-tip-bubble--floating.is-visible {
  opacity: 1;
  pointer-events: auto;
}

/* photo grid picker (Photos modal) - same tiles as a portfolio piece's
   photo grid on marketplace/author, star marks which photo becomes this
   item's thumbnail/first gallery image. */

.pcp-photo-frame {
  position: relative;
  aspect-ratio: 1;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid var(--border);
  background: #0e0e12;
}

.pcp-photo-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.pcp-photo-img[hidden] {
  display: none;
}

.pcp-photo-placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-faint);
}

.pcp-photo-placeholder svg {
  width: 24px;
  height: 24px;
}

.pcp-photo-frame.is-broken .pcp-photo-placeholder {
  color: var(--danger);
}

.pcp-photo-spinner {
  display: none;
}

.pcp-photo-frame.is-uploading .pcp-photo-placeholder {
  display: none;
}

.pcp-photo-frame.is-uploading .pcp-photo-spinner {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.pcp-photo-frame.is-uploading .pcp-photo-spinner::after {
  content: '';
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  animation: pcp-photo-spin 0.7s linear infinite;
}

@keyframes pcp-photo-spin {
  to {
    transform: rotate(360deg);
  }
}

.pa-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 10px;
  border-radius: 12px;
  transition: background-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}

/* Shown while dragging image files in from the desktop over this grid
   (see wirePieceUpload()'s dragover/drop handlers in js/main.js) - a
   dashed accent outline makes it obvious the drop will actually land
   here, since nothing else about the grid changes on a plain dragover. */
.pa-grid--drop-active {
  background: rgba(255, 157, 46, 0.08);
  box-shadow: 0 0 0 2px var(--accent) inset;
}

.pcp-photo-frame.pa-is-primary {
  border-color: var(--accent);
}

.pa-star-btn {
  position: absolute;
  top: 6px;
  left: 6px;
  z-index: 2;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: rgba(8, 8, 10, 0.72);
  border: 1px solid var(--border);
  color: var(--text-faint);
  font-size: 0.85rem;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}

.pa-star-btn:hover {
  color: var(--accent);
  border-color: var(--accent-dim);
}

.pcp-photo-frame.pa-is-primary .pa-star-btn {
  color: var(--accent);
  border-color: var(--accent-dim);
}

.pa-remove-btn {
  position: absolute;
  top: 6px;
  right: 6px;
  z-index: 2;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: rgba(8, 8, 10, 0.72);
  border: 1px solid var(--border);
  color: var(--text-faint);
  font-size: 0.85rem;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.15s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
}

.pcp-photo-frame:hover .pa-remove-btn,
.pa-remove-btn:focus-visible {
  opacity: 1;
}

.pa-remove-btn:hover {
  color: var(--danger);
  border-color: var(--danger);
}

.pa-primary-tag {
  position: absolute;
  left: 6px;
  bottom: 6px;
  z-index: 2;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
  background: rgba(8, 8, 10, 0.72);
  border: 1px solid var(--accent-dim);
  padding: 2px 7px;
  border-radius: 999px;
}

.pa-add-tile {
  aspect-ratio: 1;
  border-radius: 10px;
  border: 1px dashed var(--border);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  color: var(--text-faint);
  font-size: 0.7rem;
  cursor: pointer;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
}

.pa-add-tile:hover {
  border-color: var(--accent-dim);
  color: var(--accent);
}

.pa-add-tile-icon {
  font-size: 1.2rem;
  line-height: 1;
}

.pa-drag-handle {
  position: absolute;
  bottom: 6px;
  right: 6px;
  z-index: 2;
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  border: none;
  background: rgba(8, 8, 10, 0.72);
  color: var(--text-faint);
  cursor: grab;
  opacity: 0;
  transition: opacity 0.15s var(--ease), color 0.15s var(--ease);
}

.pcp-photo-frame:hover .pa-drag-handle,
.pa-drag-handle:focus-visible {
  opacity: 1;
}

.pa-drag-handle:hover {
  color: var(--accent);
}

.pa-drag-handle:active {
  cursor: grabbing;
}

.pa-drag-handle svg {
  width: 13px;
  height: 13px;
}

.pcp-photo-frame.pa-is-dragging {
  opacity: 0.4;
}

@media (max-width: 720px) {
  .ai-editable-row {
    flex-wrap: wrap;
  }
}

/* ---------- cookie consent banner (shared chrome, see
   partials/cookie-banner.html + js/cookie-consent.js - if you change one
   of those, mirror the change here too). ---------- */

.cookie-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 200;
  padding: 0 clamp(16px, 4vw, 32px) clamp(16px, 4vw, 32px);
  transform: translateY(120%);
  opacity: 0;
  transition: transform 0.4s var(--ease-premium), opacity 0.3s var(--ease);
  pointer-events: none;
}

.cookie-banner[hidden] {
  display: none;
}

.cookie-banner.is-visible {
  transform: translateY(0);
  opacity: 1;
  pointer-events: auto;
}

.cookie-banner-inner {
  max-width: 920px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  background: #101014;
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 18px 22px;
  box-shadow: 0 24px 60px -20px rgba(0, 0, 0, 0.65);
}

.cookie-banner-text {
  flex: 1 1 320px;
  font-size: 0.84rem;
  line-height: 1.55;
  color: var(--text-dim);
  margin: 0;
}

.cookie-banner-link {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.cookie-banner-link:hover {
  color: var(--text);
}

.cookie-banner-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: none;
  flex-wrap: wrap;
}

.cookie-banner-btn {
  font-family: var(--font-mono);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 14px 20px;
  border-radius: 999px;
  white-space: nowrap;
  transition: border-color 0.2s var(--ease), background-color 0.2s var(--ease), color 0.2s var(--ease), filter 0.2s var(--ease);
}

.cookie-banner-btn.ghost {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-dim);
}

.cookie-banner-btn.ghost:hover {
  border-color: var(--text-faint);
  color: var(--text);
}

.cookie-banner-btn.primary {
  background: var(--accent);
  border: 1px solid var(--accent);
  color: #1a1104;
}

.cookie-banner-btn.primary:hover {
  filter: brightness(1.06);
}

@media (prefers-reduced-motion: reduce) {
  .cookie-banner {
    transition: none;
  }
}

@media (max-width: 640px) {
  .cookie-banner-inner {
    flex-direction: column;
    align-items: stretch;
    text-align: left;
  }
  .cookie-banner-text {
    flex-basis: auto;
  }
  .cookie-banner-actions {
    justify-content: stretch;
  }
  .cookie-banner-btn {
    flex: 1 1 0;
    text-align: center;
  }
}

/* ---------- text selection highlight (site-wide) - restyled per team
   feedback (Discord: "Wyłączyć zaznaczanie tekstu (lub je uładnić, np.
   lekko pomarańczowe i cieńsze)") to a light, thin accent-orange
   highlight instead of the harsh browser default, rather than disabling
   selection outright - keeping text selectable matters for accessibility
   (copying, screen readers, translation tools), it just needed to look
   intentional instead of default. Same rule copied into every
   css/style.css on the site - see build.js's header comment for why
   there's no single shared stylesheet to add this to instead. ---------- */

::selection {
  background: rgba(255, 157, 46, 0.28);
  color: var(--text);
}

/* ---------- shared image-upload widget (js/image-upload.js) - same
   classes reused everywhere a real file upload was added: product
   thumbnail/photos on marketplace/sell, avatar + portfolio photos on
   marketplace/profile and marketplace/author, course thumbnail on
   tutorials/add and admin/tutorials. Copied into each of those 5 pages'
   own css/style.css, same reasoning as the text-selection rule elsewhere
   in this file.

   Markup shape every wired field uses:
     <div class="lh-upload">
       <label class="lh-upload-btn">
         Upload photo
         <input type="file" accept="image/*" class="lh-upload-input" hidden>
       </label>
       <span class="lh-upload-status" hidden></span>
       <span class="lh-upload-error" hidden></span>
     </div>
   ...plus an optional <img class="lh-upload-preview" hidden> wherever a
   thumbnail preview belongs in that field's own layout (add
   -preview-round for an avatar, -preview-wide for a full-width
   thumbnail). ---------- */

.lh-upload-input {
  display: none;
}

.lh-upload {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 8px;
}

.lh-upload-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-dim);
  background: var(--border-soft);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 14px;
  cursor: pointer;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease), background-color 0.2s var(--ease);
}

.lh-upload-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.lh-upload-status {
  font-size: 0.76rem;
  color: var(--text-faint);
}

.lh-upload-error {
  font-size: 0.76rem;
  color: #ff6b5e;
}

.lh-upload-status[hidden],
.lh-upload-error[hidden] {
  display: none;
}

.lh-upload-preview {
  display: block;
  width: 64px;
  height: 64px;
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: #0e0e12;
}

.lh-upload-preview[hidden] {
  display: none;
}

.lh-upload-preview-round {
  border-radius: 50%;
}

.lh-upload-preview-wide {
  width: 100%;
  height: 120px;
  border-radius: 10px;
}

/* ---------- notification bell (js/notifications.js) - shown once
   signed in, a small red dot appears while there's at least one unread
   notification (a REAL one - see notifications_migration.sql - not a
   decorative reuse of some other count). The bell reuses .cart-btn/
   .cart-icon for identical sizing; the dropdown below it is the same
   visual language as .popover, just anchored to the bell itself (not the
   whole .nav-right) via .notif-wrap so it doesn't have to share
   .popover's own right:0 anchor. ---------- */

.notif-wrap {
  position: relative;
  display: flex;
  align-items: center;
}

.notif-dot {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #ff6b5e;
  border: 2px solid #06070a;
}

.notif-dot[hidden] {
  display: none;
}

.notif-panel {
  position: absolute;
  top: calc(100% + 12px);
  right: 0;
  width: 320px;
  max-width: calc(100vw - 32px);
  max-height: 420px;
  overflow-y: auto;
  background: #101014;
  border: 1px solid var(--border);
  box-shadow: 0 20px 40px -12px rgba(0, 0, 0, 0.6);
  padding: 14px;
  opacity: 0;
  transform: translateY(-6px);
  pointer-events: none;
  transition: opacity 0.16s var(--ease), transform 0.16s var(--ease);
  z-index: 40;
}

.notif-panel.is-open {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.notif-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 10px;
}

.notif-panel-title {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.notif-mark-all-btn {
  font-size: 0.74rem;
  font-weight: 600;
  color: var(--accent);
  transition: opacity 0.2s var(--ease);
}

.notif-mark-all-btn:hover {
  opacity: 0.8;
}

.notif-mark-all-btn[hidden] {
  display: none;
}

.notif-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.notif-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: 10px;
  border-radius: 8px;
  transition: background-color 0.2s var(--ease);
}

.notif-item:hover {
  background-color: rgba(255, 255, 255, 0.045);
}

.notif-item.is-unread {
  background-color: rgba(255, 157, 46, 0.07);
}

.notif-item-title {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text);
  margin: 0 0 3px;
}

.notif-item-body {
  font-size: 0.78rem;
  line-height: 1.4;
  color: var(--text-dim);
  margin: 0 0 4px;
}

.notif-item-time {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  color: var(--text-faint);
}

.notif-empty {
  font-size: 0.82rem;
  color: var(--text-faint);
  text-align: center;
  padding: 18px 6px;
  margin: 0;
}

.notif-empty[hidden] {
  display: none;
}

@media (max-width: 480px) {
  .notif-panel {
    width: calc(100vw - 32px);
    right: -8px;
  }
}

/* Single-slot photo grid (the Thumbnail): once it holds a tile, the dashed
   add tile steps aside - removing the tile brings it back. */
.pa-grid--single:has(.pcp-photo-frame) .pa-add-tile {
  display: none;
}

/* ---------- banner render (optional high-res hero image) ---------- */
.ai-banner-filled {
  display: flex;
  align-items: center;
  gap: 12px;
}

.ai-banner-thumb {
  width: 96px;
  height: 40px;
  object-fit: cover;
  border-radius: 6px;
  border: 1px solid var(--border);
  flex: none;
}

.ai-banner-preview {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 7;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid var(--border);
  margin-bottom: 14px;
  background: #0e0e12;
}

.ai-banner-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.ai-banner-pick {
  cursor: pointer;
}

.ai-banner-pick.is-disabled {
  opacity: 0.5;
  pointer-events: none;
}

/* ---- draft autosave bar ---- */
.sell-draft-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 12px;
  margin: 0 0 20px;
  padding: 12px 16px;
  border-radius: 12px;
  border: 1px solid rgba(255, 159, 46, 0.35);
  background: rgba(255, 159, 46, 0.07);
}
.sell-draft-text {
  flex: 1 1 260px;
  font-size: 0.86rem;
  color: var(--text-dim);
}
.sell-draft-text strong { color: var(--text); }

/* ---- "Also add to my portfolio" ---- */
.sell-portfolio-opt {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin: 18px 0 4px;
  padding: 14px 16px;
  border-radius: 12px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.02);
  cursor: pointer;
  transition: border-color 0.2s var(--ease), background-color 0.2s var(--ease);
}
.sell-portfolio-opt[hidden] { display: none; }
.sell-portfolio-opt:hover { border-color: var(--accent-dim); }
.sell-portfolio-opt input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}
.sell-portfolio-opt-box {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  margin-top: 1px;
  border-radius: 6px;
  border: 1.5px solid var(--text-faint);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.sell-portfolio-opt input:checked + .sell-portfolio-opt-box {
  background: var(--accent);
  border-color: var(--accent);
}
.sell-portfolio-opt input:checked + .sell-portfolio-opt-box::after {
  content: "";
  width: 6px;
  height: 11px;
  border: solid #111;
  border-width: 0 2px 2px 0;
  transform: translateY(-1px) rotate(45deg);
}
.sell-portfolio-opt input:focus-visible + .sell-portfolio-opt-box {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.sell-portfolio-opt-text {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 0.82rem;
  color: var(--text-dim);
}
.sell-portfolio-opt-text strong { color: var(--text); font-size: 0.9rem; }

/* ---- banner standard: 21:9 preview with the hero's text zone ---- */
.ai-banner-frame {
  position: relative;
  margin-bottom: 14px;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid var(--border);
  background: #0e0e12;
}
.ai-banner-frame[hidden] { display: none; }
.ai-banner-frame .ai-banner-preview {
  aspect-ratio: 21 / 9;
  margin: 0;
  border: 0;
  border-radius: 0;
}
.ai-banner-textzone {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 40%;
  display: flex;
  align-items: flex-end;
  padding: 10px 12px;
  border-right: 1px dashed rgba(255, 157, 46, 0.7);
  background: linear-gradient(90deg, rgba(8, 8, 10, 0.55), rgba(8, 8, 10, 0.15));
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #ffcf8a;
  pointer-events: none;
}
.ai-banner-rules {
  margin: 8px 0 10px;
  padding-left: 18px;
  display: grid;
  gap: 4px;
}
.ai-banner-rules strong, .sell-hint strong { color: var(--text); }
