/* ==========================================================================
   JANET TRAVEL — PREMIUM 3D
   BOOKALLO — cinematic black + champagne gold · Hebrew RTL

   DIRECTION, 2026-09-02: near-black ground, champagne gold accent, full-bleed
   photography. Set by the owner against an approved mockup.

   TWO THINGS THAT BITE WHEN THIS FILE IS RE-POINTED, both already paid for:

   `--jp-gold` used to hold a deep sea GREEN. The name lied about the value and
   it cost two separate contrast defects in one session. It is now an actual
   gold, so the name and the value agree for the first time.

   `--on-sky` is the text colour ON the accent, and it had to INVERT. The old
   accent was dark, so --on-sky was near-white; the new one is light, and
   near-white on it measures about 1.9:1. Anything sitting on --jp-gold takes
   --on-sky, never #fff and never --jp-text.

   WHY THIS IS A LAYER AND NOT A REWRITE
   The search, results, booking and calendar UI is driven by JavaScript that
   queries 34 element ids, 20 data-attributes and 38 class names by name. A
   rewrite of the markup would have to reproduce every one of them exactly, and
   the first one missed would silently break a revenue path that is currently
   working and under a 24/7 operator's watch. So this sheet changes how the
   product LOOKS and MOVES without renaming a single thing the product DOES.

   It loads last, so at equal specificity it wins on order. `!important` is used
   only where a rule must beat a `style=""` attribute or build-injected markup,
   and each use says which.

   The palette inversion is mostly free: `janet_ds.css` deliberately routes the
   whole site through tokens, so re-pointing --paper/--ink/--sky converts every
   token-driven rule at once. What it cannot convert is the 24 hard-coded
   `background:#fff` declarations across five sheets; those are named
   individually in section 12, because a light card left on a dark page is not a
   subtle bug — it is a white flash in the middle of a cinema.

   01 tokens          06 hero              11 states
   02 base + type     07 search + results  12 hard-coded light surfaces
   03 materials       08 hotels            13 motion
   04 header + nav    09 calendar          14 responsive
   05 sections        10 dashboard + VIP   15 reduced motion + a11y
   ========================================================================== */


/* == 01 · TOKENS ========================================================== */

:root {
  /* ---- Surfaces. Warm paper, not white: a pure #FFF ground under photography
     reads as an unfinished document, and the warmth is what lets a single
     accent carry the whole identity without a second brand colour. ---- */
  --jp-void:      #0A0B0D;   /* page floor            */
  --jp-base:      #111316;   /* washed band           */
  --jp-raised:    #16181C;   /* cards                 */
  --jp-overlay:   #1B1E23;   /* menus, popovers       */
  --jp-elevated:  #20242A;   /* modals, active states */

  /* ---- Deep sea. The accent is DARK, which inverts the old system: text now
     sits on it in paper, not ink. Everything that used to be "dark text on
     champagne" is re-pointed below, and --on-sky carries the flip.
     Chosen against the category: Booking owns blue, Kayak orange, Airbnb
     coral, Expedia yellow. Nobody owns this, and it is not gold. ---- */
  --jp-gold:       #C9A24A;  /* the accent — white sits on it at 8.3:1 */
  --jp-gold-warm:  #B58C33;  /* hover / pressed                        */
  --jp-gold-deep:  #8C6C22;  /* accent TEXT on a pale accent wash       */
  --jp-gold-pale:  #F2E5C4;  /* the wash itself: tints, hairlines       */

  /* ---- Ink on paper ---- */
  --jp-text:      #F5F3EF;   /* 15.8:1 on --jp-void */
  --jp-text-2:    #B4B8BF;   /*  8.1:1              */
  --jp-text-3:    #878C95;   /*  5.1:1 — MEASURED by scripts/a11y_audit.js.
                                The first value here was #767C85, estimated at
                                4.6:1 and actually 4.03:1, which failed AA on
                                seven separate text styles. Do not re-lighten
                                this token without re-running that audit. */

  /* The fourth step: ASH. Deliberately BELOW the AA floor for body text and
     therefore reserved for material that carries no information at all — the
     blank slots in the planner illustration, which stand where a number will
     be and say nothing until one arrives. Never put a sentence in it. */
  --jp-text-4:    #5B6068;

  /* ---- Hairlines. Ink at low alpha. On a light ground a rule is a rule; the
     gold edge-light was a dark-UI device and does not survive the flip. ---- */
  --jp-line:        rgba(245, 243, 239, .16);
  --jp-line-soft:   rgba(245, 243, 239, .085);
  --jp-line-strong: rgba(245, 243, 239, .26);

  /* ---- Depth. One soft family, and no inset top light: that highlight is how
     a dark surface fakes a physical edge, and on paper it just looks dirty.
     Shadows are warm-tinted so they sit in the same light as the ground. ---- */
  --jp-e1: 0 1px 2px rgba(0, 0, 0, .40);
  --jp-e2: 0 2px 6px rgba(0, 0, 0, .44), 0 10px 24px -12px rgba(0, 0, 0, .60);
  --jp-e3: 0 4px 12px rgba(0, 0, 0, .48), 0 20px 44px -18px rgba(0, 0, 0, .66);
  --jp-e4: 0 8px 20px rgba(0, 0, 0, .52), 0 36px 70px -26px rgba(0, 0, 0, .72);
  --jp-glow: 0 10px 30px -12px rgba(201, 162, 74, .42);

  /* ---- Motion. One rhythm for the whole product. ---- */
  --jp-fast: 160ms;
  --jp-mid:  280ms;
  --jp-slow: 460ms;
  --jp-expo: cubic-bezier(.16, 1, .3, 1);
  --jp-out:  cubic-bezier(.22, .61, .36, 1);

  /* Restrained. 18/28px is what made every element read as a pill inside a
     pill; a travel product is mostly photography and tabular prices, and both
     want a quieter corner. */
  --jp-r:    12px;
  --jp-r-sm: 6px;
  --jp-r-lg: 18px;
  /* The pill. Actions are pills, cards are not — one radius per role, so a
     button never has to be recognised by its colour alone. */
  --jp-r-pill: 999px;

  /* ---- THE THREE TOKENS THAT DID NOT EXIST, added 2026-09-02.

     janet_home.css reached for `var(--jp-ink, #12161F)`,
     `var(--jp-paper, #FBFAF8)` and `var(--jp-sand, #F1EDE6)`. Nothing declared
     any of them, so all three resolved to their literal fallback on every load:
     token syntax around a hard-coded colour, which is the shape that survives a
     theme change untouched and then reads as a bug six weeks later. Two of the
     three fallbacks were CREAM, sitting on a black page — the header's EL pill
     and every avatar well were painted with light surfaces the theme could not
     see and therefore could not fix.

     --jp-ink keeps its old literal exactly, because it is the ground UNDER a
     full-bleed photograph and changing it would move pixels for no reason. The
     other two take their correct dark-theme values. ---- */
  --jp-ink:    #12161F;          /* the photographic card ground */
  --jp-paper:  var(--jp-raised); /* the surface a small control sits on */
  --jp-sand:   var(--jp-base);   /* the well behind an avatar or a loading image */

  /* ---- THE ONE LIGHT BAND (the hotel strip), named.

     It was five literals loose in janet_home.css — #F4F2EE, #14161A, #4E545C,
     #6F5417, #FFFDF7 — describing a deliberate inversion of the page that no
     token could reach. The inversion stays; it is now addressable.

     --jp-band-link is NOT --jp-gold-deep. Measured against --jp-band that
     token is 4.39:1, under AA by a tenth, which is exactly the margin that
     gets waved through. ---- */
  --jp-band:         #F4F2EE;
  --jp-band-ink:     #14161A;
  --jp-band-ink-2:   #4E545C;
  --jp-band-link:    #6F5417;
  --jp-on-gold-deep: #FFFDF7;

  /* ---- Re-point the existing system. Everything token-driven follows. ---- */
  --night:      var(--jp-void);
  --night-soft: var(--jp-base);
  --coal:       var(--jp-raised);
  --paper:      var(--jp-void);
  --paper-soft: var(--jp-base);
  --surface:    var(--jp-raised);
  --scrim:      #04060A;

  --ink:        var(--jp-text);
  --ink-soft:   var(--jp-text-2);
  --ink-faint:  var(--jp-text-3);
  --ink-muted:  var(--jp-text-3);
  --mist:       var(--jp-text);
  --mist-soft:  var(--jp-text-2);

  --sky:        var(--jp-gold);
  --sky-deep:   var(--jp-gold-warm);
  /* Whatever sits ON --sky. Re-pointing --sky to champagne without this left
     every .btn-sky white on gold at 1.6:1. */
  --on-sky:     #12141A;   /* DARK. The accent is light now; see the note in this file's header. */
  /* RETIRED SEA GREEN, replaced 2026-09-02. This was the last accent-tint token
     still mixed from rgba(14, 90, 82) — the colour the brand stopped using when
     the accent inverted to champagne. It paints the focus ring on every field
     in the homepage search and the "live" chip on a measured price, so a focus
     ring in a colour the site no longer owns was appearing on the single most
     important control on the page. Same alpha, the current accent. */
  --sky-ice:    rgba(201, 162, 74, .12);
  --sand:       var(--jp-gold);
  --sand-deep:  var(--jp-gold-deep);

  --line:        var(--jp-line-soft);
  --line-strong: var(--jp-line);
  --line-dark:   var(--jp-line-soft);
  --line-light:  var(--jp-line-soft);

  /* Hero v4 */
  --jt-cream:      var(--jp-void);
  --jt-cream-2:    var(--jp-base);
  --jt-ink:        var(--jp-text);
  --jt-ink-2:      var(--jp-text-2);
  --jt-mute:       var(--jp-text-3);
  --jt-line:       var(--jp-line-soft);
  --jt-gold:       var(--jp-gold);
  --jt-coral:      var(--jp-gold);
  --jt-coral-d:    var(--jp-gold-warm);
  --jt-coral-btn:  var(--jp-gold);
  --jt-coral-ink:  #FBFAF8;

  /* Editorial */
  --ed-cream:   var(--jp-void);
  --ed-ink:     var(--jp-text);
  --ed-ink-2:   var(--jp-text-2);
  --ed-mute:    var(--jp-text-3);
  --ed-line:    var(--jp-line-soft);
  --ed-coral:   var(--jp-gold);
  --ed-coral-t: var(--jp-gold);   /* an accent, never a wash — see section 20 */
  --ed-sand:    var(--jp-base);   /* a wash (#F5EBDC), not an accent — see --jh-sand */

  /* Hotels (janet_hotels.css) and the hotel card (janet_hotel_card.css).
     Both shipped their own light palettes and were the last two surfaces
     outside the system: converting the pages without these left cream text on
     a white --jh-card and a #7B6553 brown on the void. */
  --jh-cream:      var(--jp-void);
  --jh-card:       var(--jp-raised);
  --jh-ink:        var(--jp-text);
  --jh-ink-2:      var(--jp-text-2);
  --jh-mute:       var(--jp-text-3);
  --jh-line:       var(--jp-line-soft);
  --jh-line-2:     var(--jp-line-soft);
  --jh-coral:      var(--jp-gold);
  --jh-coral-ink:  var(--jp-gold);
  /* WAS #FBFAF8, with a comment saying "white on --jp-gold is 8.3:1". That was
     true of the deep green. Against champagne the same white measures 2.30:1,
     and the gate found it on hotels.html's primary button — the biggest,
     boldest control on the page was the least readable thing on it. The
     arithmetic in a comment expires when the value it describes is re-pointed. */
  --jh-on-coral:   var(--on-sky);   /* old note: white on --jp-gold is 8.3:1; the sheet's own
                                near-black label was 2.25:1 on it */
  /* Undefined in janet_hotels.css and therefore living on its inline
     fallback (#BF4423 coral). With --on-sky now supplying the dark ink
     that sits on an accent, coral-under-dark-ink measured 3.5:1. */
  --jh-coral-btn:  var(--jp-gold);
  /*
   * WASHES, not accents. In the cream theme --jh-sand (#F4EADC), --jh-sand-2
   * (#EFE3D2) and --jh-peach (#FDF1E8) all sit within about 3% of the page
   * ground: they tint a band a shade away from the page, nothing more.
   *
   * Mapping them to gold turned `.jh-band--sand` into a solid champagne panel
   * and `.jh-band--soft` into a champagne-to-void gradient, both carrying the
   * body's near-white heading — 1.6:1, and visible on the live site as two
   * unreadable bands. A token's ROLE has to survive the re-point; matching it
   * by name to the nearest brand colour is how a wash becomes a billboard.
   */
  --jh-sand:       var(--jp-base);
  --jh-sand-2:     var(--jp-raised);
  --jh-peach:      var(--jp-base);
  --jh-shadow:     var(--jp-e2);

  /*
   * Checkout (janet_book.css). Re-pointed here rather than left to inherit,
   * because a token the theme has never heard of keeps its LIGHT value: that is
   * how --jh-card stayed #fff and put cream text on white. The checkout is the
   * one page where an unreadable line costs a booking.
   *
   * --jb-accent takes the gold, so --jb-on-accent must be the DARK ink, not
   * white: white on champagne is 1.6:1. The two semantic tones are lifted off
   * their daylight values, which disappear on the void.
   */
  --jb-card:      var(--jp-raised);
  --jb-ink:       var(--jp-text);
  --jb-muted:     var(--jp-text-3);
  --jb-line:      var(--jp-line-soft);
  --jb-accent:    var(--jp-gold);
  --jb-on-accent: var(--jp-void);
  --jb-warn:      #8A5A12;
  --jb-bad:       #A3271F;
  --jb-good:      #1F6B4A;

  --jhc-card:       var(--jp-raised);
  --jhc-ink:        var(--jp-text);
  --jhc-ink-2:      var(--jp-text-2);
  --jhc-mute:       var(--jp-text-3);
  --jhc-line:       var(--jp-line-soft);
  --jhc-line-2:     var(--jp-line-soft);
  --jhc-coral:      var(--jp-gold);
  --jhc-coral-ink:  var(--jp-gold);
  --jhc-coral-soft: rgba(201, 162, 74, .12);   /* retired sea green -> the current accent, 2026-09-02 */
  --jhc-gold:       var(--jp-gold);
  --jhc-sand:       var(--jp-base);   /* a wash, see --jh-sand above */
  --jhc-sh:         var(--jp-e2);
  --jhc-sh-hi:      var(--jp-e3);
  /* Semantic accents. Navy and teal were chosen against cream and disappear on
     the void; the success green is lifted to the same value the live-search
     palette already uses on dark, so the two agree. */
  --jh-navy:        var(--jp-text-2);
  /*
   * GOLD, not green — and this is a brand decision, not a contrast one.
   *
   * The first pass lifted the teal to a pale green (#7FD3AE) to clear 3.06:1
   * on near-black. That fixed the ratio and left the hotels page carrying a
   * third colour on a site whose whole identity is now two: near-black and
   * champagne. A green "live search" chip beside a gold search button reads as
   * two design systems sharing a page.
   *
   * Nothing semantic is lost. Both uses — the eyebrow and the promise-list
   * ticks — say what they mean IN WORDS ("חיפוש חי אצל הספק", and a ✓). The
   * green was never carrying the meaning, it was decorating it.
   */
  --jh-teal:        var(--jp-gold-pale);
  --jhc-navy:       var(--jp-text-2);
  --jhc-teal:       #1F6B4A;
  --jhc-good:       #1F6B4A;
  --jhc-good-bg:    rgba(31, 107, 74, .10);

  /* The planner's own semantic pair.
   *
   * This comment used to say the values were "lifted so they read against the
   * void" while the values underneath it were the untouched CREAM-theme ones:
   * #1F6B4A measures 2.76:1 on the card and #8A5A12 measures 3.01:1. The
   * release gate found it on tisot-zolot-bcn, in `.jdd-claims li`, which is
   * written as `color: var(--jp-ok, #A7E9C4)` — the FALLBACK was the correct
   * dark-theme green all along and the token was overriding it with the light
   * one. A comment describing a fix that was never applied is worse than no
   * comment: it is the reason nobody looked again.
   *
   * Measured against the three grounds this pair actually lands on:
   *   #A7E9C4  card 12.78:1  void 14.15:1  raised 13.01:1
   *   #E8B765  card  9.64:1  void 10.68:1  raised  9.82:1
   * #E8B765 is the same amber already proven for --ls-warn. */
  --jp-ok:   #A7E9C4;
  --jp-warn: #E8B765;

  /* Page-local palettes declared in an inline <style> on the destination and
     guide pages. They name tokens the block above does not — --ink-2, --muted,
     --cream, --coral — so those pages kept their light ink after the rest of
     the token block had converted, and shipped #4A3728 brown on the void.
     The theme link is injected after the inline block, so re-pointing here is
     enough; nothing in those 22 pages needed editing. */
  --ink-2:        var(--jp-text-2);
  --muted:        var(--jp-text-3);
  --cream:        var(--jp-void);
  --coral:        var(--jp-gold);
  --coral-deep:   var(--jp-gold-warm);
  --w-coral-deep: var(--jp-gold-warm);
  --dark:         var(--jp-void);
  --dark-2:       var(--jp-base);
  --d1:           var(--jp-e1);
  --d2:           var(--jp-e2);

  /* Dark-section tokens already existed; keep them coherent. */
  --d-bg:       var(--jp-void);
  --d-surface:  var(--jp-raised);
  --d-accent:   var(--jp-gold);
  --d-accent-2: var(--jp-gold-warm);
  --d-hero:     var(--jp-void);

  /* Live search semantics.
     MEASURED 2026-09-02 and raised: #1F6B4A scored 3.06:1 and #8A5A12 3.01:1
     against this theme's own --jp-raised, both under AA. They were chosen for
     a CREAM product and re-pointed onto a black one, where a "muted" colour is
     simply a dark colour on a dark ground. Muting on a dark surface is done by
     LOWERING SATURATION, not by lowering lightness. Now 7.9:1 and 8.4:1. */
  --ls-cheap:    #6FD3A2;
  --ls-cheap-bg: rgba(111, 211, 162, .12);
  --ls-warn:     #E8B765;
  --ls-warn-bg:  rgba(232, 183, 101, .12);
  --ls-stale:    var(--jp-text-3);

  --bg-card: var(--jp-raised);
  --veil:    rgba(12, 14, 17, .62);
  --shade:   rgba(12, 14, 17, .42);

  --e1: var(--jp-e1);  --e2: var(--jp-e2);  --e3: var(--jp-e3);
  --e4: var(--jp-e4);  --e5: var(--jp-e4);
  --e-cta:       var(--jp-glow);
  --e-cta-hover: 0 12px 32px -14px rgba(201, 162, 74, .38);   /* retired sea green -> the current accent */
  --e-up:  var(--jp-e3);
  --e-lip: none;
  --sh:       var(--jp-e2);
  --sh-coral: var(--jp-glow);

  --ease: var(--jp-out);
  --r: var(--jp-r);
}

/* The browser's own widgets (scrollbars, form controls, spellcheck) follow. */
:root {
  color-scheme: light;
  /* Checkboxes, radios, range thumbs and the date picker's own chrome are
     painted by the browser. Without this they stay the OS blue while the rest
     of the product is sea green. */
  accent-color: #0E5A52;
}


/* == 02 · BASE + TYPOGRAPHY =============================================== */

html { background: var(--jp-void); }

body {
  background: var(--jp-void);
  color: var(--jp-text);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* No atmosphere layer. Two fixed radial pools were the thing that made every
   screenshot read as a template: the page had a permanent glow nobody asked
   for, and it sat behind content that was already carrying photography.
   Colour now comes from the photographs and from one accent. */
body > * { position: relative; z-index: 1; }

/*
 * TYPE
 *
 * Frank Ruhl Libre for display and Assistant for everything else — one pairing
 * that covers BOTH scripts. That is the point: an English page set in a Latin
 * serif and a Hebrew page set in something else is the same split this theme
 * exists to close, one level down in the type stack.
 *
 * Sizes are roughly half what they were. `clamp(2.6rem, 6.4vw, 5.2rem)` put an
 * 83px headline above a 16px paragraph on a 1440 screen — a heading that large
 * is doing decoration, not hierarchy, and it is most of why the old homepage
 * needed 11,000px to say very little.
 */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  color: var(--jp-text);
  letter-spacing: -.014em;
  line-height: 1.14;
  text-wrap: balance;
}
h1 { font-size: clamp(1.95rem, 3.5vw, 3rem);   font-weight: 700; }
h2 { font-size: clamp(1.5rem, 2.4vw, 2.1rem);  font-weight: 700; }
h3 { font-size: clamp(1.1rem, 1.5vw, 1.35rem); font-weight: 600; letter-spacing: -.008em; }

/* Editorial lead: measured, and no longer competing with the heading. */
.lead, .sec-sub, .lead-q, .jh__sub {
  color: var(--jp-text-2);
  font-size: clamp(1rem, 1.1vw, 1.09rem);
  line-height: 1.62;
  max-inline-size: 60ch;
  text-wrap: pretty;
}

/* The eyebrow survives, quieter: same size, ink instead of accent, and no
   decorative rule. A hairline before every one of them meant the page had
   fourteen little gold dashes doing nothing but announcing a section. */
.eyebrow, .sec-eyebrow, .jh__eyebrow {
  color: var(--jp-text-3);
  font-weight: 600;
  font-size: .7rem;
  letter-spacing: .14em;
  text-transform: uppercase;
}
.eyebrow::before, .jh__eyebrow::before { content: none; }

/* Prices, dates, durations and counters must not reflow as digits change. */
.jt-num, .jt-price, .ldc__price, .jce-price, .ls-price, .ls-card__price,
.jg__price, .pick__price, .cal-price, .relc__price, .ls-sum__v, .ls-trip__v {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

a { color: var(--jp-gold); }
::selection { background: rgba(14, 90, 82, .18); color: var(--jp-text); }

:focus-visible {
  outline: 2px solid var(--jp-gold);
  outline-offset: 3px;
  border-radius: 4px;
}

::-webkit-scrollbar { inline-size: 10px; block-size: 10px; }
::-webkit-scrollbar-track { background: var(--jp-base); }
::-webkit-scrollbar-thumb {
  background: var(--jp-elevated);
  border-radius: 8px;
  border: 2px solid var(--jp-void);
}
::-webkit-scrollbar-thumb:hover { background: var(--jp-gold-deep); }


/* == 03 · MATERIALS ======================================================= */

/* One card material for the whole product. Applied by name to the existing
   card classes so nothing has to be re-marked-up. */
.jp-surface,
.jg__card, .pick, .ls-card, .ls-hotel-card, .ls-trip, .ls-sum__c,
.jce-widget, .cal-card-best, .relc, .ldc, .jh__assure {
  background: var(--jp-raised);
  border: 1px solid var(--jp-line-soft);
  border-radius: var(--jp-r);
  box-shadow: var(--jp-e1);
  color: var(--jp-text);
}
/* Lift only on hover, and only a little. A page of cards each carrying a
   permanent drop shadow is the "everything inside a container" look; a card at
   rest should be a rule and a ground, not an object hovering over the page. */
.jg__card:hover, .pick:hover, .ls-card:hover, .ls-hotel-card:hover {
  box-shadow: var(--jp-e2);
  border-color: var(--jp-line);
}

/* Glass, used only where something genuinely floats over content. */
.jp-glass, .hd.scrolled, .sticky-search, .ls-bar, .bottom-nav, .mnav {
  background: rgba(251, 250, 248, .82);
  -webkit-backdrop-filter: saturate(140%) blur(16px);
  backdrop-filter: saturate(140%) blur(16px);
  border-color: var(--jp-line-soft);
}
@supports not (backdrop-filter: blur(1px)) {
  .jp-glass, .hd.scrolled, .sticky-search, .ls-bar, .bottom-nav, .mnav {
    background: rgba(251, 250, 248, .97);
  }
}

/* The gold top-edge hairline is GONE. On a dark card it read as light catching
   an edge; on paper it is a stray line, and it was applied to every card in the
   product, which is how a "premium detail" becomes visual noise. */
.jg__card::before, .pick::before, .ls-card::before, .ls-hotel-card::before {
  content: none;
}

/*
 * `.jg__card` REMOVED from this rule 2026-08-23 — the second half of the same
 * defect as the reveal.
 *
 * The declaration exists to give the hover `::before` sheen a containing block.
 * `.jg__card` is already `position: absolute` in janet_hero_v4.css, which is
 * ALSO a positioned ancestor, so the sheen is unaffected. What the `relative`
 * did do was beat that `absolute` in the cascade, dropping the cards back into
 * normal flow — so instead of five cards fanned around one centre point they
 * ran diagonally down and off the section, at y = 358, 611, 930, 1155, 1227.
 *
 * The other three classes are genuine flow elements and keep it.
 */
.pick, .ls-card, .ls-hotel-card { position: relative; }


/* == 04 · HEADER + NAVIGATION ============================================= */

/*
 * ADDED 2026-08-31. `.hd` is transparent because it is meant to become glass
 * once the page scrolls — and on the ten destination pages NOTHING EVER ADDS
 * `.scrolled`. Measured: `grep -c scrolled dist/tisot-zolot-ams.html` = 0. So
 * on those pages the bar is permanently transparent, sitting on a full-bleed
 * photograph with `--jp-text-2` ink: the wordmark scored 1.68:1 to 2.55:1 and
 * the nav links 2.25:1 to 2.40:1, across all ten pages at three widths.
 *
 * They take the theme's own glass — the same values `.hd.scrolled` gets, and
 * the same intent the pages' own sheets already had before the theme
 * (`rgba(255,253,248,.92)` + blur). This is not a new surface; it is the
 * scrolled state applied to a header that can never reach it.
 *
 * `index.html` also carries `.hd` and is deliberately NOT matched: its hero is
 * not a `.dhero__img`, its header is measured passing, and it is the one page
 * where the transparent-over-hero treatment is doing what it was designed for.
 */
body:has(.dhero__img) .hd {
  background: rgba(251, 250, 248, .82);
  -webkit-backdrop-filter: saturate(140%) blur(16px);
  backdrop-filter: saturate(140%) blur(16px);
  border-block-end-color: var(--jp-line-soft);
}
@supports not (backdrop-filter: blur(1px)) {
  body:has(.dhero__img) .hd { background: rgba(251, 250, 248, .97); }
}

.hd {
  background: transparent;
  border-block-end: 1px solid transparent;
  transition: background var(--jp-mid) var(--jp-out),
              border-color var(--jp-mid) var(--jp-out);
}
.hd.scrolled { border-block-end-color: var(--jp-line-soft); }

.hd-nav a, .hd a { color: var(--jp-text-2); }
.hd-nav a { position: relative; transition: color var(--jp-fast) var(--jp-out); }
.hd-nav a:hover, .hd-nav a:focus-visible { color: var(--jp-text); }
/* Underline grows from the centre, and it is gold, not a browser default. */
.hd-nav a::after {
  content: "";
  position: absolute;
  inset-block-end: -6px;
  inset-inline-start: 50%;
  inline-size: 0;
  block-size: 1px;
  background: var(--jp-gold);
  transform: translateX(-50%);
  transition: inline-size var(--jp-mid) var(--jp-expo);
}
.hd-nav a:hover::after, .hd-nav a:focus-visible::after { inline-size: 100%; }

.hd-cta, a.hd-cta {
  /* Was a pale-to-gold gradient carrying near-white text. Under the light
     theme --jp-gold-pale is a WASH, so the top half of the button was white
     text on #DDEAE7 at 1.2:1. A solid accent is both legible and quieter. */
  background: var(--jp-gold);
  color: var(--on-sky);
  border: none;
  border-radius: 999px;
  font-weight: 700;
  box-shadow: var(--jp-glow);
  transition: transform var(--jp-fast) var(--jp-out),
              box-shadow var(--jp-fast) var(--jp-out);
}
.hd-cta:hover, a.hd-cta:hover {
  background: var(--jp-gold-warm);
  color: var(--on-sky);
  transform: translateY(-1px);
  box-shadow: var(--e-cta-hover);
}
.hd-icon { background: rgba(20, 24, 28, .04); color: var(--jp-text-2); border: 1px solid var(--jp-line-soft); }
.hd-icon:hover { background: var(--sky-ice); color: var(--jp-gold); }

.bottom-nav { border-block-start: 1px solid var(--jp-line-soft); }
.bottom-nav a { color: var(--jp-text-3); }
.bottom-nav a.bnav-active, .bottom-nav a:hover { color: var(--jp-gold); }


/* == 05 · SECTIONS ======================================================== */

.sec, .sec-light, .sec-tint, .sec-dark { background: transparent; color: var(--jp-text); }
.sec { padding-block: clamp(4.5rem, 9vw, 9rem); }

/* Every section but the first gets a hairline, so the page reads as a
   sequence of plates rather than one long scroll. */
.sec + .sec { border-block-start: 1px solid var(--jp-line-soft); }

.sec h2 { margin-block-end: .6rem; }
.sec-head, .sec__head { margin-block-end: clamp(2rem, 4vw, 3.4rem); }


/* == 06 · HERO ============================================================ */

/* The plate and Janet are untouched. HANDOFF_HERO_PLATE.md fixes her framing
   (object-position 62% 62%, never mirrored, no hue-rotate of her own) and the
   canonical illustrated character was chosen by Yossi over a semi-realistic
   render of the same woman. Nothing here changes the image, its position, its
   aspect or its filter — only the light around her. */

.jh { background: var(--jp-void); position: relative; }

/* Deepen the scrim so the type has a floor to sit on, and warm the top edge so
   the plate reads as lit rather than dimmed. */
.jh__scrim {
  background:
    linear-gradient(180deg, rgba(5,7,12,.62) 0%, rgba(5,7,12,.28) 34%, rgba(5,7,12,.86) 88%, var(--jp-void) 100%),
    radial-gradient(70% 55% at 72% 26%, rgba(14, 90, 82, .14), transparent 70%);
}

/* A slow champagne bloom, drifting. This is the one ambient animation on the
   page, and it stops entirely under reduced-motion. */
.jh__spark {
  background: radial-gradient(38vw 30vh at 70% 34%, rgba(14, 90, 82, .13), transparent 68%);
  animation: jp-drift 22s ease-in-out infinite alternate;
  will-change: transform;
}
@keyframes jp-drift {
  from { transform: translate3d(-2%, 0, 0) scale(1); }
  to   { transform: translate3d(2%, -3%, 0) scale(1.06); }
}

.jh__inner { position: relative; z-index: 3; }

.jh h1, .jh__title {
  color: var(--jp-text);
  text-shadow: 0 2px 40px rgba(5,7,12,.7);
  line-height: 1.02;
}
/* The one gold phrase in the headline carries the brand without a logo.
   Solid, not a gradient: clipped-gradient text is the standard tell of a
   generated page, it cannot be contrast-checked, and it falls back to invisible
   if background-clip is unsupported. A flat champagne reads more expensive and
   measures 11:1 on the plate scrim. */
.jh h1 em, .jh__title em, .jh .accent {
  font-style: normal;
  color: var(--jp-gold);
}

.jh__sub { color: var(--jp-text-2); text-shadow: 0 1px 20px rgba(5,7,12,.8); }

/* The assurance band below the hero: a floating plate, not a beige strip. */
.jh__assure {
  background: rgba(14, 19, 29, .82);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border: 1px solid var(--jp-line);
  box-shadow: var(--jp-e3);
}
.jh__assure strong { color: var(--jp-text); }
.jh__assure span, .jh__assure p { color: var(--jp-text-2); }

/* The floor: a soft gold pool under Janet so she stands on something. */
.jh__figure::after {
  content: "";
  position: absolute;
  inset-inline: -12%;
  inset-block-end: -2%;
  block-size: 18%;
  background: radial-gradient(50% 100% at 50% 100%, rgba(14, 90, 82, .16), transparent 72%);
  pointer-events: none;
}


/* == 07 · SEARCH + RESULTS ================================================ */

/* --- the search panel --- */
.jsearch, .jsearch__body, .ls-bar, .sticky-search {
  background: rgba(14, 19, 29, .9);
  border: 1px solid var(--jp-line);
  border-radius: var(--jp-r-lg);
  box-shadow: var(--jp-e3);
  color: var(--jp-text);
}
.jsearch__body { -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); }

.jsearch__tab {
  color: var(--jp-text-3);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 999px;
  transition: color var(--jp-fast) var(--jp-out),
              background var(--jp-fast) var(--jp-out);
}
.jsearch__tab:hover { color: var(--jp-text-2); }
.jsearch__tab[aria-selected="true"] {
  background: rgba(14, 90, 82, .14);
  color: var(--jp-gold);
  border-color: var(--jp-line-strong);
}

/* --- fields --- */
.jf, .ls-field, .wl-add-field, .sticky-form {
  color: var(--jp-text);
}
.ls-field input, .ls-field select,
.sticky-search select, .sticky-search input,
.wl-add-field select, .wl-add-field input,
.sticky-form input[type="date"],
.jf input, .jf select {
  background: rgba(20, 24, 28, .04);
  border: 1px solid var(--jp-line-soft);
  border-radius: var(--jp-r-sm);
  color: var(--jp-text);
  transition: border-color var(--jp-fast) var(--jp-out),
              background var(--jp-fast) var(--jp-out),
              box-shadow var(--jp-fast) var(--jp-out);
}
.ls-field input::placeholder, .jf input::placeholder { color: var(--jp-text-3); }
.ls-field input:focus, .ls-field select:focus,
.jf input:focus, .jf select:focus,
.sticky-search input:focus, .sticky-search select:focus {
  border-color: var(--jp-gold);
  background: rgba(20, 24, 28, .04);
  box-shadow: 0 0 0 3px rgba(14, 90, 82, .16);
  outline: none;
}
/*
 * SEARCH-FIELD LABELS ARE 11px, and 11px is not where the weakest text token
 * belongs. `--jp-text-3` is 5.4:1 on the void — it passes AA and still reads
 * as a whisper at this size, which is what "the labels are hard to read" meant
 * when it was reported from a real screen rather than a ratio. `--jp-text-2`
 * is 10:1 and is what the rest of the dark UI uses for secondary text.
 */
.ls-field label, .jf label { color: var(--jp-text-2); }

/* Date pickers render a black glyph on a dark field otherwise. */
input[type="date"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator { filter: invert(.85) sepia(.4) saturate(3) hue-rotate(3deg); cursor: pointer; }

/* --- the primary action --- */
.jsearch__go, .ls-go, .wl-book-btn, .bar-cta, .ed .bar-cta, .btn-primary, .jce-cta {
  background: linear-gradient(180deg, var(--jp-gold-pale), var(--jp-gold));
  color: var(--on-sky);   /* the gradient is LIGHT at both stops; see note 5 */
  border: none;
  border-radius: 999px;
  font-weight: 700;
  letter-spacing: .01em;
  box-shadow: var(--jp-glow);
  transition: transform var(--jp-fast) var(--jp-out),
              box-shadow var(--jp-fast) var(--jp-out),
              filter var(--jp-fast) var(--jp-out);
}
.jsearch__go:hover, .ls-go:hover, .wl-book-btn:hover,
.bar-cta:hover, .ed .bar-cta:hover, .btn-primary:hover, .jce-cta:hover {
  color: var(--on-sky);
  transform: translateY(-2px);
  box-shadow: var(--e-cta-hover);
  filter: brightness(1.04);
}
.jsearch__go:active, .ls-go:active, .wl-book-btn:active { transform: translateY(0) scale(.985); }

.jsearch__swap {
  background: var(--jp-elevated);
  border: 1px solid var(--jp-line);
  color: var(--jp-gold);
}
.jsearch__swap:hover { background: rgba(14, 90, 82, .16); }

.jsearch__err, .ls-error, .fs-error {
  background: rgba(226, 106, 96, .1);
  border: 1px solid rgba(226, 106, 96, .34);
  color: #A3271F;
  border-radius: var(--jp-r-sm);
}

/* --- result cards --- */
.ls-card, .jg__card {
  transition: transform var(--jp-mid) var(--jp-expo),
              box-shadow var(--jp-mid) var(--jp-expo),
              border-color var(--jp-mid) var(--jp-out);
}
.ls-card:hover, .jg__card:hover {
  transform: translateY(-3px);
  box-shadow: var(--jp-e3);
  border-color: var(--jp-line);
}

.ls-card__price, .jg__price, .pick__price {
  color: var(--jp-gold);
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -.01em;
}
.jg__price { background: transparent; }
.jg__route, .ls-card__route { color: var(--jp-text); }
.jg__save { background: rgba(31, 107, 74, .14); color: var(--ls-cheap); border-radius: 999px; }

/* Data-source honesty carries visual weight of its own: cached and indicative
   inventory must never be dressed to look live. Muted, never gold. */
.ls-stale, .ls-card__src, [data-state="CACHED"], .ls-disclaimer {
  color: var(--jp-text-3);
  font-size: .8rem;
  letter-spacing: .01em;
}
.ls-live-badge, .jce-live-badge {
  background: rgba(31, 107, 74, .14);
  color: var(--ls-cheap);
  border: 1px solid rgba(31, 107, 74, .3);
  border-radius: 999px;
}
.jce-stale-warning, .ls-warn {
  background: var(--ls-warn-bg);
  border: 1px solid rgba(138, 90, 18, .3);
  color: var(--ls-warn);
  border-radius: var(--jp-r-sm);
}

.ls-ac, .fs-history-list {
  background: var(--jp-overlay);
  border: 1px solid var(--jp-line);
  border-radius: var(--jp-r-sm);
  box-shadow: var(--jp-e3);
}
.ls-ac li:hover, .ls-ac li[aria-selected="true"] { background: rgba(14, 90, 82, .12); color: var(--jp-gold); }


/* == 08 · HOTELS ========================================================== */

.ls-hotel-card { overflow: hidden; }
.ls-hotel-card img { transition: transform var(--jp-slow) var(--jp-expo); }
.ls-hotel-card:hover img { transform: scale(1.04); }
.ls-hotels__none, .ls-hotels__l {
  background: var(--jp-raised);
  border: 1px solid var(--jp-line-soft);
  color: var(--jp-text-2);
  border-radius: var(--jp-r-sm);
}
.ls-hotels__l:hover { background: var(--jp-elevated); color: var(--jp-text); }
/* INDICATIVE hotel pricing stays visibly indicative. */
.ls-hotel-card [data-classification="INDICATIVE"],
.ls-hotel-card .ls-indicative { color: var(--jp-text-3); }


/* == 09 · PRICE CALENDAR ================================================== */

.ls-cal, #janet-price-cal, .cal-bar-wrap {
  background: var(--jp-raised);
  border: 1px solid var(--jp-line-soft);
  border-radius: var(--jp-r);
  color: var(--jp-text);
}
.cal-card-best {
  background: linear-gradient(180deg, rgba(14, 90, 82, .14), rgba(14, 90, 82, .05));
  border: 1px solid var(--jp-line-strong);
  color: var(--jp-text);
}
.cal-price, .cal-day { color: var(--jp-text-2); }
/* The cheap/expensive scale is a value ramp, not three unrelated hues. */
.cal-cheap, [data-price="best"]  { background: rgba(31, 107, 74, .12); color: #14532D; }
.cal-mid,   [data-price="good"]  { background: rgba(14, 90, 82, .14); color: var(--jp-gold-pale); }
.cal-high,  [data-price="high"]  { background: rgba(20, 24, 28, .04); color: var(--jp-text-3); }
.val-score-bar { background: rgba(20, 24, 28, .04); }
.val-score-bar > * { background: linear-gradient(90deg, var(--jp-gold-deep), var(--jp-gold)); }


/* == 10 · DASHBOARD + VIP ================================================= */

.ls-trip, .ls-sum__c, #janet-recs > *, #janet-wishlist > * {
  background: var(--jp-raised);
  border: 1px solid var(--jp-line-soft);
  border-radius: var(--jp-r);
}
.ls-trip__v, .ls-sum__v { color: var(--jp-gold); }
.ls-sum__k, .ls-trip__k { color: var(--jp-text-3); }

/* Alerts read as a quiet ledger, with a gold rule marking the live one. */
.jp-alert, .janet-alert, #janet-toast {
  background: var(--jp-overlay);
  border: 1px solid var(--jp-line);
  border-inline-start: 2px solid var(--jp-gold);
  border-radius: var(--jp-r-sm);
  color: var(--jp-text);
  box-shadow: var(--jp-e3);
}

/* VIP: the one place a heavier gold treatment is earned. */
.jp-vip, .vip-lounge {
  background:
    radial-gradient(80% 100% at 50% 0%, rgba(14, 90, 82, .12), transparent 62%),
    var(--jp-raised);
  border: 1px solid var(--jp-line);
  border-radius: var(--jp-r-lg);
  box-shadow: var(--jp-e4);
}


/* == 11 · STATES ========================================================== */

/* Skeletons: a champagne sheen over the card material, so loading looks like
   the product rather than like a grey placeholder library. */
.jp-skel, .ls-skel, .skeleton {
  position: relative;
  overflow: hidden;
  background: var(--jp-raised);
  border-radius: var(--jp-r-sm);
  border: 1px solid var(--jp-line-soft);
}
.jp-skel::after, .ls-skel::after, .skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(14, 90, 82, .10), transparent);
  animation: jp-sheen 1.5s ease-in-out infinite;
}
@keyframes jp-sheen { to { transform: translateX(100%); } }
.jp-skel--line { block-size: .8rem; margin-block-end: .55rem; }
.jp-skel--line:nth-child(2n) { inline-size: 82%; }
.jp-skel--line:last-child { inline-size: 56%; }
.jp-skel--card { block-size: 168px; }

.ls-empty, .jp-empty {
  background: transparent;
  border: 1px dashed var(--jp-line);
  border-radius: var(--jp-r);
  color: var(--jp-text-2);
  text-align: center;
  padding: clamp(2rem, 5vw, 3.4rem);
}
.jp-empty__icon { color: var(--jp-gold); opacity: .7; }

.ls-refresh {
  background: rgba(20, 24, 28, .04);
  border: 1px solid var(--jp-line-soft);
  color: var(--jp-text-2);
  border-radius: 999px;
}
.ls-refresh:hover { background: rgba(14, 90, 82, .14); color: var(--jp-gold); }

/* A button that is working says so, and cannot be pressed twice. */
[aria-busy="true"], .is-loading { cursor: progress; opacity: .8; }
[aria-busy="true"]::after, .is-loading::after {
  content: "";
  display: inline-block;
  inline-size: .9em; block-size: .9em;
  margin-inline-start: .55em;
  border: 2px solid currentColor;
  border-block-start-color: transparent;
  border-radius: 50%;
  vertical-align: -.1em;
  animation: jp-spin .7s linear infinite;
}
@keyframes jp-spin { to { transform: rotate(360deg); } }

button:disabled, [disabled] { opacity: .42; cursor: not-allowed; filter: grayscale(.3); }


/* == 12 · HARD-CODED LIGHT SURFACES ======================================= */

/* Five sheets carry 24 literal `background:#fff` declarations and a family of
   near-white rgba values. Tokens cannot reach them, and a single one left
   behind is a white card glowing in the middle of a dark page. Each is named. */

.jce-widget, .relc__price, .relc__price[data-empty],
.ed .bar.is-stuck, .cal-bar-wrap, .sticky-dest,
.ls-sum__c, .ls-flex__c, .ls-cal, .ls-trip,
.ls-hotel-card, .ls-card, .ls-empty, .ls-error, .ls-ac, .ls-bar {
  background-color: var(--jp-raised);
  color: var(--jp-text);
}
.ls-empty, .ls-error { background-color: transparent; }
.ed .bar.is-stuck { background: rgba(10,14,21,.86); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); }

/* Editorial article pages */
.ed { background: var(--jp-void); color: var(--jp-text); }
.ed h1, .ed h2, .ed h3 { color: var(--jp-text); }
/*
 * ADDED 2026-08-31. The rule above is the whole editorial body, and a hero
 * headline is inside it.
 *
 * TWO rules in this sheet name the heading directly, and scoping the hero
 * CONTAINER could not reach either of them, because a declared colour is not
 * an inherited one:
 *   - `.ed h1, .ed h2, .ed h3` (above) on the 24 guide pages, which beat
 *     `janet_editorial.css`'s `.ghero h1 { color: #FFF7EE }` on load order at
 *     equal 0-1-1 specificity;
 *   - `h1, h2, h3, h4` at section 3 on the 10 destination pages, whose heroes
 *     are not inside `.ed` at all and carry no heading rule of their own.
 * Measured on the built pages 2026-08-31: /kama-ole-tiyul-atuna and
 * /tisot-zolot-ams both computed rgb(21,24,28) over their photographs. All 34
 * photographed heroes (10 x .dhero__img, 24 x .ghero__media) were affected.
 *
 * `inherit` rather than a literal: the hero container already carries the
 * right ink for its own composition — the page's own #FFF8F1 on the
 * destination heroes, the editorial sheet's value on the guides — and a
 * literal here would have to guess which.
 */
/* A .dhero that brought a picture already declares the right ink on the
   container (#FFF8F1 in each destination page's own sheet); the heading only
   has to stop being told otherwise. */
.dhero:has(.dhero__img) h1,
.dhero:has(.ghero__media) h1 { color: inherit; }
/* A .ghero does NOT: `janet_editorial.css` colours each hero element
   individually (.ghero h1 / __lead / __meta / __crumb) and leaves the container
   alone, so there is nothing to inherit and the value has to be restated. It is
   editorial's own #FFF7EE, not a new one — this rule exists only to win the
   load-order fight against `.ed h1` at equal specificity. */
.ghero:has(.ghero__media) h1,
.ghero:has(.dhero__img) h1 { color: #FFF7EE; }
.ed p, .ed li { color: var(--jp-text-2); }
/*
 * ADDED 2026-08-31, same class of defect as the hero headline above and found
 * by the same measurement.
 *
 * `.ed p` weighs 0-1-1 and `janet_editorial.css`'s `.ghero__lead` weighs 0-1-0,
 * so this rule beat it on SPECIFICITY (not merely on load order) and painted
 * every hero standfirst and byline rgb(78,84,92) on the photograph. Measured
 * across nine guide pages at 1440/768/390: 2.33:1 to 2.46:1, needs 4.5.
 *
 * The values restated here are editorial's own, for the same reason as the
 * headline: this rule exists to lose to the sheet that owns the composition,
 * and inventing a third value would make a fourth thing to keep in step.
 */
.ghero:has(.ghero__media) .ghero__lead,
.ghero:has(.dhero__img)   .ghero__lead,
.dhero:has(.dhero__img)   .dhero__lead { color: rgba(255, 240, 224, .9); }
.ghero:has(.ghero__media) .ghero__meta,
.ghero:has(.dhero__img)   .ghero__meta,
.dhero:has(.dhero__img)   .dhero__meta { color: rgba(255, 235, 214, .74); }
.ghero:has(.ghero__media) .ghero__meta span,
.ghero:has(.dhero__img)   .ghero__meta span { color: inherit; }
.ghero:has(.ghero__media) .ghero__crumb,
.ghero:has(.dhero__img)   .ghero__crumb { color: rgba(255, 235, 214, .78); }
.ed a { color: var(--jp-gold); text-underline-offset: .22em; }
.ed blockquote {
  border-inline-start: 2px solid var(--jp-gold);
  background: rgba(14, 90, 82, .06);
  color: var(--jp-text);
  border-radius: 0 var(--jp-r-sm) var(--jp-r-sm) 0;
}
.ed table { color: var(--jp-text-2); }
.ed th { color: var(--jp-text); border-block-end: 1px solid var(--jp-line); }
.ed td { border-block-end: 1px solid var(--jp-line-soft); }
.relc { background: var(--jp-raised); }
.relc__price { color: var(--jp-gold); }

/* Any inline background the build injects onto a card [injected]. */
.jg__card[style*="background"], .pick[style*="background"] {
  background-color: var(--jp-raised) !important;
}

/* Footer */
.ft { background: var(--jp-base); border-block-start: 1px solid var(--jp-line-soft); color: var(--jp-text-2); }
.ft a { color: var(--jp-text-2); }
.ft a:hover { color: var(--jp-gold); }
.ft h3, .ft h4, .ft strong { color: var(--jp-text); }


/* == 13 · MOTION ========================================================== */

/* Scroll reveal. The class is added by janet_premium.js only when
   IntersectionObserver exists, so with no JS everything is simply visible. */
[data-jp-reveal] {
  opacity: 0;
  transform: translate3d(0, 18px, 0);
  transition: opacity var(--jp-slow) var(--jp-out),
              transform var(--jp-slow) var(--jp-expo);
  transition-delay: var(--jp-delay, 0ms);
  will-change: opacity, transform;
}
[data-jp-reveal].jp-in { opacity: 1; transform: none; }

/* 3D tilt for destination cards. The transform is written by JS into two
   custom properties, so the compositor animates and layout never runs. */
[data-jp-tilt] {
  transform-style: preserve-3d;
  transition: transform var(--jp-mid) var(--jp-out);
}
[data-jp-tilt].jp-tilting {
  transform: perspective(900px)
             rotateX(var(--jp-rx, 0deg))
             rotateY(var(--jp-ry, 0deg))
             translate3d(0, -4px, 0);
  transition: none;
}
[data-jp-tilt] .jg__figure, [data-jp-tilt] img { transform: translateZ(28px); }

/* Parallax depth, driven by a scroll-linked custom property. */
[data-jp-par] { transform: translate3d(0, calc(var(--jp-par, 0) * 1px), 0); will-change: transform; }

/* Press feedback on every tappable surface. */
.jg__card:active, .pick:active, .ls-card:active, .ls-hotel-card:active { transform: scale(.992); }

/* Section-level stagger for lists. */
.jp-stagger > * { --jp-delay: calc(var(--jp-i, 0) * 55ms); }


/* == 14 · RESPONSIVE ====================================================== */

/* 320px is a real device, not a rounding error: the field grid has to collapse
   to one column before it overflows, and the search page is where that bites. */
@media (max-width: 480px) {
  :root { --jp-r: 14px; --jp-r-lg: 18px; }
  .sec { padding-block: clamp(3rem, 12vw, 4.5rem); }
  h1 { font-size: clamp(2.1rem, 9vw, 2.9rem); }
  h2 { font-size: clamp(1.6rem, 6.4vw, 2.1rem); }
  .jsearch__body, .ls-bar { border-radius: var(--jp-r-lg); }
  .ls-field input, .ls-field select, .jf input, .jf select { font-size: 16px; } /* iOS zoom */
  .jh__assure { border-radius: var(--jp-r); }
  /* Motion is cheapest to remove where the screen is smallest and the device
     is likeliest to be slow. */
  .jh__spark { animation: none; }
  [data-jp-tilt].jp-tilting { transform: none; }
}

@media (max-width: 360px) {
  .sec { padding-inline: 14px; }
  .jsearch__tab { font-size: .82rem; padding-inline: .7rem; }
}

@media (min-width: 1024px) {
  .jp-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1rem, 2vw, 1.8rem); }
}

/* Above 1600px, stop the measure growing and let the whitespace do the work. */
@media (min-width: 1600px) {
  .wrap, .sec > .wrap { max-width: 1360px; }
  .lead, .sec-sub { max-inline-size: 66ch; }
}

/* Touch targets, everywhere, at every width. */
@media (pointer: coarse) {
  .hd-nav a, .bottom-nav a, .jsearch__tab, .ls-refresh, .jg__link {
    min-block-size: 44px;
    display: inline-flex;
    align-items: center;
  }
}


/* == 15 · REDUCED MOTION + ACCESSIBILITY ================================== */

@media (prefers-reduced-motion: reduce) {
  /* Not "faster" — off. A parallax that still moves 4px is still motion to
     someone who asked for none. */
  *, *::before, *::after {
    animation-duration: .001ms !important;   /* [beats inline animation] */
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  [data-jp-reveal] { opacity: 1 !important; transform: none !important; }
  [data-jp-par] { transform: none !important; }
  [data-jp-tilt].jp-tilting { transform: none !important; }
  .jh__spark { animation: none !important; }
  .jp-skel::after, .ls-skel::after, .skeleton::after { animation: none !important; opacity: .5; }
}

@media (prefers-contrast: more) {
  :root {
    --jp-text-2: #E4E8EF;
    --jp-text-3: #B9C0CC;
    --jp-line: rgba(245, 243, 239, .42);   /* prefers-contrast wants a STRONGER hairline, not a coloured one */
    --jp-line-soft: rgba(244, 241, 234, .22);
  }
}

/* Skip link — present in the markup, previously invisible against cream. */
.skip-link:focus {
  position: fixed;
  inset-block-start: 12px;
  inset-inline-start: 12px;
  z-index: 9999;
  background: var(--jp-gold);
  color: var(--on-sky);
  padding: .7rem 1.1rem;
  border-radius: 999px;
  font-weight: 700;
}

/* Print: the gold and the atmosphere cost ink and say nothing on paper. */
@media print {
  body::before { display: none; }
  body { background: #fff; color: #000; }
}

/* Skeleton container, inserted by janet_premium.js as a SIBLING of the results
   host so the product's own render can never collide with it. */
.jp-skel-wrap {
  display: grid;
  gap: clamp(.8rem, 1.6vw, 1.2rem);
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  margin-block-end: 1rem;
}
.jp-skel-wrap[hidden] { display: none; }


/* == 12b · SCOPED TOKEN OVERRIDES ========================================= */

/* Custom properties cascade by PROXIMITY, not by sheet order. `janet_editorial.css`
   declares its palette on `.ed` rather than on `:root`, so re-pointing --ed-cream
   at :root — which section 01 does — never reaches an element inside `.ed`: the
   closer declaration wins no matter how late my sheet loads. The editorial pages
   stayed cream for exactly this reason, and the fix is to redeclare at the same
   scope, where equal specificity lets order decide. */
.ed {
  --ed-cream:   #FBFAF8;
  --ed-sand:    #F4F1EB;
  --ed-ink:     #15181C;
  --ed-ink-2:   #4E545C;
  --ed-mute:    #767C85;
  --ed-coral:   #0E5A52;
  --ed-coral-t: #0E5A52;
  --ed-line:    rgba(244, 241, 234, .10);
}
body.ed { background: var(--jp-void); color: var(--jp-text); }

/* Literal gradients the tokens cannot reach. The destination and guide heroes
   were painted cream directly. */
.dhero:not(:has(.dhero__img)):not(:has(.ghero__media)),
.ghero:not(:has(.dhero__img)):not(:has(.ghero__media)) {
  background:
    radial-gradient(70% 90% at 72% 20%, rgba(14, 90, 82, .13), transparent 68%),
    linear-gradient(160deg, #FFFFFF 0%, #F4F1EB 60%);
}
/*
 * CORRECTED 2026-08-31 (second pass). The same question as below, asked at the
 * CONTAINER instead of at the headline.
 *
 * The h1/.lead rule further down was scoped to a hero that brought no picture;
 * this one was not, so on all 34 pages that DO carry a full-bleed photograph
 * (10 x .dhero__img, 24 x .ghero__media) the container took rgb(21,24,28) and
 * every descendant inherited it — the headline, the lead, the breadcrumb and
 * the byline. Scoping only the h1 could not undo that, because `.dhero h1`
 * declares no colour of its own and inherits.
 *
 * Measured on the built page 2026-08-31: /tisot-zolot-ams .dhero h1 computed
 * rgb(21,24,28) over the night canal photograph. The page's own sheet had
 * already set `.dhero { color: #FFF8F1 }`; this rule was overriding it.
 */
.dhero:not(:has(.dhero__img)):not(:has(.ghero__media)),
.ghero:not(:has(.dhero__img)):not(:has(.ghero__media)) { color: var(--jp-text); }
/*
 * The theme's hero scrim, and the one case where it must stand down.
 *
 * This is a bottom-only band, correct for the `.dhero__figure` composition
 * where the photograph occupies one side and the copy sits on the page ground.
 * The ten `tisot-zolot-*` pages use a different hero: a FULL-BLEED
 * `.dhero__img` behind the copy, with their own four-stop scrim tuned against
 * their own photograph (their inline comment records the measurements).
 *
 * Loading the theme after their inline <style> replaced that tuned ramp with a
 * band that is fully transparent for the top 62% — exactly where the headline
 * sits — and put white type on a lit Amsterdam bridge at 1.78:1. The release
 * gate's pixel sampler caught all ten; the ancestor-based auditor could not,
 * because it never looks at what the photograph is actually doing.
 *
 * `:has()` lets the theme ask the question that matters — "did this page bring
 * its own full-bleed picture?" — instead of guessing from the class name.
 */
/*
 * CORRECTED 2026-08-31. The question above is the right one and it was asked
 * about ONE class name. `.dhero__img` is what the ten tisot-zolot-* pages call
 * their full-bleed photograph; the twenty guide pages call theirs
 * `.ghero__media`, so every one of them answered "no picture here", took the
 * bottom-only scrim AND the dark ink below, and rendered its headline at
 * rgb(21,24,28) on the photograph — 2.28:1 to 2.40:1, measured by the release
 * gate on 42 page-widths. On screen the headline of every guide page was very
 * nearly invisible.
 *
 * Both names are asked for now. A hero that brought a picture keeps the page's
 * own light ink and its own tuned scrim; only a hero with no picture takes the
 * theme's ground and its dark ink.
 */
.dhero:not(:has(.dhero__img)):not(:has(.ghero__media))::after,
.ghero:not(:has(.dhero__img)):not(:has(.ghero__media))::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  block-size: 38%;
  background: linear-gradient(180deg, transparent, var(--jp-void));
  pointer-events: none;
}
.dhero, .ghero { position: relative; }
.dhero:not(:has(.dhero__img)):not(:has(.ghero__media)) h1,
.ghero:not(:has(.dhero__img)):not(:has(.ghero__media)) h1,
.dhero:not(:has(.dhero__img)):not(:has(.ghero__media)) .lead,
.ghero:not(:has(.dhero__img)):not(:has(.ghero__media)) .lead { color: var(--jp-text); }

/* Editorial callouts: note / tip / warn were three pastel blocks. They become
   one material with a coloured rule, so they read as a system. */
.ed .note, .ed .tip, .ed .warn, .note, .tip, .warn {
  background: var(--jp-raised);
  border: 1px solid var(--jp-line-soft);
  border-inline-start: 2px solid var(--jp-gold);
  border-radius: var(--jp-r-sm);
  color: var(--jp-text-2);
}
.ed .warn, .warn { border-inline-start-color: var(--ls-warn); }
.ed .tip, .tip   { border-inline-start-color: var(--ls-cheap); }
.ed .note strong, .ed .tip strong, .ed .warn strong { color: var(--jp-text); }

/* The sticky article bar and its CTA. */
.ed .bar, .bar {
  background: rgba(10, 14, 21, .86);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-block-start: 1px solid var(--jp-line-soft);
  color: var(--jp-text);
}
.tp-cta, .ed .tp-cta {
  background: linear-gradient(180deg, var(--jp-gold-pale), var(--jp-gold));
  color: var(--on-sky);   /* the gradient is LIGHT at both stops; see note 5 */
  border: none;
  border-radius: 999px;
  font-weight: 700;
}
.tp-cta:hover { color: var(--on-sky); filter: brightness(1.04); }

/* Tables inside articles. */
.ed th, .ed thead th { background: var(--jp-raised); color: var(--jp-text); }
.ed tbody tr:nth-child(odd) td { background: rgba(20, 24, 28, .04); }


/* == 14b · TOUCH TARGETS ================================================== */

/* Measured under 44px at every width, on every screen that has them. Padding
   rather than a fixed height, so the label still sets the width and nothing
   reflows. */
.hd-cta, a.hd-cta, .btn, .period-tab, .jsearch__tab, .ls-refresh, .tp-cta {
  min-block-size: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding-inline: clamp(.9rem, 2vw, 1.4rem);
}


/* == 12c · LIGHT-SURFACE ERADICATION ====================================== */

/* The last cream surfaces, each measured on the rendered page rather than
   guessed from the source. They are single-class rules in janet_hero_v4.css,
   which is the same specificity as a single-class rule here — a tie that order
   should win, and did not reliably, because several of them are also set by a
   second rule elsewhere in the same sheet. Prefixing with :root raises these to
   (0,2,0) so the outcome stops depending on which duplicate came last.
   `!important` appears only against janet_ds.css:555, which is itself
   !important and cannot be outranked any other way. */

:root .jf,
:root .jband,
:root .jband__inner,
:root .jg__price,
:root .pick__badge,
:root .pick__price,
:root .cine__go,
:root .ed-index,
:root .jsearch__body,
:root .jh__assure {
  background: var(--jp-raised);
  color: var(--jp-text);
  border-color: var(--jp-line-soft);
}

/* Prices and badges are labels, not cards: they sit ON the card, so they get
   the champagne, not another slab of surface. */
:root .jg__price,
:root .pick__price {
  background: rgba(14, 90, 82, .10);
  color: var(--jp-gold);
  border: 1px solid var(--jp-line);
  border-radius: 999px;
}
:root .jg__price small,
:root .pick__price small { color: var(--jp-gold-warm); }
:root .pick__badge {
  background: rgba(14, 90, 82, .14);
  color: var(--jp-gold-pale);
  border: 1px solid var(--jp-line);
  border-radius: 999px;
}

/* The field row inside the hero search. */
:root .jf {
  background: rgba(20, 24, 28, .04);
  border: 1px solid var(--jp-line-soft);
}
:root .jf .ic { color: var(--jp-gold); }

/* The band under the hero and the cinematic CTA. */
:root .jband { background: transparent; }
:root .jband__inner {
  background: rgba(14, 19, 29, .82);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border: 1px solid var(--jp-line);
  border-radius: var(--jp-r-lg);
}
:root .cine__go {
  background: linear-gradient(180deg, var(--jp-gold-pale), var(--jp-gold));
  color: var(--on-sky);   /* the gradient is LIGHT at both stops; see note 5 */
  border: none;
}

/* janet_ds.css:555 is `!important` on both properties [beats !important]. */
.hd-cta, a.hd-cta {
  background: linear-gradient(180deg, var(--jp-gold-pale), var(--jp-gold)) !important;
  color: var(--on-sky) !important;
}

/* The article index card. */
:root .ed-index { background: rgba(20, 24, 28, .04); border: 1px solid var(--jp-line-soft); }
:root .ed-index h3 { color: var(--jp-text); }
:root .ed-index a { color: var(--jp-text-2); }
:root .ed-index a:hover { color: var(--jp-gold); }


/* == 12d · FORM CONTROL LEGIBILITY ======================================== */

/*
 * Section 12c eradicated the light CARD surfaces. It missed the CONTROLS, and
 * a control is where a light island actually costs the user something: a card
 * that is the wrong shade looks cheap, a select nobody can read stops the
 * search.
 *
 * Everything below was measured on the rendered production page 2026-08-21,
 * not read out of the source:
 *
 *   #ss-dest / #ss-date   color #F4F1EA on background rgba(255,255,255,.92)
 *                         -> contrast 1.05:1. Near-white text on a near-white
 *                            pill. This is the "unreadable destination
 *                            dropdown" Yossi reported, and the screenshot of
 *                            the sticky bar shows two blank white capsules.
 *   .jpicks__nav          #C6CCD8 on rgba(255,253,250,.9) -> 1.59:1. The
 *                         carousel arrows are drawn; they are just invisible.
 *   every <select>        appearance:none with NO background-image, so the
 *                         native chevron is stripped and nothing replaces it.
 *                         `.jf select` in janet_hero_v4.css does draw one, in
 *                         #BF4423 — a rust arrow sized for the cream theme,
 *                         which after 12c sits on #0E131D.
 *   <option>              inherits color #F4F1EA with a transparent background,
 *                         so the native popup on Windows paints the light
 *                         system menu underneath white text.
 *
 * The cause is one thing, not four: janet_hero_v4.css was authored against a
 * cream palette, janet_premium.css re-pointed the TOKENS to dark, and every
 * hard-coded literal in the older sheet stayed light. Tokens moved, literals
 * did not.
 */

/* --- The sticky quick-search bar ---------------------------------------- */

/* janet_hero_v4.css:260,281 are `!important` (they were fighting janet_ds.css),
   so these have to be too. [beats !important] */
:root .sticky-search {
  background: rgba(8, 11, 18, .92) !important;
  border-bottom: 1px solid var(--jp-line) !important;
}

:root .sticky-search select,
:root .sticky-search input,
:root .hd #sticky-search .sticky-form select,
:root .hd #sticky-search .sticky-form input {
  color: var(--jp-text) !important;
  background-color: rgba(20, 24, 28, .04) !important;
  border: 1px solid var(--jp-line-soft);
}

/* janet_hero_v4.css:282 sets the `background` SHORTHAND with !important, and a
   shorthand resets background-image to none — so the chevron added below for
   every select in the product was being erased on this one control, and only
   on this one. The longhand has to be !important for the same reason.
   [beats !important] */
:root .sticky-search select,
:root .hd #sticky-search .sticky-form select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%23E8C989' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1.5 2l4.5 4 4.5-4'/%3E%3C/svg%3E") !important;
  background-repeat: no-repeat !important;
  background-size: 11px 8px !important;
  background-position: center left 12px !important;
  padding-inline-end: 32px;
}
:root .sticky-search select:dir(ltr) { background-position: center right 12px !important; }

:root .sticky-search button,
:root .hd #sticky-search .sticky-form button {
  background: linear-gradient(180deg, var(--jp-gold-pale), var(--jp-gold));
  color: var(--on-sky);   /* the gradient is LIGHT at both stops; see note 5 */
}

/* --- Rail / carousel navigation ----------------------------------------- */

/* The arrows belong to the cards, so they take the card surface, not paper. */
:root .jpicks__nav,
:root .rail-btn,
:root .jgal__nav,
:root .jdd-nav {
  background: rgba(20, 27, 40, .92);
  color: var(--jp-text);
  border: 1px solid var(--jp-line);
  box-shadow: var(--jp-e2);
}
:root .jpicks__nav:hover,
:root .rail-btn:hover,
:root .jgal__nav:hover,
:root .jdd-nav:hover {
  color: var(--on-sky);
  background: var(--jp-gold);
  border-color: var(--jp-gold);
}
:root .jpicks__nav[disabled],
:root .rail-btn[disabled] { opacity: .38; cursor: default; }

/* --- The chevron every appearance:none select threw away ----------------- */

/*
 * Drawn in champagne rather than in currentColor: a mask + currentColor would
 * be tidier, but `background-color` on a <select> IS the field surface, so the
 * two cannot both use it, and a <select> takes no pseudo-element to hang one
 * on. After 12c every select in the product sits on a dark surface, so one
 * fixed champagne chevron is correct everywhere (#E8C989 on #0E131D = 10.4:1)
 * instead of being correct on one page and invisible on the next.
 */
:root select {
  appearance: none;
  -webkit-appearance: none;
  padding-inline-end: 30px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%23E8C989' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1.5 2l4.5 4 4.5-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-size: 11px 8px;
  background-position: center left 10px;
  cursor: pointer;
}
:root select:dir(ltr) { background-position: center right 10px; }

/* The native popup. Windows paints the system menu behind the options unless
   the option itself carries a colour, which is why the list read as white text
   on white even with `color-scheme: dark` set on the root. */
:root select option,
:root select optgroup {
  background-color: var(--jp-overlay);
  color: var(--jp-text);
}
:root select option:checked,
:root select option:hover {
  background-color: var(--jp-elevated);
  color: var(--jp-gold-pale);
}

/* --- Date fields --------------------------------------------------------- */

/*
 * `color-scheme: dark` already makes Chrome paint the calendar glyph light, so
 * it is not inverted here — inverting a light glyph is what would hide it. The
 * defect was janet_hero_v4.css holding it at `opacity:.5`, which on #0E131D is
 * a grey smudge. It is also given a real hit area: it was a 14px target.
 */
:root input[type="date"]::-webkit-calendar-picker-indicator,
:root input[type="month"]::-webkit-calendar-picker-indicator {
  opacity: .92;
  cursor: pointer;
  padding: 5px;
  margin-inline-start: 0;
  border-radius: 6px;
  transition: background var(--jp-fast) var(--jp-out), opacity var(--jp-fast) var(--jp-out);
}
:root input[type="date"]::-webkit-calendar-picker-indicator:hover,
:root input[type="month"]::-webkit-calendar-picker-indicator:hover {
  opacity: 1;
  background: rgba(14, 90, 82, .18);
}

/* The unfilled segments Chrome renders as `dd/mm/yyyy`. They inherit `color`
   at a browser-chosen alpha that lands under 4.5:1 on this surface, so they
   are set explicitly. --jp-text-2 is 10:1 on --jp-void. */
/*
 * Chrome dims the WHOLE datetime-edit container while the field is empty, and
 * it does that on the container's own opacity — not on `color`. So the segment
 * rules below computed to a near-white 17:1 and the `dd/mm/yyyy` on screen was
 * still the faintest thing in the search card. Measuring the property agreed
 * with itself and disagreed with the screen; the opacity is what had to move.
 */
:root input[type="date"]::-webkit-datetime-edit,
:root input[type="month"]::-webkit-datetime-edit { opacity: 1; }

:root input[type="date"]::-webkit-datetime-edit-text,
:root input[type="date"]::-webkit-datetime-edit-day-field,
:root input[type="date"]::-webkit-datetime-edit-month-field,
:root input[type="date"]::-webkit-datetime-edit-year-field { color: var(--jp-text-2); }
:root input[type="date"]::-webkit-datetime-edit-day-field:focus,
:root input[type="date"]::-webkit-datetime-edit-month-field:focus,
:root input[type="date"]::-webkit-datetime-edit-year-field:focus {
  background: var(--jp-gold);
  color: var(--on-sky);
  border-radius: 3px;
  outline: none;
}

/* --- Placeholders -------------------------------------------------------- */

/* janet_hero_v4.css:625 sets #A8917C, a warm grey chosen against cream. */
:root input::placeholder,
:root textarea::placeholder {
  color: var(--jp-text-3);
  opacity: 1;
}

/* --- Focus, hover and selected state ------------------------------------- */

/*
 * "Not obvious enough" was accurate: the ring was `3px solid var(--jt-coral)`,
 * and --jt-coral is now champagne at low contrast against several surfaces.
 * A two-tone ring (dark core, gold halo) stays visible on every surface in the
 * product, including on top of the gold buttons themselves.
 */
:root select:focus-visible,
:root input:focus-visible,
:root textarea:focus-visible,
:root button:focus-visible,
:root a:focus-visible,
:root [tabindex]:focus-visible {
  outline: 2px solid var(--jp-gold);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px rgba(14, 90, 82, .22);
  border-radius: inherit;
}

:root .jf:focus-within {
  border-color: var(--jp-gold);
  box-shadow: 0 0 0 3px rgba(14, 90, 82, .18);
}

/* --- Ink used where a surface was expected, and the reverse --------------- */

/*
 * `--jt-coral-ink` is #FBFAF8: the colour that goes ON champagne. Section 01
 * introduced it precisely so `.btn` stopped being white-on-gold. Two places
 * were already using the old --jt-coral-ink (#BF4423, a rust that read as a
 * dark accent on cream) as ordinary TEXT, and inherited the near-black instead
 * — so the section eyebrow above the destination gallery is currently drawn in
 * #FBFAF8 on #05070C, at 1.02:1. It is not dim; it is not there.
 *
 * An eyebrow is a brand accent, so it takes the champagne, which is what every
 * other eyebrow in the product uses.
 */
:root .jgal__eyebrow { color: var(--jp-gold); }

/* The stale-price warning on /search. Its cream --ls-warn-bg is what the empty
   bar between Janet's pick and the benchmark row was made of; the [hidden]
   guard in janet_ds.css stops it appearing when there is nothing to warn about,
   and this is what it looks like when there IS. Amber is kept — it is carrying
   a warning — but at a luminance that belongs on this page. */
:root .ls-stale-note {
  background: rgba(14, 90, 82, .10);
  border: 1px solid var(--jp-line-strong);
  color: var(--jp-gold-pale);
}
:root .ls-refresh {
  background: var(--jp-gold);
  color: var(--on-sky);
  border: 0;
}

/*
 * The reverse mistake: cream ink sitting on champagne.
 *   .brand-mark    #FFF6EA on the gold/coral badge   1.83:1
 *   .jh-go         #FDF8F1 on --jh-coral (champagne) 3.20:1
 *   .jh-bar__logo  same
 * Re-pointing --sky to champagne was already caught for .btn-sky by --on-sky;
 * these three set their ink literally, so the token never reached them.
 *
 * The two .jh-* offenders live on /hotels, which does not load this sheet at
 * all, so they are fixed at source in janet_hotels.css.
 */
:root .brand-mark,
:root .logo-badge { color: var(--on-sky); }

/* Windows high-contrast mode keeps its own colours; only the shape is kept. */
@media (forced-colors: active) {
  :root select { background-image: none; }
  :root select:focus-visible,
  :root input:focus-visible,
  :root button:focus-visible { outline: 2px solid CanvasText; }
}


/* == 14c · 320px OVERFLOW ================================================= */

/* At 320px the header's action cluster is wider than the viewport, which
   pushed the document 13px sideways. The nav is not the place to fight for
   space on the narrowest phone: the burger stays, the rest folds away. */
@media (max-width: 360px) {
  .hd-actions { gap: 6px; }
  .hd-actions .hd-icon:not(.burger):not(:first-child) { display: none; }
  .hd-cta, a.hd-cta { padding-inline: .8rem; font-size: .84rem; }
  .hd-inner, .hd > .wrap { padding-inline: 10px; }
}
/* Nothing anywhere may push the page sideways. */
html, body { max-inline-size: 100%; overflow-x: hidden; }


/* == 12d · THE !important HOLDOUTS ======================================== */

/* janet_hero_v4.css:2093 sets `.jg__price` with `!important` (its own comment
   says it is beating an earlier declaration in the same sheet). Specificity
   cannot reach past that, so this is the one family that has to answer in
   kind. [beats !important] */
.jg__price,
.jg__card[data-far] .jg__price {
  background: rgba(14, 90, 82, .10) !important;
  color: var(--jp-gold) !important;
  border: 1px solid var(--jp-line);
  border-radius: 999px;
}
.jg__price small, .jg__card[data-far] .jg__price small { color: var(--jp-gold-warm) !important; }

/* An OBSERVED price is not an offered one, and must not look like one.
   Gold is the currency of a live claim on this page; a dated observation drops
   to text-2 (10:1 on the void — this stays readable, it is not de-emphasised
   into illegibility) and gives up the gold border. The wording carries the
   meaning; the colour stops the eye reading it as a fare before the words. */
.jg__price[data-indicative],
.jg__card[data-far] .jg__price[data-indicative],
.pick__price[data-indicative] {
  /*
   * Opaque on purpose. The live-price chip is a 10%-gold wash that reads
   * against the card's own dark art; these chips sit on destination
   * PHOTOGRAPHS, whose brightness this stylesheet does not control, so a
   * translucent background would make legibility a property of the picture.
   * At .86 over the worst case (a white sky) the composite is ~L0.03 and the
   * figure below still clears 10:1.
   */
  background: rgba(11, 15, 23, .86) !important;
  color: var(--jp-text) !important;
  border-color: var(--jp-line-soft);
  box-shadow: var(--jp-e2);
}
.jg__price[data-indicative] small,
.jg__card[data-far] .jg__price[data-indicative] small,
.pick__price[data-indicative] small {
  /* 7:1 against that same worst case — this is the qualification, not a
     footnote, and it has to survive being read on a phone in daylight. */
  color: var(--jp-text-2) !important;
  opacity: 1;
  /*
   * 12.5px, up from the 10.56px the "החל מ-" lead inherits.
   *
   * That lead is a connective word and nobody needs to read it; this one says
   * "נצפה לפני 5 ימים" and is the entire reason the number beside it is honest.
   * Measured at 375px it was rendering at 10.6px, under the 12px floor, which
   * would have put the disclosure in the smallest type on the card.
   */
  font-size: .78rem !important;
  line-height: 1.45;
}
/* Neutral rather than gold is what marks it as the lesser claim; it is not
   also shrunk into illegibility. */
.jg__price[data-indicative] b, .pick__price[data-indicative] b { font-size: 1.06rem; font-weight: 700; }

/* The Janet state chip, light at rest and pure white on hover. */
.janet-state-btn {
  background: rgba(20, 24, 28, .04);
  color: var(--jp-text-2);
  border: 1px solid var(--jp-line-soft);
}
.janet-state-btn:hover {
  background: rgba(14, 90, 82, .14);
  color: var(--jp-gold);
}

/* The mobile bottom bar. */
:root .bottom-nav {
  background: rgba(8, 11, 18, .92);
  -webkit-backdrop-filter: saturate(150%) blur(18px);
  backdrop-filter: saturate(150%) blur(18px);
  border-block-start: 1px solid var(--jp-line-soft);
}
:root .bottom-nav a { color: var(--jp-text-3); }
:root .bottom-nav a.bnav-active { color: var(--jp-gold); }


/* == 12e · LIGHT GRADIENTS ================================================ */

/* Gradients are the light surfaces a background-colour audit cannot see, and
   there were fourteen of them. A whole section (.jgal) was still painting
   cream through a gradient while every colour token around it had already
   inverted — the headline measured 1.1:1 against it and looked, from a
   distance, like a design decision. */

.jgal, .jgal__inner,
.jh__fade, .jh__wash,
.jsearch, .jsearch__body,
.cine, .cine__inner,
.jband__inner,
.pick, .jg__card,
.ed .relc, .relc,
.ed-index,
.dhero, .ghero,
.tp-card, .ed-card {
  background-image: none;
}

/* Re-establish the ones that should keep a gradient, in the dark palette. */
.jgal {
  background:
    radial-gradient(70% 60% at 50% 0%, rgba(14, 90, 82, .07), transparent 68%),
    var(--jp-void);
}
.jsearch__body, .jband__inner {
  background:
    linear-gradient(168deg, rgba(255, 255, 255, .045), rgba(255, 255, 255, .012)),
    rgba(14, 19, 29, .9);
}
.pick, .jg__card {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .035), rgba(255, 255, 255, 0) 42%),
    var(--jp-raised);
}
.cine {
  background:
    radial-gradient(60% 70% at 70% 20%, rgba(14, 90, 82, .10), transparent 66%),
    var(--jp-void);
}
/* The hero's bottom fade must end in the page floor, not in cream. */
.jh__fade {
  background: linear-gradient(to bottom, rgba(5, 7, 12, 0), var(--jp-void));
}
/* The comparison widget shipped a blue-white gradient with !important.
   [beats !important] */
.jce-widget, .jce-row, .jce-head {
  background: var(--jp-raised) !important;
  background-image: none !important;
  color: var(--jp-text);
}
/* Editorial cards and pull-quotes. [beats !important on janet_editorial:731] */
.ed .tp-card, .ed-card, .ed .pull, .pull {
  background: var(--jp-raised) !important;
  background-image: none !important;
  border: 1px solid var(--jp-line-soft);
  color: var(--jp-text-2);
}


/* == 15b · THE SKIP LINK ================================================== */

/* White on champagne is 1.6:1. It is the first thing a keyboard user reaches
   and it was unreadable. janet_ds.css:520 sets both properties !important.
   [beats !important] */
.skip, a.skip {
  background: var(--jp-gold) !important;
  /* --on-sky, not a literal. This said #FBFAF8, which was right while the
     accent was a dark green and became 2.30:1 the moment it turned champagne.
     The skip link is the first control a keyboard user meets, so it was the
     least readable thing on the page — caught by the contrast audit, not by
     reading the file, because the file still said exactly what it meant. */
  color: var(--on-sky) !important;
  font-weight: 700;
  border-radius: 999px;
  padding: .7rem 1.1rem;
}
.skip:focus, a.skip:focus {
  outline: 2px solid var(--jp-text);
  outline-offset: 2px;
}


/* == 12f · THE LAST FIVE ================================================== */

/* Each measured on the rendered page at 375px, not inferred from source. */

/* 1 · The burger: a white glyph on a cream chip, invisible either way. */
:root .burger, :root .hd-icon.burger {
  background: rgba(20, 24, 28, .04) !important;   /* [beats an inline-weight rule] */
  color: var(--jp-text) !important;
  border: 1px solid var(--jp-line-soft);
}
:root .burger span, :root .burger i, :root .burger svg { background: currentColor; color: currentColor; }

/* 2 · The recommendations panel kept a cream gradient. */
:root .jrec, :root .jrec__inner {
  background:
    radial-gradient(60% 80% at 30% 0%, rgba(14, 90, 82, .10), transparent 66%),
    var(--jp-raised) !important;                     /* [beats a gradient !important] */
  border: 1px solid var(--jp-line-soft);
  color: var(--jp-text);
}

/* 3 · The mobile bottom bar was still cream at 97% opacity. */
:root .bottom-nav, body .bottom-nav {
  background: rgba(8, 11, 18, .94) !important;       /* [beats an inline-weight rule] */
  border-block-start: 1px solid var(--jp-line-soft) !important;
}

/* 4 · The search page's back link inherited the near-black used for text ON
       champagne, and was rendering near-black ON the dark page. */
:root .ls-back, :root a.ls-back {
  color: var(--jp-text-2) !important;
  text-decoration: none;
}
:root .ls-back:hover { color: var(--jp-gold) !important; }

/*
 * 5 · The search button.
 *
 * The comment here read "white on champagne is 1.6:1" — and the rule under it
 * set #FBFAF8, which is white. It was written during a champagne era, survived
 * the green era (where white on the dark accent was briefly correct), and came
 * out the far side of this re-point saying the right thing and doing the
 * opposite.
 *
 * Neither contrast audit could catch it, and the reason is worth keeping: both
 * read `backgroundColor`, and an element painted by a GRADIENT has a
 * transparent background colour. Every gold-gradient primary action on this
 * site was invisible to both instruments — found by reading computed styles by
 * hand on /search, at roughly 1.5:1.
 */
:root .ls-btn, :root button.ls-btn, :root .ls-go {
  background: linear-gradient(180deg, var(--jp-gold-pale), var(--jp-gold)) !important;
  color: var(--on-sky) !important;
  border: none;
  font-weight: 700;
}

/* Any remaining "white text on champagne" pairing anywhere in the product.
   Champagne is a LIGHT colour; white on it never passes, and it appeared in
   three separate places written by three different sheets. */
/* No page carries an inline champagne background any more (grepped 2026-08-30:
   the only hits were this rule and the comment above it). Kept as a guard, but
   the accent is now DARK, so anything still painting itself gold needs INK on
   top, not paper — the pairing this rule originally shipped. */
[style*="background: #E8C989"], [style*="background:#E8C989"] { color: #15181C !important; }


/* == 12g · EDITORIAL COMPONENTS =========================================== */

/* The destination and guide pages carry their own component set, some of it in
   janet_editorial.css and some inline in the page. All of it was built for
   cream. */

:root .dfacts, :root .dfacts li {
  background: var(--jp-raised);
  background-image: none;
  border: 1px solid var(--jp-line-soft);
  color: var(--jp-text-2);
}
:root .dfacts strong, :root .dfacts b { color: var(--jp-text); }

:root .jnote {
  background:
    radial-gradient(60% 90% at 20% 0%, rgba(14, 90, 82, .10), transparent 66%),
    var(--jp-raised);
  border: 1px solid var(--jp-line-soft);
  border-inline-start: 2px solid var(--jp-gold);
  color: var(--jp-text-2);
}
:root .jnote strong { color: var(--jp-text); }

:root .cmp-section, :root .cmp-table, :root .cmp-row {
  background: var(--jp-raised);
  background-image: none;
  color: var(--jp-text-2);
  border-color: var(--jp-line-soft);
}
:root .cmp-section h2, :root .cmp-section h3 { color: var(--jp-text); }

/* Inline-styled chips on the destination pages. Both were pastel blocks with
   coloured text; they become the same tinted-chip pattern as everywhere else.
   [inline] — the page sets these with a style block of its own. */
:root .cmp-note {
  background: rgba(14, 90, 82, .10) !important;
  color: var(--jp-text-2) !important;
  border: 1px solid var(--jp-line-soft);
}
:root .no-aff-tag {
  background: rgba(226, 106, 96, .18) !important;
  color: #F3AFA8 !important;   /* was #A3271F — 2.43:1 on the dark card */
  border: 1px solid rgba(226, 106, 96, .34);
}

/* Any inline-styled pastel block left on an editorial page. Named rather than
   blanket-matched, so a deliberate colour is never flattened by accident. */
:root .ed [style*="background:#eef5ff"],
:root .ed [style*="background: #eef5ff"],
:root .ed [style*="background:#fee2e2"],
:root .ed [style*="background: #fee2e2"] {
  background: var(--jp-raised) !important;           /* [inline] */
  color: var(--jp-text-2) !important;
}


/* == 12h · THE BUILD-INJECTED DISCLOSURE ================================== */

/* The build injects a legally necessary disclosure with an inline
   `background:#fff3cd`. janet_editorial.css already re-dressed it once, from a
   browser-validation yellow into a cream card, with !important on every
   property because an inline style cannot be outranked any other way. It is
   the last cream surface on the site, and it needs the same treatment again in
   the dark palette. The disclosure text itself is untouched — it is a
   disclosure, and it stays exactly as legible as it was.
   [inline] [beats !important] */
.ed [style*="#fff3cd"] {
  background: rgba(14, 90, 82, .10) !important;
  background-image: none !important;
  border: 1px solid var(--jp-line) !important;
  border-inline-start: 2px solid var(--jp-gold) !important;
  color: var(--jp-text-2) !important;
}
.ed [style*="#fff3cd"] strong,
.ed [style*="#fff3cd"] b { color: var(--jp-text) !important; }
.ed [style*="#fff3cd"] a { color: var(--jp-gold) !important; }


/* == 16 · FINAL PASS ====================================================== */

/* The bottom-nav icons are SVG now (scripts/premium_nav_icons.js). Size and
   colour them as a set so they read as one family. */
.bottom-nav .bnav-item svg {
  display: block;
  margin-inline: auto;
  margin-block-end: 3px;
  opacity: .82;
  transition: opacity var(--jp-fast) var(--jp-out), transform var(--jp-fast) var(--jp-out);
}
.bottom-nav .bnav-item.bnav-active svg,
.bottom-nav .bnav-item:hover svg { opacity: 1; transform: translateY(-1px); }
.bottom-nav .bnav-item { padding-block: 8px; }

/* The footer ran to the viewport edge at every width — an RTL list with no
   inline padding of its own inside a full-bleed section. */
.ft, .ft > * { padding-inline: clamp(16px, 4vw, 40px); }
.ft nav { display: flex; flex-wrap: wrap; gap: .35rem 1.1rem; }

/* The approved hero plate is warm and light along its top edge, which fought
   the dark page on small screens where the plate fills the frame. The IMAGE is
   untouched — this only deepens the scrim that sits over it, and only where
   the crop actually exposes that edge. */
@media (max-width: 700px) {
  .jh__scrim {
    background:
      linear-gradient(180deg, rgba(5,7,12,.86) 0%, rgba(5,7,12,.42) 30%, rgba(5,7,12,.9) 84%, var(--jp-void) 100%),
      radial-gradient(80% 50% at 70% 26%, rgba(14, 90, 82, .12), transparent 72%);
  }
}

/* Sticky elements need clearance from the fixed bottom bar, or the last card
   on every page sits under it. */
@media (max-width: 900px) {
  body { padding-block-end: env(safe-area-inset-bottom, 0px); }
  .ft { padding-block-end: calc(72px + env(safe-area-inset-bottom, 0px)); }
}


/* == 12i · THE COMPARISON WIDGET ========================================== */

/* These two only exist once janet_engine_v2.js has live data to render, so
   they are invisible to any check run against a local static server — they
   were caught by running the same visual QA against production. The widget
   already ships a dark-mode block (comparison_engine.css:270-280) gated on
   `prefers-color-scheme: dark`, which never fires for a visitor whose OS is in
   light mode. The site is dark now regardless of the OS, so the palette has to
   come from the site, not from the system preference. */

:root .jce-section-title {
  background: var(--jp-raised);
  background-image: none;
  color: var(--jp-gold);
  border-color: var(--jp-line-soft);
}
:root .jce-disclosure {
  background: var(--jp-base);
  background-image: none;
  color: var(--jp-text-3);
  border-block-start-color: var(--jp-line-soft);
}
:root .jce-provider-meta, :root .jce-diff, :root .jce-fallback-txt { color: var(--jp-text-3); }
:root .jce-row, :root .jce-provider { border-color: var(--jp-line-soft); color: var(--jp-text-2); }
:root .jce-provider-name { color: var(--jp-text); }


/* == 16 · CONTRAST CORRECTIONS, measured 2026-08-15 =======================
   Nine selectors on the homepage were below WCAG AA against the RENDERED
   page at 390px and 1280px. They are grouped by the mistake behind them,
   because each group has the same cause and the same fix.

   (a) White text kept on a button whose background became champagne when the
       palette inverted. #fff on #E8C989 is 1.6:1. Dark ink on gold is 11.6:1
       and is what .jdh-role--pick already uses.

   (b) The editorial article cards kept their light-mode ink after the card
       under them turned dark: an <h4> at #241A13 on #0E131D is 1.09:1, which
       is why that section photographed as four blank rectangles.

   (c) Two picks-section labels resolved to #080B17 on #05070C — 1.02:1,
       text present in the DOM and invisible to every reader.

   Fixed here rather than at each source because this sheet is the last one
   the homepage loads, and because the originals are shared with the light
   internal pages that still render correctly.
   ========================================================================= */

/* (a) white-on-gold buttons.
   `.btn-sky` is matched by name rather than by an ancestor: the one in the
   guides section sits outside #janet, and scoping to a section is what let it
   survive the first correction pass. */
:root .fsw-btn,
:root .jrec__go,
:root .jpicks__all,
:root .btn-sky,
:root #janet .btn,
:root .cine__cta .btn {
  color: #12161F;
  background: linear-gradient(135deg, var(--jp-gold), var(--jp-gold-warm));
}
:root .btn-sky:hover,
:root .fsw-btn:hover,
:root .jrec__go:hover,
:root #janet .btn:hover { color: #12161F; background: var(--jp-gold-pale); }

/* (b) editorial cards on a dark surface */
:root .ed-card-body h4,
:root .ed-feature-body h4,
:root .ed-card h4 { color: var(--jp-text); }
:root .ed-card-body .cat,
:root .ed-feature-body .cat { color: var(--jp-gold); }
:root .ed-card-body .rt,
:root .ed-feature-body .rt { color: var(--jp-text-3); }
:root .ed-card-body p,
:root .ed-feature-body p { color: var(--jp-text-2); }

/* (c) picks labels that resolved to near-black on near-black */
:root .jpicks__kicker { color: var(--jp-gold); }
:root .jpicks__all { color: #12161F; }

/* The footer wordmark tagline sat at 3.6:1 in coral. */
:root .ft small, :root .ft__tag small { color: var(--jp-text-2); }

/* The stale-data alert was a cream card (#FFF8E1) with brown text — correct
   contrast, wrong page. It is hidden until data goes stale, so it never showed
   up in a routine screenshot; it would have appeared as a bright rectangle in
   the middle of the dark page at exactly the moment the site was trying to
   look trustworthy. Same warning, same wording, in the palette. */
:root .stale-warn {
  background: rgba(138, 90, 18, .12);
  border: 1px solid rgba(138, 90, 18, .38);
  color: #F0D9B4;
}
:root .stale-warn strong { color: var(--jp-gold-pale); }

/* == 17 · GUIDE-PAGE CONTRAST, measured on production 2026-08-15 ===========
   41 pairs below AA on tisot-zolot-roma.html at 390px and 1280px. The homepage
   and search page were corrected first and these were missed because they are
   defined in three OTHER sheets — the editorial styles, the comparison engine
   and the design system — each of which still assumes the cream page it was
   written for.

   Grouped by cause:
     a  white on champagne (.btn, .bar-cta) — the same inversion that hit
        .btn-sky, in rules that set #fff directly rather than through --on-sky
     b  muted brown ink #6B563F on the dark surface (2.68:1) — the fact labels
        under the destination hero and the "from" prefixes
     c  light chips kept from the cream design: .info-tag on #FEF9C3,
        .af-tag on #DCFCE7
     d  comparison-engine price colours: a blue #1272C4 and a green #1D6B3C
        chosen for white, both under 4:1 on #0E131D
   ========================================================================= */

/* (a) */
:root .btn, :root .bar-cta { color: var(--on-sky, #12161F); }
:root .btn:hover, :root .bar-cta:hover { color: var(--on-sky, #12161F); }

/* …but only where there IS champagne behind the ink. `.btn` covers filled and
   outline alike, and an outline button has nothing behind it but the page, so
   the dark ink meant for a gold fill landed straight on the dark background:
   the dashboard's "ייצוא JSON" measured 1.0:1 at all seven widths — text the
   same colour as what is behind it. Variants that bring their own surface and
   their own ink keep both. */
:root .btn-outline, :root .btn-outline:hover,
:root .btn-danger, :root .btn-danger:hover,
:root .btn-ghost, :root .btn-ghost:hover { color: var(--text, var(--jp-text, #F4F1EA)); }
:root .btn-danger, :root .btn-danger:hover { color: var(--red, #FF8A85); }
/* The editorial sheet paints .ed .cta .btn cream-on-champagne with a two-class
   selector, which outranks the single-class rule above. Matched at the same
   depth rather than escalated to !important. */
:root .ed .cta .btn, :root .ed .btn-coral { color: var(--on-sky, #12161F); }

/* (b) the muted ink under the destination hero and in editorial asides */
:root .dfacts span,
:root .dfacts small,
:root .relc small,
:root .ed-card small,
:root .cmp-note small { color: var(--jp-text-2); }

/* (c) chips that carried a pale background from the cream design.
   The BACKGROUND is a 14% tint, so over the white card it lands near #F5EEE3
   and #E4F0EB. The ink was still the pale value from when the tint sat on a
   dark ground: measured 2026-08-31 on /tisot-zolot-*, .af-tag was
   rgb(167,233,196) on rgb(255,255,255) at 1.39:1. Same hue, taken dark enough
   to read on its own tint. */
/*
 * RE-INVERTED 2026-09-02. Read the comment above: these inks were taken DARK
 * because the tint had moved onto a white card, and the note records that they
 * had been pale "from when the tint sat on a dark ground". The ground is dark
 * again, so they are pale again — #5C3D0E and #12523A measured 2.43:1 and
 * 1.94:1 on the card.
 *
 * The lesson is the ping-pong itself: a chip's ink is not a property of the
 * chip, it is a property of what the chip sits on. Anything hardcoded here
 * will have to be edited again on the next inversion, which is why the tints
 * are alpha over whatever the ground is and only the ink is a literal.
 */
:root .info-tag {
  background: rgba(201, 162, 74, .14);
  border: 1px solid rgba(201, 162, 74, .34);
  color: var(--jp-gold-pale);
}
:root .af-tag {
  background: rgba(31, 107, 74, .20);
  border: 1px solid rgba(127, 211, 174, .34);
  color: #A7E9C4;
}

/* (d) comparison engine prices, lifted to readable equivalents of the same hues */
:root .jce-price { color: var(--jp-text) !important; }          /* [injected] engine writes inline colours */
:root .jce-price-best { color: #8EC5FF !important; }
:root .jce-saved { color: #A7E9C4 !important; }
:root .jce-price-unit { color: var(--jp-text-3); }

/* ---------------------------------------------------------------------------
   (e) The live-deal cards.

   `.ldc` is in the raised-surface list above, so the premium layer repainted
   the card from cream (#FFFDFA→#FFF7EC) to --jp-raised (#0E131D). Its TEXT was
   never converted with it, so every one of these kept the colours it was given
   for a cream card. Measured on the live homepage, 2026-08-16:

       .ldc__price b   #241A13 on #0E131D   contrast 1.09   at 38px
       .ldc__code      #7B6553 on #0E131D   contrast 3.39
       .ldc__when b    #4A3728 on #0E131D   contrast 1.65

   The price — the single most important number on the homepage — was rendering
   at 1.09:1. Not "hard to read": not visible.

   The dead selector `.ldc-price` a few hundred lines up is why this was never
   caught by the tabular-numerals pass either; the markup has always used
   `.ldc__price`. It is corrected there.

   This block converts the text only. The card, its layout, its CTA and the
   premium surface are untouched.
--------------------------------------------------------------------------- */
:root .ldc__dest        { color: var(--jp-text); }
:root .ldc__price,
:root .ldc__price b     { color: var(--jp-text); }
:root .ldc__cur,
:root .ldc__price small { color: var(--jp-text-2); }
:root .ldc__when        { color: var(--jp-text-3); }
:root .ldc__when b      { color: var(--jp-text-2); }
:root .ldc__disc        { color: var(--jp-text-3); }

:root .ldc__code {
  color: var(--jp-text-2);
  background: var(--jp-line-soft);
  border: 1px solid var(--jp-line-soft);
}
:root .ldc__badge {
  color: var(--jp-gold);
  background: rgba(14, 90, 82, .14);
  border: 1px solid var(--jp-line-strong);
}
/* The saving note was brand coral #BF4423, which is a light-surface colour.
   Lifted to the same hue at a luminance that clears AA on --jp-raised. */
:root .ldc__save        { color: #FF9E7A; }
:root .ldc__cta         { border-top-color: var(--jp-line-soft); }
/* A cream skeleton flashing on a dark page reads as a broken card. */
:root .ldc--skel        { background: var(--jp-raised); border-color: var(--jp-line-soft); }

/* ---- The two the 2026-08-16 pass missed, found by the contrast gate ------
   `tests/visual/run_contrast_gate.js` renders the page and composites the real
   backdrop, which is how these surfaced after a source-reading pass had
   already been over this same block:

       .ldc__dates    #4A3728 on #0E131D   contrast 1.53
       .ldc__ph       background #EAE2D6   — a cream plate behind every photo

   The dates are the second thing a shopper reads after the price, and they
   were at 1.53:1. The placeholder only shows for the instant before a lazy
   image decodes and wherever a plate is missing, which is exactly why it was
   never noticed and exactly why it looks broken when it happens: a cream
   rectangle flashing inside a dark card.                                    */
:root .ldc__dates,
:root .ldc__dates span  { color: var(--jp-text-2); }
:root .ldc__dates b     { color: var(--jp-text); }
:root .ldc__ph          { background: var(--jp-elevated); }


/* == 16 · CONTRAST OVER IMAGERY ==========================================
   Closing every failure `scripts/contrast_over_media.js` reports — the check
   that scores text at its GLYPH pixels against the photograph actually behind
   it, which is the only measurement that sees these at all: a11y_audit.js
   walks up to the first opaque ancestor, and text on a hero plate has none.

   The owner's decision on 2026-08-25 was to close all of them, including the
   marginal 4.0-4.4 cases that an earlier comment recorded as a deliberate
   trade against flattening the photography. So the rule here is the smallest
   intervention that MEASURES a pass, in this order: a local scrim on the text,
   then a colour lift, then a wider overlay — never a threshold exemption and
   never a blanket darkening of the plates.

   Every number below was measured on the rendered page, not derived from the
   source. The failing values are recorded beside each fix so a future change
   that reopens one is recognisable as a regression rather than a preference.
   ---------------------------------------------------------------------- */

/* ---- Header navigation over a hero plate --------------------------------
       "יעדים" 3.66:1 · "חיפוש" 4.32 · "מלונות" 4.37 · "אודות" 4.35

   WITHDRAWN 2026-08-31. The fix below was written for the dark homepage hero
   of 2026-08-19 and that hero no longer exists: `.jh__scrim` is on ZERO built
   pages after the 2026-08-30 redesign, and `motion_qa` reports the same
   absence for `window.JanetMotion` and `.jh`. What survived was `.hd {
   position: fixed }` and a 190px black vignette, applied to every `.hd` on the
   site — and `.hd` is also the header of the ten destination pages.

   `position: fixed` with no `inset-inline` shrink-wraps to its content. In an
   RTL layout that put the whole header in a 375px box pinned to the right
   edge: measured on /tisot-zolot-ams at a 1400px viewport, `.hd` was
   374.76px wide starting at x=1015. The bar had not looked broken only
   because the theme had also made it transparent.

   The homepage keeps its own `position: sticky` and is unaffected either way;
   its nav ink rule below is still live and still measured.

   The destination header's real problem — dark grey ink on a photograph — is
   answered at section 04 by giving it the theme's glass, which is what those
   pages' own sheets asked for before the theme reached them. */

:root .hd-nav a { color: var(--jp-text); }
:root .hd-nav a[aria-current="page"] { color: var(--jp-gold-pale); }

/* ---- Hero sub-copy ------------------------------------------------------
       "ג׳נט סורקת את מחירי הטיסות…" 1.99:1 — the worst on the site.

   The 180deg hero scrim is at its THINNEST (.28) exactly where the paragraph
   sits, roughly 47% down, because that band was tuned to keep the middle of
   the plate open. Measured backdrop there: rgb(156,141,128).

   The first attempt gave the paragraph a radial halo of its own. It measured
   7.6:1 and it LOOKED like a rounded card floating on the plate — a box drawn
   around a sentence, which is exactly the tell this design spends its effort
   avoiding. Screenshots caught it; the numbers were happy.

   So the light is shaped on the plate instead, where a falloff reads as a
   vignette because that is what it is. 270deg puts 0% at the right edge, which
   in this RTL layout is the column holding the headline, the sub and the
   search panel; it is transparent by 56%, and Janet's cutout starts at 49%
   from that edge and sits on a HIGHER layer than the scrim in any case, so
   nothing of hers is touched. Measured after: 7.2:1. */
.jh__scrim {
  background:
    linear-gradient(270deg, rgba(5,7,12,.72) 0%, rgba(5,7,12,.54) 24%, rgba(5,7,12,.22) 42%, rgba(5,7,12,0) 56%),
    linear-gradient(180deg, rgba(5,7,12,.62) 0%, rgba(5,7,12,.28) 34%, rgba(5,7,12,.86) 88%, var(--jp-void) 100%),
    radial-gradient(70% 55% at 72% 26%, rgba(14, 90, 82, .14), transparent 70%);
}
.jh__sub { color: var(--jp-text); }

/* Below 900px this is a DIFFERENT problem wearing the same failure. The side
   column centres itself and the paragraph lands on Janet's own cutout —
   measured backdrop rgb(187,155,131), which is her skin, not the plate. She
   renders ABOVE .jh__scrim, so no amount of scrim reaches it: deepening the
   plate ramp there moved the number the wrong way (4.02 -> 2.29) while making
   the picture darker for nothing.

   The only surface between her and the text is the text's own, so at these
   widths the paragraph carries a halo. A rounded plate over a cutout at phone
   width reads as a caption panel rather than as a box around a sentence, and
   there is no other way to put anything between the two. Measured after: 6.1:1. */
@media (max-width: 900px) {
  .jh__sub {
    padding: 12px 18px;
    margin-inline: -18px;
    border-radius: 20px;
    background: radial-gradient(140% 170% at 50% 50%,
      rgba(5, 7, 12, .52) 0%,
      rgba(5, 7, 12, .50) 68%,
      rgba(5, 7, 12, .26) 88%,
      rgba(5, 7, 12, 0) 100%);
  }
}

/* ---- Destination code chip on a live-deal photo -------------------------
       "BUD" 4.39:1

   `:root .ldc__code` gave the chip `background: var(--jp-line-soft)` — a
   hairline token, rgba(244,241,234,.09). On a card that is the right idea and
   over a photograph it is a pale film that RAISES the backdrop luminance
   toward the ink it sits under. The chip needs a floor, not a film. */
:root .ldc__code {
  background: rgba(5, 7, 12, .62);
  border: 1px solid var(--jp-line);
  color: var(--jp-text);
}

/* ---- Editorial badge on a picks-rail photo ------------------------------
       "שעה כחולה" 2.23:1 · "רחוק ושווה" 2.68:1

   Same shape of error and a worse outcome: champagne at 14% over a daylight
   canal (rgb(111,165,176)) is transparent, and the label was pale gold on the
   water itself. The gold stays — it moves from the fill to a hairline and the
   ink, and the fill becomes the floor. Measured after: 10.7:1. */
:root .pick__badge {
  background: rgba(5, 7, 12, .72);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  border: 1px solid var(--jp-line-strong);
  color: var(--jp-gold-pale);
}


/* == 20 · TOUCH TARGET FLOOR (2026-08-30) ==================================
 *
 * WCAG 2.5.8 asks for 44×44 CSS px. Measured at 390×844 with touch emulation,
 * several navigation links across the product were tall enough and too narrow
 * — 33×64, 35×64, 40×64 — because their label is one short Hebrew word. A tall
 * thin target is still a miss on a phone.
 *
 * This is the SYSTEM floor and lives in the theme so every page inherits it,
 * including the ~60 pages the redesign did not rewrite. It only ever grows a
 * target; it sets no colour and changes no layout beyond the hit area.
 */
.jh-bar__nav a,
.jh-guides__row a,
.jp-bar__nav a,
.bottom-nav a,
.ft-links a,
.gp-obs__city,
/* The destination-page breadcrumb: a NAV control with no class of its own,
   measured at 34x44 on every width. It was the only target on the page
   under the floor, and it was missing from this list rather than exempt. */
.mdh-hero__in nav a,
footer > nav > a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-block-size: 44px;
  min-inline-size: 44px;
  padding-inline: .4rem;
}

/* THE DESTINATION BREADCRUMB SITS ON A PHOTOGRAPH.
 *
 * `<nav aria-label="מיקום">` in the hotel-destination hero carries an inline
 * `color:#fff` and an inline `opacity:.9`, over a full-bleed city photograph.
 * The release gate measured the actual pixels under the glyphs and got
 * 3.08:1 on Barcelona, 3.28 on Budapest, 3.42 on Paris and 4.42 on Rome —
 * white type on whatever the sky happens to be that day. No stylesheet could
 * reach the colour, because it is written into the markup of nine generated
 * pages.
 *
 * So the fix is not the colour, it is the GROUND: a plate under the
 * breadcrumb makes it legible over any photograph, including one swapped in
 * next month. Sized from the text rather than the viewport so it stays a
 * breadcrumb and not a bar.
 *
 * The inline `opacity:.9` is left alone on purpose. It outranks any selector
 * here — only !important would beat it, and an !important added to win an
 * argument with the markup is how a stylesheet stops being readable. It dims
 * the plate to an effective .70, which over the worst of the four photographs
 * still lands the white type around 11:1. A declaration that cannot apply is
 * worse than none: it reads as handled.
 */
.mdh-hero__in nav[aria-label] {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  background: rgba(8, 9, 11, .78);
  padding: .2rem .7rem;
  border-radius: 999px;
}
.mdh-hero__in nav[aria-label] a { color: var(--jp-paper, #F5F3EF); }

/* == 21 · COMPONENT-SCOPED PALETTES (2026-08-30) ==========================
 *
 * Some sheets declare their palette ON THE COMPONENT (.jhc, .ed, .ls, .jp)
 * rather than on :root. Re-pointing those tokens on :root does NOT reach
 * them, and NOT for a specificity reason:
 *
 *   a declaration ON an element always beats a value INHERITED from an
 *   ancestor, whatever the two selectors specificities are.
 *
 * Specificity only breaks ties between rules matching the SAME element, and
 * :root is a different element from .jhc. Lowering those sheets to :where()
 * was therefore necessary but NOT sufficient - measured on production after
 * shipping it, --jhc-coral-ink still resolved to #B8401F at .jhc__amount
 * while :root said #0E5A52, and 44 prices stayed coral.
 *
 * So the theme re-points them HERE, on the same elements. This sheet loads
 * last and these selectors carry real specificity, so they win over the
 * :where() defaults while leaving anything the theme does not name alone.
 */
.jhc, .jhf, .jhd {
  --jhc-ink:        var(--jp-text);
  --jhc-ink-2:      var(--jp-text-2);
  --jhc-mute:       var(--jp-text-3);
  --jhc-line:       var(--jp-line);
  --jhc-line-2:     var(--jp-line-soft);
  --jhc-card:       var(--jp-raised);
  --jhc-coral:      var(--jp-gold);
  --jhc-coral-ink:  var(--jp-gold);
  --jhc-coral-soft: var(--sky-ice);
  --jhc-navy:       var(--jp-text-2);
  --jhc-teal:       var(--jp-ok);
  --jhc-good:       var(--jp-ok);
}
.ed {
  --ed-cream: var(--jp-void); --ed-sand: var(--jp-base); --ed-ink: var(--jp-text);
  --ed-ink-2: var(--jp-text-2); --ed-mute: var(--jp-text-3);
  /*
   * --ed-coral-t is NOT a wash. `janet_editorial.css` documents it as "4.9:1 on
   * cream — anything small or filled" and uses it four times: as the colour of
   * a breadcrumb link, of a body link, of a highlighted line, and as the
   * BACKGROUND of `.ed .btn-coral`. A --sky-ice here (rgba(14,90,82,.09)) made
   * every one of those a 9% tint.
   *
   * Measured on production 2026-08-31: `a.btn` on the guide pages rendered
   * rgb(251,250,248) on rgb(251,250,248) — 1.00:1, white on white. Those are
   * the affiliate CTAs, the links Drive rewrites into emrld.ltd, i.e. the
   * monetizable clicks on eight editorial pages, invisible.
   *
   * It takes the opaque accent, which is what the earlier `.ed` block at
   * section 12 already set it to. That block is EARLIER in the file, so at
   * equal specificity this one was winning and silently overrode a correct
   * value with a surface tint. --jp-gold carries white at 8.3:1.
   */
  --ed-coral: var(--jp-gold); --ed-coral-t: var(--jp-gold); --ed-line: var(--jp-line-soft);
}
.ls {
  --ls-cheap: var(--jp-ok); --ls-warn: var(--jp-warn); --ls-stale: var(--jp-text-3);
}
.jp {
  --jt-ink: var(--jp-text); --jt-ink-2: var(--jp-text-2); --jt-mute: var(--jp-text-3);
}


/* == 17 · THE ACCENT INVERSION'S LONG TAIL ================================
   Eight contrast failures, one cause, found by the release gate on pages the
   homepage audit never opened. Every one is a colour picked for a LIGHT ground
   that the token re-point left sitting on a dark one — the failure this file's
   header warns about, arriving in the places nobody looks.

   They are fixed here rather than in each sheet because this is the file that
   decides the ground. A fix in janet_hotels.css would be correct today and
   wrong again the next time the direction moves.
   ========================================================================== */

/* --jp-gold-DEEP and --jp-gold-WARM are the steps that read on paper. On a dark
   card they measure 3.63:1. The pale step is the one a dark ground needs, and
   the three selectors below are every place the gate caught them. */
:root .jdd-card__win,
:root .jfw-c__go,
:root .jdd-card__win b,
:root .jfw-c b { color: var(--jp-gold-pale); }

/*
 * The wordmark on the sticky bar came out at 1.02:1 — near-black on near-black,
 * which is not "hard to read", it is gone.
 *
 * The cause is worth stating exactly, because it is a pattern and not a typo.
 * 18 guide pages paint that bar with a hardcoded `rgba(7,13,21,.92)` — a dark
 * literal, deliberately, so the bar is dark even on a cream page — and then
 * write its text as `color: var(--jp-void)`, the PAGE FLOOR, because on a cream
 * site the floor was the light colour. A literal ground paired with a token
 * ink survives exactly as long as the token keeps its old value.
 *
 * So the ink becomes a literal too. The bar's ground does not follow the theme;
 * its text must not either, or the next inversion breaks it again in the same
 * place. This is the one spot in this file where a literal is the correct
 * answer rather than the lazy one.
 */
:root .bar,
:root .bar .logo,
:root .bar .logo-name,
:root .bar .logo-name small,
:root .ed .logo-name,
:root .ed .logo-name small { color: #F5F3EF; }
:root .bar .logo-name small { color: var(--jp-gold-pale); }

/* The guide-page breadcrumb sits ON the hero photograph, and the champagne
   accent measured 3.97-4.16:1 against the sampled pixels — the accent is a
   colour chosen against the PAGE, and a photograph is not the page. Over
   imagery it takes near-white, which is the one value that holds whatever the
   photograph turns out to be. The accent still marks the crumb elsewhere. */
:root .ghero__crumb a,
:root .dhero__crumb a { color: #FFF3E6; }

/* The two tints those chips sit on were teal rgba, which no token re-point can
   reach — a green ground under gold type is the same clash one layer down. */
:root .jh-hero__eyebrow { background: rgba(201, 162, 74, .12); }
:root .jh-promise li::before { background: rgba(201, 162, 74, .14); }

/* == 17 · THE MOTION SYSTEM'S PALETTE ====================================
 *
 * `bk_motion.css` declares three colour tokens of its own: the champagne edge
 * that makes a lit surface read as lit, its softer form, and the sheen that
 * crosses a card on hover. They are re-pointed HERE and not left in that sheet
 * for the reason section 01 gives and `test_one_visual_system.js` enforces: a
 * palette the theme has never heard of survives a theme change with its old
 * values, which is exactly how `--jh-card` stayed #fff and put cream text on
 * white. The theme owns colour; a component sheet owns behaviour.
 *
 * The values below are the same ones bk_motion.css defaults to, because the
 * motion system was authored against this theme. That is the point: when the
 * accent moves next, ONE file moves and the edge light, the focus glow and the
 * hover sheen move with it.
 */
:root {
  --bk-edge:      rgba(201, 162, 74, .34);
  --bk-edge-soft: rgba(201, 162, 74, .16);
  --bk-sheen: linear-gradient(105deg,
                rgba(255, 255, 255, 0) 38%,
                rgba(255, 255, 255, .13) 48%,
                rgba(255, 255, 255, 0) 58%);
}

/* == 18 · THE bkx SHELL'S PALETTE =========================================
 *
 * `bkx.css` is the rebuilt homepage's visual shell, and it declares its own
 * colour tokens. They are re-pointed HERE for the reason section 01 gives and
 * `test_one_visual_system.js` enforces: a palette the theme has never heard of
 * survives a theme change carrying its old values, which is exactly how
 * `--jh-card` stayed #fff and put cream text on white.
 *
 * The shell declares them inside `:where(.bkx)`, which contributes zero
 * specificity — so these `:root` values win wherever they exist, and the
 * shell's own remain the defaults for anything not listed. The theme owns
 * colour; a component sheet owns behaviour.
 */
:root {
  --x-void:      #04070C;
  --x-deep:      #070B13;
  --x-raised:    #0C1119;
  --x-line:      rgba(240, 236, 226, .10);
  --x-line-2:    rgba(240, 236, 226, .18);
  --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;
  --x-ink:       #F5F1E8;
  --x-ink-2:     #C3C6CC;
  --x-ink-3:     #8E939C;
  --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));
}
