*{box-sizing:border-box}html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}body{margin:0;color:var(--ink);background:var(--bg);font-family:var(--font-sans);font-size:16px;line-height:1.6;-webkit-font-smoothing:antialiased}body.menu-open{overflow:hidden}a{color:inherit;text-decoration:none}img{max-width:100%;display:block}button,input,select,textarea{font:inherit;color:inherit}button,a,input,select,textarea{outline-offset:2px}:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:4px;box-shadow:0 0 0 4px rgba(47,134,218,.22)}h1,h2,h3,p{margin-top:0}h1,h2{font-family:var(--font-display);font-weight:var(--fw-display);letter-spacing:var(--track-h2);line-height:1.08;text-wrap:balance}
/* text-wrap balance/pretty run a multi-pass line-breaking search per element,
   and that search repeats on every layout. Applied to all h1/h2/h3 and every
   <p>, it was 49 elements x 25 layouts on the homepage and measured as 1455ms
   of layout under CPU throttling. Kept on h1/h2 only, where the headline is
   short and the even line lengths actually show; h3 card titles and body
   paragraphs wrap fine with the browser's normal greedy algorithm. */
h3{font-family:var(--font-display);font-weight:var(--fw-medium);letter-spacing:var(--track-h3);line-height:1.2}.container{width:min(calc(100% - 40px),var(--container));margin-inline:auto}.section{padding:88px 0}.section-heading{display:flex;justify-content:space-between;align-items:end;gap:30px;margin-bottom:34px}.section-heading h2{max-width:760px;margin-bottom:8px;font-size:clamp(36px,4vw,50px)}.section-heading p{margin:0;color:var(--voyz-muted)}.section-heading>a{color:var(--voyz-blue-700);font-weight:var(--fw-label);display:flex;align-items:center;gap:8px}.section-heading svg{width:17px}.site-header{position:sticky;top:0;z-index:50;height:72px;border-bottom:1px solid transparent;background:rgba(255,255,255,.96)}.site-header.scrolled{border-color:var(--voyz-line);box-shadow:0 6px 20px rgba(2,31,70,.05)}.header-inner{height:72px;display:flex;align-items:center}.header-logo{display:flex;align-items:center;color:var(--ink);padding-inline-end:clamp(8px,1.4vw,20px);flex:0 0 auto}
/* Brand lockup: the real VOYZ artwork from static/images, composed
   horizontally (symbol + wordmark) so it fits a 72px header bar. The stacked
   master file carries a tagline that is illegible at this height. */
/* The lockup keeps its internal order in every direction — a logo is artwork,
   not a sentence, so it must not mirror when the page flips to RTL. */
.voyz-logo{display:inline-flex;align-items:center;gap:.5rem;line-height:1;direction:ltr}
.voyz-logo-mark{width:auto;height:30px;flex:0 0 auto}
.voyz-logo-word{width:auto;height:18px;flex:0 0 auto}
/* The artwork is navy: on dark surfaces render it white or it disappears. */
.site-footer .voyz-logo img,
.sidebar .voyz-logo img,
.voyz-logo.on-dark img{filter:brightness(0) invert(1)}.desktop-nav{margin-inline-start:clamp(28px,4vw,56px);display:flex;gap:clamp(20px,2.2vw,32px)}.desktop-nav a,.header-login{font-size:14px;font-weight:600}.desktop-nav a:hover,.header-login:hover{color:var(--voyz-blue-700)}.header-actions{margin-inline-start:auto;display:flex;gap:clamp(12px,1.4vw,20px);align-items:center}.menu-toggle{display:none;width:44px;height:44px;border:0;background:transparent;place-items:center}.mobile-drawer{display:none}.site-footer{padding:52px 0;background:var(--voyz-navy-950);color:#fff}.footer-layout{display:grid;grid-template-columns:2fr 1fr 1fr;gap:50px}.footer-layout>div{display:flex;flex-direction:column;gap:9px}.footer-layout .voyz-logo{color:#fff;margin-bottom:2px}.footer-layout .voyz-logo-mark{height:32px}.footer-layout .voyz-logo-word{height:20px}.footer-layout p,.footer-layout a{color:#c3d1e2;font-size:13px}.footer-layout a:hover{color:#fff}.toast-wrap{position:fixed;z-index:100;top:85px;right:20px}.toast{max-width:440px;padding:14px;display:flex;gap:10px;background:#fff;border:1px solid var(--voyz-line);box-shadow:0 10px 30px rgba(2,31,70,.12)}.toast button{margin-left:auto;border:0;background:none}
/* Type system. Display sizes run light; small text runs semibold. Numerals are
   tabular everywhere they sit in a column (prices, dates, counts). */
body{font-family:var(--font-sans);font-weight:var(--fw-body)}
.departure-row time b,.mood b{font-family:var(--font-display);font-weight:var(--fw-medium);font-variant-numeric:tabular-nums}
b,strong{font-weight:var(--fw-label)}
small{font-size:.8125rem}
/* Visible to screen readers only. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
.toast-wrap{z-index:110}.toast{width:min(400px,calc(100vw - 40px));align-items:center;border-radius:8px;animation:toast-in .48s cubic-bezier(.2,.8,.2,1) both}.toast.success{border-color:#b9dfd0;background:#f7fcfa}.toast-icon{width:30px;height:30px;flex:0 0 30px;display:grid;place-items:center;border-radius:50%;color:var(--voyz-blue-700);background:var(--voyz-sky-100)}.toast.success .toast-icon{color:#fff;background:var(--voyz-success);animation:success-pop .55s .22s cubic-bezier(.2,1.6,.4,1) both}.toast-icon svg{width:17px}.toast button{width:32px;height:32px;padding:0;display:grid;place-items:center;cursor:pointer}.toast button svg{width:17px}.toast.is-leaving{animation:toast-out .25s ease both}
/* No blanket section reveal. Sections render at full opacity: content is never
   gated behind a class a script has to add, and no transform is applied to
   ancestors of position:sticky children (which would break their pinning).
   Deliberate motion lives in the surface that earns it — see departure.css. */
@keyframes toast-in{from{opacity:0;transform:translateY(-12px) scale(.97)}}@keyframes toast-out{to{opacity:0;transform:translateX(20px)}}@keyframes success-pop{0%{transform:scale(.4)}100%{transform:scale(1)}}
@media(prefers-reduced-motion:reduce){*{scroll-behavior:auto!important;transition:none!important;animation:none!important}}
/* Language switcher — modelled on the iOS segmented control: a recessed track
   with one white thumb that slides between segments. The thumb is a single
   element, so a switch reads as one continuous movement rather than two
   colour swaps, and it decelerates without overshooting. */
.language-toggle{
  --seg: 40px;                       /* one segment */
  position:relative;
  padding:2px;height:34px;
  display:inline-flex;align-items:center;
  border:0;border-radius:9px;
  background:rgba(118,118,128,.12);  /* Apple's fill-tertiary over light */
  cursor:pointer;
  -webkit-tap-highlight-color:transparent;
  transition:background var(--dur-2) var(--ease-ios-soft);
}
.language-toggle:hover{background:rgba(118,118,128,.18)}
.language-toggle:focus-visible{outline:2px solid var(--brand);outline-offset:3px}

/* The thumb. Travel uses the iOS curve; the tap squeeze is separate and faster,
   so pressing feels immediate while the slide stays smooth. */
.language-toggle::before{
  content:"";position:absolute;z-index:0;
  top:2px;left:2px;width:var(--seg);height:30px;
  border-radius:7px;background:#fff;
  box-shadow:0 3px 8px rgba(0,0,0,.12),0 3px 1px rgba(0,0,0,.04),0 0 0 .5px rgba(0,0,0,.04);
  transition:transform var(--dur-3) var(--ease-ios),width var(--dur-tap) var(--ease-ios-tap);
}
.language-toggle:has(span:last-child.active)::before{transform:translateX(var(--seg))}
[dir=rtl] .language-toggle::before{left:auto;right:2px}
[dir=rtl] .language-toggle:has(span:last-child.active)::before{transform:translateX(calc(var(--seg) * -1))}
/* Press: the thumb widens a touch instead of bouncing — the iOS behaviour. */
.language-toggle:active::before{width:calc(var(--seg) + 4px)}

.language-toggle span{
  position:relative;z-index:1;
  width:var(--seg);height:30px;
  display:grid;place-items:center;
  color:var(--ink-2);font-size:12px;font-weight:var(--fw-label);letter-spacing:0;
  transition:color var(--dur-2) var(--ease-ios-soft),opacity var(--dur-2) var(--ease-ios-soft);
  opacity:.62;
}
.language-toggle span.active{color:var(--ink);opacity:1}
/* The ع in the toggle is the only Arabic glyph on a French page, and asking
   for IBM Plex Sans Arabic here pulled a 45KB webfont onto every French page's
   critical path for one character. A system Arabic face renders it identically
   at this size; the webfont still loads on Arabic pages, where it earns its
   weight. */
.language-toggle span:last-child{font-family:"Segoe UI","Geeza Pro","Noto Naskh Arabic",system-ui,sans-serif;font-size:15px;line-height:1}
.mobile-language-toggle{margin-bottom:12px;align-self:flex-start}

/* On dark surfaces (dashboard rail, drawer) the track inverts. */
.sidebar .language-toggle,.language-toggle.on-dark{background:rgba(255,255,255,.14)}
.sidebar .language-toggle::before,.language-toggle.on-dark::before{background:rgba(255,255,255,.92)}

@media (prefers-reduced-motion:reduce){
  .language-toggle::before{transition:none}
}.lang-ar body,.lang-ar h1,.lang-ar h2,.lang-ar h3{font-family:var(--font-ar)}.lang-ar h1,.lang-ar h2,.lang-ar h3{letter-spacing:0}[dir="rtl"],[lang="ar"]{font-family:var(--font-ar)}.lang-ar .desktop-nav,.lang-ar .header-actions,.lang-ar main{text-align:right}
