/* ==========================================================================
   BOOKALLO — bkx, THE VISUAL SHELL
   A NEW namespace, built to the approved reference set, not a patch over the
   old one. Nothing in this file extends janet_home.css or bk_hero.css; the
   homepage stops loading both and is rebuilt out of these components.

   WHAT IS PRESERVED, AND WHY IT LOOKS LIKE INHERITANCE BUT IS NOT
   ---------------------------------------------------------------
   Every id and class the running product QUERIES survives, because the search,
   the fares, the hotel band and the attribution path are driven by name from
   janet_home.js, janet_deals_strip.js and operator/price_refresh.js. So the
   markup keeps `#jn-form`, `#jn-dest`, `#jn-out`, `#jn-back`, `#jn-pax`,
   `#jn-go`, `#jn-go-label`, `#jn-err`, `.jn-tab[data-mode]`, `#jn-shot` and its
   two children, `#jn-rows`, `#jn-deals`, `#jn-lowcost`, `#jn-hotels`,
   `#jn-freshness`, and the `data-dest` option list the price engine scans.
   Those are the PRODUCT. Everything around them - the layout, the material,
   the depth, the type, the light - is new.

   WHERE THE REFERENCE AND THE TRUTH RULE DISAGREE
   -----------------------------------------------
   The references print "10M+ Happy Travelers", "4.9 Average Rating", "120+
   Destinations", and fares for Santorini, the Maldives and Bali. This product
   holds none of those: no review corpus, no traveller count, and ten
   destinations with measured fares to European cities. Printing them would be
   the exact failure this codebase has a rule against, and the brief that
   commissioned this work says FAKE_DATA=FORBIDDEN in the same breath as it
   names the references.

   So the reference is followed as a VISUAL system - the stat block's rhythm,
   its position, its weight - and filled with claims this site already stands
   behind, plus one number the build can count. The design is the reference's.
   The facts are ours.

   01 tokens          05 the rail          09 planner
   02 shell + nav     06 the globe         10 closing + footer
   03 hero scene      07 measured fares    11 responsive
   04 search console  08 hotels            12 reduced motion
   ========================================================================== */


/* == 01 · TOKENS ========================================================== */

:where(.bkx) {
  /* ---- Ground. Midnight, not grey: the references are lit scenes in a dark
     room, and a #14161A "dark UI" grey reads as a dashboard the moment a
     photograph sits next to it. ---- */
  --x-void:    #04070C;
  --x-deep:    #070B13;
  --x-raised:  #0C1119;
  --x-line:    rgba(240, 236, 226, .10);
  --x-line-2:  rgba(240, 236, 226, .18);

  /* ---- Champagne. Three steps: the light, the metal, the wash. ---- */
  --x-gold:      #E3BE79;
  --x-gold-deep: #C9A24A;
  --x-gold-wash: rgba(227, 190, 121, .12);
  --x-gold-edge: rgba(227, 190, 121, .42);
  --x-on-gold:   #10131A;   /* NEVER #fff on champagne - 1.6:1 */

  /* ---- Warm white. Cool white on a warm sunset frame reads as a screenshot
     of a different site pasted on top. ---- */
  --x-ink:   #F5F1E8;
  --x-ink-2: #C3C6CC;
  --x-ink-3: #8E939C;

  /* ---- Smoked glass. The console and every floating panel are the same
     material at three densities, so the product reads as one object family. ---- */
  --x-glass:   linear-gradient(157deg, rgba(14, 19, 28, .78), rgba(6, 9, 15, .88));
  --x-glass-2: linear-gradient(157deg, rgba(18, 24, 34, .86), rgba(8, 11, 18, .93));
  --x-blur: blur(22px) saturate(150%);

  /* ---- Depth. Shadows are long and soft; a tight shadow reads as a sticker. ---- */
  --x-e1: 0 2px 10px rgba(0, 0, 0, .5);
  --x-e2: 0 18px 44px -20px rgba(0, 0, 0, .86);
  --x-e3: 0 34px 80px -30px rgba(0, 0, 0, .94);
  --x-e4: 0 54px 120px -40px rgba(0, 0, 0, .98);
  --x-glow: 0 18px 50px -20px rgba(227, 190, 121, .40);

  --x-r:    16px;
  --x-r-lg: 22px;
  --x-r-pill: 999px;

  --x-ease:   cubic-bezier(.22, 1, .36, 1);
  --x-ease-2: cubic-bezier(.16, 1, .3, 1);

  /* ---- The frame. Wide, because the references are cinema: a 1180px column
     in a 2560px window is a 2013 website with a lot of unused screen. ---- */
  --x-max: min(1680px, 92vw);
  --x-gut: clamp(20px, 4vw, 64px);

  color: var(--x-ink);
  background: var(--x-void);
}


/* == 02 · SHELL + NAV ===================================================== */

html.bkx-html, body.bkx-body {
  background: var(--x-void);
  color: var(--x-ink);
}
body.bkx-body { margin: 0; overflow-x: hidden; }

.bkx a { color: inherit; }
.bkx img { display: block; max-inline-size: 100%; }
.bkx ::selection { background: var(--x-gold); color: var(--x-on-gold); }

/* Focus is one visible ring for the whole shell, and it is never removed. */
.bkx :focus-visible {
  outline: 2px solid var(--x-gold);
  outline-offset: 3px;
  border-radius: 4px;
}

.bkx-wrap { inline-size: var(--x-max); margin-inline: auto; }

/* --- nav ---------------------------------------------------------------
 * Transparent over the hero, and it takes on ground only once the page has
 * left it. The state is set by bkx.js from the same frame that drives the
 * scroll camera, so there is one authority for "where are we".
 */
.bkx-nav {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  gap: clamp(16px, 3vw, 44px);
  padding: clamp(14px, 1.6vw, 22px) var(--x-gut);
  transition: background-color .45s var(--x-ease), backdrop-filter .45s var(--x-ease),
              border-color .45s var(--x-ease), padding .45s var(--x-ease);
  border-block-end: 1px solid transparent;
}
.bkx-nav::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(4, 7, 12, .74), rgba(4, 7, 12, .16) 62%, transparent);
  transition: opacity .45s var(--x-ease);
}
.bkx-nav.is-solid {
  background: rgba(4, 7, 12, .86);
  -webkit-backdrop-filter: var(--x-blur);
  backdrop-filter: var(--x-blur);
  border-block-end-color: var(--x-line);
  padding-block: clamp(10px, 1.1vw, 14px);
}
.bkx-nav.is-solid::before { opacity: 0; }

.bkx-brand { display: flex; align-items: center; gap: .6rem; text-decoration: none; flex: none; }
.bkx-brand__mark {
  display: grid;
  place-items: center;
  inline-size: 34px; block-size: 34px;
  border-radius: 10px;
  background: linear-gradient(150deg, var(--x-gold), var(--x-gold-deep));
  color: var(--x-on-gold);
  font-weight: 700;
  font-size: 1.05rem;
  line-height: 1;
  box-shadow: var(--x-glow);
}
.bkx-brand__name {
  font-size: clamp(1rem, .9vw + .7rem, 1.25rem);
  letter-spacing: .18em;
  font-weight: 600;
  color: var(--x-ink);
}

.bkx-nav__links {
  display: flex;
  align-items: center;
  gap: clamp(14px, 1.8vw, 30px);
  margin-inline-end: auto;
  /* so the compact search can claim room instead of pushing the nav wider
     than the viewport once it appears */
  min-inline-size: 0;
}
.bkx-nav__links a {
  position: relative;
  font-size: .93rem;
  letter-spacing: .01em;
  color: var(--x-ink-2);
  text-decoration: none;
  padding-block: 6px;
  transition: color .25s var(--x-ease);
}
.bkx-nav__links a::after {
  content: "";
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 0;
  inline-size: 0;
  block-size: 1px;
  background: var(--x-gold);
  transition: inline-size .3s var(--x-ease);
}
.bkx-nav__links a:hover { color: var(--x-ink); }
.bkx-nav__links a:hover::after { inline-size: 100%; }

.bkx-nav__acts { display: flex; align-items: center; gap: 10px; flex: none; }
.bkx-icon {
  display: grid;
  place-items: center;
  inline-size: 38px; block-size: 38px;
  border-radius: var(--x-r-pill);
  border: 1px solid var(--x-line-2);
  background: rgba(255, 255, 255, .03);
  color: var(--x-ink-2);
  text-decoration: none;
  transition: border-color .25s var(--x-ease), color .25s var(--x-ease),
              background-color .25s var(--x-ease), transform .25s var(--x-ease);
}
.bkx-icon:hover { border-color: var(--x-gold-edge); color: var(--x-gold); transform: translateY(-1px); }
.bkx-icon svg { inline-size: 17px; block-size: 17px; }
.bkx-icon--el { padding-inline: 4px; inline-size: auto; gap: 8px; }
.bkx-icon--el img { inline-size: 26px; block-size: 26px; border-radius: 50%; }
.bkx-icon--el span { font-size: .84rem; padding-inline-end: 10px; }

.bkx-burger { display: none; }


/* == 03 · HERO SCENE ====================================================== */

/*
 * FIVE LAYERS, and each one is a real element at a real distance:
 *   sky      the graded horizon wash
 *   world    the destination photograph
 *   haze     atmosphere between the world and the interface
 *   ui       headline, console, stats
 *   float    the destination panel that sits in front of everything
 *
 * The camera is `--x-cam-*`, written once a frame by bkx.js from the pointer
 * and the scroll position, and INHERITED by the layers - so one write moves
 * the whole scene and every layer decides how much of it applies to itself.
 */
.bkx-hero {
  position: relative;
  min-block-size: 94svh;
  display: grid;
  place-items: center;
  isolation: isolate;
  overflow: hidden;
  --x-cam-x: 0;
  --x-cam-y: 0;
  --x-cam-z: 0;
}

.bkx-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  transform: translate3d(
    calc(var(--x-cam-x) * var(--x-depth, 0px)),
    calc(var(--x-cam-y) * var(--x-depth, 0px) + var(--x-scroll, 0px)),
    0) scale(var(--x-zoom, 1));
}
.bkx-layer--sky   { --x-depth: 6px;  z-index: 0; }
.bkx-layer--world { --x-depth: 16px; z-index: 1; }
.bkx-layer--haze  { --x-depth: 26px; z-index: 2; }

.bkx-hero__pic {
  position: absolute;
  inset: -6%;
  inline-size: 112%;
  block-size: 112%;
  /*
   * THE OVERSCAN WAS BEING CANCELLED, and the parallax then exposed the
   * ground behind it. Measured at 1440 on the English homepage: the picture
   * sat at left -86 (the 6% offset, correctly applied) and was 1440 wide
   * rather than 1612 — an 86px black band down the right edge of the hero.
   *
   * The base sheet publishes a global `img { max-inline-size: 100% }`, which
   * is right for every photograph in an article and wrong for the one image
   * on the page that is DELIBERATELY bigger than its frame so the camera has
   * somewhere to travel.
   */
  object-fit: cover;
  object-position: center 52%;
}
/*
 * Two classes, because `.bkx img { max-inline-size: 100% }` is two and a
 * single-class override loses to it wherever it sits in the file. That cap is
 * right for every photograph in an article and wrong for the one image on the
 * page that is deliberately bigger than its frame so the camera has somewhere
 * to travel.
 */
.bkx .bkx-hero__pic { max-inline-size: none; max-block-size: none; }

/* The grade. The reference frames are dark at the edges and lit in the middle,
   with the ground carrying the interface. Three gradients, each priced for what
   it does alone - stacked opaque scrims are how a photograph disappears. */
.bkx-hero__grade {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(4, 7, 12, .86) 0%, rgba(4, 7, 12, .34) 22%,
                            rgba(4, 7, 12, .52) 62%, rgba(4, 7, 12, .90) 100%),
    radial-gradient(112% 74% at 50% 40%, rgba(4, 7, 12, .06) 22%, rgba(4, 7, 12, .82) 100%);
}

/* Atmosphere: two very slow warm/cool lights, and a horizon sheen that crosses
   the frame once every twenty seconds. No canvas, no particles - a dust field
   behind a search box is a game. */
.bkx-hero__haze {
  position: absolute;
  inset: -10%;
  opacity: .8;
  background:
    radial-gradient(42% 46% at 26% 30%, rgba(240, 196, 128, .16), transparent 70%),
    radial-gradient(46% 42% at 78% 62%, rgba(120, 158, 208, .12), transparent 72%);
}
@keyframes bkx-haze { 0%,100% { translate: 0 0; scale: 1; } 50% { translate: 2.2% -1.4%; scale: 1.07; } }
html.js .bkx-hero__haze { animation: bkx-haze 28s cubic-bezier(.25,.1,.25,1) infinite; }

.bkx-hero__sheen {
  position: absolute;
  inset: 0;
  opacity: .5;
  background: linear-gradient(102deg, transparent 42%, rgba(255, 244, 222, .10) 50%, transparent 58%);
  background-size: 280% 100%;
}
@keyframes bkx-sheen { from { background-position: 160% 0; } to { background-position: -70% 0; } }
html.js .bkx-hero__sheen { animation: bkx-sheen 22s linear infinite; }

.bkx-hero__body {
  position: relative;
  z-index: 5;
  inline-size: var(--x-max);
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-block: clamp(88px, 11vh, 132px) clamp(26px, 4vh, 48px);
  transform: translate3d(0, var(--x-ui-y, 0px), 0) scale(var(--x-ui-s, 1));
  opacity: var(--x-ui-o, 1);
}

/* Full width; the MEASURE is capped on the lines that need one. */
.bkx-hero__say { inline-size: 100%; text-align: center; }

/* --- the clearance the side panels need -------------------------------- */
:where(.bkx) { --x-side: 238px; --x-side-gap: 26px; }
@media (min-width: 1280px) {
  /* Two class selectors, deliberately: the .bkx-console block below sets its
     own max-inline-size, and at equal specificity the later rule wins. This
     one has to hold wherever it sits in the file. */
  .bkx .bkx-hero__say,
  .bkx .bkx-console {
    max-inline-size: min(920px, calc(100vw - 2 * (var(--x-side) + var(--x-gut) + var(--x-side-gap))));
  }
}
.bkx-hero__eyebrow {
  display: block;
  font-size: .72rem;
  letter-spacing: .34em;
  text-transform: uppercase;
  color: var(--x-gold);
  margin-block-end: 1.1rem;
}
/*
 * The display face is Frank Ruhl Libre, which the page ALREADY loads for
 * Hebrew and which carries a full Latin serif. One font request for both
 * languages, and the same headline weight in each - a second display family
 * for English would be two brands.
 */
.bkx-h1 {
  font-family: "Frank Ruhl Libre", Georgia, "Times New Roman", serif;
  font-weight: 500;
  font-size: clamp(2.4rem, 4.4vw + .6rem, 5.2rem);
  line-height: 1.02;
  letter-spacing: -.02em;
  margin: 0 auto;
  max-inline-size: 18ch;
  text-wrap: balance;
  text-shadow: 0 4px 40px rgba(0, 0, 0, .7);
}
.bkx-h1 em {
  display: block;
  font-style: normal;
  color: var(--x-gold);
}
.bkx-hero__sub {
  margin: 1rem auto 0;
  max-inline-size: 46ch;
  font-size: clamp(.95rem, .4vw + .84rem, 1.08rem);
  line-height: 1.55;
  color: var(--x-ink-2);
  text-shadow: 0 2px 18px rgba(0, 0, 0, .8);
}

/* --- the floating destination panel ------------------------------------
 * This is #jn-shot: janet_home.js writes the city, the dates, the measured
 * fare and when it was observed into it, and sets its href. It is restyled,
 * never rebuilt, and it stays a real link to the search for that city.
 */
.bkx-float {
  position: absolute;
  z-index: 6;
  inset-block-start: 46%;
  inset-inline-end: var(--x-gut);
  inline-size: var(--x-side);
  border-radius: var(--x-r-lg);
  border: 1px solid var(--x-line-2);
  background: var(--x-glass-2);
  -webkit-backdrop-filter: var(--x-blur);
  backdrop-filter: var(--x-blur);
  box-shadow: var(--x-e3);
  overflow: hidden;
  text-decoration: none;
  transform: translate3d(calc(var(--x-cam-x) * 34px), calc(var(--x-cam-y) * 34px), 0);
  transition: border-color .3s var(--x-ease), box-shadow .3s var(--x-ease);
}
.bkx-float::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 16%;
  block-size: 1px;
  background: linear-gradient(90deg, transparent, var(--x-gold-edge), transparent);
}
.bkx-float:hover { border-color: var(--x-gold-edge); box-shadow: var(--x-e3), var(--x-glow); }
@keyframes bkx-float { 0%,100% { translate: 0 0; } 50% { translate: 0 -10px; } }
html.js .bkx-float { animation: bkx-float 9s cubic-bezier(.25,.1,.25,1) infinite; }

.bkx-float__pic { inline-size: 100%; block-size: 132px; object-fit: cover; }
.bkx-float__body { padding: .9rem 1.05rem 1rem; }
.bkx-float__where b { display: block; font-size: 1.08rem; font-weight: 600; line-height: 1.25; }
.bkx-float__where span { display: block; font-size: .78rem; color: var(--x-ink-3); margin-block-start: .1rem; }
.bkx-float__price {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: .6rem;
  margin-block-start: .7rem;
}
.bkx-float__price b {
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1;
  color: var(--x-gold);
  font-variant-numeric: tabular-nums;
}
.bkx-float__price span { font-size: .7rem; color: var(--x-ink-3); line-height: 1.35; text-align: start; }
.bkx-float__go {
  display: grid; place-items: center;
  inline-size: 34px; block-size: 34px;
  flex: none;
  border-radius: 50%;
  background: var(--x-gold);
  color: var(--x-on-gold);
}
.bkx-float__go svg { inline-size: 16px; block-size: 16px; }

/* --- the trust block ---------------------------------------------------
 * The reference's stat block, filled with facts rather than invented ones.
 * The count is written by the build from the destinations that actually have
 * a page; the other two are commitments this site already makes everywhere.
 */
.bkx-stats {
  position: absolute;
  z-index: 6;
  inset-block-start: 46%;
  inset-inline-start: var(--x-gut);
  display: grid;
  gap: clamp(14px, 2vh, 26px);
  margin: 0;
  padding: 0;
  list-style: none;
  /* Narrow on purpose. This block is three short claims, and giving it the
     fare panel's width would take the room the console needs. */
  max-inline-size: 176px;
}
.bkx-stats li { display: block; }
.bkx-stats b {
  display: block;
  font-family: "Frank Ruhl Libre", Georgia, serif;
  font-size: clamp(1.5rem, 1.4vw + 1rem, 2.1rem);
  font-weight: 500;
  line-height: 1.05;
  color: var(--x-ink);
}
.bkx-stats span {
  display: block;
  font-size: .78rem;
  line-height: 1.4;
  color: var(--x-ink-3);
  margin-block-start: .2rem;
}

/* --- scroll cue --------------------------------------------------------- */
.bkx-cue {
  position: absolute;
  z-index: 6;
  inset-block-end: clamp(18px, 3vh, 34px);
  inset-inline-start: 50%;
  translate: -50% 0;
  display: flex;
  align-items: center;
  gap: .6rem;
  font-size: .72rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--x-ink-3);
  background: none;
  border: 0;
  cursor: pointer;
}
.bkx-cue__ring {
  display: grid; place-items: center;
  inline-size: 30px; block-size: 30px;
  border-radius: 50%;
  border: 1px solid var(--x-line-2);
}
@keyframes bkx-cue { 0%,100% { transform: translateY(0); opacity: .6; } 50% { transform: translateY(4px); opacity: 1; } }
html.js .bkx-cue__ring svg { animation: bkx-cue 2.4s ease-in-out infinite; inline-size: 12px; block-size: 12px; }


/* == 04 · SEARCH CONSOLE ================================================== */

/*
 * The control deck. It is the largest object in the frame and the one thing
 * the page exists to be used through, so every effect here gets out of the way
 * the moment somebody touches it: the rest angle flattens on hover, on
 * focus-within and on every coarse pointer.
 */
.bkx-console {
  position: relative;
  z-index: 7;
  inline-size: 100%;
  max-inline-size: min(920px, 100%);
  margin-block-start: clamp(26px, 4vh, 46px);
  border-radius: var(--x-r-lg);
  border: 1px solid var(--x-line-2);
  background: var(--x-glass);
  -webkit-backdrop-filter: var(--x-blur);
  backdrop-filter: var(--x-blur);
  box-shadow: var(--x-e4), 0 0 0 1px rgba(227, 190, 121, .08);
  transform: perspective(1600px) rotateX(var(--x-deck, 5deg));
  transform-origin: 50% 100%;
  transition: transform .6s var(--x-ease-2), box-shadow .6s var(--x-ease-2);
}
html.js .bkx-console:hover,
html.js .bkx-console:focus-within { --x-deck: 0deg; }
@media (hover: none), (pointer: coarse) { .bkx-console { --x-deck: 0deg; } }

.bkx-console::before {
  content: "";
  position: absolute;
  inset-block-start: -1px;
  inset-inline: 15%;
  block-size: 1px;
  background: linear-gradient(90deg, transparent, rgba(227, 190, 121, .8), transparent);
}
/* The light it stands in. Clipped short - a full mirror image is a 2009 effect. */
.bkx-console::after {
  content: "";
  position: absolute;
  inset-block-start: 100%;
  inset-inline: 8%;
  block-size: 52px;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(227, 190, 121, .18), transparent 76%);
  filter: blur(10px);
}

/* --- tabs --------------------------------------------------------------- */
.bkx-tabs {
  position: relative;
  display: flex;
  gap: 2px;
  padding: 8px 8px 0;
  border-block-end: 1px solid var(--x-line);
  /*
   * The console has a 22px corner; the glide behind the active tab is a
   * square-shouldered box sitting flush against the top edge, so at the
   * leading corner it poked OUT of the panel and the selected tab read as a
   * chip stuck onto the outside of it. Clipping the tab row to the same
   * radius keeps the highlight inside the object it belongs to; the console
   * itself stays unclipped so its reflection below is not cut off.
   */
  border-radius: var(--x-r-lg) var(--x-r-lg) 0 0;
  overflow: hidden;
}
.bkx-tab {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .74rem 1.15rem;
  border: 0;
  background: none;
  color: var(--x-ink-3);
  font: inherit;
  font-size: .9rem;
  border-radius: 12px 12px 0 0;
  cursor: pointer;
  text-decoration: none;
  transition: color .28s var(--x-ease);
  min-block-size: 44px;
}
.bkx-tab svg { inline-size: 17px; block-size: 17px; transition: transform .28s var(--x-ease), filter .28s var(--x-ease); }
.bkx-tab:hover { color: var(--x-ink-2); }
.bkx-tab[aria-selected="true"] { color: var(--x-ink); }
.bkx-tab[aria-selected="true"] svg {
  color: var(--x-gold);
  transform: translateY(-1px) scale(1.06);
  filter: drop-shadow(0 0 8px rgba(227, 190, 121, .6));
}
/* One light that GLIDES between tabs, rather than a border that reappears. */
.bkx-tabs__glide {
  position: absolute;
  z-index: 0;
  inset-block: 8px 0;
  inset-inline-start: 0;
  inline-size: var(--x-tab-w, 0px);
  transform: translate3d(var(--x-tab-x, 0px), 0, 0);
  border-radius: 12px 12px 0 0;
  background: linear-gradient(180deg, rgba(227, 190, 121, .20), rgba(227, 190, 121, .04));
  box-shadow: inset 0 0 0 1px rgba(227, 190, 121, .24);
  opacity: var(--x-tab-o, 0);
  transition: transform .32s var(--x-ease), inline-size .32s var(--x-ease), opacity .2s linear;
  pointer-events: none;
}

/* --- fields ------------------------------------------------------------- */
/* Not five equal columns. A dd/mm/yyyy control needs about 130px of usable
   width and clipped to "/mm/yyyy" at an even fifth, and the passengers cell is
   two words, so it can give room back.

   The origin cell used to be listed here as "a fixed string" and took the
   narrowest column on the deck. It is a searchable field over 3,787 airports
   now, so it takes the same width as the destination: a city typed into a
   column sized for "TLV" is ellipsised while it is being typed. */
.bkx-form {
  display: grid;
  grid-template-columns:
    minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.2fr) minmax(0, 1.2fr) minmax(0, .8fr) auto;
  align-items: stretch;
}
.bkx-field {
  position: relative;
  display: block;
  padding: .5rem .85rem .45rem;
  border-inline-start: 1px solid var(--x-line);
  transition: background-color .28s var(--x-ease), box-shadow .28s var(--x-ease);
  min-inline-size: 0;
}
.bkx-field:first-child { border-inline-start: 0; }
.bkx-field:focus-within { background: rgba(227, 190, 121, .05); box-shadow: inset 0 -2px 0 var(--x-gold); }
.bkx-field > span {
  display: block;
  font-size: .65rem;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--x-ink-3);
  margin-block-end: .3rem;
}
.bkx-field input,
.bkx-field select {
  /*
   * 50px, for a 44px TARGET, and the difference is the console's rest angle.
   *
   * The deck sits at rotateX(5deg), which foreshortens everything standing on
   * it: a control computing 46px measured 42px on screen, and the touch-target
   * sweep measures the RENDERED box - which is the one a thumb lands on. So the
   * height is chosen against the transform rather than against the number in
   * the specification: 50 * (42/46) = 45.6.
   *
   * border-box as well, because the base sheet sizes form controls on the
   * content box and a 44px minimum came out 40 once its own padding was
   * subtracted. Two separate reasons, both measured, neither visible in the
   * declared value.
   *
   * The alternative was to flatten the deck, which is the one thing about this
   * hero the reference is most specific about.
   */
  box-sizing: border-box;
  inline-size: 100%;
  border: 0;
  background: none;
  color: var(--x-ink);
  font: inherit;
  font-size: .98rem;
  padding: 0;
  min-block-size: 50px;
}
.bkx-field select { appearance: none; cursor: pointer; }
.bkx-field input::placeholder { color: var(--x-ink-3); }
.bkx-field input[type="date"]::-webkit-calendar-picker-indicator { filter: invert(.8) sepia(1) saturate(2) hue-rotate(2deg); cursor: pointer; }
.bkx-field option { background: var(--x-raised); color: var(--x-ink); }

.bkx-go {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .55rem;
  margin: 8px;
  padding-inline: clamp(1.2rem, 2vw, 2rem);
  min-block-size: 52px;
  border: 0;
  border-radius: 14px;
  background: linear-gradient(160deg, var(--x-gold), var(--x-gold-deep));
  color: var(--x-on-gold);
  font: inherit;
  font-weight: 700;
  font-size: .98rem;
  cursor: pointer;
  box-shadow: var(--x-glow);
  transition: transform .2s var(--x-ease), box-shadow .2s var(--x-ease), filter .2s var(--x-ease);
  white-space: nowrap;
}
.bkx-go:hover { transform: translateY(-2px); box-shadow: 0 22px 60px -20px rgba(227, 190, 121, .6); filter: brightness(1.04); }
.bkx-go:active { transform: translateY(1px) scale(.99); }
.bkx-go svg { inline-size: 17px; block-size: 17px; }

.bkx-err {
  grid-column: 1 / -1;
  margin: 0;
  padding: 0 1.1rem .7rem;
  color: #FFB4A2;
  font-size: .85rem;
  min-block-size: 0;
}
.bkx-err:empty { display: none; }
#jf-hint { color: var(--x-ink-3); }

/* --- the compact form of the same object -------------------------------- */
.bkx-sticky {
  /* A CHILD OF THE HEADER. See the mount comment in bkx.js: as a
     position:fixed overlay this pill printed itself on top of the globe, the
     coverflow and the planner, which is the "floating controls detached /
     debug-like" P0 verbatim. In the flow of the nav it can only ever sit
     beside the links, so there is nothing left for it to cover. */
  display: flex;
  align-items: center;
  flex: 0 1 auto;
  min-inline-size: 0;
  pointer-events: none;
  transform: translate3d(0, -6px, 0);
  opacity: 0;
  transition: transform .4s var(--x-ease), opacity .28s linear;
}
.bkx-sticky.is-on { transform: none; opacity: 1; }
.bkx-sticky[hidden] { display: none; }
.bkx-sticky__btn {
  pointer-events: auto;
  /* Sized to its CONTENT. Before the reader has chosen anything the bar holds
     four words, and a fixed 760px pill around them reads as an empty search
     field somebody left floating over the page rather than as a compact
     control. It grows as the summary does. */
  inline-size: auto;
  max-inline-size: min(360px, 30vw);
  min-block-size: 44px;
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: .55rem 1rem;
  border-radius: var(--x-r-pill);
  border: 1px solid var(--x-line-2);
  background: rgba(8, 11, 18, .92);
  -webkit-backdrop-filter: var(--x-blur);
  backdrop-filter: var(--x-blur);
  box-shadow: var(--x-e2);
  color: var(--x-ink);
  font: inherit;
  font-size: .92rem;
  text-align: start;
  cursor: pointer;
}
.bkx-sticky__btn:hover { border-color: var(--x-gold-edge); }
.bkx-sticky__ico {
  display: grid; place-items: center;
  inline-size: 32px; block-size: 32px; flex: none;
  border-radius: 50%;
  background: var(--x-gold);
  color: var(--x-on-gold);
}
.bkx-sticky__ico svg { inline-size: 16px; block-size: 16px; }
.bkx-sticky__vals { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }


/* == SCENES · shared frame ================================================ */

.bkx-scene {
  position: relative;
  padding-block: clamp(56px, 7vh, 104px);
  isolation: isolate;
}
.bkx-scene--tight { padding-block: clamp(48px, 6vh, 90px); }

/* The ground between scenes is never flat black: a long soft wash keeps the
   page reading as one continuous room rather than stacked panels. */
.bkx-scene::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(80% 60% at 50% 0%, rgba(18, 26, 40, .55), transparent 70%);
}

.bkx-head { inline-size: var(--x-max); margin-inline: auto; margin-block-end: clamp(26px, 4vh, 48px); }
.bkx-head--row { display: flex; align-items: flex-end; justify-content: space-between; gap: 2rem; flex-wrap: wrap; }
.bkx-h2 {
  font-family: "Frank Ruhl Libre", Georgia, serif;
  font-weight: 500;
  font-size: clamp(1.75rem, 2.3vw + .6rem, 3.1rem);
  line-height: 1.06;
  letter-spacing: -.018em;
  margin: 0;
}
.bkx-h2 em { font-style: normal; color: var(--x-gold); }
.bkx-lede { margin: .6rem 0 0; color: var(--x-ink-3); font-size: clamp(.9rem, .4vw + .8rem, 1.02rem); max-inline-size: 60ch; }

.bkx-arrows { display: flex; gap: 10px; flex: none; }
.bkx-arrow {
  display: grid; place-items: center;
  inline-size: 44px; block-size: 44px;
  border-radius: 50%;
  border: 1px solid var(--x-line-2);
  background: rgba(255, 255, 255, .03);
  color: var(--x-ink-2);
  cursor: pointer;
  transition: transform .25s var(--x-ease), border-color .25s var(--x-ease), color .25s var(--x-ease);
}
.bkx-arrow:hover { border-color: var(--x-gold-edge); color: var(--x-gold); transform: translateY(-2px); }
.bkx-arrow:active { transform: translateY(1px) scale(.96); }
.bkx-arrow svg { inline-size: 18px; block-size: 18px; }


/* == 05 · THE 3D RAIL ===================================================== */

/*
 * A curved rail, not a slider. The scroller stays a scroller - momentum,
 * two-finger swipe, Home/End, the scrollbar and back-restore all keep working -
 * and every card is placed on the curve from ONE number: its signed distance
 * from the centre of the viewport, written per frame by bkx.js.
 *
 * The rotation is deliberately large (up to 34deg) because the brief is
 * explicit that a 2-degree tilt is not 3D. At this angle the neighbours read
 * as physically turned away, which is what the reference shows.
 */
.bkx-rail {
  position: relative;
  perspective: 1500px;
  perspective-origin: 50% 46%;
}
.bkx-rail__track {
  display: flex;
  gap: clamp(14px, 1.6vw, 26px);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding-block: clamp(22px, 3vh, 40px);
  padding-inline: calc(50% - min(150px, 31vw));
  scrollbar-width: none;
  transform-style: preserve-3d;
}
.bkx-rail__track::-webkit-scrollbar { display: none; }

.bkx-card {
  --d: 0;    /* signed distance from centre, -1.6..1.6 */
  --ad: 0;   /* its absolute value                      */
  position: relative;
  flex: 0 0 auto;
  inline-size: min(300px, 62vw);
  aspect-ratio: 3 / 4.1;
  border-radius: var(--x-r-lg);
  overflow: hidden;
  scroll-snap-align: center;
  text-decoration: none;
  transform-origin: 50% 62%;
  transform:
    translate3d(0, calc(var(--ad) * 16px), calc(var(--ad) * -190px))
    rotateY(calc(var(--d) * -34deg))
    scale(calc(1 - var(--ad) * .04));
  transition: transform .16s linear, box-shadow .3s var(--x-ease), border-color .3s var(--x-ease);
  border: 1px solid var(--x-line);
  background: var(--x-raised);
  box-shadow: var(--x-e2);
}
.bkx-card__pic {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  transition: transform .6s var(--x-ease), filter .4s var(--x-ease);
  filter: brightness(calc(1 - var(--ad) * .30)) saturate(calc(1 - var(--ad) * .26));
}
.bkx-card:hover .bkx-card__pic { transform: scale(1.05); }
.bkx-card__veil {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(4, 7, 12, .12) 0%, rgba(4, 7, 12, .05) 40%, rgba(4, 7, 12, .90) 100%);
}
.bkx-card__body { position: absolute; inset-block-end: 0; inset-inline: 0; padding: 1.1rem 1.15rem 1.25rem; }
.bkx-card__where { display: block; font-size: 1.16rem; font-weight: 600; line-height: 1.2; }
.bkx-card__country { display: block; font-size: .78rem; color: var(--x-ink-2); margin-block-start: .1rem; }
.bkx-card__from { display: block; font-size: .68rem; letter-spacing: .14em; text-transform: uppercase; color: var(--x-ink-3); margin-block-start: .7rem; }
.bkx-card__price { display: block; font-size: 1.45rem; font-weight: 700; color: var(--x-gold); line-height: 1.1; font-variant-numeric: tabular-nums; }
.bkx-card__note { display: block; font-size: .68rem; color: var(--x-ink-3); margin-block-start: .25rem; line-height: 1.4; }

/* The card at the centre is the primary object: upright, forward, lit, and
   given the champagne edge so it reads as CHOSEN rather than merely nearest. */
.bkx-card[data-centre] {
  z-index: 3;
  border-color: var(--x-gold-edge);
  box-shadow: var(--x-e3), 0 0 0 1px rgba(227, 190, 121, .34), var(--x-glow);
}
.bkx-card[data-centre] .bkx-card__pic { filter: none; }

/* The platform the rail stands on, and its reflection. */
.bkx-rail__floor {
  position: absolute;
  inset-block-end: 8%;
  inset-inline-start: 50%;
  translate: -50% 0;
  inline-size: min(1100px, 88vw);
  block-size: 42%;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(58% 52% at 50% 100%, rgba(227, 190, 121, .22), rgba(227, 190, 121, .04) 46%, transparent 74%);
}

.bkx-dots { display: flex; justify-content: center; gap: 8px; margin-block-start: clamp(12px, 2vh, 22px); }
/* The deck's control row: prev, the dots the engine writes, next — one group,
   centred under the deck it drives. Inside this row the dots carry no top
   margin of their own; the row owns the spacing. */
.bkx-railctl {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(12px, 1.6vw, 24px);
  margin-block-start: clamp(16px, 2.2vh, 28px);
}
.bkx-railctl .bkx-dots { margin-block-start: 0; }
.bkx-dots button {
  inline-size: 7px; block-size: 7px; padding: 0;
  border: 0; border-radius: 50%;
  background: var(--x-line-2);
  cursor: pointer;
  transition: inline-size .3s var(--x-ease), background-color .3s var(--x-ease);
}
.bkx-dots button[aria-current="true"] { inline-size: 26px; border-radius: 4px; background: var(--x-gold); }


/* == 06 · THE GLOBE ======================================================= */

.bkx-globe {
  position: relative;
  inline-size: var(--x-max);
  margin-inline: auto;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) minmax(0, 300px);
  gap: clamp(18px, 3vw, 44px);
  align-items: center;
}
.bkx-globe__rail { display: grid; gap: 6px; align-content: center; }
.bkx-globe__rail a {
  display: flex;
  align-items: center;
  gap: .7rem;
  padding: .6rem .9rem;
  border-radius: var(--x-r-pill);
  border: 1px solid transparent;
  color: var(--x-ink-3);
  text-decoration: none;
  font-size: .88rem;
  white-space: nowrap;
  transition: color .25s var(--x-ease), border-color .25s var(--x-ease), background-color .25s var(--x-ease);
}
.bkx-globe__rail a:hover { color: var(--x-ink); border-color: var(--x-line-2); background: rgba(255,255,255,.03); }
.bkx-globe__rail svg { inline-size: 17px; block-size: 17px; color: var(--x-gold); flex: none; }

.bkx-globe__stage {
  position: relative;
  aspect-ratio: 1 / 1;
  max-block-size: min(66vh, 620px);
  margin-inline: auto;
  inline-size: 100%;
}
.bkx-globe__stage canvas { display: block; inline-size: 100%; block-size: 100%; cursor: grab; }
.bkx-globe__stage.is-dragging canvas { cursor: grabbing; }
/* The atmosphere behind it, in CSS, so the scene has a halo before the
   texture has loaded and still has one if WebGL never starts. */
.bkx-globe__stage::before {
  content: "";
  position: absolute;
  inset: 6%;
  border-radius: 50%;
  z-index: -1;
  background: radial-gradient(circle at 50% 50%, rgba(70, 120, 190, .20), rgba(70, 120, 190, .05) 58%, transparent 72%);
  filter: blur(18px);
}

/* The fallback. Not a grey box and not an apology - a real, lit picture of
   the world with the same routes drawn on it, so a machine with no WebGL gets
   a scene rather than a hole. */
.bkx-globe__fallback {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background:
    radial-gradient(circle at 38% 32%, rgba(58, 96, 150, .55), transparent 58%),
    radial-gradient(circle at 50% 50%, #0B1A2E 0%, #060C16 62%, transparent 72%);
  box-shadow: inset 0 0 90px rgba(0, 0, 0, .8), 0 0 90px -30px rgba(70, 120, 190, .5);
}
.bkx-globe__fallback::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background:
    radial-gradient(2px 2px at 30% 44%, var(--x-gold), transparent 60%),
    radial-gradient(2px 2px at 58% 36%, var(--x-gold), transparent 60%),
    radial-gradient(2px 2px at 66% 58%, var(--x-gold), transparent 60%),
    radial-gradient(3px 3px at 47% 52%, #FFF0CE, transparent 60%);
}

.bkx-globe__panel {
  border-radius: var(--x-r-lg);
  border: 1px solid var(--x-line-2);
  background: var(--x-glass-2);
  -webkit-backdrop-filter: var(--x-blur);
  backdrop-filter: var(--x-blur);
  box-shadow: var(--x-e3);
  overflow: hidden;
}
.bkx-globe__panel img { inline-size: 100%; block-size: 150px; object-fit: cover; }
.bkx-globe__panel-body { padding: 1rem 1.1rem 1.15rem; }
.bkx-globe__panel h3 { margin: 0; font-size: 1.15rem; font-weight: 600; }
.bkx-globe__panel p { margin: .15rem 0 0; font-size: .8rem; color: var(--x-ink-3); }
.bkx-globe__panel .bkx-price { display: block; margin-block-start: .7rem; font-size: 1.4rem; font-weight: 700; color: var(--x-gold); font-variant-numeric: tabular-nums; }
.bkx-globe__panel .bkx-note { display: block; font-size: .7rem; color: var(--x-ink-3); margin-block-start: .2rem; }
.bkx-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  margin-block-start: .9rem;
  inline-size: 100%;
  min-block-size: 44px;
  border-radius: var(--x-r-pill);
  background: linear-gradient(160deg, var(--x-gold), var(--x-gold-deep));
  color: var(--x-on-gold);
  font-weight: 700;
  font-size: .92rem;
  text-decoration: none;
  border: 0;
  cursor: pointer;
  transition: transform .2s var(--x-ease), box-shadow .2s var(--x-ease);
}
.bkx-cta:hover { transform: translateY(-2px); box-shadow: var(--x-glow); }
.bkx-cta--ghost {
  background: none;
  color: var(--x-ink);
  border: 1px solid var(--x-line-2);
}
.bkx-cta--ghost:hover { border-color: var(--x-gold-edge); color: var(--x-gold); box-shadow: none; }


/* == 07 · MEASURED FARES ================================================== */

.bkx-fares { inline-size: var(--x-max); margin-inline: auto; }
.bkx-freshness {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  margin: 0 0 1.4rem;
  padding: .45rem .9rem;
  border-radius: var(--x-r-pill);
  border: 1px solid var(--x-line);
  background: rgba(255, 255, 255, .03);
  font-size: .8rem;
  color: var(--x-ink-2);
}
.bkx-freshness svg { inline-size: 15px; block-size: 15px; color: var(--x-gold); }

/* Each fare is a layered panel, not a table row: a hairline, a photograph, the
   city, the window, the figure and the observation that produced it. */
.bkx-fare {
  display: grid;
  grid-template-columns: 64px minmax(0, 1.2fr) minmax(0, 1fr) auto auto;
  align-items: center;
  gap: clamp(10px, 1.4vw, 22px);
  padding: .8rem 1rem;
  border-radius: var(--x-r);
  border: 1px solid var(--x-line);
  background: linear-gradient(140deg, rgba(16, 22, 32, .7), rgba(7, 11, 18, .82));
  text-decoration: none;
  transition: transform .3s var(--x-ease), border-color .3s var(--x-ease), box-shadow .3s var(--x-ease);
}
.bkx-fare + .bkx-fare { margin-block-start: 10px; }
.bkx-fare:hover {
  transform: translateY(-2px);
  border-color: var(--x-gold-edge);
  box-shadow: var(--x-e2);
}
.bkx-fare__pic { inline-size: 64px; block-size: 64px; border-radius: 12px; object-fit: cover; }
.bkx-fare__where b { display: block; font-size: 1.02rem; font-weight: 600; }
.bkx-fare__where span { display: block; font-size: .78rem; color: var(--x-ink-3); }
.bkx-fare__when b { display: block; font-size: .9rem; font-variant-numeric: tabular-nums; }
.bkx-fare__when small { display: block; font-size: .7rem; color: var(--x-ink-3); }
.bkx-fare__price { text-align: end; }
.bkx-fare__price b { font-size: 1.3rem; font-weight: 700; color: var(--x-gold); font-variant-numeric: tabular-nums; }
.bkx-fare__price span { display: block; font-size: .72rem; color: var(--x-ink-3); }
.bkx-fare__go { color: var(--x-ink-3); }


/* == 08 · HOTELS ========================================================== */

.bkx-hotels { inline-size: var(--x-max); margin-inline: auto; }
.bkx-hotels__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr));
  gap: clamp(14px, 1.6vw, 22px);
}
.bkx-hotel {
  position: relative;
  display: block;
  border-radius: var(--x-r-lg);
  overflow: hidden;
  aspect-ratio: 3 / 4;
  border: 1px solid var(--x-line);
  text-decoration: none;
  background: var(--x-raised);
  transition: transform .4s var(--x-ease), border-color .3s var(--x-ease), box-shadow .4s var(--x-ease);
}
.bkx-hotel:hover { transform: translateY(-8px); border-color: var(--x-gold-edge); box-shadow: var(--x-e3); }
.bkx-hotel img { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; object-fit: cover; transition: transform .7s var(--x-ease); }
.bkx-hotel:hover img { transform: scale(1.06); }
.bkx-hotel__veil { position: absolute; inset: 0; background: linear-gradient(180deg, transparent 34%, rgba(4, 7, 12, .92) 100%); }
.bkx-hotel__body { position: absolute; inset-block-end: 0; inset-inline: 0; padding: 1rem 1.1rem 1.15rem; }


/* == 09 · PLANNER ========================================================= */

.bkx-plan {
  inline-size: var(--x-max);
  margin-inline: auto;
  display: grid;
  grid-template-columns: minmax(0, 200px) minmax(0, 1fr) minmax(0, 320px);
  gap: clamp(18px, 2.6vw, 40px);
  align-items: center;
}
.bkx-steps { display: grid; gap: 4px; margin: 0; padding: 0; list-style: none; counter-reset: bkx-step; }
.bkx-steps li {
  display: flex;
  align-items: center;
  gap: .8rem;
  padding: .6rem .5rem;
  color: var(--x-ink-3);
  font-size: .92rem;
  transition: color .5s var(--x-ease);
}
.bkx-steps li::before {
  counter-increment: bkx-step;
  content: counter(bkx-step);
  display: grid; place-items: center;
  inline-size: 30px; block-size: 30px; flex: none;
  border-radius: 50%;
  border: 1px solid var(--x-line-2);
  font-size: .8rem;
  font-variant-numeric: tabular-nums;
  transition: background-color .5s var(--x-ease), color .5s var(--x-ease), border-color .5s var(--x-ease);
}
.bkx-steps li.is-on { color: var(--x-ink); }
.bkx-steps li.is-on::before {
  background: linear-gradient(160deg, var(--x-gold), var(--x-gold-deep));
  color: var(--x-on-gold);
  border-color: transparent;
}

.bkx-plan__stage { position: relative; aspect-ratio: 16 / 11; border-radius: var(--x-r-lg); overflow: hidden; border: 1px solid var(--x-line); }
.bkx-plan__stage img { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; object-fit: cover; }
.bkx-plan__stage::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(4,7,12,.32), rgba(4,7,12,.72)); }

/* The markers the trip assembles out of. Each one appears when its step does,
   and each one carries a REAL figure or no figure at all. */
.bkx-pin {
  position: absolute;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .5rem .75rem;
  border-radius: var(--x-r-pill);
  border: 1px solid var(--x-line-2);
  background: rgba(8, 11, 18, .86);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  box-shadow: var(--x-e2);
  font-size: .84rem;
  opacity: 0;
  transform: translate3d(0, 10px, 0) scale(.94);
  transition: opacity .55s var(--x-ease), transform .55s var(--x-ease);
}
.bkx-pin.is-on { opacity: 1; transform: none; }
.bkx-pin svg { inline-size: 15px; block-size: 15px; color: var(--x-gold); }
.bkx-pin b { color: var(--x-gold); font-variant-numeric: tabular-nums; }

.bkx-plan__card {
  border-radius: var(--x-r-lg);
  border: 1px solid var(--x-line-2);
  background: var(--x-glass-2);
  -webkit-backdrop-filter: var(--x-blur);
  backdrop-filter: var(--x-blur);
  box-shadow: var(--x-e3);
  padding: 1.2rem 1.25rem 1.35rem;
}
.bkx-plan__card h3 { margin: 0 0 .1rem; font-size: 1.1rem; font-weight: 600; }
.bkx-plan__card > p { margin: 0 0 1rem; font-size: .82rem; color: var(--x-ink-3); }
.bkx-ledger { margin: 0; display: grid; gap: .5rem; }
.bkx-ledger div { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; font-size: .88rem; }
.bkx-ledger dt { color: var(--x-ink-2); margin: 0; }
.bkx-ledger dd { margin: 0; font-variant-numeric: tabular-nums; }
.bkx-ledger dd.is-empty { color: var(--x-ink-3); font-size: .8rem; }
.bkx-meter { block-size: 3px; border-radius: 2px; background: var(--x-line); margin-block: 1rem .3rem; overflow: hidden; }
.bkx-meter i { display: block; block-size: 100%; inline-size: var(--x-meter, 0%); background: linear-gradient(90deg, var(--x-gold-deep), var(--x-gold)); transition: inline-size 1.1s var(--x-ease); }


/* == 10 · CLOSING + FOOTER ================================================ */

.bkx-closing {
  position: relative;
  min-block-size: 76vh;
  display: grid;
  place-items: center;
  text-align: center;
  overflow: hidden;
  isolation: isolate;
}
.bkx-closing img { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; object-fit: cover; z-index: -2; }
.bkx-closing::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(90% 70% at 50% 50%, rgba(4, 7, 12, .45), rgba(4, 7, 12, .96) 78%);
}
.bkx-closing__mark { display: grid; justify-items: center; gap: .5rem; margin-block-start: 2rem; }
.bkx-closing__mark span { font-size: .68rem; letter-spacing: .38em; text-transform: uppercase; color: var(--x-gold); }

.bkx-foot { border-block-start: 1px solid var(--x-line); background: var(--x-deep); }
.bkx-foot__in {
  inline-size: var(--x-max);
  margin-inline: auto;
  padding-block: clamp(40px, 6vh, 72px);
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) repeat(3, minmax(0, 1fr));
  gap: clamp(20px, 3vw, 48px);
}
.bkx-foot__h { margin: 0 0 .8rem; font-size: .72rem; letter-spacing: .2em; text-transform: uppercase; color: var(--x-ink-3); }
.bkx-foot ul { margin: 0; padding: 0; list-style: none; display: grid; gap: .5rem; }
.bkx-foot a { color: var(--x-ink-2); text-decoration: none; font-size: .9rem; transition: color .25s var(--x-ease); }
.bkx-foot a:hover { color: var(--x-gold); }
.bkx-foot__legal {
  inline-size: var(--x-max);
  margin-inline: auto;
  padding-block: 1.2rem 2rem;
  border-block-start: 1px solid var(--x-line);
  font-size: .78rem;
  color: var(--x-ink-3);
  display: flex; flex-wrap: wrap; gap: .8rem 1.6rem; align-items: center; justify-content: space-between;
}


/* == RENDERER MARKUP ======================================================
 *
 * `janet_deals_strip.js` and `janet_home.js` emit their own class names, and
 * they must NOT have to learn a second vocabulary to be styled — a renderer
 * that has to know about the shell is a renderer that breaks the next time the
 * shell changes. So the shell dresses what they already write.
 *
 * Everything below is scoped under `.bkx`, so the same renderers keep their
 * old appearance on any page still running the previous system.
 */

/* --- a fare card on the rail (#jn-deals, #jn-lowcost) ------------------- */
.bkx .jn-deals__track {
  display: flex;
  gap: clamp(14px, 1.6vw, 26px);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding-block: clamp(22px, 3vh, 40px);
  padding-inline: calc(50% - min(144px, 31vw));
  scrollbar-width: none;
}
.bkx .jn-deals__track::-webkit-scrollbar { display: none; }

.bkx .jn-deal {
  position: relative;
  flex: 0 0 auto;
  inline-size: min(288px, 62vw);
  min-block-size: 340px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 1.1rem 1.15rem 1.25rem;
  border-radius: var(--x-r-lg);
  border: 1px solid var(--x-line);
  background: var(--x-raised);
  overflow: hidden;
  text-decoration: none;
  scroll-snap-align: center;
  box-shadow: var(--x-e2);
}
.bkx .jn-deal__img {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-size: cover;
  background-position: center;
  transition: transform .7s var(--x-ease), filter .4s var(--x-ease);
  filter: brightness(calc(1 - var(--ad, 0) * .30)) saturate(calc(1 - var(--ad, 0) * .26));
}
.bkx .jn-deal:hover .jn-deal__img { transform: scale(1.05); }
.bkx .jn-deal[data-centre] .jn-deal__img { filter: none; }
.bkx .jn-deal__plate {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: grid;
  place-items: center;
  padding: 1rem;
  text-align: center;
  font-family: "Frank Ruhl Libre", Georgia, serif;
  font-size: 1.4rem;
  color: var(--x-ink-3);
  background: linear-gradient(150deg, #101823, #070B12);
}
.bkx .jn-deal::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(180deg, rgba(4,7,12,.10) 0%, rgba(4,7,12,.06) 38%, rgba(4,7,12,.93) 100%);
}
.bkx .jn-deal__body { position: relative; z-index: 2; display: grid; gap: .12rem; }
.bkx .jn-deal__where { font-size: 1.14rem; font-weight: 600; line-height: 1.2; }
.bkx .jn-deal__when { font-size: .78rem; color: var(--x-ink-2); direction: ltr; unicode-bidi: isolate; }
.bkx .jn-deal__price { display: flex; align-items: baseline; gap: .18rem; margin-block-start: .5rem; }
.bkx .jn-deal__price b { font-size: 1.62rem; font-weight: 700; color: var(--x-gold); line-height: 1; font-variant-numeric: tabular-nums; }
.bkx .jn-deal__price span { font-size: .95rem; color: var(--x-gold); }
.bkx .jn-deal__unit,
.bkx .jn-deal__src { font-size: .72rem; color: var(--x-ink-3); }
.bkx .jn-deal__obs { font-size: .68rem; color: var(--x-ink-3); line-height: 1.4; margin-block-start: .18rem; }
.bkx .jn-deal__label {
  display: inline-block;
  margin-block-start: .4rem;
  padding: .18rem .55rem;
  border-radius: var(--x-r-pill);
  border: 1px solid var(--x-gold-edge);
  background: var(--x-gold-wash);
  color: var(--x-gold);
  font-size: .68rem;
}
.bkx .jn-deal__claim { font-size: .8rem; color: var(--x-ink); font-weight: 600; }

/* --- a measured row (#jn-rows) ------------------------------------------ */
.bkx .jn-rows { display: grid; gap: 10px; }
.bkx .jn-row-item {
  display: grid;
  grid-template-columns: 56px minmax(0, 1.1fr) minmax(0, 1fr) auto auto;
  align-items: center;
  gap: clamp(10px, 1.4vw, 22px);
  padding: .8rem 1rem;
  border-radius: var(--x-r);
  border: 1px solid var(--x-line);
  background: linear-gradient(140deg, rgba(16, 22, 32, .70), rgba(7, 11, 18, .82));
  text-decoration: none;
  transition: transform .3s var(--x-ease), border-color .3s var(--x-ease), box-shadow .3s var(--x-ease);
}
.bkx .jn-row-item:hover { transform: translateY(-2px); border-color: var(--x-gold-edge); box-shadow: var(--x-e2); }
.bkx .jn-row-item__pic { inline-size: 56px; block-size: 56px; border-radius: 12px; object-fit: cover; background: rgba(255,255,255,.04); }
.bkx .jn-row-item__where b { display: block; font-size: 1rem; font-weight: 600; }
.bkx .jn-row-item__where span { display: block; font-size: .76rem; color: var(--x-ink-3); }
.bkx .jn-row-item__when { font-size: .8rem; color: var(--x-ink-2); }
/*
 * FIVE TRACKS DO NOT FIT ON A PHONE.
 *
 * .jn-row-item is `56px minmax(0,1.1fr) minmax(0,1fr) auto auto`. At 390px,
 * once the thumbnail, two auto tracks and four gaps are taken out, the name
 * column resolves to about 30px — and a country label needs 33-34. Measured on
 * the built page: "הונגריה" scrollWidth 33 / clientWidth 30, "קפריסין" 34 / 30.
 * Three or four pixels, which is the last letter of the word.
 *
 * It reported no horizontal overflow, because a squeeze INSIDE a grid never
 * widens the document. Only comparing each leaf's scrollWidth to its own
 * clientWidth finds it.
 *
 * The row keeps its parts and its order; below 560px the trailing cells simply
 * take the second line instead of stealing width from the name. Nothing above
 * that width changes.
 */
@media (max-width: 560px) {
  .bkx .jn-row-item {
    grid-template-columns: 56px minmax(0, 1fr) auto;
    row-gap: .45rem;
  }
  .bkx .jn-row-item__when { grid-column: 2 / -1; }
}
.bkx .jn-row-item__when b { font-variant-numeric: tabular-nums; direction: ltr; unicode-bidi: isolate; display: inline-block; }
.bkx .jn-row__at { color: var(--x-ink-3); font-size: .7rem; }
.bkx .jn-row-item__price { text-align: end; }
.bkx .jn-row-item__price b { font-size: 1.24rem; font-weight: 700; color: var(--x-gold); font-variant-numeric: tabular-nums; }
.bkx .jn-row-item__price span { display: block; font-size: .72rem; color: var(--x-ink-3); }
.bkx .jn-row-item__claim { font-size: .84rem; color: var(--x-ink); font-weight: 600; }
.bkx .jn-row-item__go { color: var(--x-ink-3); }
.bkx .jn-tag {
  display: inline-block;
  padding: .12rem .5rem;
  border-radius: var(--x-r-pill);
  border: 1px solid var(--x-line-2);
  font-size: .68rem;
  color: var(--x-ink-2);
}
.bkx .jn-tag--live { border-color: var(--x-gold-edge); color: var(--x-gold); background: var(--x-gold-wash); }

/* --- a hotel (#jn-hotels) ----------------------------------------------- */
.bkx .jn-hotels__grid {
  display: flex;
  gap: clamp(14px, 1.6vw, 22px);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding-block: clamp(22px, 3vh, 40px);
  padding-inline: calc(50% - min(150px, 33vw));
  scrollbar-width: none;
}
.bkx .jn-hotels__grid::-webkit-scrollbar { display: none; }
.bkx .jn-hot {
  position: relative;
  flex: 0 0 auto;
  inline-size: min(300px, 66vw);
  scroll-snap-align: center;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-block-size: 400px;
  padding: 1rem 1.1rem 1.15rem;
  border-radius: var(--x-r-lg);
  border: 1px solid var(--x-line);
  background: var(--x-raised);
  overflow: hidden;
  text-decoration: none;
  transition: transform .4s var(--x-ease), border-color .3s var(--x-ease), box-shadow .4s var(--x-ease);
}
.bkx .jn-hot:hover { transform: translateY(-8px); border-color: var(--x-gold-edge); box-shadow: var(--x-e3); }
.bkx .jn-hot__img { position: absolute; inset: 0; z-index: 0; background-size: cover; background-position: center; transition: transform .7s var(--x-ease); }
.bkx .jn-hot:hover .jn-hot__img { transform: scale(1.06); }
.bkx .jn-hot::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(180deg, rgba(4,7,12,.10) 0%, rgba(4,7,12,.34) 34%, rgba(4,7,12,.97) 78%);
}
.bkx .jn-hot__body { position: relative; z-index: 2; display: grid; gap: .12rem; }
.bkx .jn-hot__name { font-size: 1.05rem; font-weight: 600; line-height: 1.25; }
.bkx .jn-hot__where, .bkx .jn-hot__perks, .bkx .jn-hot__obs { font-size: .76rem; color: var(--x-ink-3); }
/* Two lines, then an ellipsis. A provider address is arbitrary length and a
   card that grows to fit the longest one in the set sizes every other card
   against a hotel nobody is looking at. */
.bkx .jn-hot__where { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.bkx .jn-hot__name { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.bkx .jn-hot__price { margin-block-start: .5rem; font-size: 1.3rem; font-weight: 700; color: var(--x-gold); font-variant-numeric: tabular-nums; }

/* --- the quiet states the renderers fall back to ------------------------ */
.bkx .jn-note { color: var(--x-ink-3); font-size: .88rem; margin: 0; }
.bkx .jn-note a { color: var(--x-gold); }



/* == PAGE FURNITURE THE SHELL OWNS NOW ====================================
 * These were in janet_home.css, which this page no longer loads. They are
 * re-authored here rather than imported, because importing one rule out of
 * a sheet means loading the whole sheet and re-opening the trench war the
 * head of index.html describes.
 */

/* The skip link. It exists for exactly one reader and it must be visible to
   them the instant it takes focus. */
.bkx .skip {
  position: absolute;
  inset-block-start: -100px;
  inset-inline-start: 12px;
  z-index: 200;
  padding: .7rem 1.1rem;
  border-radius: var(--x-r-pill);
  background: var(--x-gold);
  color: var(--x-on-gold);
  font-weight: 600;
  text-decoration: none;
  transition: inset-block-start .2s var(--x-ease);
}
.bkx .skip:focus { inset-block-start: 12px; }

/* The mobile menu. A layered sheet under the nav, not a cheap drawer. */
.bkx .mnav {
  position: fixed;
  z-index: 89;
  inset-block-start: var(--x-nav-h, 66px);
  inset-inline: 0;
  display: grid;
  gap: 2px;
  padding: 14px var(--x-gut) 20px;
  background: rgba(6, 9, 15, .96);
  -webkit-backdrop-filter: var(--x-blur);
  backdrop-filter: var(--x-blur);
  border-block-end: 1px solid var(--x-line);
  box-shadow: var(--x-e3);
}
.bkx .mnav[hidden] { display: none; }
.bkx .mnav a {
  padding: .85rem .4rem;
  min-block-size: 44px;
  display: flex;
  align-items: center;
  color: var(--x-ink);
  text-decoration: none;
  border-block-end: 1px solid var(--x-line);
}
.bkx .mnav a:last-child { border-block-end: 0; }

/* The read-only origin cell. It states a fact about the search rather than
   offering a control that changes nothing. */
.bkx-field__static { font-weight: 400; font-size: .98rem; color: var(--x-ink); }

/* --- the floating panel, dressed on the classes janet_home.js writes into
   Both of those elements have their innerHTML REPLACED, so the shell styles
   their own class names rather than a wrapper it happens to control. */
.bkx-float .jn-shot__where b { display: block; font-size: 1.08rem; font-weight: 600; line-height: 1.25; }
.bkx-float .jn-shot__where span { display: block; font-size: .78rem; color: var(--x-ink-3); margin-block-start: .1rem; direction: ltr; unicode-bidi: isolate; text-align: start; }
.bkx-float .jn-shot__price { display: block; min-inline-size: 0; }
.bkx-float .jn-shot__price b { display: block; font-size: 1.5rem; font-weight: 700; line-height: 1.05; color: var(--x-gold); font-variant-numeric: tabular-nums; }
.bkx-float .jn-shot__price span { display: block; font-size: .7rem; color: var(--x-ink-3); line-height: 1.35; margin-block-start: .15rem; }
.bkx-float .jn-shot__claim { display: block; font-size: .86rem; font-weight: 600; color: var(--x-ink); line-height: 1.35; }

/* --- the globe panel, same principle ---------------------------------- */
.bkx-globe__panel .bk-panel__pic {
  inline-size: 100%;
  block-size: 150px;
  object-fit: cover;
  background: rgba(255, 255, 255, .04);
}
.bkx-globe__panel .bk-panel__price--claim {
  font-size: .88rem;
  font-weight: 600;
  color: var(--x-ink);
  line-height: 1.35;
}
/* The idle copy stands down the moment a real measured destination arrives.
   Two panels showing at once would be the product talking over itself. */
.bkx-globe__panel #jn-shot2:not([hidden]) ~ [data-bkx-globe-idle] { display: none; }


/* == THE ENGLISH PAGE'S OWN CONTROLS ======================================
 * A language switcher and a currency select the Hebrew homepage does not
 * have. They are the English page's product, not decoration, so they get
 * shell material rather than being dropped to make the two pages match.
 */
.bkx-langs {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border-radius: var(--x-r-pill);
  border: 1px solid var(--x-line-2);
  background: rgba(255, 255, 255, .03);
}
.bkx-langs a,
.bkx-langs span {
  padding: .38rem .7rem;
  border-radius: var(--x-r-pill);
  font-size: .84rem;
  color: var(--x-ink-3);
  text-decoration: none;
  white-space: nowrap;
  transition: color .25s var(--x-ease), background-color .25s var(--x-ease);
}
.bkx-langs a:hover { color: var(--x-ink); background: rgba(255, 255, 255, .05); }
.bkx-langs [aria-current="true"] {
  background: linear-gradient(160deg, var(--x-gold), var(--x-gold-deep));
  color: var(--x-on-gold);
  font-weight: 600;
}

.bkx-cur { display: flex; align-items: center; gap: .5rem; font-size: .8rem; color: var(--x-ink-3); }
.bkx-cur select {
  min-block-size: 38px;
  padding-inline: .8rem;
  border-radius: var(--x-r-pill);
  border: 1px solid var(--x-line-2);
  background: rgba(255, 255, 255, .03);
  color: var(--x-ink);
  font: inherit;
  font-size: .84rem;
  cursor: pointer;
}
.bkx-cur option { background: var(--x-raised); color: var(--x-ink); }

/* Three commitments, side by side. Not a rail: these are statements, and a
   statement the reader has to drag into view is one they will not read. */
.bkx-trio {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: clamp(14px, 1.6vw, 22px);
}
.bkx-trio .bkx-plan__card p { margin: 0; font-size: .9rem; line-height: 1.6; color: var(--x-ink-2); }

.bkx-foot__blurb { margin-block-start: .9rem; max-inline-size: 34ch; }
.bkx-closing .bkx-h1 { max-inline-size: 16ch; margin-inline: auto; }
.bkx-closing__mark .bkx-brand__name { font-size: 1.4rem; }

/* At the narrow end the header cannot hold five languages and a currency
   select beside the brand. They move into the mobile menu's territory. */
@media (max-width: 1180px) {
  .bkx-langs, .bkx-cur { display: none; }
}


/* == TOUCH TARGETS ========================================================
 * 44px in BOTH dimensions on every control the sweep can reach, and the
 * sweep is the authority here rather than a judgement about which of these a
 * thumb will realistically land on. Measured before this block:
 * .skip 102x43 (one pixel short), .bkx-brand 118x34, .bkx-icon--el 77x40,
 * and every primary nav link 33x31.
 *
 * Height is bought with padding, never with a fixed block-size: a fixed
 * height on a link whose label wraps at 390px clips the second line.
 */
.bkx .skip { min-block-size: 44px; display: inline-flex; align-items: center; }
.bkx-brand { min-block-size: 44px; }
.bkx-icon { inline-size: 44px; block-size: 44px; }
.bkx-icon--el { inline-size: auto; min-inline-size: 44px; }
.bkx-nav__links a { min-block-size: 44px; display: inline-flex; align-items: center; padding-inline: 2px; }
.bkx-globe__rail a { min-block-size: 44px; }
.bkx-cue { min-block-size: 44px; }
.bkx-foot a { display: inline-flex; align-items: center; min-block-size: 44px; }
.bkx-foot__legal a { min-block-size: 44px; display: inline-flex; align-items: center; }
.bkx-langs a, .bkx-langs span { min-block-size: 38px; display: inline-flex; align-items: center; }
.bkx-arrow { inline-size: 44px; block-size: 44px; }

/* == SCENE REVEALS ========================================================
 * Behind `html.js`, and the class is added by bkx.js rather than written into
 * the markup. Both halves matter: with no JS these rules do not exist AND
 * there is no attribute to hide anything, so a page whose script failed and a
 * crawler that runs none both see the whole document.
 */
html.js .bkx-rise {
  opacity: 0;
  transform: translate3d(0, 26px, 0);
  transition: opacity .9s var(--x-ease-2), transform .9s var(--x-ease-2);
}
html.js .bkx-rise.bkx-in { opacity: 1; transform: none; }


/* == 11 · RESPONSIVE ====================================================== */

@media (max-width: 1180px) {
  .bkx-globe { grid-template-columns: minmax(0, 1fr); }
  .bkx-globe__rail { grid-auto-flow: column; justify-content: center; overflow-x: auto; }
  .bkx-globe__panel { max-inline-size: 420px; margin-inline: auto; }
  .bkx-plan { grid-template-columns: minmax(0, 1fr); }
  .bkx-steps { grid-auto-flow: column; overflow-x: auto; padding-block-end: 6px; }
  .bkx-steps li { white-space: nowrap; }
  .bkx-stats, .bkx-float { position: static; inline-size: auto; max-inline-size: none; transform: none; animation: none; }
}

@media (max-width: 1080px) {
  .bkx-form { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .bkx-go { grid-column: 1 / -1; }
  .bkx-field:nth-child(3n + 1) { border-inline-start: 0; }
  .bkx-field:nth-child(n + 4) { border-block-start: 1px solid var(--x-line); }
}
@media (max-width: 900px) {
  .bkx-form { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .bkx-field:nth-child(3n + 1) { border-inline-start: 1px solid var(--x-line); }
  .bkx-field:nth-child(odd) { border-inline-start: 0; }
  .bkx-field:nth-child(n + 3) { border-block-start: 1px solid var(--x-line); }
}

@media (max-width: 860px) {
  .bkx-nav__links { display: none; }
  .bkx-burger {
    display: grid; place-items: center; gap: 4px;
    inline-size: 44px; block-size: 44px;
    border-radius: var(--x-r-pill);
    border: 1px solid var(--x-line-2);
    background: rgba(255,255,255,.03);
    cursor: pointer;
  }
  .bkx-burger span { display: block; inline-size: 16px; block-size: 1.5px; background: var(--x-ink); border-radius: 2px; }
  .bkx-nav__acts { margin-inline-start: auto; }
  .bkx-fare { grid-template-columns: 52px minmax(0, 1fr) auto; row-gap: .4rem; }
  .bkx-fare__when { grid-column: 2 / -1; }
  .bkx-fare__go { display: none; }
  .bkx-foot__in { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 720px) {
  .bkx-hero { min-block-size: auto; }
  .bkx-hero__body { padding-block: clamp(88px, 16vh, 130px) clamp(24px, 5vh, 40px); }
  .bkx-hero__say { max-inline-size: 100%; }
  .bkx-console { transform: none; margin-block-start: 22px; }
  .bkx-console::after { display: none; }
  .bkx-form { grid-template-columns: minmax(0, 1fr); }
  .bkx-field { border-inline-start: 0; border-block-start: 1px solid var(--x-line); }
  .bkx-field:first-child { border-block-start: 0; }
  .bkx-tabs { overflow-x: auto; scrollbar-width: none; }
  .bkx-tabs::-webkit-scrollbar { display: none; }
  .bkx-stats { grid-auto-flow: column; justify-content: space-between; max-inline-size: none; margin-block-start: 26px; }
  .bkx-stats b { font-size: 1.2rem; }
  .bkx-float { margin-block-start: 22px; inline-size: 100%; }
  .bkx-cue { display: none; }
  .bkx-card { inline-size: min(268px, 74vw); }
  .bkx-rail__track { padding-inline: max(16px, calc(50vw - min(134px, 37vw))); }
  .bkx-foot__in { grid-template-columns: minmax(0, 1fr); }
  /*
   * THE BOTTOM BAR RESERVES ITS OWN SPACE.
   *
   * It is position:fixed, so it floats over whatever is beneath it — and
   * measured 2026-09-05 at 430x932 it sat at 868-920 with the globe panel's
   * "discover this destination" button at 844-888: twenty pixels of a primary
   * call to action underneath a control the reader cannot move. At 390 the same
   * two elements missed each other, which is the tell that this is a scroll
   * position and not a layout, and therefore not fixable by nudging either one.
   *
   * --x-dock is the height the bar occupies including its offset and the
   * device's own safe area. Padding the page by it means content can always be
   * scrolled clear of the bar, and scroll-padding means the browser's own
   * scrollIntoView never parks something under it either. Both are needed: the
   * first fixes where scrolling can REACH, the second fixes where it STOPS.
   */
  :where(.bkx) { --x-dock: calc(52px + 12px + 14px + env(safe-area-inset-bottom, 0px)); }
  /* The SCROLLING ELEMENT is <html>, not the .bkx body. scroll-padding on the
     body is inert — the browser reads it from the scrollport, and putting it
     on the wrong element is a rule that looks applied and does nothing. */
  html { scroll-padding-block-end: var(--x-dock); }
  body.bkx { padding-block-end: var(--x-dock); }

  .bkx-sticky {
    position: fixed;
    z-index: 88;
    inset-block-start: auto;
    inset-block-end: calc(12px + env(safe-area-inset-bottom, 0px));
    inset-inline: 0;
    justify-content: center;
    padding-inline: var(--x-gut);
    transform: translate3d(0, 180%, 0);
  }
  .bkx-sticky__btn { max-inline-size: min(560px, 100%); min-block-size: 48px; }
  /* Beats .is-on, which sets transform:none — two classes to its one. */
  .bkx-sticky.is-on.is-tucked { transform: translate3d(0, 180%, 0); }
}

/* 4K and ultrawide: the FRAME grows. A 1180px column in the middle of a 3840px
   black field is a 1440px design with margins, which is the failure the brief
   names by name. */
@media (min-width: 2200px) {
  :where(.bkx) { --x-max: min(2040px, 88vw); }
  .bkx-card { inline-size: 340px; }
  .bkx-float { inline-size: 340px; }
  .bkx-console { inline-size: min(1180px, 100%); }
}
@media (min-width: 3000px) {
  :where(.bkx) { --x-max: min(2560px, 84vw); }
  .bkx-card { inline-size: 400px; }
  .bkx-console { inline-size: min(1360px, 100%); }
  .bkx-globe__stage { max-block-size: min(66vh, 860px); }
}


/* == 12 · REDUCED MOTION ================================================== */

/*
 * Movement goes. Content, state, depth and every affordance stay. A
 * reduced-motion reader still gets the layered scene, the lit centre card and
 * every hover and focus state - the layers simply do not travel.
 */
@media (prefers-reduced-motion: reduce) {
  html.js .bkx-hero__haze,
  html.js .bkx-hero__sheen,
  html.js .bkx-float,
  html.js .bkx-cue__ring svg { animation: none !important; }
  .bkx-layer, .bkx-hero__body, .bkx-float { transform: none !important; }
  .bkx-console { transform: none !important; transition: none !important; }
  .bkx-console::after { display: none; }
  .bkx-rail__track { scroll-behavior: auto; }
  .bkx-card {
    transform: none !important;
    transition: none !important;
  }
  .bkx-card__pic { filter: none !important; transition: none !important; }
  .bkx-pin { opacity: 1 !important; transform: none !important; transition: none !important; }
  .bkx-meter i { transition: none !important; }
  .bkx-sticky { transition: opacity .2s linear; transform: none; }
  .bkx-sticky.is-on { transform: none; }
  .bkx-hotel:hover, .bkx-fare:hover, .bkx-go:hover, .bkx-cta:hover, .bkx-arrow:hover { transform: none; }
  .bkx-hotel:hover img, .bkx-card:hover .bkx-card__pic { transform: none; }
}

/* == P0 · THE HERO COMPOSITION ============================================
 *
 * WHAT WAS WRONG, from the owner's own screenshot rather than from taste:
 * the headline was CENTRED and set at up to 5.2rem across 18ch, so it landed
 * on top of the Parthenon — the one thing the photograph is of. Two side
 * blocks were pinned at 46% height on both edges (three claims on one side, a
 * fare card on the other), squeezing the console between them and competing
 * with the headline for the same horizontal band. The scrim was flat, so the
 * picture was equally dark under the type and away from it.
 *
 * The approved references do none of that. The headline sits on the READING
 * EDGE in a column of its own; the photograph's subject keeps the other half
 * of the frame; the grade is DIRECTIONAL, heavy behind the type and clear over
 * the subject; and the standing claims run along the bottom of the frame
 * instead of floating at mid height.
 *
 * All of it is logical properties, so the mirror is the Hebrew composition and
 * not a second set of rules that can drift from the first.
 */
.bkx-hero__body {
  align-items: flex-start;
  padding-block: clamp(104px, 14vh, 168px) clamp(96px, 13vh, 150px);
}
.bkx-hero__say {
  inline-size: 100%;
  text-align: start;
  max-inline-size: min(660px, 54%);
}
.bkx-h1 {
  margin-inline: 0;
  /* 15ch broke the Hebrew headline onto four lines at 1440. The approved
     reference sets its display in TWO, and three is the most this copy can be
     without the block starting to read as a paragraph. */
  max-inline-size: 19ch;
  font-size: clamp(2.2rem, 3.1vw + .45rem, 4rem);
  text-wrap: balance;
}
.bkx-hero__sub {
  margin-inline: 0;
  max-inline-size: 42ch;
}
/* The console is a panel on the same column, not a bar centred in the frame. */
.bkx-console { margin-inline: 0; }
@media (min-width: 1280px) {
  /*
   * The clearance subtraction is GONE, and this rule is what removes it.
   * `--x-side` existed to keep the console clear of two panels pinned at mid
   * height on both edges; neither is there any more, and leaving the
   * subtraction in place would keep a 476px hole in the layout to make room
   * for nothing.
   */
  .bkx .bkx-hero__say { max-inline-size: min(660px, 54%); }
  /* Narrow enough that the floating fare card at the far edge has a lane of
     its own. They were both full-bleed to their own edge and met in the
     middle. */
  .bkx .bkx-console { max-inline-size: min(880px, 66%); }
}

/*
 * THE GRADE IS DIRECTIONAL NOW.
 *
 * A flat scrim is the only kind that cannot serve both jobs at once: legible
 * type needs a dark ground, and a cinematic photograph needs to be visible.
 * The reading edge gets the weight; the far half keeps the picture. The bottom
 * band stays for the claims row, and the top band for the header.
 */
.bkx-hero .bkx-layer--world .bkx-hero__grade {
  background:
    linear-gradient(to left, rgba(4, 7, 12, .90) 0%, rgba(4, 7, 12, .70) 28%, rgba(4, 7, 12, .18) 58%, rgba(4, 7, 12, .30) 100%),
    linear-gradient(180deg, rgba(4, 7, 12, .78) 0%, rgba(4, 7, 12, .10) 26%, rgba(4, 7, 12, .12) 58%, rgba(4, 7, 12, .92) 100%);
}
.bkx-hero:dir(ltr) .bkx-layer--world .bkx-hero__grade {
  background:
    linear-gradient(to right, rgba(4, 7, 12, .90) 0%, rgba(4, 7, 12, .70) 28%, rgba(4, 7, 12, .18) 58%, rgba(4, 7, 12, .30) 100%),
    linear-gradient(180deg, rgba(4, 7, 12, .78) 0%, rgba(4, 7, 12, .10) 26%, rgba(4, 7, 12, .12) 58%, rgba(4, 7, 12, .92) 100%);
}

/* --- the standing claims, along the bottom ------------------------------
 * Three commitments, in the reference's stat position: a row at the foot of
 * the frame, quiet, on one line. Not a number of travellers and not an average
 * rating — this product holds neither, and the reference's own "10M+ Happy
 * Travelers" is a mockup label, not a fact we may copy.
 */
.bkx-stats {
  position: absolute;
  z-index: 6;
  inset-block-start: auto;
  inset-block-end: clamp(58px, 7vh, 84px);
  /*
   * THE SAME COLUMN AS THE CONSOLE, not the raw viewport gutter.
   *
   * Measured 2026-09-05 at 1920x1080, both languages: the console sits inside
   * .bkx-hero__body (inline-size: var(--x-max), centred) and starts at x=115,
   * while these claims were anchored to --x-gut and started at x=64. Fifty-one
   * pixels out of line, on the same edge of the same frame — and mirrored
   * exactly in Hebrew, where the row overshot the console's right edge by the
   * same 51px instead. A grid that only NEARLY lines up is the kind of defect
   * a reader feels and cannot name, and the brief calls the hero's composition
   * unbalanced for reasons that include this one.
   *
   * 100% is the hero's own width here, so this is the body column's offset
   * computed rather than restated — one number, and it cannot drift from
   * --x-max. Logical, so Hebrew is the mirror and not a second rule.
   */
  inset-inline-start: max(var(--x-gut), calc((100% - var(--x-max)) / 2));
  inset-inline-end: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: clamp(20px, 3.4vw, 54px);
  max-inline-size: min(760px, 62%);
}
.bkx-stats li { display: block; max-inline-size: 22ch; }
.bkx-stats b { font-size: clamp(1.2rem, .9vw + .9rem, 1.7rem); }
.bkx-stats span { font-size: .74rem; }

/* --- the floating fare panel, out of the headline's way -----------------
 * The reference keeps one floating card in the hero and puts it at the FAR
 * edge, low, half over the frame's own margin. Here it was at 46% — the exact
 * height of the headline — on the opposite side to the claims, so the two of
 * them made a corridor and the console had to live in it.
 */
.bkx-float {
  inset-block-start: auto;
  /* Clear of the claims row, which now runs along the bottom of the same
     frame — two absolutely-positioned blocks anchored to the same edge is how
     the first version produced a collision nobody wrote. */
  inset-block-end: clamp(150px, 22vh, 250px);
  inset-inline-end: var(--x-gut);
  inset-inline-start: auto;
  inline-size: clamp(196px, 15vw, 230px);
}
.bkx-float__pic { block-size: 112px; }

@media (max-width: 1180px) {
  /* Below the two-column width the frame cannot hold a floating card beside a
     headline without one of them landing on the other. The card is not hidden
     — it is a real measured fare and a real link — it simply stops floating
     and the claims stack under the console. */
  .bkx-hero__say, .bkx .bkx-hero__say { max-inline-size: 100%; }
  .bkx .bkx-console { max-inline-size: 100%; }
  .bkx-float { position: static; inline-size: 100%; margin-block-start: 1.2rem; animation: none; transform: none; }
  .bkx-stats { position: static; margin-block-start: 1.4rem; max-inline-size: 100%; }
  .bkx-hero__body { padding-block-end: clamp(40px, 6vh, 64px); }
  .bkx-hero .bkx-layer--world .bkx-hero__grade,
  .bkx-hero:dir(ltr) .bkx-layer--world .bkx-hero__grade {
    background: linear-gradient(180deg, rgba(4,7,12,.80) 0%, rgba(4,7,12,.34) 28%, rgba(4,7,12,.52) 60%, rgba(4,7,12,.94) 100%);
  }
}

/* --- the header: one bar, not a bar and two loose controls --------------
 * The owner's note is "floating controls detached/debug-like". They were: the
 * actions group sat hard against the far edge of a 92vw bar while the nav sat
 * against the near one, so at 1440 there was half a screen of nothing between
 * the brand and the language button and the pair read as debug overlay rather
 * than as part of the header.
 */
.bkx-nav {
  gap: clamp(14px, 2vw, 30px);
  padding-inline: var(--x-gut);
}
.bkx-nav__links { margin-inline-start: clamp(18px, 3vw, 52px); }
.bkx-nav__acts { margin-inline-start: auto; gap: 8px; }

/* == P0 · THE GLOBE SCENE =================================================
 *
 * The owner's notes were "oversized / bad framing", "pushed low and right",
 * "dead space", "weak relation between title, globe and destination context".
 * Three of the four were the CAMERA and are fixed in bkx_globe.js — it was
 * framing a 1.16-radius body inside a 1.02 half-height and lifting the camera
 * so the planet sat below centre. The fourth is this layout.
 *
 * The heading used to sit in a band ABOVE the scene, so the eye had to travel
 * from a title at the top of the frame, past an empty strip, to a globe that
 * was then blamed for being low. The framing reference has one row: copy on
 * the reading edge, vertically centred; the planet filling its own column with
 * air all round; the destination context on the far edge.
 */
.bkx-globe {
  grid-template-columns: minmax(0, .82fr) minmax(0, 1.5fr) minmax(0, 300px);
  align-items: center;
  gap: clamp(20px, 3vw, 52px);
}
.bkx-globe__say { display: grid; align-content: center; gap: .85rem; justify-items: start; }
.bkx-globe__say .bkx-h2 { margin: 0; }
.bkx-globe__say .bkx-lede { margin: 0; max-inline-size: 34ch; }
/*
 * The CTA is a GRID ITEM here, and .bkx-cta carries no intrinsic size of its
 * own — so the arrow, an <svg> with no width, stretched to the column and the
 * button came out 330px across and 260px tall. A grid child needs its own
 * bounds; `justify-items: start` only stops it filling the track, not its own
 * content from filling it.
 */
.bkx-globe__say .bkx-cta {
  margin-block-start: .4rem;
  inline-size: auto;
  align-self: start;
  justify-self: start;
}
.bkx-globe__say .bkx-cta svg { inline-size: 17px; block-size: 17px; flex: none; }

.bkx-eyebrow {
  display: block;
  font-size: .7rem;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--x-gold);
}

.bkx-globe__stats {
  display: flex;
  gap: clamp(18px, 2.4vw, 38px);
  margin: .6rem 0 0;
  padding: 0;
  list-style: none;
}
.bkx-globe__stats b {
  display: block;
  font-family: "Frank Ruhl Libre", Georgia, serif;
  font-size: clamp(1.4rem, 1.2vw + 1rem, 2rem);
  font-weight: 500;
  line-height: 1.05;
  color: var(--x-ink);
  font-variant-numeric: tabular-nums;
}
.bkx-globe__stats span {
  display: block;
  font-size: .74rem;
  line-height: 1.4;
  color: var(--x-ink-3);
  margin-block-start: .2rem;
  max-inline-size: 18ch;
}

/* The shortcut rail becomes a quiet column against the far edge rather than a
   third block of body text competing with the copy. */
/*
 * The shortcut rail sits UNDER the copy, not in the far column. Both it and
 * the fare panel were placed at column 3 / row 1 and drew on top of each
 * other — a grid does not stack, it overlaps, and the taller of the two simply
 * hid the other.
 */
.bkx-globe__rail {
  grid-column: 1;
  grid-row: 2;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-block-start: .4rem;
}
.bkx-globe__rail a { padding: .45rem .7rem; font-size: .82rem; }
.bkx-globe__panel { grid-column: 3; grid-row: 1 / span 2; align-self: center; }
.bkx-globe__say { grid-column: 1; grid-row: 1; }
.bkx-globe__stage { grid-column: 2; grid-row: 1 / span 2; }

/* The stage gets the whole middle column and a square frame, so the computed
   camera distance has a predictable shape to fit into. */
.bkx-globe__stage {
  aspect-ratio: 1 / 1;
  max-block-size: min(72vh, 700px);
  inline-size: 100%;
}

/*
 * The drag hint. The reference carries one under the planet, and it is the
 * only thing on the page that tells a reader the globe is an instrument
 * rather than a picture.
 */
.bkx-globe__hint {
  position: absolute;
  inset-block-end: -6px;
  inset-inline: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  font-size: .74rem;
  letter-spacing: .12em;
  color: var(--x-ink-3);
  pointer-events: none;
}
.bkx-globe__hint svg { inline-size: 15px; block-size: 15px; }

@media (max-width: 1100px) {
  .bkx-globe {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(18px, 3vh, 32px);
  }
  /*
   * EVERY child, not three of the four.
   *
   * The desktop layout pins .bkx-globe__say to column 1, .bkx-globe__stage to
   * column 2 and .bkx-globe__panel to column 3. This block collapsed the track
   * list to a single column and re-homed only the rail and the panel — so the
   * STAGE kept `grid-column: 2` and created an implicit second track for
   * itself, and the say/rail/panel were left sharing the first.
   *
   * Measured at 390x844 on the built page, after the globe's canvas mounts and
   * the stage claims its intrinsic 300px: the track list resolved to
   * `33.48px 300px` and the destination panel, the copy and the rail were all
   * 33-35px wide with their text clipped at the frame edge. Nothing reported
   * horizontal overflow, because the squeeze happens INSIDE the grid rather
   * than past the document edge — which is why a scrollWidth check passed on a
   * page a phone renders as a column of sliced words.
   *
   * span 1 as well as column 1: the desktop rules also give two of these
   * `grid-row: 1 / span 2`, which in a one-column grid stacks them on top of
   * each other.
   */
  .bkx-globe__say,
  .bkx-globe__rail,
  .bkx-globe__stage,
  .bkx-globe__panel { grid-column: 1; grid-row: auto / span 1; }
  .bkx-globe__rail { display: flex; flex-wrap: wrap; justify-content: center; }
  .bkx-globe__stage { max-block-size: min(56vh, 460px); }
}

/* == THE COVERFLOW ========================================================
 *
 * The engine writes transform, opacity, z-index and `--cf-a` (the card's own
 * distance from the front, 0 at centre). Everything here is the LOOK, and
 * nothing here animates transform — bkx_coverflow.js is the only animation
 * authority for position, and a CSS transition on top of a spring is two
 * animations arguing about one property.
 *
 * WHAT THIS SHEET MUST NOT DO, learned by doing it:
 * a first version set `position: relative; z-index: 4` on every direct child
 * of a card so the text would sit above the picture. The deals renderer paints
 * its photograph with `<span class="jn-deal__img" style="background-image:…">`
 * positioned absolutely — so the blanket rule pulled the picture back into
 * flow and every card went black. The deck rendered, moved and centred
 * perfectly, with no images in it.
 *
 * So the picture is named explicitly, and nothing here touches "every child".
 */
.bkx-cf {
  position: relative;
  perspective: 1500px;
  perspective-origin: 50% 46%;
  touch-action: pan-y;               /* vertical page scroll still belongs to the page */
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
  block-size: var(--cf-h, clamp(430px, 56vh, 560px));
  overflow: hidden;
}
.bkx-cf.is-dragging { cursor: grabbing; }
.bkx-cf:focus-visible { outline: 2px solid var(--x-gold, #E3BE79); outline-offset: 6px; border-radius: var(--x-r-lg, 22px); }

/* The track is only a positioning context: the cards are placed absolutely
   from the centre, because a flex row would fight the transforms for the left
   edge of every card. */
/*
 * SPECIFICITY, and why these selectors are three classes deep.
 *
 * The renderers style their own cards at TWO classes — `.bkx .jn-deal`
 * gives a fare card `position: relative`, `flex: 0 0 auto` and a fixed
 * 288px, and `.bkx .jn-deals__track` makes its container a flex scroller.
 * A single-class `.bkx-cf__item` loses to both, so the engine was writing
 * transforms onto cards that were still being LAID OUT by a flex row: the
 * deck moved, turned and lit correctly and was centred 431px off, because
 * `inset-inline-start: 50%` was resolving against a 288px card rather than
 * the 1440px frame.
 *
 * Three classes beats two whatever order the sheets load in, which matters
 * because this block is appended and a later edit could move it.
 */
.bkx-cf .bkx-cf__track {
  /*
   * THE TRACK MUST NOT CATCH THE POINTER, and this is not a nicety.
   *
   * Measured: elementFromPoint returned the TRACK at all fifteen points
   * across a side card's own box. Not one pixel of any card except the
   * centre one was hittable, so the headline interaction — hover a side
   * card, the deck turns — was dead for every reader, and so were the links
   * on those cards.
   *
   * The cause is `preserve-3d`: inside it, z-index does not decide stacking,
   * 3D POSITION does. The side cards are pushed back by translateZ, which
   * puts them behind their own parent's plane at z = 0 — and the parent
   * fills the frame, so it wins the hit test everywhere. Raising z-index on
   * the cards cannot fix it; the engine was already writing one.
   */
  pointer-events: none;
  position: absolute;
  display: block !important;
  overflow: visible;
  padding: 0;
  gap: 0;
  inset: 0;
  display: block;
  transform-style: preserve-3d;
}
.bkx-cf .bkx-cf__track .bkx-cf__item {
  /* …and the cards take it back. */
  pointer-events: auto;
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  margin-block-start: calc(var(--cf-card-h, 400px) / -2);
  margin-inline-start: calc(var(--cf-card-w, 300px) / -2);
  inline-size: var(--cf-card-w, 300px);
  block-size: var(--cf-card-h, 400px);
  transform-origin: 50% 58%;
  will-change: transform, opacity;
  border-radius: var(--x-r-lg, 22px);
  overflow: hidden;
  border: 1px solid var(--x-line, rgba(240,236,226,.10));
  background: var(--x-raised, #0C1119);
  box-shadow: 0 34px 76px -30px rgba(0, 0, 0, .96);
  text-decoration: none;
  /* NOT transform — see above. These two are the only properties the
     stylesheet is allowed to ease. */
  transition: box-shadow .34s var(--x-ease, cubic-bezier(.22,1,.36,1)),
              border-color .34s var(--x-ease, cubic-bezier(.22,1,.36,1));
}

/*
 * THE PICTURE, in whichever of the three shapes a renderer emits it: a real
 * <img>, the deals strip's background-image <span>, or the hotel row's.
 * Named rather than matched by position, so a renderer that adds a wrapper
 * does not silently lose its photograph.
 */
.bkx-cf__item > img,
.bkx-cf__item > .jn-deal__img,
.bkx-cf__item > .bkx-card__pic,
.bkx-cf__item > .jn-hot__img {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  background-size: cover;
  background-position: center;
  z-index: 0;
  filter: saturate(calc(1 - var(--cf-a, 0) * .20)) brightness(calc(1 - var(--cf-a, 0) * .08));
}

/* The dimming is driven by the SAME number the geometry uses, so a card half
   way to the front is half way lit. */
.bkx-cf__item::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(4,7,12,.04) 0%, rgba(4,7,12,.06) 38%, rgba(4,7,12,.94) 100%),
    /*
     * THERE ARE TWO DIMMERS, AND ONLY ONE OF THEM WAS TUNED.
     *
     * bkx_coverflow.js lowered `fade` from .26 to .13 with a comment saying the
     * reference shows seven cards "receding but all legibly there" — and this
     * veil, at .24 per unit of offset, quietly put the same dimming back. The
     * two multiply. --cf-a saturates at D.range (2.6), so the far card was
     * carrying .62 of near-black ON TOP of an engine opacity of .53: about 20%
     * visible, which is the row of black slabs beside the front card in the
     * 2026-09-05 capture.
     *
     * At .11 the deck recedes 100 -> 77 -> 58 -> 47 percent effective, which
     * is a deck seen in perspective rather than three cards and some shadows.
     * The turn, the scale and the perspective still carry the depth; that was
     * always the engine comment's own argument for keeping opacity low.
     */
    linear-gradient(rgba(4, 7, 12, calc(var(--cf-a, 0) * 0.11)), rgba(4, 7, 12, calc(var(--cf-a, 0) * 0.11)));
  transition: background-color .2s linear;
}
/* The card's own text sits above the veil. Named classes again, never `> *`. */
.bkx-cf__item > .jn-deal__body,
.bkx-cf__item > .bkx-card__body,
.bkx-cf__item > .jn-deal__where,
.bkx-cf__item > .jn-deal__meta,
.bkx-cf__item > .jn-deal__price,
.bkx-cf__item > .jn-deal__note,
.bkx-cf__item > .jn-deal__tag,
.bkx-cf__item > figcaption,
.bkx-cf__item > h3,
.bkx-cf__item > p,
.bkx-cf__item > span:not(.jn-deal__img):not(.bkx-card__pic):not(.jn-hot__img) { position: relative; z-index: 2; }

/* The front card is the primary object: champagne edge, its own light, no
   extra veil at all. */
.bkx-cf__item[data-cf-centre] {
  border-color: var(--x-gold, #E3BE79);
  box-shadow:
    0 44px 96px -28px rgba(0, 0, 0, .98),
    0 0 0 1px rgba(227, 190, 121, .34),
    0 22px 60px -22px rgba(227, 190, 121, .34);
}

/* The floor the deck stands on. */
.bkx-cf__floor {
  position: absolute;
  inset-block-end: 3%;
  inset-inline-start: 50%;
  translate: -50% 0;
  inline-size: min(1180px, 92%);
  block-size: 30%;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(56% 54% at 50% 100%,
    rgba(227, 190, 121, .20), rgba(227, 190, 121, .04) 46%, transparent 74%);
}

@media (max-width: 860px) {
  .bkx-cf { --cf-h: clamp(340px, 56vh, 460px); }
}
@media (prefers-reduced-motion: reduce) {
  .bkx-cf__item { transition: none !important; }
  .bkx-cf__item > img, .bkx-cf__item > .jn-deal__img { filter: none !important; }
  /*
   * THE DECK IS NOT BLANKED, IT IS FLATTENED.
   *
   * The old rail sat in flow, so `transform: none !important` was the right
   * reduced-motion answer for it and the suite pins that. A coverflow card is
   * positioned absolutely at the centre of its frame and placed by transform,
   * so the same rule would stack all eight cards on one spot — a page that
   * respects the preference by destroying the content.
   *
   * The flattening happens where the transform is WRITTEN instead:
   * bkx_coverflow.js sets rotateY and translateZ to zero under the same media
   * query, so a reader who asked for less motion gets a flat, still, readable
   * row and keeps every card. The spring is skipped there too — the deck moves
   * to its target in one frame rather than easing.
   *
   * The old guarantee still holds for every .bkx-card that is NOT in a deck.
   */
  .bkx-card:not(.bkx-cf__item) { transform: none !important; }
}

/* --- the destination list beside the world -----------------------------
 * The reference's right column. Rows, not a card: a thumbnail, a city, a
 * country and a chevron, and NO price — this is navigation, and a figure here
 * would be a claim with nowhere to check it. The measured fare stays in
 * #jn-shot2 above, which janet_home.js fills from a real observation or leaves
 * empty.
 */
.bkx-dests { list-style: none; margin: .9rem 0 0; padding: 0; display: grid; gap: 2px; }
.bkx-dests a {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) 16px;
  align-items: center;
  gap: .75rem;
  padding: .5rem .6rem;
  border-radius: var(--x-r);
  border: 1px solid transparent;
  text-decoration: none;
  color: inherit;
  min-block-size: 56px;
  transition: background-color .25s var(--x-ease), border-color .25s var(--x-ease);
}
.bkx-dests a:hover { background: rgba(255, 255, 255, .04); border-color: var(--x-line-2); }
.bkx-dests img { inline-size: 40px; block-size: 40px; border-radius: 50%; object-fit: cover; }
.bkx-dests b { display: block; font-size: .93rem; font-weight: 600; line-height: 1.2; color: var(--x-ink); }
.bkx-dests small { display: block; font-size: .74rem; color: var(--x-ink-3); margin-block-start: .1rem; }
.bkx-dests svg { inline-size: 16px; block-size: 16px; color: var(--x-ink-3); }
.bkx-dests a:hover svg { color: var(--x-gold); }
@media (max-width: 1100px) {
  .bkx-dests { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
}

/* == THE PLANNER SCENE ====================================================
 *
 * WHAT WAS REJECTED, in the owner's words: "one large Athens image + detached
 * status box + vertical 1-6 list… visually unclear… sparse wireframe-like".
 * That is a fair description of what it was — a photograph with three text
 * pins on it, a bare ordered list beside it, and a card of empty ledger rows
 * with no relationship to either.
 *
 * The approved mockup is a COMPOSITION: copy and numbered stages on the
 * reading edge, and beside them a deck of destination photographs standing in
 * space with a glass panel of capabilities floating over it. The trip
 * assembles into that panel as the reader arrives.
 *
 * NO FIGURES, and the mockup has none either — its own panel reads "Flights /
 * Best options", "Hotels / Handpicked stays". That is both the referenced
 * shape and the honest one: a total belongs to a plan, and this page holds
 * none. /plan is where every number appears beside its observation.
 */
.bkx-scene--plan { overflow: visible; }
.bkx-plan {
  inline-size: var(--x-max);
  margin-inline: auto;
  display: grid;
  grid-template-columns: minmax(0, .86fr) minmax(0, 1.14fr);
  gap: clamp(28px, 4vw, 72px);
  align-items: center;
}
.bkx-plan__say { display: grid; align-content: center; gap: .8rem; justify-items: start; }
.bkx-plan__say .bkx-h2 { margin: 0; }
.bkx-plan__say .bkx-lede { margin: 0; max-inline-size: 38ch; }

/* --- the five questions, as chips that light in order ------------------- */
.bkx-plan__steps {
  list-style: none;
  margin: .7rem 0 0;
  padding: 0;
  display: grid;
  gap: 8px;
  inline-size: 100%;
  max-inline-size: 420px;
}
.bkx-plan__steps li {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  grid-template-rows: auto auto;
  align-items: center;
  column-gap: .8rem;
  padding: .62rem .8rem;
  border-radius: var(--x-r);
  border: 1px solid var(--x-line);
  background: linear-gradient(150deg, rgba(16, 22, 32, .55), rgba(7, 11, 18, .70));
  transition: border-color .5s var(--x-ease), background-color .5s var(--x-ease);
}
html.js .bkx-plan__steps li { opacity: 0; }
html.js [data-bkx-plan].is-built .bkx-plan__steps li {
  animation: bkx-plan-in .6s var(--x-ease-2) both;
  animation-delay: calc(var(--i, 0) * 110ms);
}
[data-bkx-plan].is-built .bkx-plan__steps li.is-on {
  border-color: var(--x-gold-edge);
  background: linear-gradient(150deg, rgba(227, 190, 121, .10), rgba(7, 11, 18, .74));
}
.bkx-plan__n {
  grid-row: 1 / span 2;
  display: grid;
  place-items: center;
  inline-size: 30px;
  block-size: 30px;
  border-radius: 50%;
  border: 1px solid var(--x-line-2);
  font-size: .82rem;
  font-weight: 700;
  color: var(--x-ink-3);
  transition: background-color .45s var(--x-ease), color .45s var(--x-ease), border-color .45s var(--x-ease);
}
.bkx-plan__steps li.is-on .bkx-plan__n {
  background: linear-gradient(160deg, var(--x-gold), var(--x-gold-deep));
  border-color: transparent;
  color: var(--on-sky, #10131A);
}
.bkx-plan__steps b { font-size: .95rem; font-weight: 600; color: var(--x-ink); }
.bkx-plan__steps small { font-size: .76rem; color: var(--x-ink-3); }
/*
 * .bkx-cta carries `inline-size: 100%`, which is right inside the cards it was
 * written for and wrong the moment it becomes a grid item in a column: 100% of
 * a grid AREA is the whole column, and `justify-items: start` does not stop
 * it, so the button came out 740px wide. The large variant is the standalone
 * one and sizes to its own content.
 */
.bkx-cta--lg {
  inline-size: auto;
  align-self: start;
  justify-self: start;
  padding-block: .85rem;
  padding-inline: 1.6rem;
  font-size: 1rem;
  margin-block-start: .6rem;
}
.bkx-cta--lg svg { inline-size: 17px; block-size: 17px; flex: none; }

/* --- the scene: photographs standing in space, panel floating over ------ */
.bkx-plan__scene {
  position: relative;
  perspective: 1500px;
  perspective-origin: 50% 46%;
  min-block-size: clamp(420px, 52vh, 560px);
}
.bkx-plan__glow {
  position: absolute;
  inset: 8% -6% -4% -6%;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(58% 54% at 42% 62%, rgba(227, 190, 121, .16), rgba(227, 190, 121, .03) 48%, transparent 74%);
}
.bkx-plan__deck { position: absolute; inset: 0; transform-style: preserve-3d; }
.bkx-plan__shot {
  position: absolute;
  margin: 0;
  border-radius: var(--x-r-lg);
  overflow: hidden;
  border: 1px solid var(--x-line-2);
  box-shadow: 0 40px 88px -32px rgba(0, 0, 0, .96);
  transform-origin: 50% 60%;
}
.bkx-plan__shot img { display: block; inline-size: 100%; block-size: 100%; object-fit: cover; }

/* Three photographs at three depths. The lead one is upright and lit; the two
   behind are turned away and dimmed — the same vocabulary the destination deck
   uses one scene up, so the page has one visual system rather than two. */
.bkx-plan__shot[data-shot="1"] {
  inset-block: 12% 12%;
  inset-inline-start: 6%;
  inline-size: min(290px, 40%);
  z-index: 3;
}
.bkx-plan__shot[data-shot="2"] {
  inset-block: 20% 20%;
  inset-inline-start: 34%;
  inline-size: min(230px, 32%);
  z-index: 2;
  filter: brightness(.72) saturate(.85);
}
.bkx-plan__shot[data-shot="3"] {
  inset-block: 27% 27%;
  inset-inline-start: 56%;
  inline-size: min(200px, 27%);
  z-index: 1;
  filter: brightness(.54) saturate(.72);
}
html.js .bkx-plan__shot { opacity: 0; }
html.js [data-bkx-plan].is-built .bkx-plan__shot { animation: bkx-plan-shot .9s var(--x-ease-2) both; }
html.js [data-bkx-plan].is-built .bkx-plan__shot[data-shot="1"] { animation-delay: .10s; }
html.js [data-bkx-plan].is-built .bkx-plan__shot[data-shot="2"] { animation-delay: .26s; }
html.js [data-bkx-plan].is-built .bkx-plan__shot[data-shot="3"] { animation-delay: .40s; }

@keyframes bkx-plan-shot {
  from { opacity: 0; transform: translate3d(0, 26px, -220px) rotateY(-24deg); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateY(-13deg); }
}
@keyframes bkx-plan-in {
  from { opacity: 0; transform: translate3d(0, 14px, 0); }
  to   { opacity: 1; transform: none; }
}

/* The destination locking in — the one caption in the scene, on the lead
   photograph, because that is the stage the reader is watching complete. */
.bkx-plan__shot--lead figcaption {
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0;
  padding: 2.4rem 1rem .95rem;
  background: linear-gradient(180deg, transparent, rgba(4, 7, 12, .92));
}
.bkx-plan__shot--lead b { display: block; font-size: 1.15rem; font-weight: 600; color: var(--x-ink); }
.bkx-plan__lock {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  margin-block-end: .4rem;
  padding: .2rem .55rem;
  border-radius: 999px;
  background: rgba(227, 190, 121, .16);
  border: 1px solid var(--x-gold-edge);
  color: var(--x-gold);
  font-size: .68rem;
  font-weight: 700;
}
.bkx-plan__lock svg { inline-size: 12px; block-size: 12px; }

/* --- the glass panel the trip assembles into ---------------------------- */
.bkx-plan__panel {
  position: absolute;
  z-index: 4;
  inset-block-end: 6%;
  inset-inline-end: 0;
  inline-size: min(330px, 52%);
  padding: 1rem 1.05rem;
  border-radius: var(--x-r-lg);
  border: 1px solid var(--x-line-2);
  background: linear-gradient(180deg, rgba(31, 34, 40, .90), rgba(13, 15, 18, .95));
  -webkit-backdrop-filter: var(--x-blur);
  backdrop-filter: var(--x-blur);
  box-shadow: 0 40px 90px -30px rgba(0, 0, 0, .96), 0 0 0 1px rgba(227, 190, 121, .08);
}
.bkx-plan__row {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  align-items: center;
  gap: .7rem;
  padding-block: .5rem;
  border-block-end: 1px solid var(--x-line);
}
.bkx-plan__row:last-of-type { border-block-end: 0; }
.bkx-plan__row svg { inline-size: 18px; block-size: 18px; color: var(--x-gold); }
.bkx-plan__row b { display: block; font-size: .9rem; font-weight: 600; color: var(--x-ink); }
.bkx-plan__row small { display: block; font-size: .74rem; color: var(--x-ink-3); margin-block-start: .1rem; }
html.js .bkx-plan__row { opacity: 0; }
html.js [data-bkx-plan].is-built .bkx-plan__row {
  animation: bkx-plan-in .55s var(--x-ease-2) both;
  animation-delay: calc(.55s + var(--i, 0) * 160ms);
}
.bkx-plan__truth {
  display: flex;
  align-items: flex-start;
  gap: .5rem;
  margin: .7rem 0 0;
  font-size: .72rem;
  line-height: 1.45;
  color: var(--x-ink-3);
}
.bkx-plan__truth svg { inline-size: 14px; block-size: 14px; flex: none; margin-block-start: .12rem; }

@media (max-width: 1080px) {
  .bkx-plan { grid-template-columns: minmax(0, 1fr); }
  .bkx-plan__scene { min-block-size: clamp(360px, 56vh, 460px); perspective: none; }
  .bkx-plan__shot[data-shot="3"] { display: none; }
  .bkx-plan__shot[data-shot="1"] { inline-size: 46%; inset-inline-start: 2%; }
  .bkx-plan__shot[data-shot="2"] { inline-size: 34%; inset-inline-start: 40%; }
  .bkx-plan__panel { inline-size: min(320px, 76%); inset-block-end: 2%; }
  .bkx-plan__steps { max-inline-size: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  html.js .bkx-plan__steps li,
  html.js .bkx-plan__shot,
  html.js .bkx-plan__row { opacity: 1 !important; animation: none !important; }
  html.js [data-bkx-plan].is-built .bkx-plan__shot { transform: none !important; }
}

/* == REFERENCE PASS 2 =====================================================
 * Written after putting the render and the mockup side by side at 1920
 * (artifacts/reference_compare/). Colour was already right; COMPOSITION was
 * not, and these are the four differences that were actually visible.
 */

/* --- 1. HERO: the foreground the reference has and this did not ----------
 *
 * The mockup is framed by dark, OUT-OF-FOCUS foreground: a stone column down
 * the right edge, foliage and lanterns bottom-left. That is what gives it
 * depth — there is something in front of the scene, not just behind it. The
 * render had a photograph running edge to edge with nothing nearer than the
 * subject, which is why it read flat however good the picture was.
 *
 * Built from gradients rather than cut-out photography because the repository
 * holds no foreground plates, and because a blurred mass at the frame edge is
 * exactly what an out-of-focus object IS. It rides `.bkx-layer--haze`, which
 * already travels at the highest parallax rate on the page — so it moves more
 * than the city behind it, which is the whole point.
 */
.bkx-hero__fg {
  position: absolute;
  inset: -4%;
  pointer-events: none;
  /*
   * The PLATE is the foreground now, not a gradient. scripts/build_foreground_plate.js
   * draws a column, low fronds and a canopy sprig, defocuses them, and writes a
   * transparent PNG. A gradient darkened the corners and never read as depth,
   * because the eye takes depth from a recognisable shape occluding a scene.
   *
   * URL is root-absolute: this custom-property-free url() still resolves against
   * the STYLESHEET, which ships from /assets/v/ after versioning.
   *
   * 100% 100% rather than cover, deliberately. Every shape in the plate is
   * anchored to an EDGE, and cover would crop whichever axis overflows — the
   * bottom fronds at 16:9, the canopy at 21:9. Stretching a blurred silhouette
   * is invisible; losing a third of the frame is not.
   */
  background:
    url("/assets/edit/hero_foreground_1600.png") 50% 50% / 100% 100% no-repeat,
    /* the warm bounce a lantern would throw onto the near foliage */
    radial-gradient(18% 26% at 9% 90%, rgba(227, 172, 96, .20) 0%, transparent 72%),
    /* and a general weighting of the corners, under the plate */
    radial-gradient(52% 66% at 2% 106%, rgba(4, 7, 12, .60) 0%, transparent 72%),
    radial-gradient(34% 118% at 100% 48%, rgba(4, 6, 10, .52) 0%, transparent 74%);
}
/* Mirrored in RTL so the relationship to the READING edge is preserved: the
   fronds and the lantern sit where the eye starts, the column falls away on the
   far side. Un-mirrored it would stand the column on top of the headline. */
[dir="rtl"] .bkx-hero__fg { transform: scaleX(-1); }
@media (max-width: 900px) {
  /* At phone width the frame is too narrow to give up its edges. */
  .bkx-hero__fg { display: none; }
}

/* --- 2. COVERFLOW: one ribbon, not seven separate tiles ------------------
 * The mockup's deck is a continuous overlapping ribbon that reaches both frame
 * edges, and the front card is unmistakably lit. The render's cards were
 * narrower with air between them, so it read as a row of pictures rather than
 * one object seen in perspective.
 */
.bkx-rail { --cf-card-w: min(330px, 66vw); --cf-card-h: min(440px, 88vw); }
.bkx-cf { --cf-h: clamp(470px, 60vh, 600px); }
.bkx-cf__item[data-cf-centre] {
  box-shadow:
    0 46px 100px -26px rgba(0, 0, 0, .98),
    0 0 0 1px rgba(227, 190, 121, .46),
    0 0 46px -6px rgba(227, 190, 121, .40),
    0 26px 70px -20px rgba(227, 190, 121, .38);
}
/* A soft ground behind the deck, so the band is a SCENE rather than a hole
   cut in the page — the mockup has a dark photographic backdrop here. */
.bkx-cf::before {
  content: "";
  position: absolute;
  inset: 6% -4% 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(52% 46% at 50% 46%, rgba(58, 96, 150, .16), transparent 68%),
    radial-gradient(70% 40% at 50% 104%, rgba(227, 190, 121, .10), transparent 72%);
}

/* --- 3. GLOBE: bigger in frame, and the column beside it gets room -------
 * The mockup's planet fills its column with a thin margin; the render left a
 * wide gap all round, which made it look smaller than the copy beside it. And
 * the destination list was sharing its column with a large fare card, so it
 * was squeezed into a strip.
 */
/*
 * SCOPED, AND THIS IS THE WHOLE PHONE DEFECT.
 *
 * This three-column refinement sat at TOP LEVEL, after
 * `@media (max-width: 1100px) { .bkx-globe { grid-template-columns: minmax(0,1fr) } }`.
 * A media query adds no specificity, so an unconditional rule further down the
 * file beats it at every width — the single-column mobile layout below it was
 * dead code and had been since it was written.
 *
 * Measured 2026-09-05 at 390x844, both languages: the grid resolved to
 * `0px 0px 308.172px` — the first two tracks collapsed to ZERO. The
 * destination panel came out 2px wide with its content overflowing at 18-35px,
 * and its call to action measured 2px on English and 0px on Hebrew: a control
 * that cannot be seen, read or pressed on a phone.
 *
 * The refinement is right where it was written for, so it is confined there
 * rather than deleted. Desktop is unchanged, byte for byte.
 */
@media (min-width: 1101px) {
  .bkx-globe { grid-template-columns: minmax(0, .78fr) minmax(0, 1.55fr) minmax(0, 320px); }
  .bkx-globe__stage { max-block-size: min(78vh, 760px); }
}
.bkx-globe__panel { inline-size: 100%; }
#jn-shot2-wrap .bkx-panel__pic-slot img,
#jn-shot2-wrap img { max-block-size: 116px; object-fit: cover; }

/* --- 4. PLANNER: the cinematic environment the scene sits in -------------
 * The mockup is a full-bleed dusk landscape with the composition floating over
 * it. The render was the composition alone on flat black, which is most of why
 * it still read as sparse after the rebuild.
 */
.bkx-scene--plan { position: relative; isolation: isolate; }
.bkx-scene--plan::before {
  content: "";
  position: absolute;
  inset-block: -6% -6%;
  inset-inline: calc(50% - 50vw);
  z-index: -2;
  pointer-events: none;
  /*
   * ROOT-ABSOLUTE, and it has to be. A relative url() inside a custom property
   * is resolved against the STYLESHEET that USES the var, not the element that
   * declared it — and this sheet is served content-addressed from /assets/v/,
   * so `url(assets/dest/…)` resolved to /assets/v/assets/dest/… and 404ed.
   * The scene rendered as flat black with no error anyone would notice.
   */
  background-image: var(--x-plan-bg);
  background-size: cover;
  background-position: center 62%;
  opacity: .5;
}
.bkx-scene--plan::after {
  content: "";
  position: absolute;
  inset-block: -6% -6%;
  inset-inline: calc(50% - 50vw);
  z-index: -1;
  pointer-events: none;
  background:
    linear-gradient(180deg, var(--x-void) 0%, rgba(4, 7, 12, .74) 22%, rgba(4, 7, 12, .80) 68%, var(--x-void) 100%),
    linear-gradient(to left, rgba(4, 7, 12, .90) 0%, rgba(4, 7, 12, .40) 46%, rgba(4, 7, 12, .70) 100%);
}
@media (max-width: 900px) {
  .bkx-scene--plan::before { opacity: .34; }
}

/* EL, in the planner scene. A byline, not a widget: an avatar, her name, her
   role and one line. Her config lists a floating bubble and a persistent
   assistant under never_appears_in, and a persona that follows the reader down
   the page is arguing with them rather than offering something. */
.bkx-plan__who {
  display: flex;
  align-items: flex-start;
  gap: .7rem;
  margin: .2rem 0 0;
  padding: .7rem .85rem;
  border-radius: var(--x-r);
  border: 1px solid var(--x-line);
  background: linear-gradient(150deg, rgba(227, 190, 121, .07), rgba(7, 11, 18, .62));
  max-inline-size: 420px;
}
.bkx-plan__who img { inline-size: 34px; block-size: 34px; border-radius: 50%; flex: none; }
.bkx-plan__who b { color: var(--x-ink); font-weight: 600; }
.bkx-plan__who span { font-size: .84rem; color: var(--x-ink-2); line-height: 1.45; }
.bkx-plan__who small { display: block; font-size: .78rem; color: var(--x-ink-3); margin-block-start: .15rem; }

/* == COVERFLOW · PASS 3 — A DECK, NOT A ROW =============================
 *
 * The note was "it reads as a row of portrait cards", and it did. The engine's
 * geometry is fixed in bkx_coverflow.js; these are the three things the
 * stylesheet owns that were also missing.
 */

/* 1. THE PERSPECTIVE WAS TOO FAR AWAY. At 1400px a 58-degree turn foreshortens
 *    by a few percent and reads as a slightly narrower card. At 900 the same
 *    turn is unmistakable, and the receding cards genuinely converge. */
.bkx-cf {
  perspective: 900px;
  perspective-origin: 50% 42%;
}

/* 2. SHADING THAT LEANS. A turned card in the world is lit unevenly: the edge
 *    swinging away from you goes dark, the near edge catches the light. `--cf-s`
 *    is the sign of the card's offset, so the gradient can point at whichever
 *    side is actually the far one. Without this, a rotated card is just a
 *    narrower rectangle — this is what makes the turn legible. */
.bkx-cf .bkx-cf__track .bkx-cf__item::after {
  background:
    linear-gradient(180deg, rgba(4,7,12,.04) 0%, rgba(4,7,12,.06) 38%, rgba(4,7,12,.94) 100%),
    linear-gradient(
      calc(90deg + var(--cf-s, 1) * 180deg),
      /* --cf-a runs to 2.6, so a 0.62 coefficient clamped the far edge of the
         outer cards to solid black and the deck lost its ends. These are priced
         against the RANGE, not against 1. */
      rgba(2, 4, 8, calc(var(--cf-a, 0) * 0.27)) 0%,
      rgba(2, 4, 8, calc(var(--cf-a, 0) * 0.07)) 48%,
      rgba(255, 246, 232, calc(var(--cf-a, 0) * 0.035)) 100%
    );
}

/* 3. THE FLOOR. The reference deck stands on something — there is a soft
 *    reflection and a pool of light under it. A deck floating on flat black is
 *    the other half of why it read as a row of tiles. */
.bkx-cf::after {
  content: "";
  position: absolute;
  inset-block-end: 0;
  inset-inline: 8%;
  block-size: 24%;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(46% 100% at 50% 0%, rgba(227, 190, 121, .16), transparent 70%),
    radial-gradient(70% 100% at 50% 0%, rgba(58, 96, 150, .10), transparent 72%);
  filter: blur(6px);
}

/* The front card carries a real cast shadow now, not just a glow — a lit object
   above a floor throws one, and its absence is subtle but reads as a sticker. */
.bkx-cf .bkx-cf__track .bkx-cf__item[data-cf-centre] {
  box-shadow:
    0 54px 90px -30px rgba(0, 0, 0, .98),
    0 0 0 1px rgba(227, 190, 121, .50),
    0 0 52px -8px rgba(227, 190, 121, .34),
    0 30px 76px -22px rgba(227, 190, 121, .30);
}

/* == HERO · PASS 4 — LIGHT, SCALE, AND SOMETHING IN FRONT ==================
 *
 * Measured against the reference at 1920, not judged by eye:
 *
 *   headline      64px in a 1015px hero — 6.3% of the frame. The reference's
 *                 display is 8.7%. Two lines in both, so this is scale alone.
 *   top of frame  darkened TWICE. `.bkx-layer--sky` carries the base grade
 *                 (.86 at the top) and `.bkx-layer--world` carries the
 *                 directional one (.78), and they stack to near-opaque. The
 *                 reference's sky is the brightest thing in the picture.
 *   foreground    a plate now hangs on the haze layer, and the light in the
 *                 frame has to agree with it: it is lit from the far side.
 */

/* 1. THE SKY LAYER STOPS BEING A SCRIM. It sits above nothing — there is no
 *    photograph on it — so every point of darkness it adds is subtracted from
 *    the one on the layer below. It becomes atmosphere instead: the warm depth
 *    of a low sun, and a bare minimum of weight under the header. */
.bkx-hero .bkx-layer--sky .bkx-hero__grade {
  background:
    linear-gradient(180deg, rgba(4, 7, 12, .52) 0%, rgba(4, 7, 12, .12) 13%, transparent 26%),
    radial-gradient(58% 42% at 62% 24%, rgba(255, 198, 122, .20) 0%, transparent 72%);
}

/* 2. THE PICTURE KEEPS ITS SKY. The top band shortens to roughly the header's
 *    own height and lightens; the reading edge keeps its weight because the
 *    type still has to sit on it; the floor lifts off .92 so the ruins at the
 *    bottom of the frame are still a photograph and not a shadow. */
.bkx-hero .bkx-layer--world .bkx-hero__grade,
.bkx-hero:dir(ltr) .bkx-layer--world .bkx-hero__grade {
  background:
    /* the sun, sitting behind the subject — the single largest reason the
       reference reads as cinematic and a flat exposure does not */
    radial-gradient(44% 34% at 61% 30%, rgba(255, 206, 138, .30) 0%, transparent 68%),
    linear-gradient(to var(--x-read-far, left),
      rgba(4, 7, 12, .88) 0%, rgba(4, 7, 12, .62) 26%, rgba(4, 7, 12, .10) 56%, rgba(4, 7, 12, .22) 100%),
    linear-gradient(180deg,
      rgba(4, 7, 12, .62) 0%, rgba(4, 7, 12, .06) 12%, transparent 34%,
      rgba(4, 7, 12, .16) 62%, rgba(4, 7, 12, .80) 100%);
}
.bkx-hero { --x-read-far: left; }
.bkx-hero:dir(ltr) { --x-read-far: right; }

/* 3. SCALE. The reference's hierarchy is one very large statement and one small
 *    line under it; ours was reading as two medium ones. */
.bkx-hero .bkx-hero__say .bkx-h1 {
  font-size: clamp(2.5rem, 3.9vw + .5rem, 5.1rem);
  letter-spacing: -.028em;
  text-shadow: 0 6px 54px rgba(0, 0, 0, .78), 0 1px 2px rgba(0, 0, 0, .5);
}
.bkx-hero .bkx-hero__say { max-inline-size: min(720px, 56%); }
@media (min-width: 1280px) {
  .bkx .bkx-hero__say { max-inline-size: min(720px, 56%); }
}
.bkx-hero .bkx-hero__eyebrow { letter-spacing: .22em; }

/* 4. The haze is warmer and heavier on the sun side, so the atmosphere and the
 *    grade are lit from one place rather than two. */
.bkx-hero .bkx-hero__haze {
  opacity: .92;
  background:
    radial-gradient(40% 44% at 64% 26%, rgba(255, 200, 132, .22), transparent 70%),
    radial-gradient(48% 44% at 22% 68%, rgba(104, 142, 198, .14), transparent 74%);
}

/* The larger display needs a wider lane. At 81.6px the first Hebrew line is
   about 810px and the 720px column broke it, making THREE lines where the
   reference sets two — a bigger type size that costs the hierarchy it was
   meant to buy. Measured, not guessed: the probe reported lines:3. */
@media (min-width: 1280px) {
  .bkx .bkx-hero__say,
  .bkx-hero .bkx-hero__say { max-inline-size: min(900px, 58%); }
}

/* The plate belongs at the EDGES of the frame and nowhere else. Without this
   the bottom corner's lantern bokeh drifted across the search console — light
   sources floating over an input, which is the opposite of the depth they are
   there to create. The mask keeps the outer ring and discards the middle, so
   the plate can only ever frame the picture. */
.bkx-hero__fg {
  opacity: .88;
  -webkit-mask-image: radial-gradient(78% 74% at 50% 46%, transparent 26%, #000 88%);
          mask-image: radial-gradient(78% 74% at 50% 46%, transparent 26%, #000 88%);
}

/* == GLOBE · DESTINATION LABELS ==========================================
 * Asked for by name: "premium destination labels". The globe carried gold
 * nodes and nothing that said what they were, so the one thing the scene is
 * about — these are the cities we measure prices to — had to be read off the
 * list beside it.
 *
 * The layer is aria-hidden on purpose. The same cities are already in the
 * `.bkx-dests` list next to the globe as real links; a screen reader meeting
 * both would hear every destination twice.
 */
.bkx-globe__labels {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 3;
  /* Names are set in the page's own type, never the canvas's. */
  font-family: inherit;
}
.bkx-globe__tag {
  position: absolute;
  /*
   * PHYSICAL, not logical, and this is load-bearing. The tag's position comes
   * from projecting a 3D point to PIXELS, which are physical by definition.
   * With inset-inline-start the RTL homepage anchored every tag to the layer's
   * right edge and then added the projected x to it — measured 1630px for a
   * node the projection put at 858. Logical properties are right for text and
   * wrong for a coordinate that has already been computed.
   */
  top: 0;
  left: 0;
  /* The projected point is the NODE. The tag sits above and just clear of it,
     so the marker it names is not covered by its own name. */
  margin-top: -2.15em;
  margin-left: .55em;
  visibility: hidden;
  white-space: nowrap;
  font-size: clamp(.62rem, .48vw + .3rem, .78rem);
  font-weight: 600;
  letter-spacing: .01em;
  line-height: 1;
  padding: .34em .62em;
  border-radius: 999px;
  color: #F6ECDA;
  background: rgba(9, 13, 21, .62);
  border: 1px solid rgba(227, 190, 121, .34);
  box-shadow: 0 2px 14px rgba(0, 0, 0, .55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: opacity .18s linear;
}
@media (max-width: 760px) {
  /* At phone width twelve pills over a 320px sphere is a wall of text. */
  .bkx-globe__labels { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .bkx-globe__tag { transition: none; }
}

/* == MOBILE TOUCH + THE FINE PRINT THAT CARRIES THE TRUTH =================
 * Measured on live production at 390x844, iPhone emulation, 2026-09-05.
 */

/*
 * THE COVERFLOW DOTS WERE 7x7 CSS PIXELS — measured, eight of them, and on a
 * phone they are the ONLY tap-to-navigate control the deck has: the pointer
 * cruise is a mouse affordance and there is no cursor to put near an edge.
 * So the one control a touch reader can use was a fifth of the 44px minimum.
 *
 * The dot stays 7px. A pseudo-element carries the touch area, so the visual
 * rhythm of the pagination is unchanged and only the hit box grows. Sizing the
 * dot itself to 44px would have turned a discreet row of dots into eight
 * buttons and redesigned a section that reads correctly.
 */
.bkx-dots button { position: relative; }
/*
 * WIDTH IS THE PITCH, HEIGHT IS FREE.
 *
 * Eight 44px-wide boxes over an 8px gap would overlap by 36px each, and the
 * dot a thumb landed on would then be decided by DOM order rather than by
 * aim — worse than a small target, because it is a target that lies about
 * where it is. So the box is exactly the pitch wide (dot + gap, no overlap)
 * and takes its height freely, where nothing competes.
 *
 * 24px is WCAG 2.5.8 AA, and it is what a pitch of 24 buys without spreading
 * eight dots across the whole phone. Widening to the 44px Apple guideline
 * would need a 37px gap and would turn a discreet row into a button bar —
 * redesigning a section that reads correctly, to fix a row that swipe
 * already makes secondary.
 */
/*
 * ONE SOURCE FOR THE PITCH. The hit box is derived from the gap, so the two
 * can never disagree: widen the gap and the box widens with it, and no pair
 * of boxes can overlap by construction. Overlapping boxes are worse than
 * small ones — the dot a tap lands on would be decided by DOM order rather
 * than by aim, which is a target that lies about where it is.
 *
 * The desktop gap is left at its original 8px: a mouse does not need 24px and
 * the dot row is part of a composition that reads correctly. Only touch, where
 * the 7px dot was the ONLY tap-to-navigate control the deck has, buys the
 * wider pitch — 24px, WCAG 2.5.8 AA.
 */
.bkx-dots { --dot-gap: 8px; gap: var(--dot-gap); }
@media (max-width: 900px), (pointer: coarse) { .bkx-dots { --dot-gap: 17px; } }
.bkx-dots button::after {
  content: "";
  position: absolute;
  inset-block-start: 50%;
  /* PHYSICAL left, not inset-inline-start. transform: translate() is not
     direction-aware, so pairing it with a logical inset centres the box in
     LTR and throws it a full width off in RTL — the same physical/logical
     mismatch that put the globe labels on the wrong edge. */
  left: 50%;
  inline-size: calc(7px + var(--dot-gap));
  block-size: 44px;
  transform: translate(-50%, -50%);
}

/*
 * THE OBSERVATION TIME IS NOT DECORATION.
 *
 * `.jn-deal__obs` is the "measured at" stamp — the annotation the whole truth
 * rule rests on, since a price without its observation time is a claim rather
 * than a reading. At .68rem it computed to 10.9px on a phone, which made the
 * load-bearing sentence the least readable thing on the card. It stays visually
 * subordinate to the price; it stops being fine print you cannot read.
 */
@media (max-width: 760px) {
  .bkx .jn-deal__obs,
  .bkx .jn-deal__src,
  .bkx .jn-row__at { font-size: .78rem; }
}

/*
 * THE ANNOTATIONS THAT CARRY THE TRUTH GET A FLOOR ON MOBILE.
 *
 * Measured at 390x844 on live: the observed-price tag, the price basis, the
 * price unit and the no-service-fee statement all computed to 10.9-11.8px —
 * the whole set of sentences the product's honesty rests on, rendered as the
 * least readable text on the page. A price without a legible unit or
 * observation time is a claim rather than a reading, and the rule this site is
 * built on is that the reading has to travel with the number.
 *
 * Scope is deliberately narrow. Eyebrows, section kickers, footer headings and
 * country labels stay where they are: they are navigation, and raising every
 * small class would be a typographic redesign of a page that reads correctly.
 */
@media (max-width: 760px) {
  .bkx .jn-tag,
  .bkx .jn-deal__unit,
  .bkx .jn-row-item__claim,
  .bkx .bkx-note,
  .bkx-float .jn-shot__claim,
  .bkx .bkx-stats li span { font-size: .78rem; }
}

/* --- the origin combobox ------------------------------------------------ */
/*
 * "מאיפה יוצאים?" — the field that used to be a fixed string reading
 * "תל אביב (TLV)". It is now a real search over 3,787 airports and
 * multi-airport cities, so it needs a list that can escape the console.
 *
 * The console carries `transform: perspective(1600px) rotateX(5deg)`, which
 * makes it the containing block for anything absolute inside it — so the list
 * is positioned against the FIELD and rides the deck with it. That is why the
 * deck flattens to 0deg on :focus-within (already in .bkx-console above): a
 * list of airports read at a five-degree tilt is a list read badly.
 *
 * No `overflow: hidden` exists on .bkx-console, deliberately — adding one
 * would clip this list to the console's bottom edge.
 */
.bkx-origin { position: relative; }
  /*
   * WIDER THAN THE FIELD, because the field is a sixth of a search console.
   *
   * This was inset-inline: -1px, i.e. exactly the column width. Measured on an
   * 800px-wide pane: the list came out 99px across and the name inside it 14px,
   * so every row rendered as an icon, a code chip and a sliver of text. The
   * column is sized for a typed code; the list has to hold
   * "Paris Charles de Gaulle Airport".
   *
   * Only the START edge is pinned, so it grows away from the field in the page
   * direction — and bkx_origin.js fit() pulls it back when that would take it
   * off-screen, which no static rule can know.
   */
.bkx-origin__list {
  position: absolute;
  z-index: 40;
  inset-inline-start: -1px;
  inline-size: max(100%, min(340px, 92vw));
  max-inline-size: 92vw;
  inset-block-start: calc(100% - 2px);
  margin: 0;
  padding: .3rem;
  list-style: none;
  max-block-size: min(52vh, 340px);
  overflow-y: auto;
  overscroll-behavior: contain;
  border: 1px solid var(--x-line-2);
  border-radius: 0 0 var(--x-r-md, 14px) var(--x-r-md, 14px);
  background: var(--x-raised);
  box-shadow: var(--x-e4);
}
.bkx-origin__opt {
  display: flex;
  align-items: center;
  gap: .6rem;
  /* 44px, the same touch floor the fields keep. A list a thumb cannot hit is
     a list that sends people back to typing a code they do not know. */
  min-block-size: 44px;
  padding: .4rem .55rem;
  border-radius: 10px;
  cursor: pointer;
  color: var(--x-ink);
}
.bkx-origin__opt:hover,
.bkx-origin__opt.is-on { background: rgba(227, 190, 121, .10); }
.bkx-origin__kind { flex: none; color: var(--x-gold); font-size: .82rem; line-height: 1; }
.bkx-origin__text { min-inline-size: 0; flex: 1 1 auto; }
.bkx-origin__text b {
  display: block;
  font-weight: 600;
  font-size: .92rem;
  /* One line, ellipsised. "Paris Charles de Gaulle Airport" wrapping to three
     lines turns eight results into a page nobody scans. */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bkx-origin__text small {
  display: block;
  font-size: .74rem;
  color: var(--x-ink-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bkx-origin__code {
  flex: none;
  font-size: .74rem;
  letter-spacing: .08em;
  color: var(--x-ink-3);
  border: 1px solid var(--x-line);
  border-radius: 7px;
  padding: .12rem .38rem;
  /* The code is Latin in both languages. Without this it renders reversed
     inside the RTL row on Hebrew. */
  direction: ltr;
  unicode-bidi: isolate;
}
.bkx-origin__note {
  padding: .7rem .6rem;
  font-size: .82rem;
  color: var(--x-ink-3);
}
@media (prefers-reduced-motion: no-preference) {
  .bkx-origin__list { animation: bkx-origin-in .16s var(--x-ease, ease-out); }
  @keyframes bkx-origin-in { from { opacity: 0; transform: translateY(-4px); } }
}
