/*
 * [hub_boxy] — curated offer-box grid. Dedicated card design (.hub-cs-box-card-*),
 * not a reuse of [hub_szukaj]'s .hub-cs-row — depends on search.css only for the
 * shared --hub-cs-accent/--hub-cs-base-font theme-inheriting variables (see that
 * file's :root), not for any of its row/card classes.
 */

.hub-cs-boxes-grid {
    /* Explicit width: 100% + box-sizing: border-box — this plugin has no
       global box-sizing reset, so left implicit this is content-box, and a
       shrink-to-fit-vs-fill-parent ambiguity on the SLIDER container itself
       (not just its .hub-cs-box-card children, already fixed) turned out to
       be part of why the mobile card was overflowing the viewport: the
       calc(100% - ...) flex-basis on each card only means what it says if
       this container's OWN 100% is unambiguously the actual visible width. */
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    display: grid;
    /* min() against the actual card count (set inline by the shortcode as
       --hub-cs-box-count) instead of a bare "4" — with fewer cards than the
       breakpoint's usual max, a hardcoded repeat(4, 1fr) still reserves 4
       equal-width tracks and only fills the first N, so e.g. 2 cards each
       render at 1/4 width with 2 empty tracks alongside instead of at the
       1/2 width the container actually has room for. The var's fallback (4)
       covers any caller that renders this markup without setting it. */
    grid-template-columns: repeat(min(4, var(--hub-cs-box-count, 4)), 1fr);
    gap: 20px;
}

@media (max-width: 1100px) {
    .hub-cs-boxes-grid {
        grid-template-columns: repeat(min(3, var(--hub-cs-box-count, 3)), 1fr);
    }
}

/*
 * Tablet/phone switch from a wrapping grid to a horizontal scroll-snap
 * slider — one row, native touch swipe (no JS needed), each card sized so
 * the NEXT one peeks in ~10% on the right edge as a visual invitation to
 * swipe, per request: 2 full cards + 10% of a 3rd on tablet, 1 full card +
 * 10% of the 2nd on phone. box-width * 1.1 = container width is the
 * relationship that makes "10% of the box" and "the sliver left over past N
 * full boxes" the same number, hence the /1.1 and /2.1 divisors below.
 */
@media (max-width: 900px) {
    .hub-cs-boxes-grid {
        display: flex;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        -webkit-overflow-scrolling: touch;
        gap: 16px;
        /* Room so each card's own :hover box-shadow doesn't clip against the
           scroll container's edge, and for platforms that render a visible
           horizontal scrollbar. */
        padding-bottom: 6px;
        /* Hides that scrollbar where the browser allows it — a swipeable
           row reads as a carousel, a scrollbar under it reads as a bug. */
        scrollbar-width: none;
    }

    .hub-cs-boxes-grid::-webkit-scrollbar {
        display: none;
    }

    .hub-cs-boxes-grid .hub-cs-box-card {
        scroll-snap-align: start;
        flex: 0 0 calc((100% - 2 * 16px) / 2.1);
    }
}

@media (max-width: 600px) {
    .hub-cs-boxes-grid .hub-cs-box-card {
        flex: 0 0 calc((100% - 16px) / 1.1);
    }

    /* Tighter than the desktop/tablet sizing — the narrowest slider card
       width is what was letting a date's own text outgrow its (equal-width,
       min-width: 0) box in the first place; this reduces how often the
       overflow: hidden safety net above actually has anything to clip. */
    .hub-cs-box-card-fact {
        padding: 6px 4px;
    }

    .hub-cs-box-card-fact b {
        font-size: 0.8125rem;
    }
}

.hub-cs-box-card {
    display: flex;
    flex-direction: column;
    /* A flex/grid item's default min-width is auto, not 0 — it refuses to
       shrink below its own content's natural width. A real cruise-ship photo
       is easily 1200-2000px+ wide, so without this, the card sized itself off
       THAT instead of its assigned flex-basis/grid track (found live: "the
       mobile card is at ~700% of screen width" in the horizontal slider,
       where flex: 0 0 calc(...) was being ignored entirely for exactly this
       reason). Set on the base rule, not just the mobile slider override, so
       the desktop grid (grid-template-columns: repeat(4, 1fr), which has the
       exact same footgun for a plain 1fr track) can't hit this either. */
    min-width: 0;
    /* The 1px border below would otherwise add to a calc()-based flex-basis
       width (content-box is the default here — no global reset in this
       plugin) instead of being absorbed into it. Small on its own (2px),
       included as part of the same box-sizing audit as the container fix
       above rather than leaving it as the one remaining implicit case. */
    box-sizing: border-box;
    border: 1px solid #e2e2e2;
    border-radius: 14px;
    overflow: hidden;
    text-decoration: none;
    color: inherit;
    background: #fff;
    transition: box-shadow 0.15s ease;
}

.hub-cs-box-card:hover {
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.1);
}

.hub-cs-box-card-media {
    position: relative;
    /* Explicit width: 100% (not left to flex's align-items: stretch to
       supply it) is what makes aspect-ratio reliably compute a height from
       it — .hub-cs-box-card is flex-direction: column, and an item's cross-
       axis stretch + aspect-ratio interaction is a newer, less consistently
       implemented part of the spec than "definite width -> aspect-ratio
       height", which every current browser handles the same way. Without
       this, the height side of the ratio wasn't resolving in the mobile
       stacked layout, so the <img> below (height: 100%, a percentage that's
       only meaningful against a PARENT with a definite height) fell back to
       its own raw intrinsic size instead — a real photo can easily be
       2000px+ tall, which is exactly what rendered (found live via
       screenshot: a single photo taller than the whole visible screen). */
    width: 100%;
    aspect-ratio: 16 / 10;
    /* Unconditional hard cap, independent of whether aspect-ratio above
       resolves correctly at all — two rounds of fixing the aspect-ratio/
       stretch computation itself (see the comment above) made zero visible
       difference per live testing, so this stops trusting that computation
       and just forbids the box from ever exceeding this height outright.
       max-height has no complex spec interactions to get wrong the way
       aspect-ratio+flex-stretch apparently does — combined with the
       existing overflow: hidden + the photo's own object-fit: cover, a
       genuinely huge intrinsic image just gets cropped, never renders at
       its raw size. */
    max-height: 220px;
    background: #eee;
    overflow: hidden;
}

.hub-cs-box-card-media img:not(.hub-cs-box-card-logo) {
    /* Absolutely positioned against .hub-cs-box-card-media's own position:
       relative box instead of a plain width/height: 100% — sidesteps the
       percentage-height-needs-a-definite-height-parent question entirely
       (belt-and-suspenders on top of the width: 100% fix above, not a
       replacement for it: something already this defensive shouldn't need
       a THIRD occurrence of this exact bug to get found). */
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.hub-cs-box-card-logo {
    position: absolute;
    top: 10px;
    left: 10px;
    /* -30% of the previous 30%/110px, per request. */
    width: 21%;
    max-width: 77px;
    height: auto;
    border-radius: 4px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
}

/* "Na zdjęciu etykieta z ceną" — overlaid on the photo itself (per request),
   not in its own section like the [hub_szukaj] row. No EUR hint line here at
   all, even for a non-EUR price — that conversion hint is a listing-only
   thing (see search.js), not shown on a box regardless of currency. */
.hub-cs-box-card-price {
    position: absolute;
    right: 10px;
    bottom: 10px;
    /* Fixed, not content-sized — otherwise "179 EUR" and "88 503 EUR" badges
       land at different widths/positions across cards in the same row. Wide
       enough for a realistic worst case ("123 456 EUR") at this font-size. */
    width: 150px;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 2px;
    padding: 8px 14px;
    border-radius: 10px;
    background: var(--hub-cs-accent);
    color: var(--hub-cs-accent-text);
}

.hub-cs-box-card-price-label {
    font-size: 0.75rem;
    opacity: 0.85;
}

.hub-cs-box-card-price-value {
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.1;
    white-space: nowrap;
}

.hub-cs-box-card-body {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 16px 18px 18px;
}

.hub-cs-box-card-region {
    align-self: flex-start;
    padding: 4px 12px;
    border-radius: 999px;
    background: var(--hub-cs-accent);
    color: var(--hub-cs-accent-text);
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.4;
}

/* Region + transport chips in one line, same pill style for both. */
.hub-cs-box-card-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

/* Parent-qualified (not just .hub-cs-box-card-title) and margin-block-*
   explicitly reset, not just margin: 0 — a bare single-class selector on a
   real <h3> ties in specificity with Blocksy's own
   `:is(.is-layout-flow,.is-layout-constrained) :where(h1..h6)` margin rule
   (its :where() contributes zero specificity, landing it at exactly one
   class), and a tie goes to whichever loads later (the theme) — the exact
   bug already found and fixed for search.css's own .hub-cs-row-title. */
.hub-cs-box-card-body .hub-cs-box-card-title {
    margin: 0;
    margin-block-start: 0;
    margin-block-end: 0;
    /* Reserves the full 2-line height regardless of whether THIS title
       actually wraps to 2 lines — without it, a 1-line title left everything
       below (route, fact boxes, footer) sitting higher than in a neighboring
       card whose title/route wrapped further, so the fact boxes across a row
       ended up at different Y positions instead of aligning (found live). */
    min-height: 2.6em;
    font-size: 1.0625rem;
    font-weight: 700;
    line-height: 1.3;
    text-transform: uppercase;
    /* Clamped to 2 lines — only shows an ellipsis when it actually doesn't
       fit, never cuts a title that already fits in two lines. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.hub-cs-box-card-route {
    margin: 0;
    /* Same reservation as the title above, same reason — a 1-line route
       (e.g. "Keelung → Busan") must take up as much vertical space as a
       2-line one, or the fact boxes below it drift up. */
    min-height: 2.8em;
    font-size: 0.8125rem;
    color: #555;
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* CSS Grid, not flex — a flex item's default min-width is auto, meaning it
   won't shrink below its own content's width even at equal flex-grow, so the
   OD/DO boxes ended up sized by their OWN date text ("23.09.2026" wider than
   "5.09.2026") instead of matching each other (found live). Grid's `1fr`
   tracks don't have that footgun IF paired with minmax(0, 1fr) — that's what
   actually forces both date columns to the same width regardless of their
   text, without touching the card's own outer padding at all. */
.hub-cs-box-card-facts {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) minmax(0, 1fr);
    gap: 8px;
    margin: 4px 0 2px;
}

.hub-cs-box-card-fact {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 6px 8px;
    border: 1.5px solid var(--hub-cs-accent);
    border-radius: 8px;
    text-align: center;
    min-width: 0;
    /* minmax(0, 1fr) on the grid track above deliberately allows this box to
       shrink narrower than its own date text's natural width (that's what
       makes the two date boxes match each other regardless of content) — on
       a narrow slider card that shrink can go far enough that the date
       spilled visually past this border instead of just being clipped by it
       (found live). This is the safety net for that case. */
    overflow: hidden;
}

.hub-cs-box-card-fact span {
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: #888;
}

.hub-cs-box-card-fact b {
    font-size: 0.9375rem;
    white-space: nowrap;
}

.hub-cs-box-card-fact-nights {
    min-width: 60px;
}

.hub-cs-box-card-fact-nights b {
    font-size: 1.375rem;
    line-height: 1.1;
}

.hub-cs-box-card-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-top: 8px;
}

/* Icon ABOVE the name (per the reference screenshot), not beside it — a
   centered column, not a row. flex: 0 1 auto (grow: 0) is what actually
   fixes the huge left/right "padding" look from the previous version: with
   flex-grow: 1 this column claimed ALL leftover space in the footer row
   (the CTA button is flex: 0 0 auto and never grows), so a short name like
   "Mein Schiff 2" sat centered inside a column much wider than it needed —
   reading as oversized padding even though no padding was ever set (found
   live via a DevTools screenshot). flex-shrink stays 1 + min-width: 0 so a
   genuinely long name still shrinks/ellipsizes against the button instead
   of pushing it off — it just no longer grows past its own content first.
   font-size set here (not just on the name span) so the icon's own em
   height below means exactly what was asked: relative to the name's own
   text height, not some unrelated inherited size. */
.hub-cs-box-card-ship {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    flex: 0 1 auto;
    min-width: 0;
    font-size: 0.875rem;
}

.hub-cs-box-card-ship img {
    /* -20% of the previous 2.8em, per request. */
    height: 2.24em;
    width: auto;
}

.hub-cs-box-card-ship-name {
    /* align-items: center above sizes everything to its own content by
       default — fine for the icon, but the name then has no definite width
       to ellipsize against (content that's free to be as wide as it wants
       never overflows itself). align-self: stretch overrides just this one
       child back to the column's full (already width-constrained) size, and
       text-align centers whatever text ends up inside that box. */
    align-self: stretch;
    min-width: 0;
    font-size: 1em;
    font-weight: 700;
    text-align: center;
    /* Explicit, not theme-derived — this site's own --theme-link-initial-color
       resolves to black (verified live against Blocksy's actual generated
       CSS), which isn't blue at all; requested specifically as this exact hex
       rather than whatever the theme's real link color happens to be. */
    color: #004aad;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.hub-cs-box-card-cta {
    flex: 0 0 auto;
    /* -10px each side from the original 20px, per request — frees up room
       for the ship name before it has to ellipsize. */
    padding: 10px 10px;
    border-radius: 8px;
    background: var(--hub-cs-accent);
    color: var(--hub-cs-accent-text);
    font-weight: 700;
    font-size: 0.875rem;
    white-space: nowrap;
}

.hub-cs-box-card:hover .hub-cs-box-card-cta {
    background: var(--hub-cs-accent-hover);
    color: var(--hub-cs-accent-text-hover);
}
