/* Wares — layered 2026 CSS. Tier policy lives in CLAUDE.md.
   Layer order is fixed. If you fight specificity, you're in the wrong layer. */

@layer reset, tokens, components, utilities;

/* ---------- reset ---------- */
@layer reset {
  *, *::before, *::after { box-sizing: border-box; }
  [hidden] { display: none !important; }  /* keep the hidden attribute authoritative */
  body { margin: 0; -webkit-font-smoothing: antialiased; }
  img { max-width: 100%; height: auto; display: block; }
  button { font: inherit; cursor: pointer; }
  h1, h2, h3, p, figure { margin: 0; }
}

/* ---------- tokens ---------- */
@layer tokens {
  @property --brand-hue {
    syntax: "<number>";
    inherits: true;
    initial-value: 275;
  }

  :root {
    --brand: oklch(55% 0.19 var(--brand-hue));
    --brand-soft: oklch(from var(--brand) 96% 0.03 h);
    --brand-text: oklch(from var(--brand) 35% 0.15 h);
    --surface: oklch(99% 0.004 90);
    --surface-raised: oklch(100% 0 0);
    --ink: oklch(22% 0.01 90);
    --ink-muted: oklch(50% 0.015 90);
    --line: oklch(90% 0.008 90);
    --success: oklch(60% 0.15 155);
    --danger: oklch(58% 0.2 25);

    /* Fluid space scale — grows with the viewport, no media queries (Kevin Powell / Utopia). */
    --space-1: clamp(0.25rem, 0.2rem + 0.2vw, 0.35rem);
    --space-2: clamp(0.5rem, 0.4rem + 0.4vw, 0.75rem);
    --space-3: clamp(0.9rem, 0.75rem + 0.7vw, 1.25rem);
    --space-4: clamp(1.35rem, 1rem + 1.5vw, 2.25rem);
    --space-5: clamp(2rem, 1.4rem + 2.6vw, 3.5rem);

    --radius: 10px;
    --measure: 65ch;               /* max readable line length */
    --gutter: max(var(--space-3), 5vw);  /* page side padding that never crowds small screens */

    --step-0: clamp(0.95rem, 0.9rem + 0.3vw, 1.05rem);
    --step-1: clamp(1.1rem, 1rem + 0.6vw, 1.35rem);
    --step-2: clamp(1.4rem, 1.2rem + 1.2vw, 1.9rem);
    --step-3: clamp(2rem, 1.5rem + 2.8vw, 3.25rem);   /* hero display size */

    accent-color: var(--brand);   /* native controls inherit the brand hue */
    color-scheme: light dark;
  }

  /* Animatable angle — powers the conic hover border below (Jhey-style delight). */
  @property --angle {
    syntax: "<angle>";
    inherits: false;
    initial-value: 0deg;
  }

  @media (prefers-color-scheme: dark) {
    :root {
      --surface: oklch(18% 0.01 90);
      --surface-raised: oklch(23% 0.012 90);
      --ink: oklch(93% 0.005 90);
      --ink-muted: oklch(65% 0.01 90);
      --line: oklch(32% 0.01 90);
      --brand-soft: oklch(from var(--brand) 28% 0.06 h);
      --brand-text: oklch(from var(--brand) 80% 0.1 h);
    }
  }

  /* NOTE: no global scroll-behavior:smooth — it animates every focus jump
     (dialog open/close) into a visible page glide. The hero anchor scrolls
     smoothly via JS instead. */

  html { scrollbar-gutter: stable; }    /* no layout shift when content grows a scrollbar */

  /* Freeze the page while any modal is open — no background scroll jumps. */
  body:has(dialog[open]) { overflow: hidden; }

  ::selection {
    background: color-mix(in oklch, var(--brand) 25%, transparent);
  }

  body {
    background: var(--surface);
    color: var(--ink);
    font-family: system-ui, sans-serif;
    font-size: var(--step-0);
    line-height: 1.6;
    text-wrap: pretty;              /* better paragraph rag, no orphans */

    /* Sticky footer without magic numbers — the main region soaks up spare height. */
    min-height: 100svh;
    display: grid;
    grid-template-rows: auto 1fr auto;
  }
}

/* ---------- components ---------- */
@layer components {

  .site-header {
    position: sticky;
    top: 0;
    z-index: 10;
    background: color-mix(in oklch, var(--surface) 88%, transparent);
    backdrop-filter: blur(8px);
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding-block: var(--space-3);
    padding-inline: var(--gutter);
    border-block-end: 1px solid var(--line);

    & .brand {
      font-size: var(--step-1);
      font-weight: 700;
      text-decoration: none;
      color: var(--ink);
      & span { color: var(--brand); }
    }

    /* Narrow phones: search wraps to its own full-width row. */
    flex-wrap: wrap;
    row-gap: var(--space-2);

    & search {
      flex: 1 1 12rem;
      & input {
        width: 100%;
        max-inline-size: 34rem;
        padding: var(--space-2) var(--space-3);
        border: 1px solid var(--line);
        border-radius: 999px;
        background: var(--surface-raised);
        color: var(--ink);
        &:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
      }
    }
  }

  /* Account dropdown: native popover + anchor positioning (tier 2 — default position set). */
  .account-btn {
    anchor-name: --account;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--surface-raised);
    color: var(--ink);
  }

  .menu {
    position: fixed;
    position-anchor: --account;
    top: anchor(bottom);
    right: anchor(right);
    margin-block-start: var(--space-1);
    min-inline-size: 12rem;
    padding: var(--space-2);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface-raised);
    display: none;
    flex-direction: column;

    &:popover-open { display: flex; }

    & a, & button {
      padding: var(--space-2) var(--space-3);
      border-radius: calc(var(--radius) - 4px);
      text-decoration: none;
      color: var(--ink);
      background: none;
      border: none;
      text-align: start;
      &:hover { background: var(--brand-soft); color: var(--brand-text); }
    }
  }

  .status-bar {
    font-size: 0.85em;
    padding: var(--space-2) var(--space-3);
    border-radius: var(--radius);
    margin-block-end: var(--space-3);
    background: var(--brand-soft);
    color: var(--brand-text);
    &[data-kind="ok"] { background: color-mix(in oklch, var(--success) 15%, transparent); color: var(--success); }
    &[data-kind="error"] { background: color-mix(in oklch, var(--danger) 15%, transparent); color: var(--danger); }
  }

  /* Dialogs trap their scroll — no page scroll bleeding through. */
  dialog, .menu { overscroll-behavior: contain; }

  /* One close button for every dialog. */
  dialog .dialog-close {
    position: absolute;
    inset-block-start: var(--space-2);
    inset-inline-end: var(--space-2);
    inline-size: 2rem;
    block-size: 2rem;
    display: grid;
    place-items: center;
    border: none;
    border-radius: 999px;
    background: color-mix(in oklch, var(--ink) 8%, transparent);
    color: var(--ink);
    &:hover { background: color-mix(in oklch, var(--ink) 14%, transparent); }
  }

  /* Hero — quiet confidence: one radial brand wash, big balanced type, two CTAs. */
  .hero {
    /* Fluid presence: grows from phone-quiet to desktop-grand, no breakpoints. */
    padding-block: clamp(2.25rem, 1.5rem + 4vw, 4.75rem);
    padding-inline: var(--gutter);
    display: grid;
    justify-items: center;
    gap: clamp(0.75rem, 0.55rem + 0.9vw, 1.35rem);
    text-align: center;
    background: radial-gradient(
      60rem 32rem at 50% -12rem,
      color-mix(in oklch, var(--brand) 9%, transparent),
      transparent 70%
    );

    & .eyebrow {
      font-size: 0.78em;
      font-weight: 600;
      letter-spacing: 0.09em;
      text-transform: uppercase;
      color: var(--brand-text);
    }

    & h1 {
      font-size: var(--step-3);
      font-weight: 700;
      line-height: 1.08;
      letter-spacing: -0.02em;
      text-wrap: balance;
    }

    & .hero-sub {
      color: var(--ink-muted);
      max-inline-size: 42ch;
      text-wrap: balance;
    }

    & .hero-actions {
      display: flex;
      flex-wrap: wrap;
      justify-content: center;
      gap: var(--space-2);
      margin-block-start: var(--space-2);

      & .primary { padding: var(--space-2) var(--space-4); }
    }

    & .trust-row {
      list-style: none;
      margin: var(--space-2) 0 0;
      padding: 0;
      display: flex;
      flex-wrap: wrap;
      justify-content: center;
      gap: var(--space-2) var(--space-3);
      color: var(--ink-muted);
      font-size: 0.85em;

      & li + li::before {
        content: "·";
        margin-inline-end: var(--space-3);
        color: var(--line);
      }
    }
  }

  /* Secondary CTA — bordered, calm. */
  .ghost {
    display: inline-block;
    padding: var(--space-2) var(--space-4);
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--surface-raised);
    color: var(--ink);
    font-weight: 600;
    text-decoration: none;
    transition: border-color 0.2s ease, color 0.2s ease;
    &:hover { border-color: var(--brand); color: var(--brand-text); }
  }

  .storefront {
    padding-block: var(--space-4);
    padding-inline: var(--gutter);
    max-inline-size: 72rem;
    margin-inline: auto;

    & .section-title {
      font-size: var(--step-2);
      text-wrap: balance;
      margin-block-end: var(--space-3);
    }
  }

  /* Category chips — quiet until chosen; the active chip inverts to ink. */
  .filter-bar {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-block-end: var(--space-4);

    & .chip {
      padding: calc(var(--space-1) + 2px) var(--space-3);
      border: 1px solid var(--line);
      border-radius: 999px;
      background: var(--surface-raised);
      color: var(--ink-muted);
      font-size: 0.88em;
      font-weight: 500;
      transition: border-color 0.2s ease, background 0.2s ease, color 0.2s ease;

      &:hover { border-color: var(--brand); color: var(--brand-text); }
      &:active { scale: 0.94; }               /* tactile squish */
      &[aria-pressed="true"] {
        background: var(--ink);
        border-color: var(--ink);
        color: var(--surface);
      }
    }
    & .chip { transition: border-color 0.2s ease, background 0.2s ease, color 0.2s ease, scale 0.15s ease; }
  }

  .empty-state {
    text-align: center;
    color: var(--ink-muted);
    padding-block: var(--space-5);
  }

  /* Legal pages (/terms, /privacy) — quiet reading layout. */
  .legal {
    max-inline-size: var(--measure);
    margin-inline: auto;
    padding-block: var(--space-4);
    padding-inline: var(--gutter);

    & h1 { font-size: var(--step-2); text-wrap: balance; }
    & h2 { font-size: var(--step-1); margin-block-start: var(--space-4); }
    & a { color: var(--brand-text); }
    & em { color: var(--ink-muted); }
  }

  /* Container-query grid. Intrinsic sizing: min(15rem, 100%) stops a single
     card overflowing a narrow container; auto-fill picks the column count. */
  .product-grid {
    container-type: inline-size;
    container-name: storefront;
    display: grid;
    gap: clamp(1.25rem, 1rem + 1.5vw, 2.25rem) clamp(0.8rem, 0.6rem + 1vw, 1.5rem);
    /* Column floor scales with the viewport: tighter on phones, roomier on desktop. */
    grid-template-columns: repeat(auto-fill, minmax(min(clamp(13rem, 11rem + 6vw, 16rem), 100%), 1fr));
  }

  /* SUBGRID: each card spans 5 parent row tracks and adopts them, so image /
     title / seller / price / button align across every card in a row — even
     when one title wraps to two lines. The card no longer defines its own rows. */
  .product-card {
    position: relative;
    display: grid;
    grid-row: span 5;
    grid-template-rows: subgrid;
    /* Container-query units: card content breathes with the CARD's context,
       not the viewport — 1cqi = 1% of the storefront container's inline size. */
    row-gap: clamp(0.45rem, 0.35rem + 0.5cqi, 0.85rem);
    align-content: start;
    padding: clamp(0.9rem, 0.7rem + 1.4cqi, 1.9rem);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface-raised);
    view-transition-name: auto;
    cursor: pointer;                     /* the whole card opens the detail view */
    transition: transform 0.25s ease, box-shadow 0.25s ease;

    &:hover {
      transform: translateY(-2px);
      box-shadow: 0 12px 30px -18px color-mix(in oklch, var(--brand) 45%, transparent);
    }

    & figure {
      border-radius: calc(var(--radius) - 4px);
      overflow: hidden;
      aspect-ratio: 4 / 3;
      background: var(--brand-soft);
      & img { inline-size: 100%; block-size: 100%; object-fit: cover; transition: scale 0.45s ease; }
    }
    &:hover figure img { scale: 1.04; }

    /* Fluid card type: scales with the container, clamped to sane bounds.
       Titles wrap freely (overflow-wrap catches unbroken words); the shared
       subgrid row track keeps cards aligned when a title needs more lines.
       NOTE: -webkit-box line-clamp rendered single-line in Pi Browser — avoid. */
    & h2 {
      font-size: clamp(0.92rem, 0.84rem + 0.5cqi, 1.08rem);
      font-weight: 600;
      text-wrap: balance;
      overflow-wrap: anywhere;
    }
    & .seller { color: var(--ink-muted); font-size: clamp(0.78rem, 0.72rem + 0.35cqi, 0.9rem); }
    & .price { font-weight: 700; color: var(--brand-text); align-self: end; font-size: clamp(0.95rem, 0.86rem + 0.55cqi, 1.15rem); }
    & .buy-btn { align-self: end; }
  }

  /* Subgrid needs the row tracks to live on the parent, so define them there.
     Fallback (no subgrid) → cards fall back to intrinsic auto rows gracefully. */
  @supports (grid-template-rows: subgrid) {
    .product-grid { grid-auto-rows: auto; }
  }

  /* Jhey-style animated gradient border, revealed on hover. Masked so only the
     1px ring shows. Pure decoration → aria-hidden by being a pseudo-element. */
  .product-card::before {
    content: "";
    position: absolute;
    inset: 0;
    padding: 1px;
    border-radius: inherit;
    background: conic-gradient(from var(--angle),
      transparent 55%, var(--brand) 80%, transparent 100%);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
            mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask-composite: exclude;
    opacity: 0;
    transition: opacity 0.3s ease;
    pointer-events: none;
  }
  .product-card:hover::before { opacity: 1; }

  @media (prefers-reduced-motion: no-preference) {
    .product-card:hover::before { animation: trace-border 3s linear infinite; }
  }
  @keyframes trace-border { to { --angle: 360deg; } }

  .buy-btn, .primary {
    padding: var(--space-2) var(--space-3);
    border: none;
    border-radius: 999px;
    background: var(--brand);
    color: oklch(99% 0.005 90);
    font-weight: 600;
    transition: background 0.2s ease, transform 0.12s ease, box-shadow 0.2s ease;
    &:hover {
      background: oklch(from var(--brand) calc(l - 0.06) c h);
      transform: translateY(-1px);
      box-shadow: 0 6px 16px -8px color-mix(in oklch, var(--brand) 70%, transparent);
    }
    &:active { transform: translateY(0) scale(0.97); }   /* the press */
    &:focus-visible { outline: 2px solid var(--brand-text); outline-offset: 2px; }
  }

  /* Signed-out state without JS class juggling: :has() on body. */
  body:not(:has(#username-label[data-authed])) .buy-btn::after {
    content: " · sign in";
    font-weight: 400;
    opacity: 0.8;
  }

  /* Modal dialogs (checkout, sell, detail, purchases) with @starting-style entry animation (tier 2). */
  #checkout-dialog,
  #sell-dialog,
  #edit-dialog,
  #detail-dialog,
  #purchases-dialog,
  #listings-dialog,
  #seller-dialog,
  #admin-dialog,
  #success-dialog {
    /* Pi Browser overlays its address bar on the TOP of the viewport but still
       reports that space as usable, so top-anchored/centered dialogs hide
       behind the bar. Fix: anchor toward the BOTTOM (margin-top auto pushes it
       down, small fixed margin-bottom) — the bottom edge is always chrome-free,
       so the whole card is visible and sits low on screen as asked. Height is
       capped generously so even a tall card's top clears the address bar. */
    margin-block: auto max(1.25rem, env(safe-area-inset-bottom, 0px) + 1rem);
    margin-inline: auto;
    max-block-size: 72svh;             /* fallback */
    max-block-size: calc(100svh - 8.5rem);
    overflow-y: auto;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface-raised);
    color: var(--ink);
    padding: var(--space-4);
    max-inline-size: 26rem;
    width: calc(100% - 2 * var(--space-4));

    opacity: 1;
    translate: 0 0;
    transition: opacity 0.25s ease, translate 0.25s ease, overlay 0.25s ease allow-discrete, display 0.25s ease allow-discrete;

    @starting-style {
      opacity: 0;
      translate: 0 0.75rem;
    }

    &::backdrop { background: oklch(15% 0.01 90 / 0.5); }

    & .checkout-total { font-size: var(--step-1); font-weight: 700; }
    & .dialog-actions {
      display: flex;
      justify-content: end;
      gap: var(--space-2);
      margin-block-start: var(--space-3);
      & button[value="cancel"],
      & button[type="button"] {
        background: none;
        border: 1px solid var(--line);
        border-radius: 999px;
        padding: var(--space-2) var(--space-3);
        color: var(--ink);
      }
    }
  }

  /* My purchases — quiet rows: thumb, title/meta, one action. */
  #purchases-dialog {
    max-inline-size: 32rem;
    position: relative;

    & h2 { font-size: var(--step-1); font-weight: 600; margin-block-end: var(--space-3); }
  }

  /* Purchase confirmation — the moment that must feel unmistakably done. */
  #success-dialog {
    max-inline-size: 24rem;
    position: relative;
    text-align: center;

    & .success-mark {
      inline-size: 3rem;
      block-size: 3rem;
      margin-inline: auto;
      display: grid;
      place-items: center;
      border-radius: 999px;
      background: color-mix(in oklch, var(--success) 15%, transparent);
      color: var(--success);
      font-size: 1.4rem;
      font-weight: 700;

      /* Jhey-style spring pop when the dialog opens (linear() easing;
         browsers without it just show the mark instantly — fine). */
      scale: 1;
      rotate: 0deg;
      transition:
        scale 0.6s linear(0, 0.4 25%, 1.12 50%, 0.95 70%, 1.02 85%, 1),
        rotate 0.6s ease;
      @starting-style {
        scale: 0;
        rotate: -14deg;
      }
    }

    & h2 { font-size: var(--step-1); font-weight: 600; margin-block-start: var(--space-2); }
    & #success-summary { color: var(--ink-muted); }

    & .success-download {
      display: inline-block;
      margin-block: var(--space-3);
      text-decoration: none;
      padding: var(--space-2) var(--space-4);
    }

    & .success-hint { color: var(--ink-muted); font-size: 0.85em; }
  }

  /* SUBGRID: the list owns three column tracks (thumb / info / action) and every
     row adopts them — thumbs, text and buttons align across rows regardless of
     title length, and the action column is exactly as wide as its widest button. */
  .purchase-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: auto 1fr auto;
    column-gap: clamp(0.6rem, 0.5rem + 0.6vw, 1.1rem);

    & .purchase-row {
      grid-column: 1 / -1;
      display: grid;
      grid-template-columns: subgrid;
      align-items: center;
      padding-block: clamp(0.7rem, 0.55rem + 0.7vw, 1.2rem);

      & + .purchase-row { border-block-start: 1px solid var(--line); }

      & img {
        border-radius: calc(var(--radius) - 6px);
        background: var(--brand-soft);
      }

      & div { min-inline-size: 0; }
      & .purchase-title { font-weight: 600; text-wrap: balance; overflow-wrap: anywhere; }
      & .purchase-meta { color: var(--ink-muted); font-size: 0.85em; overflow-wrap: anywhere; }
    }

    & .purchase-error {
      grid-column: 1 / -1;
      color: var(--danger);
      font-size: 0.9em;
      padding-block: var(--space-3);
    }
  }

  /* Admin panel. */
  #admin-dialog {
    max-inline-size: 34rem;
    position: relative;
    & h2 { font-size: var(--step-1); font-weight: 600; }
    & .admin-sub { color: var(--ink-muted); font-size: 0.85em; margin-block: var(--space-1) var(--space-3); }
    & #admin-status { font-size: 0.85em; color: var(--ink-muted); margin-block-end: var(--space-2); }
    & .purchase-row.is-delisted { opacity: 0.55; & img { filter: grayscale(1); } }
  }
  .admin-toggle {
    flex-shrink: 0;
    padding: var(--space-2) var(--space-3);
    border-radius: 999px;
    border: 1px solid var(--line);
    background: var(--surface-raised);
    color: var(--ink);
    font-weight: 600;
    font-size: 0.9em;
    &.danger { color: var(--danger); border-color: color-mix(in oklch, var(--danger) 40%, var(--line)); }
    &:hover { border-color: var(--brand); }
    &:disabled { opacity: 0.5; cursor: wait; }
  }

  /* Trust: sold counts + seller profile. */
  .sold-count { color: var(--success); font-weight: 600; }

  .seller-link {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    color: var(--brand-text);
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
  }

  #seller-dialog {
    max-inline-size: 32rem;
    position: relative;
    & h2 { font-size: var(--step-1); font-weight: 600; }
    & .seller-stats { color: var(--ink-muted); font-size: 0.85em; margin-block: var(--space-1) var(--space-3); }
    & .seller-item { cursor: pointer; }
  }

  /* My listings shares purchase-row bones; delisted rows fade. */
  #listings-dialog { max-inline-size: 32rem; position: relative;
    & h2 { font-size: var(--step-1); font-weight: 600; margin-block-end: var(--space-3); }
  }

  /* Seller earnings + withdraw — the payout moment gets brand emphasis. */
  .earnings-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-3);
    margin-block-end: var(--space-2);
    border-radius: var(--radius);
    background: var(--brand-soft);

    & .earnings-label { display: block; font-size: 0.8em; color: var(--brand-text); }
    & .earnings-balance { font-size: var(--step-1); color: var(--brand-text); }
  }
  .earnings-note {
    font-size: 0.82em;
    color: var(--ink-muted);
    margin-block-end: var(--space-3);
    &[data-kind="ok"] { color: var(--success); }
    &[data-kind="error"] { color: var(--danger); }
  }

  .purchase-row.is-delisted {
    opacity: 0.55;
    & img { filter: grayscale(1); }
  }

  .toggle-listing {
    flex-shrink: 0;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--surface-raised);
    color: var(--ink);
    font-weight: 600;
    font-size: 0.9em;
    transition: border-color 0.2s ease, background 0.2s ease;
    &:hover { border-color: var(--brand); color: var(--brand-text); }
    &:disabled { opacity: 0.5; cursor: wait; }
  }

  .label-hint { font-weight: 400; color: var(--ink-muted); }

  .download-again {
    flex-shrink: 0;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--line);
    border-radius: 999px;
    font-weight: 600;
    font-size: 0.9em;
    text-decoration: none;
    color: var(--brand-text);
    transition: border-color 0.2s ease, background 0.2s ease;
    &:hover { border-color: var(--brand); background: var(--brand-soft); }
  }

  /* Product detail dialog. */
  /* Detail opens as a FULL-SCREEN sheet — fills the whole viewport so no
     browser/PiNet chrome can ever cover it. Overrides the shared centered
     sizing above (same specificity, declared later → wins). */
  #detail-dialog {
    inset: 0;
    margin: 0;
    inline-size: 100%;
    max-inline-size: 100%;
    block-size: 100svh;
    max-block-size: 100svh;
    border: none;
    border-radius: 0;
    padding: var(--space-4);
    padding-block-start: max(var(--space-4), env(safe-area-inset-top, 0px) + var(--space-3));
    position: fixed;              /* fill the viewport; close ✕ anchors to it */

    /* Center card content vertically via auto margins — but ONLY when open.
       display MUST stay tied to [open]: putting display:flex on the base rule
       overrides the UA `dialog:not([open]){display:none}` and leaves the empty
       sheet covering the whole storefront. */
    &[open] { display: flex; flex-direction: column; }
    & .detail { margin-block: auto; width: 100%; }

    & figure {
      border-radius: calc(var(--radius) - 4px);
      overflow: hidden;
      aspect-ratio: 4 / 3;
      max-block-size: 40svh;         /* cover never dominates the sheet */
      background: var(--brand-soft);
      margin-block-end: var(--space-3);
      & img { inline-size: 100%; block-size: 100%; object-fit: cover; }
    }

    & h2 { font-size: var(--step-1); font-weight: 600; text-wrap: balance; overflow-wrap: anywhere; }
    & .seller { color: var(--ink-muted); font-size: 0.85em; margin-block-end: var(--space-2); }
    & .detail-meta {
      display: inline-flex;
      align-self: start;
      gap: var(--space-2);
      margin-block-end: var(--space-2);
      padding: var(--space-1) var(--space-3);
      border-radius: 999px;
      background: var(--brand-soft);
      color: var(--brand-text);
      font-size: 0.8em;
      font-weight: 600;
      letter-spacing: 0.02em;
    }
    & .detail-desc { color: var(--ink-muted); max-inline-size: var(--measure); }

    & .detail-previews {
      margin-block-start: var(--space-3);
      & .preview-label {
        font-size: 0.78em;
        font-weight: 600;
        letter-spacing: 0.04em;
        text-transform: uppercase;
        color: var(--ink-muted);
        margin-block-end: var(--space-2);
      }
      & .preview-strip {
        display: flex;
        gap: var(--space-2);
        flex-wrap: wrap;
      }
      & .preview-thumb {
        inline-size: clamp(4.5rem, 22cqi, 7rem);
        aspect-ratio: 4 / 3;
        border-radius: calc(var(--radius) - 4px);
        overflow: hidden;
        border: 1px solid var(--line);
        background: var(--brand-soft);
        & img { inline-size: 100%; block-size: 100%; object-fit: cover; }
        &:hover { border-color: var(--brand); }
      }
    }

    & .detail-foot {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--space-3);
      margin-block-start: var(--space-3);
      & .price { font-size: var(--step-1); font-weight: 700; color: var(--brand-text); }
    }
  }

  /* Edit dialog shares the sell-form field styling. */
  .listing-actions {
    display: flex;
    gap: var(--space-2);
    flex-shrink: 0;
  }
  .edit-listing {
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--surface-raised);
    color: var(--ink);
    font-weight: 600;
    font-size: 0.9em;
    transition: border-color 0.2s ease, background 0.2s ease;
    &:hover { border-color: var(--brand); color: var(--brand-text); }
  }

  /* Sell form: labels stack their controls; fields match the search input's look. */
  #sell-form, #edit-form {
    --flow-space: var(--space-3);

    & label {
      display: grid;
      gap: var(--space-1);
      font-weight: 600;
      font-size: 0.9em;
    }

    & input:not([type="file"]),
    & textarea {
      font: inherit;
      padding: var(--space-2) var(--space-3);
      border: 1px solid var(--line);
      border-radius: calc(var(--radius) - 4px);
      background: var(--surface);
      color: var(--ink);
      &:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
    }

    & textarea { resize: vertical; }

    & input[type="file"] { font-size: 0.9em; }

    & #sell-status, & #edit-status {
      font-size: 0.85em;
      padding: var(--space-2) var(--space-3);
      border-radius: calc(var(--radius) - 4px);
      background: var(--brand-soft);
      color: var(--brand-text);
      &[data-kind="error"] { background: color-mix(in oklch, var(--danger) 15%, transparent); color: var(--danger); }
    }
  }

  /* Forms (seller onboarding etc.): validity styling only after interaction. */
  input:user-invalid { border-color: var(--danger); }
  input:user-valid { border-color: var(--success); }

  .site-footer {
    padding: var(--space-4);
    border-block-start: 1px solid var(--line);
    color: var(--ink-muted);
    & a { color: var(--brand-text); }
  }

  /* ---- micro-interactions ---- */

  /* One consistent, accessible focus ring for every interactive element. */
  a:focus-visible,
  [popovertarget]:focus-visible,
  .product-card:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 3px;
    border-radius: 4px;
  }
  .product-card:focus-visible { border-radius: var(--radius); }

  /* Hero eases in on first paint — staggered, reduced-motion guarded. */
  @media (prefers-reduced-motion: no-preference) {
    .hero > * {
      opacity: 1;
      translate: 0 0;
      transition: opacity 0.55s ease, translate 0.55s ease;
      @starting-style {
        opacity: 0;
        translate: 0 0.6rem;
      }
    }
    .hero > :nth-child(2) { transition-delay: 0.05s; }
    .hero > :nth-child(3) { transition-delay: 0.1s; }
    .hero > :nth-child(4) { transition-delay: 0.15s; }
    .hero > :nth-child(5) { transition-delay: 0.2s; }
  }

  /* Links grow a soft underline instead of snapping one on. */
  .site-footer a,
  .menu a {
    text-decoration: underline;
    text-decoration-color: transparent;
    text-underline-offset: 3px;
    transition: text-decoration-color 0.2s ease;
    &:hover { text-decoration-color: currentColor; }
  }

  /* Brand mark: the accent letter breathes on hover. */
  .brand {
    & span { color: var(--brand); transition: scale 0.2s ease; display: inline-block; }
    &:hover span { scale: 1.15; }
  }

  /* Search field lifts subtly into focus. */
  .site-header search input {
    transition: box-shadow 0.2s ease, border-color 0.2s ease;
    &:focus-visible {
      border-color: var(--brand);
      box-shadow: 0 0 0 4px color-mix(in oklch, var(--brand) 18%, transparent);
    }
  }

  /* Account menu doesn't just appear — it eases in (popover + @starting-style). */
  .menu {
    transition: opacity 0.18s ease, translate 0.18s ease,
                overlay 0.18s ease allow-discrete, display 0.18s ease allow-discrete;
    opacity: 1;
    translate: 0 0;
    &:not(:popover-open) { opacity: 0; }
    @starting-style { opacity: 0; translate: 0 -0.4rem; }
  }

  /* Status bar gently pulses while a step is in progress. */
  @media (prefers-reduced-motion: no-preference) {
    .status-bar[data-kind="info"] { animation: status-pulse 1.4s ease-in-out infinite; }
    @keyframes status-pulse { 50% { opacity: 0.62; } }
  }
}

/* ---------- utilities ---------- */
@layer utilities {
  .visually-hidden {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* Flow ("lobotomized owl") — even vertical rhythm between siblings, no per-element margins. */
  .flow > * + * { margin-block-start: var(--flow-space, 1em); }

  /* Constrain prose to a comfortable measure. */
  .measure { max-inline-size: var(--measure); }
}

/* Tier 3 enhancement: scroll-driven card reveal. Chromium + WebKit only; harmless elsewhere. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .product-card {
      animation: card-in linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 40%;
    }
    @keyframes card-in {
      from { opacity: 0; transform: translateY(0.75rem); }
      to { opacity: 1; transform: none; }
    }
  }
}

/* Tier 3: header earns a shadow only after you scroll past the top. */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .site-header {
      animation: header-lift linear both;
      animation-timeline: scroll(root);
      animation-range: 0 120px;
    }
    @keyframes header-lift {
      to {
        box-shadow: 0 6px 22px -14px color-mix(in oklch, var(--ink) 55%, transparent);
        border-block-end-color: transparent;
      }
    }
  }
}
