@layer components {
  /* ── Full-height map page ── */

  .group-map-page {
    display: flex;
    flex-direction: column;
    /* Fill the available viewport minus top nav and bottom nav inset.
       --top-nav-inset is 4rem on web, 0 in the native shell — without
       this the map left a 4rem dead band above the bottom nav on native. */
    height: calc(100dvh - var(--top-nav-inset) - var(--bottom-nav-inset));
    margin: calc(-1 * var(--block-space)) calc(-1 * var(--inline-space-l));

    /* The map_content turbo-frame defaults to display:inline; force it to
       behave as a flex column so tabs + canvas stack and the canvas fills
       the remaining viewport. */
    & > turbo-frame {
      display: flex;
      flex-direction: column;
      flex: 1;
      min-height: 0;
    }
  }

  .group-map {
    position: relative;
    flex: 1;
    min-height: 0;
  }

  .group-map__canvas {
    width: 100%;
    height: 100%;
  }

  /* ── Hidden ping data elements ── */

  .group-map__pings {
    display: none;
  }

  /* ── Avatar pin markers ── */

  .group-map__pin {
    background: none;
    border: none;
  }

  /* Pin inner reads --avatar-color / --avatar-ink set inline by the
   * partial — same custom-property contract as a crew-context avatar.
   * Photo / icon / initial content is rendered by avatars/_content and
   * styled by avatars.css. */
  .group-map__pin-inner {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    overflow: hidden;
    border: 2px solid oklch(var(--lch-flare));
    box-shadow: 0 2px 8px oklch(0% 0 0 / 0.4);
    transition: opacity 300ms ease;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--avatar-color, transparent);
    color: var(--avatar-ink, currentColor);
    font-weight: 700;
    font-size: 0.875rem;
    user-select: none;
  }

  .group-map__pin--stale .group-map__pin-inner {
    opacity: 0.45;
    border-color: var(--color-border);
  }

  /* ── Popup styling ── */

  .group-map__popup .leaflet-popup-content-wrapper {
    background: var(--color-surface);
    color: var(--color-ink);
    border-radius: var(--radius-lg, 0.75rem);
    border: 1px solid var(--color-border);
    box-shadow: 0 4px 16px oklch(0% 0 0 / 0.4);
  }

  .group-map__popup .leaflet-popup-tip {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
  }

  .group-map__popup-content {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    text-align: center;
    padding: 0.25rem;
  }

  .group-map__popup-content strong {
    font-size: 0.875rem;
  }

  .group-map__popup-status {
    font-size: 0.75rem;
  }

  .group-map__popup-status--active {
    color: oklch(var(--lch-laser));
  }

  .group-map__popup-status--stale {
    color: var(--color-ink-muted);
  }

  /* ── Venue overlay markers ── */

  .group-map__venue-marker {
    background: none;
    border: none;

    & span {
      display: block;
      background: oklch(0% 0 0 / 0.7);
      color: oklch(100% 0 0);
      font-size: 0.625rem;
      font-weight: 600;
      padding: 0.15rem 0.35rem;
      border-radius: var(--radius-sm, 0.25rem);
      white-space: nowrap;
      text-align: center;
    }
  }

  /* ── Cluster badges ── */

  .group-map__cluster {
    background: none;
    border: none;
  }

  .group-map__cluster span {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: color-mix(in oklch, oklch(var(--lch-flare)) 85%, oklch(0% 0 0));
    color: oklch(100% 0 0);
    font-size: 0.8125rem;
    font-weight: 700;
    border: 2px solid oklch(var(--lch-flare));
    box-shadow: 0 2px 8px oklch(0% 0 0 / 0.4);
  }

  .leaflet-cluster-anim .leaflet-marker-icon,
  .leaflet-cluster-anim .leaflet-marker-shadow {
    transition: transform 300ms ease, opacity 300ms ease;
  }

  /* ── Rally point pin markers ── */

  .group-map__rally-pin {
    background: none;
    border: none;
  }

  /* New marker layout: a teardrop pin head (circle + downward tail) on the
     left, a separate label chip floating to the right. Anchor lives at the
     tip of the pin head — see iconAnchor in group_map_controller.js. */
  .group-map__rally-pin-inner {
    display: flex;
    align-items: flex-start;
    gap: 0.375rem;
    --pin-bg: oklch(var(--lch-flare));
    --pin-fg: oklch(100% 0 0);
  }

  /* ── Custom spot pin markers ── */

  .group-map__spot-pin {
    background: none;
    border: none;
  }

  .group-map__spot-pin-inner {
    display: flex;
    align-items: flex-start;
    gap: 0.375rem;
    --pin-bg: oklch(var(--lch-laser));
    --pin-fg: oklch(100% 0 0);
  }

  /* Teardrop pin head — round top, point at bottom-centre (rotation trick).
     Holds either the picked emoji or the fallback SVG glyph. */
  .group-map__pin-head {
    inline-size: 32px;
    block-size: 32px;
    border-radius: 50% 50% 50% 0;
    rotate: -45deg;
    background: var(--pin-bg);
    color: var(--pin-fg);
    border: 2px solid oklch(100% 0 0);
    box-shadow: 0 2px 8px oklch(0% 0 0 / 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
  }

  /* Emoji + SVG glyph counter-rotate so they read upright inside the pin. */
  .group-map__pin-emoji,
  .group-map__pin-head svg {
    rotate: 45deg;
    line-height: 1;
  }

  .group-map__pin-emoji {
    font-size: 1.25rem;
  }

  .group-map__pin-head svg {
    width: 16px;
    height: 16px;
  }

  /* Label chip beside the pin head. Small offset down so the chip
     visually centres on the pin head's circle (which sits in the top
     two-thirds of the rotated square). */
  .group-map__pin-label {
    margin-block-start: 4px;
    background: var(--pin-bg);
    color: var(--pin-fg);
    font-size: 0.6875rem;
    font-weight: 600;
    padding: 0.2rem 0.5rem;
    border-radius: var(--radius-sm, 0.25rem);
    white-space: nowrap;
    box-shadow: 0 2px 8px oklch(0% 0 0 / 0.4);
  }

  /* ── Placement mode (drag-the-map crosshair) ────────────────────────
     Shown only while the user is positioning a rally point or My Spot.
     Toggled by the group-map controller via .group-map--placing-*. */

  .group-map__placement {
    display: none;
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 800;
  }

  .group-map--placing .group-map__placement {
    display: block;
  }

  /* Hide the action FAB while placing so the user focuses on positioning. */
  .group-map--placing .group-map__action-fab {
    display: none;
  }

  .group-map__placement-banner {
    position: absolute;
    inset-block-start: 0.75rem;
    inset-inline: 1rem;
    margin-inline: auto;
    max-inline-size: 22rem;
    padding: 0.625rem 0.875rem;
    border-radius: var(--radius);
    background: var(--color-surface);
    color: var(--color-ink);
    border: 1px solid var(--color-border);
    box-shadow: 0 4px 16px oklch(0% 0 0 / 0.4);
    font-size: 0.8125rem;
    line-height: 1.35;
    text-align: center;
    pointer-events: none;
  }

  .group-map__crosshair {
    position: absolute;
    inset-block-start: 50%;
    inset-inline-start: 50%;
    translate: -50% -50%;
    inline-size: 56px;
    block-size: 56px;
    pointer-events: none;
    /* Brand accent — Flare for rally, Laser for spot. */
    color: oklch(var(--lch-flare));
    filter: drop-shadow(0 2px 6px oklch(0% 0 0 / 0.5));
  }

  .group-map--placing-spot .group-map__crosshair {
    color: oklch(var(--lch-laser));
  }

  .group-map__placement-actions {
    position: absolute;
    inset-block-end: calc(2rem + var(--bottom-nav-inset));
    inset-inline: 0;
    display: flex;
    justify-content: center;
    gap: 0.5rem;
    pointer-events: auto;
  }

  /* ── Emoji picker (rally + spot dialogs) ─────────────────────────── */

  .emoji-picker {
    border: none;
    padding: 0;
    margin: 0;
    min-inline-size: 0;
  }

  .emoji-picker__legend {
    padding: 0;
    margin-block-end: 0.375rem;
    font-size: 0.8125rem;
    color: var(--color-ink-muted);
  }

  .emoji-picker__grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(2.25rem, 1fr));
    gap: 0.375rem;
  }

  .emoji-picker__option {
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 1;
    border-radius: var(--radius);
    border: 1px solid var(--color-border);
    background: var(--color-canvas);
    cursor: pointer;
    transition: border-color 120ms ease, background 120ms ease;

    & input {
      position: absolute;
      opacity: 0;
      pointer-events: none;
    }

    &:hover {
      border-color: oklch(var(--lch-laser) / 0.5);
    }

    &:has(input:checked) {
      border-color: oklch(var(--lch-flare));
      background: color-mix(in oklch, oklch(var(--lch-flare)) 12%, var(--color-canvas));
    }

    &:has(input:focus-visible) {
      outline: 2px solid oklch(var(--lch-flare));
      outline-offset: 1px;
    }
  }

  .emoji-picker__icon {
    font-size: 1.25rem;
    line-height: 1;
  }

  .emoji-picker__icon--none {
    color: var(--color-ink-muted);
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  /* ── Rally point dialog ── */

  .group-map__rally-dialog {
    /* Force viewport-centred positioning even when the dialog lives inside
       a positioned ancestor (the .group-map relative wrapper). Top-layer
       defaults from :modal vary across browsers, so pin it explicitly. */
    position: fixed;
    inset: 0;
    margin: auto;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg, 0.75rem);
    background: var(--color-surface);
    color: var(--color-ink);
    padding: var(--block-space) var(--inline-space-l);
    max-width: 20rem;
    width: 90vw;
    block-size: fit-content;
    box-shadow: 0 8px 32px oklch(0% 0 0 / 0.5);

    &::backdrop {
      background: oklch(0% 0 0 / 0.6);
    }
  }

  .group-map__rally-form {
    display: flex;
    flex-direction: column;
    gap: 1rem;
  }

  .group-map__rally-form-actions {
    display: flex;
    gap: 0.5rem;
    justify-content: flex-end;
  }

  /* ── Bottom sheet (rally points + saved spots) ─────────────────────
     Three-state pull-up panel that overlays the map. Heights drive
     visibility; transitions stay on the sheet so dragging feels live. */

  .group-map__sheet {
    position: absolute;
    inset-inline: 0;
    inset-block-end: 0;
    z-index: 700;
    display: flex;
    flex-direction: column;
    background: var(--color-surface);
    border-block-start: 1px solid var(--color-border);
    border-start-start-radius: 16px;
    border-start-end-radius: 16px;
    box-shadow: 0 -8px 24px oklch(0% 0 0 / 0.4);
    transition: block-size 200ms ease;
    overflow: hidden;
    touch-action: none;

    &[data-state="peek"]    { block-size: var(--sheet-peek-height, 64px); }
    &[data-state="partial"] { block-size: 50%; }
    &[data-state="full"]    { block-size: 85%; }
  }

  .group-map__sheet-handle {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.25rem;
    padding: 0.5rem 1rem 0.625rem;
    background: transparent;
    border: 0;
    color: inherit;
    cursor: grab;
    user-select: none;

    &:active { cursor: grabbing; }
  }

  .group-map__sheet-grip {
    inline-size: 36px;
    block-size: 4px;
    border-radius: 999px;
    background: oklch(50% 0.02 280);
  }

  .group-map__sheet-count {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--color-ink);
  }

  .group-map__sheet-body {
    flex: 1;
    min-block-size: 0;
    overflow-y: auto;
    padding: 0 var(--inline-space-l) var(--block-space);
    overscroll-behavior: contain;

    /* Hide overflow when the sheet is collapsed so partial rows don't
       peek through the rounded top of the handle area. */
    .group-map__sheet[data-state="peek"] & { display: none; }
  }

  .group-map__sheet-section + .group-map__sheet-section {
    margin-block-start: var(--block-space);
  }

  .group-map__sheet-title {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--color-ink-muted);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-block-end: 0.5rem;
  }

  .group-map__rally-item {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--color-border);
    cursor: pointer;

    &:last-child {
      border-bottom: none;
    }

    &:hover strong {
      color: oklch(var(--lch-flare));
    }
  }

  /* ── Crew nearby ── */

  .crew-nearby {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
  }

  .crew-nearby__row {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--color-border);

    &:last-child {
      border-bottom: none;
    }
  }

  .crew-nearby__info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
  }

  .crew-nearby__name {
    font-size: 0.875rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .crew-nearby__meta {
    font-size: 0.75rem;
    color: var(--color-ink-muted);
  }

  .crew-nearby__distance {
    font-weight: 600;
    color: oklch(var(--lch-laser));
  }

  .crew-nearby__find {
    width: var(--touch-min);
    height: var(--touch-min);
    border: 1px solid var(--color-border);
    border-radius: 50%;
    background: var(--color-surface);
    color: oklch(var(--lch-flare));
    display: grid;
    place-items: center;
    cursor: pointer;
    transition: background 120ms ease, border-color 120ms ease;
    flex-shrink: 0;

    &:hover {
      background: color-mix(in oklch, var(--color-surface) 80%, oklch(var(--lch-flare)));
      border-color: oklch(var(--lch-flare));
    }

    & svg {
      width: 1.125rem;
      height: 1.125rem;
    }
  }

  /* ── Rally point ETAs ── */

  .rally-eta__list {
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
  }

  .rally-eta__chip {
    display: inline-flex;
    align-items: center;
    padding: 0.15em 0.5em;
    font-size: 0.6875rem;
    font-weight: 500;
    border-radius: var(--radius-pill);
    background: color-mix(in oklch, oklch(var(--lch-sky)) 15%, var(--color-surface));
    color: oklch(var(--lch-sky));
  }

  .rally-eta__chip--there {
    background: color-mix(in oklch, oklch(var(--lch-laser)) 18%, var(--color-surface));
    color: oklch(var(--lch-laser));
    font-weight: 600;
  }

  .rally-eta__actions {
    width: 100%;
    display: flex;
    gap: 0.25rem;
  }

  .rally-eta__btn {
    flex: 1;
    min-height: 1.75rem;
    padding: 0.2em 0;
    font-size: 0.6875rem;
    font-weight: 600;
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    background: var(--color-surface);
    color: var(--color-ink-muted);
    cursor: pointer;
    transition: border-color 100ms ease, color 100ms ease;

    &:hover {
      border-color: oklch(var(--lch-sky));
      color: oklch(var(--lch-sky));
    }
  }

  .rally-eta__btn--primary {
    background: oklch(var(--lch-laser));
    border-color: oklch(var(--lch-laser));
    color: var(--color-surface);
    font-weight: 700;

    &:hover {
      background: color-mix(in oklch, oklch(var(--lch-laser)) 85%, var(--color-ink));
      border-color: oklch(var(--lch-laser));
      color: var(--color-surface);
    }
  }

  .group-map__rally-item-info {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    min-width: 0;

    & strong {
      font-size: 0.875rem;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }

  .group-map__rally-item-meta {
    font-size: 0.75rem;
    color: var(--color-ink-muted);
  }

  .group-map__rally-item-distance:not(:empty)::after {
    content: " · ";
  }

  /* Leaflet layer control dark theme override */

  .group-map .leaflet-control-layers {
    background: var(--color-surface);
    color: var(--color-ink);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md, 0.5rem);
    box-shadow: 0 2px 8px oklch(0% 0 0 / 0.3);
    font-size: 0.8125rem;
  }

  /* ── Sheet-aware adjustments (added by bottom_sheet_controller) ─────
     --has-sheet: lift Leaflet attribution above the peek bar and lift
     the action FAB above the sheet handle so it never collides. */

  .group-map--has-sheet .leaflet-bottom {
    bottom: var(--sheet-peek-height, 4rem);
    z-index: 600;
    transition: bottom 200ms ease;
  }

  .group-map--has-sheet .group-map__action-fab {
    bottom: calc(2rem + var(--bottom-nav-inset) + var(--sheet-peek-height, 4rem));
  }

  /* ── Single + action FAB ────────────────────────────────────────── */

  .group-map__action-fab {
    position: fixed;
    bottom: calc(2rem + var(--bottom-nav-inset));
    right: 1rem;
    z-index: 1000;
    width: var(--touch-min);
    height: var(--touch-min);
    border-radius: 50%;
    border: none;
    background: oklch(var(--lch-flare));
    color: oklch(100% 0 0);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    box-shadow: 0 4px 16px oklch(0% 0 0 / 0.4);
    transition: background 150ms ease, transform 150ms ease, bottom 200ms ease;

    & svg {
      width: 1.5rem;
      height: 1.5rem;
    }

    &:hover {
      background: color-mix(in oklch, oklch(var(--lch-flare)) 88%, oklch(0% 0 0));
    }

    &:active { transform: scale(0.95); }
  }

  /* ── Actions popover (light-dismiss, native HTML popover) ───────── */

  .group-map__action-menu {
    /* Native popovers live in the top layer; we override the UA defaults
       and pin the menu just above the FAB at the bottom-right. */
    position: fixed;
    inset: auto 1rem calc(2rem + var(--bottom-nav-inset) + var(--touch-min) + 0.5rem) auto;
    margin: 0;
    padding: 0.375rem;
    min-inline-size: 16rem;
    background: var(--color-surface);
    color: var(--color-ink);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg, 0.75rem);
    box-shadow: 0 12px 32px oklch(0% 0 0 / 0.5);
    display: flex;
    flex-direction: column;
    gap: 0.125rem;

    /* Hidden until the popover attribute is opened. */
    &:not(:popover-open) { display: none; }

    @media (prefers-reduced-motion: no-preference) {
      &:popover-open {
        @starting-style {
          opacity: 0;
          translate: 0 8px;
        }
        transition: opacity 150ms ease, translate 150ms ease;
      }
    }

    &::backdrop { background: transparent; }
  }

  /* Slide the menu up an extra peek-height when the sheet is mounted so it
     opens above the sheet handle. */
  .group-map--has-sheet .group-map__action-menu {
    inset-block-end: calc(2rem + var(--bottom-nav-inset) + var(--touch-min) + 0.5rem + var(--sheet-peek-height, 4rem));
  }

  .action-menu-item {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.625rem 0.75rem;
    min-block-size: var(--touch-min);
    border: 0;
    border-radius: var(--radius, 0.5rem);
    background: transparent;
    color: inherit;
    font-size: 0.875rem;
    font-weight: 500;
    text-align: start;
    cursor: pointer;
    transition: background 120ms ease;

    & svg {
      width: 1.125rem;
      height: 1.125rem;
      flex-shrink: 0;
      color: var(--color-ink-muted);
    }

    &:hover { background: color-mix(in oklch, var(--color-surface) 80%, oklch(var(--lch-flare))); }
    &:active { background: color-mix(in oklch, var(--color-surface) 65%, oklch(var(--lch-flare))); }

    /* button_to wraps in a <form>; level the button to fill the form. */
    & + .action-menu-item__form,
    .button_to & { width: 100%; }
  }

  .action-menu-item--danger {
    color: oklch(var(--lch-golden));

    & svg { color: oklch(var(--lch-golden)); }

    &:hover {
      background: color-mix(in oklch, var(--color-surface) 75%, oklch(var(--lch-golden)));
    }
  }

  .action-menu-item__emoji {
    width: 1.125rem;
    height: 1.125rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 1rem;
    line-height: 1;
    flex-shrink: 0;
  }

  .action-menu-divider {
    border: 0;
    border-block-start: 1px solid var(--color-border);
    margin: 0.25rem 0.5rem;
  }

  /* button_to renders <form><button>; remove the form's default block layout
     so it slots into the menu like the other items. */
  .group-map__action-menu form {
    margin: 0;
    display: contents;
  }

  /* ── Find Friend overlay ── */

  .find-friend {
    width: min(90vw, 360px);
    max-height: 90vh;
    padding: 1.5rem 1.25rem 1.25rem;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-l, 1rem);
    background: var(--color-surface);
    color: var(--color-ink);
    text-align: center;

    &::backdrop {
      background: oklch(0% 0 0 / 0.7);
      backdrop-filter: blur(8px);
    }
  }

  .find-friend__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-block-end: 1rem;
  }

  .find-friend__title {
    font-family: var(--font-display, "Outfit", sans-serif);
    font-weight: 700;
    font-size: 1rem;
    text-align: start;
  }

  .find-friend__close {
    width: 2rem;
    height: 2rem;
    border: 0;
    border-radius: 50%;
    background: var(--color-border);
    color: var(--color-ink);
    font-size: 1.25rem;
    line-height: 1;
    cursor: pointer;
  }

  .find-friend__compass {
    position: relative;
    width: 12rem;
    height: 12rem;
    margin: 0 auto 1rem;
    display: grid;
    place-items: center;
  }

  .find-friend__ring {
    position: absolute;
    border-radius: 50%;
  }

  .find-friend__ring--outer {
    inset: 0;
    border: 1px solid color-mix(in oklch, oklch(var(--lch-flare)) 50%, transparent);
  }

  .find-friend__ring--inner {
    inset: 1.5rem;
    border: 2px solid color-mix(in oklch, oklch(var(--lch-flare)) 30%, transparent);
  }

  .find-friend__arrow {
    width: 8rem;
    height: 8rem;
    color: oklch(var(--lch-flare));
    transition: transform 200ms ease;
    transform-origin: 50% 50%;
  }

  .find-friend__distance {
    display: block;
    font-family: var(--font-display, "Outfit", sans-serif);
    font-weight: 800;
    font-size: 3.5rem;
    line-height: 1;
    color: var(--color-ink);
  }

  .find-friend__unit {
    font-size: 0.875rem;
    color: var(--color-ink-muted);
    margin-block-end: 1.5rem;
  }

  .find-friend__actions {
    display: flex;
    gap: 0.75rem;
  }

  .find-friend__btn {
    flex: 1;
    min-height: var(--touch-min);
    padding: 0.625rem 1rem;
    border: 0;
    border-radius: var(--radius);
    font-weight: 700;
    font-size: 0.9375rem;
    cursor: pointer;
  }

  .find-friend__btn--cancel {
    background: var(--color-border);
    color: var(--color-ink);
  }

  .find-friend__btn--ping {
    background: oklch(var(--lch-flare));
    color: var(--color-surface);
  }
}
