/* Listing details / edit page (rendered into #details by details.js). */
/* No top padding: the sticky .sheet-peek provides the top spacing and must sit flush with the scroll top. */
.details-page { font-family: "Nunito", system-ui, sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; padding: 0 16px 16px; box-sizing: border-box; }
.details-page a { color: var(--accent); }
.details-page h1 { font-size: 16px; margin: 0 0 6px; }
.details-page .meta { color: var(--muted); font-size: 13px; margin-bottom: 10px; }
.details-page .dim { color: var(--muted); }
/* Buttons read as buttons — accent-outlined pills, deliberately unlike the filled panel input fields and the
   bordered source cards, so the three never blur together. */
.details-page .btn { display: inline-flex; align-items: center; gap: 6px; background: transparent; color: var(--accent);
  border: 1px solid var(--accent); border-radius: 999px; cursor: pointer; font-size: 13px; font-weight: 600; padding: 6px 14px; }
.details-page .btn:hover { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.details-page .btn .ic { width: 15px; height: 15px; }
.details-page .btn.on { background: #7a3b3b; border-color: #b06a6a; color: #ffd9d9; }
/* The address is a menu trigger (Show on map / Open in Google Maps), styled as the accent link it replaced.
   It yields first when the row is tight (ellipsis, full text on hover) so "Wrong?" stays on the address line
   instead of being pushed onto one of its own — the pairing is the whole point of putting it there. */
.details-page .loc-link { background: none; border: none; padding: 0; cursor: pointer; font: inherit;
  color: var(--accent); text-align: left;
  flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.details-page .loc-link:hover { text-decoration: underline; }
/* "Wrong info" is a low-emphasis, muted-outline variant. */
.details-page .btn-ghost { color: var(--muted); border-color: var(--border-2); font-weight: 500; }
.details-page .btn-ghost:hover { color: var(--text); border-color: var(--muted); background: var(--hover); }
/* One quiet disclosure at the very bottom, split off from the edit fields by a divider — plus the pill for a
   report the user has already made, which is a state and must stay readable without opening the menu. */
.details-page .sheet-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--divider); }
/* A lone outlined pill gave no sign it reveals anything. The trailing chevron is the whole tell — it points
   down when closed and flips up once the menu is out. */
.details-page #sheetIssueBtn .ic:last-child { width: 15px; height: 15px; margin-left: 1px; transition: transform .14s; }
.details-page #sheetIssueBtn.open .ic:last-child { transform: rotate(180deg); }
.details-page .btn-ghost.open { color: var(--text); border-color: var(--muted); background: var(--hover); }
.details-page .state-pill { font-weight: 600; }
/* Each correction states what it claims, then what it does — "It's a duplicate" named neither, and nothing
   said whether marking a place rented told the world or only tidied your own map. */
.details-page .issue-menu { display: flex; flex-direction: column; gap: 2px; margin-top: 8px;
  border: 1px solid var(--border); border-radius: 8px; padding: 4px; background: var(--panel); }
.details-page .issue-menu[hidden] { display: none; }
.details-page .issue-opt { display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
  width: 100%; box-sizing: border-box; text-align: left; padding: 8px 10px; border: none; border-radius: 6px;
  background: none; color: var(--text); font: inherit; cursor: pointer; }
.details-page .issue-opt[hidden] { display: none; }
.details-page .issue-opt:hover { background: var(--hover); }
.details-page .issue-opt.on { background: var(--hover); }
.details-page .issue-opt b { font-size: 13px; font-weight: 600; }
.details-page .issue-opt small { font-size: 11px; color: var(--muted); }
.details-page .tagedit { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin: 8px 0; }
.details-page .chips { display: flex; gap: 5px 6px; flex-wrap: wrap; }
/* No tags yet → the chips row collapses entirely, so the add-tag input lines up flush-left with every other
   row instead of being nudged right by an empty flex item + its gap. */
.details-page #sheetTagChips:empty { display: none; }
.details-page .chip { background: var(--chip-bg); color: var(--chip-fg); border: 1px solid var(--chip-bd); border-radius: 12px; padding: 2px 4px 2px 9px; font-size: 12px; display: inline-flex; align-items: center; gap: 4px; }
.details-page .chip button { background: none; border: none; color: var(--muted); cursor: pointer; font-size: 14px; line-height: 1; padding: 0 2px; }
/* Read-only, no remove button — amenities rendered from the region's AttributeDefinition registry. Smaller
   than the editable tag chips: there are many of them and they're supporting detail, not a control. */
.details-page .chip.feature { background: var(--feat-bg); border-color: var(--feat-bd); color: var(--feat-fg);
  padding: 1px 7px; font-size: 11px; border-radius: 10px; }
.details-page .chip.feature .ic { width: 12px; height: 12px; }
/* They CLOSE the read-only facts band (under min-stay) rather than leading the whole sheet. */
.details-page .chips.features { margin-top: 8px; }
.details-page input, .details-page textarea { background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: 4px; padding: 6px 8px; font-size: 13px; font-family: inherit; }
.details-page input:focus, .details-page textarea:focus { outline: none; border-color: var(--accent); }
.details-page textarea { display: block; width: 100%; max-width: 640px; min-height: 70px; margin: 8px 0 0; resize: vertical; }
/* The report box owns its own spacing (the form is a column: box, then Send under it) — the shared textarea
   top margin would push the Send button away from the box it belongs to. */
.details-page .report-form textarea { margin: 0; min-height: 60px; }
.details-page .hint { font-size: 11px; color: var(--muted); margin-left: 8px; }
/* Location + date rows: same size and color — the date line used to inherit the 16px body default. */
/* One line, never wrapped: everything on it (Wrong?, the radius, the moved-by-hand history) refers to the
   address next to it, and a wrap put them on a row of their own that read as unrelated controls. The address
   ellipsises to make room — it's the only elastic item here. */
.details-page .loc { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; margin-top: 12px; font-size: 13px; color: var(--muted); }
.details-page .loc > :not(.loc-link) { flex: none; }
.details-page .loc .ic { width: 15px; height: 15px; flex: 0 0 auto; }
/* Where the pin came from is the pin glyph's own tooltip — it was a separate ⓘ button, which is a control the
   user can't do anything with sitting next to controls they can. Named .loc-src, not .loc-pin: map.css's
   .loc-pin is the big draggable relocate marker (with its own drop-shadow) — sharing the name pulled that
   shadow onto this inline glyph too, since map.css is global and unscoped. */
.details-page .loc-src { display: inline-flex; align-items: center; cursor: help; }

/* Facts (type / beds / baths / furnishing / min-stay) and the two found-dates render as compact icon+value
   pills, each carrying a hover tooltip with the full label. */
.details-page .fact { display: inline-flex; align-items: center; gap: 3px; }
/* Dated facts (found/checked) stack the key above the value instead of setting them side by side — a 9.5px
   caption and a 13px date centered on one line never share a baseline, however careful the sizing, and read
   as two mismatched fonts rather than one label. Stacked, the icon centers against the whole two-line block. */
.details-page .fact-body { display: flex; flex-direction: column; line-height: 1.15; }
/* The key names the value ("found", "checked") without ever competing with it: small, upper-case, muted. */
.details-page .fact-k { font-style: normal; font-size: 9.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; opacity: .7; }
.details-page .fact .ic { width: 15px; height: 15px; }
.details-page .dates-row { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px; margin-top: 8px; font-size: 13px; color: var(--muted); }
/* A pill and the row's ? travelling as one flex item, so the ? can never be left wrapped on a line by itself. */
.details-page .fact-grp { display: inline-flex; align-items: center; gap: 7px; }
/* Precision radius shown inline on the location line (e.g. "⌖ ±60m"); min-stay is its own row under dates. */
.details-page .precision { display: inline-flex; align-items: center; gap: 3px; white-space: nowrap; }
.details-page .precision .ic { width: 14px; height: 14px; }
.details-page .terms-row { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; margin-top: 8px; font-size: 13px; color: var(--muted); }
.details-page .terms-row .ic { width: 15px; height: 15px; }

/* Rating, tags and notes are the one band nobody else can see, and a lone "Your private rating" label was
   carrying that whole fact. It now reads as its own place: a tinted panel behind an accent rail, headed by what
   it is. Deliberately NOT a bordered box — the source cards below are bordered, and a second rectangle at the
   same weight would flatten the two back into one another. */
.details-page .mine { margin-top: 14px; padding: 10px 12px; border-left: 2px solid var(--accent);
  border-radius: 0 8px 8px 0; background: color-mix(in srgb, var(--accent) 7%, transparent); }
.details-page .mine-head { display: flex; align-items: center; gap: 5px; margin-bottom: 8px;
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.details-page .mine-head .ic { width: 12px; height: 12px; }
.details-page .mine-row { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
.details-page .mine-label { font-size: 12px; font-weight: 600; color: var(--muted); }
/* A column, not a wrapping row: as a row the input was a flex sibling of the chips and lost width to every tag
   already applied, so the field you type in shrank as you used it. */
.details-page .tagedit { flex-direction: column; align-items: stretch; gap: 6px; }
.details-page .hint-note { font-size: 11px; color: var(--muted); margin-left: 8px; }
/* Empty, it's still an inline element with a line-height — a phantom line under "Add a private note"
   until the "saved" text briefly fills it. */
.details-page .hint-note:empty { display: none; }
/* Correcting the pin is one of the report actions and lives in that menu with the rest — it used to be a
   "Wrong?" link on the address line, a second, differently-worded reporting affordance a scroll away from
   "Wrong info". The editor it reveals now sits directly under the menu that opened it, so .loc-fix carries no
   styling of its own and .loc-wrong is left entirely to .issue-opt. */
.details-page .loc-fix { margin: 0; }
.details-page .loc-hist-btn { display: inline-flex; align-items: center; justify-content: center;
  background: none; border: none; padding: 0; margin-left: 2px; cursor: pointer; color: var(--muted); }
.details-page .loc-hist-btn .ic { width: 14px; height: 14px; }
.details-page .loc-hist-btn:hover { color: var(--accent); }
.details-page .locedit { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.details-page .locedit[hidden] { display: none; }
.details-page .locedit > label { font-size: 12px; font-weight: 600; color: var(--muted); }
.details-page .locsearch { position: relative; width: 100%; max-width: 560px; }
.details-page #locInput { width: 100%; box-sizing: border-box; }
.details-page .locsuggest { position: absolute; top: calc(100% + 2px); left: 0; right: 0; z-index: 50;
  background: var(--panel); border: 1px solid var(--border); border-radius: 4px; overflow: hidden; box-shadow: 0 4px 14px rgba(0,0,0,.5); }
.details-page .locsuggest[hidden] { display: none; }
.details-page .locsuggest-item { display: block; width: 100%; box-sizing: border-box; text-align: left;
  background: none; border: none; padding: 7px 9px; font: inherit; font-size: 13px; color: var(--text); cursor: pointer; }
.details-page .locsuggest-item:hover { background: var(--hover); }
.details-page .locedit-msg { font-size: 12px; }
.details-page .locedit-msg[hidden] { display: none; }
.details-page .locedit-region { display: flex; flex-direction: column; gap: 4px; margin-top: 4px;
  padding-top: 8px; border-top: 1px dashed var(--border); }
.details-page .locedit-region[hidden] { display: none; }
.details-page .locedit-region > label { font-size: 12px; font-weight: 600; }
.details-page .locedit-region > label small { font-weight: 400; }
.details-page .locedit-region select { max-width: 280px; background: var(--panel); color: #dc2626;
  border: 1px solid var(--border); border-radius: 4px; padding: 4px 6px; font-size: 13px; }
/* The offer sources are a section, not a box: a divider and a quiet header set them apart from the notes/tags
   band above. Wrapping the rows in a panel put a rectangle around rectangles — every part of the sheet then
   read at the same weight. */
.details-page .dups { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--divider);
  font-size: 13px; color: var(--muted); }
.details-page .dups-h { margin-bottom: 2px; color: var(--muted); font-weight: 600; font-size: 12px; }
.details-page .dups-h .hint { margin-left: 5px; }
/* The rows are links, but a list of them still looked like content until something said so. */
.details-page .dups-sub { margin-bottom: 8px; font-size: 11px; color: var(--muted); opacity: .8; }
.details-page .srclist { display: flex; flex-direction: column; gap: 6px; }
/* One row per source: channel mark, then who posted it (up to two lines — group names are long), then price,
   date and photo count as one quiet meta line. The whole row is the link, and now carries a border and a press
   state to say so — filled and borderless it sat at the same weight as the read-only facts above it. */
.details-page .srccard { display: flex; align-items: flex-start; gap: 10px; padding: 9px 10px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--card);
  text-decoration: none; color: inherit; font-size: 12px; }
.details-page a.srccard:hover { background: var(--card-hover); border-color: var(--accent); }
.details-page a.srccard:active { transform: translateY(1px); }
/* Brand colours as color-mix tints so one rule works on both the dark and the light theme. */
.details-page .srcmark { width: 26px; height: 26px; flex: none; border-radius: 7px;
  display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 700; }
.details-page .srcmark .ic { width: 16px; height: 16px; }
.details-page .src-fb { color: #3b82c4; background: color-mix(in srgb, #3b82c4 16%, transparent); }
.details-page .src-lamudi { color: #e0761a; background: color-mix(in srgb, #e0761a 16%, transparent); }
.details-page .src-dot { color: #4f9d3a; background: color-mix(in srgb, #4f9d3a 16%, transparent); }
.details-page .src-other { color: var(--muted); background: var(--thumb); }
.details-page .srccard-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
/* Two lines, then clamp — a long FB group name never fitted on one row and was cut mid-word. */
.details-page .srccard-label { color: var(--accent); font-size: 13px; line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.details-page .srccard-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 5px;
  font-size: 11px; color: var(--muted); }
.details-page .srcsep { opacity: .6; }
/* Owner-direct badge — the same green the amenity chips use for the direct_listing attribute it comes from.
   Text is longer than the old "Owner", so the font shrinks further to keep the badge from wrapping the row. */
.details-page .srcowner { display: inline-flex; align-items: center; gap: 3px; padding: 0 5px;
  border: 1px solid var(--feat-bd); border-radius: 5px; background: var(--feat-bg); color: var(--feat-fg);
  font-size: 8px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; white-space: nowrap; }
.details-page .srcowner .ic { width: 10px; height: 10px; }
/* A poster's folded re-posts: the disclosure and the rows it reveals both indent to the mark's width, so they
   read as belonging to the row above rather than as more top-level offers. */
.details-page .srcgroup { display: flex; flex-direction: column; gap: 2px; }
.details-page .srcmore { align-self: flex-start; margin-left: 36px; display: inline-flex; align-items: center;
  gap: 5px; padding: 2px 0; background: none; border: none; font: inherit; font-size: 11px;
  color: var(--muted); cursor: pointer; }
.details-page .srcmore:hover { color: var(--accent); }
.details-page .srcmore .ic { width: 13px; height: 13px; transition: transform .12s; }
.details-page .srcmore.open .ic { transform: rotate(180deg); }
.details-page .srcmore-body { display: flex; flex-direction: column; gap: 6px; margin: 2px 0 0 36px; }
.details-page .srcmore-body[hidden] { display: none; }
/* Named, bordered and accent-coloured: the bare glyph this replaces was the only thing marking the sheet's
   primary action — opening the actual ad — while four report pills below it wore full outlines. */
.details-page .srccard-go { flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border: 1px solid var(--accent); border-radius: 8px; color: var(--accent); }
.details-page .srccard-go .ic { width: 14px; height: 14px; }
.details-page a.srccard:hover .srccard-go { background: color-mix(in srgb, var(--accent) 16%, transparent); }
.details-page .srcphotos { display: inline-flex; align-items: center; gap: 3px; }
.details-page .srcphotos .ic { width: 13px; height: 13px; }
/* Per-source availability: a small status chip pinned to the row's right edge next to the open-in-new glyph.
   Inside the two-line clamped label its bottom border was shaved off by the clamp's overflow box.
   A DELETED source is a non-clickable, faded row (the original post no longer resolves — nothing to open). */
.details-page .srccard-side { display: flex; align-items: center; gap: 7px; flex: none; }
.details-page .srcstatus { font-size: 10px; font-weight: 700; text-transform: uppercase; white-space: nowrap;
  letter-spacing: .04em; padding: 1px 5px; border-radius: 3px; border: 1px solid currentColor; }
.details-page .srcstatus.rented { color: #e07070; }
.details-page .srcstatus.pending { color: #e0a33a; }
.details-page .srcstatus.deleted { color: var(--muted); }
.details-page .srccard-dead { opacity: .55; cursor: default; }
.details-page .srccard-dead .srccard-label { color: var(--text); }
/* Availability badge + a ? carrying the WHY, inside the price strip. flex-basis:100% gives the pair its own
   row so it starts flush with the price instead of being nudged right by the badge's own margin. */
.details-page .state-line { display: flex; align-items: center; gap: 2px; min-width: 0; flex-basis: 100%; }
.details-page .state-line:empty { display: none; }
.details-page .state-line .sold-tag { margin-left: 0; flex: none; }
/* Availability history: the current window's events shown openly; earlier tenancies (events + their source
   rows) behind the History toggle. */
.details-page .evlist { display: flex; flex-direction: column; gap: 3px; }
.details-page .evlist:not(:empty) { margin-bottom: 6px; }
.details-page .ev-row { display: flex; gap: 8px; font-size: 12px; align-items: baseline; }
.details-page .ev-when { flex: none; white-space: nowrap; }
.details-page .hist-toggle { display: inline-flex; align-items: center; gap: 6px; background: none; border: none;
  color: var(--accent); font-size: 12px; cursor: pointer; padding: 2px 0; }
.details-page .hist-toggle[hidden] { display: none; }
.details-page .hist-toggle .ic { width: 13px; height: 13px; }
.details-page .hist-toggle.open { color: var(--muted); }
.details-page #sheetHistBody { margin-top: 8px; border-top: 1px dashed var(--border); padding-top: 8px; }
.details-page #sheetHistBody[hidden] { display: none; }
.details-page #sheetHistBody .srclist { margin-bottom: 8px; }
.details-page .history-sec:has(.evlist:empty) .dups-h { margin-bottom: 0; }
.details-page .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 8px; margin-top: 12px; }
.details-page .grid-photo { padding: 0; border: none; background: none; cursor: pointer; display: block; }
.details-page .grid img, .details-page .grid-photo img { width: 100%; height: 240px; object-fit: cover; border-radius: 4px; background: var(--thumb); display: block; }
.details-page.sold .grid, body.sold .details-page .grid { opacity: .45; filter: grayscale(.75); }

/* "It's a duplicate" review modal. Appended to <body>, so these selectors are deliberately NOT scoped to
   .details-page (which only styles the sheet). Uses the shared .modal-overlay/.modal-card chrome from map.css. */
#dupModal.modal-overlay { z-index: 3500; }   /* below the lightbox (3600) so a clicked photo opens over it */
.dup-card { width: min(94vw, 560px); }
/* container-type lets the result card react to THIS panel's width, not the viewport — the card is shared by the
   wide duplicate modal (stays a row) and the narrow search dropdown (stacks), on the same desktop screen. */
.dup-body { display: flex; flex-direction: column; gap: 10px; padding: 4px 2px 2px; container-type: inline-size; }
.dup-body .dim, .dup-loading, .dup-empty { color: var(--muted); }
.dup-loading, .dup-empty { padding: 24px 6px; text-align: center; font-size: 13px; display: flex; flex-direction: column; align-items: center; gap: 8px; }
.dup-loading-note { font-size: 12px; }
/* Small spinner shared by the search + merge in-flight states — same visual as the tag-save spinner. */
.fbmr-spinner { width: 20px; height: 20px; border-radius: 50%; border: 2px solid var(--border); border-top-color: var(--accent); animation: fbmr-spin .7s linear infinite; }
.fbmr-spinner-sm { display: inline-block; width: 13px; height: 13px; border-width: 2px; margin-right: 6px; vertical-align: -2px; }
.dup-merge-note { font-size: 11px; flex-basis: 100%; }
/* Shared result card (duplicate popup + search): photos+caption on the left; the meta column leads with the
   long address (full width) and a footer that keeps the short fields left and the button pinned bottom-right.
   align-items:stretch so the meta is as tall as the photo stack, letting the footer sink to the bottom. */
.dup-candidate { display: flex; gap: 14px; padding: 11px 13px; border: 1px solid var(--border-2); border-radius: 12px; align-items: stretch; }
.dup-photos-col { display: flex; flex-direction: column; gap: 6px; flex: none; align-items: flex-start; }
.dup-photos { display: flex; gap: 3px; }
.dup-photo { position: relative; width: 46px; height: 46px; padding: 0; border: none; border-radius: 6px; overflow: hidden; cursor: pointer; background: var(--thumb); flex: none; }
.dup-photo img { width: 46px; height: 46px; object-fit: cover; display: block; }
.dup-more { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; background: rgba(0,0,0,.55); color: #fff; font-size: 13px; font-weight: 700; }
.dup-nophoto { width: 46px; height: 46px; display: flex; align-items: center; justify-content: center; color: var(--muted); background: var(--thumb); border-radius: 6px; }
/* The match caption sits under the photo strip as a quiet label for those photos. */
.dup-conf { font-size: 12px; font-weight: 600; color: var(--muted); padding-left: 1px; }
.dup-meta { display: flex; flex-direction: column; gap: 6px; min-width: 0; flex: 1; }
/* Address leads the card — the one long field, given the full width (up to two lines). */
.dup-addr { font-size: 13px; color: var(--text); font-weight: 600; line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* Footer: short fields (price + dates) on the left, action button bottom-right. margin-top:auto sinks it to the
   bottom; flex-wrap + the button's margin-left:auto let the button drop to its own right-aligned line when the
   row is too tight (long price + two distinct dates), instead of overlapping the dates. */
.dup-metafoot { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px 12px; margin-top: auto; }
.dup-facts { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 14px; min-width: 0; flex: 1 1 auto; }
.dup-price { font-size: 15px; color: var(--accent); font-weight: 700; }
/* First-found / last-activity dates on the shared result card (calendar + history glyphs). Restyled here because
   the sheet's .details-page .dates-row rule doesn't reach this card. */
.dup-facts .dates-row { display: flex; align-items: center; gap: 14px; margin: 0; font-size: 12px; color: var(--muted); }
.dup-facts .dates-row .fact { display: inline-flex; align-items: center; gap: 4px; }
.dup-action { flex: none; margin-left: auto; }
/* Both action buttons share one look — the only real difference between the two surfaces is what they DO. */
.dup-merge, .dup-open { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; background: transparent;
  color: var(--accent); border: 1px solid var(--accent); border-radius: 999px; cursor: pointer; font-size: 13px; font-weight: 600; padding: 6px 15px; }
.dup-merge:hover, .dup-open:hover { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.dup-merge:disabled, .dup-open:disabled { opacity: .6; cursor: default; }

/* Paste-a-link merge bar: merge with a listing the photo scan didn't surface (e.g. found on another site). */
.dup-bylink { display: flex; gap: 8px; align-items: center; padding: 8px 2px; border-bottom: 1px solid var(--divider); }
.dup-bylink input { flex: 1; min-width: 0; padding: 7px 10px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--panel); color: var(--text); font: inherit; font-size: 13px; }
.dup-bylink input:focus { outline: none; border-color: var(--accent); }
.dup-bylink button { flex: none; display: inline-flex; align-items: center; gap: 6px; padding: 6px 14px; background: transparent;
  color: var(--accent); border: 1px solid var(--accent); border-radius: 999px; font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; }
.dup-bylink button:hover { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.dup-bylink button:disabled { opacity: .6; cursor: default; }

/* Mobile: stack each candidate (photo strip on top, meta full-width below). Side-by-side squeezes the meta into
   a sliver next to the 5-thumb strip and wraps every word onto its own line. */
/* When the CARD'S PANEL is narrow (the search dropdown on any screen, or either surface on a phone) the row
   layout can't fit photos + address + footer, so stack it: photos on top, then address, then a full-width
   button. Keyed to the container width (see .dup-body / #searchResults container-type), not the viewport. */
@container (max-width: 470px) {
  .dup-candidate { flex-direction: column; align-items: stretch; gap: 10px; }
  .dup-photos-col { align-items: stretch; }
  .dup-photos { flex-wrap: wrap; }
  .dup-metafoot { flex-direction: column; align-items: stretch; gap: 8px; }
  .dup-action { margin-left: 0; }
  .dup-merge, .dup-open { width: 100%; justify-content: center; }
}
