/**
 * Locations finder — search row, location cards, hub detail panel.
 *
 * Restyled 2026-08 to the approved join/quote design: pill search row, tinted
 * gradient cards in a rail beside the map, and an expanded hub detail panel
 * (built by quoteToolRail.js from each card's <template class="loc-card__detail">).
 *
 * In the quote tool each card is the label of a Gravity Forms radio choice, so
 * the selectable unit is `.gchoice` and the radio input itself is hidden — same
 * pattern as the step-3 rate cards. The rail chrome (count label, detail panel)
 * is inserted by quoteToolRail.js as SIBLINGS of .gfield_radio, never inside
 * it: locationsFinder.js's distance sort re-appends the .gchoice units inside
 * that list and would shuffle anything else living there.
 */

/* Search row ---------------------------------------------------------------
   The flex row lives on .loc-finder__searchbar (a div): inside the quote tool
   this markup sits in the Gravity Forms <form> and the parser DROPS the nested
   <form> tag. Where the form survives (standalone finder) it becomes
   display:contents so its children lay out from the wrapper either way. */

.loc-finder__searchbar {
    display: flex;
    flex-wrap: wrap;
    gap: 15px;
    align-items: center;
}

.loc-finder__searchbar .loc-finder__search {
    display: contents;
}

.loc-finder__field {
    position: relative;
    flex: 0 1 220px;
    display: flex;
}

#quote-tool .loc-finder__search-input,
.loc-finder__search-input {
    width: 100%;
    box-sizing: border-box;
    height: 58px;
    padding: 0 44px 0 22px;
    font-family: var(--qt-font-body, Lato, sans-serif);
    font-size: 17px;
    color: var(--qt-ink, #2a2a2a);
    background: var(--qt-white);
    border: 1px solid var(--qt-input-border, #cacaca);
    border-radius: var(--qt-radius-input, 25px);
    transition: all 0.18s ease-in-out;
}

#quote-tool .loc-finder__search-input:hover,
.loc-finder__search-input:hover {
    border-color: var(--qt-cyan-hover, #25afd2);
}

/* Chrome and Safari draw their own clear button inside a type="search" field
   once it has text, which is the second X that appears on hover/focus. It is
   suppressed rather than the button beside it, because only .loc-finder__clear
   runs reset() — the native one clears the text and nothing else, leaving the
   distance-sorted order, the badges and the map origin behind. Firefox draws no
   such button, so this is also the affordance that exists everywhere. */
#quote-tool .loc-finder__search-input::-webkit-search-cancel-button,
.loc-finder__search-input::-webkit-search-cancel-button,
#quote-tool .loc-finder__search-input::-webkit-search-decoration,
.loc-finder__search-input::-webkit-search-decoration {
    -webkit-appearance: none;
    appearance: none;
    display: none;
}

#quote-tool .loc-finder__clear,
.loc-finder__clear {
    position: absolute;
    right: 0.9rem;
    top: 50%;
    transform: translateY(-50%);
    width: 1.75rem;
    height: 1.75rem;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    background: none;
    color: var(--qt-gray);
    cursor: pointer;
}

.loc-finder__clear .icon {
    font-size: 12px;
}

/* "Show Results" — the DS gradient pill, compact. Hover slides the gradient to
   purple (the --qt-gradient-pill mechanics, documented in quote-tool.css). */
#quote-tool .loc-finder__submit,
.loc-finder__submit {
    padding: 15px 28px;
    background: var(--qt-gradient-pill);
    background-size: 300% 100%;
    background-position: 0 0;
    color: var(--qt-white);
    font-family: var(--qt-font-heading, Cachet, Geneva, sans-serif);
    font-size: 16px;
    line-height: 22.4px;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    border: 0;
    border-radius: var(--qt-radius-pill, 29px);
    cursor: pointer;
    transition: all 0.18s ease-in-out;
}

#quote-tool .loc-finder__submit:hover,
.loc-finder__submit:hover,
#quote-tool .loc-finder__submit:focus-visible,
.loc-finder__submit:focus-visible {
    background-position: 100% 0;
}

/* "Use my location" — a text link with the pin icon. */
#quote-tool .loc-finder__geo,
.loc-finder__geo {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--qt-blue);
    font-family: var(--qt-font-body, Lato, sans-serif);
    font-size: 16px;
    cursor: pointer;
    transition: all 0.18s ease-in-out;
}

#quote-tool .loc-finder__geo:hover,
.loc-finder__geo:hover {
    color: var(--qt-purple);
}

#quote-tool .loc-finder__geo .icon,
.loc-finder__geo .icon {
    font-size: 18px;
}

.loc-finder__msg {
    margin: 0;
    font-size: 15px;
    color: var(--qt-gray);
}

/* Layout (standalone finder — the quote tool overrides this grid with its own
   in quote-tool.css via display:contents promotion) ----------------------- */

.loc-finder__layout {
    display: grid;
    grid-template-columns: 46% 1fr;
    gap: 1rem;
    align-items: start;
    margin-top: 25px;
}

/* The quote tool renders the cards in a separate Gravity Forms field, so the
   finder is map-only and takes the full width. */
.loc-finder__layout:not(:has(.loc-finder__list)) {
    grid-template-columns: 1fr;
}

.loc-finder__list {
    max-height: 500px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

/* User's own position, dropped by locationsFinder.js after a search. */
.loc-finder__user-dot {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--qt-purple);
    border: 3px solid var(--qt-white);
    box-shadow: 0 0 0 2px rgba(134, 40, 137, 0.35);
}

/* Location cards ----------------------------------------------------------
   Tinted-gradient tiles, flat at rest — no border, no shadow. The active card
   gets an inset ring (it's a control state, not decoration). */

.loc-card {
    position: relative;
    box-sizing: border-box;
    width: 100%;
    padding: 20px 22px;
    background: var(--qt-surface-grad, linear-gradient(146.98deg, #f1f1f1 0, #ffffff 100%));
    border-radius: var(--qt-radius-card, 20px);
    cursor: pointer;
    transition: all 0.18s ease-in-out;
}

/* Hover reads on three channels at once — a 2px ring, a cyan-tinted surface and
   a soft lift — because one pixel of cyan on an already-tinted card was easy to
   miss. The tint is what does most of the work: the ring is only ever a hairline
   at the card's edge, while the surface change is the whole tile. */
.loc-card:hover {
    background: linear-gradient(146.98deg, #e8f6fb 0, #ffffff 100%);
    box-shadow:
        inset 0 0 0 2px var(--qt-cyan-hover, #25afd2),
        0 6px 18px rgba(0, 52, 95, 0.13);
}

.loc-card--active {
    box-shadow: inset 0 0 0 2px var(--qt-blue, #0060af);
}

/* Selected outranks hovered. .loc-card:hover is (0,2,0) and .loc-card--active is
   only (0,1,0), so without this the chosen card repaints itself in the hover
   colours under the cursor and stops looking chosen — which the louder hover
   above would have made obvious rather than subtle. */
.loc-card--active:hover {
    background: linear-gradient(146.98deg, #e8f2fa 0, #ffffff 100%);
    box-shadow:
        inset 0 0 0 2px var(--qt-blue, #0060af),
        0 6px 18px rgba(0, 52, 95, 0.13);
}

.loc-card__main {
    min-width: 0;
}

.loc-card__top {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 14px;
}

.loc-card__title {
    margin: 0;
    font-family: var(--qt-font-heading, Cachet, Geneva, sans-serif);
    font-weight: 700;
    font-size: 24px;
    line-height: 24px;
    letter-spacing: -2px;
    color: #000;
}

/* Distance badge. Stays a flex ITEM rather than going absolute so the title
   can never run underneath it, then negative margins lift it up and out into
   the card's own padding — it reads as sitting in the corner, and the ~10px of
   card left around it is the breathing room that makes it pop.

   No `display` here on purpose: locationsFinder.js shows and hides this with
   the `hidden` attribute, which a display of our own would override. */
.loc-card__distance {
    flex: 0 0 auto;
    margin: -10px -12px 0 0;
    padding: 8px 15px;
    border-radius: 9999px;
    background: var(--qt-gradient-badge, linear-gradient(135deg, #0460ad 0, #862889 100%));
    font-size: 14px;
    font-weight: 700;
    line-height: 1;
    letter-spacing: 0.3px;
    color: var(--qt-white, #fff);
    white-space: nowrap;
    box-shadow: 0 3px 10px rgba(134, 40, 137, 0.3);
}

/* "Nearest" rides inside the distance pill on whichever hub the sort put first,
   because every other way of marking that card is already spoken for: a border,
   ring or glow reads as .loc-card:hover (cyan ring) or .loc-card--active (blue
   ring), and a line of its own would give back the vertical space hiding the
   offerings just bought. Label/value, so it stays one pill rather than two. */
.loc-card__nearest {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.8px;
    text-transform: uppercase;
}

.loc-card__nearest::after {
    content: " · ";
    letter-spacing: 0;
    opacity: 0.7;
}

.loc-card__address {
    margin: 8px 0 0;
    font-size: 14px;
    line-height: 21px;
    color: var(--qt-gray);
}

.loc-card__offerings {
    margin: 10px 0 0;
    font-size: 13px;
    line-height: 20px;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    color: var(--qt-ink, #2a2a2a);
}

.loc-card__offerings-more {
    color: var(--qt-gray);
}

/* Step 2 shows every hub at once, so each card is bought with vertical space in
   the rail — the offerings line is the most expensive part of one and the least
   useful before a hub is picked. Hidden here, NOT removed from
   location_card_html(): the standalone finder ([generate_map finder="1"]) has
   no detail panel to expand into (quoteToolRail.js is scoped to #quote-tool),
   so dropping the markup would leave those cards with no amenities at all. */
#quote-tool .loc-card__offerings {
    display: none;
}

.loc-card__more {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 14px;
    font-size: 15px;
    color: var(--qt-blue);
    transition: all 0.18s ease-in-out;
}

.loc-card:hover .loc-card__more {
    color: var(--qt-purple);
}

.loc-card__more .icon {
    font-size: 16px;
}

/* Rail chrome (inserted by quoteToolRail.js) ------------------------------ */

#quote-tool .qt-rail__count,
.qt-rail__count {
    margin: 0;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    color: var(--qt-gray);
}

/* Hub detail panel (cloned from each card's <template>) ------------------- */

.qt-hub-detail {
    display: flex;
    flex-direction: column;
    height: 100%;
    box-sizing: border-box;
    padding: 24px;
    background: var(--qt-surface-grad, linear-gradient(146.98deg, #f1f1f1 0, #ffffff 100%));
    border-radius: var(--qt-radius-card, 20px);
}

#quote-tool .qt-hub-detail__back,
.qt-hub-detail__back {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    align-self: flex-start;
    padding: 0;
    border: 0;
    background: none;
    font-family: var(--qt-font-body, Lato, sans-serif);
    font-size: 15px;
    color: var(--qt-blue);
    cursor: pointer;
    transition: all 0.18s ease-in-out;
}

#quote-tool .qt-hub-detail__back:hover,
.qt-hub-detail__back:hover {
    color: var(--qt-purple);
}

.qt-hub-detail__back .icon {
    font-size: 18px;
}

.qt-hub-detail__media {
    flex: none;
    height: 140px;
    margin-top: 16px;
    border-radius: 8px;
    overflow: hidden;
}

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

.qt-hub-detail__title {
    margin: 18px 0 0;
    font-family: var(--qt-font-heading, Cachet, Geneva, sans-serif);
    font-weight: 700;
    font-size: 30px;
    line-height: 30px;
    letter-spacing: -2px;
    color: #000;
}

.qt-hub-detail__meta {
    margin: 10px 0 0;
    font-size: 15px;
    line-height: 22px;
    color: var(--qt-gray);
}

/* Section headings. These were 13px grey uppercase eyebrows — the same size,
   case and tracking as the amenity items under them, so "Amenities" vanished
   into its own list (client note 2026-09-02). Now a Cachet subhead one step
   under the panel title. */
.qt-hub-detail__label {
    margin: 22px 0 0;
    font-family: var(--qt-font-heading, Cachet, Geneva, sans-serif);
    font-weight: 700;
    font-size: 20px;
    line-height: 22px;
    letter-spacing: -1px;
    text-transform: none;
    color: #000;
}

.qt-hub-detail__hours {
    margin-top: 6px;
}

.qt-hub-detail__hours-row {
    display: flex;
    justify-content: space-between;
    gap: 15px;
    padding: 7px 0;
    border-bottom: 1px solid var(--qt-hairline, #dcdcdc);
}

.qt-hub-detail__days {
    font-size: 14px;
    color: var(--qt-gray);
}

.qt-hub-detail__times {
    font-size: 14px;
    color: var(--qt-ink, #2a2a2a);
}

.qt-hub-detail__amenities {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0 15px;
    margin: 8px 0 0;
    padding: 0;
    list-style: none;
}

.qt-hub-detail__amenities li {
    font-size: 13px;
    line-height: 26px;
    letter-spacing: 0.6px;
    text-transform: uppercase;
}

/* Contact: phone over email, both using the same icon-and-text link grammar as
   "All hubs" above them and "Use my location" in the search row. The wrapper
   owns the run's top margin so either row can be absent (a branch may have one,
   both, or neither) without leaving a gap behind. */
.qt-hub-detail__contact {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 18px 0 0;
}

.qt-hub-detail__phone,
.qt-hub-detail__email {
    margin: 0;
    font-size: 15px;
}

.qt-hub-detail__phone a,
.qt-hub-detail__email a {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-weight: 700;
    color: var(--qt-blue);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
    text-decoration-color: rgba(0, 96, 175, 0.35);
    transition: all 0.18s ease-in-out;
}

.qt-hub-detail__phone a:hover,
.qt-hub-detail__email a:hover {
    color: var(--qt-purple);
    text-decoration-color: currentColor;
}

.qt-hub-detail__phone .icon,
.qt-hub-detail__email .icon {
    font-size: 15px;
    flex: 0 0 auto;
}

/* westgarfieldpark@ymcachicago.org is 32 characters — longer than the panel is
   wide at the narrow end. Let the address wrap rather than widen the panel, and
   keep the icon top-aligned to the first line once it does. */
.qt-hub-detail__email a {
    align-items: flex-start;
    word-break: break-word;
}

.qt-hub-detail__email .icon {
    position: relative;
    top: 2px;
}

/* "Select This Hub" — full-width gradient pill pinned to the panel bottom.
   Same purple slide on hover as every other pill. */
.qt-hub-detail__cta {
    margin-top: auto;
    padding-top: 22px;
}

#quote-tool .qt-hub-detail__select,
.qt-hub-detail__select {
    display: block;
    width: 100%;
    padding: 18px 35px;
    background: var(--qt-gradient-pill);
    background-size: 300% 100%;
    background-position: 0 0;
    color: var(--qt-white);
    font-family: var(--qt-font-heading, Cachet, Geneva, sans-serif);
    font-size: 16px;
    line-height: 22.4px;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    text-align: center;
    border: 0;
    border-radius: var(--qt-radius-pill, 29px);
    cursor: pointer;
    transition: all 0.18s ease-in-out;
}

#quote-tool .qt-hub-detail__select:hover,
.qt-hub-detail__select:hover,
#quote-tool .qt-hub-detail__select:focus-visible,
.qt-hub-detail__select:focus-visible {
    background-position: 100% 0;
}

/* GF inserts its loader inside the native Next button. Once that button lives
   in the detail panel, let the loader replace the label just as it does in the
   standard form footer. */
#quote-tool .qt-hub-detail__select.gform-has-spinner,
#quote-tool .qt-hub-detail__select.gform-has-spinner:hover,
#quote-tool .qt-hub-detail__select.gform-has-spinner:focus {
    color: transparent;
}

/* As a Gravity Forms radio choice ----------------------------------------- */

#quote-tool .location-cards {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 15px;
    height: 100%;
    box-sizing: border-box;
}

/* Every hub shows at once — two columns where the rail is wide enough, one
   where it isn't, scrolling past the map's bottom edge. Nearest-first once a
   search has run (the sort re-appends in distance order, then snaps to top).
   The max() pins each track to at least half the rail, so auto-fill tops out
   at two columns no matter how wide the screen gets. */
#quote-tool .location-cards .gfield_radio {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(max(280px, calc(50% - 8px)), 1fr));
    gap: 15px;
    max-height: 505px;
    overflow-y: auto;
}

/* position: relative keeps each hidden radio's containing block INSIDE the
   scrolling list. Without it the 1px inputs resolve against the field root
   (position: relative, outside the scroller) at their UNSCROLLED positions, so
   once the rail is scrolled, clicking a card label makes the browser's
   focus-into-view scroll chase a phantom input far below — the page jumps and
   the form leaves the viewport. */
/* Stretched to the full grid track on purpose. A .gchoice sizes to its content
   otherwise, and until the offerings line was hidden that content was wide
   enough to reach the track edge on its own — so the cards LOOKED like a tidy
   two-column grid while actually being shrink-to-fit, and lost half their width
   the moment the widest line went away. */
#quote-tool .location-cards .gfield_radio .gchoice {
    position: relative;
    display: block;
    box-sizing: border-box;
    width: 100%;
    min-width: 0;
}

/* Bottom fade — "there's more below". quoteToolRail.js drops it (via the
   at-end class) once the list is scrolled to the end or nothing overflows. */
#quote-tool .location-cards::after {
    content: "";
    position: absolute;
    inset: auto 0 0 0;
    height: 64px;
    background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #fff);
    pointer-events: none;
    opacity: 1;
    transition: opacity 0.18s ease-in-out;
}

#quote-tool .location-cards--at-end::after,
#quote-tool .location-cards--detail::after {
    opacity: 0;
}

/* Detail state: the panel replaces the rail in place. */
#quote-tool .location-cards--detail .gfield_radio,
#quote-tool .location-cards--detail .qt-rail__count {
    display: none;
}

#quote-tool .location-cards--detail {
    max-height: none;
}

/* The card IS the control; the input is redundant to sighted users but must stay
   focusable, so it's clipped rather than display:none. */
#quote-tool .location-cards input[type="radio"] {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

#quote-tool .location-cards .gchoice label {
    display: block;
    width: 100%;
    cursor: pointer;
}

#quote-tool .location-cards input[type="radio"]:focus-visible + label .loc-card {
    outline: 2px solid var(--qt-purple);
    outline-offset: 2px;
}

/* Step-2 motion -------------------------------------------------------------
   The card ⇄ panel swap (quoteToolRail.js) and the search re-sort
   (locationsFinder.js) run inside view transitions with transient
   view-transition-names; browsers without the API get the instant behavior. */

/* The map repaints on its own (tiles, camera flights) — snapshot it as its own
   stable group so it doesn't strobe inside the page crossfade. Note: a page
   with TWO maps would duplicate this name and the browser would skip the
   transition (instant swap) — acceptable, never broken. */
.shortcode-map {
    view-transition-name: qt-map;
}

/* One tempo for the morph, the card glides, and the residual crossfade — the
   house 0.18s family, stretched slightly because these travel. */
::view-transition-group(*),
::view-transition-old(*),
::view-transition-new(*) {
    animation-duration: 0.3s;
    animation-timing-function: ease-in-out;
}

@media (prefers-reduced-motion: reduce) {
    ::view-transition-group(*),
    ::view-transition-old(*),
    ::view-transition-new(*) {
        animation: none !important;
    }
}

@media (max-width: 60em) {
    .loc-finder__layout {
        grid-template-columns: 1fr;
    }

    .loc-finder__list {
        max-height: none;
    }

    /* Stacked layout: the list flows in full, so there's no scroll to hint at. */
    #quote-tool .location-cards .gfield_radio {
        max-height: none;
    }

    #quote-tool .location-cards::after {
        content: none;
    }

    .qt-hub-detail {
        height: auto;
    }

    .qt-hub-detail__cta {
        padding-top: 25px;
    }
}

/* Small phones (≤375px): the rail track's 280px floor is wider than the rail
   itself at 320px (242px), so the location cards ran 38px past the column.
   One track that can shrink. Lives here, not in quote-tool.css: this sheet
   loads after it and the auto-fill rule above would win on source order. */
@media (max-width: 23.4375em) {
    #quote-tool .location-cards .gfield_radio {
        grid-template-columns: minmax(0, 1fr);
    }
}
