/* ---- Map markers -------------------------------------------------------------------------------
   Implements the "Fingli Map Markers" design: marker variant 1b (icon + price), the five marker
   states, cluster capsule 1e on white, preview card 1g, and the zoom behaviour in section 05.

   Global because Google moves a marker's DOM node out of the component's subtree onto the map, so
   neither scoped CSS nor ::deep can reach it — the same trap as .bell-panel in the server's app.css.

   It lives in the *client* project so that one file serves both the app and the component gallery.
   The gallery references only aurora-blazor.Client and cannot see the server's wwwroot — which is
   exactly why theme.css had to be mirrored there once, and had already drifted by the time anyone
   looked. Linked from App.razor (app) and iframe.html (gallery). */

:root {
    /* The design's ink is #1a1a1a, a shade darker than the app's --brand-graphite (#2f2f2f). Kept as
       the design specifies rather than reconciled, since the two are used in different places and
       nothing yet says which should win. Worth settling if a third near-black ever appears. */
    --marker-ink: #1a1a1a;
    --marker-icon-bg: #f1ecff;
    --marker-muted: #b5b5b3;
}

/* ---- Single marker: variant 1b, icon + price ---- */

.fmarker {
    display: flex;
    flex-direction: column;
    align-items: center;
    cursor: pointer;
    /* Not hit-testable itself, only its visible parts are.
       The column is as wide as its widest child, so the moment the preview opens this box becomes 242px
       across — and every empty pixel beside the pill still counted as hovering the marker. The card then
       only closed once the pointer left that whole invisible rectangle, which felt like it was sticking.
       Children opt back in below; :hover still propagates to this element from them. */
    pointer-events: none;
}

.fmarker__pill,
.fmarker__tail,
.fmarker__dot,
.fcard-anchor {
    pointer-events: auto;
}

.fmarker__pill {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 5px 13px 5px 5px;
    border-radius: 20px;
    background: #fff;
    box-shadow: 0 2px 10px rgba(26, 26, 26, 0.18);
    transition: transform 150ms ease, background-color 150ms ease, box-shadow 150ms ease;
}

.fmarker__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--marker-icon-bg);
    color: var(--brand-purple);
}

.fmarker__icon svg {
    width: 14px;
    height: 14px;
}

.fmarker__price {
    font-size: 14px;
    font-weight: 700;
    line-height: 1;
    color: var(--brand-purple);
    white-space: nowrap;
    /* Prices redraw on every pan; proportional digits make the pill width twitch. */
    font-variant-numeric: tabular-nums;
}

/* The tail is a rotated square, so it has to sit under the pill to hide its top two edges. */
.fmarker__tail {
    width: 11px;
    height: 11px;
    margin-top: -7px;
    background: #fff;
    box-shadow: 2px 2px 4px rgba(26, 26, 26, 0.10);
    transform: rotate(45deg);
    transition: background-color 150ms ease;
}

/* ---- States ----
   Selected reuses hover rather than the design's dark-with-purple-ring variant, per Konrad. That also
   removes the only state that needed a third background colour. */

.fmarker:hover .fmarker__pill,
.fmarker--selected .fmarker__pill {
    background: var(--brand-purple);
    box-shadow: 0 6px 18px rgba(75, 0, 249, 0.35);
    transform: scale(1.08) translateY(-2px);
}

.fmarker:hover .fmarker__price,
.fmarker--selected .fmarker__price {
    color: #fff;
}

.fmarker:hover .fmarker__tail,
.fmarker--selected .fmarker__tail {
    background: var(--brand-purple);
}

/* White rather than lilac on the purple pill — lilac on purple loses the glyph. */
.fmarker:hover .fmarker__icon,
.fmarker--selected .fmarker__icon {
    background: #fff;
}

.fmarker--featured .fmarker__pill,
.fmarker--featured .fmarker__tail {
    background: var(--brand-green);
}

.fmarker--featured .fmarker__price {
    color: var(--brand-graphite);
}

.fmarker--featured .fmarker__icon {
    background: #fff;
    color: var(--brand-graphite);
}

/* Featured keeps its lime on hover — turning it purple would drop the one signal it exists to carry.
   It still lifts, so it stays obvious that it responds. */
.fmarker--featured:hover .fmarker__pill {
    background: var(--brand-green);
    box-shadow: 0 6px 18px rgba(26, 26, 26, 0.28);
}

.fmarker--featured:hover .fmarker__price {
    color: var(--brand-graphite);
}

.fmarker--featured:hover .fmarker__tail {
    background: var(--brand-green);
}

/* "bez hover / kliku" in the spec: struck through, and inert. The marker is still announced, so a
   screen reader user learns the space exists and is taken — it just does not pretend to be actionable. */
.fmarker--unavailable {
    cursor: default;
}

.fmarker--unavailable .fmarker__pill {
    box-shadow: 0 1px 4px rgba(26, 26, 26, 0.10);
    pointer-events: none;
}

.fmarker--unavailable .fmarker__price {
    color: var(--marker-muted);
    text-decoration: line-through;
}

.fmarker--unavailable .fmarker__icon {
    background: #f2f2f0;
    color: var(--marker-muted);
}

/* ---- Zoom behaviour (section 05) ----
   The dot is a circle with a white ring, so it is drawn rather than fetched — assets/pin-dot-*.svg is
   exactly this shape, and one image request per marker to draw a circle is a poor trade.

   The zoom class goes on the map container, which is an ancestor of every marker, so switching form
   costs one class toggle rather than re-rendering every marker. Clusters-only below zoom 12 is the
   clusterer's job, not CSS's — that threshold belongs with the real clusterer in AB-30. */

.fmarker__dot {
    display: none;
    /* content-box on purpose. The spec draws a 22px core with a 3.5px ring around it — 29px overall —
       but blazorblueprint.css sets box-sizing:border-box globally, which would eat the ring out of the
       22px and leave a 15px core. The design canvas has no such reset, so this is what it renders. */
    box-sizing: content-box;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--brand-purple);
    border: 3.5px solid #fff;
    box-shadow: 0 2px 8px rgba(26, 26, 26, 0.45);
}

.fmarker--featured .fmarker__dot {
    background: var(--brand-green);
}

.fmarker--unavailable .fmarker__dot {
    background: var(--marker-muted);
}

.map-zoom--far .fmarker__pill,
.map-zoom--far .fmarker__tail {
    display: none;
}

.map-zoom--far .fmarker__dot {
    display: block;
}

/* A selected marker keeps its pill whatever the zoom — the card is anchored to it and a card floating
   above a 14px dot reads as unattached. */
.map-zoom--far .fmarker--selected .fmarker__pill,
.map-zoom--far .fmarker--selected .fmarker__tail {
    display: flex;
}

.map-zoom--far .fmarker--selected .fmarker__dot {
    display: none;
}

@media (prefers-reduced-motion: reduce) {
    .fmarker__pill,
    .fmarker__tail {
        transition: none;
    }

    .fmarker:hover .fmarker__pill,
    .fmarker--selected .fmarker__pill {
        transform: none;
    }
}

/* ---- Cluster capsule: variant 1e, white ---- */

.fcluster {
    display: inline-flex;
    align-items: center;
    padding: 4px;
    border: 0;
    border-radius: 30px;
    background: #fff;
    box-shadow: 0 3px 12px rgba(26, 26, 26, 0.20);
    cursor: pointer;
    font: inherit;
    transition: transform 150ms ease;
}

.fcluster:hover {
    transform: scale(1.08);
}

.fcluster__count {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    border-radius: 50%;
    background: var(--brand-purple);
    color: #fff;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.fcluster__range {
    padding: 0 13px 0 9px;
    font-weight: 700;
    color: var(--marker-ink);
    white-space: nowrap;
}

/* Three size tiers, so a dense cluster reads as bigger before you read the number at all. */
.fcluster--s .fcluster__count { width: 28px; height: 28px; font-size: 12px; }
.fcluster--s .fcluster__range { font-size: 11.5px; }

.fcluster--m .fcluster__count { width: 34px; height: 34px; font-size: 14px; }
.fcluster--m .fcluster__range { font-size: 12.5px; }

.fcluster--l .fcluster__count { width: 42px; height: 42px; font-size: 15px; }
.fcluster--l .fcluster__range { font-size: 13px; }

/* No range known yet — the capsule collapses to the counter rather than showing an empty pill. */
.fcluster__range:empty {
    display: none;
}

@media (prefers-reduced-motion: reduce) {
    .fcluster {
        transition: none;
    }

    .fcluster:hover {
        transform: none;
    }
}

/* ---- Preview card: variant 1g ---- */

.fcard {
    width: 242px;
    border-radius: 14px;
    background: #fff;
    box-shadow: 0 10px 30px rgba(26, 26, 26, 0.22);
    overflow: hidden;
    text-align: left;
    cursor: default;
}

.fcard__media {
    position: relative;
    width: 100%;
    height: 110px;
    background: #ece9e2;
}

.fcard__media img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Stands in for a photo that has not loaded or does not exist. Not an error state — plenty of spaces
   are listed without one. */
.fcard__media--empty {
    display: flex;
    align-items: center;
    justify-content: center;
    color: #a9a49a;
}

.fcard__media--empty svg {
    width: 26px;
    height: 26px;
}

.fcard__badge {
    position: absolute;
    left: 9px;
    top: 9px;
    z-index: 1;
    padding: 3px 9px;
    border-radius: 12px;
    background: #fff;
    font-size: 10.5px;
    font-weight: 700;
    color: var(--brand-graphite);
}

.fcard__body {
    padding: 11px 13px 13px;
}

.fcard__title {
    margin: 0 0 4px;
    font-size: 13px;
    font-weight: 600;
    line-height: 1.3;
    color: var(--marker-ink);
    /* Two lines then ellipsis. Titles are user-written and unbounded; without this the card grows
       until it covers the map it floats over. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.fcard__place {
    margin-bottom: 8px;
    font-size: 11.5px;
    /* The spec says #8a8a8a, which is 3.45:1 on white at this size and fails WCAG AA. #6e6e6e is
       5.0:1 and still reads as secondary against the title. Deliberate deviation. */
    color: #6e6e6e;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fcard__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.fcard__price {
    font-size: 14.5px;
    font-weight: 700;
    color: var(--brand-purple);
    font-variant-numeric: tabular-nums;
}

.fcard__cta {
    flex: none;
    padding: 5px 10px;
    border-radius: 7px;
    background: var(--brand-green);
    color: var(--brand-graphite);
    font-size: 11.5px;
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
}

.fcard__cta:hover {
    background: #8de92f;
    color: var(--brand-graphite);
}

/* The card's own tail, then a 9px gap before the marker it belongs to. */
.fcard__tail {
    width: 12px;
    height: 12px;
    margin-top: -7px;
    background: #fff;
    box-shadow: 3px 3px 5px rgba(26, 26, 26, 0.10);
    transform: rotate(45deg);
}

/* Hidden until hovered, focused or selected. Hover is the primary path — a preview should not cost a
   click — with selection as the sticky version for touch, keyboard, and for reading the card while the
   pointer wanders. Unavailable markers never render one. */
.fcard-anchor {
    display: none;
    flex-direction: column;
    align-items: center;
    /* Padding, not margin: the 9px between card and pill has to stay inside a hit-testable box, or the
       pointer crosses a dead strip on its way down to the pill and the card closes under it. */
    padding-bottom: 9px;
}

.fmarker:hover > .fcard-anchor,
.fmarker--selected > .fcard-anchor,
gmp-advanced-marker:focus-visible .fcard-anchor {
    display: flex;
}

/* A hovered card has to sit above neighbouring markers, and the stacking context is the marker host,
   whose z-index Google writes inline. A stylesheet !important is the only thing that outranks it. */
gmp-advanced-marker:hover,
gmp-advanced-marker:focus-visible {
    z-index: 500 !important;
}

@media (prefers-reduced-motion: no-preference) {
    .fcard-anchor {
        /* The delay is hover intent: sweeping the pointer across a dense map should not strobe cards
           on and off. fill-mode both holds it invisible through the delay rather than flashing first. */
        animation: fcard-in 150ms ease-out 220ms both;
    }

    /* Clicking is a commitment, so the sticky card does not wait. Must follow the rule above — same
       specificity, so source order decides. */
    .fmarker--selected > .fcard-anchor {
        animation-delay: 0s;
    }
}

@keyframes fcard-in {
    from { opacity: 0; transform: translateY(4px) scale(0.98); }
    to { opacity: 1; transform: none; }
}

/* ---- Focus ----
   Google makes the <gmp-advanced-marker> host focusable, so the UA draws its default ring around the
   whole content — including an open card, which looked like a stray white box with a blue edge. The
   ring is replaced rather than removed: keyboard focus still lands on the pill. */

gmp-advanced-marker:focus {
    outline: none;
}

gmp-advanced-marker:focus-visible .fmarker__pill,
.fcluster:focus-visible {
    outline: 3px solid var(--marker-ink);
    outline-offset: 2px;
}

/* ---- Map shell ----
   The containing block for anything overlaid on the map — today just the legend. Global rather than
   scoped because the legend positions itself against it and the two live in different components;
   a scoped `position: relative` on one would not be what the other resolves against. */

.map-shell {
    position: relative;
}

/* ---- Map legend ----
   Global, and for a different reason than the markers above. Nothing moves this DOM — it is ours, in
   our own subtree, so ::deep would reach it in the app perfectly well. The gallery is the constraint:
   its scoped-CSS bundle carries only the *Stories* project's own styles, and scoped CSS from the
   referenced aurora-blazor.Client is not in it at all. A MapLegend.razor.css therefore styles the app
   and silently nothing in the component gallery, which is where the legend is actually reviewed.

   Same trade this file's header describes for the markers, arrived at from the other direction. */

.flegend {
    position: absolute;
    bottom: 16px;
    left: 16px;
    z-index: 1;
    max-width: 15rem;
    padding: 8px 10px;
    border: 1px solid #e4e4e7;
    border-radius: 10px;
    background: rgb(255 255 255 / 95%);
    box-shadow: 0 2px 10px rgb(26 26 26 / 18%);
    font: 500 12px/1.4 system-ui;
    color: var(--marker-ink);
}

.flegend__summary {
    display: flex;
    align-items: center;
    gap: 6px;
    font-weight: 700;
    cursor: pointer;
    /* The default disclosure triangle sits oddly beside the map glyph, and [open] already reads from
       the list being there. list-style covers Firefox, the pseudo-element covers WebKit. */
    list-style: none;
}

.flegend__summary::-webkit-details-marker {
    display: none;
}

.flegend__summary svg {
    width: 14px;
    height: 14px;
}

.flegend__list {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 8px 0 0;
    padding: 0;
    list-style: none;
}

.flegend__row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.flegend__glyph {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--marker-icon-bg);
    color: var(--brand-purple);
}

.flegend__glyph svg {
    width: 13px;
    height: 13px;
}

.flegend__label {
    /* A long category name shortens the row rather than widening the panel out over the map.

       No min-width:0 here, deliberately — it is the usual companion to this pattern and it is a
       no-op in this one. A flex item's automatic minimum size applies only while its overflow is
       `visible` (CSS Flexbox 4.5), so the `overflow: hidden` below already resolves min-width:auto
       to zero and the ellipsis triggers without help. Measured all four combinations: with overflow
       hidden, auto and 0 render identically at 188px and clip; only overflow:visible + min-width:auto
       overflows, by 129px. Adding it back would be a line that changes nothing. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.flegend__toggle {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid #ececee;
    cursor: pointer;
}

.flegend__toggle input {
    /* accent-color styles the native check with one line — no custom control, no ARIA, no keyboard
       handling to write, and the platform's focus ring stays intact. */
    accent-color: var(--brand-purple);
    margin: 0;
    cursor: pointer;
}

/* ---- Cluster expansion panel ----
   The way into ads that share one coordinate, where zooming can never separate the markers.

   A native <dialog> opened with showModal(): the backdrop, the focus trap and Escape are the
   platform's, so nothing here reimplements them. Global rather than scoped for the same reason as
   .flegend — the component gallery's scoped bundle carries only its own project's styles. */

.fstack {
    max-width: min(420px, calc(100vw - 32px));
    padding: 0;
    border: 0;
    border-radius: 14px;
    box-shadow: 0 12px 40px rgba(26, 26, 26, 0.28);
    color: var(--marker-ink);
}

.fstack::backdrop {
    background: rgba(26, 26, 26, 0.35);
}

.fstack__body {
    padding: 14px 16px 16px;
}

.fstack__title {
    margin: 0 0 10px;
    font-size: 14px;
    font-weight: 700;
}

.fstack__list {
    /* Scrolls rather than growing past the viewport: a stack at one address has no upper bound, and a
       list that runs off the screen puts the ads at the bottom out of reach. */
    max-height: min(50vh, 320px);
    overflow-y: auto;
    margin: 0;
    padding: 0;
    list-style: none;
}

.fstack__row {
    display: flex;
    align-items: baseline;
    gap: 8px;
    width: 100%;
    padding: 10px 8px;
    border: 0;
    border-radius: 8px;
    background: none;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.fstack__row:hover {
    background: var(--marker-icon-bg);
}

.fstack__badge {
    flex: none;
    padding: 2px 8px;
    border-radius: 20px;
    background: var(--marker-icon-bg);
    color: var(--brand-purple);
    font-size: 11px;
    font-weight: 700;
    white-space: nowrap;
}

.fstack__name {
    flex: 1;
    /* flex-basis: 0 is not enough — min-width: auto floors a flex item at its min-content width, and
       nowrap makes that the whole title. Without this the row overflows instead of clipping. */
    min-width: 0;
    /* One line, clipped at a word boundary. Titles are user-supplied and can be any length. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 13px;
    font-weight: 700;
}

.fstack__price {
    flex: none;
    font-size: 12px;
    font-weight: 700;
    white-space: nowrap;
}

/* ---- Location picker pin ----
   The new-ad wizard's draggable marker. Global for the same reason as .fmarker above: Google moves the
   marker's node onto the map, out of the component's subtree, where neither scoped CSS nor ::deep
   reaches it.

   Its own class rather than a reuse of .fmarker: that one is a price pill for browsing many ads, and
   this is one pin the user positions. The shared vocabulary is the palette, not the shape. */

.fpin {
    box-sizing: content-box;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--brand-purple);
    border: 4px solid #fff;
    box-shadow: 0 2px 8px rgb(26 26 26 / 45%);
    /* The affordance. Google puts an openhand cursor on the host, but the host is only as big as this
       element, so without a size there is nothing to aim at — which is precisely how the pin managed to
       be draggable and invisible at the same time. */
    cursor: grab;
}

.fpin:active {
    cursor: grabbing;
}

/* Keyboard users get the same target: Google makes the host focusable, and map.css already clears the
   UA ring on gmp-advanced-marker:focus for the browse markers, so without this the picker's pin would
   take focus and show nothing. */
gmp-advanced-marker:focus-visible .fpin {
    outline: 3px solid var(--marker-ink);
    outline-offset: 3px;
}
