/* Romanotto — monochrome design system.
   White walls, black ink, black buttons; the only color on any page is the
   artwork itself. Status reads through weight, fill, and glyph, not hue. */

@font-face {
  font-family: "IBM Plex Serif";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/static/fonts/plex-serif-500.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Serif";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/static/fonts/plex-serif-600.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/plex-sans-400.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/plex-mono-400.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/static/fonts/plex-mono-500.woff2") format("woff2");
}

:root {
  --bg: #FFFFFF;
  --bg-alt: #F6F6F4;
  --surface: #FFFFFF;
  --ink: #111111;
  /* The grey ramp is set by the AA floor, not by taste. Measured on the two
     backgrounds these ever sit on (#FFFFFF and --wash #F6F6F4):
       --ink-muted  6.8:1 / 6.3:1   secondary prose, labels, sub-lines
       --ink-faint  5.0:1 / 4.7:1   eyebrows, table heads, small captions
     The previous pair (#6B6B67 / #A6A59E) left --ink-faint at 2.5:1 on
     white — every eyebrow, column head and fact label in the app sat below
     the 4.5:1 floor. --ink-muted darkens with it so the two steps stay
     legible against each other, and lands where the landing page's ramp
     already had to be corrected to. */
  --ink-muted: #5C5B56;
  --ink-faint: #706F69;
  --border: #E4E3DE;
  /* The boundary of a control the user has to find (input, select, chip,
     ghost button), so WCAG 1.4.11 asks 3:1 against the page: this is
     3.24:1. --border above stays hairline-pale — it only ever draws row
     rules and dividers, which are decoration. */
  --border-strong: #918F88;
  --wash: #F6F6F4;
  --error: #8A2D23;
  --error-wash: #F7ECEA;

  --shadow-sm: 0 1px 2px rgba(17, 17, 17, 0.05);
  --shadow-md: 0 6px 20px rgba(17, 17, 17, 0.08), 0 1px 3px rgba(17, 17, 17, 0.05);
  --shadow-lg: 0 16px 40px rgba(17, 17, 17, 0.12), 0 4px 10px rgba(17, 17, 17, 0.06);

  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 16px;
  --radius-pill: 999px;
}

* { box-sizing: border-box; }
html { color-scheme: light; -webkit-text-size-adjust: 100%; }
a, button, .btn { -webkit-tap-highlight-color: transparent; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: "IBM Plex Serif", Georgia, serif;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-wrap: balance;
  margin: 0;
}

.mono {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
}

/* Measurements. Mono is for figures a reader scans down a column and
   compares — prices, catalogue numbers. "30 x 36 cm" is a phrase, with a
   separator and a unit in it, and setting it in Plex Mono makes it read
   like source code rather than a dimension. Proportional face, but Plex
   Sans's tabular figures, so a column of them still lines up. */
.dims, .num { font-variant-numeric: tabular-nums; }

a { color: inherit; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

.eyebrow {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* ---------- Shell ---------- */
.page { max-width: 1180px; margin: 0 auto; padding: 2rem 2rem 6rem; }

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.1rem 2rem;
  /* Opaque enough that scrolled content can't ghost through where
     backdrop-filter isn't supported. */
  background: rgba(255, 255, 255, 0.95);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border);
  padding-top: calc(1.1rem + env(safe-area-inset-top));
}

.wordmark {
  font-family: "IBM Plex Serif", serif;
  font-weight: 600;
  font-size: 1.05rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  color: inherit;
}

.nav-links { display: flex; align-items: center; gap: 1.75rem; }
.nav-link {
  text-decoration: none; font-size: 0.86rem; font-weight: 500; color: var(--ink-muted);
  padding: 0.4rem 0;
  border-bottom: 1px solid transparent;
}
.nav-link.active { color: var(--ink); border-bottom-color: var(--ink); }

/* ---------- Bottom tab bar (phone only) ---------- */
.tabbar {
  display: none;
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 30;
  background: rgba(255, 255, 255, 0.95);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-top: 1px solid var(--border);
  padding: 0.4rem 0 calc(0.4rem + env(safe-area-inset-bottom));
}
.tab {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; gap: 0.15rem;
  padding: 0.35rem 0;
  min-height: 44px;
  text-decoration: none;
  font-size: 0.62rem; font-weight: 600; letter-spacing: 0.04em;
  color: var(--ink-faint);
}
.tab svg { display: block; }
.tab.active { color: var(--ink); }

.breadcrumb { font-size: 0.8rem; color: var(--ink-faint); display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.breadcrumb a { color: var(--ink-muted); text-decoration: none; }
.breadcrumb a:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.crumb-sep { color: var(--border-strong); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.45rem;
  font-family: "IBM Plex Sans", sans-serif; font-weight: 600; font-size: 0.84rem;
  letter-spacing: 0.02em;
  padding: 0.65rem 1.3rem; border-radius: var(--radius-pill);
  border: 1px solid transparent; cursor: pointer; text-decoration: none;
  background: var(--ink); color: var(--bg);
  box-shadow: var(--shadow-sm);
  transition: transform 0.12s ease, box-shadow 0.12s ease, opacity 0.12s ease, background 0.12s ease;
  white-space: nowrap;
}
.btn:hover { opacity: 0.82; box-shadow: var(--shadow-md); }
.btn:active { transform: scale(0.97); }
.btn[disabled] { opacity: 0.5; cursor: not-allowed; box-shadow: none; }
.btn-ghost { background: transparent; color: var(--ink); border-color: var(--border-strong); box-shadow: none; }
.btn-ghost:hover { background: var(--wash); border-color: var(--ink-faint); opacity: 1; }
.btn-sm { padding: 0.42rem 0.9rem; font-size: 0.76rem; }
.link-button {
  font: inherit; font-size: 0.8rem; background: none; border: none; cursor: pointer;
  color: var(--ink-muted); text-decoration: underline; text-underline-offset: 3px; padding: 0;
}
.link-button:hover { color: var(--ink); }
/* Destructive, and quiet until it is pointed at: six rows of red "Remove"
   down a table reads as six errors. */
.link-danger:hover, .link-danger:focus-visible { color: var(--error); }

/* Available to a screen reader, absent to everyone else — a column of row
   actions needs a heading that the layout has no room to print. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ---------- Stat strip ---------- */
.stat-strip {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 2.75rem;
  padding: 0.5rem 0 2rem;
  border-bottom: 1px solid var(--border);
  margin-bottom: 3rem;
}
.stat { display: flex; align-items: baseline; gap: 0.55rem; }
.stat-value { font-family: "IBM Plex Serif", serif; font-size: 1.7rem; font-weight: 600; }
.stat-label { font-size: 0.76rem; color: var(--ink-muted); }

/* ---------- Section heading ---------- */
.section-head {
  display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem;
  margin: 0 0 1.5rem;
}
.section-head h1 { font-size: 1.9rem; }
.section-head h2 { font-size: 1.3rem; }
.section-meta { margin: 0; font-size: 0.84rem; color: var(--ink-muted); }
.section-title-row {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  flex-wrap: wrap; align-self: stretch;
}
.section-row { display: flex; align-items: baseline; justify-content: space-between; width: 100%; gap: 1rem; flex-wrap: wrap; }
.see-all { font-size: 0.82rem; color: var(--ink); text-decoration: underline; text-underline-offset: 3px; font-weight: 500; }

/* ---------- Collections index ---------- */
.collection-list { border-top: 1px solid var(--ink); }
.collection-row {
  display: flex; align-items: center; gap: 1.5rem;
  padding: 1.35rem 0.5rem;
  border-bottom: 1px solid var(--border);
  text-decoration: none; color: inherit;
  transition: background 0.12s ease;
}
.collection-row:hover { background: var(--wash); }
.collection-row-main { flex: 1; min-width: 0; }
.collection-name { font-family: "IBM Plex Serif", serif; font-size: 1.15rem; font-weight: 600; }
.collection-client { font-size: 0.82rem; color: var(--ink-muted); margin-top: 0.15rem; }
.collection-figures {
  display: flex; flex-direction: column; align-items: flex-end; gap: 0.15rem;
  font-size: 0.85rem; font-variant-numeric: tabular-nums;
}
.collection-figures .count { color: var(--ink-muted); font-size: 0.78rem; }
.collection-total .cur { color: var(--ink-faint); font-size: 0.72rem; margin-right: 0.15rem; }
.row-chevron { color: var(--ink-faint); font-size: 1.1rem; }
.collection-row:hover .row-chevron { color: var(--ink); }

/* ---------- Chips ---------- */
.chip {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-size: 0.72rem; font-weight: 600; letter-spacing: 0.02em;
  padding: 0.28rem 0.7rem; border-radius: var(--radius-pill);
  border: 1px solid var(--border-strong); color: var(--ink-muted); background: var(--bg);
}
.chip-solid { background: var(--ink); color: var(--bg); border-color: var(--ink); }
.chip-glyph { font-family: "IBM Plex Mono", monospace; font-size: 0.82rem; line-height: 1; }

/* ---------- Catalog (salon hang) ---------- */
.catalog-grid { columns: 3 240px; column-gap: 1.75rem; }
.piece-card {
  display: block; width: 100%; margin-bottom: 2.5rem;
  break-inside: avoid; -webkit-column-break-inside: avoid;
  text-decoration: none; color: inherit;
}
.piece-thumb {
  position: relative; border-radius: var(--radius-md); overflow: hidden;
  box-shadow: var(--shadow-sm); transition: box-shadow 0.2s ease;
  line-height: 0;
}
.piece-thumb img { width: 100%; height: auto; display: block; }
.piece-card:hover .piece-thumb { box-shadow: var(--shadow-lg); }
.no-image {
  aspect-ratio: 4 / 3; display: flex; align-items: center; justify-content: center;
  background: var(--wash); color: var(--ink-faint); font-size: 0.82rem;
  border-radius: var(--radius-md); border: 1px solid var(--border);
}
.piece-card-body { padding: 0.95rem 0.15rem 0; display: flex; flex-direction: column; gap: 0.35rem; }
.piece-title { font-family: "IBM Plex Serif", serif; font-style: italic; font-size: 1.04rem; font-weight: 500; line-height: 1.3; }
.piece-artist { font-size: 0.74rem; color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.06em; }
.piece-meta-row {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 0.45rem 0.75rem; margin-top: 0.35rem;
}
.piece-value { font-family: "IBM Plex Mono", monospace; font-size: 0.85rem; font-weight: 500; font-variant-numeric: tabular-nums; }
.piece-value .cur { color: var(--ink-faint); font-size: 0.7rem; margin-right: 0.15rem; }

/* ---------- Piece page ---------- */
.plate-number {
  font-family: "IBM Plex Mono", monospace; font-size: 0.78rem; letter-spacing: 0.06em;
  color: var(--ink-faint); margin: 0.75rem 0 0.6rem;
}
.work-title { font-style: italic; font-weight: 500; font-size: 2rem; }
.work-artist {
  font-size: 0.86rem; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--ink-muted); margin-top: 0.4rem;
}
.hero-frame {
  width: 100%; border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md); overflow: hidden; margin-top: 1.6rem;
  line-height: 0;
}
.hero-frame img { width: 100%; height: auto; display: block; }

.dossier {
  display: grid; grid-template-columns: 260px 1fr; gap: 2.5rem; align-items: start;
  margin-top: 2.25rem;
}
.dossier-main, .dossier-rail { min-width: 0; }
.dossier-rail {
  position: sticky; top: 96px;
  border-top: 1px solid var(--ink);
  padding-top: 1.1rem;
  display: flex; flex-direction: column; gap: 1.1rem;
}
.fact { display: flex; flex-direction: column; gap: 0.2rem; }
.fact-label { font-size: 0.68rem; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase; color: var(--ink-faint); }
.fact-value { font-size: 0.92rem; overflow-wrap: anywhere; }

.views-label {
  font-size: 0.68rem; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--ink-faint); margin: 0 0 0.9rem;
}
.photo-strip { display: flex; gap: 0.9rem; overflow-x: auto; padding-bottom: 0.3rem; }
.photo-strip img {
  height: 170px; width: auto; border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm); display: block;
}

.subsection { margin-top: 2.75rem; }
.subsection-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-bottom: 1rem; flex-wrap: wrap; }
.subsection-head h2 { font-size: 1.15rem; }
.comp-cta { display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap; }

/* ---------- Data table ---------- */
.data-table-wrap { overflow-x: auto; border-top: 1px solid var(--ink); }
table.data-table { width: 100%; border-collapse: collapse; font-size: 0.86rem; }
.data-table th {
  text-align: left; font-size: 0.68rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-faint); padding: 0.85rem 0.9rem; border-bottom: 1px solid var(--border);
}
.data-table td { padding: 0.9rem; border-bottom: 1px solid var(--border); vertical-align: top; }
.data-table tbody tr:hover { background: var(--wash); }
/* Sub-lines carry words — a price type, a source, "observed" — so they
   take the proportional face even inside a mono cell. */
.cell-sub {
  color: var(--ink-muted); font-size: 0.8rem;
  font-family: "IBM Plex Sans", sans-serif;
}
/* The key marker hangs in the cell's padding gutter so titles keep one
   left edge whether or not a row is flagged. */
/* The title is what the row is; it gets first claim on the slack, and the
   medium wraps instead. Left to itself the browser gave both the same
   width and broke five-word titles over five lines. */
.data-table .c-title { min-width: 11.5rem; }
td.c-title { position: relative; }
.key-mark { font-size: 0.7rem; position: absolute; left: 0.05rem; top: 1.15rem; }
.comp-stats {
  margin: 0 0 0.9rem; font-size: 0.8rem; color: var(--ink-muted);
}
.comp-stats .mono { font-size: 0.78rem; }

/* Market context: per-year lot count + median from the comps on file. */
/* No outer margin of its own — it always sits inside a .context-block, and
   carrying a second bottom margin left the block sitting off-centre in the
   accordion, with half again as much air under the last line as over the
   first one. */
.market-context { margin: 0; }
/* The paragraphs under the series read against the table's closing rule, so
   they clear it by more than they clear each other. At the paragraph gap
   they looked stuck to it. */
.market-context .context-table { margin-bottom: 1.3rem; }
/* Primary content: the ink the rest of the page uses, at the size the rest
   of the page uses. Only the source line above it stays quiet. */
.market-context p { color: var(--ink); font-size: 0.9rem; margin: 0 0 0.9rem; }
.market-context p:last-child { margin-bottom: 0; }
.market-context .eyebrow { display: block; margin-bottom: 0.5rem; }
.context-table { border-collapse: collapse; font-size: 0.84rem; width: 100%; table-layout: fixed; }
.context-table th {
  font-size: 0.65rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-faint); text-align: left; padding: 0.4rem 1rem 0.4rem 0;
  border-bottom: 1px solid var(--border);
}
.context-table td { padding: 0.7rem 1rem 0.7rem 0; border-bottom: 1px solid var(--border); }
/* Year, lots and median start at the same x in both tables. The two carry
   different column counts — the comps table has three, the artist series
   adds a normalized fourth — so an even split put their shared columns in
   different places and the two sat one above the other not lining up.
   Pinning the first two leaves the rest to share what remains, which keeps
   the median's left edge at 40% in both. */
.context-table th:nth-child(1), .context-table td:nth-child(1) { width: 20%; }
.context-table th:nth-child(2), .context-table td:nth-child(2) { width: 20%; }

/* Artist disambiguation candidates (picker page + search page). */
.candidate-list { display: flex; flex-direction: column; }
.candidate-row {
  display: flex; align-items: baseline; gap: 0.65rem; padding: 0.7rem 0.2rem;
  border-bottom: 1px solid var(--border); text-decoration: none; color: inherit;
}
.candidate-row:last-child { border-bottom: none; }
a.candidate-row:hover .candidate-name { text-decoration: underline; }
.candidate-name { font-weight: 600; font-size: 0.92rem; }
.candidate-meta { color: var(--ink-muted); font-size: 0.8rem; }

.fact-sub { display: block; color: var(--ink-faint); font-size: 0.72rem; margin-top: 0.15rem; }
.inline-form { display: inline; }
.inline-form .link-button { font-size: 0.72rem; }

/* Photo management strip on the dossier. */
.photo-item { display: flex; flex-direction: column; gap: 0.35rem; margin: 0; flex-shrink: 0; }
.photo-tools { display: flex; align-items: center; gap: 0.6rem; font-size: 0.72rem; }
.photo-tools .link-button { font-size: 0.72rem; }
.photo-hero-tag {
  font-size: 0.62rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-muted); border: 1px solid var(--border-strong); border-radius: var(--radius-pill);
  padding: 0.05rem 0.5rem;
}
img.lightboxable { cursor: zoom-in; }
.lightbox {
  position: fixed; inset: 0; z-index: 100; background: rgba(20, 19, 18, 0.92);
  display: flex; align-items: center; justify-content: center; cursor: zoom-out; padding: 4vmin;
}
/* display:flex above would otherwise beat the UA's [hidden] rule. */
.lightbox[hidden] { display: none; }
.lightbox img { max-width: 100%; max-height: 100%; box-shadow: 0 12px 60px rgba(0,0,0,0.5); }

/* Catalog-wall pagination. */
.pager { display: flex; align-items: center; gap: 1rem; justify-content: center; margin: 2rem 0 0.5rem; }
.pager-label { font-size: 0.78rem; color: var(--ink-muted); }

/* Report options: per-report piece picker. */
.report-piece-picker { display: flex; flex-direction: column; }
.picker-row {
  display: flex; align-items: baseline; gap: 0.65rem; padding: 0.45rem 0.1rem;
  border-bottom: 1px solid var(--border); font-size: 0.88rem;
}
.picker-row:last-child { border-bottom: none; }
.picker-row .mono { font-size: 0.76rem; color: var(--ink-muted); }

/* Camera + file-picker pair on the new-piece form. */
.dropzone-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
@media (max-width: 640px) { .dropzone-row { grid-template-columns: 1fr; } }

/* Destructive actions: same quiet ghost button, unmistakably marked. */
/* Border darkened from #c9a29b (2.3:1) to clear the 3:1 asked of a control
   boundary; the ink is unchanged. */
.btn-danger { color: #8c2f22; border-color: #b0887f; }
.btn-danger:hover { background: #f7ece9; }

/* Archived engagements: present but visually closed. */
/* The fade cannot go below the point where the row's own secondary text
   drops under 4.5:1 — at 0.65 the client line measured 3.2:1. The fade is
   the weaker cue anyway: these rows sit under their own "Archived
   engagements" heading and each one carries its archived date. */
.archived-list .collection-row { opacity: 0.85; }
.archived-list .collection-row:hover { opacity: 1; }

/* Terms / privacy prose pages. */
.prose-page { max-width: 62ch; }
.prose-page h2 {
  font-size: 0.78rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-muted); margin: 1.8rem 0 0.6rem;
}
.prose-page p, .prose-page li { font-size: 0.92rem; line-height: 1.65; margin-bottom: 0.7rem; }
.prose-page ul { padding-left: 1.2rem; margin-bottom: 0.7rem; }
.auth-legal { text-align: center; margin-top: 0.8rem; font-size: 0.72rem; }
.certificate-actions { display: flex; align-items: center; gap: 0.6rem; }
.vc-start { display: flex; align-items: center; gap: 0.75rem; margin-top: 1rem; flex-wrap: wrap; }
.vc-form { display: flex; align-items: center; gap: 0.6rem; }
.depth-select {
  font: inherit; font-size: 0.78rem; padding: 0.4rem 1.8rem 0.4rem 0.7rem;
  border: 1px solid var(--border-strong); border-radius: var(--radius-pill);
  background-color: var(--bg); color: var(--ink);
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%23111111' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 0.7rem center; background-size: 9px;
}
.comp-thumb { display: block; height: 52px; width: auto; max-width: 78px; border-radius: 5px; box-shadow: var(--shadow-sm); }
/* Holds the plate column open for comps with no image on file (usually
   paste-ins), so the evidence column always reads as a column. */
.thumb-none {
  display: block; height: 52px; width: 40px; border-radius: 5px;
  border: 1px dashed var(--border-strong); background: var(--wash);
}
.parse-notes-row td { color: var(--ink-muted); font-style: italic; font-size: 0.8rem; border-bottom: 1px solid var(--border); padding-top: 0; }

/* ---------- Certificate (value conclusion) ---------- */
.certificate {
  margin-top: 1.4rem;
  border-top: 2px solid var(--ink);
  border-bottom: 2px solid var(--ink);
  padding: 1.9rem 0.25rem;
}
.certificate-value {
  font-family: "IBM Plex Serif", serif; font-weight: 600;
  font-size: clamp(1.7rem, 3.5vw, 2.5rem);
  margin: 0.4rem 0 1rem;
  font-variant-numeric: tabular-nums;
}
.certificate-value .cur { font-size: 1rem; color: var(--ink-muted); font-family: "IBM Plex Sans", sans-serif; font-weight: 500; margin-right: 0.35rem; }
.certificate p { white-space: pre-wrap; }
.certificate-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  margin-top: 1.3rem; padding-top: 1.1rem; border-top: 1px solid var(--border);
}

/* ---------- Forms ---------- */
.panel { border-top: 1px solid var(--ink); padding-top: 1.5rem; }
.field-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1rem; }
.field { display: block; margin-bottom: 1.1rem; }
.field-grid .field { margin-bottom: 0; }
.field > span, .field label {
  display: block; font-size: 0.74rem; font-weight: 600; color: var(--ink-muted); margin-bottom: 0.4rem;
}
.field input, .field select, .field textarea, .form-actions input {
  width: 100%; font: inherit; font-size: 0.88rem; padding: 0.6rem 0.8rem;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--bg); color: var(--ink);
}
.field textarea { resize: vertical; }
/* Left to the browser this is a UA grey that differs per engine and is
   under the floor in some of them; pin it to the measured faint ink. */
.field input::placeholder,
.field textarea::placeholder {
  color: var(--ink-faint);
  opacity: 1;
}
/* The two halves of a choice ("use this collection" / "start a new one")
   read as one long list of six fields unless something says otherwise. */
.field-or {
  display: flex; align-items: center; gap: 0.9rem;
  margin: 1.5rem 0 1.2rem;
  font-size: 0.74rem; font-weight: 600; letter-spacing: 0.04em;
  color: var(--ink-faint);
}
.field-or::before, .field-or::after {
  content: ""; flex: 1; height: 1px; background: var(--border);
}
/* Native select chrome crowds the border and lets text run under the
   arrow — draw our own chevron, reserve room for it, ellipsize the rest. */
.field select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 2.4rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%23111111' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.85rem center;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: 2px solid var(--ink); outline-offset: 1px; border-color: var(--ink);
}
.form-actions { display: flex; align-items: center; justify-content: flex-end; gap: 0.75rem; margin-top: 1.4rem; flex-wrap: wrap; }
.form-sheet { max-width: 760px; }
.search-panel { max-width: 860px; margin-bottom: 2.25rem; }

.dropzone {
  position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.4rem;
  border: 1.5px dashed var(--border-strong); border-radius: var(--radius-md);
  padding: 2rem 1.5rem; text-align: center; cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
  margin-bottom: 1.1rem;
}
.dropzone:hover { border-color: var(--ink-faint); background: var(--wash); }
/* Solid, not dashed: the target has closed and is ready to take the file. */
.dropzone.is-dragover {
  border-style: solid; border-color: var(--ink); background: var(--wash);
}
.dropzone.is-dragover .dropzone-title { text-decoration: underline; text-underline-offset: 3px; }
/* The overlaid input would otherwise be the drop target's child that
   dragleave keeps firing against. */
.dropzone.is-dragover input[type="file"] { pointer-events: none; }
/* The substantiation behind the figure: the comp arithmetic, the caveats on
   it, and what the draft was written from. Deliberately not styled as a
   result — it is what the appraiser checks the result against, and it sits
   below the conclusion because none of it is the answer. */
.working {
  margin: 1.6rem 0 1.4rem; padding: 1.1rem 1.2rem;
  background: var(--wash); border: 1px solid var(--border); border-radius: var(--radius-md);
}
.working-steps {
  margin: 0.5rem 0 0; padding-left: 1.3rem;
  font-size: 0.86rem; font-variant-numeric: tabular-nums;
}
.working-steps li { margin-bottom: 0.25rem; color: var(--ink-muted); }
.working-steps li:last-child { color: var(--ink); font-weight: 600; }
.working-note { font-size: 0.78rem; color: var(--ink-muted); margin: 0.6rem 0 0; }
/* What the draft was written from — a provenance line for the write-up, so
   it takes the same rule and the same quiet as the caveats above it. */
.working-basis {
  border-top: 1px solid var(--border); margin: 1.1rem 0 0; padding-top: 1rem;
  font-size: 0.78rem; color: var(--ink-muted);
}

.eyebrow-row { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.unit-toggle { display: inline-flex; border: 1px solid var(--border-strong); border-radius: var(--radius-md); overflow: hidden; }
.unit-toggle label { cursor: pointer; }
.unit-toggle input { position: absolute; opacity: 0; pointer-events: none; }
.unit-toggle span {
  display: block; padding: 0.25rem 0.7rem; font-size: 0.8rem; color: var(--ink-muted);
  transition: background 0.15s ease, color 0.15s ease;
}
.unit-toggle label + label span { border-left: 1px solid var(--border-strong); }
.unit-toggle input:checked + span { background: var(--ink); color: #fff; }
.unit-toggle input:focus-visible + span { outline: 2px solid var(--ink); outline-offset: -2px; }

.dropzone-title { font-weight: 600; font-size: 0.95rem; }
.dropzone-hint { font-size: 0.8rem; color: var(--ink-muted); max-width: 46ch; }
.dropzone input[type="file"] {
  position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; height: 100%;
}

/* ---------- Auth pages ---------- */
.auth-page {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: 2rem 1.25rem calc(2rem + env(safe-area-inset-bottom));
}
.auth-card {
  width: 100%; max-width: 380px;
  border-top: 2px solid var(--ink);
  padding-top: 1.6rem;
}
.auth-card .wordmark { font-size: 0.9rem; }
.auth-card h1 { font-size: 1.5rem; margin: 1.4rem 0 0.4rem; }
.auth-card .hint { margin: 0 0 1.2rem; }
.auth-card form { margin-top: 1.2rem; }
.auth-submit { width: 100%; margin-top: 0.4rem; }

/* ---------- Notices ---------- */
.notice {
  background: var(--wash); color: var(--ink-muted);
  border-radius: var(--radius-sm); padding: 0.65rem 0.9rem; font-size: 0.84rem;
  margin: 0 0 1.25rem;
}
.notice a { color: var(--ink); font-weight: 600; }
.notice-error { background: var(--error-wash); color: var(--error); }
/* Something the appraiser should weigh, not something that went wrong. Keeps
   the ink colour and marks itself with a rule rather than a red wash. */
.notice-advice {
  background: var(--wash); color: var(--ink);
  border-left: 3px solid var(--border-strong); border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.notice-advice strong { font-weight: 600; }

/* The caveats live inside the working panel, divided from the arithmetic by
   a rule rather than by being a second box of their own. */
.working-flags { border-top: 1px solid var(--border); margin-top: 1.1rem; padding-top: 1rem; }
.working-flags .eyebrow { display: block; margin-bottom: 0.5rem; }
.working-flags ul { margin: 0; padding-left: 1.1rem; display: flex; flex-direction: column; gap: 0.6rem; }
.working-flags li { color: var(--ink); font-size: 0.88rem; }

/* ---------- Disclosure ----------
   A section of the page that happens to be collapsible, not a text link
   with a plus sign in front of it. It was the latter, and a block holding
   an artist's whole auction record announced itself more quietly than the
   table rows underneath it.

   <details> rather than a scripted panel: it opens without JavaScript,
   takes keyboard focus, and is findable by the browser's own in-page
   search even while closed. */
.disclosure {
  border: 1px solid var(--border-strong); border-radius: var(--radius-md);
  margin: 1.5rem 0; background: var(--surface);
}
.disclosure > summary {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 1.5rem;
  padding: 1rem 1.15rem; cursor: pointer; list-style: none; border-radius: var(--radius-md);
}
.disclosure > summary::-webkit-details-marker { display: none; }
.disclosure > summary:hover { background: var(--wash); }
.disclosure > summary:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.disclosure[open] > summary { border-bottom: 1px solid var(--border); border-radius: var(--radius-md) var(--radius-md) 0 0; }

.disclosure-title {
  display: flex; flex-direction: column; gap: 0.2rem;
  font-family: "IBM Plex Serif", Georgia, serif; font-size: 1rem; font-weight: 600;
  color: var(--ink);
}
/* One line. A 52ch cap broke a 78-character sentence in two with 300px of
   empty band beside it, which read as a paragraph rather than a subtitle;
   the header is wide enough to hold it whole. It still wraps on a phone,
   where nothing would fit on one line anyway. */
.disclosure-note {
  font-family: "IBM Plex Sans", sans-serif; font-size: 0.82rem; font-weight: 400;
  color: var(--ink-muted);
}
/* A chevron that points where opening will take you. */
.disclosure-mark {
  flex: none; width: 0.55rem; height: 0.55rem; margin-top: 0.42rem;
  border-right: 1.5px solid var(--ink-faint); border-bottom: 1.5px solid var(--ink-faint);
  transform: rotate(45deg); transition: transform 0.15s ease;
}
.disclosure[open] .disclosure-mark { transform: rotate(-135deg); margin-top: 0.62rem; }
.disclosure-body { padding: 1.3rem 1.15rem; }

/* ---------- Channel picker ----------
   One paste-in form serving two channels, with the channel stated rather
   than implied. Two look-alike forms used to sit here; the only thing
   distinguishing them was which heading you had scrolled past. */
.channel-picker { border: 0; margin: 0 0 1.2rem; padding: 0; }
.channel-picker legend { padding: 0; margin-bottom: 0.6rem; }
.channel-option {
  display: grid; grid-template-columns: auto 1fr; gap: 0.15rem 0.6rem;
  align-items: baseline; padding: 0.6rem 0.8rem; cursor: pointer;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  margin-bottom: 0.5rem;
}
.channel-option:has(input:checked) { border-color: var(--ink); background: var(--wash); }
.channel-option input { margin: 0; }
.channel-label { font-weight: 600; font-size: 0.88rem; }
.channel-note { grid-column: 2; color: var(--ink-muted); font-size: 0.8rem; }
/* ---------- Menu ----------
   A dropdown, not an accordion: browsing is the same job "Find comparables"
   does automatically, so it sits with it rather than as a list of links
   stranded under the table. */
.menu { position: relative; }
.menu > summary { list-style: none; }
.menu > summary::-webkit-details-marker { display: none; }
.menu > summary::after { content: "\25BE"; font-size: 0.7em; }
/* Anchored to its own right edge: the trigger is the last control in a
   right-aligned row, so a panel hung from the left ran off the page. */
.menu-body {
  position: absolute; z-index: 25; top: calc(100% + 0.4rem); right: 0; min-width: 15rem;
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border-strong);
  border-radius: var(--radius-md); box-shadow: var(--shadow-md); padding: 0.35rem;
}
.menu-body a {
  padding: 0.55rem 0.7rem; border-radius: var(--radius-sm);
  font-size: 0.84rem; text-decoration: none; color: var(--ink);
}
.menu-body a:hover { background: var(--wash); }

/* ---------- Comparable, on its own page ---------- */
.comp-link { text-decoration: none; }
.comp-link:hover { text-decoration: underline; text-underline-offset: 3px; }
.comp-page { display: grid; grid-template-columns: minmax(0, 260px) minmax(0, 1fr); gap: 2rem; align-items: start; }
.comp-page-figure img { width: 100%; border-radius: var(--radius-sm); box-shadow: var(--shadow-md); }
.comp-page-figure .no-image {
  display: grid; place-items: center; aspect-ratio: 1; border: 1px dashed var(--border-strong);
  border-radius: var(--radius-sm); color: var(--ink-faint); font-size: 0.82rem;
}
.comp-page-facts { display: flex; flex-direction: column; gap: 0.9rem; }
@media (max-width: 640px) { .comp-page { grid-template-columns: 1fr; } }

/* A form that is the whole point of the screen it is on. */
.form-page { max-width: 46rem; }
.form-page .form-actions { justify-content: flex-start; gap: 0.6rem; }

/* Button over its explanation, rather than a sentence wrapping around it. */
.stacked-form { display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem; margin-bottom: 1.4rem; }
.stacked-form .hint { max-width: 60ch; }

/* The estimate and sale name, under the comp they describe. */
.cell-note { font-style: italic; }

/* ---------- Row controls ----------
   "Key" is a property of the comparable, not something you do to it, so it
   is drawn as a toggle that shows its own state rather than an underlined
   verb with a geometric glyph beside it. Remove is the destructive one and
   looks like it: quiet until reached for. */
.key-toggle {
  font: inherit; font-size: 0.72rem; font-weight: 600; letter-spacing: 0.04em;
  padding: 0.2rem 0.6rem; border-radius: var(--radius-pill); cursor: pointer;
  border: 1px solid var(--border-strong); background: transparent; color: var(--ink-muted);
}
.key-toggle:hover { border-color: var(--ink); color: var(--ink); }
.key-toggle.is-key { background: var(--ink); border-color: var(--ink); color: var(--bg); }
.row-remove {
  font: inherit; font-size: 1.05rem; line-height: 1; cursor: pointer;
  background: none; border: none; padding: 0.15rem 0.35rem;
  color: var(--ink-faint); border-radius: var(--radius-sm);
}
.row-remove:hover { color: var(--error); background: var(--error-wash); }

/* ---------- Places to go looking ---------- */
.context-block { margin-bottom: 1.6rem; }
.context-block:last-child { margin-bottom: 0; }
.context-block .eyebrow { display: block; margin-bottom: 0.5rem; }
.context-block .hint { margin: 0 0 0.8rem; }

.browse-row { margin: 1.6rem 0 0; }

.browse-row .eyebrow { display: block; margin-bottom: 0.5rem; }
.hint { color: var(--ink-muted); font-size: 0.88rem; }
.empty-state { color: var(--ink-muted); }

/* ---------- Responsive ---------- */
/* The rail stands beside the work only while what it stands beside still
   fits. A 260px rail plus its gutter left the comps table 660px of a 1024px
   window to hold a seven-column record: it scrolled sideways with its last
   column past the edge, and squeezed to fit it broke a title over seven
   lines. Under 1200 the rail goes below, where it costs the evidence
   nothing — the catalogue record is a handful of short facts and reads the
   same either way. */
@media (max-width: 1199px) {
  .dossier { grid-template-columns: 1fr; }
  .dossier-rail { position: static; }
}
@media (max-width: 640px) {
  /* Nav moves to a bottom tab bar; the topbar keeps just the wordmark. */
  .page { padding: 1.25rem 1.1rem calc(6rem + env(safe-area-inset-bottom)); }
  .topbar { padding: 0.9rem 1.1rem; padding-top: calc(0.9rem + env(safe-area-inset-top)); justify-content: center; }
  .nav-links { display: none; }
  .tabbar { display: flex; }

  .stat-strip { gap: 1.25rem 1.75rem; padding-bottom: 1.5rem; margin-bottom: 2rem; }
  .stat-value { font-size: 1.35rem; }
  .work-title { font-size: 1.5rem; }
  .certificate-value { font-size: 1.6rem; }
  .catalog-grid { columns: 2 150px; column-gap: 1.1rem; }
  .piece-card { margin-bottom: 1.8rem; }

  /* Stack the row: name/client on top, chip + figures beneath. */
  .collection-row { flex-wrap: wrap; gap: 0.6rem 1rem; }
  .collection-row-main { flex-basis: 100%; }
  .collection-figures { flex: 1; align-items: flex-start; }
  .collection-figures .collection-total { order: -1; }
  .row-chevron { display: none; }

  /* Artwork runs edge to edge, like a native photo view. */
  .hero-frame { margin-left: -1.1rem; margin-right: -1.1rem; border-radius: 0; box-shadow: none; }
  .photo-strip { margin: 0 -1.1rem; padding: 0 1.1rem 0.3rem; -webkit-overflow-scrolling: touch; }

  /* iOS zooms any focused control under 16px — hold inputs at 1rem/16px. */
  body { font-size: 16px; }
  .field input, .field select, .field textarea, .form-actions input { font-size: 1rem; }
  .btn { min-height: 44px; }
  .link-button { min-height: 44px; display: inline-flex; align-items: center; }

  /* Comps: the wide table restacks into one labelled record per row.
     Sideways scrolling hides half a comparable behind the edge of the
     screen, and a comparable half-read is a comparable not checked.

     Each row is a two-column grid: plate on the left, everything else on
     the right, with the fields that used to be column-headed now carrying
     their own label from data-label. */
  .data-table-wrap { overflow-x: visible; }
  .data-table thead { display: none; }
  table.data-table, .data-table tbody { display: block; width: 100%; }
  .data-table tr {
    display: grid;
    grid-template-columns: 72px minmax(0, 1fr) auto;
    gap: 0.4rem 0.9rem;
    padding: 1.15rem 0;
    border-bottom: 1px solid var(--border);
  }
  .data-table tbody tr:hover { background: none; }
  /* Anything not placed explicitly runs the full width as its own line. */
  .data-table td { display: block; grid-column: 1 / -1; padding: 0; border: none; }
  td.c-thumb { grid-column: 1; grid-row: 1; }
  td.c-thumb .comp-thumb { height: auto; width: 72px; max-width: 72px; }
  td.c-thumb .thumb-none { height: 72px; width: 72px; }
  td.c-title { grid-column: 2; grid-row: 1; font-size: 0.94rem; }
  /* On the card the action sits on the title's line, at the far edge — the
     one place in the row that is about the comparable as a whole rather
     than about one of its fields. */
  td.c-actions { grid-column: 3; grid-row: 1; text-align: right; }
  /* Card layout: hang the key marker in the gutter beside the title. */
  .key-mark { left: -0.85rem; top: 0.3rem; }

  /* The labelled line: label left, value right, both baselines aligned. */
  .data-table td[data-label] {
    display: grid;
    grid-template-columns: 6.25rem minmax(0, 1fr);
    gap: 0.15rem 0.75rem;
    font-size: 0.84rem;
  }
  .data-table td[data-label]::before {
    content: attr(data-label);
    font-size: 0.62rem; font-weight: 600; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--ink-faint);
    grid-column: 1; grid-row: 1;
    padding-top: 0.16rem;
  }
  /* Sub-lines (price type, "observed") stack under the value, not under
     the label — without this they auto-place back into column one. */
  .data-table td[data-label] > * { grid-column: 2; }
  td.c-meta { color: var(--ink-muted); }
  td.c-price { color: var(--ink); font-weight: 500; }
  td.c-action { margin-top: 0.6rem; }
  tr.parse-notes-row { padding: 0 0 1.15rem; }
}

/* ---------- Readiness to deliver ----------
   The checklist behind the report's draft mark. Met items shrink to a line;
   unmet ones carry the fix, because a checklist that only says "no" makes
   the appraiser hunt for the screen that says yes. */
.readiness-list { list-style: none; margin: 0; padding: 0; }
.readiness-list li {
  display: flex; gap: 0.7rem; align-items: baseline;
  padding: 0.5rem 0; border-top: 1px solid var(--border);
}
.readiness-list li:first-child { border-top: none; }
.readiness-mark { font-size: 0.8rem; line-height: 1.4; width: 0.9rem; flex: none; }
.is-met .readiness-mark { color: var(--ink); }
.is-unmet .readiness-mark { color: var(--ink-muted); }
.readiness-body { display: flex; flex-direction: column; gap: 0.15rem; }
.readiness-label { font-size: 0.92rem; }
.is-met .readiness-label { color: var(--ink-muted); }
.readiness-detail { font-size: 0.84rem; color: var(--ink-muted); max-width: 62ch; }

/* ---------- Working state ----------
   Paired with /static/app.js. The label keeps its place in the layout and in
   the accessibility tree — only its ink goes — so swapping in the spinner
   cannot reflow the row the button sits in. */
.is-working { pointer-events: none; }

@media (prefers-reduced-motion: no-preference) {
  .btn.is-working { position: relative; color: transparent; }
  .btn.is-working::after {
    content: ""; position: absolute; top: 50%; left: 50%;
    width: 0.9em; height: 0.9em; margin: -0.45em 0 0 -0.45em;
    border: 1.5px solid var(--spin-track);
    border-top-color: var(--spin-head);
    border-radius: 50%;
    animation: romanotto-spin 0.62s linear infinite;
  }
  /* A spinner at 0.8rem would be a speck, so the small inline actions
     ("remove", "key", "delete it") just breathe instead. */
  .link-button.is-working { animation: romanotto-fade 1.1s ease-in-out infinite; }
}

/* Track/head as custom properties so a variant sets its own colours without
   depending on which rule the stylesheet happens to declare last. */
.btn { --spin-track: rgba(250, 250, 248, 0.34); --spin-head: var(--bg); }
.btn-ghost { --spin-track: rgba(17, 17, 17, 0.18); --spin-head: var(--ink); }
.btn-danger { --spin-track: rgba(140, 47, 34, 0.25); --spin-head: #8c2f22; }

/* No spinner to watch, so say it with weight instead. */
@media (prefers-reduced-motion: reduce) {
  .is-working { opacity: 0.5; }
}

@keyframes romanotto-spin { to { transform: rotate(360deg); } }
@keyframes romanotto-fade { 0%, 100% { opacity: 0.35; } 50% { opacity: 0.8; } }

/* A date belongs on one line. "Apr 16, 2024" is short enough to fit and
   long enough that the column will break it at the comma given the chance. */
.data-table .c-date { white-space: nowrap; }
/* A measurement broken across lines ("100.0 x 96.0" / "cm") stops reading as
   one quantity, so it holds its line too. */
.data-table .c-dims { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Seven columns in an 816px block leaves the price about 90px, which broke
   "USD 22,860" across two lines and stacked the estimate under it three
   lines deep. Holding the figure on one line makes the column ask for the
   width it needs; the wrapping goes to the title and medium, which are
   prose and read fine wrapped. */
.data-table .c-price, .data-table .c-price .cell-sub { white-space: nowrap; }
/* The row's own action. Sized to its word and pushed to the edge, so it
   costs the evidence columns as little width as an action column can. */
.data-table .c-actions { width: 1%; white-space: nowrap; text-align: right; padding-left: 0; }

/* Narrower than about 880px there is not room for the table's preferences
   even with the whole window to itself, so they give way: a price wrapped
   over two lines is legible, and the alternative was scrolling the table
   sideways with the column that removes a comparable parked off the edge. */
@media (max-width: 879px) {
  .data-table .c-price, .data-table .c-price .cell-sub, .data-table .c-dims { white-space: normal; }
  .data-table .c-title { min-width: 0; }
}
/* The last of the preferences to give way, in the sliver between the phone
   card layout and a window wide enough to keep it: "Feb 26, / 2026". */
@media (max-width: 700px) {
  .data-table .c-date { white-space: normal; }
}

/* Where to go looking for a retail comp. Sits above the paste-in because
   that is the order the work happens in: find the listing, then record it. */
.retail-hunt {
  margin: 0 0 1.1rem; padding: 0.85rem 1rem;
  background: var(--wash); border: 1px solid var(--border); border-radius: var(--radius-md);
}
.retail-links { list-style: none; margin: 0.55rem 0 0; padding: 0; display: grid; gap: 0.5rem; }
.retail-links li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem; }
.retail-links a { font-weight: 600; font-size: 0.86rem; text-decoration: underline; text-underline-offset: 3px; }
.retail-link-note { font-size: 0.78rem; color: var(--ink-muted); }
.retail-hunt .hint { margin: 0.7rem 0 0; max-width: 66ch; }
