﻿/* ==========================================================================
   Tours From Baku — public design system
   --------------------------------------------------------------------------
   Cool, high-contrast, modern: a deep navy-slate chrome (masthead, hero,
   footer) wrapped around a cool off-white content ground, with one azure
   accent carrying every action.

   Two structural decisions separate this from the sibling sites:

   • RESULTS ARE ROWS, not a three-up card grid. A card forces every product
     into the same square regardless of what distinguishes it, and buries the
     price at the bottom of a box. A row gives the title a full measure, keeps
     duration and rating on one readable line, and parks the price in a fixed
     right-hand rail so prices line up down the column and can be compared at a
     glance — which is what someone shopping for a tour is actually doing.

   • THE HERO IS DARK AND ASYMMETRIC, set to the left against a facts panel,
     rather than a centred stage with a headline over a photograph.

   Three rules govern the file:

   1. NO web fonts. The system sans renders on first paint in every language
      the site ships; Arabic, Hebrew and Chinese fallbacks are named explicitly
      rather than left to chance. A font request is the most expensive thing a
      page like this can block on.

   2. LOGICAL PROPERTIES ONLY — margin-inline, padding-block, inset-inline-start,
      border-inline-start. Two right-to-left languages ship, and logical
      properties mirror off <html dir>, so RTL needs no second set of rules and
      cannot drift out of sync with the LTR one.

   3. NO layout that depends on JavaScript. Rows reflow with the viewport, the
      FAQ opens with <details>, and the nav is usable before any script runs.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Tokens
   -------------------------------------------------------------------------- */
:root {
    color-scheme: light;

    /* Cool neutrals — every grey is blue-shifted, so the light ground and the
       dark chrome read as one temperature rather than two designs. */
    --c-bg:      #ffffff;
    --c-canvas:  #f4f7fb;
    --c-canvas-2:#e9eff7;

    --c-ink:   #0b1220;
    --c-ink-2: #1e2a3d;
    --c-slate: #46536b;
    --c-muted: #6b7789;

    --c-line:   #dde4ee;
    --c-line-2: #eef2f8;

    /* Dark surfaces */
    --c-dark:    #0c1422;
    --c-dark-2:  #162134;
    --c-dark-3:  #22304a;
    --c-on-dark: #ffffff;
    --c-on-dark-2: #9fb0c7;

    /* One accent. Actions only — never decoration. */
    --c-accent:     #1668e3;
    --c-accent-600: #1156bd;
    --c-accent-050: #eaf2fe;
    --c-cyan:       #29b6d8;
    --c-star:       #f0a92a;

    --c-ok: #0e9f6e;

    /* Radii — soft, consistent, never pills except where a chip is a chip. */
    --r-sm:  8px;
    --r-md:  12px;
    --r-lg:  18px;
    --r-pill: 999px;

    /* Elevation, cool-tinted so shadows do not read brown on the blue ground. */
    --sh-1: 0 1px 2px rgba(11, 18, 32, .06);
    --sh-2: 0 10px 30px -12px rgba(11, 18, 32, .22);
    --sh-3: 0 24px 60px -24px rgba(11, 18, 32, .38);

    /* Space scale (4px base) */
    --s-1: .25rem;  --s-2: .5rem;   --s-3: .75rem;  --s-4: 1rem;
    --s-5: 1.5rem;  --s-6: 2rem;    --s-7: 3rem;    --s-8: 4.5rem;

    --ff: system-ui, -apple-system, "Segoe UI Variable Display", "Segoe UI",
          Roboto, "Helvetica Neue", Arial, "Noto Sans",
          "Noto Sans Arabic", "Noto Sans Hebrew",
          "PingFang SC", "Microsoft YaHei", "Noto Sans SC",
          sans-serif, "Apple Color Emoji", "Segoe UI Emoji";

    --fs-xs:   .75rem;
    --fs-sm:   .8125rem;
    --fs-base: .9375rem;
    --fs-md:   1.0625rem;
    --fs-lg:   clamp(1.15rem, 1.02rem + .45vw, 1.4rem);
    --fs-xl:   clamp(1.5rem, 1.25rem + 1.1vw, 2.1rem);
    --fs-2xl:  clamp(2.1rem, 1.5rem + 2.7vw, 3.6rem);

    --lh-tight: 1.06;
    --lh-snug:  1.32;
    --lh-base:  1.62;

    /* Wide enough for a four-up card row to keep a usable track width
       (~300px) without the gutters collapsing. */
    --w-max: 1400px;
    --w-prose: 64ch;

    --head-h: 66px;
}

/* --------------------------------------------------------------------------
   Reset
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
    scroll-padding-top: calc(var(--head-h) + 56px);
}
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after {
        animation-duration: .01ms !important;
        transition-duration: .01ms !important;
    }
}

body {
    margin: 0;
    background: var(--c-bg);
    color: var(--c-ink);
    font-family: var(--ff);
    font-size: var(--fs-base);
    line-height: var(--lh-base);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0; font-weight: 700; line-height: var(--lh-tight); letter-spacing: -.022em; }
h1 { font-size: var(--fs-2xl); letter-spacing: -.032em; }
h2 { font-size: var(--fs-xl); }
h3 { font-size: var(--fs-lg); letter-spacing: -.015em; }
p  { margin: 0; }

img, picture, svg, video { max-width: 100%; display: block; }
img { height: auto; }

/* Every media box on this site fixes its own aspect ratio and expects the photo
   to cover it. ImageOptimizer wraps images in <picture>, which the rule above
   makes a block of AUTO height — so the img's `height: 100%` had nothing to
   resolve against, the picture sat at its own natural ratio inside the box, and
   any photo that was not exactly the box's ratio left a band of card background
   under it. One rule rather than one per component. */
.tfb-card__media picture,
.tfb-rcard__media picture,
.tfb-entry__thumb picture,
.tfb-gal__t picture,
.trp-opt__img picture { display: block; height: 100%; }

/* <search> is a 2023 element. A browser that does not know it treats it as an
   unknown INLINE element, which would collapse the planner out of the hero
   grid. One declaration makes it behave everywhere. */
search { display: block; }

a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }

ul, ol, dl, dd { margin: 0; padding: 0; }
li { list-style: none; }

button, input, select, textarea { font: inherit; color: inherit; }

:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 3px; border-radius: var(--r-sm); }

/* --------------------------------------------------------------------------
   Primitives
   -------------------------------------------------------------------------- */
.tfb-shell {
    width: 100%;
    max-width: var(--w-max);
    margin-inline: auto;
    padding-inline: var(--s-5);
}

.tfb-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--c-muted);
}
.tfb-eyebrow--on-dark { color: var(--c-cyan); }

.tfb-skip {
    position: absolute;
    inset-inline-start: var(--s-4);
    top: -100px;
    z-index: 100;
    padding: var(--s-3) var(--s-4);
    background: var(--c-accent);
    color: var(--c-on-dark);
    border-radius: var(--r-sm);
    transition: top .15s ease;
}
.tfb-skip:focus { top: var(--s-2); text-decoration: none; }

.tfb-sr {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */
.tfb-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-2);
    padding: .78rem 1.35rem;
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    background: none;
    font-size: var(--fs-sm);
    font-weight: 600;
    line-height: 1.2;
    cursor: pointer;
    transition: background-color .16s ease, border-color .16s ease, color .16s ease, transform .16s ease;
}
.tfb-btn:hover { text-decoration: none; transform: translateY(-1px); }

.tfb-btn--primary { background: var(--c-accent); color: var(--c-on-dark); box-shadow: var(--sh-1); }
.tfb-btn--primary:hover { background: var(--c-accent-600); }

.tfb-btn--ghost { border-color: var(--c-line); color: var(--c-ink); background: var(--c-bg); }
.tfb-btn--ghost:hover { border-color: var(--c-ink); }

/* On the dark hero the ghost button needs its own contrast pair. */
.tfb-btn--onDark { border-color: rgba(255,255,255,.28); color: var(--c-on-dark); }
.tfb-btn--onDark:hover { border-color: var(--c-on-dark); background: rgba(255,255,255,.08); }

.tfb-link {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    color: var(--c-accent);
    font-size: var(--fs-sm);
    font-weight: 600;
    white-space: nowrap;
}
.tfb-link::after { content: "→"; transition: transform .16s ease; }
[dir="rtl"] .tfb-link::after { content: "←"; }
.tfb-link:hover::after { transform: translateX(3px); }
[dir="rtl"] .tfb-link:hover::after { transform: translateX(-3px); }

/* ------------------------------------------------------------------------
   Bidi for database content.

   Titles, excerpts, durations and answers come from the database and are not
   guaranteed to be in the page's language — a tour whose Arabic duration has
   not been filled in yet falls back to the English "5 hours", which the RTL
   paragraph direction then reorders into "hours 5".

   `unicode-bidi: plaintext` takes each element's direction from the first
   strong character of its own content, so English content lays out LTR and
   Arabic content RTL, with no per-string tagging and nothing to keep in sync
   as translations get filled in.
   ------------------------------------------------------------------------ */
.tfb-chip,
.tfb-card__title,
.tfb-card__excerpt,
.tfb-entry__title,
.tfb-entry__excerpt,
.tfb-faq__q,
.tfb-faq__a { unicode-bidi: plaintext; }

/* Fact chip — the small grey capsule used for duration, group size, capacity. */
.tfb-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    padding: .22rem .6rem;
    background: var(--c-canvas);
    border: 1px solid var(--c-line-2);
    border-radius: var(--r-pill);
    color: var(--c-slate);
    font-size: var(--fs-xs);
    font-weight: 500;
    white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Masthead — dark, sticky, with the switchers inline
   -------------------------------------------------------------------------- */
.tfb-head {
    position: sticky;
    top: 0;
    z-index: 50;
    background: var(--c-dark);
    color: var(--c-on-dark);
}
@supports (backdrop-filter: blur(8px)) {
    .tfb-head { background: rgba(12, 20, 34, .92); backdrop-filter: blur(10px); }
}
.tfb-head__bar {
    display: flex;
    align-items: center;
    gap: var(--s-5);
    min-height: var(--head-h);
}

.tfb-brand {
    /* gap:0 — the accent dot is punctuation, not a sibling element, so flex gap
       would push it away from the wordmark and read as a stray full stop.

       direction:ltr — the wordmark is a Latin name. On the Arabic and Hebrew
       pages the bidi algorithm otherwise reorders it against the RTL paragraph
       and the trailing dot jumps to the front (".Tours From Baku"). A brand
       name is a single LTR entity wherever it appears. */
    display: inline-flex;
    align-items: center;
    gap: 0;
    direction: ltr;
    font-size: 1.2rem;
    font-weight: 800;
    letter-spacing: -.03em;
    white-space: nowrap;
    color: var(--c-on-dark);
}
.tfb-brand:hover { text-decoration: none; }
.tfb-brand img { max-height: 36px; width: auto; }
/* The full stop matches the map pin in the badge standing next to it. It used
   to be --c-cyan, which was right when the site had no logo; beside a navy and
   orange mark it read as a second brand. Only this one rule moved — --c-cyan
   still does its job everywhere else. */
.tfb-brand__dot { color: #f07000; }

/* The compass mark in front of the wordmark. Sized in em so it tracks the
   brand's own font-size instead of needing its own breakpoints, and
   margin-inline-end rather than a flex gap because .tfb-brand sets gap:0 to
   keep the full stop welded to the name. */
/* The badge in front of the wordmark. Sized in em so it tracks the brand's own
   font-size instead of needing its own breakpoints, and margin-inline-end
   rather than a flex gap because .tfb-brand sets gap:0 to keep the full stop
   welded to the name. Bigger than a cap height on purpose: the mark is a ring
   around a monogram, and below ~28px its middle turns to mush. */
.tfb-brand__mark {
    height: 1.65em;
    width: auto;
    margin-inline-end: .42em;
    flex: 0 0 auto;
}

.tfb-nav { margin-inline-start: auto; }
.tfb-nav__list { display: flex; align-items: center; gap: var(--s-1); }
.tfb-nav__list a {
    display: block;
    padding: var(--s-2) var(--s-3);
    border-radius: var(--r-sm);
    color: var(--c-on-dark-2);
    font-size: var(--fs-sm);
    font-weight: 600;
}
.tfb-nav__list a:hover {
    text-decoration: none;
    color: var(--c-on-dark);
    background: rgba(255, 255, 255, .07);
}

.tfb-nav li.has-dropdown { position: relative; }
.tfb-nav .submenu-toggle { position: absolute; opacity: 0; pointer-events: none; }

/* The parent link and its caret sit on one line; the link navigates to the hub,
   the caret opens the submenu. They were one element before, which meant the
   submenu could not be opened at all on a pointer device. */
.tfb-nav .menu-parent { display: inline-flex; align-items: center; gap: 2px; }
.tfb-nav .menu-caret {
    cursor: pointer;
    padding: 0 var(--s-1);
    line-height: 1;
    font-size: .7em;
    color: inherit;
    opacity: .7;
    user-select: none;
}
.tfb-nav .menu-caret:hover { opacity: 1; }
/* The caret is a label, so it takes focus through its checkbox, not itself —
   style the ring off the input's focus state instead. */
.tfb-nav .submenu-toggle:focus-visible ~ .menu-parent .menu-caret {
    outline: 2px solid var(--c-cyan);
    outline-offset: 2px;
    border-radius: var(--r-sm);
}

/* The hub's own link, emitted first inside every section. It exists for the
   burger panel, where a tap on the parent row opens the section rather than
   following it; on desktop the parent link still navigates, so showing this
   too would just be the same destination twice in one menu. */
.tfb-nav .dropdown__self { display: none; }

.tfb-nav .dropdown {
    display: none;
    position: absolute;
    inset-inline-start: 0;
    top: 100%;
    margin-top: 8px;
    min-width: 220px;
    padding: var(--s-2);
    background: var(--c-dark-2);
    border: 1px solid var(--c-dark-3);
    border-radius: var(--r-md);
    box-shadow: var(--sh-3);
    z-index: 60;
}
/* The 8px offset is margin, not `top`, so the gap belongs to the dropdown and
   the pointer never crosses dead space on its way down — a hover menu with a
   real hole under it closes while you are reaching for it. */
.tfb-nav .dropdown::before {
    content: "";
    position: absolute;
    inset-inline: 0;
    top: -8px;
    height: 8px;
}

/* Three ways in, because one is never enough: hover for a mouse, focus-within
   for the keyboard, and the checkbox for touch, where hover does not exist. */
.tfb-nav .submenu-toggle:checked ~ .dropdown,
.tfb-nav li.has-dropdown:hover > .dropdown,
.tfb-nav li.has-dropdown:focus-within > .dropdown { display: block; }

/* A device that cannot hover must not open menus on a stray tap. */
@media (hover: none) {
    .tfb-nav li.has-dropdown:hover > .dropdown { display: none; }
    .tfb-nav .submenu-toggle:checked ~ .dropdown { display: block; }
}

.tfb-head__actions { display: flex; align-items: center; gap: var(--s-2); }

.tfb-head__phone {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    padding: var(--s-2) var(--s-3);
    color: var(--c-on-dark);
    font-size: var(--fs-sm);
    font-weight: 600;
    white-space: nowrap;
}
.tfb-head__phone svg { color: var(--c-cyan); }
/* A phone number is an LTR entity. Left to the RTL paragraph direction, the
   groups reorder and "+994 10 720 70 73" renders as "73 70 720 10 994+". */
.tfb-head__phone span { direction: ltr; unicode-bidi: isolate; }
@media (max-width: 1080px) { .tfb-head__phone span { display: none; } }

/* Switchers. The `curr-` / `lang-` class names are the contract with
   public/assets/js/currency.js and must not be renamed. */
.curr-switcher, .lang-switcher { position: relative; }
.curr-current, .lang-current {
    display: inline-flex;
    align-items: center;
    gap: var(--s-1);
    padding: var(--s-2) var(--s-3);
    border: 1px solid rgba(255, 255, 255, .16);
    border-radius: var(--r-sm);
    color: var(--c-on-dark);
    font-size: var(--fs-xs);
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}
.curr-current:hover, .lang-current:hover { border-color: rgba(255, 255, 255, .42); }
.caret { opacity: .55; font-size: .7em; }

.curr-dropdown-list, .lang-dropdown-list {
    display: none;
    position: absolute;
    inset-inline-end: 0;
    top: calc(100% + 8px);
    min-width: 158px;
    padding: var(--s-2);
    background: var(--c-dark-2);
    border: 1px solid var(--c-dark-3);
    border-radius: var(--r-md);
    box-shadow: var(--sh-3);
    z-index: 60;
}
.submenu-toggle:checked ~ .curr-dropdown-list,
.submenu-toggle:checked ~ .lang-dropdown-list { display: block; }

.curr-dropdown-list a, .lang-dropdown-list a,
.tfb-nav .dropdown a {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    padding: var(--s-2) var(--s-3);
    border-radius: var(--r-sm);
    color: var(--c-on-dark-2);
    font-size: var(--fs-sm);
}
.curr-dropdown-list a:hover, .lang-dropdown-list a:hover,
.tfb-nav .dropdown a:hover {
    background: rgba(255, 255, 255, .08); color: var(--c-on-dark); text-decoration: none;
}
.curr-option.active, .lang-dropdown-list a.active { color: var(--c-cyan); font-weight: 700; }
.curr-opt-symbol { width: 1.1em; }

.tfb-burger {
    display: none;
    padding: var(--s-2) var(--s-3);
    background: none;
    border: 1px solid rgba(255, 255, 255, .18);
    border-radius: var(--r-sm);
    cursor: pointer;
}
.tfb-burger span[aria-hidden] {
    display: block;
    width: 18px; height: 2px;
    margin: 3px 0;
    background: var(--c-on-dark);
    border-radius: 2px;
}

/* --------------------------------------------------------------------------
   Hero — dark, asymmetric, left-set
   -------------------------------------------------------------------------- */
.tfb-hero {
    position: relative;
    background: var(--c-dark);
    color: var(--c-on-dark);
    /* Shorter than it was: the search bar used to live inside this block, which
       meant the first screen carried a headline, a lede, a 63px pill and the
       facts row before a single tour appeared. The bar now sits in its own band
       below, and the extra bottom padding is the room that band overlaps into. */
    padding-block: clamp(var(--s-5), 3.5vw, var(--s-7)) var(--s-8);
    overflow: hidden;
}
/* Cool light-source behind the headline. Pure CSS — no image request, and it
   keeps the panel from reading as a flat block of navy. */
.tfb-hero::before {
    content: "";
    position: absolute;
    inset: 0;
    background:
        radial-gradient(80% 120% at 12% 0%, rgba(22, 104, 227, .42) 0%, transparent 58%),
        radial-gradient(60% 100% at 92% 100%, rgba(41, 182, 216, .26) 0%, transparent 60%);
    pointer-events: none;
}
.tfb-hero > * { position: relative; }

/* The headline column is capped so the h1 keeps a readable measure, but the
   search bar below it spans the full shell — it is the primary action, and the
   pill needs the room to hold three segments and a submit on one line. */
.tfb-hero__body { max-width: 100%; }
.tfb-hero h1 { margin-block: var(--s-4) var(--s-5); max-width: 17ch; }
.tfb-hero__lede { max-width: 52ch; color: var(--c-on-dark-2); font-size: var(--fs-md); }
/* The band that carries the search bar out of the hero. It is pulled up so the
   pill straddles the boundary between the dark block and the page — which reads
   as deliberate and, more usefully, buys back the vertical space that stacking
   the two would have cost. */
.tfb-planner-band {
    position: relative;
    z-index: 5;
    margin-block-start: -34px;
    padding-block-end: var(--s-6);
}

/* At-a-glance facts, carried inline under the lede. A <dl>, because every entry
   here is genuinely a label and its value. */
.tfb-hero__facts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-4) var(--s-6);
    margin-block-start: var(--s-6);
    padding-block-start: var(--s-5);
    border-block-start: 1px solid rgba(255, 255, 255, .14);
}
.tfb-hero__fact dt {
    color: var(--c-on-dark-2);
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: .1em;
}
.tfb-hero__fact dd { margin-block-start: var(--s-1); font-weight: 600; }
.tfb-hero__fact--big dd { font-size: 1.35rem; letter-spacing: -.02em; }

/* --------------------------------------------------------------------------
   Trip planner — the search bar
   --------------------------------------------------------------------------
   One pill split into three segments (what / when / how many) plus a submit.

   It is a plain GET form. Every control maps onto a filter the catalogue
   actually implements — ?q, ?date, ?pax — so a search is a shareable,
   crawlable, back-button-able URL and the bar works before, and entirely
   without, any script. The suggestion dropdown is a native <datalist>: the
   browser supplies the popup, its keyboard handling and its platform styling,
   so there is no scripted overlay and no XHR endpoint behind it.
   -------------------------------------------------------------------------- */
.tfb-planner__bar {
    display: flex;
    align-items: stretch;
    gap: 0;
    /* Capped rather than full-bleed: stretched across a 1400px shell the free-
       text field swallows the row and the date and traveller segments shrink to
       slivers. */
    max-width: 940px;
    padding: var(--s-2);
    background: var(--c-bg);
    color: var(--c-ink);
    border: 1px solid var(--c-line);
    border-radius: var(--r-pill);
    box-shadow: var(--sh-2);
}
.tfb-planner--dark .tfb-planner__bar { border-color: transparent; box-shadow: var(--sh-3); }
/* On a light page the bar sits above the filter row, which needs breathing
   room; in the hero the surrounding block already provides it. */
.tfb-sec .tfb-planner { display: block; margin-block-end: var(--s-5); }

.tfb-planner__seg {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    flex: 0 1 auto;
    min-width: 0;
    padding-inline: var(--s-5);
    border-inline-start: 1px solid var(--c-line);
}
.tfb-planner__seg:first-of-type { border-inline-start: 0; }
/* The free-text field is the primary one: it takes whatever width is left. */
.tfb-planner__seg--q { flex: 1 1 auto; }

.tfb-planner__seg > label,
.tfb-planner__seglabel {
    display: block;
    color: var(--c-muted);
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: .09em;
    text-transform: uppercase;
}
.tfb-planner__seg input,
.tfb-planner__seg select {
    width: 100%;
    padding: 0;
    background: none;
    border: 0;
    font-size: var(--fs-base);
    font-weight: 600;
    color: var(--c-ink);
}
.tfb-planner__seg input::placeholder { color: var(--c-muted); font-weight: 400; }
/* Focus is shown on the whole segment, not as a ring around a borderless
   control that has no visible box of its own. */
.tfb-planner__seg input:focus,
.tfb-planner__seg select:focus { outline: none; }
.tfb-planner__seg:focus-within > label { color: var(--c-accent); }
.tfb-planner__seg select { cursor: pointer; }
/* Safari renders a date input with an inner spin/clear affordance that breaks
   the borderless alignment; the appearance reset keeps every segment level. */
.tfb-planner__seg input[type="date"] { appearance: none; -webkit-appearance: none; min-height: 1.5em; }

.tfb-planner__go {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-2);
    flex: none;
    margin-inline-start: var(--s-3);
    padding-inline: var(--s-5);
    background: var(--c-accent);
    color: var(--c-on-dark);
    border: 0;
    border-radius: var(--r-pill);
    font-size: var(--fs-sm);
    font-weight: 700;
    cursor: pointer;
    transition: background-color .16s ease;
}
.tfb-planner__go:hover { background: var(--c-accent-600); }

.tfb-field { display: grid; gap: var(--s-2); }
.tfb-field > label {
    color: var(--c-muted);
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
}
/* The native select control is kept — it brings its own keyboard behaviour, its
   own mobile picker, and an arrow that mirrors itself in right-to-left
   languages. A custom caret would have to reimplement all three. */
.tfb-field select {
    width: 100%;
    padding: .7rem .85rem;
    background: var(--c-bg);
    border: 1px solid var(--c-line);
    border-radius: var(--r-sm);
    font-size: var(--fs-base);
    cursor: pointer;
}
.tfb-field select:hover { border-color: #c6d3e6; }
.tfb-field select:focus-visible { border-color: var(--c-accent); }

/* The button that replaces a native control once tfb-planner.js takes over.
   It carries the same visual weight as the input it stands in for, so the bar
   does not shift when the script arrives. */
.tfb-planner__trigger {
    display: block;
    width: 100%;
    padding: 0;
    background: none;
    border: 0;
    text-align: start;
    font-size: var(--fs-base);
    font-weight: 600;
    color: var(--c-muted);
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.tfb-planner__trigger.is-set { color: var(--c-ink); }

/* Enhanced segments hide the raw controls but keep them in the DOM — they are
   still the values that get submitted. */
.tfb-planner__seg.is-enhanced .tfb-planner__paxraw,
.tfb-planner__seg.is-enhanced .tfb-planner__dateraw { display: none; }

/* Un-enhanced fallbacks: labelled native boxes side by side. Both are fully
   working controls — the from/to pair submits a real date range on its own. */
.tfb-planner__paxraw,
.tfb-planner__dateraw { display: flex; gap: var(--s-3); }
.tfb-planner__paxraw span,
.tfb-planner__dateraw span { display: flex; align-items: baseline; gap: var(--s-2); min-width: 0; }
.tfb-planner__paxraw label,
.tfb-planner__dateraw label { color: var(--c-muted); font-size: var(--fs-xs); }
.tfb-planner__paxraw input { width: 3.2rem; }
.tfb-planner__dateraw input { width: auto; }

/* --------------------------------------------------------------------------
   Planner popovers
   -------------------------------------------------------------------------- */
.tfb-planner__seg { position: relative; }

.tfb-pop {
    position: absolute;
    z-index: 70;
    inset-block-start: calc(100% + var(--s-3));
    inset-inline-start: 0;
    background: var(--c-bg);
    color: var(--c-ink);
    border: 1px solid var(--c-line);
    border-radius: var(--r-lg);
    box-shadow: var(--sh-3);
}

/* Suggestions ------------------------------------------------------------ */
.tfb-pop--list {
    inset-inline-start: calc(var(--s-5) * -1);
    min-width: min(520px, 92vw);
    max-height: min(420px, 60vh);
    overflow-y: auto;
    padding: var(--s-2);
}
.tfb-pop--list a {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    padding: var(--s-2) var(--s-3);
    border-radius: var(--r-md);
    color: var(--c-ink);
}
.tfb-pop--list a:hover,
.tfb-pop--list a.is-active { background: var(--c-canvas); text-decoration: none; }
.tfb-pop--list img,
.tfb-pop__ph {
    flex: none;
    width: 44px; height: 44px;
    border-radius: var(--r-sm);
    object-fit: cover;
    background: var(--c-canvas-2);
}
.tfb-pop__txt { display: flex; flex-direction: column; min-width: 0; }
.tfb-pop__txt strong {
    font-size: var(--fs-base);
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.tfb-pop__txt small { color: var(--c-muted); font-size: var(--fs-xs); }

/* Calendar --------------------------------------------------------------- */
/* Anchored to the END of its segment so the panel grows back across the bar
   instead of off the edge of the viewport — the "when" segment sits near the
   right of a 940px pill, and a 620px panel opening rightward from it would
   overflow the page. */
.tfb-pop--cal {
    inset-inline-start: auto;
    inset-inline-end: 0;
    padding: var(--s-4);
    min-width: min(620px, 94vw);
}
.tfb-cal__quick { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-block-end: var(--s-4); }
.tfb-cal__quick button {
    padding: var(--s-2) var(--s-4);
    background: var(--c-canvas);
    border: 1px solid transparent;
    border-radius: var(--r-pill);
    font-size: var(--fs-sm);
    font-weight: 600;
    cursor: pointer;
}
.tfb-cal__quick button:hover { border-color: var(--c-accent); color: var(--c-accent); }

/* The arrows sit in their own row, absolutely placed over the month headings,
   so they stay put as the two grids change height month to month. */
.tfb-cal__nav { position: relative; height: 0; }
.tfb-cal__arrow {
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: 0;
    width: 30px; height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: 1px solid var(--c-line);
    border-radius: 50%;
    cursor: pointer;
}
.tfb-cal__arrow--next { inset-inline-start: auto; inset-inline-end: 0; }
.tfb-cal__arrow:hover:not(:disabled) { border-color: var(--c-ink); }
.tfb-cal__arrow:disabled { opacity: .35; cursor: default; }
/* The glyphs are literal ← / → characters, so they must be flipped for a
   right-to-left reading order rather than left pointing the wrong way. */
[dir="rtl"] .tfb-cal__arrow { transform: scaleX(-1); }

.tfb-cal__months { display: flex; gap: var(--s-6); }
.tfb-cal__month { flex: 1 1 0; min-width: 0; }
.tfb-cal__month h3 {
    margin-block-end: var(--s-3);
    text-align: center;
    font-size: var(--fs-base);
    font-weight: 700;
}
.tfb-cal__dow, .tfb-cal__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.tfb-cal__dow span {
    padding-block: var(--s-1);
    text-align: center;
    color: var(--c-muted);
    font-size: var(--fs-xs);
    font-weight: 600;
}
.tfb-cal__grid > * {
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 1;
    border: 0;
    border-radius: var(--r-sm);
    background: none;
    font-size: var(--fs-sm);
    font-weight: 500;
}
.tfb-cal__grid button { cursor: pointer; }
.tfb-cal__grid button:hover { background: var(--c-accent-050); color: var(--c-accent); }
.tfb-cal__grid .is-past { color: var(--c-line); }

/* Range: the two ends are solid, the days between them a tint. The ends keep
   square inner corners so the run reads as one continuous band rather than
   three separate pills. */
.tfb-cal__grid .is-in  { background: var(--c-accent-050); color: var(--c-accent); border-radius: 0; }
.tfb-cal__grid .is-sel { background: var(--c-accent); color: var(--c-on-dark); font-weight: 700; }
.tfb-cal__grid .is-start.is-end { border-radius: var(--r-sm); }
.tfb-cal__grid .is-start:not(.is-end) { border-start-end-radius: 0; border-end-end-radius: 0; }
.tfb-cal__grid .is-end:not(.is-start) { border-start-start-radius: 0; border-end-start-radius: 0; }

.tfb-cal__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-4);
    margin-block-start: var(--s-4);
    padding-block-start: var(--s-3);
    border-block-start: 1px solid var(--c-line-2);
}
.tfb-cal__foot button {
    background: none;
    border: 0;
    color: var(--c-muted);
    font-size: var(--fs-sm);
    font-weight: 600;
    cursor: pointer;
}
.tfb-cal__foot button:hover { color: var(--c-accent); }
/* The panel no longer closes on the first click, so Done is the way out and
   has to look like the primary action rather than a second Clear. */
.tfb-cal__done {
    padding: var(--s-2) var(--s-5);
    background: var(--c-accent) !important;
    color: var(--c-on-dark) !important;
    border-radius: var(--r-sm);
}
.tfb-cal__done:hover { background: var(--c-accent-600) !important; }

/* Travellers ------------------------------------------------------------- */
.tfb-pop--pax { inset-inline-start: auto; inset-inline-end: 0; min-width: 300px; padding: var(--s-4) var(--s-5); }
.tfb-pax__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-5);
    padding-block: var(--s-3);
}
.tfb-pax__row + .tfb-pax__row { border-block-start: 1px solid var(--c-line-2); }
.tfb-pax__name { font-weight: 600; }
.tfb-pax__ctrl { display: inline-flex; align-items: center; gap: var(--s-3); }
.tfb-pax__ctrl button {
    width: 32px; height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: 1px solid var(--c-line);
    border-radius: 50%;
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
}
.tfb-pax__ctrl button:hover:not(:disabled) { border-color: var(--c-accent); color: var(--c-accent); }
.tfb-pax__ctrl button:disabled { opacity: .35; cursor: default; }
.tfb-pax__ctrl output { min-width: 1.6rem; text-align: center; font-weight: 700; }

@media (max-width: 700px) {
    .tfb-cal__months { flex-direction: column; gap: var(--s-5); }
    .tfb-pop--cal { min-width: min(340px, 92vw); }
    .tfb-pop--list { inset-inline-start: 0; }
}

/* Below ~820px the pill stops being a pill: the segments stack, the dividers
   become rules, and the submit spans the width. Squeezing four controls onto
   one line on a phone gives every one of them an unusable tap target. */
@media (max-width: 820px) {
    /* Once the pill stacks it is far taller than the 34px overlap allows for,
       and pulling it up would drag it over the facts row above. */
    .tfb-planner-band { margin-block-start: var(--s-5); }

    .tfb-planner__bar {
        flex-direction: column;
        gap: var(--s-2);
        padding: var(--s-3);
        border-radius: var(--r-lg);
    }
    .tfb-planner__seg {
        padding: var(--s-2) var(--s-3);
        border-inline-start: 0;
        border-block-start: 1px solid var(--c-line);
    }
    .tfb-planner__seg:first-of-type { border-block-start: 0; }
    .tfb-planner__go {
        margin-inline-start: 0;
        padding-block: var(--s-3);
        border-radius: var(--r-md);
    }
}

/* --------------------------------------------------------------------------
   Page header — the shorter, inner-page relative of the hero
   -------------------------------------------------------------------------- */
.tfb-pagehead {
    position: relative;
    background: var(--c-dark);
    color: var(--c-on-dark);
    padding-block: var(--s-6) var(--s-7);
    overflow: hidden;
}
.tfb-pagehead::before {
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(70% 130% at 10% 0%, rgba(22, 104, 227, .38) 0%, transparent 60%);
    pointer-events: none;
}
.tfb-pagehead > * { position: relative; }
.tfb-pagehead h1 { max-width: 20ch; }
.tfb-pagehead__lede {
    max-width: 62ch;
    margin-block-start: var(--s-4);
    color: var(--c-on-dark-2);
    font-size: var(--fs-md);
}
.tfb-pagehead .tfb-rate { margin-block-start: var(--s-4); }

/* Breadcrumbs. Separators are drawn by CSS, so they never end up in the text a
   screen reader announces or a crawler extracts. */
.tfb-crumbs { margin-block-end: var(--s-4); font-size: var(--fs-sm); }
.tfb-crumbs ol { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }
.tfb-crumbs li { display: inline-flex; align-items: center; gap: var(--s-2); color: var(--c-on-dark-2); }
.tfb-crumbs li + li::before { content: "/"; opacity: .45; }
.tfb-crumbs a { color: var(--c-on-dark-2); }
.tfb-crumbs a:hover { color: var(--c-on-dark); }
.tfb-crumbs [aria-current] { color: var(--c-on-dark); }

/* The catalogue's "Showing N of M · Theme · Sort" bar was removed — theme and
   trip length are chosen in the search bar, and the count restated what the
   grid already showed. Its styles went with the markup; they belong together
   and would only rot here. `data-autosubmit` in tfb.js is left in place, since
   it enhances any future filter form the same way.

   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   Pagination
   -------------------------------------------------------------------------- */
.tfb-pager { margin-block-start: var(--s-6); }
.tfb-pager ol { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s-2); }
.tfb-pager a, .tfb-pager__current {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 40px;
    padding: var(--s-2) var(--s-3);
    border: 1px solid var(--c-line);
    border-radius: var(--r-sm);
    font-size: var(--fs-sm);
    font-weight: 600;
}
.tfb-pager a:hover { text-decoration: none; border-color: var(--c-accent); color: var(--c-accent); }
.tfb-pager__current { background: var(--c-ink); border-color: var(--c-ink); color: var(--c-on-dark); }
.tfb-pager__gap { display: inline-flex; align-items: center; padding-inline: var(--s-1); color: var(--c-muted); }

/* --------------------------------------------------------------------------
   Hub copy — the CMS-authored prose and FAQ below a catalogue
   -------------------------------------------------------------------------- */
.tfb-hub { max-width: 860px; }
.tfb-prose { color: var(--c-ink-2); line-height: 1.72; }
.tfb-prose > * + * { margin-block-start: var(--s-4); }
.tfb-prose h2 { font-size: var(--fs-lg); margin-block-start: var(--s-6); }
.tfb-prose h3 { font-size: var(--fs-md); margin-block-start: var(--s-5); }
.tfb-prose a  { color: var(--c-accent); text-decoration: underline; text-underline-offset: 2px; }
.tfb-prose ul, .tfb-prose ol { padding-inline-start: var(--s-5); }
.tfb-prose li { list-style: disc; margin-block-start: var(--s-2); }
.tfb-prose ol li { list-style: decimal; }
.tfb-hub__faq { margin-block-start: var(--s-7); }
.tfb-hub__faq > h3 { margin-block-end: var(--s-4); font-size: var(--fs-lg); }

/* --------------------------------------------------------------------------
   Sections
   -------------------------------------------------------------------------- */
.tfb-sec { padding-block: clamp(var(--s-6), 4vw, var(--s-8)); }
.tfb-sec--canvas { background: var(--c-canvas); }

.tfb-sec__head {
    display: flex;
    flex-wrap: wrap;
    align-items: end;
    justify-content: space-between;
    gap: var(--s-3);
    margin-block-end: var(--s-5);
}
.tfb-sec__intro {
    flex-basis: 100%;
    max-width: var(--w-prose);
    margin-block-start: var(--s-3);
    color: var(--c-slate);
    font-size: var(--fs-sm);
}

/* --------------------------------------------------------------------------
   Product cards — four to a row on a wide screen, reflowing by track width
   rather than by breakpoint, so the grid never has to be told how many columns
   the viewport can hold.
   -------------------------------------------------------------------------- */
.tfb-grid {
    display: grid;
    gap: var(--s-4);
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 290px), 1fr));
}
/* The <li> is the grid item and stretches to the row height; the <article>
   inside it does not inherit that. Without this the card stops at its own
   content height and its footer — and therefore its price — floats mid-row
   whenever the title above runs to fewer lines than its neighbours. */
.tfb-grid > li { display: flex; }
.tfb-grid > li > .tfb-card { flex: 1 1 auto; }

.tfb-card {
    position: relative;
    display: flex;
    flex-direction: column;
    background: var(--c-bg);
    border: 1px solid var(--c-line);
    border-radius: var(--r-lg);
    overflow: hidden;
    transition: border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.tfb-card:hover {
    border-color: #c6d3e6;
    box-shadow: var(--sh-2);
    transform: translateY(-3px);
}
.tfb-card:focus-within { box-shadow: var(--sh-2); }

.tfb-card__media {
    position: relative;
    aspect-ratio: 4 / 3;
    overflow: hidden;
    background: var(--c-canvas-2);
}
.tfb-card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform .35s ease; }
.tfb-card:hover .tfb-card__media img { transform: scale(1.04); }

.tfb-badge {
    position: absolute;
    z-index: 2;
    top: var(--s-3);
    inset-inline-start: var(--s-3);
    padding: .2rem .55rem;
    background: var(--c-accent);
    color: var(--c-on-dark);
    border-radius: var(--r-sm);
    font-size: var(--fs-xs);
    font-weight: 700;
}

/* The theme labels that used to sit over the image are gone (2026-09-02). They
   were never links, so they carried no SEO weight, and the first theme is
   printed a line below anyway — the eyebrow reads "Baku · City Tour". Four
   dark pills per card competed with the badge, which is the one label on a card
   that has to be noticed. The themes themselves still reach the card: they
   build that eyebrow. */

.tfb-card__body {
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
    flex: 1 1 auto;
    padding: var(--s-4);
}

/* Place and category, above the title. */
.tfb-card__eyebrow {
    color: var(--c-muted);
    font-size: var(--fs-xs);
    font-weight: 600;
}

.tfb-card__title {
    font-size: var(--fs-md);
    line-height: var(--lh-snug);
    /* Two lines, then ellipsis: titles in this catalogue run long, and a card
       that grows to four lines drags the price out of alignment with the rest
       of the row. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Duration and highlights on one line, separated by bullets drawn in CSS so
   they never reach the accessibility tree or a text extractor. */
.tfb-card__facts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-1) var(--s-2);
    color: var(--c-slate);
    font-size: var(--fs-sm);
}
.tfb-card__facts li { display: inline-flex; align-items: center; gap: var(--s-2); }
.tfb-card__facts li + li::before { content: "•"; color: var(--c-line); }

/* The whole card is clickable, but only the title carries the link — a
   stretched pseudo-element covers the rest. That keeps exactly ONE link per
   product in the accessibility tree and in the crawler's link graph, where a
   wrapping <a> around image, title and price would emit the same destination
   three or four times. */
.tfb-card__link::after { content: ""; position: absolute; inset: 0; z-index: 1; }
.tfb-card:hover .tfb-card__title { color: var(--c-accent); }

.tfb-facts { display: flex; flex-wrap: wrap; gap: var(--s-2); }

/* Footer pinned to the bottom by margin-top:auto, so prices sit on one line
   across the row however tall the titles above them run. */
.tfb-card__foot {
    display: flex;
    align-items: flex-end;
    justify-content: flex-end;
    gap: var(--s-3);
    margin-block-start: auto;
    padding-block-start: var(--s-3);
    text-align: end;
}
.tfb-price__label { display: block; color: var(--c-muted); font-size: var(--fs-xs); }
.tfb-price__row { display: inline-flex; align-items: baseline; gap: var(--s-2); }
.tfb-price__value { font-size: 1.3rem; font-weight: 800; letter-spacing: -.03em; white-space: nowrap; }
/* A price that undercuts a struck-through one is the one claim on the card
   worth colouring; everywhere else the accent belongs to actions. */
.tfb-price__value.is-cut { color: var(--c-accent); }
/* Colour, size and the strike itself are all set in the discount block at the
   foot of this file, where the three struck figures are styled together. Only
   the thing that is specific to the CARD stays here. */
.tfb-price__was { white-space: nowrap; }
.tfb-card__cta { color: var(--c-accent); font-size: var(--fs-sm); font-weight: 600; white-space: nowrap; }

/* Rating. Stars are decoration; the number beside them is the content. */
.tfb-rate { display: inline-flex; align-items: center; gap: var(--s-2); font-size: var(--fs-sm); color: var(--c-muted); }
.tfb-stars {
    position: relative;
    display: inline-block;
    color: var(--c-line);
    font-size: 13px;
    letter-spacing: 1px;
}
.tfb-stars__fill {
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: 0;
    overflow: hidden;
    white-space: nowrap;
    color: var(--c-star);
}
.tfb-rate__value { color: var(--c-ink); font-weight: 700; }
.tfb-rate--onDark { color: var(--c-on-dark-2); }
.tfb-rate--onDark .tfb-rate__value { color: var(--c-on-dark); }
.tfb-rate--onDark .tfb-stars { color: rgba(255, 255, 255, .25); }

/* --------------------------------------------------------------------------
   Empty state — deliberately plain. A placeholder row here would put a product
   that does not exist into the page's ItemList data.
   -------------------------------------------------------------------------- */
.tfb-empty {
    padding: var(--s-7);
    background: var(--c-bg);
    border: 1px dashed var(--c-line);
    border-radius: var(--r-lg);
    color: var(--c-muted);
    font-size: var(--fs-sm);
    text-align: center;
}

/* --------------------------------------------------------------------------
   Numbered promises
   -------------------------------------------------------------------------- */
.tfb-promises {
    display: grid;
    gap: var(--s-4);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr));
    counter-reset: promise;
}
.tfb-promise {
    counter-increment: promise;
    padding: var(--s-5);
    background: var(--c-bg);
    border: 1px solid var(--c-line);
    border-radius: var(--r-lg);
}
.tfb-promise::before {
    content: "0" counter(promise);
    display: block;
    margin-block-end: var(--s-4);
    color: var(--c-accent);
    font-size: 1.35rem;
    font-weight: 800;
    letter-spacing: -.03em;
}
.tfb-promise h3 { font-size: var(--fs-md); margin-block-end: var(--s-2); }
.tfb-promise p  { color: var(--c-slate); font-size: var(--fs-sm); }

/* --------------------------------------------------------------------------
   Journal — text-first entries with a small thumbnail
   -------------------------------------------------------------------------- */
.tfb-journal { display: grid; gap: var(--s-4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); }
.tfb-entry {
    position: relative;
    display: flex;
    gap: var(--s-4);
    height: 100%;
    padding: var(--s-4);
    background: var(--c-bg);
    border: 1px solid var(--c-line);
    border-radius: var(--r-lg);
    transition: border-color .16s ease, box-shadow .16s ease;
}
.tfb-entry:hover { border-color: #c6d3e6; box-shadow: var(--sh-2); }
.tfb-entry__thumb {
    flex: none;
    width: 84px;
    aspect-ratio: 1;
    overflow: hidden;
    border-radius: var(--r-md);
    background: var(--c-canvas-2);
}
.tfb-entry__thumb img { width: 100%; height: 100%; object-fit: cover; }
.tfb-entry__body { display: flex; flex-direction: column; gap: var(--s-2); min-width: 0; }
.tfb-entry__title { font-size: var(--fs-md); }
.tfb-entry__link::after { content: ""; position: absolute; inset: 0; }
.tfb-entry:hover .tfb-entry__title { color: var(--c-accent); }
.tfb-entry time { color: var(--c-muted); font-size: var(--fs-xs); letter-spacing: .07em; text-transform: uppercase; }
.tfb-entry__excerpt {
    color: var(--c-slate);
    font-size: var(--fs-sm);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* --------------------------------------------------------------------------
   FAQ — heading in a left column, questions in the right. <details> keeps the
   answers in the DOM whether open or closed, which is what makes them
   extractable by crawlers and assistants.
   -------------------------------------------------------------------------- */
.tfb-faq {
    display: grid;
    gap: var(--s-6);
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.9fr);
    align-items: start;
}
.tfb-faq__aside { position: sticky; top: calc(var(--head-h) + var(--s-6)); }
.tfb-faq__list { display: grid; gap: var(--s-3); }
.tfb-faq__item {
    background: var(--c-bg);
    border: 1px solid var(--c-line);
    border-radius: var(--r-md);
    padding-inline: var(--s-5);
    transition: border-color .16s ease;
}
.tfb-faq__item[open] { border-color: #c6d3e6; box-shadow: var(--sh-1); }
.tfb-faq__q {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-4);
    padding-block: var(--s-4);
    font-size: var(--fs-md);
    font-weight: 600;
    cursor: pointer;
    list-style: none;
}
.tfb-faq__q::-webkit-details-marker { display: none; }
.tfb-faq__q:hover { color: var(--c-accent); }
.tfb-faq__q::after {
    content: "";
    flex: none;
    width: 9px; height: 9px;
    border-inline-end: 2px solid var(--c-muted);
    border-block-end: 2px solid var(--c-muted);
    transform: rotate(45deg) translateY(-2px);
    transition: transform .18s ease;
}
.tfb-faq__item[open] .tfb-faq__q::after { transform: rotate(-135deg) translateY(-2px); }
.tfb-faq__a { padding-block-end: var(--s-5); max-width: var(--w-prose); color: var(--c-slate); font-size: var(--fs-sm); }

/* --------------------------------------------------------------------------
   Footer — dark, with a deeper bottom bar
   -------------------------------------------------------------------------- */
.tfb-foot {
    background: var(--c-dark);
    color: var(--c-on-dark-2);
    padding-block-start: var(--s-8);
    font-size: var(--fs-sm);
}
.tfb-foot__cols {
    display: grid;
    gap: var(--s-6);
    grid-template-columns: minmax(0, 1.5fr) repeat(auto-fit, minmax(min(100%, 165px), 1fr));
    padding-block-end: var(--s-7);
}
.tfb-foot h2 {
    margin-block-end: var(--s-4);
    color: var(--c-on-dark);
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: .14em;
    text-transform: uppercase;
}
.tfb-foot a:hover { color: var(--c-on-dark); }
.tfb-foot li + li { margin-block-start: var(--s-3); }
.tfb-foot__word {
    display: block;
    margin-block-end: var(--s-3);
    color: var(--c-on-dark);
    font-size: 1.3rem;
    font-weight: 800;
    letter-spacing: -.03em;
}
.tfb-foot__about { max-width: 38ch; }
.tfb-foot address { font-style: normal; }
.tfb-foot__social { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); margin-block-start: var(--s-5); }
/* the column lists' "li + li" spacing must not push the 2nd icon down a row-height */
.tfb-foot__social li { display: flex; }
.tfb-foot__social li + li { margin-block-start: 0; }
.tfb-foot__social a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px; height: 34px;
    border: 1px solid rgba(255, 255, 255, .15);
    border-radius: var(--r-sm);
}
.tfb-foot__social a:hover { border-color: var(--c-cyan); color: var(--c-cyan); }
.tfb-foot__bar {
    background: rgba(0, 0, 0, .3);
    padding-block: var(--s-4);
    font-size: var(--fs-xs);
}
.tfb-foot__bar .tfb-shell {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: var(--s-3);
}

/* --------------------------------------------------------------------------
   Floating contact buttons
   -------------------------------------------------------------------------- */
.tfb-fabs {
    position: fixed;
    z-index: 45;
    inset-block-end: var(--s-5);
    inset-inline-end: var(--s-5);
    display: flex;
    flex-direction: column;
    gap: var(--s-2);
}
.tfb-fab {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px; height: 44px;
    border: 0;
    border-radius: var(--r-md);
    color: #fff;
    box-shadow: var(--sh-2);
    cursor: pointer;
    transition: transform .16s ease;
}
.tfb-fab:hover { transform: translateY(-2px); }
.tfb-fab--wa  { background: #25d366; }
.tfb-fab--tg  { background: #229ed9; }
/* WeChat green. Shown on the Chinese pages only — see the layout. */
.tfb-fab--wc  { background: #07c160; }
/* The "Edit in admin" button had no background of its own, so its white icon was
   invisible on a white page. Give it the site accent (staff-only button). */
.tfb-fab--edit { background: var(--c-accent, #0a4d68); }
.tfb-fab--top { background: var(--c-dark-2); display: none; }

/* --------------------------------------------------------------------------
   Tour page — the gallery, and the card that takes the booking

   Two columns: the picture mosaic and, BESIDE it rather than under the fold,
   the booking card. The card is the only thing on the page that takes money,
   so it gets the space next to the first thing anyone looks at.

   The DOM order is gallery → card → prose, which is also the order a phone
   reads them in when the grid collapses to one column. The desktop placement
   is explicit (`grid-row`), so the prose can sit under the gallery while the
   card spans both rows and stays sticky for the whole scroll.

   Everything named .bk-* here is the contract with tour-page.js — that script
   owns pricing, availability and the live WhatsApp message, and it injects
   .bk-price-line / .bk-bd-row / the whole calendar grid. Renaming any of them
   silently unstyles a control that still works.
   -------------------------------------------------------------------------- */
.tfb-pagehead--tour { padding-block: var(--s-5) var(--s-6); }
.tfb-pagehead--tour h1 { max-width: 26ch; }

/* The chip row above the H1 is gone from every page that had one — tour,
   transfer vehicle and blog article. Nothing renders .tfb-tourhead__themes any
   more, so its rules went with it rather than sitting here waiting to be
   rediscovered. See the note on the cards' theme chips further up. */

/* Rating, duration, capacity, languages — one line under the title. Separators
   are drawn by CSS so they never reach a screen reader or a crawler. */
.tfb-tourhead__facts {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-2) var(--s-3);
    margin-block-start: var(--s-4);
    color: var(--c-on-dark-2);
    font-size: var(--fs-sm);
}
.tfb-tourhead__facts li { display: inline-flex; align-items: center; gap: var(--s-3); unicode-bidi: plaintext; }
.tfb-tourhead__facts li + li::before { content: "·"; opacity: .5; }
.tfb-tourhead__facts .tfb-rate { margin: 0; }

.tfb-tour__grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 372px;
    gap: var(--s-6);
    align-items: start;
}
.tfb-tour__grid > .tfb-gal { grid-column: 1; grid-row: 1; }
.tfb-tour__aside { grid-column: 2; grid-row: 1 / span 2; align-self: stretch; }
.tfb-tour__body  { grid-column: 1; grid-row: 2; min-width: 0; }

.tfb-tour__block + .tfb-tour__block { margin-block-start: var(--s-7); }
.tfb-tour__block > h2 { margin-block-end: var(--s-4); }

/* --- What the price covers -------------------------------------------------
   Two columns where both lists exist, one where only the inclusions do — which
   is most tours, and the reason this is auto-fit rather than a fixed 1fr 1fr.

   The tick and cross are ::before content on the list item rather than
   characters in the text, so they never end up in a copied paragraph, never
   reach a screen reader, and never need translating. Logical properties
   throughout: the Arabic and Hebrew pages mirror this block wholesale. */
.tfb-incl__cols {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
    gap: var(--s-5) var(--s-6);
    align-items: start;
}
.tfb-incl { margin: 0; padding: 0; list-style: none; }
.tfb-incl li {
    position: relative;
    padding-inline-start: 1.6em;
    margin-block-end: var(--s-2);
    line-height: 1.5;
}
.tfb-incl li::before {
    position: absolute;
    inset-inline-start: 0;
    font-weight: 700;
}
.tfb-incl--yes li::before { content: "✓"; color: #0e6b60; }   /* 6.38:1 on white */
.tfb-incl--no  li::before { content: "✕"; color: #8a5a00; }   /* 4.71:1 on white */
.tfb-incl__sub {
    margin: 0 0 var(--s-3);
    font-size: .95rem;
    color: var(--c-muted, #5b6470);
}

/* --- Gallery mosaic -------------------------------------------------------
   One large tile and up to four small ones, laid out by how many pictures the
   tour actually has — a four-image tour must not print an empty cell. Rounded
   on the outside only, so the run reads as one picture rather than five. */
.tfb-gal {
    display: grid;
    gap: 6px;
    aspect-ratio: 16 / 9;
    border-radius: var(--r-lg);
    overflow: hidden;
    background: var(--c-canvas);
}
.tfb-gal--n1 { grid-template-columns: 1fr; }
.tfb-gal--n2 { grid-template-columns: 1fr 1fr; }
.tfb-gal--n3,
.tfb-gal--n4,
.tfb-gal--n5 { grid-template-columns: 2fr 1fr 1fr; grid-template-rows: 1fr 1fr; }
.tfb-gal--n3 .tfb-gal__t:first-child,
.tfb-gal--n4 .tfb-gal__t:first-child,
.tfb-gal--n5 .tfb-gal__t:first-child { grid-column: 1; grid-row: 1 / span 2; }
/* Three pictures: the two small ones stack in a single right-hand column. */
.tfb-gal--n3 { grid-template-columns: 2fr 1fr; }
/* Four: the last one runs the full width beneath the other two. */
.tfb-gal--n4 .tfb-gal__t:nth-child(4) { grid-column: 2 / span 2; }

.tfb-gal__t { position: relative; overflow: hidden; }
.tfb-gal__t > a { display: block; height: 100%; }
.tfb-gal__t img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .35s ease;
}
.tfb-gal__t > a:hover img { transform: scale(1.04); }
.tfb-gal__t > a:hover { text-decoration: none; }

/* "+12 photos", on the last visible tile. It opens the same lightbox as any
   other tile, so it is a label inside that tile's link, not a second one. */
.tfb-gal__more {
    position: absolute;
    inset-block-end: var(--s-3);
    inset-inline-end: var(--s-3);
    padding: .4rem .8rem;
    border-radius: var(--r-pill);
    background: rgba(12, 20, 34, .78);
    color: var(--c-on-dark);
    font-size: var(--fs-xs);
    font-weight: 600;
    backdrop-filter: blur(4px);
}

/* --- Booking card --------------------------------------------------------- */
.tfb-bk {
    background: var(--c-bg);
    border: 1px solid var(--c-line);
    border-radius: var(--r-lg);
    box-shadow: var(--sh-2);
    padding: var(--s-5);
}
/* Sticky only when the admin has left the setting on. tour-page.js measures the
   card and writes --bk-sticky-top so the whole of it fits a short viewport; the
   fallback clears the masthead on its own if the script has not run yet. */
body.sticky-sidebar .tfb-bk {
    position: sticky;
    top: var(--bk-sticky-top, calc(var(--head-h) + var(--s-4)));
}
/* One rule for every control the script hides — a class with its own `display`
   would otherwise beat the UA stylesheet's [hidden] and show an empty row. */
.tfb-bk [hidden] { display: none !important; }

.tfb-bk__head { padding-block-end: var(--s-4); border-block-end: 1px solid var(--c-line-2); }
.tfb-bk__title { font-size: var(--fs-md); }
.tfb-bk__price {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--s-2);
    margin-block-start: var(--s-3);
}
.tfb-bk__from { font-size: var(--fs-xs); color: var(--c-muted); }
/* Styled with the other two struck figures in the discount block at the foot. */
.tfb-bk__amount { font-size: 1.7rem; font-weight: 800; letter-spacing: -.03em; }
.tfb-bk__unit { font-size: var(--fs-xs); color: var(--c-muted); }
.tfb-bk__save {
    padding: .1rem .45rem;
    border-radius: var(--r-sm);
    background: var(--c-accent-050);
    color: var(--c-accent);
    font-size: var(--fs-xs);
    font-weight: 700;
}

.tfb-bk__field { margin-block-start: var(--s-4); }
.tfb-bk__field > label,
.tfb-bk__label {
    display: block;
    margin-block-end: var(--s-2);
    color: var(--c-muted);
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
}
.tfb-bk__date-plain { width: 100%; margin-block-start: var(--s-2); }
/* A label and its control on one line, where the control is small enough that a
   line of its own would be wasted height. */
.tfb-bk__field--inline { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s-2) var(--s-3); }
.tfb-bk__field--inline > label { margin: 0; }
.tfb-bk__field--inline .bk-pax-hint { flex-basis: 100%; margin: 0; }

/* The date trigger doubles as the value display, so the card carries one date
   control rather than a field plus a permanently open grid. */
.bk-date-toggle {
    display: flex;
    width: 100%;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-3);
    padding: .7rem .85rem;
    border: 1px solid var(--c-line);
    border-radius: var(--r-sm);
    background: var(--c-bg);
    color: var(--c-muted);
    text-align: start;
    cursor: pointer;
    transition: border-color .16s ease;
}
.bk-date-toggle:hover { border-color: var(--c-accent); }
.bk-date-toggle.has-value { color: var(--c-ink); font-weight: 600; border-color: var(--c-ink); }

.bk-date-status:not(:empty) { margin-block-start: var(--s-2); font-size: var(--fs-xs); }
.bk-date-status.is-error { color: #b42318; }
.bk-date-status.is-ok    { color: var(--c-ok); }
.bk-date-status.is-warn  { color: #b25e09; }

/* Availability grid. Injected by tour-page.js — the class names below are its
   output, not this file's invention. */
.bk-cal {
    margin-block-start: var(--s-2);
    padding: var(--s-3);
    border: 1px solid var(--c-line);
    border-radius: var(--r-md);
    background: var(--c-bg);
    box-shadow: var(--sh-1);
}
.bk-cal-head { display: flex; align-items: center; justify-content: space-between; margin-block-end: var(--s-2); }
.bk-cal-title { font-size: var(--fs-sm); font-weight: 700; }
.bk-cal-nav {
    width: 30px; height: 30px;
    border: 1px solid var(--c-line);
    border-radius: var(--r-sm);
    background: none;
    line-height: 1;
    cursor: pointer;
}
.bk-cal-nav[disabled] { opacity: .35; cursor: not-allowed; }
.bk-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.bk-cal-dow { padding-block: 2px; color: var(--c-muted); font-size: var(--fs-xs); text-align: center; }
.bk-cal-day {
    position: relative;
    aspect-ratio: 1;
    border: 0;
    border-radius: var(--r-sm);
    background: var(--c-canvas);
    font-size: var(--fs-sm);
    cursor: pointer;
}
.bk-cal-day.is-empty  { background: none; }
.bk-cal-day.is-open   { background: rgba(14, 159, 110, .14); font-weight: 600; }
.bk-cal-day.is-closed { background: var(--c-line-2); color: var(--c-muted); cursor: not-allowed; text-decoration: line-through; }
.bk-cal-day.is-selected { background: var(--c-accent); color: var(--c-on-dark); font-weight: 700; }
/* The day's price, on hover — the one thing a month grid cannot show at a
   glance and the visitor actually needs. */
.bk-cal-tip {
    position: absolute;
    inset-block-end: calc(100% + 4px);
    inset-inline-start: 50%;
    transform: translateX(-50%);
    z-index: 3;
    display: none;
    padding: .25rem .5rem;
    border-radius: var(--r-sm);
    background: var(--c-ink);
    color: var(--c-on-dark);
    font-size: var(--fs-xs);
    white-space: nowrap;
    pointer-events: none;
}
[dir="rtl"] .bk-cal-tip { transform: translateX(50%); }
.bk-cal-day:hover .bk-cal-tip { display: block; }
.bk-cal-legend { display: flex; gap: var(--s-3); margin-block-start: var(--s-2); color: var(--c-muted); font-size: var(--fs-xs); }
.bk-cal-legend i { display: inline-block; width: 10px; height: 10px; margin-inline-end: 4px; border-radius: 3px; }

/* Party size. One stepper, or three when the tour offers a child rate. */
.bk-pax-stepper {
    display: inline-flex;
    align-items: center;
    padding: 2px;
    border: 1px solid var(--c-line);
    border-radius: var(--r-sm);
}
.bk-pax-btn {
    width: 34px; height: 34px;
    border: 0;
    border-radius: 6px;
    background: var(--c-canvas);
    font-size: 1.05rem;
    line-height: 1;
    cursor: pointer;
}
.bk-pax-btn:hover { background: var(--c-canvas-2); }
.bk-pax-btn[disabled] { opacity: .4; cursor: not-allowed; }
.bk-pax-stepper input {
    width: 50px;
    border: 0;
    background: none;
    font-weight: 700;
    text-align: center;
    -moz-appearance: textfield;
    appearance: textfield;
}
.bk-pax-stepper input::-webkit-outer-spin-button,
.bk-pax-stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
/* The party field, collapsed. Three labelled rows with steppers cost eleven
   lines of a card that has to fit beside the gallery on a laptop, so the field
   reads as one line — "2 people" — and opens on demand.
   A native <details>: it opens, closes, takes focus and works with no script,
   which a div with a click handler does not. */
.bk-pax > summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-3);
    padding: .7rem .85rem;
    border: 1px solid var(--c-line);
    border-radius: var(--r-sm);
    background: var(--c-bg);
    cursor: pointer;
    list-style: none;
    transition: border-color .16s ease;
}
.bk-pax > summary::-webkit-details-marker { display: none; }
.bk-pax > summary:hover { border-color: var(--c-accent); }
.bk-pax[open] > summary { border-color: var(--c-ink); border-end-start-radius: 0; border-end-end-radius: 0; }
/* Inside the trigger the caption is a caption, not a field label above it. */
.bk-pax > summary .tfb-bk__label { margin: 0; }
.bk-pax__sum { display: flex; align-items: center; gap: var(--s-2); font-weight: 600; }
/* The chevron is drawn, so it never reaches a screen reader or a crawler. */
.bk-pax__sum::after {
    content: "";
    width: 8px; height: 8px;
    border-inline-end: 2px solid var(--c-muted);
    border-block-end: 2px solid var(--c-muted);
    transform: rotate(45deg) translateY(-2px);
    transition: transform .18s ease;
}
.bk-pax[open] .bk-pax__sum::after { transform: rotate(-135deg) translateY(-2px); }
.bk-pax[open] .bk-pax-rows {
    padding: var(--s-3) var(--s-4);
    border: 1px solid var(--c-ink);
    border-block-start: 0;
    border-end-start-radius: var(--r-sm);
    border-end-end-radius: var(--r-sm);
}
.bk-pax-rows { display: grid; gap: var(--s-2); }
.bk-pax-row { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); }
.bk-pax-row__label { font-size: var(--fs-sm); font-weight: 600; }
.bk-pax-row__label small { display: block; color: var(--c-muted); font-size: var(--fs-xs); font-weight: 400; }
.bk-pax-stepper--sm .bk-pax-btn { width: 28px; height: 28px; }
.bk-pax-stepper--sm input { width: 38px; }
.bk-pax-hint { margin-block-start: var(--s-2); color: var(--c-muted); font-size: var(--fs-xs); }

/* Group / Private. Each tab carries its own live total, so the two can be
   compared without switching between them. */
.bk-type-tabs { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-2); margin-block-start: var(--s-4); }
.bk-type-tab {
    display: grid;
    gap: 2px;
    padding: .55rem .5rem;
    border: 1px solid var(--c-line);
    border-radius: var(--r-sm);
    background: var(--c-bg);
    text-align: center;
    cursor: pointer;
}
.bk-type-tab.active { border-color: var(--c-accent); background: var(--c-accent-050); }
.bk-type-tab__label { font-size: var(--fs-sm); font-weight: 600; }
.bk-type-tab__price { color: var(--c-muted); font-size: var(--fs-xs); font-weight: 600; }
.bk-type-tab.active .bk-type-tab__price { color: var(--c-accent); }

/* Injected price states. */
#bk-price-area:not(:empty) { margin-block-start: var(--s-3); }
.bk-price-line { display: grid; gap: 2px; }
.bk-price-total { font-size: 1.45rem; font-weight: 800; letter-spacing: -.03em; }
.bk-price-sub { color: var(--c-muted); font-size: var(--fs-xs); }
.bk-no-price { color: var(--c-slate); font-size: var(--fs-sm); font-weight: 600; }

.bk-breakdown {
    margin-block-start: var(--s-3);
    padding: var(--s-3);
    border-radius: var(--r-sm);
    background: var(--c-canvas);
    font-size: var(--fs-sm);
}
.bk-bd-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); }
.bk-bd-row + .bk-bd-row { margin-block-start: 2px; }
.bk-bd-row small { color: var(--c-muted); font-size: var(--fs-xs); margin-inline-start: .3rem; }

.bk-total {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s-3);
    margin-block-start: var(--s-3);
    padding-block-start: var(--s-3);
    border-block-start: 1px solid var(--c-line);
}
.bk-total__label { color: var(--c-muted); font-size: var(--fs-xs); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.bk-total__value { text-align: end; }
#bk-total-amount { font-size: 1.35rem; font-weight: 800; letter-spacing: -.03em; }
.bk-total__value small { display: block; color: var(--c-muted); font-size: var(--fs-xs); }

/* WhatsApp — the second booking path, above the checkout button because it is
   how most of this agency's customers actually book. Outlined, not filled: the
   form is still the primary action. */
.bk-wa {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-2);
    width: 100%;
    margin-block-start: var(--s-4);
    padding: .72rem 1rem;
    border: 1px solid #25d366;
    border-radius: var(--r-sm);
    background: var(--c-bg);
    color: #10893f;
    font-size: var(--fs-sm);
    font-weight: 700;
}
.bk-wa:hover { background: #25d366; color: #fff; text-decoration: none; }

.bk-trust {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--s-1) var(--s-2);
    margin-block: var(--s-3);
    color: var(--c-muted);
    font-size: var(--fs-xs);
    text-align: center;
}
.bk-trust a { color: var(--c-accent); text-decoration: underline; text-underline-offset: 2px; }

.bk-cta { width: 100%; }
.bk-cta[disabled] { opacity: .55; cursor: not-allowed; transform: none; }

/* --- Body blocks ---------------------------------------------------------- */
.tfb-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr));
    gap: var(--s-3);
    margin-block-start: var(--s-5);
}
.tfb-facts > div { padding: var(--s-3) var(--s-4); border-radius: var(--r-md); background: var(--c-canvas); }
.tfb-facts dt { color: var(--c-muted); font-size: var(--fs-xs); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.tfb-facts dd { margin-block-start: 2px; font-weight: 600; unicode-bidi: plaintext; }

/* The itinerary is a timeline, not an accordion: an accordion needs a script,
   and steps hidden behind one are steps a crawler has to be trusted to open. */
.tfb-itin {
    display: grid;
    gap: var(--s-5);
    padding-inline-start: var(--s-5);
    border-inline-start: 2px solid var(--c-line);
}
.tfb-itin__step { position: relative; }
.tfb-itin__step::before {
    content: "";
    position: absolute;
    inset-inline-start: calc((var(--s-5) + 6px) * -1);
    top: .35em;
    width: 10px; height: 10px;
    border-radius: 50%;
    background: var(--c-accent);
    box-shadow: 0 0 0 3px var(--c-bg);
}
.tfb-itin__time { color: var(--c-accent); font-size: var(--fs-xs); font-weight: 700; letter-spacing: .06em; }
.tfb-itin__title { margin-block-start: 2px; font-size: var(--fs-md); unicode-bidi: plaintext; }
.tfb-itin__text { margin-block-start: var(--s-2); max-width: var(--w-prose); color: var(--c-slate); unicode-bidi: plaintext; }

.tfb-embed { aspect-ratio: 16 / 9; border-radius: var(--r-md); overflow: hidden; background: var(--c-canvas); }
.tfb-embed iframe { display: block; width: 100%; height: 100%; border: 0; }

/* The reviews block has not been rebuilt yet. It ships its own stylesheet,
   which reads five variables from the OLD design system; mapping them onto the
   current tokens lets it sit in this shell unmodified. Delete this with the
   block when it gets its own pass. */
.tfb-legacy {
    --bg-white: var(--c-bg);
    --border-color: var(--c-line);
    --radius: var(--r-md);
    --text-dark: var(--c-ink);
    --text-light: var(--c-muted);
    --primary: var(--c-accent);
    margin-block-start: var(--s-7);
}
.tfb-legacy .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-2);
    padding: .7rem 1.2rem;
    border: 1px solid var(--c-line);
    border-radius: var(--r-sm);
    background: var(--c-bg);
    font-size: var(--fs-sm);
    font-weight: 600;
    cursor: pointer;
}
.tfb-legacy .btn-primary { background: var(--c-accent); border-color: var(--c-accent); color: var(--c-on-dark); }
/* The comment form is `.form-group` + `.form-control`, which the old stylesheet
   laid out and this one has no equivalent for — without these the label sits
   beside the field and the textarea keeps its UA width. */
.tfb-legacy .form-group { display: grid; gap: var(--s-2); margin-block-end: var(--s-4); }
.tfb-legacy .form-group > label { color: var(--c-muted); font-size: var(--fs-xs); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.tfb-legacy .form-control {
    width: 100%;
    padding: .7rem .85rem;
    border: 1px solid var(--c-line);
    border-radius: var(--r-sm);
    background: var(--c-bg);
    font-size: var(--fs-base);
}
.tfb-legacy textarea.form-control { resize: vertical; }
.tfb-legacy .form-control:focus { border-color: var(--c-accent); outline: none; }
/* Its rating badge draws a grey track with a clipped amber overlay. Those three
   rules live in styles.css, not in the block's own stylesheet, so without them
   the two rows of stars stack side by side and the tour reads as ten stars. */
.tfb-legacy .tour-stars { position: relative; display: inline-block; font-size: 15px; line-height: 1; letter-spacing: 1px; }
.tfb-legacy .tour-stars__track { display: block; color: var(--c-line); }
.tfb-legacy .tour-stars__fill {
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: 0;
    overflow: hidden;
    white-space: nowrap;
    color: var(--c-star);
}
.tfb-legacy .tour-rating-value { font-weight: 700; color: var(--c-ink); }

/* --- Lightbox -------------------------------------------------------------
   A native <dialog>: the browser supplies the modal semantics, the focus trap,
   the backdrop and Escape-to-close. Closed it renders nothing, so its lazy
   images are never fetched. */
.tfb-lb {
    width: 100vw;
    max-width: 100vw;
    height: 100dvh;
    max-height: 100dvh;
    margin: 0;
    padding: 0;
    border: 0;
    background: #0a1018;
    color: var(--c-on-dark);
}
.tfb-lb::backdrop { background: rgba(8, 12, 20, .92); }
.tfb-lb__track {
    display: flex;
    height: 100%;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    overscroll-behavior-x: contain;
}
.tfb-lb__track::-webkit-scrollbar { display: none; }
.tfb-lb__slide {
    position: relative;
    flex: 0 0 100%;
    height: 100%;
    margin: 0;
    scroll-snap-align: center;
}
.tfb-lb__slide picture { display: contents; }
/* Absolutely positioned against the slide, so the box is definite whatever the
   dialog's height resolves to — a percentage max-height on a grid item is not.
   `scale-down` letterboxes a large photo and leaves a small one at its own
   size; the padding keeps the picture clear of the buttons and the counter. */
.tfb-lb__slide img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    padding: var(--s-7) calc(var(--s-4) + 44px);
    object-fit: scale-down;
}

.tfb-lb__nav, .tfb-lb__close {
    position: absolute;
    display: grid;
    place-items: center;
    width: 44px; height: 44px;
    border: 1px solid rgba(255, 255, 255, .25);
    border-radius: 50%;
    background: rgba(8, 12, 20, .55);
    color: var(--c-on-dark);
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
}
.tfb-lb__nav:hover, .tfb-lb__close:hover { background: rgba(255, 255, 255, .16); }
.tfb-lb__nav { top: 50%; transform: translateY(-50%); }
.tfb-lb__nav--prev { inset-inline-start: var(--s-4); }
.tfb-lb__nav--next { inset-inline-end: var(--s-4); }
/* The chevrons are drawn characters, so they must mirror with the writing
   direction the way the buttons themselves do. */
[dir="rtl"] .tfb-lb__nav { transform: translateY(-50%) scaleX(-1); }
.tfb-lb__close { top: var(--s-4); inset-inline-end: var(--s-4); }
.tfb-lb__count {
    position: absolute;
    inset-block-end: var(--s-4);
    inset-inline: 0;
    text-align: center;
    font-size: var(--fs-sm);
    color: var(--c-on-dark-2);
}

@media (max-width: 1080px) {
    /* One column. The DOM order — gallery, card, prose — becomes the reading
       order, so the booking card stays above the article rather than below it. */
    .tfb-tour__grid { grid-template-columns: 1fr; }
    .tfb-tour__grid > .tfb-gal,
    .tfb-tour__aside,
    .tfb-tour__body { grid-column: 1; grid-row: auto; }
    body.sticky-sidebar .tfb-bk { position: static; }
}

@media (max-width: 720px) {
    /* The mosaic becomes a swipeable row. Scroll-snap does the whole job — no
       carousel script, and nothing to initialise before the pictures work. */
    .tfb-gal {
        display: flex;
        aspect-ratio: auto;
        gap: var(--s-2);
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        scrollbar-width: none;
        border-radius: 0;
        background: none;
        margin-inline: calc(var(--s-4) * -1);
        padding-inline: var(--s-4);
    }
    .tfb-gal::-webkit-scrollbar { display: none; }
    .tfb-gal__t {
        flex: 0 0 88%;
        aspect-ratio: 4 / 3;
        border-radius: var(--r-md);
        scroll-snap-align: center;
    }
    .tfb-bk { padding: var(--s-4); }
    .tfb-itin { padding-inline-start: var(--s-4); }
    .tfb-itin__step::before { inset-inline-start: calc((var(--s-4) + 6px) * -1); }
}

/* --------------------------------------------------------------------------
   Transfers — the hub, and the quote widget that opens it

   The widget (.trp-*) is ONE implementation rendered in two layouts: a compact
   row in the hub's header band (`hero`), and a two-column page at
   /transfers/plan/ (`full`). Its markup and its pricing mirror live in
   partials/transfer_planner.php; only the look is here, because the results
   list, the typeahead and the class filter are pieces of the design system now
   rather than one page's private styles.

   The date fields are `.bk-picker` controls — the same control the tour booking
   card uses, so the site has one calendar rather than two that drift.
   -------------------------------------------------------------------------- */

/* --- The shared picker, as it behaves inside a compact field row ---------- */
.bk-picker { position: relative; width: 100%; }
.bk-picker-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* tfb-picker.js marks a selectable day `is-free`; the availability calendar on a
   tour page calls the same state `is-open`. Two scripts, one look. */
.bk-cal-day.is-free { background: rgba(14, 159, 110, .14); font-weight: 600; }
.bk-cal-day.is-free:hover { background: rgba(14, 159, 110, .26); }
/* Time picker, for the pickup hour on a transfer booking form. */
.bk-timegrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; padding: var(--s-3);
    border: 1px solid var(--c-line); border-radius: var(--r-md); background: var(--c-bg); box-shadow: var(--sh-1);
    max-height: 240px; overflow-y: auto; }
.bk-time-slot { padding: .35rem .2rem; border: 0; border-radius: var(--r-sm); background: var(--c-canvas);
    font-size: var(--fs-sm); cursor: pointer; }
.bk-time-slot:hover { background: var(--c-canvas-2); }
.bk-time-slot.is-selected { background: var(--c-accent); color: var(--c-on-dark); font-weight: 700; }
.bk-timefield { display: flex; align-items: center; gap: var(--s-2); }
.bk-time-input { flex: 1 1 auto; min-width: 0; border: 0; background: none; font-weight: 600; }
.bk-time-open { flex: none; border: 0; background: none; cursor: pointer; color: var(--c-muted); }

/* --- Quote widget -------------------------------------------------------- */
.trp__card {
    background: var(--c-bg);
    border: 1px solid var(--c-line);
    border-radius: var(--r-lg);
    box-shadow: var(--sh-2);
}
.trp-fields { display: grid; gap: var(--s-3); align-items: end; }
.trp-field { display: flex; flex-direction: column; gap: var(--s-1); min-width: 0; }
/* The labels are wider than their fields on the numeric columns, so without the
   ellipsis "PASSENGERS" spills into its neighbour and the two read as one
   run-on label. */
.trp-field > label {
    color: var(--c-muted);
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.trp-field > input,
.trp-field .trp-ta,
.trp-field .bk-date-toggle {
    width: 100%;
    height: 46px;
    padding-inline: var(--s-3);
    border: 1px solid var(--c-line);
    border-radius: var(--r-sm);
    background: var(--c-bg);
    font-size: var(--fs-base);
}
.trp-field > input:focus, .trp-field .trp-ta:focus { border-color: var(--c-accent); }
/* The panel is absolutely positioned in this compact row — inline, it would push
   the results list down by a whole calendar every time someone opened it. */
.trp-field .bk-cal,
.trp-field .bk-timegrid {
    position: absolute;
    z-index: 30;
    inset-inline-start: 0;
    min-width: 280px;
    box-shadow: var(--sh-3);
}
/* The last field's panel opens inward, or it runs off the card. */
.trp-field:last-of-type .bk-cal { inset-inline-start: auto; inset-inline-end: 0; }

/* The return date before the round-trip box is ticked: on screen so the option
   is visible, plainly not yet usable. The `disabled` attribute on the trigger is
   what actually stops it — this only makes that legible, and the LABEL stays at
   full strength so the field can still be read for what it is. */
.trp-field.is-inert .bk-picker { opacity: .5; }
.trp-field.is-inert .bk-date-toggle { cursor: not-allowed; background: var(--c-canvas); }
.trp-field.is-inert > label { opacity: .75; }

/* Round, and overlapping both place fields, so From/To read as one journey
   control rather than two unrelated inputs with a button wedged between them. */
.trp-swap {
    flex: none;
    align-self: end;
    display: grid;
    place-items: center;
    width: 36px; height: 36px;
    margin-block-end: 5px;
    border: 1px solid var(--c-line);
    border-radius: 50%;
    background: var(--c-bg);
    color: var(--c-muted);
    cursor: pointer;
    box-shadow: var(--sh-1);
    transition: color .15s ease, border-color .15s ease, transform .2s ease;
}
.trp-swap:hover { border-color: var(--c-accent); color: var(--c-accent); transform: rotate(180deg); }

/* From/To typeahead. .typeahead-wrap must establish the positioning context, or
   the list anchors to the whole field row. */
.typeahead-wrap { position: relative; }
.typeahead-list {
    position: absolute;
    z-index: 40;
    inset-inline: 0;
    top: 100%;
    margin-block-start: 4px;
    min-width: 220px;
    max-height: 264px;
    overflow-y: auto;
    background: var(--c-bg);
    border: 1px solid var(--c-line);
    border-radius: var(--r-md);
    box-shadow: var(--sh-3);
}
/* An author `display` beats the UA's [hidden] rule, so keep this explicit. */
.typeahead-list[hidden] { display: none; }
.ta-item { padding: var(--s-2) var(--s-3); border-block-end: 1px solid var(--c-line-2); cursor: pointer; font-size: var(--fs-base); unicode-bidi: plaintext; }
.ta-item:last-child { border-block-end: 0; }
.ta-item:hover, .ta-item.is-active { background: var(--c-accent-050); }
.ta-empty { padding: var(--s-3); color: var(--c-muted); font-size: var(--fs-sm); line-height: var(--lh-snug); }

/* Round trip reads as a toggle chip, matching the class filter beside it — as a
   bare checkbox it looked like leftover form furniture. */
.trp-check {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    padding: .34rem .8rem .34rem .6rem;
    border: 1px solid var(--c-line);
    border-radius: var(--r-pill);
    background: var(--c-bg);
    color: var(--c-slate);
    font-size: var(--fs-sm);
    font-weight: 600;
    cursor: pointer;
}
.trp-check:hover { border-color: var(--c-accent); color: var(--c-accent); }
.trp-check input { flex: none; width: 15px; height: 15px; margin: 0; accent-color: var(--c-accent); }
.trp-check:has(input:checked) { border-color: var(--c-accent); color: var(--c-accent); background: var(--c-accent-050); }

/* Class filter: radios, so the choice is one value, arrow-navigable, and works
   without a script. */
.trp-tiers { display: flex; flex-wrap: wrap; gap: var(--s-2); margin: 0; padding: 0; border: 0; min-width: 0; }
.trp-tier { position: relative; }
.trp-tier input { position: absolute; width: 0; height: 0; opacity: 0; }
.trp-tier span {
    display: inline-block;
    padding: .34rem .75rem;
    border: 1px solid var(--c-line);
    border-radius: var(--r-pill);
    background: var(--c-bg);
    color: var(--c-slate);
    font-size: var(--fs-sm);
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
}
.trp-tier span:hover { border-color: var(--c-accent); color: var(--c-accent); }
.trp-tier input:checked + span { background: var(--c-ink); border-color: var(--c-ink); color: var(--c-on-dark); }
.trp-tier input:focus-visible + span { outline: 2px solid var(--c-accent); outline-offset: 2px; }

/* --- Results ------------------------------------------------------------- */
.trp-empty { padding: var(--s-5) var(--s-4); color: var(--c-muted); font-size: var(--fs-base); text-align: center; }
.trp-note { padding: var(--s-3) var(--s-4); border-radius: var(--r-md); font-size: var(--fs-base); line-height: var(--lh-snug); }
.trp-note--warn { background: #fff5da; color: #7a4b06; }

.trp-summary {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s-4);
    padding-block-end: var(--s-3);
    border-block-end: 1px solid var(--c-line);
}
.trp-summary__t { font-weight: 700; }
.trp-summary__m { color: var(--c-muted); font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }

.trp-opt { padding-block: var(--s-3); border-block-end: 1px solid var(--c-line-2); }
.trp-opt:last-child { border-block-end: 0; }
.trp-opt__row { display: grid; grid-template-columns: auto 1fr auto auto; gap: var(--s-4); align-items: center; }
.trp-opt__img { position: relative; flex: none; display: block; width: 82px; height: 56px; border-radius: var(--r-sm); overflow: hidden; background: var(--c-canvas); }
.trp-opt__img img { width: 100%; height: 100%; object-fit: cover; }
.trp-opt__img--ph { display: grid; place-items: center; color: var(--c-muted); }
.trp-opt__img--ph svg { width: 26px; height: 26px; }
.trp-opt__i { min-width: 0; }
.trp-opt__n { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); font-weight: 600; line-height: var(--lh-snug); unicode-bidi: plaintext; }
.trp-opt__s { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-block-start: var(--s-1); color: var(--c-muted); font-size: var(--fs-sm); }
.trp-spec { display: inline-flex; align-items: center; gap: var(--s-1); }
.trp-spec svg { flex: none; width: 14px; height: 14px; opacity: .8; }
.trp-opt__pw { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.trp-opt__p { font-size: 1.2rem; font-weight: 800; letter-spacing: -.02em; white-space: nowrap; font-variant-numeric: tabular-nums; }
.trp-best {
    padding: 2px 6px;
    border-radius: var(--r-sm);
    background: rgba(14, 159, 110, .12);
    color: #0b7f58;
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    white-space: nowrap;
}
/* The decisive action, in the one accent the design system spends on actions. */
.trp-opt__b {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: .55rem 1.1rem;
    border: 1px solid var(--c-accent);
    border-radius: var(--r-sm);
    background: var(--c-accent);
    color: var(--c-on-dark);
    font-size: var(--fs-sm);
    font-weight: 700;
    white-space: nowrap;
}
.trp-opt__b:hover { background: var(--c-accent-600); border-color: var(--c-accent-600); color: var(--c-on-dark); text-decoration: none; }

/* The second kind of card in the same list: this vehicle has no settled fare on
   this journey, so where the price sits there is a word, and the button opens a
   message instead of the booking form. WhatsApp green rather than the site
   accent, so the two options in one list are told apart at a glance. */
.trp-opt__p--ask { font-size: var(--fs-sm); font-weight: 700; color: var(--c-text-muted, #64748b); letter-spacing: 0; }
.trp-opt__b--wa { background: #25D366; border-color: #25D366; }
.trp-opt__b--wa:hover { background: #1da851; border-color: #1da851; }

.trp-tierpill { padding: 2px 6px; border-radius: var(--r-sm); font-size: var(--fs-xs); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; white-space: nowrap; }
.trp-tierpill--economy  { background: var(--c-canvas-2); color: var(--c-slate); }
.trp-tierpill--comfort  { background: #dcf1f8; color: #0b5f75; }
.trp-tierpill--business { background: #e7e6fb; color: #443c9b; }
.trp-tierpill--vip      { background: #fdefd2; color: #7a5406; }

.trp-more { margin-block-start: var(--s-2); margin-inline-start: calc(82px + var(--s-4)); }
.trp-more summary { display: inline-flex; align-items: center; gap: var(--s-1); color: var(--c-accent); font-size: var(--fs-sm); font-weight: 600; cursor: pointer; list-style: none; }
.trp-more summary::-webkit-details-marker { display: none; }
.trp-more summary::after { content: "›"; display: inline-block; transform: rotate(90deg); transition: transform .15s ease; }
.trp-more[open] summary::after { transform: rotate(270deg); }
.trp-more__body { padding-block: var(--s-2); }
.trp-amens { display: flex; flex-wrap: wrap; gap: var(--s-1); margin-block-end: var(--s-2); }
.trp-amen { padding: 3px 9px; border-radius: var(--r-pill); background: var(--c-canvas); color: var(--c-slate); font-size: var(--fs-xs); }
.trp-more__link, .trp-link a { color: var(--c-accent); font-weight: 600; }
.trp-link { margin-block-start: var(--s-3); font-size: var(--fs-sm); }

/* --- Hero mode: the search IS the page header ---------------------------- */
.trp--hero .trp__card { padding: var(--s-4) var(--s-5); }
/* Six fields: from, swap, to, date, return date, passengers. The px minimums are
   sized to the LABELS, not the inputs — a numeric field needs two digits, but
   "PASSENGERS" above it needs ~94px or it collides with its neighbour. */
.trp--hero .trp-fields {
    grid-template-columns:
        minmax(0, 1.6fr) auto minmax(0, 1.6fr)
        minmax(120px, 1fr) minmax(120px, 1fr)
        minmax(94px, .55fr);
}
.trp--hero .trp-extras {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-4);
    margin-block-start: var(--s-4);
    padding-block-start: var(--s-3);
    border-block-start: 1px solid var(--c-line-2);
}
.trp--hero .trp-results:not(:empty) { margin-block-start: var(--s-4); }
.trp--hero .trp-results {
    padding-inline: var(--s-5);
    border: 1px solid var(--c-line);
    border-radius: var(--r-lg);
    background: var(--c-bg);
    box-shadow: var(--sh-2);
}
/* Before a journey is picked the panel holds one line of placeholder text, and a
   bordered card around it reads as an empty box the page forgot to fill. */
.trp--hero .trp-results:has(.trp-empty) { border-color: transparent; background: none; box-shadow: none; }
.trp--hero .trp-summary { padding-block-start: var(--s-4); }
.trp--hero .trp-link { padding-block-end: var(--s-4); }

/* --- Full mode: two columns on /transfers/plan/ -------------------------- */
.trp--full { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: var(--s-6); align-items: start; }
.trp--full .trp__card { padding: var(--s-5); }
/* Three EQUAL columns, two rows: From / swap / To, then Date / Return / Pax. An
   `auto` middle track sized itself to the swap button and left the return date
   half the width of the fields beside it, which read as a mistake. */
.trp--full .trp-fields { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.trp--full .trp-swap { justify-self: center; }
.trp--full .trp-extras { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s-3); margin-block-start: var(--s-4); padding-block-start: var(--s-4); border-block-start: 1px solid var(--c-line-2); }
.trp--full .trp-results { position: sticky; top: calc(var(--head-h) + var(--s-4)); padding: var(--s-5); border: 1px solid var(--c-line); border-radius: var(--r-lg); background: var(--c-bg); box-shadow: var(--sh-1); }

/* The journey map. Empty until two places are chosen, and it takes no space
   until then — `:not(:empty)` rather than a class the JS has to remember to
   remove. In the two-column planner it spans both, because a road squeezed into
   a half-width column is a road nobody can read. */
.trp-map:not(:empty) { margin-block-start: var(--s-4); }
.trp--full .trp-map:not(:empty) { grid-column: 1 / -1; margin-block-start: 0; }

/* ── A journey we do not list ─────────────────────────────────────────────
   The checkbox sits under the two place fields, and its one text box appears
   only when it is ticked — an empty field on every page load would read as a
   third place to fill in. */
.trp-other { margin-block-start: var(--s-3); }
/* The answer appears here, under the checkbox that asked for it — inside the
   form card, so it sits tighter than the same panel would in the results area
   below. */
.trp-other__box:not([hidden]) {
    margin-block-start: var(--s-3);
    padding-block-start: var(--s-3);
    border-block-start: 1px solid var(--c-line-2);
}
.trp-other__box .trp-help { padding: 0; }

/* What stands where the prices would be. Not a card pretending to be a quote:
   a sentence and two ways to reach a person. */
.trp-help { padding: var(--s-5) 0; }
.trp-help__lead { margin: 0 0 var(--s-4); color: var(--c-ink); line-height: var(--lh-normal); }
.trp-help__btns { display: flex; flex-wrap: wrap; gap: var(--s-3); }
/* Spelled out rather than leaning on `.btn`, which carries no look of its own
   here — every button in this widget is dressed by its modifier class. Same
   shape as the booking button in a vehicle row, so the two live in one family. */
.trp-help__b {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: .55rem 1.1rem;
    border: 1px solid var(--c-accent);
    border-radius: var(--r-sm);
    background: var(--c-accent);
    color: var(--c-on-dark);
    font-size: var(--fs-sm);
    font-weight: 700;
    white-space: nowrap;
}
.trp-help__b:hover { background: var(--c-accent-600); border-color: var(--c-accent-600); color: var(--c-on-dark); text-decoration: none; }
/* WhatsApp's own green, the same as the on-request cards use, so the two places
   that offer a message look like the same offer. */
.trp-help__b--wa { background: #25D366; border-color: #25D366; }
.trp-help__b--wa:hover { background: #1da851; border-color: #1da851; }

/* ── The journey: road on the left, the two numbers on the right ───────────
   The map used to be a full-width band, which gave a 210 km drive the same
   emphasis as the whole booking. It is now the wider of two columns rather than
   the whole row, and the distance and driving time sit beside it — the pair of
   questions that follow "which way does it go". Below 720px they stack, map
   first: on a phone the numbers are one thumb-scroll away and the road is what
   orients you. */
.trp-journey {
    display: grid;
    grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
    gap: var(--s-4);
    align-items: stretch;
}
/* Capped, not just narrowed. At the width of this column a 16:10 box is still
   over 500px tall, which pushes the prices — the thing the visitor came for —
   off the screen. The cap wins over the ratio and the row settles on it. */
.trp-journey .tfb-map { aspect-ratio: 16 / 10; height: 100%; max-height: 340px; }

.trp-facts {
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
    padding: var(--s-4);
    border: 1px solid var(--c-line);
    border-radius: var(--r-lg);
    background: var(--c-bg);
}
/* The journey, named. `unicode-bidi: plaintext` so an Arabic or Hebrew place
   name keeps its own direction inside a line that also holds an arrow. */
.trp-facts__j {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2);
    margin: 0; font-weight: 600; line-height: var(--lh-snug);
    unicode-bidi: plaintext;
}
.trp-facts__arrow { color: var(--c-muted); }
/* The arrow points the way the language reads. */
[dir="rtl"] .trp-facts__arrow { transform: scaleX(-1); }

.trp-facts__list { margin: 0; display: flex; flex-direction: column; gap: var(--s-3); }
.trp-facts__row {
    display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3);
    padding-block-start: var(--s-3);
    border-block-start: 1px solid var(--c-line-2);
}
.trp-facts__row dt { color: var(--c-muted); font-size: var(--fs-sm); }
/* Tabular figures so 210 km and 25 km line up under one another. */
.trp-facts__row dd {
    margin: 0; font-size: var(--fs-lg); font-weight: 700;
    font-variant-numeric: tabular-nums; white-space: nowrap;
}
.trp-facts__note {
    margin: 0; color: var(--c-muted); font-size: var(--fs-sm);
    /* Never a bare doubled number: this line says why it doubled. */
}

@media (max-width: 720px) {
    .trp-journey { grid-template-columns: 1fr; }
    .trp-journey .tfb-map { height: auto; }
}

/* --- Transfers hub ------------------------------------------------------- */
/* The planner band already carries the space under the header, so the first
   section does not need its own full lid of padding on top. */
.tfb-sec--tight { padding-block-start: var(--s-3); }
.tfb-lead { max-width: 78ch; color: var(--c-slate); font-size: var(--fs-md); line-height: 1.72; }
.tfb-block + .tfb-block { margin-block-start: var(--s-7); }
.tfb-lead + .tfb-block { margin-block-start: var(--s-7); }
/* A heading and the line under it. Not .tfb-sec__head: that one sets the two
   side by side, which is right when the second item is a link and wrong when it
   is a sentence about the heading. */
.tfb-block__head { margin-block-end: var(--s-5); }
.tfb-block__sub { max-width: 68ch; margin-block-start: var(--s-3); color: var(--c-slate); font-size: var(--fs-sm); }
.tfb-block__label { margin-block: var(--s-5) var(--s-3); color: var(--c-muted); font-size: var(--fs-xs); font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }

.tfb-chips { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.tfb-chips a {
    display: inline-block;
    padding: .3rem .7rem;
    border: 1px solid var(--c-line);
    border-radius: var(--r-pill);
    background: var(--c-bg);
    color: var(--c-slate);
    font-size: var(--fs-sm);
    unicode-bidi: plaintext;
}
.tfb-chips a:hover { border-color: var(--c-accent); color: var(--c-accent); text-decoration: none; }

/* Journey cards. 3 / 2 / 1 fixed columns rather than auto-fill: the block shows
   six, and auto-fill lands on four with a ragged row of two underneath. */
.tfb-rcards { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-4); margin-block-end: var(--s-5); }
.tfb-rcard {
    display: flex;
    flex-direction: column;
    height: 100%;
    border: 1px solid var(--c-line);
    border-radius: var(--r-md);
    overflow: hidden;
    background: var(--c-bg);
    transition: border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.tfb-rcard:hover { border-color: var(--c-accent); box-shadow: var(--sh-2); transform: translateY(-2px); text-decoration: none; }
/* `overflow: hidden` and `flex: none` are load-bearing, not decoration: the card
   is a flex column, so this box's automatic minimum size is its content and a
   portrait photograph would push it past the ratio rather than be cropped to it.
   That is exactly what happened to a vehicle card on the sister site, where a
   960x1280 image stood at twice the height of its neighbours. */
.tfb-rcard__media { position: relative; display: block; aspect-ratio: 3 / 2; background: var(--c-canvas); overflow: hidden; flex: none; }
.tfb-rcard__media img { width: 100%; height: 100%; object-fit: cover; }
.tfb-rcard__ph { display: grid; place-items: center; width: 100%; height: 100%; color: var(--c-muted); }
.tfb-rcard__price {
    position: absolute;
    inset-block-end: var(--s-2);
    inset-inline-end: var(--s-2);
    display: inline-flex;
    align-items: baseline;
    gap: var(--s-1);
    padding: .28rem .7rem;
    border-radius: var(--r-pill);
    background: rgba(255, 255, 255, .95);
    color: var(--c-muted);
    font-size: var(--fs-xs);
    box-shadow: var(--sh-1);
}
.tfb-rcard__price strong { color: var(--c-ink); font-size: var(--fs-base); font-variant-numeric: tabular-nums; }
.tfb-rcard__body { display: flex; flex-direction: column; gap: var(--s-1); padding: var(--s-3) var(--s-4) var(--s-4); }
/* Two lines are reserved for the title: the images are all one height, but
   "Baku to Heydar Aliyev Airport Transfer" wraps where "Baku to Quba Transfer"
   does not, and a grid only stretches items within a row — so the second row sat
   short. Reserving the taller of the two makes every card identical. */
.tfb-rcard__t {
    font-weight: 600;
    line-height: var(--lh-snug);
    min-height: 2.7em;
    unicode-bidi: plaintext;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.tfb-rcard__m { color: var(--c-muted); font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }

/* The priced-journeys table. Rows are the product here, so they get the weight:
   a quiet header, generous row height, tabular figures so the price reads as a
   column. `contain: paint` is load-bearing — with overflow-x alone the wide
   table still pushes the ROOT scroll width past the viewport on a phone. */
.tfb-tablewrap { overflow-x: auto; contain: paint; border: 1px solid var(--c-line); border-radius: var(--r-md); background: var(--c-bg); }
.tfb-table { width: 100%; min-width: 540px; border-collapse: collapse; }
.tfb-table thead th {
    padding: var(--s-3) var(--s-4);
    border-block-end: 1px solid var(--c-line);
    background: var(--c-canvas);
    color: var(--c-muted);
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: .06em;
    text-align: start;
    text-transform: uppercase;
    white-space: nowrap;
}
.tfb-table tbody th, .tfb-table tbody td { padding: var(--s-3) var(--s-4); border-block-end: 1px solid var(--c-line-2); font-weight: 400; text-align: start; }
.tfb-table tbody tr:last-child th, .tfb-table tbody tr:last-child td { border-block-end: 0; }
.tfb-table tbody tr:hover { background: var(--c-canvas); }
.tfb-table tbody th a { font-weight: 600; unicode-bidi: plaintext; }
.tfb-table tbody th a:hover { color: var(--c-accent); }
.tfb-table__num { color: var(--c-slate); font-size: var(--fs-sm); font-variant-numeric: tabular-nums; white-space: nowrap; }
.tfb-table__price { color: var(--c-ink); font-weight: 700; }
.tfb-table__go { width: 1%; color: var(--c-muted); }
[dir="rtl"] .tfb-table__go { transform: scaleX(-1); }
.tfb-table tbody tr:hover .tfb-table__go { color: var(--c-accent); }

/* --- Journey groups on /transfers/ ---------------------------------------- */
/* The listing shows one row per journey with the return leg beside it, grouped
   by the kind of trip. Before this it printed both legs of all 22 journeys as 44
   rows sorted by kilometres — every distance, time and fare twice. */
.tfb-rgroup { margin-block-start: var(--s-6); }
.tfb-rgroup__h {
    font-size: var(--fs-md);
    font-weight: 700;
    letter-spacing: .01em;
    margin-block: 0 var(--s-3);
    color: var(--c-ink);
}

/* The return leg: a quiet second link in the same cell. Quiet because it leads
   to the same numbers under a mirrored title — it is there to be followed and
   crawled, not to compete with the journey it belongs to. */
.tfb-table__back {
    display: inline-flex;
    align-items: center;
    gap: .3em;
    margin-inline-start: var(--s-2);
    font-size: var(--fs-xs);
    font-weight: 500;
    color: var(--c-muted);
    white-space: nowrap;
    vertical-align: middle;
}
.tfb-table__back:hover { color: var(--c-accent); text-decoration: none; }
/* No RTL flip: the glyph is a two-headed arrow and means the same thing in
   either script direction. */
@media (max-width: 640px) { .tfb-table__back-t { display: none; } }

/* Collapsed tail. The rows stay in the markup — they are the only links into
   those route pages — and the class is added by script, so with no JS the whole
   group is simply visible. */
.tfb-table--cut tbody tr.tfb-table__extra { display: none; }

.tfb-more {
    display: inline-flex;
    align-items: center;
    gap: .4em;
    margin-block-start: var(--s-3);
    padding: .5rem 1rem;
    border: 1px solid var(--c-line);
    border-radius: var(--r-sm);
    background: var(--c-surface);
    color: var(--c-ink);
    font: inherit;
    font-size: var(--fs-sm);
    font-weight: 600;
    cursor: pointer;
}
.tfb-more:hover { border-color: var(--c-accent); color: var(--c-accent); }

.tfb-rgroup__miss {
    margin-block-start: var(--s-5);
    color: var(--c-slate);
    font-size: var(--fs-sm);
}

/* --- Route page ---------------------------------------------------------- */
/* The vehicle column carries a thumbnail beside the name. The <th> stays the
   table cell; the flex row lives in a span inside it, because a `display: flex`
   on the cell itself takes it out of the column layout. */
.tfb-veh { display: flex; align-items: center; gap: var(--s-3); }
.tfb-veh__img { flex: none; width: 72px; height: 48px; border-radius: var(--r-sm); overflow: hidden; background: var(--c-canvas); }
.tfb-veh__img picture, .tfb-veh__img img { width: 100%; height: 100%; object-fit: cover; }
.tfb-veh__name { font-weight: 600; unicode-bidi: plaintext; }
.tfb-table--veh tbody th, .tfb-table--veh tbody td { vertical-align: middle; }
.tfb-table__act { text-align: end; }
.tfb-table__act .tfb-btn { padding: .5rem 1rem; }

.tfb-note { max-width: 74ch; margin-block-start: var(--s-4); color: var(--c-muted); font-size: var(--fs-sm); line-height: var(--lh-snug); }

/* A ticked list, for a "what's included" set. The mark is drawn by CSS, so it
   never lands in the text a screen reader reads out or a crawler extracts. */
.tfb-ticks { display: grid; gap: var(--s-3); max-width: 74ch; }
.tfb-ticks li { position: relative; padding-inline-start: var(--s-6); color: var(--c-ink-2); }
.tfb-ticks li::before {
    content: "";
    position: absolute;
    inset-inline-start: 0;
    top: .35em;
    width: 14px; height: 8px;
    border-inline-start: 2px solid var(--c-ok);
    border-block-end: 2px solid var(--c-ok);
    transform: rotate(-45deg);
}

/* Small cards: a destination tour, or another route. Enough to carry a name and
   one line under it, and nothing more — these are cross-links, not products. */
.tfb-minicards { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 240px), 1fr)); gap: var(--s-3); }
.tfb-minicard {
    display: flex;
    flex-direction: column;
    height: 100%;
    border: 1px solid var(--c-line);
    border-radius: var(--r-md);
    overflow: hidden;
    background: var(--c-bg);
    transition: border-color .16s ease, box-shadow .16s ease;
}
.tfb-minicard:hover { border-color: var(--c-accent); box-shadow: var(--sh-1); text-decoration: none; }
/* Same pair, same reason, as .tfb-rcard__media above. */
.tfb-minicard__img { display: block; aspect-ratio: 16 / 10; background: var(--c-canvas); overflow: hidden; flex: none; }
.tfb-minicard__img picture, .tfb-minicard__img img { width: 100%; height: 100%; object-fit: cover; }
.tfb-minicard__t { padding: var(--s-3) var(--s-4); font-weight: 600; line-height: var(--lh-snug); unicode-bidi: plaintext; }
.tfb-minicard__m { padding: 0 var(--s-4) var(--s-3); color: var(--c-muted); font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
.tfb-minicards--text .tfb-minicard__t { padding-block-end: var(--s-1); }

/* --- Vehicle page: the booking form ---------------------------------------
   A long form on a public page, so it is kept quiet: one column of fields, a
   pair where two short values belong on one line, and nothing boxed unless it
   is genuinely a separate thing. The summary card beside it is the same
   .tfb-bk component the tour page books with. */
.tfb-bform { display: flex; flex-direction: column; gap: var(--s-4); }
.tfb-bform__sub { margin-block-start: var(--s-4); font-size: var(--fs-md); }
/* One rule for every field the script hides — a class with its own `display`
   would otherwise beat the UA stylesheet's [hidden]. */
.tfb-bform [hidden] { display: none !important; }

.tfb-bform__group { display: flex; flex-direction: column; gap: var(--s-2); min-width: 0; }
/* The round-trip control is a label too, but it is a chip rather than a field
   caption — without the exclusion it inherited the uppercase caption treatment
   and stretched across the form. */
.tfb-bform__group > label:not(.trp-check),
.tfb-bform__label {
    display: block;
    color: var(--c-muted);
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
}
.tfb-bform__group > label em,
.tfb-bform__label em { font-style: normal; font-weight: 400; letter-spacing: 0; text-transform: none; }
.tfb-bform__group input[type="text"],
.tfb-bform__group input[type="email"],
.tfb-bform__group input[type="tel"],
.tfb-bform__group input[type="number"],
.tfb-bform__group input[type="date"],
.tfb-bform__group input[type="time"],
.tfb-bform__group select,
.tfb-bform__group textarea,
.tfb-bform__group .bk-date-toggle {
    width: 100%;
    padding: .7rem .85rem;
    border: 1px solid var(--c-line);
    border-radius: var(--r-sm);
    background: var(--c-bg);
    font-size: var(--fs-base);
}
.tfb-bform__group .bk-date-toggle { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); color: var(--c-muted); text-align: start; cursor: pointer; }
.tfb-bform__group .bk-date-toggle.has-value { color: var(--c-ink); font-weight: 600; border-color: var(--c-ink); }
.tfb-bform__group textarea { resize: vertical; }
.tfb-bform__group input:focus, .tfb-bform__group select:focus, .tfb-bform__group textarea:focus { border-color: var(--c-accent); }
.tfb-bform__group .bk-cal, .tfb-bform__group .bk-timegrid { position: absolute; z-index: 30; inset-inline-start: 0; min-width: 280px; box-shadow: var(--sh-3); }
.tfb-bform__inline { display: flex; align-items: center; gap: var(--s-3); }
.tfb-bform__inline input[type="number"] { width: 100px; }
.tfb-bform__row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-4); }
.tfb-hint { color: var(--c-muted); font-size: var(--fs-xs); line-height: var(--lh-snug); }
/* The round-trip chip hugs its label instead of stretching the column — as a
   full-width bordered bar it read as a field rather than a switch. */
.tr-round-group .trp-check { align-self: flex-start; }

/* The return pair before the round-trip box is ticked. `disabled` on the
   triggers is what actually stops them; this only makes that legible. */
.tfb-bform__row.is-inert .bk-picker { opacity: .5; }
.tfb-bform__row.is-inert .bk-date-toggle { cursor: not-allowed; background: var(--c-canvas); }

/* A figure the form reports rather than asks for — the overnight charge. */
.tfb-callout {
    display: flex;
    flex-direction: column;
    gap: var(--s-1);
    padding: var(--s-3) var(--s-4);
    border-inline-start: 3px solid var(--c-accent);
    border-radius: var(--r-sm);
    background: var(--c-accent-050);
}

/* Trip type: radios styled as a segmented control. The input stays in the DOM
   so the choice is one value and arrow keys still move between them. */
.tr-tabs { display: inline-flex; flex-wrap: wrap; gap: var(--s-2); }
.tr-tab { position: relative; }
.tr-tab input { position: absolute; width: 0; height: 0; opacity: 0; }
.tr-tab span {
    display: inline-block;
    padding: .45rem .9rem;
    border: 1px solid var(--c-line);
    border-radius: var(--r-pill);
    background: var(--c-bg);
    color: var(--c-slate);
    font-size: var(--fs-sm);
    font-weight: 600;
    cursor: pointer;
}
.tr-tab span:hover { border-color: var(--c-accent); color: var(--c-accent); }
.tr-tab input:checked + span,
.tr-tab.active span { background: var(--c-ink); border-color: var(--c-ink); color: var(--c-on-dark); }
.tr-tab input:focus-visible + span { outline: 2px solid var(--c-accent); outline-offset: 2px; }

/* Journey pair — the same control as the planner's From/To, in a form column. */

/* THE RULE THAT WAS MISSING. The From/To pickers are built out of the journey
   <select>'s own options and are meant to REPLACE it: the script adds this class
   and the form's comment says "the select keeps submitting — display:none fields
   still post". Nobody ever wrote the class. So the select stayed on screen under
   the two pickers, a third control asking the same question a third time, with
   the fare printed inside its option text.

   It stays in the DOM: it is both the submitted field and the data source the
   pickers read. With no JavaScript the class is never added and the select is
   the whole control, which is the fallback working as designed. */
.tr-route--replaced { display: none; }

.tr-journey__pair { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: var(--s-2); align-items: center; }
.tr-journey__input {
    width: 100%;
    padding: .7rem .85rem;
    border: 1px solid var(--c-line);
    border-radius: var(--r-sm);
    background: var(--c-bg);
    font-size: var(--fs-base);
}
.tr-journey__input:focus { border-color: var(--c-accent); }
.tr-journey__swap { align-self: center; margin: 0; }
.tr-journey__quote { color: var(--c-slate); font-size: var(--fs-sm); font-weight: 600; }

/* Messenger chips. --msgr is set per chip in the markup, so the brand colour
   appears only once it is chosen — a row of four brand colours would shout. */
.ck-messengers { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.ck-msgr { position: relative; }
.ck-msgr input { position: absolute; width: 0; height: 0; opacity: 0; }
.ck-msgr span {
    display: inline-block;
    padding: .35rem .8rem;
    border: 1px solid var(--c-line);
    border-radius: var(--r-pill);
    background: var(--c-bg);
    color: var(--c-slate);
    font-size: var(--fs-sm);
    font-weight: 600;
    cursor: pointer;
}
.ck-msgr.is-on span,
.ck-msgr:has(input:checked) span { border-color: var(--msgr, var(--c-accent)); color: var(--msgr, var(--c-accent)); background: var(--c-bg); }
.ck-msgr input:focus-visible + span { outline: 2px solid var(--c-accent); outline-offset: 2px; }

/* The summary card's vehicle name and its two-row read-out. */
.tfb-bk__vehicle { margin-block-start: var(--s-2); font-weight: 700; unicode-bidi: plaintext; }
.tfb-bk__dl { display: grid; gap: var(--s-2); margin-block-start: var(--s-4); }
.tfb-bk__dl > div { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); }
.tfb-bk__dl dt { color: var(--c-muted); font-size: var(--fs-sm); }
.tfb-bk__dl dd { font-weight: 600; text-align: end; }

/* Chips as plain labels — amenities are facts about the car, not filters. */
.tfb-chips--plain li {
    display: inline-block;
    padding: .25rem .7rem;
    border: 1px solid var(--c-line-2);
    border-radius: var(--r-pill);
    background: var(--c-canvas);
    color: var(--c-slate);
    font-size: var(--fs-xs);
}
.tfb-chips--plain { margin-block-end: var(--s-4); }

.tfb-gal__ph { display: grid; place-items: center; color: var(--c-muted); background: var(--c-canvas); }

/* Booking confirmed, and the one thing that goes wrong before it. */
.tfb-success {
    max-width: 560px;
    margin-inline: auto;
    padding: var(--s-6);
    border: 1px solid var(--c-line);
    border-radius: var(--r-lg);
    background: var(--c-bg);
    box-shadow: var(--sh-2);
    text-align: center;
}
.tfb-success__mark {
    display: grid;
    place-items: center;
    width: 48px; height: 48px;
    margin: 0 auto var(--s-4);
    border-radius: 50%;
    background: rgba(14, 159, 110, .14);
    color: var(--c-ok);
    font-size: 1.5rem;
}
.tfb-success h2 { margin-block-end: var(--s-3); }
.tfb-success__ref { margin-block: var(--s-4); color: var(--c-muted); font-size: var(--fs-sm); }
.tfb-alert {
    margin-block-end: var(--s-5);
    padding: var(--s-3) var(--s-4);
    border: 1px solid #f0c4bd;
    border-radius: var(--r-md);
    background: #fdf0ee;
    color: #93251a;
    font-size: var(--fs-sm);
}

/* Reviews on a vehicle page. The tour page's block is a much larger thing —
   a form, filters, photos, operator replies — and is not reused here. */
.tfb-revs { display: grid; gap: var(--s-3); max-width: 860px; }
.tfb-rev { padding: var(--s-4) var(--s-5); border: 1px solid var(--c-line); border-radius: var(--r-md); background: var(--c-bg); }
.tfb-rev__top { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); }
.tfb-rev__name { font-weight: 600; }
.tfb-rev__title { margin-block-start: var(--s-2); font-size: var(--fs-md); unicode-bidi: plaintext; }
.tfb-rev__body { margin-block-start: var(--s-2); color: var(--c-slate); unicode-bidi: plaintext; }
.tfb-rev__date { display: block; margin-block-start: var(--s-2); color: var(--c-muted); font-size: var(--fs-xs); }

/* --------------------------------------------------------------------------
   Blog — the index, and the article

   The index is a card grid; the article is one column at a readable measure,
   with its title, byline and dates in the page header rather than stacked above
   the prose. The conversion block under every article (.trip-cta) is styled here
   too: its markup is shared with nothing else, but its styles used to live in
   the legacy stylesheet, which redesigned pages do not load.
   -------------------------------------------------------------------------- */
.tfb-posts { display: grid; gap: var(--s-5); grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr)); }
.tfb-post {
    position: relative;
    display: flex;
    flex-direction: column;
    height: 100%;
    border: 1px solid var(--c-line);
    border-radius: var(--r-lg);
    overflow: hidden;
    background: var(--c-bg);
    transition: border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.tfb-post:hover { border-color: #c6d3e6; box-shadow: var(--sh-2); transform: translateY(-2px); }
.tfb-post__media { aspect-ratio: 16 / 10; overflow: hidden; background: var(--c-canvas-2); }
.tfb-post__media picture { display: block; height: 100%; }
.tfb-post__media img { width: 100%; height: 100%; object-fit: cover; transition: transform .35s ease; }
.tfb-post:hover .tfb-post__media img { transform: scale(1.04); }
.tfb-post__body { display: flex; flex-direction: column; gap: var(--s-2); padding: var(--s-4) var(--s-5) var(--s-5); }
.tfb-post__date { color: var(--c-muted); font-size: var(--fs-xs); letter-spacing: .07em; text-transform: uppercase; }
.tfb-post__title { font-size: var(--fs-md); line-height: var(--lh-snug); unicode-bidi: plaintext; }
/* ONE link per card: the title is the anchor and this covers the rest. */
.tfb-post__link::after { content: ""; position: absolute; inset: 0; }
.tfb-post__link:hover { text-decoration: none; color: var(--c-accent); }
.tfb-post__excerpt { color: var(--c-slate); font-size: var(--fs-sm); unicode-bidi: plaintext; }

/* An article's header carries a title that can run long, so it is not held to
   the hero's short measure. */
.tfb-pagehead--article h1 { max-width: 30ch; }
.tfb-byline {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-2) var(--s-4);
    margin-block-start: var(--s-5);
    padding-block-start: var(--s-4);
    border-block-start: 1px solid rgba(255, 255, 255, .14);
    color: var(--c-on-dark-2);
    font-size: var(--fs-sm);
}
.tfb-byline a { color: var(--c-on-dark); font-weight: 600; }
.tfb-byline__pic { width: 36px; height: 36px; border-radius: 50%; object-fit: cover; }

.tfb-article { max-width: 820px; margin-inline: auto; }
.tfb-article__lead { margin: 0 0 var(--s-6); border-radius: var(--r-lg); overflow: hidden; background: var(--c-canvas); }
.tfb-article__lead img { width: 100%; height: auto; }
.tfb-article__block { margin-block-start: var(--s-7); }
.tfb-article__block > h2 { margin-block-end: var(--s-4); }
/* Images inside authored prose get the same rounding as the lead, so a body
   photo does not read as a different kind of object from the one above it. */
.tfb-article .tfb-prose img { border-radius: var(--r-md); }
.tfb-article .tfb-prose h2 { margin-block-start: var(--s-7); }
.tfb-article .tfb-prose h3 { margin-block-start: var(--s-6); }

/* --- The end-of-article conversion block --------------------------------- */
.trip-cta {
    margin-block-start: var(--s-7);
    padding: var(--s-6);
    border: 1px solid var(--c-line);
    border-radius: var(--r-lg);
    background: var(--c-canvas);
}
.trip-cta__h { font-size: var(--fs-lg); }
.trip-cta__p { margin-block-start: var(--s-3); max-width: var(--w-prose); color: var(--c-slate); }
.trip-cta__tours { display: grid; gap: var(--s-3); margin-block-start: var(--s-5); }
.trip-cta__tourlink {
    display: flex;
    align-items: center;
    gap: var(--s-4);
    padding: var(--s-3);
    border: 1px solid var(--c-line);
    border-radius: var(--r-md);
    background: var(--c-bg);
    transition: border-color .16s ease, box-shadow .16s ease;
}
.trip-cta__tourlink:hover { border-color: var(--c-accent); box-shadow: var(--sh-1); text-decoration: none; }
.trip-cta__thumb { flex: none; width: 88px; height: 62px; border-radius: var(--r-sm); overflow: hidden; background: var(--c-canvas-2); }
.trip-cta__thumb picture { display: block; height: 100%; }
.trip-cta__thumb img { width: 100%; height: 100%; object-fit: cover; }
.trip-cta__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.trip-cta__name { font-weight: 600; line-height: var(--lh-snug); unicode-bidi: plaintext; }
.trip-cta__meta { display: flex; flex-wrap: wrap; gap: var(--s-3); color: var(--c-muted); font-size: var(--fs-sm); }
.trip-cta__rate { color: var(--c-slate); }
.trip-cta__price { color: var(--c-muted); font-size: var(--fs-sm); }
.trip-cta__price strong { color: var(--c-ink); font-size: var(--fs-md); font-variant-numeric: tabular-nums; }
.trip-cta__actions { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-block-start: var(--s-5); }
.trip-cta__btn {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    padding: .7rem 1.2rem;
    border: 1px solid var(--c-line);
    border-radius: var(--r-sm);
    background: var(--c-bg);
    font-size: var(--fs-sm);
    font-weight: 600;
}
.trip-cta__btn:hover { border-color: var(--c-ink); text-decoration: none; }
.trip-cta__btn--primary { background: var(--c-accent); border-color: var(--c-accent); color: var(--c-on-dark); }
.trip-cta__btn--primary:hover { background: var(--c-accent-600); border-color: var(--c-accent-600); }
.trip-cta__btn--wa { border-color: #25d366; color: #10893f; }
.trip-cta__btn--wa:hover { background: #25d366; border-color: #25d366; color: #fff; }
.trip-cta__btn--tg { border-color: #229ed9; color: #16688e; }
.trip-cta__btn--tg:hover { background: #229ed9; border-color: #229ed9; color: #fff; }
.trip-cta__ico { flex: none; }
.trip-cta__browse { margin-block-start: var(--s-4); font-size: var(--fs-sm); }
.trip-cta__browse a { color: var(--c-accent); font-weight: 600; }

/* --------------------------------------------------------------------------
   Checkout

   The same two-column shape as the tour page: the questions on the left, what is
   being bought and what it costs in a sticky card on the right. The blocks are
   separated by rules rather than boxed, because a boxed form on the last page
   before a booking reads as more steps than it is.
   -------------------------------------------------------------------------- */
.tfb-checkout { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: var(--s-6); align-items: start; }
.tfb-checkout__main { gap: 0; }
.tfb-checkout__block + .tfb-checkout__block {
    margin-block-start: var(--s-6);
    padding-block-start: var(--s-6);
    border-block-start: 1px solid var(--c-line-2);
}
.tfb-checkout__block > h2 { margin-block-end: var(--s-4); font-size: var(--fs-lg); }
.tfb-checkout__block > .tfb-bform__group + .tfb-bform__group,
.tfb-checkout__block > .tfb-bform__row + .tfb-bform__group,
.tfb-checkout__block > .tfb-bform__group + .tfb-bform__row,
.tfb-checkout__block > .tfb-bform__row + .tfb-bform__row { margin-block-start: var(--s-4); }
/* Accommodation and room number: a hotel name needs the room to breathe. */
.tfb-bform__row--2-1 { grid-template-columns: 2fr 1fr; }
/* The passenger rows come from the booking card, where they sit in a 280px
   column. Left to fill this one they would put the stepper the better part of a
   metre from the word it counts — so both the collapsed trigger and the rows
   inside it are held to a readable width. */
.tfb-checkout .bk-pax,
.tfb-checkout .bk-pax-rows { max-width: 480px; }
/* A label and its control on one line, where the control is small enough that a
   line of its own would be wasted height. */
.tfb-bform__group--inline { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-4); }
.tfb-bform__group--inline > label { margin: 0; }
.tfb-bform__group--inline .bk-pax-hint { flex-basis: 100%; margin: 0; }
.tfb-checkout__thumb { margin-block-start: var(--s-4); border-radius: var(--r-md); overflow: hidden; background: var(--c-canvas-2); aspect-ratio: 16 / 10; }
.tfb-checkout__thumb picture { display: block; height: 100%; }
.tfb-checkout__thumb img { width: 100%; height: 100%; object-fit: cover; }
/* The availability line under the date. It takes height only when it has
   something to say, so the field does not sit above a permanent blank row. */
.ck-date-status:not(:empty) { margin-block-start: var(--s-2); font-size: var(--fs-xs); }
.ck-date-status.is-error { color: #b42318; }
.ck-date-status.is-ok    { color: var(--c-ok); }
.ck-date-status.is-warn  { color: #b25e09; }
/* The tour-type tabs are labels wrapping a radio here, buttons on the tour page.
   Hiding the input in CSS rather than inline keeps the control keyboard-usable:
   `display: none` would take it out of the tab order entirely. */
.bk-type-tab input { position: absolute; width: 0; height: 0; opacity: 0; }
.bk-type-tab:has(input:checked) { border-color: var(--c-accent); background: var(--c-accent-050); }
.bk-type-tab input:focus-visible + .bk-type-tab__label { outline: 2px solid var(--c-accent); outline-offset: 3px; }

@media (max-width: 1000px) {
    .tfb-checkout { grid-template-columns: 1fr; }
    /* The summary goes first on one column: someone on a phone should see what
       they are buying and what it costs before they start typing. */
    .tfb-checkout__aside { order: -1; }
}
@media (max-width: 620px) {
    .tfb-bform__row--2-1 { grid-template-columns: 1fr; }
}

/* --------------------------------------------------------------------------
   Static pages — contact, about, FAQ, and the two states a visitor lands in
   when something has gone right (message sent) or wrong (404)
   -------------------------------------------------------------------------- */

/* --- Contact ------------------------------------------------------------- */
.tfb-contact { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: var(--s-6); align-items: start; }
.tfb-contact__form > h2 { margin-block-end: var(--s-5); }
.tfb-contact__card {
    padding: var(--s-5);
    border: 1px solid var(--c-line);
    border-radius: var(--r-lg);
    background: var(--c-bg);
    box-shadow: var(--sh-2);
}
.tfb-contact__title { font-size: var(--fs-md); }
.tfb-contact__sub { margin-block-start: var(--s-2); color: var(--c-slate); font-size: var(--fs-sm); }
.tfb-contact__list { display: grid; gap: var(--s-4); margin-block-start: var(--s-5); }
.tfb-contact__list dt { color: var(--c-muted); font-size: var(--fs-xs); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.tfb-contact__list dd { margin-block-start: var(--s-1); font-weight: 600; unicode-bidi: plaintext; }
.tfb-contact__list a { color: var(--c-ink); }
.tfb-contact__list a:hover { color: var(--c-accent); }
/* The WeChat ID is read and typed, not clicked, so it gets a face that makes
   character-by-character copying easy and a box that says "select me". */
.tfb-contact__id {
    display: inline-block;
    padding: .15rem .5rem;
    border: 1px dashed var(--c-line);
    border-radius: var(--r-sm);
    background: var(--c-canvas);
    font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
    letter-spacing: .04em;
    user-select: all;
}
.tfb-contact__qr { display: block; width: 140px; height: 140px; margin-block-start: var(--s-3); border-radius: var(--r-sm); }
.tfb-contact__actions { display: grid; gap: var(--s-3); margin-block-start: var(--s-5); padding-block-start: var(--s-4); border-block-start: 1px solid var(--c-line-2); }
/* The WhatsApp button is the booking card's, unchanged: one green button on the
   site, not two that nearly match. */
.tfb-contact__actions .bk-wa { margin-block-start: 0; }

/* --- About --------------------------------------------------------------- */
.tfb-about { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: var(--s-7); align-items: start; }
/* A page with no sidebar keeps the prose at a readable measure rather than
   stretching it across the whole shell. */
.tfb-about--solo { grid-template-columns: minmax(0, 820px); justify-content: center; }
.tfb-about__lead { font-size: var(--fs-md); }
.tfb-about__text > h2 { margin-block-end: var(--s-4); }
.tfb-about__ctas { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-block-start: var(--s-6); }
.tfb-about__aside { position: sticky; top: calc(var(--head-h) + var(--s-4)); display: grid; gap: var(--s-4); }
.tfb-about__img { width: 100%; border-radius: var(--r-lg); box-shadow: var(--sh-2); }
.tfb-about__facts { padding: var(--s-5); border: 1px solid var(--c-line); border-radius: var(--r-lg); background: var(--c-bg); }
.tfb-about__facts h3 { margin-block-end: var(--s-4); font-size: var(--fs-md); }

/* The numbers band. A description list: each entry is a label and its value,
   and putting the label first in the DOM keeps it that way for a reader who
   cannot see the size difference. */
.tfb-stats { background: var(--c-dark); color: var(--c-on-dark); padding-block: var(--s-6); }
.tfb-stats__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr)); gap: var(--s-5); text-align: center; }
.tfb-stats__grid dt { order: 2; margin-block-start: var(--s-2); color: var(--c-on-dark-2); font-size: var(--fs-sm); }
.tfb-stats__grid dd { order: 1; font-size: 2.2rem; font-weight: 800; letter-spacing: -.03em; line-height: 1; }
.tfb-stats__grid > div { display: flex; flex-direction: column; }

/* Contact channels, shared by /about/ and anywhere else that lists them. */
.tfb-channels { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); gap: var(--s-4); }
.tfb-channels a {
    display: flex;
    flex-direction: column;
    gap: var(--s-1);
    height: 100%;
    padding: var(--s-5);
    border: 1px solid var(--c-line);
    border-radius: var(--r-lg);
    background: var(--c-bg);
    transition: border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.tfb-channels a:hover { border-color: var(--c-accent); box-shadow: var(--sh-2); transform: translateY(-2px); text-decoration: none; }
.tfb-channels__lab { color: var(--c-muted); font-size: var(--fs-xs); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.tfb-channels__val { font-size: var(--fs-md); font-weight: 600; unicode-bidi: plaintext; }
.tfb-channels__more { margin-block-start: var(--s-2); color: var(--c-accent); font-size: var(--fs-sm); font-weight: 600; }

/* --- Notices: 404, and the "anything else?" panel under the FAQ ---------- */
.tfb-notice {
    max-width: 640px;
    margin-inline: auto;
    padding: var(--s-6);
    border: 1px solid var(--c-line);
    border-radius: var(--r-lg);
    background: var(--c-bg);
    text-align: center;
}
.tfb-notice--soft { max-width: none; margin-block-start: var(--s-7); border-color: transparent; background: var(--c-canvas); }
.tfb-notice h2 { margin-block-end: var(--s-3); }
.tfb-notice p { color: var(--c-slate); }
.tfb-notice__code { color: var(--c-canvas-2); font-size: 4.5rem; font-weight: 800; line-height: 1; letter-spacing: -.04em; }
.tfb-notice__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s-3); margin-block-start: var(--s-5); }

.tfb-alert--ok { border-color: #b9e2cd; background: #eefaf3; color: #0b6b47; }

/* --- Booking confirmed --------------------------------------------------- */
.tfb-success--wide { max-width: 720px; }
/* The reference is the one string a traveller may have to quote back to us, so
   it gets its own framed line and a monospaced face — the two things that make a
   code easy to read out over a phone. */
.tfb-ref {
    display: inline-block;
    margin-block: var(--s-5);
    padding: var(--s-3) var(--s-5);
    border: 1px dashed var(--c-line);
    border-radius: var(--r-md);
    background: var(--c-canvas);
}
.tfb-ref span { display: block; color: var(--c-muted); font-size: var(--fs-xs); letter-spacing: .08em; text-transform: uppercase; }
.tfb-ref strong { font-family: ui-monospace, "SFMono-Regular", "Cascadia Mono", Consolas, monospace; font-size: 1.25rem; letter-spacing: .08em; }
/* The booking, read back. Left-aligned inside a centred panel on purpose: a
   label/value list is read down the left edge, not from the middle. */
.tfb-recap { display: grid; gap: var(--s-2); max-width: 460px; margin-inline: auto; text-align: start; }
.tfb-recap > div { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-4); }
.tfb-recap dt { color: var(--c-muted); font-size: var(--fs-sm); }
.tfb-recap dd { font-weight: 600; text-align: end; unicode-bidi: plaintext; }
.tfb-recap code { font-family: ui-monospace, "SFMono-Regular", Consolas, monospace; }
.tfb-success__wa { max-width: 460px; margin-inline: auto; margin-block-start: var(--s-6); padding-block-start: var(--s-5); border-block-start: 1px solid var(--c-line-2); }
.tfb-success__wa p { margin-block-end: var(--s-3); color: var(--c-slate); font-size: var(--fs-sm); }
.tfb-success__wa .bk-wa { margin-block-start: 0; }

@media (max-width: 1000px) {
    .tfb-contact { grid-template-columns: 1fr; }
    .tfb-about { grid-template-columns: 1fr; gap: var(--s-6); }
    .tfb-about__aside { position: static; }
}

/* The planner and the hub table both carry a visually hidden label. */
.sr-only {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

@media (max-width: 1000px) {
    .trp--hero .trp-fields { grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); }
    .tfb-rcards { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 860px) {
    .trp--full { grid-template-columns: 1fr; }
    .trp--full .trp-results { position: static; }
}
@media (max-width: 620px) {
    .trp--hero .trp-fields,
    .trp--full .trp-fields { grid-template-columns: 1fr 1fr; }
    .trp--hero .trp-field--place,
    .trp--full .trp-field--place { grid-column: 1 / -1; }
    .trp-swap { display: none; }
    /* The thumbnail keeps its column, name and price share the second, and the
       button spans the row beneath them. */
    .trp-opt__row { grid-template-columns: auto 1fr auto; gap: var(--s-3); }
    .trp-opt__b { grid-column: 1 / -1; }
    .trp-opt__img { width: 64px; height: 46px; }
    .trp-more { margin-inline-start: calc(64px + var(--s-3)); }
    .trp-tiers { width: 100%; flex-wrap: nowrap; overflow-x: auto; padding-block-end: 2px; }
    .tfb-rcards { grid-template-columns: 1fr; }
    /* A two-up field row is two cramped fields on a phone. */
    .tfb-bform__row { grid-template-columns: 1fr; }
    .tr-journey__pair { grid-template-columns: 1fr; }
    .tr-journey__swap { justify-self: center; }
}

/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */
@media (max-width: 1000px) {
    .tfb-hero h1 { max-width: 20ch; }
    .tfb-faq { grid-template-columns: 1fr; gap: var(--s-4); }
    .tfb-faq__aside { position: static; }
}

@media (max-width: 860px) {
    .tfb-burger { display: block; order: 3; margin-inline-start: auto; }
    .tfb-head__actions { order: 2; margin-inline-start: auto; }
    .tfb-nav {
        order: 5;
        flex-basis: 100%;
        margin-inline-start: 0;
        display: none;
        padding-block-end: var(--s-4);
        border-block-start: 1px solid rgba(255, 255, 255, .12);
    }
    .tfb-nav.open { display: block; }
    .tfb-head__bar { flex-wrap: wrap; }
    .tfb-nav__list { flex-direction: column; align-items: stretch; gap: 0; }
    .tfb-nav__list a { padding: var(--s-3); }
    /* ── Submenus in the burger panel: CLOSED until tapped ─────────────────
       This block used to force `display: block` on every dropdown and hide the
       caret, on the reasoning that a panel already showing everything needs no
       control to show it. In practice that put the entire tree — every hub and
       all of its children — on screen the moment the burger opened, so the
       reader had to scroll past a wall of links to reach the item they came
       for, and had no way to fold any of it away.

       Now each parent opens on its own tap, which is what the markup was built
       for all along: the checkbox and its caret label already exist, and
       main.js already closes siblings when one opens while leaving ancestors
       alone. Only this stylesheet was overriding them. */
    .tfb-nav .dropdown {
        display: none;
        position: static;
        margin-top: 0;
        border: 0;
        box-shadow: none;
        background: none;
        padding-inline-start: var(--s-4);
    }

    /* Neither hover nor focus opens one here. On a laptop narrow enough to get
       the burger, a pointer drifting across the list would otherwise expand
       sections the reader never asked for, and because the panel is stacked
       rather than floating, everything below would jump. The tap is the only
       way in. */
    .tfb-nav li.has-dropdown:hover > .dropdown,
    .tfb-nav li.has-dropdown:focus-within > .dropdown { display: none; }

    /* Specificity matters more than order here: the two rules above would
       otherwise win over the global :checked rule — focus lands INSIDE the li
       the moment the label is tapped, so :focus-within would slam shut the very
       menu that tap just opened. This selector carries one class more than
       they do. */
    .tfb-nav li.has-dropdown .submenu-toggle:checked ~ .dropdown { display: block; }

    /* The hub link, first in its section — the only way into /tours/ and its
       siblings now that the row above opens instead of navigating. */
    .tfb-nav .dropdown__self { display: block; }
    .tfb-nav .dropdown__self > a { font-weight: 600; }

    /* THE WHOLE ROW IS THE CONTROL, not the caret at the end of it. The caret
       stays as the affordance — something has to say the row expands — but the
       tap is handled on the row in tfb.js, so the arrow no longer has to be
       hit. `cursor: pointer` on the link too, because it is a link that does
       not navigate here and the I-beam would suggest otherwise. */
    .tfb-nav .menu-parent {
        display: flex;
        align-items: center;
        justify-content: space-between;
        width: 100%;
        cursor: pointer;
    }
    .tfb-nav .menu-parent > a { flex: 1 1 auto; cursor: pointer; }
    .tfb-nav .menu-caret {
        display: flex;
        align-items: center;
        align-self: stretch;
        padding-inline: var(--s-4);
        font-size: .85em;
        opacity: .85;
        /* The row owns the click; the caret must not swallow it and toggle the
           checkbox a second time, which would cancel the row's own toggle. */
        pointer-events: none;
    }
    /* Which way the arrow points is the only feedback that the tap registered. */
    .tfb-nav .menu-caret > [aria-hidden="true"] {
        display: inline-block;
        transition: transform .18s ease;
    }
    .tfb-nav .submenu-toggle:checked ~ .menu-parent .menu-caret > [aria-hidden="true"] {
        transform: rotate(180deg);
    }

    .tfb-nav .dropdown::before { content: none; }
}

@media (max-width: 520px) {
    .tfb-shell { padding-inline: var(--s-4); }
    .tfb-card__media { aspect-ratio: 16 / 9; }
    .tfb-hero__cta .tfb-btn { flex: 1 1 100%; }
    /* One card per row on a phone: the auto-fill track floor is 290px, which a
       360px viewport minus gutters cannot hold two of anyway. */
    .tfb-grid { grid-template-columns: 1fr; }
}

/* ══════════════════════════════════════════════════════════════════════════
   RAIL — the homepage product rows: four cards visible, the rest one arrow
   away, and every one of them in the HTML the whole time.

   WHY A SCROLL CONTAINER AND NOT PAGINATION. The requirement was four at a
   time AND indexable, and those pull against each other the moment you reach
   for `display:none` or a fetch-on-click. An overflow container satisfies
   both without a compromise: the cards past the fourth are laid out, painted
   and linked — they are simply further right. Google reads the lot.

   `grid-auto-columns` divides the visible width by four MINUS the three gaps
   between them, so four cards land flush with the shell on both edges and the
   fifth begins exactly at the fold. Change the divisor per breakpoint and the
   arrows keep working untouched: they scroll by clientWidth, whatever that is.

   The last breakpoint deliberately shows 1.15 cards rather than 1. The
   fifteen per cent of the next card is the only affordance a phone user gets
   that the row moves — arrows are too small to fight for at that width, and a
   row that looks like a single card looks like a single card. */

.tfb-railwrap { position: relative; }

.tfb-rail {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: calc((100% - (var(--s-4) * 3)) / 4);
    gap: var(--s-4);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    /* Room for the card's focus ring and shadow, which a flush overflow clips. */
    padding: 2px 2px 6px;
    margin: -2px -2px -6px;
    scrollbar-width: none;
}
.tfb-rail::-webkit-scrollbar { display: none; }

/* The same two rules .tfb-grid needs, for the same reason: the <li> is the
   track item and stretches, the card inside it does not inherit that. */
.tfb-rail > li { display: flex; scroll-snap-align: start; }
.tfb-rail > li > .tfb-card,
.tfb-rail > li > .tfb-entry { flex: 1 1 auto; }

/* Keyboard users scroll the rail with the arrow keys once it has focus, so it
   needs a visible focus ring of its own — it is an interactive region, not a
   passive list. */
.tfb-rail:focus-visible {
    outline: 2px solid var(--c-accent, #0a4d68);
    outline-offset: 4px;
    border-radius: var(--r-lg);
}

/* The arrows are the only part of the rail that has to advertise itself. A
   40px button with a #dde4ee hairline read as decoration — present, but not
   obviously the thing to press. These are 48px, ringed and filled in the brand
   blue, and they invert on hover, which is the same contract every other
   primary control on the site offers. */
.tfb-rail__nav {
    position: absolute;
    top: calc(50% - 24px);
    z-index: 2;
    display: grid;
    place-items: center;
    width: 48px;
    height: 48px;
    padding: 0;
    color: var(--c-accent);
    background: var(--c-bg);
    border: 2px solid var(--c-accent);
    border-radius: 999px;
    box-shadow: 0 4px 14px rgb(11 18 32 / .18);
    cursor: pointer;
    transition: background .15s ease, color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.tfb-rail__nav svg { width: 24px; height: 24px; stroke-width: 2.5; }
/* The icon is drawn with stroke-width on the path itself, which a shorthand on
   the <svg> does not reach; both are set so neither source has to be edited. */
.tfb-rail__nav svg path { stroke-width: 2.5; }
/* `display:grid` above beats the user-agent's `[hidden] { display: none }`,
   which is an unqualified type-less rule and loses to a class. Without this the
   arrows render on every rail including the ones with a single card, and the
   `hidden` attribute the JS sets does nothing visible — the state was right and
   the paint ignored it. Any component that sets `display` and also toggles
   `hidden` needs this line. */
.tfb-rail__nav[hidden] { display: none; }

.tfb-rail__nav:hover {
    background: var(--c-accent);
    color: var(--c-on-dark);
    box-shadow: 0 6px 18px rgb(22 104 227 / .34);
}
.tfb-rail__nav:active { transform: scale(.94); }
.tfb-rail__nav:focus-visible {
    outline: 3px solid var(--c-accent-050);
    outline-offset: 2px;
}

/* There is no disabled state any more. An arrow at the end of its travel is
   hidden outright — the JS sets `hidden` per button rather than greying one
   out — because a dimmed circle still reads as a control and still collects
   the click it is going to refuse. The styling that used to describe that
   state is gone with it rather than left behind to describe nothing. */

/* Half on the cards, half off — the overlap is what tells you the row
   continues underneath. */
.tfb-rail__nav--prev { inset-inline-start: -24px; }
.tfb-rail__nav--next { inset-inline-end: -24px; }
/* The icons are drawn pointing left and right; in Arabic and Hebrew the rail
   itself is mirrored by the browser, so the glyphs have to be mirrored too or
   "next" points back the way you came. */
[dir="rtl"] .tfb-rail__nav svg { transform: scaleX(-1); }

@media (max-width: 1080px) {
    .tfb-rail { grid-auto-columns: calc((100% - (var(--s-4) * 2)) / 3); }
    /* Below the widest breakpoint the shell gutter is narrower than the button,
       so a fully outside arrow would hang off the viewport. It moves inward and
       sits over the first and last card instead. */
    .tfb-rail__nav--prev { inset-inline-start: -12px; }
    .tfb-rail__nav--next { inset-inline-end: -12px; }
}
@media (max-width: 860px) {
    .tfb-rail { grid-auto-columns: calc((100% - var(--s-4)) / 2); }
}
@media (max-width: 620px) {
    .tfb-rail { grid-auto-columns: calc(100% / 1.15); }
    /* On a phone the row is swiped, not clicked. */
    .tfb-rail__nav { display: none; }
}
@media (prefers-reduced-motion: reduce) {
    .tfb-rail { scroll-behavior: auto; }
}

/* ══════════════════════════════════════════════════════════════════════════
   PRICE ON REQUEST — what a route page shows when the owner has not published
   a fare for that direction. Deliberately not styled as an apology: no muted
   grey, no empty-state illustration. It is a different way to buy, so it gets
   a real primary action. */

.tfb-onreq {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s-4);
    padding: var(--s-5, 1.25rem);
    background: var(--c-canvas);
    border: 1px solid var(--c-line);
    border-radius: var(--r-lg);
}
.tfb-onreq__lead { margin: 0; max-width: 62ch; color: var(--c-slate); }

/* WhatsApp green, darkened to 6.38:1 against white — the brand #25d366 is
   1.98 and unreadable. Same pair the blog CTA already uses, so the two
   buttons cannot drift apart. */
.tfb-btn--wa {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    background: #0e6b60;
    border-color: #0e6b60;
    color: #fff;
}
.tfb-btn--wa:hover { background: #0b574e; border-color: #0b574e; color: #fff; }
.tfb-btn__ico { flex: 0 0 auto; }

/* The catalogue card's corner when there is no figure to put in it. */
.tfb-rcard__price--ask { color: var(--c-slate); font-weight: 500; }

.tfb-table__ask { color: var(--c-slate); font-weight: 500; white-space: nowrap; }

/* ── Struck-through "was" price ──────────────────────────────────────────────
   One rule for both catalogues. The old figure is struck in red because the
   owner asked for red; the reference site (atitravel.az) uses grey for the same
   element, so if it ever reads as too loud, this colour is the only thing to
   change. The LIVE price keeps the accent — a discount claim is the one number
   on the page worth colouring, and colouring both leaves nothing to look at.

   Applies to: transfer route tables (.tfb-was / .tfb-now / .tfb-cut), the tour
   booking box (.tfb-bk__was) and the tour cards (.tfb-price__was). */
.tfb-was,
.tfb-bk__was,
.tfb-price__was {
    color: #dc2626;

    /* ── The rule is LIGHTER than the digits, on purpose ───────────────────
       It used to be drawn in `currentColor`, so a #dc2626 line crossed #dc2626
       numerals and the two fought: the strike is the loudest thing in the pair
       and the figure underneath is what has to be read. A lighter red still
       says "cancelled" — nothing else on the card is red — while letting the
       number through. Slightly thicker than before to stay visible at the
       paler tone. */
    --strike: #fca5a5;

    /* No blanket opacity any more. Dimming the whole element to soften the
       line dimmed the digits with it, which is the opposite of the point;
       the softening now lives in --strike alone. */
    /* A line drawn through light text costs legibility, and this figure has to
       be READ — it is half the comparison. The extra weight buys that back
       without needing more size. */
    font-weight: 600;

    /* ── The strike is DRAWN, not decorated ────────────────────────────────
       `text-decoration: line-through` is horizontal and cannot be tilted, so
       the rule is a pseudo-element instead. A drawn line also lets the
       thickness scale with the type, which the old fixed 1.5px did not: it
       looked heavy on the card and thin in the booking box now that the three
       struck figures are three different sizes. */
    text-decoration: none;
    position: relative;
    display: inline-block;
    /* Hugging the text makes the line's vertical position predictable; the
       rows around it align on the baseline, so this does not move anything. */
    line-height: 1.1;
}

.tfb-was::after,
.tfb-bk__was::after,
.tfb-price__was::after {
    content: "";
    position: absolute;
    /* Slight overhang past both digits — a rule that stops exactly at the
       glyph edges reads as an accident rather than a strike. Trimmed from
       .12em when the angle steepened: the steeper the line, the further its
       ends drift above and below the text, and a long overhang left them
       floating clear of the figure altogether. */
    left: -.06em;
    right: -.06em;
    top: 52%;
    /* Thicker again as the tone gets paler — at #fca5a5 a hairline simply
       stops registering, and a strike nobody notices is worse than none. */
    height: .1em;
    background: var(--strike, #fca5a5);
    border-radius: .05em;
    /* TWELVE degrees, on the owner's call — six read as almost level.
       The angle is fixed while the figures are not: "₼35" is about 45px wide
       and "₼490" about 60px, so the same rotation climbs proportionally more
       of the short one. Twelve is about as far as that can go before the line
       leaves the digits at the ends of the shortest figure; the shorter
       overhang above keeps it on the glyphs. */
    transform: translateY(-50%) rotate(-12deg);
    pointer-events: none;
}

/* Arabic and Hebrew read the other way, so the tilt mirrors with them —
   otherwise the line leans against the direction of reading. */
[dir="rtl"] .tfb-was::after,
[dir="rtl"] .tfb-bk__was::after,
[dir="rtl"] .tfb-price__was::after {
    transform: translateY(-50%) rotate(12deg);
}

/* ── How big the struck figure is ──────────────────────────────────────────
   All three used to sit at --fs-sm (.8125rem) regardless of what they were
   sitting next to, which made the tour booking box the worst case: .8125rem
   against a 1.7rem price, so the old figure rendered at 48% of the new one and
   read as a footnote rather than as the other half of a comparison.

   Sized per surface now, each a deliberate fraction of the price beside it.
   They stay clearly smaller — the reader must never have to work out which of
   the two numbers is the one they will be charged — but they are legible at a
   glance, which is the whole job. */

/* Card: 1.2rem against the 1.3rem price (92%). */
.tfb-price__was { font-size: 1.2rem; }

/* Tour booking box: 1.4rem against the 1.7rem amount (82%). */
.tfb-bk__was { font-size: 1.4rem; }

/* The fare table on a route page is the one case where both figures were the
   SAME size — .tfb-now inherited the cell and .tfb-was matched it — so growing
   only the struck one would have made the old price the larger of the pair.
   Both move, and the live fare keeps the lead. */
.tfb-was { margin-inline-end: .35rem; font-size: 1.05rem; white-space: nowrap; }
.tfb-now { font-size: 1.15rem; font-weight: 800; white-space: nowrap; }

/* ── Size no longer separates the two figures ──────────────────────────────
   At 82–92% the struck price is within a hair of the live one, so the whole
   job of telling them apart now rests on three things, and none of them may
   be weakened without putting the pair back in play:

     COLOUR   red against the card's accent blue and the booking box's ink
     WEIGHT   600 against 800
     THE RULE the diagonal itself

   This is as far as the struck figure can grow. Past it a reader has to stop
   and work out which number they will be charged, which is the one thing a
   price pair must never make them do. If more emphasis is wanted later it has
   to come from somewhere other than the type size. */
/* The saving badge. `.tfb-bk__save` is the tour booking box, which shipped in
   August wearing the blue accent; it is listed here so a tour and a transfer do
   not disagree about what a discount looks like on the same site. Red for both,
   to match the struck figure beside it. */
.tfb-cut,
.tfb-bk__save {
    display: inline-block;
    margin-inline-start: .35rem;
    padding: .05rem .35rem;
    border-radius: var(--r-sm, 4px);
    background: #fee2e2;
    color: #b91c1c;
    font-size: var(--fs-xs);
    font-weight: 700;
    white-space: nowrap;
}

/* ── The demand line ──────────────────────────────────────────────────────
   "7 travellers booked this tour in the last 7 days", entered daily by the
   sales desk. See app/Services/BookingCounts.php for when it is allowed to
   appear at all.

   On a card it reuses `.tfb-badge`'s corner and only repaints it: dark and
   neutral rather than the accent colour, because this is an observation and
   the "Best Seller" badge it replaces is a claim. It must not shout louder
   than the price — a card that looks like an advertisement gets skimmed past
   exactly like one.

   The width cap matters. This string is longer in German and Russian than in
   English ("%N% Buchungen in den letzten %D% Tagen"), and left to itself it
   runs the full width of the photo. Two short lines read; one long one is
   wallpaper. */
.tfb-badge--demand {
    max-width: calc(100% - var(--s-3) * 2);
    padding: .22rem .5rem;
    background: rgba(17, 24, 39, .82);
    color: #fff;
    font-size: calc(var(--fs-xs) * .95);
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: 0;
    white-space: normal;
    text-wrap: balance;
    backdrop-filter: blur(2px);
}

/* In the booking box it is a sentence, not a pill: it sits under the price
   where the visitor is already reading words, and a second coloured chip
   beside the struck-through figure would be two things competing in one
   corner. Muted green — present, not alarming. Scarcity styling (red, a
   clock, a countdown) is deliberately avoided: the number is real, and
   dressing a real number as an emergency is how it stops being believed. */
.tfb-bk__demand {
    margin-block-start: var(--s-2);
    margin-block-end: 0;
    font-size: var(--fs-sm);
    font-weight: 600;
    color: #15803d;
    line-height: 1.45;
}

/* On a route page it sits under the distance/time/price facts, on the dark
   page head — so the green that works on the tour card's white sidebar would
   be unreadable. Light with a translucent plate, the same shape the facts
   above it already have. */
.tfb-pagehead__demand {
    margin-block-start: var(--s-3);
    margin-block-end: 0;
    display: inline-block;
    padding: .3rem .7rem;
    border-radius: var(--r-pill, 999px);
    background: rgba(255, 255, 255, .14);
    color: #fff;
    font-size: var(--fs-sm);
    font-weight: 600;
    line-height: 1.4;
}
