/* ═══════════════════════════════════════════════════════════════════════════
   TOURIST DASHBOARD — homepage hero search, tours, destinations

   Every colour here is a theme.css token, so the page holds in both themes
   without a single rule living inside a [data-theme] block. Two tokens do the
   heavy lifting:

     --hub-fill        the logo's 115° green sweep. It FILLS; the only text
                       allowed on it is --hub-on-fill.
     --hub-overlay-rgb white on dark, ink on light — so one rgb(… / α) rule
                       tints correctly in both.

   The hero deliberately is not 100vh. The tours below it are the point of the
   page, and a viewport-tall opener pushes them out of the first screen.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Hero ────────────────────────────────────────────────────────────────── */

.td-hero {
    position: relative;
    /* No overflow:hidden. The search panel drops out of this section and was
       being clipped at its lower edge; the two decorative layers inside are
       inset:0 absolutes, so they stay contained without it. */
    padding: clamp(3.5rem, 9vw, 6.5rem) 0 clamp(3rem, 6vw, 4.5rem);
    background: linear-gradient(170deg,
        var(--hub-bg-deep) 0%,
        var(--hub-bg) 55%,
        var(--hub-elev) 100%);
}

.td-hero > .container {
    position: relative;
    z-index: 1;
}

.td-hero-content {
    max-width: 860px;
}

.td-hero-title {
    font-size: clamp(2.2rem, 5.5vw, 3.6rem);
    line-height: 1.06;
    letter-spacing: -0.02em;
    font-weight: 800;
    color: var(--hub-ink);
    text-wrap: balance;
    margin: 0 0 1rem;
}

.td-hero-sub {
    font-size: clamp(1rem, 1.6vw, 1.15rem);
    line-height: 1.6;
    color: var(--hub-ink-muted);
    max-width: 62ch;
    margin: 0 0 2.25rem;
}

/* ── Search ──────────────────────────────────────────────────────────────── */


/* ── Sections ────────────────────────────────────────────────────────────── */

.td-section {
    padding: clamp(3rem, 6vw, 4.5rem) 0;
    background: var(--hub-bg);
}

.td-section-alt {
    background: var(--hub-bg-deep);
}

.td-section-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1.5rem;
    margin-bottom: 2rem;
}

.td-section-title {
    font-size: clamp(1.5rem, 3vw, 2.1rem);
    font-weight: 800;
    letter-spacing: -0.015em;
    color: var(--hub-ink);
    margin: 0 0 0.4rem;
}

.td-section-sub {
    color: var(--hub-ink-muted);
    font-size: 0.98rem;
    line-height: 1.55;
    max-width: 56ch;
    margin: 0;
}

.td-section-link {
    color: var(--hub-accent);
    font-weight: 700;
    font-size: 0.95rem;
    text-decoration: none;
    white-space: nowrap;
}

.td-section-link:hover { text-decoration: underline; }

/* ── Tour cards ──────────────────────────────────────────────────────────── */

.td-tours {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 1.5rem;
}

/* With one departure published, an auto-fit track would stretch the single
   card across the full width and it would stop reading as a card. */
.td-tours > .td-tour:only-child {
    max-width: 420px;
}

.td-tour {
    display: flex;
    flex-direction: column;
    background: var(--hub-elev);
    border: 1px solid var(--hub-hairline);
    border-radius: var(--hub-radius);
    overflow: hidden;
    text-decoration: none;
    color: inherit;
    transition: transform var(--hub-transition), box-shadow var(--hub-transition),
                border-color var(--hub-transition);
}

.td-tour:hover {
    transform: translateY(-3px);
    border-color: rgb(var(--hub-accent-rgb) / 0.5);
    box-shadow: var(--hub-shadow);
}

.td-tour:focus-visible {
    outline: 3px solid var(--hub-focus);
    outline-offset: 2px;
}

.td-tour-media {
    position: relative;
    aspect-ratio: 16 / 10;
    background: var(--hub-fill);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

/* Sits over the gradient fallback; removes itself when the file is missing. */
.td-tour-media img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* Stands in for the banner most tours do not have, and stays under the image
   so a 404 leaves a panel rather than a broken-image icon. It used to carry
   the place name, which the card body also prints — every card without a
   banner said "Hanoi, Vietnam" twice. */
.td-tour-fallback {
    position: absolute;
    inset: 0;
    display: block;
}

.td-tour-body {
    display: flex;
    flex-direction: column;
    flex: 1;
    gap: 0.5rem;
    padding: 1.1rem 1.25rem 1.25rem;
}

.td-tour-place {
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--hub-accent);
    margin: 0;
}

.td-tour-title {
    font-size: 1.05rem;
    line-height: 1.35;
    font-weight: 700;
    color: var(--hub-ink);
    margin: 0;
    /* Titles here run long; three lines, then ellipsis, so every card in the
       row keeps the same shape. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.td-tour-facts {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 0.9rem;
    list-style: none;
    margin: 0;
    padding: 0;
    font-size: 0.85rem;
    color: var(--hub-ink-muted);
}

.td-tour-scarce {
    color: var(--hub-warning);
    font-weight: 700;
}

.td-tour-price {
    margin: auto 0 0;
    padding-top: 0.75rem;
    border-top: 1px solid var(--hub-hairline);
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    color: var(--hub-ink);
    font-variant-numeric: tabular-nums;
}

.td-tour-from {
    font-size: 0.8rem;
    color: var(--hub-ink-faint);
}

.td-tour-price strong {
    font-size: 1.25rem;
    font-weight: 800;
}

/* ── Destination tiles ───────────────────────────────────────────────────── */

.td-region-filter {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.td-region {
    padding: 0.4rem 1rem;
    border-radius: 100px;
    border: 1px solid var(--hub-hairline);
    background: transparent;
    color: var(--hub-ink-muted);
    font-family: inherit;
    font-size: 0.88rem;
    font-weight: 600;
    cursor: pointer;
    transition: all var(--hub-transition);
}

.td-region:hover {
    border-color: rgb(var(--hub-accent-rgb) / 0.5);
    color: var(--hub-ink);
}

.td-region.is-active {
    background: var(--hub-fill);
    border-color: transparent;
    color: var(--hub-on-fill);
}

.td-region:focus-visible {
    outline: 3px solid var(--hub-focus);
    outline-offset: 2px;
}

.td-dests {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 1rem;
}

/* No photography in the catalogue, so these are typographic tiles: the border
   and the season line carry them, not an image. */
.td-dest {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
    padding: 1.15rem 1.25rem 1.25rem;
    background: var(--hub-elev);
    border: 1px solid var(--hub-hairline);
    border-radius: var(--hub-radius);
    text-decoration: none;
    color: inherit;
    overflow: hidden;
    transition: border-color var(--hub-transition), transform var(--hub-transition);
}

.td-dest-body { display: flex; flex-direction: column; gap: 0.45rem; }

/* ── With a photograph ──────────────────────────────────────────
   The picture fills the tile and the words sit on it. A photograph
   can be any brightness, so the text is not trusted to the image:
   a scrim underneath it guarantees the contrast, and the palette is
   fixed to white-on-dark rather than following the theme, because
   the ground here is the photograph, not the page. */

.td-dest.has-image {
    padding: 0;
    min-height: 210px;
    justify-content: flex-end;
    border-color: transparent;
}

.td-dest-photo {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    z-index: 0;
    transition: transform 0.4s ease;
}

.td-dest.has-image:hover .td-dest-photo { transform: scale(1.04); }

.td-dest-scrim {
    position: absolute;
    inset: 0;
    z-index: 1;
    background: linear-gradient(
        to top,
        rgb(6 18 10 / 0.86) 0%,
        rgb(6 18 10 / 0.62) 38%,
        rgb(6 18 10 / 0.18) 72%,
        rgb(6 18 10 / 0.06) 100%
    );
}

.td-dest.has-image .td-dest-body {
    position: relative;
    z-index: 2;
    padding: 1.15rem 1.25rem 1.25rem;
}

.td-dest.has-image .td-dest-name,
.td-dest.has-image .td-dest-local,
.td-dest.has-image .td-dest-tagline { color: #FFFFFF; }

.td-dest.has-image .td-dest-region,
.td-dest.has-image .td-dest-season {
    border-color: rgb(255 255 255 / 0.45);
    background: rgb(255 255 255 / 0.14);
    color: #FFFFFF;
}

.td-dest.has-image .td-dest-season.is-now {
    border-color: rgb(255 255 255 / 0.75);
    background: rgb(255 255 255 / 0.24);
}

@media (prefers-reduced-motion: reduce) {
    .td-dest.has-image:hover .td-dest-photo { transform: none; }
}

.td-dest:hover {
    border-color: rgb(var(--hub-accent-rgb) / 0.55);
    transform: translateY(-2px);
}

.td-dest:focus-visible {
    outline: 3px solid var(--hub-focus);
    outline-offset: 2px;
}

.td-dest-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.5rem;
}

.td-dest-name {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--hub-ink);
    margin: 0;
}

.td-dest-local {
    font-size: 0.85rem;
    color: var(--hub-ink-faint);
}

.td-dest-region {
    align-self: flex-start;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--hub-ink-faint);
}

.td-dest-tagline {
    font-size: 0.88rem;
    line-height: 1.5;
    color: var(--hub-ink-muted);
    margin: 0;
    flex: 1;
}

.td-dest-season {
    align-self: flex-start;
    margin-top: 0.25rem;
    padding: 0.28rem 0.7rem;
    border-radius: 100px;
    border: 1px solid var(--hub-hairline);
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--hub-ink-muted);
    font-variant-numeric: tabular-nums;
}

/* The one flourish on the page, and it earns its place: it marks the tiles
   whose season covers the month in the search box. */
.td-dest-season.is-now {
    background: var(--hub-fill);
    border-color: transparent;
    color: var(--hub-on-fill);
    font-weight: 700;
}

/* ── Loading and empty states ────────────────────────────────────────────── */

.td-skeleton {
    height: 300px;
    border-radius: var(--hub-radius);
    background: rgb(var(--hub-overlay-rgb) / 0.05);
    border: 1px solid var(--hub-hairline);
    animation: td-pulse 1.6s ease-in-out infinite;
}

.td-skeleton-sm { height: 150px; }

@keyframes td-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.55; }
}

.td-empty {
    grid-column: 1 / -1;
    padding: 2.5rem 1rem;
    text-align: center;
    color: var(--hub-ink-muted);
    border: 1px dashed var(--hub-hairline);
    border-radius: var(--hub-radius);
    margin: 0;
}

.td-empty a {
    color: var(--hub-accent);
    font-weight: 600;
}


@media (max-width: 560px) {


    .td-section-head { flex-direction: column; align-items: flex-start; }
}

@media (prefers-reduced-motion: reduce) {
    .td-skeleton { animation: none; }
    .td-tour:hover,
    .td-dest:hover { transform: none; }
}

/* ── Language, on a phone ───────────────────────────────────────
   The navbar — which holds the language and theme controls on a wide
   screen — is replaced by the bottom tab bar below 768px, so the
   language control has nowhere to live. It sits at the top of the hero
   instead.

   In the flow on purpose, not position:fixed: a pinned badge in the
   corner is what the session countdown was, and it covered the page it
   was pinned to. This scrolls away like everything else. */

.td-hero-lang { display: none; }

@media (max-width: 768px) {
    /* Theme on the left, language on the right of the pair, both against the
       right edge. The gap under them was 0.9rem, which read as a hole between
       the controls and the headline; 0.35rem keeps them attached to the top of
       the hero without crowding the title. */
    .td-hero-lang {
        display: flex;
        justify-content: flex-end;
        gap: 0.4rem;
        margin-bottom: 0.35rem;
    }

    .td-hero-lang .lang-toggle,
    .td-hero-lang .theme-toggle {
        display: inline-flex;
        align-items: center;
        gap: 0.35rem;
        min-height: 40px;
        padding: 0.35rem 0.8rem;
        border: 1px solid var(--hub-hairline);
        border-radius: 999px;
        background: var(--hub-elev);
        color: var(--hub-ink-muted);
        font: inherit;
        font-size: 0.82rem;
        font-weight: 700;
        letter-spacing: 0.03em;
        cursor: pointer;
    }

    .td-hero-lang .lang-toggle:hover,
    .td-hero-lang .lang-toggle:focus-visible,
    .td-hero-lang .theme-toggle:hover,
    .td-hero-lang .theme-toggle:focus-visible {
        border-color: rgb(var(--hub-accent-rgb) / 0.55);
        color: var(--hub-ink);
    }

    .td-hero-lang .theme-toggle svg { width: 15px; height: 15px; flex: none; }
}

@media (hover: none) and (pointer: coarse) {
    .td-hero-lang .lang-toggle { min-height: 44px; }
}
