/* osm-shop-ui — front-end styles.
   Component styles are ported from the Askama edit.html template; the
   gallery layout is new. */

/* ── base ──────────────────────────────────────────────────────────────── */
* { box-sizing: border-box; }
body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  color: #1a1a1a;
  background: #f4f4f6;
  line-height: 1.5;
}
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.muted { color: #666; font-size: 0.85rem; }
.placeholder { max-width: 40rem; margin: 4rem auto; padding: 0 1rem; }

/* ── gallery ───────────────────────────────────────────────────────────── */
.gallery { max-width: 64rem; margin: 0 auto; padding: 1.5rem 1rem 4rem; }
.gallery-head { border-bottom: 2px solid #e2e2e6; padding-bottom: 1rem;
                margin-bottom: 1.5rem; }
.gallery-head h1 { margin: 0 0 0.25rem; font-size: 1.4rem; }

/* ── language switcher (page-global, top-right) ────────────────────────── */
.lang-switcher { position: fixed; top: 0.6rem; right: 0.6rem; z-index: 100; }
.lang-switcher select {
  border: 1px solid #c8d4e0; background: #fff; color: #2358a8;
  padding: 0.3rem 0.5rem; font-size: 0.85rem; border-radius: 6px;
  font-weight: 600; cursor: pointer;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
}

.gallery-section { margin-bottom: 2.5rem; }
.gallery-section h2 { font-size: 1.1rem; margin: 0 0 0.15rem;
                      border-bottom: 1px solid #e2e2e6; padding-bottom: 0.3rem; }
.demo-grid {
  display: grid; gap: 1rem; margin-top: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
}
.demo-case {
  background: #fff; border: 1px solid #e2e2e6; border-radius: 8px;
  padding: 0.9rem;
}
.demo-label { font-weight: 700; font-size: 0.9rem; margin-bottom: 0.5rem; }
.demo-output {
  margin-top: 0.6rem; font-size: 0.8rem; word-break: break-all;
  border-top: 1px dashed #e2e2e6; padding-top: 0.5rem;
}
.demo-output-key { color: #888; }
.demo-output code { color: #1a5e1a; }

/* ── gallery table of contents ─────────────────────────────────────────────
   Mobile-first: a wrapped row of links at the top of the page. Desktop
   (>=48rem): a sticky toolbar floating to the left of the content. */
.gallery-toc {
  display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: baseline;
  margin-bottom: 1.5rem; padding-bottom: 1rem;
  border-bottom: 1px solid #e2e2e6;
}
.gallery-toc-head {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; color: #8a8a92; margin-right: 0.3rem;
}
.gallery-toc-link {
  font-size: 0.85rem; color: #2358a8; text-decoration: none;
  padding: 0.3rem 0.65rem; border: 1px solid #c8d4e0;
  border-radius: 999px; background: #fff;
}
.gallery-toc-link:hover { background: #eef3fa; }
/* Anchor jumps land a little below the viewport top, not flush. */
.gallery-section { scroll-margin-top: 1rem; }

@media (min-width: 48rem) {
  .gallery { max-width: 76rem; }
  .gallery-body { display: flex; gap: 2rem; align-items: flex-start; }
  .gallery-toc {
    flex: 0 0 11rem; flex-direction: column; flex-wrap: nowrap;
    gap: 0.1rem; align-items: stretch;
    position: sticky; top: 1.5rem;
    margin: 0; padding: 0; border: none;
  }
  .gallery-toc-head { margin: 0 0 0.45rem; }
  .gallery-toc-link {
    border: none; border-left: 2px solid transparent; border-radius: 0;
    background: none; padding: 0.35rem 0.55rem;
  }
  .gallery-toc-link:hover { background: #eef3fa; border-left-color: #2358a8; }
  .gallery-sections { flex: 1; min-width: 0; }
}

/* ── opening-hours widget ──────────────────────────────────────────────── */
.oh { border: 1px solid #ddd; border-radius: 6px; padding: 0.75rem;
      background: #fcfcfc; }
.oh-empty-hint { color: #666; font-size: 0.85rem; font-style: italic;
                 margin-bottom: 0.5rem; padding: 0.4rem 0; text-align: center; }
.oh-12h-warn { background: #fff8e0; color: #6b5500; border: 1px solid #ffe5a0;
               padding: 0.4rem 0.6rem; font-size: 0.8rem; border-radius: 4px;
               margin-bottom: 0.6rem; line-height: 1.35; }
.oh-presets { display: flex; gap: 0.4rem; flex-wrap: wrap;
              margin-bottom: 0.75rem; padding-bottom: 0.6rem;
              border-bottom: 1px dashed #e0e0e0; }
.oh-preset { border: 1px solid #c8d4e0; background: #f0f6ff; color: #2358a8;
             padding: 0.3rem 0.65rem; font-size: 0.8rem; border-radius: 999px;
             cursor: pointer; line-height: 1; font-weight: 600; }
.oh-preset:active { background: #d8e6fa; }
/* Voice → opening_hours: a single big button beneath the presets row, with
   the live transcript / error in a small line below. */
.oh-voice { margin: 0.2rem 0 0.8rem; }
.oh-mic {
  border: 1px solid #c8d4e0; background: #fff; color: #2358a8;
  padding: 0.5rem 0.9rem; font-size: 0.95rem; border-radius: 8px;
  font-weight: 600; cursor: pointer; min-height: 2.4rem;
}
.oh-mic:active { background: #f0f6ff; }
.oh-mic:disabled { opacity: 0.6; cursor: default; }
.oh-voice-status {
  margin-top: 0.35rem; font-size: 0.85rem; color: #444;
  white-space: pre-wrap;
}
.oh-voice-status.err { color: #a14; }
.oh-row { display: grid; grid-template-columns: 3rem 1fr; gap: 0.6rem;
          align-items: start; padding: 0.5rem 0;
          border-bottom: 1px solid #f0f0f0; }
.oh-row:last-of-type { border-bottom: 0; }
.oh-pill { border: 0; border-radius: 999px; padding: 0.35rem 0;
           font-weight: 600; font-size: 0.85rem; cursor: pointer;
           text-align: center; line-height: 1; }
.oh-row[data-state="open"]   .oh-pill { background: #eaf2ff; color: #2358a8; }
.oh-row[data-state="closed"] .oh-pill { background: #f0f0f0; color: #999; }
.oh-body { min-width: 0; }
.oh-closed { color: #999; font-style: italic; font-size: 0.9rem; line-height: 2; }
/* Each time range is a distinct tinted card, so multiple ranges per day
   stay visually separate even when a card wraps onto two lines. The card
   being edited lifts via :focus-within. */
.oh-slot { display: flex; align-items: center; gap: 0.35rem; flex-wrap: wrap;
           margin-bottom: 0.35rem; padding: 0.3rem 0.4rem;
           background: #f4f7fb; border: 1px solid #e3e9f0; border-radius: 5px; }
.oh-slot:focus-within { background: #eaf2ff; border-color: #9bb8dd; }
/* No flex-grow: the browser sizes a time input to fit its locale's format,
   so every input on the page is the same width regardless of what else is
   in the row — and the AM/PM marker (12h locales) is never clipped. With
   flex-grow, a row with a remove button sized its inputs narrower than one
   without, clipping the marker inconsistently. */
.oh-time { flex: 0 0 auto; padding: 0.3rem 0.4rem;
           font-size: 0.9rem; font-variant-numeric: tabular-nums;
           border: 1px solid #ccc; border-radius: 4px; }
.oh-time.oh-bad { border-color: #d33; background: #fff5f5; }
.oh-dash { color: #888; }
.oh-allday { background: #eaf2ff; color: #2358a8; border: 1px solid #c8d4e0;
             border-radius: 4px; padding: 0.3rem 0.6rem; font-size: 0.85rem;
             font-weight: 600; white-space: nowrap; }
.oh-actions { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-top: 0.2rem; }
.oh-btn { border: 1px solid #d8d8d8; background: #fff; color: #555;
          padding: 0.25rem 0.55rem; font-size: 0.8rem; border-radius: 4px;
          cursor: pointer; line-height: 1.1; }
.oh-btn:active { background: #f0f0f0; }
.oh-btn.oh-rm { color: #b22; }
.oh-osm-preview { margin-top: 0.7rem; display: flex; gap: 0.4rem;
                  align-items: baseline; font-size: 0.8rem; flex-wrap: wrap; }
.oh-osm-key { color: #999; }
.oh-osm-val { color: #555; word-break: break-all; }
.oh-raw { margin-top: 0.5rem; font-size: 0.8rem; }
.oh-raw summary { color: #666; cursor: pointer; }
.oh-raw input { margin-top: 0.4rem; width: 100%; padding: 0.4rem;
                font-size: 0.85rem; font-family: ui-monospace, monospace;
                border: 1px solid #ccc; border-radius: 4px; }

/* ── business-type selector — combobox typeahead ─────────────────────────── */
.type-selector { border: 1px solid #ddd; border-radius: 6px; background: #fcfcfc;
                 padding: 0.75rem; }
.type-search {
    width: 100%; padding: 0.45rem 0.6rem; font-size: 0.95rem;
    border: 1px solid #ccc; border-radius: 6px; margin-bottom: 0.6rem;
}
/* empty-state category chips: responsive grid, one column on a phone */
.type-chips {
    display: grid; gap: 0.5rem;
    grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
}
.type-chip {
    display: flex; align-items: center; justify-content: space-between;
    gap: 0.5rem; cursor: pointer; text-align: left;
    background: #fff; border: 1px solid #dde3ea; border-radius: 8px;
    padding: 0.6rem 0.7rem; font-size: 0.9rem; font-weight: 600; color: #2b333c;
}
.type-chip:hover { border-color: #9bb8dd; background: #f4f7fb; }
.type-chip:focus-visible { outline: 2px solid #2358a8; outline-offset: 1px; }
.type-chip-count {
    font-size: 0.72rem; font-weight: 700; color: #5a6b7d; background: #eef2f6;
    border-radius: 999px; padding: 0.05rem 0.45rem;
}
.type-back {
    cursor: pointer; background: none; border: none; color: #2358a8;
    font-size: 0.85rem; padding: 0.2rem 0; margin-bottom: 0.3rem;
}
.type-back:hover { text-decoration: underline; }
.type-drill-head {
    font-size: 0.78rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.04em; color: #8a929b; margin-bottom: 0.35rem;
}
.type-list { list-style: none; margin: 0; padding: 0; }
.type-opt {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.15rem 0.5rem;
    width: 100%; text-align: left; cursor: pointer; background: #fff;
    border: 1px solid #e3e9f0; border-radius: 6px; padding: 0.45rem 0.55rem;
    margin-bottom: 0.25rem;
}
.type-opt:hover { border-color: #9bb8dd; background: #f4f7fb; }
.type-opt-active { border-color: #2358a8; background: #f4f7fb; }
.type-opt-sel { border-color: #2358a8; background: #eaf2ff; }
.type-opt-name { flex-basis: 100%; font-weight: 600; font-size: 0.92rem;
                 color: #1a1a1a; }
.type-opt-cat {
    font-size: 0.68rem; color: #5a6b7d; background: #eef2f6;
    border-radius: 4px; padding: 0.06rem 0.4rem; white-space: nowrap;
}
.type-opt-osm { font-family: ui-monospace, monospace; font-size: 0.76rem;
                color: #9aa3ad; overflow-wrap: anywhere; }
.type-empty { color: #888; font-style: italic; text-align: center;
              padding: 0.7rem; }

/* phone: the category chip grid collapses to a single column */
@media (max-width: 480px) {
    .type-chips { grid-template-columns: 1fr; }
}

/* ── flow: confirmation screen & editor chrome ─────────────────────────── */
.flow { max-width: 30rem; margin: 0 auto; padding: 2rem 1rem 4rem; }
.flow-card { background: #fff; border: 1px solid #e2e2e6; border-radius: 10px;
             padding: 1.5rem 1.25rem; box-shadow: 0 1px 6px rgba(0, 0, 0, 0.05); }
.flow-status { text-align: center; color: #666; padding: 1rem 0; }
.flow-error { color: #b22; }

/* Public root landing page — intentionally low-information. */
.landing-title { font-size: 1.3rem; margin: 0 0 1rem; }
.landing-card p { color: #444; line-height: 1.55; margin: 0 0 0.75rem; }
.landing-card p:last-child { margin-bottom: 0; }
.confirm-name { font-size: 1.35rem; margin: 0 0 0.2rem; }
.confirm-address { color: #666; font-size: 0.9rem; margin: 0 0 1.1rem; }
.confirm-type { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem;
                background: #f4f7fb; border: 1px solid #e3e9f0; border-radius: 6px;
                padding: 0.6rem 0.7rem; margin-bottom: 1.1rem; }
.confirm-type-label { font-size: 0.72rem; font-weight: 700; text-transform: uppercase;
                      letter-spacing: 0.05em; color: #8a929b; width: 100%; }
.confirm-type-name { font-weight: 600; }
.confirm-type-osm { font-family: ui-monospace, monospace; font-size: 0.78rem;
                    color: #9aa3ad; }
.confirm-q { font-weight: 600; margin: 0 0 0.9rem; }
.confirm-help { color: #555; line-height: 1.5; margin: 0 0 1rem; }
/* What-this-is intro at the bottom of the landing card. De-emphasised vs
   the actionable choices above; offset by a top rule so it reads as a
   separate orientation section. */
.confirm-intro {
  margin-top: 1.2rem; padding-top: 0.9rem;
  border-top: 1px solid #ebeef2;
}
.confirm-intro-p {
  color: #555; font-size: 0.88rem; line-height: 1.5;
  margin: 0 0 0.65rem;
}
.confirm-intro-p:last-child { margin-bottom: 0; }
.flow-actions { display: flex; flex-direction: column; gap: 0.5rem; }
.btn-primary, .btn-secondary, .btn-quiet {
  width: 100%; padding: 0.7rem 1rem; font-size: 0.95rem; border-radius: 7px;
  cursor: pointer; font-weight: 600; border: 1px solid transparent;
}
.btn-primary { background: #2358a8; color: #fff; }
.btn-primary:active { background: #1c4a8e; }
.btn-secondary { background: #fff; color: #2358a8; border-color: #c8d4e0; }
.btn-secondary:active { background: #eef3f9; }
.btn-quiet { background: transparent; color: #777; font-weight: 500; }
.btn-quiet:active { color: #333; }

/* ── dev test-nodes directory (debug only) ─────────────────────────────── */
.gallery-link { display: inline-block; margin-top: 0.6rem; font-size: 0.85rem;
                color: #2358a8; font-weight: 600; text-decoration: none; }
.test-nodes { max-width: 44rem; margin: 0 auto; padding: 1.5rem 1rem 4rem; }
.test-nodes-head { border-bottom: 2px solid #e2e2e6; padding-bottom: 1rem;
                   margin-bottom: 1.25rem; }
.test-nodes-head h1 { margin: 0 0 0.25rem; font-size: 1.4rem; }
.test-nodes-back { display: inline-block; margin-top: 0.6rem; font-size: 0.85rem;
                   color: #2358a8; font-weight: 600; text-decoration: none; }
.test-node-list { list-style: none; margin: 0; padding: 0; }
.test-node-list li { background: #fff; border: 1px solid #e3e9f0;
                     border-radius: 8px; padding: 0.75rem 0.85rem;
                     margin-bottom: 0.6rem; }
.test-node-head { display: flex; flex-direction: column; gap: 0.1rem; }
.test-node-name { font-weight: 700; color: #1a1a1a; }
.test-node-note { font-size: 0.85rem; color: #666; }
.test-node-ref { display: block; margin: 0.3rem 0; font-size: 0.75rem;
                 color: #9aa3ad; }
.test-node-open { display: inline-block; color: #2358a8; font-weight: 600;
                  text-decoration: none; font-size: 0.9rem; }
.test-node-tok { display: block; margin-top: 0.15rem; font-size: 0.72rem;
                 color: #9aa3ad; }
.test-node-gen { background: #2358a8; color: #fff; border: 0; border-radius: 6px;
                 padding: 0.4rem 0.85rem; font-size: 0.85rem; font-weight: 600;
                 cursor: pointer; }
.test-error { color: #b22; }
.test-nodes-foot { margin-top: 1.25rem; }

/* ── static reassurance map (landing screen) ───────────────────────────── */
/* Belt-and-braces inertness — see components/static_map.rs. MapOptions
   already kills the Leaflet handlers we control; pointer-events:none here
   kills box-zoom (shift+drag) and the grab-cursor that invites panning. */
.static-map { margin: 0 0 1.1rem; border: 1px solid #e3e9f0; border-radius: 8px;
              overflow: hidden; pointer-events: none; }
.static-map .dioxus-leaflet-container { height: 14rem; }
@media (min-width: 40rem) {
  .static-map .dioxus-leaflet-container { height: 18rem; }
}
/* Restore pointer-events on the OSM attribution — it's a legal requirement
   that the credit link stays clickable, even though the map itself is inert. */
.static-map .leaflet-control-attribution { pointer-events: auto; }
.static-map-caption { margin: 0.45rem 0.1rem 0; font-size: 0.85rem; color: #666;
                      text-align: center; pointer-events: auto; }

/* ── map-based node picker ─────────────────────────────────────────────── */
.map-picker { border: 1px solid #e3e9f0; border-radius: 8px; overflow: hidden; }
/* dioxus-leaflet 0.3.1 does not size the container itself (a fix is on its
   main branch, unreleased) — Leaflet needs an explicit height to mount. */
.map-picker .dioxus-leaflet-container { height: 360px; }
.map-picker-readout { padding: 0.5rem 0.7rem; font-size: 0.85rem; color: #555;
                      background: #f4f7fb; border-top: 1px solid #e3e9f0;
                      font-variant-numeric: tabular-nums; }
.map-picker-pick { font-weight: 600; color: #1a5e1a; }
.map-picker-warn { color: #b26b00; font-weight: 600; }
/* Locate-me toolbar above the map. Putting it in the normal flow rather
   than overlaying it on the map's stacking context sidesteps Leaflet's
   z-index dance and works at every screen width. */
.map-picker-controls {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.4rem 0.6rem;
  background: #f4f7fb; border-bottom: 1px solid #e3e9f0;
}
.map-picker-locate {
  display: inline-flex; align-items: center; gap: 0.35rem;
  padding: 0.35rem 0.7rem;
  background: #fff; border: 1px solid #c8d4e0; border-radius: 6px;
  font-size: 0.9rem; cursor: pointer;
}
.map-picker-locate:hover { background: #f0f6ff; }
.map-picker-locate:disabled { opacity: 0.6; cursor: default; }
.map-picker-locate-err {
  background: #fff3cd; border: 1px solid #ffe69c;
  color: #6a4900; padding: 0.25rem 0.5rem;
  border-radius: 6px; font-size: 0.8rem;
}

/* ── admin ─────────────────────────────────────────────────────────────── */
/* The top padding clears the fixed language switcher, so the nav never
   collides with it regardless of viewport width. */
.admin { max-width: 52rem; margin: 0 auto; padding: 3rem 1rem 4rem; }
.admin h1 { font-size: 1.4rem; margin: 0.4rem 0 1rem; }
.admin-error { color: #b22; }
.admin-nav { display: flex; flex-wrap: wrap; gap: 0.5rem 1rem;
             padding-bottom: 0.6rem; border-bottom: 2px solid #e2e2e6; }
.admin-nav a { color: #2358a8; text-decoration: none; font-weight: 600;
               font-size: 0.9rem; }
.admin-nav a.admin-nav-here { color: #1a1a1a; border-bottom: 2px solid #2358a8;
                              padding-bottom: 0.55rem; margin-bottom: -0.62rem; }
.admin-nav-logout { margin-left: auto; background: none;
                    border: 0; cursor: pointer; color: #2358a8; font-weight: 600;
                    font-size: 0.9rem; padding: 0; }
.token-list { list-style: none; margin: 0; padding: 0; }
.token-card { display: flex; align-items: center; gap: 0.75rem;
              background: #fff; border: 1px solid #e3e9f0; border-radius: 8px;
              padding: 0.6rem 0.8rem; margin-bottom: 0.5rem; }
.token-card-expired { opacity: 0.7; background: #faf7f3; }
.token-card-main { flex: 1; min-width: 0; }
.token-name { width: 100%; font-weight: 600; font-size: 0.95rem;
              border: 1px solid transparent; border-radius: 4px;
              padding: 0.2rem 0.3rem; background: transparent; }
.token-name:hover, .token-name:focus { border-color: #ccc; background: #fff; }
.token-meta { display: block; font-size: 0.78rem; color: #888;
              padding: 0.1rem 0.3rem; font-variant-numeric: tabular-nums; }
.token-card-stats { display: flex; gap: 0.6rem; font-size: 0.85rem; color: #555;
                    white-space: nowrap; font-variant-numeric: tabular-nums; }
.token-card-actions { display: flex; gap: 0.4rem; }
.token-link { color: #2358a8; text-decoration: none; font-weight: 600;
              font-size: 0.85rem; padding: 0.3rem 0.5rem; }
.token-delete { border: 1px solid #e2c8c8; background: #fff; color: #b22;
                border-radius: 5px; padding: 0.3rem 0.55rem; font-size: 0.85rem;
                cursor: pointer; }
/* Below tablet width the single-row card cannot fit the name, meta, stats
   and actions side by side — stack them so nothing is crushed. */
@media (max-width: 44rem) {
  .token-card { flex-direction: column; align-items: stretch; }
  .token-card-actions { flex-wrap: wrap; }
}
.stat-grid { display: grid; gap: 0.7rem; margin-top: 1rem;
             grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr)); }
.stat-card { background: #fff; border: 1px solid #e3e9f0; border-radius: 8px;
             padding: 0.8rem; text-align: center; }
.stat-value { font-size: 1.6rem; font-weight: 700; color: #2358a8;
              font-variant-numeric: tabular-nums; }
.stat-label { font-size: 0.8rem; color: #555; margin-top: 0.2rem; }
.stat-note { font-size: 0.75rem; color: #999; margin-top: 0.15rem; }
.gen-go { margin-top: 0.9rem; background: #2358a8; color: #fff; border: 0;
          border-radius: 6px; padding: 0.5rem 1rem; font-weight: 600;
          font-size: 0.9rem; cursor: pointer; }
.gen-go:disabled { opacity: 0.6; cursor: default; }
.gen-ok { font-weight: 600; color: #1a5e1a; margin: 0 0 0.5rem; }

/* Marker popup: open or mint a node's token in place. */
.node-popup { font-size: 0.85rem; min-width: 9rem; }
.node-popup-kind { color: #666; font-size: 0.8rem; }
.node-popup-label { display: block; font-weight: 600; color: #555;
                    font-size: 0.75rem; margin: 0.5rem 0 0.15rem; }
.node-popup select { width: 100%; padding: 0.3rem 0.4rem; font-size: 0.85rem;
                     border: 1px solid #ccc; border-radius: 5px; }
.node-popup .gen-go { width: 100%; margin-top: 0.5rem; padding: 0.4rem 0.6rem; }
.node-popup-ok { font-weight: 600; color: #1a5e1a; margin: 0.5rem 0 0.3rem; }
.node-popup-note { color: #555; margin: 0.5rem 0 0.3rem; }
.node-popup-err { color: #b22; margin: 0.4rem 0 0; font-size: 0.8rem; }
.node-popup-link { display: block; margin-top: 0.35rem; }
/* Three side-by-side action chips in the popup of an existing token: edit
   page, QR PDF, manage. On a phone-width popup (Leaflet caps at ~16 rem),
   three chips fit in a single row; flex-wrap drops the third onto a new
   line on the narrowest popups rather than crushing the labels. */
.node-popup-actions { display: flex; flex-wrap: wrap; gap: 0.3rem;
                      margin-top: 0.4rem; }
.popup-action { flex: 1 1 auto; min-width: 4.2rem; text-align: center;
                padding: 0.4rem 0.55rem; border-radius: 5px;
                background: #eaf0f7; color: #2358a8;
                border: 1px solid #cfdcec; text-decoration: none;
                font-weight: 600; font-size: 0.82rem;
                white-space: nowrap; }
.popup-action:hover, .popup-action:focus {
  background: #2358a8; color: #fff; border-color: #2358a8; }
/* Deprioritized look for actions on an expired token — still tappable so the
   admin can reprint the QR or jump to the manage page to renew. */
.node-popup-actions-expired .popup-action {
  background: #f5f5f5; color: #777; border-color: #ddd; }
.node-popup-actions-expired .popup-action:hover,
.node-popup-actions-expired .popup-action:focus {
  background: #777; color: #fff; border-color: #777; }
.set-block { background: #fff; border: 1px solid #e3e9f0; border-radius: 8px;
             padding: 1rem; margin-bottom: 0.8rem; }
.set-block h2 { font-size: 1rem; margin: 0 0 0.5rem; }
.set-block label { display: block; font-size: 0.8rem; font-weight: 600;
                   color: #555; margin: 0.55rem 0 0.2rem; }
.set-block input { width: 100%; padding: 0.4rem 0.5rem; font-size: 0.9rem;
                   border: 1px solid #ccc; border-radius: 5px; }
.set-block a.token-link { display: inline-block; margin: 0.4rem 0; }
.danger-btn { background: #fff; color: #b22; border: 1px solid #e2c8c8;
              border-radius: 6px; padding: 0.45rem 0.9rem; font-weight: 600;
              font-size: 0.9rem; cursor: pointer; }
.tok-active { color: #1a5e1a; font-weight: 600; }
.tok-expired { color: #b22; font-weight: 600; }

/* Login / first-run setup pages. */
.auth-page { max-width: 22rem; margin: 3rem auto; padding: 0 1rem; }
.auth-page h1 { font-size: 1.3rem; margin: 0 0 0.6rem; }
.auth-form { background: #fff; border: 1px solid #e3e9f0; border-radius: 8px;
             padding: 1rem; }
.auth-form label { display: block; font-size: 0.8rem; font-weight: 600;
                   color: #555; margin: 0.6rem 0 0.2rem; }
.auth-form label:first-child { margin-top: 0; }
.auth-form input { width: 100%; padding: 0.4rem 0.5rem; font-size: 0.9rem;
                   border: 1px solid #ccc; border-radius: 5px; }
.auth-form .gen-go { width: 100%; }

/* Guided editor (ADR 005). */
.editor { max-width: 32rem; margin: 1.5rem auto; padding: 0 1rem; }
.editor-section { background: #fff; border: 1px solid #e3e9f0; border-radius: 8px;
                  padding: 1rem; margin-bottom: 0.9rem; }
.editor-section-title { font-size: 1.05rem; margin: 0 0 0.7rem; }
.editor-label { display: block; font-size: 0.8rem; font-weight: 600;
                color: #555; margin: 0 0 0.25rem; }
.editor-input { width: 100%; padding: 0.45rem 0.55rem; font-size: 0.95rem;
                border: 1px solid #ccc; border-radius: 6px; }
.editor-diff { list-style: none; margin: 0.5rem 0; padding: 0;
               font-family: ui-monospace, monospace; font-size: 0.85rem; }
.editor-diff li { padding: 0.2rem 0.4rem; border-radius: 4px; margin-bottom: 0.15rem;
                  word-break: break-word; display: flex; align-items: flex-start;
                  gap: 0.4rem; }
.editor-diff .diff-text { flex: 1; min-width: 0; }
/* Per-diff-entry undo button. Hovers on the right of each row; reverts
   just that one tag to its loaded-from-OSM value. */
.diff-undo {
  flex: 0 0 auto; cursor: pointer; background: transparent; border: 1px solid transparent;
  color: #5a6b7d; border-radius: 4px; padding: 0.05rem 0.35rem; font-size: 1rem;
  line-height: 1; font-family: inherit;
}
.diff-undo:hover, .diff-undo:focus {
  background: #fff; border-color: #c8d4e0; color: #2358a8;
}
.diff-add { background: #e7f6e7; color: #1a5e1a; }
.diff-del { background: #fbe9e9; color: #b22; }
.diff-mod { background: #f4f7fb; }
.diff-old { color: #b22; text-decoration: line-through; }
.diff-new { color: #1a5e1a; }
.editor-saved { font-weight: 600; color: #1a5e1a; margin: 0.6rem 0;
                 padding: 0.55rem 0.7rem; background: #e7f6e7; border-radius: 6px;
                 border: 1px solid #c6e6c6; }
/* Post-save section: stays-open hint + osm.org link + geo: deep-link.
   Shown beneath the editor only after a successful save. */
.editor-post-save { margin-top: 0.9rem; padding: 0.9rem; background: #f4f7fb;
                    border: 1px solid #d8e4f0; border-radius: 8px; }
.post-save-hint { margin: 0 0 0.7rem; color: #2b333c; font-size: 0.92rem;
                  line-height: 1.4; }
.post-save-links { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.post-save-link { display: inline-block; padding: 0.5rem 0.8rem; border-radius: 6px;
                  background: #fff; border: 1px solid #c8d4e0; color: #2358a8;
                  text-decoration: none; font-weight: 600; font-size: 0.9rem; }
.post-save-link:hover, .post-save-link:focus {
  background: #2358a8; color: #fff; border-color: #2358a8; }
/* Android-only deep-link — soft styling so a user on an OS that ignores
   `geo:` doesn't perceive it as the primary action. */
.post-save-link-app { color: #5a6b7d; }
.editor .btn-primary { margin-top: 0.7rem; }
.editor-type-current { display: flex; align-items: baseline; gap: 0.5rem;
                       flex-wrap: wrap; }
.editor-type-name { font-weight: 600; font-size: 1rem; }
.editor-type-osm { font-family: ui-monospace, monospace; font-size: 0.8rem;
                   color: #9aa3ad; margin-right: auto; }
.editor-tag-row { display: flex; flex-wrap: wrap; align-items: center;
                  gap: 0.25rem 0.4rem; margin-bottom: 0.45rem; }
.editor-tag-key { flex-basis: 100%; font-family: ui-monospace, monospace;
                  font-size: 0.78rem; color: #5a6b7d; word-break: break-all; }
.editor-tag-row .editor-input { flex: 1; }
.editor-tag-del { flex: 0 0 auto; width: 1.9rem; height: 1.9rem; cursor: pointer;
                  background: #fff; border: 1px solid #e2c8c8; color: #b22;
                  border-radius: 5px; font-size: 1rem; line-height: 1; }
/* Add-a-tag block — set apart from the existing tag rows above it. */
.editor-tag-new { border-top: 1px solid #e3e9f0; margin-top: 0.9rem;
                  padding-top: 0.85rem; }
.editor-tag-new-hint { font-size: 0.8rem; color: #777; margin: 0 0 0.55rem; }
.editor-tag-new-row { display: flex; flex-wrap: wrap; gap: 0.4rem;
                      margin-bottom: 0.55rem; }
.editor-tag-new-row .editor-input { flex: 1 1 7rem; }
.editor-tag-add-btn { width: auto; }
.field-row { margin-bottom: 0.75rem; }
/* Label row: label on the left, optional per-field reset (↺) on the right.
   align-items baseline keeps the icon and the button on the same baseline
   as the label text. */
.field-row-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 0.4rem;
}
.field-reset {
  flex-shrink: 0;
  background: transparent; border: none; cursor: pointer;
  padding: 0.1rem 0.4rem;
  color: #2358a8; font-size: 1.05rem; line-height: 1;
  border-radius: 4px;
}
.field-reset:hover { background: #eaf2ff; color: #1a4d8f; }
select.editor-input { background: #fff; }

/* addr:street combobox — a custom focus-driven nearby-streets dropdown
   (a reliable replacement for <datalist>). */
.street-combo { position: relative; }
.street-suggest {
  position: absolute; top: calc(100% + 0.15rem); left: 0; right: 0; z-index: 20;
  margin: 0; padding: 0.2rem; list-style: none;
  background: #fff; border: 1px solid #c8d4e0; border-radius: 6px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.14);
  max-height: 14rem; overflow-y: auto;
}
.street-opt {
  padding: 0.55rem 0.6rem; border-radius: 4px; cursor: pointer;
  font-size: 0.95rem; color: #1a1a1a;
}
.street-opt:hover, .street-opt-active {
  background: #eaf2ff; color: #1a4d8f;
}

/* semiCombo widget (cuisine, sport, clothes, …): a row of chips followed by
   a free-typing input; the input keeps focus throughout so soft-keyboard
   Backspace can arm and then delete chips Thunderbird-style. */
.semicombo { position: relative; }
.semicombo-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem;
  padding: 0.3rem;
  background: #fff;
  border: 1px solid #c8d4e0; border-radius: 6px;
  min-height: 2.6rem;
}
.semicombo-row:focus-within { border-color: #6f9bd3; }
.semicombo-chip {
  display: inline-flex; align-items: center; gap: 0.1rem;
  background: #eaf2ff; color: #1a4d8f;
  border: 1px solid #c8dcf5; border-radius: 999px;
  padding: 0.1rem 0.1rem 0.1rem 0.6rem;
  font-size: 0.92rem; line-height: 1.4;
  cursor: pointer; user-select: none;
}
/* The armed state — visible signal that the next Backspace will delete. */
.semicombo-chip-armed {
  background: #fde2a8; border-color: #e0a93b; color: #5a3a00;
}
.semicombo-chip-label { white-space: nowrap; }
/* The canonical OSM value shown muted alongside the human label, in a mono
   font to read as a machine identifier — transparency about what we'll
   write to OSM. */
.semicombo-chip-osm {
  margin-left: 0.3rem;
  padding: 0;
  background: transparent;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.78rem;
  color: #5a6b7d;
}
.semicombo-chip-armed .semicombo-chip-osm { color: #7a5400; }
.semicombo-chip-x {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.6rem; height: 1.6rem;
  border-radius: 999px;
  background: transparent; color: inherit;
  font-size: 1rem; line-height: 1; cursor: pointer;
}
.semicombo-chip-x:hover { background: rgba(0, 0, 0, 0.1); }
.semicombo-input {
  flex: 1 1 6rem; min-width: 5rem;
  border: none; outline: none; background: transparent;
  padding: 0.25rem 0.2rem;
}
.semicombo-suggest {
  position: absolute; top: calc(100% + 0.15rem); left: 0; right: 0; z-index: 20;
  margin: 0; padding: 0.2rem; list-style: none;
  background: #fff; border: 1px solid #c8d4e0; border-radius: 6px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.14);
  max-height: 14rem; overflow-y: auto;
}
.semicombo-opt {
  padding: 0.55rem 0.6rem; border-radius: 4px; cursor: pointer;
  font-size: 0.95rem; color: #1a1a1a;
  /* Keep label + OSM value on a single line; overflow visibly past the
     dropdown's right edge rather than wrapping (per user request). */
  white-space: nowrap;
}
.semicombo-opt:hover, .semicombo-opt-active {
  background: #eaf2ff; color: #1a4d8f;
}
.semicombo-opt-osm {
  margin-left: 0.4rem;
  padding: 0;
  background: transparent;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.82rem;
  color: #5a6b7d;
}
.semicombo-opt-active .semicombo-opt-osm { color: #1a4d8f; opacity: 0.7; }
.semicombo-hint {
  margin: 0.3rem 0 0; font-size: 0.85rem; color: #5a6b7d;
}

/* Contact group: visually-grouped card holding website + social platform
   inputs, so they read as one block rather than ten loose fields. */
.contact-group {
  margin: 0.7rem 0;
  padding: 0.6rem 0.85rem 0.5rem;
  border: 1px solid #d8e4f0;
  border-radius: 8px;
  background: #fafcff;
}
.contact-group-title {
  padding: 0 0.4rem;
  font-weight: 600;
  font-size: 0.95rem;
  color: #2358a8;
}
/* Tighten the field-row vertical spacing inside the block so the card
   doesn't dwarf its surroundings. */
.contact-group .field-row { margin-bottom: 0.45rem; }
.contact-group .field-row:last-child { margin-bottom: 0.1rem; }
/* Brand/globe glyph next to each contact-group label. Sits inline with the
   label text so the icon + label form one visual unit above the input.
   SVGs loaded via <img> render in an isolated context — `color`/
   `currentColor` from the parent doesn't reach the SVG fill — so the
   brand icons paint in their default black (no fill attribute set) and
   the globe in its stroke=currentColor evaluated inside the SVG (also
   black). Monochrome by design; if we ever want per-brand colours we'd
   switch to CSS mask-image. */
.contact-icon {
  display: inline-block;
  width: 1rem;
  height: 1rem;
  margin-right: 0.4rem;
  vertical-align: -2px;
}

/* Reverse-geocode confirmation banner: appears above the addr:* inputs when
   Nominatim has post code / city values to propose and at least one is
   missing in the form. The "Use these" button only fills empty subkeys, so
   it can never silently overwrite something the user typed. */
.addr-suggest {
  margin: 0 0 0.8rem; padding: 0.7rem 0.85rem;
  background: #f4f7fb; border: 1px solid #d8e4f0; border-radius: 8px;
}
.addr-suggest-intro { margin: 0 0 0.35rem; font-size: 0.9rem; color: #2b333c; }
.addr-suggest-list { list-style: none; margin: 0 0 0.55rem; padding: 0;
                     font-size: 0.92rem; }
.addr-suggest-list li { padding: 0.1rem 0; }
.addr-suggest-label { color: #5a6b7d; }
.addr-suggest-value { font-weight: 600; color: #1a1a1a; }
.addr-suggest-apply { padding: 0.4rem 0.85rem; font-size: 0.9rem; }
.editor-collapse { cursor: pointer; user-select: none; }
.editor-collapse-mark { color: #9aa3ad; font-size: 0.85rem; }
