/* ==========================================================================
   Pro Auction — Base element styles
   Every value derives from tokens.css. No literal hex or px below except
   hairline widths (1px) and the 4px-base values already tokenised.
   ========================================================================== */

body {
  background: var(--paper);
  color: var(--slate);
  font-family: var(--font-ui);
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}

/* --- Mobile safeguards ---------------------------------------------------
   The page body must never scroll sideways. Wide content gets its own
   overflow container instead; these are the backstops for anything that
   slips through — long lot titles, pasted URLs, embeds, oversized media. */
/* `overflow-x: hidden` on html alone does not clip an overflow that
   originates on body — measured at 320px, the page still scrolled 9px.
   `clip` on body catches it, and unlike `hidden` it does not create a scroll
   container, so the sticky header keeps working. */
html { overflow-x: hidden; }
body { overflow-x: clip; }

img, svg, video, canvas, iframe, embed, object {
  max-width: 100%;
  height: auto;
}

/* Long unbroken strings (BidSpirit lot references, URLs in pasted copy)
   would otherwise force the viewport wider than the screen. */
h1, h2, h3, h4, h5, h6, p, li, td, th, dd, dt, figcaption, address {
  overflow-wrap: break-word;
}

/* Tables are the most common source of horizontal overflow on mobile. */
table { max-width: 100%; }

/* iOS zooms the page when a focused input is under 16px. Inputs use
   --fs-base (17px) so this does not happen; this guard keeps it true if a
   plugin injects its own fields. */
input, select, textarea { font-size: max(16px, 1rem); }

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-heading);
  color: var(--ink);
  text-wrap: balance;
}

h1 { font-size: var(--fs-3xl); letter-spacing: -.01em; }
h2 { font-size: var(--fs-2xl); }
h3 { font-size: var(--fs-xl); }
h4 { font-size: var(--fs-lg); }

p { max-width: var(--measure); }

a { color: var(--brand-deep); }
a:hover { color: var(--ink); }

/* --- Layout §4.4 --------------------------------------------------------- */
.shell   { max-width: var(--shell-max);   margin-inline: auto; }
.content { max-width: var(--content-max); margin-inline: auto;
           padding-inline: var(--gutter); }

/* --- Eyebrow / label §4.3 ------------------------------------------------
   Section eyebrows and lot metadata labels only. */
.eyebrow {
  font-family: var(--font-ui);
  font-weight: var(--fw-medium);
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--muted);
}

/* --- Tabular figures §4.3 ------------------------------------------------
   Non-negotiable on every price, estimate, lot number, countdown and results
   cell: proportional figures make countdowns jitter as they tick and make
   columns of money fail to align. */
.u-tnum,
.lot-number, .lot-estimate, .lot-current-bid, .lot-hammer,
.countdown, .stat-figure,
.results-table td, .results-table th {
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
}

/* --- Focus §10 -----------------------------------------------------------
   Ring inverts on dark surfaces — see the [ADDED] note in tokens.css. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: var(--focus-width) solid var(--focus);
  outline-offset: var(--focus-offset);
}
.on-ink :where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline-color: var(--focus-on-dark);
}

/* Dark regions (hero scrim, footer, lot-number tab) opt in with .on-ink. */
.on-ink { background: var(--ink); color: var(--paper); }
.on-ink :where(h1, h2, h3, h4, h5, h6) { color: var(--paper); }
.on-ink .eyebrow { color: var(--steel); }
.on-ink a { color: var(--paper); }

/* --- Visually hidden, still announced -----------------------------------
   For headings that structure the document but would be redundant on screen,
   e.g. the footer's company heading where the logo already says it. */
.screen-reader-text {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.screen-reader-text:focus-visible {
  position: static;
  width: auto;
  height: auto;
  margin: 0;
  clip-path: none;
  white-space: normal;
}

/* --- Skip link §10 ------------------------------------------------------- */
.skip-link {
  position: absolute;
  left: var(--s-2);
  top: var(--s-2);
  z-index: var(--z-toast);
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: var(--s-2) var(--s-4);
  background: var(--ink);
  color: var(--paper);
  border-radius: var(--r-sm);
  transform: translateY(-200%);
}
.skip-link:focus { transform: translateY(0); }

/* --- Status chips §4.1 ---------------------------------------------------
   Red is reserved exclusively for live/urgent auction state. Never for form
   errors on a bidding page, where it would read as "bid failed" (§4.2). */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: var(--s-1) var(--s-2);
  border-radius: var(--r-sm);
  white-space: nowrap;
}
.chip--live { background: var(--live); color: var(--white); }
.chip--sold { background: var(--sold); color: var(--white); }
.chip--open { background: transparent; color: var(--muted);
              border: 1px solid var(--line); }

/* §4.2: error text is ink with an icon, never red, on any bidding path. */
.form-error { color: var(--ink); display: flex; gap: var(--s-2);
              align-items: flex-start; }

/* --- Hairline rules §4.4 -------------------------------------------------
   Borders do the work of elevation; the one shadow token is for overlays. */
.rule       { border: 0; border-top: 1px solid var(--line); }
.rule--brass{ border: 0; border-top: 2px solid var(--steel); width: var(--s-16); }
.overlay    { box-shadow: var(--shadow-overlay); }

/* --- Reveal §4.5 ---------------------------------------------------------
   12px rise + fade, staggered across grid children, once only.

   Scoped to .js, which an inline script in <head> sets. Without that scope a
   failed or blocked script leaves opacity:0 on every revealed element and the
   page renders empty below the fold — content must never depend on JS to be
   visible. The .js class is set before first paint, so there is no flash. */
.js .reveal {
  opacity: 0;
  transform: translateY(var(--reveal-rise));
  transition: opacity var(--dur-reveal) var(--ease-out),
              transform var(--dur-reveal) var(--ease-out);
}
.js .reveal.is-in { opacity: 1; transform: none; }

/* --- Reduced motion §4.5 -------------------------------------------------
   Must disable Lenis, kill GSAP tweens to their end state, and remove
   transforms. The JS reads the same query; CSS covers the rest. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .js .reveal { opacity: 1 !important; transform: none !important; }
}
