/* ─────────────────────────────────────────────────────────────────────────
   Place card — shared template used wherever a "place" needs to be shown
   as a square-ish card with image, title, category, bookmark, and votes.
   Mirrors the saved-card visual language from /profile/saved.

   Pages should:
     <link rel="stylesheet" href="/partials/place-card.css?v=N">
     <script src="/partials/place-card.js?v=N"></script>
   ───────────────────────────────────────────────────────────────────────── */

.place-card {
    position: relative;
    display: flex;
    flex-direction: column;
    text-decoration: none;
    color: inherit;
    cursor: pointer;
    background: white;
    border: 1px solid var(--color-divider);
    border-radius: var(--radius-md);
    overflow: hidden;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
    transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.2s ease;
}
.place-card:hover,
.place-card.is-hovered {
    transform: scale(1.01);
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    /*border-color: var(--color-border);*/
}

.place-card-img {
    position: relative;
    aspect-ratio: 4 / 3;
    overflow: hidden;
    margin: 0;
    background: var(--color-divider);
}

.place-card-bookmark {
    position: absolute;
    /* Nudged 4px toward the corner: the 40px button centers a 28px icon, so
       the visible icon sat ~16px in. 6px button inset → icon edge ~12px,
       closer to the region pill / votes 10px gap. */
    top: 6px;
    right: 6px;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: transform 0.3s ease;
    border: none;
    background: transparent;
    padding: 0;
}
.place-card-bookmark:hover { transform: scale(1.1); }
.place-card-bookmark svg {
    width: 28px;
    height: 28px;
    stroke: white;
    stroke-width: 1.7;
    fill: rgba(0, 0, 0, 0.35);
    transition: fill 0.2s ease, stroke 0.2s ease;
}
.place-card-bookmark.active svg {
    fill: var(--color-brand);
    /* stroke stays white (from base) — only the fill turns brand when saved. */
}

.place-card-region {
    position: absolute;
    bottom: 10px;
    right: 10px;
    padding: 5px 12px;
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: blur(4px);
    border-radius: 999px;
    font-size: 14px;
    font-weight: 500;
    color: var(--color-text);
    white-space: nowrap;
    line-height: 1;
}

/* Sponsored "Ad" label — sits at the right end of the eyebrow row, faint.
   (Placed in the V2 grid below; sponsored places only.) */
.place-card-ad {
    font-size: 14px;
    font-weight: 500;
    color: var(--color-text-disabled);
    line-height: 1.3;
    white-space: nowrap;
}

.place-card-eyebrow {
    font-size: 14px;
    font-weight: 500;
    color: var(--color-text-muted);
    margin: 0 0 2px;
    padding: 14px 16px 0;
    line-height: 1.3;
}
.place-card-title {
    font-size: 18px;
    font-weight: 500;
    color: var(--color-text);
    margin: 0;
    padding: 0 16px;
    line-height: 1.3;
    min-height: 2.6em;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.place-card-category {
    font-size: 14px;
    color: var(--color-text-muted);
    margin: 2px 0 0;
    padding: 0 60px 14px 16px;
    line-height: 1.3;
}

.place-card-votes {
    position: absolute;
    right: 6px;          /* compensated for the pill padding */
    bottom: 6px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    /* Fixed size + two fixed zones (arrow | number) so the pill never resizes
       and the number never shifts, whether the count is 1, 3, or 4 digits.
       72×28: width 72; height = 6 + 16 (svg) + 6. */
    width: 72px;
    box-sizing: border-box;
    font-size: 14px;
    color: var(--color-text-muted);
    line-height: 1;
    cursor: pointer;
    user-select: none;
    padding: 6px 10px;
    border-radius: 999px;
    background: transparent;
    transform-origin: center;
    transition: color 0.15s ease, background-color 0.15s ease, transform 0.3s ease;
}
.place-card-votes:hover {
    background: var(--color-surface);
    transform: scale(1.05);   /* slight grow from center — signals it's clickable */
}
.place-card-votes svg {
    width: 16px;
    height: 16px;
    flex: 0 0 16px;      /* left zone — arrow, fixed */
    /* Outlined arrow (not filled): a solid/filled arrow reads as "already
       voted", so the default state is a stroke-only outline. stroke-width is in
       24-unit viewBox space → 1.875 renders ~1.25px at the 16px display size. */
    fill: none;
    stroke: currentColor;
    stroke-width: 1.875;
    stroke-linejoin: round;
    stroke-linecap: round;
    transition: transform 0.2s ease, stroke 0.15s ease, fill 0.15s ease;
}
/* Right zone — number. Fills the remaining width and centers the digits, so
   they sit in the same spot regardless of count; tabular-nums keeps every
   digit the same width (no jitter within a given length). */
.place-card-vote-count {
    flex: 1 1 auto;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
/* Vote states cycle on click: none → upvoted → downvoted → none.
   Colors mirror the detail-page vote pill (#23d3d3 mint / #9494FF lavender). */
.place-card-votes.upvoted   { color: var(--color-brand); }
.place-card-votes.downvoted { color: var(--color-downvote); }
.place-card-votes.downvoted svg { transform: rotate(180deg); }
/* Voted (upvoted) → fill the arrow while keeping the same stroke + width; the
   .upvoted color above makes both stroke and fill currentColor = brand
   (#23d3d3). Unvoted stays a stroke-only (muted) outline. */
.place-card-votes.upvoted svg { fill: currentColor; }

/* Hit-slop: a transparent ::before expands the tap/click target beyond the
   pill on all four sides. Box = 82×44 (pill 72×28 grown by these insets):
   -8 top/bottom → 44 tall, -5 left/right → 82 wide. Clicks on the slop fire
   the votes handler. */
.place-card-votes::before {
    content: "";
    position: absolute;
    top: -8px;
    bottom: -8px;
    left: -5px;
    right: -5px;
}

/* ─────────────────────────────────────────────────────────────────────────
   Variant V2 — Airbnb-style minimal: no card border/bg/shadow, image is a
   standalone rounded rectangle, text below uses CSS Grid to put eyebrow +
   category on the same row and place votes (in flow, not absolute) where
   category used to be — at the bottom of the text block.
   Same HTML structure as V1, switched via the `place-card--v2` modifier.
   ───────────────────────────────────────────────────────────────────────── */
.place-card--v2 {
    display: grid;
    /* col3 (auto) holds the sponsored "Ad" label, right-aligned; 0-width when
       absent so non-sponsored cards are unaffected. minmax(0,1fr) on col2 lets it
       shrink below the category's content (default 1fr min is min-content) so the
       category clips behind the Ad instead of wrapping/pushing the row wider. */
    grid-template-columns: auto minmax(0, 1fr) auto;
    background: transparent;
    border: none;
    border-radius: 0;
    box-shadow: none;
    overflow: visible;
}
.place-card--v2:hover,
.place-card--v2.is-hovered {
    transform: none;
    box-shadow: none;
}
.place-card--v2 .place-card-img {
    grid-column: 1 / -1;
    grid-row: 1;
    /* Radius = Seoul pill's effective radius (~12px) + its 10px inset,
       so the image's corner curve is concentric with the pill's. */
    border-radius: var(--radius-lg);
    /* Shadow + hover lift mirror the serendipity .resource-card-img: a
       slightly stronger resting shadow and a 1.02 scale on hover, eased with
       a springy cubic-bezier. Applied only to the image frame (V2 has no
       card container to carry the shadow). */
    box-shadow: 0 2px 2px rgba(0, 0, 0, 0.15);
    transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.3s ease;
}
/* Bevel — a hair of "card thickness": light catches the top inner edge, the
   bottom inner edge shades, plus a hairline keyline so pale photos don't melt
   into the page. Pairs with the outer drop shadow (same top-light model).
   Static inset shadows paint once — no animation/perf cost. */
.place-card--v2 .place-card-img::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    z-index: 3;
    box-shadow:
        inset 0 2px 2px rgba(255, 255, 255, 0.55),
        inset 0 -2px 3px rgba(0, 0, 0, 0.22),
        inset 0 0 0 1px rgba(0, 0, 0, 0.08);
}
.place-card--v2:hover .place-card-img,
.place-card--v2.is-hovered .place-card-img {
    transform: scale(1.02);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
}
/* Row 2: eyebrow + category + (Ad) ALWAYS one line — never wraps to two. The
   category clips (nowrap + min-width:0 so its col can shrink + overflow:hidden),
   disappearing behind the Ad at the right when it's too long. */
.place-card--v2 .place-card-eyebrow {
    grid-column: 1;
    grid-row: 2;
    padding: 12px 0 0 12px;
    margin: 0;
    white-space: nowrap;
}
.place-card--v2 .place-card-category {
    grid-column: 2;
    grid-row: 2;
    padding: 12px 12px 0 12px;
    margin: 0;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    /* Fade the (clipped) category out over its last 16px toward the Ad — same
       16px fade as the tab bar's left veil, but applied as a mask on the text so
       it dissolves into the card instead of hard-cutting. */
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 16px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 16px), transparent);
}
/* "Ad" label → far-right of the eyebrow row (col 3), top-aligned with it. */
.place-card--v2 .place-card-ad {
    grid-column: 3;
    grid-row: 2;
    justify-self: end;
    align-self: start;
    padding: 12px 12px 0 0;
}
/* Row 3: title spans the full text block — keep V1's 2-line min-height so
   long titles wrap cleanly and cards stay aligned. */
.place-card--v2 .place-card-title {
    grid-column: 1 / -1;
    grid-row: 3;
    padding: 0 12px;
}
/* Region pill → top-left corner of the image (V2 only). */
.place-card--v2 .place-card-region {
    top: 10px;
    left: 10px;
    bottom: auto;
    right: auto;
}
/* Votes → overlaid on the image's bottom-right, where the region used to sit.
   It's a CHILD of .place-card-img (see place-card.js), pinned to the image's
   bottom-right corner; given the region pill's frosted background so it stays
   legible over photos. Being inside the image means the image's hover scale
   carries it along. */
.place-card--v2 .place-card-votes {
    position: absolute;
    bottom: 10px;
    right: 10px;
    margin: 0;
    z-index: 2;
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: blur(4px);
}

