/* =============================================================================
   styles-v2.css — StroomkaartV2-specific CSS additions
   -----------------------------------------------------------------------------
   This file layers on top of styles-designer.css (the verbatim designer
   stylesheet). Everything in here is a V2-specific addition or override that
   was authored by the engineering team, NOT by the designer.

   Loading order in HTML must be:
     <link rel="stylesheet" href="/assets/css/styles-designer.css">
     <link rel="stylesheet" href="/assets/css/styles-v2.css">

   When the designer pushes a fresh styles.css, drop it in as
   styles-designer.css and leave this file untouched.

   Sections below are grouped by topic. Each block carries the commit / feature
   that introduced it for traceability.
   ============================================================================= */


/* -----------------------------------------------------------------------------
   1. Status palette — V2 semantic rename
   -----------------------------------------------------------------------------
   Designer ships only --sk-status-soon / --sk-status-occupied. The V2 backend
   uses --maintenance / --out_of_service as the canonical status names. We add
   the V2 names as authoritative, then keep the designer's names as aliases so
   any rules still using --sk-status-soon / --sk-status-occupied keep working
   until the designer's stylesheet stops referencing them.
   --------------------------------------------------------------------------- */
:root {
  --sk-status-maintenance:    #d49a1a;
  --sk-status-out_of_service: #b6433a;
  /* Legacy aliases — designer's stylesheet still references these names. */
  --sk-status-soon:           var(--sk-status-maintenance);
  --sk-status-occupied:       var(--sk-status-out_of_service);
}


/* -----------------------------------------------------------------------------
   2. Status classes — V2 semantic rename (filter chip / status tag / marker)
   -----------------------------------------------------------------------------
   Companion to section 1: the markup uses --maintenance / --out_of_service as
   class suffixes. Designer's stylesheet already supplies --soon / --occupied
   variants; these add the V2-named equivalents.
   --------------------------------------------------------------------------- */
.filter-chip__dot--maintenance    { background: var(--sk-status-maintenance); }
.filter-chip__dot--out_of_service { background: var(--sk-status-out_of_service); }

.status-tag--maintenance { background: rgba(212, 154, 26, 0.14); color: #8e6611; }
.status-tag--maintenance::before { background: var(--sk-status-maintenance); }
.status-tag--out_of_service { background: rgba(182, 67, 58, 0.12); color: var(--sk-status-out_of_service); }
.status-tag--out_of_service::before { background: var(--sk-status-out_of_service); }

.sk-marker--maintenance    { background: var(--sk-status-maintenance); }
.sk-marker--out_of_service { background: var(--sk-status-out_of_service); }


/* -----------------------------------------------------------------------------
   3. Map header — search dropdown (autocomplete results)
   -----------------------------------------------------------------------------
   Public-map header search component. Pure V2 — not in designer's stylesheet.
   --------------------------------------------------------------------------- */
.map-search__results {
  position: absolute;
  top: calc(100% + 4px); left: 0; right: 0;
  background: var(--sk-white);
  border: 1px solid var(--sk-border-strong);
  box-shadow: 0 12px 28px rgba(10, 42, 92, 0.18);
  max-height: 360px; overflow-y: auto;
  z-index: 1000;
}
.map-search__group {
  padding: 8px 14px 4px;
  font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--sk-muted);
  background: var(--sk-surface);
}
.map-search__row {
  display: block; width: 100%;
  padding: 10px 14px;
  border: 0; background: transparent;
  text-align: left; cursor: pointer;
  font-size: 13px; color: var(--sk-navy-800);
  border-bottom: 1px solid var(--sk-border);
}
.map-search__row:last-child { border-bottom: 0; }
.map-search__row:hover,
.map-search__row:focus { background: var(--sk-blue-100); outline: 0; }
.map-search__row-meta { font-size: 11.5px; color: var(--sk-muted); margin-top: 2px; }
.map-search__empty { padding: 14px; font-size: 13px; color: var(--sk-muted); }

/* Leaflet ships `.leaflet-top` / `.leaflet-bottom` at z-index 1000, which is
   the same layer as the sticky nav and our search dropdown — the zoom and
   attribution controls end up stacking above stuff that should sit on top
   of them. Drop to 400 so the controls live under the detail drawer (500),
   legend (500), draw toast/toolbar (600), search dropdown (1000), and modals
   (5000), but still above the map tiles. */
.leaflet-top,
.leaflet-bottom { z-index: 400 !important; }


/* -----------------------------------------------------------------------------
   4. Admin bar — language switcher recolouring
   -----------------------------------------------------------------------------
   Designer's .lang-switcher is styled for a light background. The admin top
   bar is dark navy, so we recolour the switcher when nested inside .admin-bar.
   --------------------------------------------------------------------------- */
.admin-bar .lang-switcher {
  background: transparent;
  border: 1px solid rgba(255,255,255,0.25);
}
.admin-bar .lang-switcher button {
  color: rgba(255,255,255,0.85);
}
.admin-bar .lang-switcher button + button {
  border-left-color: rgba(255,255,255,0.18);
}
.admin-bar .lang-switcher button:hover {
  background: rgba(255,255,255,0.12);
  color: var(--sk-white);
}
.admin-bar .lang-switcher button.is-active {
  background: var(--sk-blue-300);
  color: var(--sk-navy-900);
}


/* -----------------------------------------------------------------------------
   5. Lang-switcher visibility — make the `hidden` attribute work
   -----------------------------------------------------------------------------
   Designer's rule is `.lang-switcher { display: inline-flex; }` (and similar
   for .nav__lang-switcher-mobile). That high-specificity display value beats
   the user-agent `[hidden] { display: none; }`, so the language switcher stays
   visible even when we set the `hidden` attribute to suppress it for brands
   with only one language (e.g. Bristol). Override with an explicit !important
   on [hidden] so the designer's rule keeps working otherwise.

   Originally introduced in commit ce24350 as `:not([hidden])` qualifiers on
   the designer's rules — moved here as an !important override so it survives
   future designer-stylesheet edits.
   --------------------------------------------------------------------------- */
.lang-switcher[hidden],
.nav__lang-switcher-mobile[hidden] {
  display: none !important;
}


/* -----------------------------------------------------------------------------
   6. Admin auth-pending DOM gate
   -----------------------------------------------------------------------------
   Admin pages set body[data-auth-pending] before Cognito has confirmed the
   user is signed in, so unauthenticated DOM doesn't flash. ::before paints a
   neutral surface, ::after paints a small spinner — both stay visible because
   visibility cascades to children but pseudo-elements can be re-shown
   explicitly. Introduced in commit 9b2b6ff.
   --------------------------------------------------------------------------- */
body[data-auth-pending] { visibility: hidden; }
body[data-auth-pending]::before {
  content: "";
  visibility: visible;
  position: fixed;
  inset: 0;
  background: var(--sk-surface);
  z-index: 9999;
}
body[data-auth-pending]::after {
  content: "";
  visibility: visible;
  position: fixed;
  top: 50%;
  left: 50%;
  width: 32px;
  height: 32px;
  margin: -16px 0 0 -16px;
  border: 3px solid var(--sk-border);
  border-top-color: var(--sk-navy-800);
  border-radius: 50%;
  animation: sk-auth-spin 0.8s linear infinite;
  z-index: 10000;
}
@keyframes sk-auth-spin {
  to { transform: rotate(360deg); }
}


/* -----------------------------------------------------------------------------
   7. Admin app-settings — inline editable value cell
   -----------------------------------------------------------------------------
   Used by the admin AppSettings page for inline-edit inputs. Introduced in
   commit 09097e7.
   --------------------------------------------------------------------------- */
.setting-value {
  width: 100%;
  font-family: inherit;
  font-size: 13px;
  padding: 8px 12px;
  border: 1px solid var(--sk-border-strong);
  background: var(--sk-white);
  color: var(--sk-navy-800);
  outline: none;
}
.setting-value:focus { border-color: var(--sk-navy-700); }


/* -----------------------------------------------------------------------------
   8. Admin tables — inline row actions (Edit / Delete)
   -----------------------------------------------------------------------------
   Compact icon+label buttons used inside admin list-table rows. The danger
   variant is used for Delete. Container <td class="row-actions"> right-aligns
   its children.
   --------------------------------------------------------------------------- */
.row-actions {
  text-align: right;
  vertical-align: middle;
  white-space: nowrap;
}
.row-actions .row-action + .row-action { margin-left: 6px; }
.row-action {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 10px;
  font-size: 12px;
  font-weight: 500;
  font-family: inherit;
  line-height: 1.2;
  border: 1px solid var(--sk-border-strong);
  background: var(--sk-white);
  color: var(--sk-navy-800);
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.row-action:hover {
  background: var(--sk-blue-100);
  border-color: var(--sk-blue-500);
  color: var(--sk-navy-900);
}
.row-action svg {
  width: 12px;
  height: 12px;
}
.row-action--danger { color: var(--sk-status-occupied); }
.row-action--danger:hover {
  background: rgba(182, 67, 58, 0.08);
  border-color: var(--sk-status-occupied);
  color: var(--sk-status-occupied);
}


/* -----------------------------------------------------------------------------
   9. Public-map — detail panel image gallery
   -----------------------------------------------------------------------------
   Horizontal scrolling thumbnail strip shown in the public-map detail panel.
   --------------------------------------------------------------------------- */
.map-detail__gallery {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  margin-top: 14px;
  padding-bottom: 4px;
  scrollbar-width: thin;
}
.map-detail__gallery-item {
  flex: 0 0 auto;
  display: block;
  width: 100px;
  height: 140px;
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid var(--sk-border);
  background: var(--sk-blue-100);
}
.map-detail__gallery-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 200ms ease;
}
.map-detail__gallery-item:hover img {
  transform: scale(1.04);
}


/* -----------------------------------------------------------------------------
   10. Admin power-station — image gallery + uploader
   -----------------------------------------------------------------------------
   Grid of image tiles with hover-revealed action buttons (delete / promote).
   Used on the admin power-station edit page.
   --------------------------------------------------------------------------- */
.ps-gallery {
  margin-top: 24px;
}
.ps-gallery__hint {
  font-size: 12.5px;
  color: var(--sk-muted);
  margin: 0 0 12px;
}
.ps-gallery__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 12px;
  margin: 12px 0;
}
.ps-gallery__empty {
  font-size: 13px;
  color: var(--sk-muted);
  font-style: italic;
  margin: 8px 0 16px;
}
.ps-gallery__tile {
  position: relative;
  margin: 0;
  border: 1px solid var(--sk-border);
  border-radius: 6px;
  overflow: hidden;
  background: var(--sk-blue-100);
  aspect-ratio: 4 / 3;
}
.ps-gallery__tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.ps-gallery__actions {
  position: absolute;
  top: 6px;
  right: 6px;
  display: flex;
  gap: 4px;
  opacity: 0;
  transition: opacity 120ms ease;
}
.ps-gallery__tile:hover .ps-gallery__actions,
.ps-gallery__tile:focus-within .ps-gallery__actions {
  opacity: 1;
}
.ps-gallery__btn {
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(10, 42, 92, 0.85);
  color: #fff;
  border: 0;
  border-radius: 4px;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
}
.ps-gallery__btn:disabled {
  opacity: 0.4;
  cursor: default;
}
.ps-gallery__btn--danger {
  background: rgba(182, 67, 58, 0.9);
}
.ps-gallery__uploader {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 8px;
}
.ps-gallery__uploader input[type="file"] {
  font-size: 13px;
}


/* -----------------------------------------------------------------------------
   N. Area-request modal: size to content instead of stretching to max-height
   -----------------------------------------------------------------------------
   Designer's `.modal` declares `display: flex; flex-direction: column;
   max-height: calc(100vh - 48px)`, with `.modal__body { flex: 1;
   overflow-y: auto }` intended to fill the remaining space and scroll. That
   pattern is for the admin modals (manual aanvraag, installatiepartij), whose
   structure is a flat `.modal__head` / `.modal__body` / `.modal__foot`.

   The area-request modal on the map page wraps the head+body in an extra
   `<div id="area-modal-body">` so polygon.ts can toggle form/success states
   with a single style.display flip. That wrapper breaks the flex chain:
   `.modal__body { flex: 1 }` is no longer a direct child of a flex parent, so
   it doesn't grow — and because nothing else has flex-grow, the foot anchors
   to the bottom of the max-height modal while the form sits at the top with
   a visible gap between them.

   Easiest fix: opt this modal out of the flex/max-height layout and let it
   size to its content. The form is short enough that body-scroll isn't
   needed; if the viewport is genuinely small the overlay can scroll instead.
   --------------------------------------------------------------------------- */
#area-modal {
  align-items: flex-start;
  overflow-y: auto;
}
#area-modal .modal {
  display: block;
  max-height: none;
  margin: 24px auto;
}


/* -----------------------------------------------------------------------------
   N+1. Area-cta delete button (shown when a polygon is drawn but not submitted)
   -----------------------------------------------------------------------------
   Companion to the "Teken een gebied" primary CTA. Hidden by default
   (`hidden` HTML attribute); polygon.ts toggles it visible after finish() and
   hides it again on reset()/closeModal(). Visually a small ghost-style action
   under the primary button — tinted with the "out of service" colour so it
   reads as destructive without screaming for attention.
   --------------------------------------------------------------------------- */
.area-cta__delete-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  margin-top: 8px;
  padding: 10px 14px;
  background: transparent;
  color: var(--sk-status-out_of_service);
  border: 1px solid var(--sk-border);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.area-cta__delete-btn:hover {
  background: rgba(182, 67, 58, 0.08);
  border-color: var(--sk-status-out_of_service);
}
.area-cta__delete-btn svg {
  width: 14px; height: 14px;
}


/* -----------------------------------------------------------------------------
   N+1.3. Buttons — destructive variant
   -----------------------------------------------------------------------------
   Designer ships .btn--primary (navy) and .btn--ghost. Confirm-delete modals
   need a primary red so the destructive intent is obvious without a custom
   colour at each call site.
   --------------------------------------------------------------------------- */
.btn--danger {
  background: var(--sk-status-occupied);
  color: var(--sk-white);
}
.btn--danger:hover { background: #993128; }

/* -----------------------------------------------------------------------------
   N+1.4. Admin forms — fieldsets, labels, actions, response banners
   -----------------------------------------------------------------------------
   Admin create/edit pages (water-points, power-stations, users, organisations,
   …) build their forms from JS using `.form-group` (fieldset), `.form-field`
   (label wrapping a <span> + input), `.form-actions`, `.btn-link`,
   `.success-box`, and `.login-error`. Most of these classes had no rules, so
   the form rendered as raw HTML below the styled <input>s. Add the missing
   structure + visible response banners. Scoped under `.admin-main` so the
   rules only land on admin shell pages.
   --------------------------------------------------------------------------- */
.admin-main .form-group {
  border: 1px solid var(--sk-border);
  border-radius: var(--r-sm);
  background: var(--sk-white);
  padding: 18px 22px 6px;
  margin: 0 0 20px;
}
.admin-main .form-group > legend {
  padding: 0 8px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sk-muted);
}
.admin-main .form-field > span {
  display: block;
  font-size: 13px;
  font-weight: 500;
  color: var(--sk-navy-800);
  margin-bottom: 6px;
}
.admin-main .form-field > input,
.admin-main .form-field > select,
.admin-main .form-field > textarea {
  margin-bottom: 6px;
}
.admin-main .form-field--required > span::after {
  content: " *";
  color: var(--sk-status-occupied);
}
.admin-main .form-field--check {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
  margin-bottom: 6px;
}
.admin-main .form-field--check > input[type="checkbox"] {
  width: auto;
  margin: 0;
}
.admin-main .form-field--check > span {
  margin: 0;
  font-size: 14px;
  color: var(--sk-navy-800);
}
.admin-main .form-actions {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 8px;
}
.admin-main .btn-link {
  font-size: 14px;
  color: var(--sk-navy-700);
  text-decoration: underline;
}
.admin-main .btn-link:hover { color: var(--sk-navy-900); }
.admin-main input[type="file"] {
  padding: 8px 10px;
  font-size: 13px;
  color: var(--sk-navy-800);
}
.admin-main input[type="file"]::file-selector-button {
  appearance: none;
  margin-right: 12px;
  padding: 6px 14px;
  border-radius: var(--r-pill);
  border: 1px solid var(--sk-border-strong);
  background: transparent;
  color: var(--sk-navy-800);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.admin-main input[type="file"]::file-selector-button:hover {
  background: var(--sk-navy-800);
  color: var(--sk-white);
  border-color: var(--sk-navy-800);
}
.admin-main input[type="file"]:focus {
  outline: none;
}
.admin-main input[type="file"]:focus::file-selector-button {
  box-shadow: 0 0 0 3px rgba(20, 58, 120, 0.18);
}
.success-box,
.login-error {
  padding: 12px 16px;
  border-radius: var(--r-sm);
  font-size: 14px;
  font-weight: 500;
  margin: 0 0 16px;
}
.success-box[hidden],
.login-error[hidden] { display: none; }
.success-box {
  background: #e8f5ec;
  color: #15532c;
  border: 1px solid #b6deb8;
}
.login-error {
  background: #fdecec;
  color: #8a1f1f;
  border: 1px solid #f4b9b9;
}

/* -----------------------------------------------------------------------------
   N+1.45. Admin tables — inline status edit select
   -----------------------------------------------------------------------------
   The AC/DC charging-station lists drop a status <select> into the row so
   the importer-managed columns can still be tweaked manually. Without a
   rule it renders as the browser's default control — give it the same look
   as the form-field select on edit pages so the visual language is shared.
   --------------------------------------------------------------------------- */
.admin-main select.cs-status {
  width: 100%;
  padding: 8px 12px;
  font-family: inherit;
  font-size: 13px;
  color: var(--sk-navy-800);
  background: var(--sk-white);
  border: 1px solid var(--sk-border-strong);
  border-radius: var(--r-sm);
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.admin-main select.cs-status:focus {
  outline: none;
  border-color: var(--sk-navy-700);
  box-shadow: 0 0 0 3px rgba(20, 58, 120, 0.12);
}

/* -----------------------------------------------------------------------------
   N+1.5. Admin tables — paginator alignment
   -----------------------------------------------------------------------------
   The `.pagination` block lives below every admin list (power stations, water
   points, AC/DC chargers, audit logs). Without a rule it flows as a plain
   block, leaving the prev / pageinfo / next trio flush-left. Center the trio
   under the table instead.
   --------------------------------------------------------------------------- */
.pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 14px;
  margin-top: 16px;
}
.pagination .btn {
  padding: 9px 14px;
  font-size: 13px;
}
.pagination .btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}
.pagination .btn:disabled:hover {
  background: transparent;
  color: var(--sk-navy-800);
  border-color: var(--sk-border-strong);
  transform: none;
}

/* -----------------------------------------------------------------------------
   N+2. Map page — mobile filter UX (horizontal chip bar)
   -----------------------------------------------------------------------------
   Designer's mobile layout pins a fixed-240px sidebar above the map. The
   sidebar still tries to lay out the desktop content vertically: title + sub
   + search + two stacked filter groups (each with its own label) + the
   draw-area CTA. That doesn't fit — labels dominate, chips wrap onto multiple
   rows, and the draw-area button overflows the 240px band.

   The mobile redesign drops to a tight three-row strip above the map:
     * row 1: search input (compact, no title/sub above it),
     * row 2: filter chips — both groups merged into a single horizontally-
       scrolling row with no labels and a thin divider between status and
       type so the intent stays readable,
     * row 3: the draw-area button (compact, no surrounding title/sub).

   Sidebar height becomes content-driven (≈140-160px) so the map gets most
   of the viewport.
   --------------------------------------------------------------------------- */
@media (max-width: 920px) {
  /* Sidebar sizes to its content; the map fills the rest.
     `min-width: 0` is the fix for the "200% width" overflow: grid/flex items
     default to `min-width: auto`, which lets the chip bar's content size
     propagate up and push .map-sidebar wider than its 1fr grid track. */
  .map-shell { grid-template-rows: auto 1fr; min-width: 0; }
  .map-sidebar {
    overflow: visible;
    min-width: 0;
    max-width: 100%;
  }

  /* Drop the heading title + sub-line. Keep the search input but tighten its
     padding so it fits without the heading taking space above it. */
  .map-sidebar__head {
    padding: 10px 12px;
    background: var(--sk-white);
    border-bottom: 1px solid var(--sk-border);
  }
  .map-sidebar__title,
  .map-sidebar__sub { display: none; }
  .map-search { margin-top: 0; }
  .map-search input { padding: 10px 12px 10px 36px; font-size: 13.5px; }

  /* Flatten the two .map-filters__group sections into one horizontally-
     scrolling chip bar with no labels and no wrap. A thin border between the
     status group and the type group keeps the two intents readable without
     stealing a label-row. */
  .map-filters {
    padding: 8px 12px;
    flex-direction: row;
    gap: 8px;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    min-width: 0;
  }
  .map-filters::-webkit-scrollbar { display: none; }
  .map-filters__group {
    flex-direction: row;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
  }
  .map-filters__label { display: none; }
  .filter-chips {
    flex-wrap: nowrap;
    gap: 6px;
  }
  .filter-chip {
    flex-shrink: 0;
    white-space: nowrap;
  }
  .map-filters__group + .map-filters__group {
    border-left: 1px solid var(--sk-border);
    padding-left: 10px;
    margin-left: 4px;
  }

  /* Collapse the draw-area CTA into a single-line button — the surrounding
     title + sub aren't worth the vertical space on mobile. */
  .area-cta {
    padding: 8px 12px;
    background: var(--sk-white);
    border-top: 1px solid var(--sk-border);
    margin-top: 0;
  }
  .area-cta__title,
  .area-cta__sub { display: none; }
  /* Keep .area-cta__btn at its desktop sizing (10px 14px / 13px font / 14px
     svg) on mobile so it matches the .area-cta__delete-btn that may appear
     below it. */
}


/* -----------------------------------------------------------------------------
   Admin map — visibility cues
   -----------------------------------------------------------------------------
   Marker ring + filter-chip dot variants for the three point visibilities
   (public / admin_only / draft) on /admin-map.html. The dashed + dotted
   borders mirror the spec in frontend/INTEGRATION_PHASE2.md §5.2.
   --------------------------------------------------------------------------- */
.sk-marker--vis-admin_only { box-shadow: 0 0 0 2px var(--sk-white), 0 0 0 4px var(--sk-blue-500); border-style: dashed; }
.sk-marker--vis-draft      { box-shadow: 0 0 0 2px var(--sk-white), 0 0 0 4px var(--sk-muted);     border-style: dotted; }

.filter-chip__vis {
  display: inline-block;
  width: 10px; height: 10px;
  margin-right: 6px;
  vertical-align: -1px;
}
.filter-chip__vis--public     { background: #1aa863; }
.filter-chip__vis--admin_only { background: transparent; border: 1.5px dashed var(--sk-blue-500); }
.filter-chip__vis--draft      { background: transparent; border: 1.5px dotted var(--sk-muted); }

/* Vis-badge — matches designer/styles.css §"Visibility badges". Used in the
   admin map's result list and detail header. Renders for every visibility,
   including public, so the badge is always the at-a-glance state. */
.vis-badge {
  display: inline-block;
  font-size: 11px; font-weight: 600;
  padding: 2px 8px;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.vis-badge--public     { background: #e8f5ee; color: #0e7c45; border: 1px solid #1aa863; }
.vis-badge--admin_only { background: #e6f1fb; color: #143a78; border: 1px dashed #2f7fd6; }
.vis-badge--draft      { background: var(--sk-surface-2); color: var(--sk-muted); border: 1px dotted var(--sk-muted); }

/* Visibility-selector — radio strip in the detail panel. Verbatim from
   designer/styles.css §"Visibility-selector". Wired to
   PATCH /admin/power-stations/:id/visibility from src/admin/map.ts. */
.vis-selector {
  display: flex; flex-direction: column; gap: 6px;
  padding: 12px 14px;
  background: var(--sk-surface);
  border: 1px solid var(--sk-border);
  margin: 12px 0;
}
.vis-selector__label {
  font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--sk-muted);
  margin-bottom: 4px;
}
.vis-selector__opt {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 6px 8px;
  font-size: 13px;
  color: var(--sk-navy-800);
  cursor: pointer;
}
.vis-selector__opt:hover { background: var(--sk-blue-100); }
.vis-selector__opt input { margin-top: 3px; flex: 0 0 auto; }
.vis-selector__opt-main { font-weight: 500; }
.vis-selector__opt-sub  { font-size: 11.5px; color: var(--sk-muted); margin-top: 1px; }

/* Source-tag — small chip next to a point's name showing where it came from
   (CSV, API, scout). Manual rows skip it. Verbatim from designer. */
.source-tag {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 10.5px; font-weight: 500;
  padding: 1px 6px;
  background: var(--sk-surface-2);
  color: var(--sk-muted);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin-left: 4px;
}
