/*
 * Revie Travels - Design Tokens
 * Based on Revie Design System v1.0
 * All values match the official design system exactly.
 */

/* ── CRITICAL: hidden always wins ── */
[hidden] { display: none !important; }

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 16px; -webkit-text-size-adjust: 100%; }

:root {
  /* ── Brand colours ── */
  --revie-blue-50:  #E6F4FA;
  --revie-blue-100: #C2E4F2;
  --revie-blue-300: #4DB3D6;
  --revie-blue-500: #0492C2;   /* PRIMARY */
  --revie-blue-700: #035F80;

  /* ── Semantic colour aliases ── */
  --color-primary:       #0492C2;
  --color-primary-hover: #035F80;
  --color-primary-soft:  #E6F4FA;

  /* ── Neutral palette ── */
  --neutral-25:  #FAFBFC;   /* page background */
  --neutral-50:  #F3F5F7;
  --neutral-100: #E7EBEF;   /* hairline borders */
  --neutral-200: #CDD3D9;
  --neutral-300: #A8B2BC;
  --neutral-400: #8C96A0;   /* placeholder text */
  --neutral-500: #667380;
  --neutral-600: #4A5560;
  --neutral-700: #353D45;   /* body text */
  --neutral-900: #0E1318;   /* footer / nav dark */

  /* ── Semantic status ── */
  --color-success:       #1B8A4A;
  --color-success-soft:  #E8F5EE;
  --color-warning:       #B8770A;
  --color-warning-soft:  #FDF4E3;
  --color-error:         #C62828;
  --color-error-soft:    #FDEAEA;
  --color-info:          #0492C2;
  --color-info-soft:     #E6F4FA;

  /* ── Surface ── */
  --surface-page:  #FAFBFC;
  --surface-card:  #FFFFFF;
  --surface-raised: #FFFFFF;

  /* ── Border ── */
  --border-subtle: #E7EBEF;
  --border-default: #CDD3D9;
  --border-strong: #8C96A0;

  /* ── Text ── */
  --text-primary:   #0E1318;
  --text-secondary: #353D45;
  --text-tertiary:  #667380;
  --text-placeholder: #8C96A0;
  --text-disabled:  #A8B2BC;
  --text-inverse:   #FFFFFF;
  --text-brand:     #0492C2;

  /* ── Typography ── */
  --font-sans: Arial, Helvetica, sans-serif;
  --fw-regular: 400;
  --fw-medium:  500;
  --fw-bold:    700;

  /* Font sizes */
  --fs-12: 0.75rem;     /* 12px - caption, labels */
  --fs-13: 0.8125rem;   /* 13px - helper */
  --fs-14: 0.875rem;    /* 14px - body-sm */
  --fs-15: 0.9375rem;   /* 15px - body */
  --fs-16: 1rem;        /* 16px - body-lg */
  --fs-18: 1.125rem;    /* 18px - h4 */
  --fs-20: 1.25rem;     /* 20px - h3 */
  --fs-24: 1.5rem;      /* 24px - h2 */
  --fs-32: 2rem;        /* 32px - h1 */

  /* ── Spacing (4px base grid) ── */
  --space-1:  4px;
  --space-2:  8px;
  --space-3:  12px;
  --space-4:  16px;
  --space-5:  20px;
  --space-6:  24px;
  --space-8:  32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;

  /* ── Border radius ── */
  --radius-sm: 4px;
  --radius-md: 6px;   /* inputs, buttons */
  --radius-lg: 10px;  /* cards */
  --radius-xl: 16px;  /* heroes */
  --radius-pill: 999px;

  /* ── Shadows ── */
  --shadow-sm: 0 1px 3px rgba(14,19,24,0.08), 0 1px 2px rgba(14,19,24,0.04);
  --shadow-md: 0 4px 12px rgba(14,19,24,0.10), 0 2px 4px rgba(14,19,24,0.06);
  --shadow-lg: 0 8px 24px rgba(14,19,24,0.12), 0 4px 8px rgba(14,19,24,0.06);

  /* ── Transitions ── */
  --t: 0.18s ease;
}

/* ════════════════════════════════════════
   BASE
════════════════════════════════════════ */
body {
  font-family: var(--font-sans);
  font-size: var(--fs-15);
  font-weight: var(--fw-regular);
  color: var(--text-secondary);
  background: var(--surface-page);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* WIDGET MODE (?widget=1) - for embedding just the search card in a
   third-party page's own hero section (e.g. a WordPress iframe), instead
   of this page's normal full-width, padded, grey-background layout.
   Strips the outer page chrome down to just the card itself so it sits
   flush against whatever background it's embedded into. Nothing about
   the search form/results logic changes - this is CSS-only. */
body.r-widget-mode { background: transparent; }
body.r-widget-mode .r-page-body { padding: 0; }
body.r-widget-mode .r-container { padding: 0; max-width: none; }

a { color: var(--color-primary); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ════════════════════════════════════════
   TYPOGRAPHY SCALE (r- prefix = Revie DS)
════════════════════════════════════════ */
.r-h1 { font-size: var(--fs-32); font-weight: var(--fw-bold); color: var(--text-primary); line-height: 1.2; letter-spacing: -0.01em; }
.r-h2 { font-size: var(--fs-24); font-weight: var(--fw-bold); color: var(--text-primary); line-height: 1.3; }
.r-h3 { font-size: var(--fs-20); font-weight: var(--fw-bold); color: var(--text-primary); line-height: 1.35; }
.r-h4 { font-size: var(--fs-18); font-weight: var(--fw-bold); color: var(--text-primary); line-height: 1.4; }
.r-lead   { font-size: var(--fs-16); color: var(--text-secondary); line-height: 1.6; }
.r-body   { font-size: var(--fs-15); color: var(--text-secondary); }
.r-helper { font-size: var(--fs-13); color: var(--text-tertiary); }
.r-caption{ font-size: var(--fs-12); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-tertiary); }

/* ════════════════════════════════════════
   BUTTONS  (r-btn)
════════════════════════════════════════ */
.r-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  padding: 10px var(--space-6);
  background: var(--color-primary);
  color: var(--text-inverse);
  border: 1.5px solid var(--color-primary);
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
  font-size: var(--fs-15);
  font-weight: var(--fw-bold);
  cursor: pointer;
  transition: background var(--t), border-color var(--t), box-shadow var(--t), transform var(--t);
  text-decoration: none;
  white-space: nowrap;
  user-select: none;
}
.r-btn:hover:not(:disabled) {
  background: var(--color-primary-hover);
  border-color: var(--color-primary-hover);
  box-shadow: 0 2px 8px rgba(4,146,194,0.25);
}
.r-btn:active:not(:disabled) { transform: translateY(1px); }
.r-btn:disabled { background: var(--neutral-200); border-color: var(--neutral-200); color: var(--text-disabled); cursor: not-allowed; }
.r-btn:focus-visible { outline: 3px solid var(--revie-blue-300); outline-offset: 2px; }

.r-btn--secondary { background: transparent; color: var(--color-primary); }
.r-btn--secondary:hover:not(:disabled) { background: var(--color-primary-soft); border-color: var(--color-primary); box-shadow: none; }
.r-btn--ghost { background: transparent; border-color: var(--border-default); color: var(--text-secondary); }
.r-btn--ghost:hover:not(:disabled) { border-color: var(--neutral-400); background: var(--neutral-50); box-shadow: none; }
.r-btn--danger { background: var(--color-error); border-color: var(--color-error); }
.r-btn--danger:hover:not(:disabled) { background: #A32020; border-color: #A32020; }
.r-btn--sm { padding: 6px var(--space-4); font-size: var(--fs-13); }
.r-btn--lg { padding: 14px var(--space-8); font-size: var(--fs-16); }
.r-btn--block { width: 100%; }
.r-btn.is-loading { opacity: 0.75; cursor: wait; pointer-events: none; }

/* ════════════════════════════════════════
   FORM FIELDS  (r-field, r-input)
════════════════════════════════════════ */
.r-field { display: flex; flex-direction: column; gap: var(--space-1); }
.r-field__label {
  font-size: var(--fs-13);
  font-weight: var(--fw-bold);
  color: var(--text-primary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.r-required { color: var(--color-error); margin-left: 2px; }
.r-field__hint  { font-size: var(--fs-12); color: var(--text-tertiary); }
.r-field__error { font-size: var(--fs-12); color: var(--color-error); font-weight: var(--fw-medium); }
.r-field.has-error .r-input { border-color: var(--color-error); }

.r-input {
  width: 100%;
  height: 44px;
  padding: 10px 15px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
  font-size: var(--fs-15);
  color: var(--text-primary);
  background: var(--surface-card);
  transition: border-color var(--t), box-shadow var(--t);
  appearance: auto;
}
/* Select boxes (like Cabin) get a custom arrow instead of the browser's
   native one, so it visually matches the Passengers dropdown's arrow
   instead of looking like a different control. appearance:none also
   stops the native arrow from crowding the right edge. */
select.r-input {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 34px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' stroke='%23667085' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 14px center;
}
/* Native date inputs on iOS/Android apply their own internal layout for
   the day/month/year segments and calendar icon, and can ignore a plain
   width:100% - the field then renders wider than its container and its
   right edge gets pushed off the screen. Forcing appearance:none here
   makes it respect our box model like a normal text input; the calendar
   icon itself is a separate element (::-webkit-calendar-picker-indicator)
   and still shows and works normally. */
input[type="date"].r-input {
  appearance: none;
  -webkit-appearance: none;
  min-width: 0;
}
.r-input::placeholder { color: var(--text-placeholder); }
.r-input:focus { border-color: var(--color-primary); outline: none; box-shadow: 0 0 0 3px rgba(4,146,194,0.15); }
.r-input:disabled { background: var(--neutral-50); color: var(--text-disabled); cursor: not-allowed; }

/* Grid layout for forms */
.r-form-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px,1fr)); gap: var(--space-4); }
.r-form-grid--2 { grid-template-columns: repeat(2, 1fr); }
.r-form-grid--3 { grid-template-columns: repeat(3, 1fr); }
.r-form-grid--4 { grid-template-columns: repeat(4, 1fr); }
.r-col-span-2 { grid-column: span 2; }
.r-col-full   { grid-column: 1 / -1; }

/* Checkbox / radio */
.r-check { display: flex; align-items: flex-start; gap: var(--space-3); cursor: pointer; font-size: var(--fs-14); color: var(--text-secondary); }
.r-check input { width: 16px; height: 16px; margin-top: 2px; flex-shrink: 0; accent-color: var(--color-primary); cursor: pointer; }

/* ════════════════════════════════════════
   CARDS  (r-card)
════════════════════════════════════════ */
.r-card {
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-6);
}
.r-card__header { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); margin-bottom: var(--space-4); padding-bottom: var(--space-4); border-bottom: 1px solid var(--border-subtle); }
.r-card__title  { font-size: var(--fs-16); font-weight: var(--fw-bold); color: var(--text-primary); margin: 0; }
.r-card--compact { padding: var(--space-4); }
.r-card--flush   { padding: 0; overflow: hidden; }
.r-divider { border: none; border-top: 1px solid var(--border-subtle); margin: var(--space-4) 0; }

/* ════════════════════════════════════════
   BADGES  (r-badge)
════════════════════════════════════════ */
.r-badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-12);
  font-weight: var(--fw-bold);
  background: var(--neutral-100);
  color: var(--text-secondary);
  white-space: nowrap;
}
.r-badge--brand   { background: var(--revie-blue-50);      color: var(--color-primary); }
.r-badge--success { background: var(--color-success-soft); color: var(--color-success); }
.r-badge--warning { background: var(--color-warning-soft); color: var(--color-warning); }
.r-badge--error   { background: var(--color-error-soft);   color: var(--color-error); }
.r-badge--info    { background: var(--color-info-soft);    color: var(--color-info); }
/* For "we genuinely don't have this detail" placeholders (e.g. baggage not
   reported by the airline) - visually quieter than the default badge so it
   doesn't look like a confirmed fact the way a solid-fill badge would. */
.r-badge--muted   { background: transparent; border: 1px dashed var(--border-default); color: var(--text-tertiary); font-weight: var(--fw-regular); }
/* For Non-Refundable: tried red (too alarming), amber (clashed with the
   brand blue used elsewhere on the same card), and a darker slate gray
   (read as too heavy/cold) before landing here - a muted plum. It's warm
   rather than a status color (not red/amber/green), so it doesn't read as
   an alarm, but it's still distinct enough from the blue Book button and
   green Refundable badge that it doesn't disappear or fight with them. */
.r-badge--plum    { background: #F1E4EC; color: #7A3F63; }

/* ════════════════════════════════════════
   ALERTS  (r-alert)
════════════════════════════════════════ */
.r-alert {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-4);
  border-radius: var(--radius-md);
  background: var(--color-info-soft);
  border: 1px solid var(--revie-blue-100);
  color: var(--color-primary);
  font-size: var(--fs-14);
  line-height: 1.5;
}
.r-alert__icon  { width: 20px; height: 20px; flex-shrink: 0; margin-top: 1px; }
.r-alert__title { display: block; font-weight: var(--fw-bold); margin-bottom: 2px; }
.r-alert--success { background: var(--color-success-soft); border-color: #C7E6D4; color: var(--color-success); }
.r-alert--warning { background: var(--color-warning-soft); border-color: #F5DFA0; color: var(--color-warning); }
.r-alert--error   { background: var(--color-error-soft);   border-color: #F2C6C6; color: var(--color-error); }
.r-alert__close { margin-left: auto; flex-shrink: 0; background: none; border: none; cursor: pointer; color: inherit; opacity: .6; font-size: 16px; line-height: 1; padding: 0; }

/* ════════════════════════════════════════
   PROGRESS STEPS  (r-steps)
════════════════════════════════════════ */
.r-steps { display: flex; align-items: center; gap: 0; list-style: none; padding: 0; margin: 0; }
.r-steps__item { display: flex; align-items: center; gap: var(--space-2); font-size: var(--fs-13); color: var(--text-tertiary); font-weight: var(--fw-medium); }
.r-steps__item.is-complete { color: var(--color-success); }
.r-steps__item.is-current  { color: var(--color-primary); font-weight: var(--fw-bold); }
.r-steps__dot {
  width: 24px; height: 24px;
  border-radius: 50%;
  border: 2px solid currentColor;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-12); font-weight: var(--fw-bold);
  flex-shrink: 0;
}
.r-steps__item.is-complete .r-steps__dot { background: var(--color-success); border-color: var(--color-success); color: #fff; }
.r-steps__item.is-current  .r-steps__dot { background: var(--color-primary); border-color: var(--color-primary); color: #fff; }
.r-steps__bar { flex: 1; height: 2px; background: var(--border-subtle); min-width: 24px; }
.r-steps__label { white-space: nowrap; }

/* ════════════════════════════════════════
   PRICE SUMMARY  (r-summary)
════════════════════════════════════════ */
.r-summary { }
.r-summary__head  { margin-bottom: var(--space-3); }
.r-summary__title { font-size: var(--fs-15); font-weight: var(--fw-bold); color: var(--text-primary); margin: 0; }
.r-summary__body  { display: flex; flex-direction: column; gap: 0; }
.r-summary__line  { display: flex; justify-content: space-between; align-items: baseline; padding: var(--space-2) 0; border-bottom: 1px solid var(--border-subtle); font-size: var(--fs-14); }
.r-summary__line:last-of-type { border-bottom: none; }
.r-summary__line-label { color: var(--text-secondary); }
.r-summary__line-label small { display: block; font-size: var(--fs-12); color: var(--text-tertiary); }
.r-summary__line-value { font-weight: var(--fw-medium); color: var(--text-primary); }
/* Carry-on allowance: a short sentence, not a price, so it stacks under its
   own label instead of sitting side by side the way a number does. */
#prCarryOnRow { flex-direction: column; align-items: flex-start; gap: var(--space-1); }
.r-summary__line-value--text { font-weight: var(--fw-regular); font-size: var(--fs-13); color: var(--text-secondary); text-align: left; }
.r-summary__total {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: var(--space-3) 0 0;
  margin-top: var(--space-2);
  border-top: 2px solid var(--border-default);
}
.r-summary__total-label { font-size: var(--fs-15); font-weight: var(--fw-bold); color: var(--text-primary); }
.r-summary__total-value { font-size: var(--fs-20); font-weight: var(--fw-bold); color: var(--text-primary); }
.r-summary__note  { font-size: var(--fs-12); color: var(--text-tertiary); margin-top: var(--space-2); }

/* ════════════════════════════════════════
   SEARCH FORM WIDGET
════════════════════════════════════════ */
.r-search-widget {
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  padding: var(--space-6);
}

/* Trip type toggle */
.r-trip-toggle { display: flex; margin-bottom: var(--space-5); border: 1px solid var(--border-default); border-radius: var(--radius-md); overflow: hidden; width: fit-content; }
.r-trip-toggle__label {
  display: flex; align-items: center; gap: var(--space-2);
  padding: 8px 20px;
  font-size: var(--fs-14); font-weight: var(--fw-medium);
  cursor: pointer; color: var(--text-secondary);
  background: var(--surface-card);
  transition: all var(--t);
  user-select: none;
}
.r-trip-toggle__label input[type="radio"] { display: none; }
/* Divider between adjacent pills. With exactly two options this never
   mattered - one is always the blue active pill and the other plain
   white, so the color change itself read as the boundary. With a third
   option (Multi-City) added, it's now possible for two INACTIVE white
   pills to sit side by side with nothing between them at all - which is
   exactly what looked like "no line separating Round Trip and Multi-
   City". A plain divider on every boundary fixes it regardless of which
   pill (if any) is active, and reads as a normal segmented control. */
.r-trip-toggle__label:not(:first-child) { border-left: 1px solid var(--border-default); }
/* Reverted to brand blue after feedback that the dark-neutral version
   (tried as part of de-emphasizing repeated blue elsewhere on the results
   page) looked broken/out of place here - this is a primary trip-type
   choice at the very top of the form, not a secondary filter, so it stays
   visually aligned with the Search/Book buttons. The dark-neutral
   treatment was kept for the sort tabs and filter chips further down,
   which is what the original "too much blue" feedback was actually about. */
.r-trip-toggle__label:has(input:checked),
.r-trip-toggle__label.is-active { background: var(--color-primary); color: #fff; }

/* Search row - Google Flights style: all fields on one horizontal bar.
   Reverted to nowrap (the previous flex-wrap:wrap change caused an early,
   ugly wrap even at normal desktop widths, because the combined minimum
   widths of every field left very little headroom). Instead, min-widths
   below are trimmed down so fields have room to shrink gracefully before
   ever needing to wrap, and the existing 900px/768px breakpoints further
   down already handle real tablet/mobile restructuring cleanly. */
.r-search-row {
  display: flex;
  gap: var(--space-3) var(--space-2);
  align-items: flex-end;
  flex-wrap: nowrap;
}
/* .r-search-field needs column direction (label stacked above its input).
   The two wrapper rows (dates, pax+cabin) need ROW direction instead -
   they hold two fields side by side on desktop. Grouping all three under
   one flex-direction:column rule (previous version) accidentally stacked
   Depart above Return and Passengers above Cabin on every desktop width,
   which is what broke the whole layout - the mobile media query further
   down was re-asserting row-for-these-wrappers, which is why it looked
   fine on mobile but broke on desktop. */
.r-search-field { display: flex; flex-direction: column; gap: var(--space-1); align-self: stretch; }
.r-search-dates-row,
.r-search-pax-cabin-row { display: flex; flex-direction: row; align-self: stretch; }
.r-search-field--airport { flex: 2 1 140px; min-width: 130px; }
.r-search-field--date    { flex: 1 1 120px; min-width: 110px; }
.r-search-field--pax     { flex: 1 1 140px; min-width: 130px; }
.r-search-field--cabin   { flex: 1 1 120px; min-width: 110px; }
.r-search-field--btn     { flex: 0 0 auto; min-width: 90px; }
.r-field-label-upper { font-size: var(--fs-12); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-tertiary); margin-bottom: var(--space-1); }

/* Multi-city: once the row's From/Swap/To/Dates fields are hidden
   (.r-route-field, toggled in app.js/index.php), Passengers+Cabin becomes
   the only flex-grow item left in .r-search-row - its base flex:1 1 240px
   would then stretch to eat the entire row width instead of staying the
   same compact size it is on One Way/Round Trip, which is what read as
   "two big boxes". Capping growth to 0 with a fixed basis keeps it the
   same size in every trip type; leftover space just sits empty next to
   Search, matching the reference screenshots. */
.r-search-pax-cabin-row--compact { flex: 0 1 420px !important; }

/* Multi-city leg rows (.r-search-leg-row below - deliberately its own
   class, NOT .r-leg-row). .r-leg-row already exists further down this
   file (align-items:center, its own mobile gap rule) - leftover from an
   earlier flight-card layout, not currently applied to any live markup,
   but still real CSS that any element carrying that class name inherits.
   Putting the search-form leg rows on it was the actual cause of the
   misaligned boxes: its align-items:center silently overrode this file's
   own .r-search-row align-items:flex-end above, so each leg row's
   label+input stack no longer sat on the same baseline as the main
   search row. */
.r-search-leg-row { /* intentionally inherits .r-search-row's own rules only */ }

/* The × is always in the DOM on every leg (including leg 1), never
   conditionally removed - it's just disabled once removing it would drop
   below the 2-flight minimum. Same visual treatment as the passenger
   stepper's disabled minus button elsewhere on this page, so a dimmed ×
   reads as "not available right now" rather than a dead, broken-looking
   control. */
.r-leg-remove-btn { flex-shrink: 0; }
.r-leg-remove-btn:disabled { opacity: .35; cursor: not-allowed; }
.r-leg-remove-btn:disabled:hover { background: var(--neutral-100); }

/* Brief highlight pulse - used to draw attention to the Search button after
   a "recent search" chip has refilled the form, without auto-running a search */
@keyframes r-pulse { 0%,100% { box-shadow: 0 0 0 0 rgba(4,146,194,0.45); } 50% { box-shadow: 0 0 0 8px rgba(4,146,194,0); } }
.r-btn--pulse { animation: r-pulse 0.8s ease-out 2; }

/* Swap button */
.r-swap-btn {
  width: 36px; height: 36px; border-radius: 50%;
  border: 1px solid var(--border-default);
  background: var(--surface-card);
  cursor: pointer; font-size: 16px;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-tertiary); flex-shrink: 0;
  align-self: flex-end; margin-bottom: 2px;
  transition: all var(--t);
}
.r-swap-btn:hover { border-color: var(--color-primary); color: var(--color-primary); transform: rotate(180deg); }

/* Airport typeahead */
.r-typeahead { position: relative; }
.r-typeahead__input { cursor: text; }
.r-dropdown {
  position: absolute; top: calc(100% + 4px); left: 0;
  min-width: 280px; max-height: 300px; overflow-y: auto;
  background: var(--surface-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  z-index: 500;
}
.r-dropdown__item {
  display: flex; justify-content: space-between; align-items: center;
  padding: var(--space-3) var(--space-4);
  cursor: pointer; gap: var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
  transition: background var(--t);
}
.r-dropdown__item:last-child { border-bottom: none; }
.r-dropdown__item:hover, .r-dropdown__item.focused { background: var(--revie-blue-50); }
.r-dropdown__name { font-size: var(--fs-14); color: var(--text-primary); font-weight: var(--fw-medium); }
.r-dropdown__country { font-size: var(--fs-12); color: var(--text-tertiary); margin-top: 1px; }
.r-dropdown__code { font-size: var(--fs-13); font-weight: var(--fw-bold); color: var(--color-primary); flex-shrink: 0; }
.r-dropdown__empty { padding: var(--space-4); font-size: var(--fs-14); color: var(--text-tertiary); text-align: center; }

/* Passenger dropdown (Google Flights style) */
.r-pax-trigger {
  display: flex; justify-content: space-between; align-items: center;
  padding: 10px 15px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  cursor: pointer; font-size: var(--fs-15);
  color: var(--text-primary); background: var(--surface-card);
  transition: border-color var(--t);
  user-select: none;
}
.r-pax-trigger:hover { border-color: var(--color-primary); }
.r-pax-trigger__chevron {
  width: 10px; height: 6px;
  font-size: 0; /* hide the ▾ text character, show the icon below instead */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' stroke='%23667085' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: center;
  flex-shrink: 0;
}
.r-pax-panel {
  position: absolute; top: calc(100% + 4px); left: 0;
  background: var(--surface-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-4);
  min-width: 260px; z-index: 400;
}
.r-pax-row { display: flex; justify-content: space-between; align-items: center; padding: var(--space-3) 0; border-bottom: 1px solid var(--border-subtle); }
.r-pax-row:last-of-type { border-bottom: none; }
.r-pax-row__info strong { display: block; font-size: var(--fs-14); color: var(--text-primary); }
.r-pax-row__info small  { font-size: var(--fs-12); color: var(--text-tertiary); }
.r-pax-stepper { display: flex; align-items: center; gap: var(--space-3); }
.r-pax-stepper__btn {
  width: 28px; height: 28px; border-radius: 50%;
  border: 1.5px solid var(--border-default);
  background: var(--surface-card); cursor: pointer;
  font-size: 16px; display: flex; align-items: center; justify-content: center;
  color: var(--text-secondary); transition: all var(--t);
}
.r-pax-stepper__btn:hover:not(:disabled) { border-color: var(--color-primary); color: var(--color-primary); }
.r-pax-stepper__btn:disabled { opacity: .4; cursor: not-allowed; }
.r-pax-stepper__val { font-size: var(--fs-16); font-weight: var(--fw-bold); min-width: 20px; text-align: center; }
.r-pax-panel__done { width: 100%; margin-top: var(--space-3); }

/* Advanced options */
.r-adv-toggle { margin-top: var(--space-3); }
.r-adv-link { background: none; border: none; color: var(--color-primary); font-size: var(--fs-13); cursor: pointer; padding: 0; font-family: var(--font-sans); }
.r-adv-link:hover { text-decoration: underline; }
.r-adv-panel { margin-top: var(--space-3); padding: var(--space-4); background: var(--neutral-50); border-radius: var(--radius-md); display: flex; gap: var(--space-4); flex-wrap: wrap; align-items: center; }

/* Compact search summary - replaces the full form once a search has run
   and produced results, so the page doesn't force a visitor to scroll
   past every field again just to see their flights. This is the biggest
   single fix for the results page feeling "heavy" on mobile, where the
   full form used to take up the entire first screen on its own. */
.r-search-widget--summary { padding: var(--space-4) var(--space-5); }
.r-search-summary { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-3); justify-content: space-between; }
.r-search-summary__route { display: flex; align-items: center; gap: var(--space-2); font-size: var(--fs-18); font-weight: var(--fw-bold); color: var(--text-primary); }
.r-search-summary__arrow { color: var(--text-tertiary); font-size: var(--fs-15); font-weight: var(--fw-regular); }
.r-search-summary__meta { display: flex; align-items: center; gap: var(--space-2); font-size: var(--fs-13); color: var(--text-tertiary); flex-wrap: wrap; }
.r-search-summary__dot { opacity: .6; }
.r-search-summary__edit {
  background: none; border: 1px solid var(--border-default); border-radius: var(--radius-pill);
  padding: 6px 14px; font-size: var(--fs-13); font-weight: var(--fw-medium);
  color: var(--text-secondary); cursor: pointer; font-family: var(--font-sans);
  transition: all var(--t); white-space: nowrap;
}
.r-search-summary__edit:hover { border-color: var(--neutral-400); background: var(--neutral-50); }

/* ════════════════════════════════════════
   LOADER OVERLAY
════════════════════════════════════════ */
.r-loader-overlay {
  position: fixed; inset: 0;
  background: rgba(14,19,24,0.55);
  backdrop-filter: blur(3px);
  z-index: 9999;
  display: flex; align-items: center; justify-content: center;
}
.r-loader-card {
  background: var(--surface-card);
  border-radius: var(--radius-xl);
  padding: var(--space-10) var(--space-12);
  text-align: center;
  /* Fixed width, not just a floor: the card used to size itself to
     whichever cycling message was showing, so it visibly grew and
     shrank as the text changed (for example "Searching flights..."
     vs "Almost there"). A fixed width stops that; max-width keeps it
     from overflowing a narrow phone screen. */
  width: 320px;
  max-width: calc(100vw - 48px);
  box-shadow: var(--shadow-lg);
}
/* Loader scene v4: airplane window. Landed on this after comparing many
   options side by side - a capsule-shaped window (rounded semicircle
   top, flatter bottom; the corner radius is set with explicit separate
   horizontal/vertical values below so it can't collapse into a plain
   circle) whose shade slides open ONCE when the loading screen first
   appears, then stays open with full, clearly cloud-shaped shapes
   streaming continuously past for as long as the search takes. It
   deliberately does NOT loop the open/close cycle - a shade that kept
   closing and reopening on a fixed timer would start to look repetitive
   on a slow search, since each close resets the viewer's attention.
   Opening once and leaving it open scales to any wait length without
   ever looking like it's "doing that again." */
.r-loader-plane {
  position: relative;
  width: 112px; height: 150px;
  margin: 0 auto var(--space-4);
  border-radius: 56px 56px 46px 46px / 82px 82px 46px 46px;
  border: 3px solid var(--color-primary);
  background: var(--revie-blue-50);
  overflow: hidden;
}
.r-loader-window-tab {
  position: absolute;
  top: 14px; left: 50%;
  width: 20px; height: 3px;
  margin-left: -10px;
  border-radius: 2px;
  background: var(--color-primary);
  z-index: 3;
}
.r-loader-cloud-track {
  position: absolute; top: 0; left: 0;
  width: 220px; height: 100%;
  display: flex; align-items: center;
  animation: r-stream 4.6s linear infinite;
}
@keyframes r-stream {
  from { transform: translateX(0); }
  to   { transform: translateX(-110px); }
}
/* Each cloud is three flat shapes (a pill base plus two circle "puffs")
   rather than a single SVG path, so it reliably reads as a full, fluffy
   cloud at this small size instead of a flat blob. */
.r-loader-cloud-shape {
  position: relative;
  width: 32px; height: 13px;
  background: var(--color-primary);
  border-radius: 20px;
  flex-shrink: 0;
}
.r-loader-cloud-shape::before,
.r-loader-cloud-shape::after {
  content: '';
  position: absolute;
  background: var(--color-primary);
  border-radius: 50%;
}
.r-loader-cloud-shape::before { width: 15px; height: 15px; top: -7px; left: 3px; }
.r-loader-cloud-shape::after  { width: 19px; height: 19px; top: -10px; right: 2px; }
.r-loader-cloud-shape--sm { width: 20px; height: 9px; margin-top: 22px; }
.r-loader-cloud-shape--sm::before { width: 10px; height: 10px; top: -5px; }
.r-loader-cloud-shape--sm::after  { width: 13px; height: 13px; top: -7px; }
.r-lc-1 { margin-left: 10px; }
.r-lc-2 { margin-left: 18px; }
.r-lc-3 { margin-left: 10px; }
.r-lc-4 { margin-left: 18px; }
.r-loader-window-shade {
  position: absolute; inset: 0;
  background: var(--neutral-50);
  border-radius: 56px 56px 46px 46px / 82px 82px 46px 46px;
  z-index: 2;
  animation: r-shade-open 1.7s ease-in-out 1 forwards;
}
.r-loader-shade-handle {
  position: absolute;
  left: 50%; bottom: 16px;
  width: 22px; height: 4px;
  margin-left: -11px;
  border-radius: 2px;
  background: var(--border-default);
}
@keyframes r-shade-open {
  0%   { transform: translateY(0%); }
  100% { transform: translateY(-100%); }
}
.r-loader-msg {
  font-size: var(--fs-16); font-weight: var(--fw-bold); color: var(--text-primary); margin-bottom: var(--space-2);
}
.r-loader-sub {
  font-size: var(--fs-13); color: var(--text-tertiary); margin-bottom: var(--space-5);
}
.r-loader-bar { height: 4px; background: var(--neutral-100); border-radius: var(--radius-pill); overflow: hidden; }
.r-loader-fill { height: 100%; background: var(--color-primary); border-radius: var(--radius-pill); animation: r-progress 2.4s cubic-bezier(.4,0,.2,1) infinite; }
@keyframes r-progress { 0%{width:0;transform:translateX(-100%)} 100%{width:100%;transform:translateX(350%)} }
.r-loader-cancel {
  display: block;
  margin: var(--space-4) auto 0;
  padding: 4px 8px;
  background: none;
  border: none;
  font-family: var(--font-sans);
  font-size: var(--fs-13);
  font-weight: var(--fw-medium);
  color: var(--text-tertiary);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.r-loader-cancel:hover { color: var(--text-secondary); }

/* ════════════════════════════════════════
   FLIGHT RESULT CARDS
════════════════════════════════════════ */
.r-result-bar {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.r-result-count { font-size: var(--fs-16); font-weight: var(--fw-bold); color: var(--text-primary); }

/* display:contents on desktop/web: invisible for layout purposes, so
   .r-mobile-controls (sort tabs + Filters trigger, its own real flex row -
   see below) renders as a direct item in the outer .r-result-bar
   space-between row alongside the flight count. Only becomes a real flex
   column at mobile widths (see the mobile override below), stacking
   things if needed rather than everything trying to cram into one line. */
.r-result-controls { display: contents; }

/* Sort + filter bar */
.r-sort-tabs  { display: flex; border: 1px solid var(--border-default); border-radius: var(--radius-md); overflow: hidden; }
.r-sort-tab   { padding: 7px 16px; font-size: var(--fs-13); font-weight: var(--fw-medium); border: none; background: var(--surface-card); color: var(--text-secondary); cursor: pointer; border-right: 1px solid var(--border-subtle); font-family: var(--font-sans); transition: all var(--t); }
.r-sort-tab:last-child { border-right: none; }
/* Neutral gray, not brand blue: blue is reserved for actual call-to-action
   buttons (Search, Book). Selection states (sort tabs, filter chips, trip
   type) instead use this gray so a glance at the page shows one clear
   color meaning "click this to act" and a different one meaning "this is
   what's currently selected" - previously almost every one of these used
   the same blue as the Book button, so everything competed for attention
   as if it were an equally urgent call to action. Uses --neutral-600 (a
   mid slate gray) rather than --neutral-900 (near-black) - the near-black
   version read as too harsh/heavy. */
.r-sort-tab.is-active { background: var(--neutral-600); color: #fff; }
.r-sort-tab:hover:not(.is-active) { background: var(--neutral-50); }

/* .r-mobile-controls wraps the sort tabs + Filters trigger - a real flex
   row at every width now, so the Filters button (and the single shared
   sheet it opens - stops, fare type, baggage) shows up on desktop too,
   not just mobile. Used to be display:contents on desktop with the
   trigger itself hidden there, back when desktop had its own separate
   stops-chips+refund-select row instead. */
.r-mobile-controls { display: flex; gap: var(--space-2); align-items: center; }
.r-filters-trigger {
  display: inline-flex;
  align-items: center; gap: 6px;
  padding: 6px 14px;
  border-radius: var(--radius-pill);
  border: 1.5px solid var(--border-default);
  background: var(--surface-card);
  font-size: var(--fs-13);
  color: var(--text-secondary);
  cursor: pointer;
  font-family: var(--font-sans);
  flex: 0 0 auto;
}
.r-filters-trigger:hover { border-color: var(--neutral-400); color: var(--text-primary); }
.r-filters-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: var(--radius-pill);
  background: var(--color-primary); color: #fff;
  font-size: 11px; font-weight: var(--fw-bold);
}

/* Filter sheet contents (mobile only - reuses .r-modal-overlay/.r-modal
   from the Fare Rules modal for the same slide-up treatment). Each option
   row is a plain button styled as a radio row (empty ring, filled dot
   when active via border-width) - consistent with the rest of the site
   using plain buttons instead of native form controls for this kind of
   single-choice list. */
.r-filter-group { margin-bottom: var(--space-5); }
.r-filter-group:last-of-type { margin-bottom: var(--space-2); }
.r-filter-group__label { font-size: var(--fs-12); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-tertiary); margin-bottom: var(--space-2); }
.r-filter-option {
  width: 100%; display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) 0;
  background: none; border: none; border-bottom: 1px solid var(--border-subtle);
  font-size: var(--fs-15); color: var(--text-primary);
  cursor: pointer; font-family: var(--font-sans); text-align: left;
}
.r-filter-option:last-child { border-bottom: none; }
.r-filter-option::before {
  content: ''; width: 18px; height: 18px; flex-shrink: 0;
  border-radius: 50%; border: 1.5px solid var(--border-default);
}
.r-filter-option.is-active::before { border-color: var(--color-primary); border-width: 5px; }
.r-filter-sheet__footer { display: flex; gap: var(--space-3); padding-top: var(--space-4); border-top: 1px solid var(--border-subtle); }
.r-filter-sheet__footer .r-btn--secondary { flex: 0 0 auto; }
.r-filter-sheet__footer .r-btn--block { flex: 1; }

/* Flight card */
.r-flight-card {
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  margin-bottom: var(--space-3);
  transition: box-shadow var(--t), transform var(--t);
  overflow: hidden;
}
.r-flight-card:hover { box-shadow: var(--shadow-md); transform: translateY(-1px); }
.r-flight-card--hidden { display: none; }
.r-flight-card--filtered { display: none; }

/* Card main row */
.r-flight-main { display: flex; align-items: stretch; }

/* Leg (flight route display) */
/* .r-flight-main (the row containing .r-leg and .r-flight-price) stretches
   both columns to equal height by default, which is what makes the card's
   right-edge divider line up cleanly top-to-bottom. The price column
   already centers its own content vertically within that stretched
   height (see .r-flight-price below) - .r-leg needs the same treatment,
   or its shorter content (especially a one-way search: a single box, vs.
   the price column's badges+price+three buttons) just sits pinned to the
   top with a slab of empty space left dangling underneath it, which reads
   as broken rather than intentional. */
.r-leg { flex: 1; padding: var(--space-4) var(--space-5); display: flex; flex-direction: column; justify-content: center; gap: var(--space-3); }
.r-leg + .r-leg { border-top: 1px dashed var(--border-subtle); }
.r-leg-row { display: flex; align-items: center; gap: var(--space-4); }
.r-leg-point { text-align: center; min-width: 64px; flex-shrink: 0; }
.r-leg-point__time { font-size: var(--fs-20); font-weight: var(--fw-bold); color: var(--text-primary); line-height: 1; }
.r-leg-point__code { font-size: var(--fs-13); font-weight: var(--fw-bold); color: var(--color-primary); }
.r-leg-point__city { font-size: var(--fs-12); color: var(--text-tertiary); margin-top: 2px; }
.r-leg-point__date { font-size: var(--fs-11, 0.6875rem); color: var(--text-tertiary); }
.r-leg-mid { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px; }
.r-airline-strip { display: flex; align-items: center; gap: var(--space-2); font-size: var(--fs-12); color: var(--text-tertiary); font-weight: var(--fw-medium); }
.r-airline-logo  { height: 14px; width: auto; max-width: 36px; object-fit: contain; }
.r-leg-dur { font-size: var(--fs-12); color: var(--text-tertiary); font-weight: var(--fw-medium); }
.r-leg-line { position: relative; width: 100%; height: 16px; display: flex; align-items: center; }
.r-leg-line::before { content: ''; position: absolute; left: 0; right: 0; height: 1px; background: var(--border-default); }
.r-leg-plane { position: absolute; left: 50%; transform: translateX(-50%); background: var(--surface-card); padding: 0 4px; color: var(--color-primary); font-size: 13px; }
.r-leg-stops { font-size: var(--fs-12); }
.r-leg-stops--direct { color: var(--color-success); font-weight: var(--fw-bold); }
.r-leg-stops--warn   { color: var(--color-warning); font-weight: var(--fw-bold); }

/* Boxed Depart/Return layout - replaces the old single continuous
   .r-leg-row/.r-leg-point/.r-leg-mid timeline (rules above kept in place,
   unused, in case any of this needs reverting). Splitting each leg into
   its own boxed panel lets the eye land on either the outbound or the
   return independently, instead of tracking through one long row with a
   plain-text "RETURN" divider in between. Each card only needs the
   airport CODE, not the city name, since every result in this list
   already shares the same origin/destination shown once in the search
   summary above - repeating the city on every single card was redundant. */
.r-leg-header { display: flex; align-items: center; gap: var(--space-2); font-size: var(--fs-14); color: var(--text-secondary); font-weight: var(--fw-medium); }
/* Logo + name (+ operated-by) as their own grouped unit - see the PHP
   comment above this markup for why. Same display/gap the header itself
   always had, so on desktop (where the cabin pill next to it is hidden)
   this renders identically to before this wrapper existed. */
.r-leg-header__brand { display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
.r-leg-header__name { color: var(--text-primary); }
.r-leg-header__op { font-size: 11px; color: var(--text-tertiary); font-weight: var(--fw-regular); }
/* Cabin pill: hidden on desktop (web keeps its current header exactly as
   it is today - this is a mobile-only addition), shown top-right of the
   header at mobile widths (see @media 900px below). */
.r-leg-header__cabin { display: none; }

.r-leg-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0; margin-top: var(--space-2); }
.r-leg-grid--oneway { grid-template-columns: 1fr; }
.r-leg-col { padding-right: var(--space-5); }
.r-leg-col--return { padding-right: 0; padding-left: var(--space-5); border-left: 1px dashed var(--border-subtle); }
.r-leg-col__label { font-size: var(--fs-13); font-weight: var(--fw-bold); color: var(--text-secondary); margin-bottom: var(--space-2); }

.r-leg-box { background: var(--neutral-50); border-radius: var(--radius-md); padding: var(--space-3) var(--space-4); display: flex; align-items: center; gap: var(--space-3); }
.r-leg-box__point { min-width: 0; }
.r-leg-box__time { font-size: var(--fs-20); font-weight: var(--fw-bold); color: var(--text-primary); line-height: 1.1; white-space: nowrap; }
.r-leg-box__dayoffset { font-size: var(--fs-11, 0.6875rem); font-weight: var(--fw-bold); color: var(--color-warning); vertical-align: top; margin-left: 2px; cursor: help; }
.r-leg-box__code { font-size: var(--fs-13); font-weight: var(--fw-bold); color: var(--color-primary); margin-top: 2px; }
.r-leg-box__mid { flex: 1; text-align: center; min-width: 0; }
.r-leg-box__dur { font-size: var(--fs-13); font-weight: var(--fw-bold); color: var(--text-primary); white-space: nowrap; }
.r-leg-box__line { position: relative; height: 1px; background: var(--border-default); margin: var(--space-1) var(--space-2); }
.r-leg-box__line .r-leg-plane { position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%); background: var(--neutral-50); padding: 0 4px; color: var(--text-tertiary); font-size: var(--fs-12); }
.r-leg-box__stops { font-size: var(--fs-12); white-space: nowrap; }

.r-leg-via { font-size: var(--fs-12); color: var(--text-tertiary); margin-top: var(--space-2); }

/* Return divider */
.r-return-label { font-size: var(--fs-11, 0.6875rem); font-weight: var(--fw-bold); color: var(--text-tertiary); text-transform: uppercase; letter-spacing: 0.06em; padding: var(--space-2) var(--space-5); background: var(--neutral-25); border-top: 1px dashed var(--border-subtle); border-bottom: 1px dashed var(--border-subtle); }

/* Price column - given its own light gray background (distinct from the
   white card) so it reads as a separate "what you pay" zone at a glance,
   matching the reference mockup. Widened from 190px to 230px so the two
   badges (baggage + refund status) fit on one row instead of wrapping to
   two - at 190px there wasn't enough room for both side by side. */
.r-flight-price {
  flex: 0 0 230px;
  /* min-width:0 overrides the flex item's automatic min-width:auto. Without
     this, a long badge combo (e.g. "See fare rules" + "Non-Refundable" is
     noticeably wider than "2PC" + "Non-Refundable") was allowed to force
     this column WIDER than its fixed 230px basis despite flex-shrink:0,
     because flex items refuse to shrink below their own content size by
     default. That's exactly why cards weren't all the same width - the
     leg column (flex:1) was losing a different amount of space to the
     price column depending on that card's specific badge text. With
     min-width:0 plus badges allowed to wrap (below), this column is now a
     fixed 230px on every single card regardless of its content, so the
     leg box next to it is always the same size too. */
  min-width: 0;
  /* Blue tint (was plain grey) to match the mobile price box, so the same
     "this is the price/booking zone" treatment reads consistently on both
     web and mobile. */
  background: var(--revie-blue-50);
  border-left: 1px solid var(--revie-blue-100);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  padding: var(--space-4);
  gap: var(--space-3); text-align: center;
}
/* Price + "per person" grouped tightly together with their own small gap,
   separate from the container's larger gap - previously both used the same
   gap value as the space before the badges/Book button, which read as too
   much air between the price and its own caption directly under it. */
.r-price-head   { display: flex; flex-direction: column; gap: 2px; order: 1; }
.r-price-amount { font-size: var(--fs-20); font-weight: var(--fw-bold); color: var(--text-primary); }
.r-price-sub    { font-size: var(--fs-12); color: var(--text-tertiary); }
/* Wrap (not nowrap): two short badges ("2PC" + "Non-Refundable") still sit
   on one line since they fit within 230px, but a longer combo ("See fare
   rules" + "Non-Refundable") now wraps to a second line instead of forcing
   the whole column - and therefore the whole card - wider than its
   neighbors. order:2 keeps badges between price and Book on desktop, where
   .r-price-book-box below is display:contents (see its own comment). */
.r-price-badges { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--space-1); order: 2; }
/* display:contents on desktop: this wrapper doesn't render at all - its
   children (price-head, Book button) become direct flex items of
   .r-flight-price, sitting alongside .r-price-badges with the order
   values above/below controlling the final sequence (price, then badges,
   then Book) exactly as it's always been on web. It only becomes a real,
   visible, tinted/bordered box at mobile widths (see @media 900px below),
   where it groups just price+Book together side by side - badges stay
   outside it as their own row, matching the approved mockup. */
.r-price-book-box { display: contents; }
.r-flight-price .book-now-btn { order: 3; }
/* Deliberately just quiet caption text next to "per person", not a colored
   badge next to Refundable/Non-Refundable - a USD pill sitting in that
   same row read like a status the customer needed to worry about, when
   really it's just a note about which currency the airline itself quoted
   the fare in (the price above is always shown converted to Naira). Still
   its own class/selector so it stays easy to find or track separately. */
.r-price-usd-note { margin-left: 4px; font-weight: var(--fw-regular); }

/* Details/Fare Rules - demoted from buttons to plain text links, sitting
   side by side under Book. The goal is one obvious primary action (the
   solid blue Book button); Details and Fare Rules are secondary lookups,
   not competing calls to action, so they read as quiet text rather than
   a second and third button stacked under the first. */
.r-price-links { display: flex; align-items: center; justify-content: center; gap: var(--space-4); order: 4; }
.r-link-btn {
  background: none; border: none; padding: 0; margin: 0;
  font-family: var(--font-sans); font-size: var(--fs-13); font-weight: var(--fw-medium);
  color: var(--text-secondary); cursor: pointer;
  display: inline-flex; align-items: center; gap: 3px;
}
.r-link-btn:hover { color: var(--text-primary); }
/* A real inline SVG chevron, not a Unicode glyph - the previous "⌄"
   character rendered inconsistently across devices (baseline position,
   weight, sometimes a mismatched size), which is what read as "wonky" on
   both web and mobile. An SVG renders identically everywhere, the same
   approach already used for the select-box and passenger-dropdown arrows
   elsewhere on this page. currentColor keeps it in sync with the button's
   own text color automatically. */
.r-link-caret { display: inline-block; flex-shrink: 0; color: currentColor; transition: transform var(--t); }
.r-link-btn.is-expanded .r-link-caret { transform: rotate(180deg); }
.r-link-btn--brand { color: var(--color-primary); text-decoration: underline; }
.r-link-btn--brand:hover { color: var(--color-primary-hover); }

/* Expanded details - compact TravelBank/Wakanow style */
.r-flight-details {
  border-top: 1px solid var(--border-subtle);
  background: var(--neutral-25);
  padding: var(--space-4) var(--space-5);
}
/* Outbound and Return shown as two side-by-side columns (same idea as the
   Depart/Return boxes above), instead of the Outbound list stacked fully
   above the Return list - that previous layout meant a round trip's
   segment breakdown ran twice as long as it needed to, requiring a lot of
   scrolling to compare both legs. Side by side, both legs sit at the same
   height and can be scanned together. Also reused (unchanged) for a
   one-way itinerary's own segments - segment 1 and segment 2 of a 1-stop
   one-way sit side by side in these same two columns instead of stacking,
   and a third segment (2-stop one-way) simply wraps to its own row via
   plain CSS grid auto-placement. */
.r-detail-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0; }
.r-detail-col { padding-right: var(--space-5); }
.r-detail-col--return { padding-right: 0; padding-left: var(--space-5); border-left: 1px dashed var(--border-subtle); }
.r-seg-list { display: flex; flex-direction: column; gap: var(--space-2); }
.r-seg {
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
}
.r-seg-row {
  display: grid;
  grid-template-columns: 64px 1fr 64px;
  align-items: center; gap: var(--space-3);
}
.r-seg-ep { text-align: center; }
.r-seg-ep__time { font-size: var(--fs-16); font-weight: var(--fw-bold); color: var(--text-primary); }
.r-seg-ep__code { font-size: var(--fs-12); font-weight: var(--fw-bold); color: var(--color-primary); }
.r-seg-ep__city { font-size: var(--fs-11, 0.6875rem); color: var(--text-tertiary); }
.r-seg-ep__date { font-size: var(--fs-11, 0.6875rem); color: var(--text-tertiary); }
.r-seg-mid { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.r-seg-mid__line { width: 100%; height: 1px; background: var(--border-default); position: relative; }
.r-seg-mid__dur  { font-size: var(--fs-12); color: var(--text-tertiary); }
.r-seg-meta { margin-top: var(--space-2); padding-top: var(--space-2); border-top: 1px dashed var(--border-subtle); display: flex; flex-wrap: wrap; gap: var(--space-3); font-size: var(--fs-12); color: var(--text-tertiary); }
.r-seg-meta span { display: flex; align-items: center; gap: 4px; }
.r-layover { text-align: center; padding: var(--space-2) 0; font-size: var(--fs-12); color: var(--text-tertiary); display: flex; align-items: center; justify-content: center; gap: var(--space-2); }
.r-layover--short { color: var(--color-warning); }
.r-layover__icon  { font-size: 14px; }
.r-seg-group-label { font-size: var(--fs-11, 0.6875rem); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-tertiary); margin-bottom: var(--space-2); }

/* ════════════════════════════════════════
   FARE RULES MODAL
════════════════════════════════════════ */
.r-modal-overlay { position: fixed; inset: 0; z-index: 9000; display: flex; align-items: center; justify-content: center; padding: var(--space-4); }
.r-modal-backdrop { position: fixed; inset: 0; background: rgba(14,19,24,0.6); backdrop-filter: blur(4px); z-index: 8999; }
.r-modal {
  background: var(--surface-card); border-radius: var(--radius-xl);
  width: 100%; max-width: 640px; max-height: 85vh;
  display: flex; flex-direction: column;
  box-shadow: var(--shadow-lg); position: relative; z-index: 9001;
  animation: r-modal-in 0.2s ease;
}
@keyframes r-modal-in { from { opacity:0; transform:scale(.96) translateY(12px); } to { opacity:1; transform:none; } }
/* position:sticky (not just flex-shrink:0) so the close button stays
   pinned to the visible top of the modal even in edge cases where the
   modal's own height gets miscalculated - belt-and-braces alongside the
   mobile max-height fix below, which is the actual root-cause fix. */
.r-modal__header { display: flex; justify-content: space-between; align-items: center; padding: var(--space-4) var(--space-6); border-bottom: 1px solid var(--border-subtle); flex-shrink: 0; position: sticky; top: 0; background: var(--surface-card); z-index: 2; }
.r-modal__title  { font-size: var(--fs-18); font-weight: var(--fw-bold); margin: 0; color: var(--text-primary); }
.r-modal__close  { background: var(--neutral-100); border: none; width: 30px; height: 30px; border-radius: 50%; cursor: pointer; font-size: 14px; display: flex; align-items: center; justify-content: center; transition: background var(--t); }
.r-modal__close:hover { background: var(--neutral-200); }
.r-modal__body   { overflow-y: auto; padding: var(--space-5) var(--space-6); flex: 1; }

/* Fare rules - redesigned for readability. The categories a customer
   actually needs to decide with (Cancellations, Refunds, Changes,
   Baggage, No-Show) are shown fully expanded as plain bullet lists, not
   truncated summaries or collapsed accordions someone has to click open
   one at a time. Anything else the airline sends back is real but rarely
   what someone's looking for, so it's grouped under a small "Other
   conditions" accordion below instead of competing for attention. */
.r-fr-card { border: 1px solid var(--border-subtle); border-radius: var(--radius-md); padding: var(--space-4); margin-bottom: var(--space-3); }
.r-fr-route { font-weight: var(--fw-bold); margin-bottom: var(--space-2); font-size: var(--fs-15); }
.r-fr-iata { color: var(--color-primary); }
.r-fr-airline { font-size: var(--fs-13); color: var(--text-tertiary); margin-bottom: var(--space-3); }

.r-fr-farebasis { display: flex; align-items: center; gap: var(--space-2); background: var(--neutral-50); border-radius: var(--radius-sm); padding: var(--space-2) var(--space-3); margin-bottom: var(--space-3); font-size: var(--fs-13); }
.r-fr-farebasis__label { color: var(--text-tertiary); }
.r-fr-farebasis__code { font-weight: var(--fw-bold); color: var(--text-primary); font-family: monospace; letter-spacing: 0.02em; }

.r-fr-section { padding: var(--space-3) 0; border-bottom: 1px solid var(--border-subtle); }
.r-fr-section:last-of-type { border-bottom: none; }
.r-fr-section__title { font-size: var(--fs-13); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-primary); margin-bottom: var(--space-2); }
.r-fr-section p, .r-fr-nodata { font-size: var(--fs-14); color: var(--text-secondary); line-height: 1.6; }
.r-fr-nodata { color: var(--text-tertiary); font-style: italic; }
.r-fr-bullets { padding-left: var(--space-5); font-size: var(--fs-14); color: var(--text-secondary); line-height: 1.6; }
.r-fr-bullets li { margin-bottom: var(--space-2); }
.r-fr-bullets li:last-child { margin-bottom: 0; }
.r-fr-fulllink { font-size: var(--fs-13); }

.r-fr-more { margin-top: var(--space-2); padding-top: var(--space-3); border-top: 1px dashed var(--border-subtle); }
.r-fr-more__label { font-size: var(--fs-12); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-tertiary); margin-bottom: var(--space-1); }
.r-fr-cat { border-bottom: 1px solid var(--border-subtle); }
.r-fr-cat:last-child { border-bottom: none; }
.r-fr-cat-btn { width: 100%; display: flex; justify-content: space-between; align-items: center; padding: var(--space-3) 0; background: none; border: none; cursor: pointer; font-size: var(--fs-14); font-weight: var(--fw-medium); color: var(--text-primary); font-family: var(--font-sans); text-align: left; }
.r-fr-cat-btn:hover { color: var(--color-primary); }
.r-fr-chevron { font-size: 14px; color: var(--text-tertiary); transition: transform var(--t); }
.r-fr-cat-btn[aria-expanded="true"] .r-fr-chevron { transform: rotate(90deg); }
.r-fr-cat-body { font-size: var(--fs-13); color: var(--text-tertiary); padding-bottom: var(--space-3); line-height: 1.6; }
.r-fr-empty { text-align: center; color: var(--text-tertiary); font-size: var(--fs-14); padding: var(--space-6); }

/* ════════════════════════════════════════
   RECENT SEARCHES
════════════════════════════════════════ */
.r-recent { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; margin-top: var(--space-3); }
/* #recentList itself had no layout rules at all - the chip buttons inside
   it were relying on default inline-block wrapping with zero gap between
   them (the JS builds them via .join('') with no separating whitespace),
   so they'd sit flush against each other if two ever did fit on one row.
   Explicit flex-wrap + gap makes wrapping (and the spacing between
   wrapped chips) an actual rule instead of an accident of long text. */
#recentList { display: flex; flex-wrap: wrap; gap: var(--space-2); }

/* Alternate fare options (grouped same-flight fares) */
.r-alt-fares { margin-top: var(--space-2); border-top: 1px dashed var(--border-subtle); padding-top: var(--space-2); display: flex; flex-direction: column; gap: var(--space-2); }
.r-alt-fare-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); flex-wrap: wrap; padding: var(--space-2); border: 1px solid var(--border-subtle); border-radius: var(--radius-md); }
.r-alt-fare-badges { display: flex; gap: var(--space-1); flex-wrap: wrap; }
.r-alt-fare-price { font-weight: var(--fw-bold); font-size: var(--fs-14); color: var(--text-primary); }
.r-recent__label { font-size: var(--fs-12); color: var(--text-tertiary); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: 0.05em; white-space: nowrap; }
.r-recent-chip { padding: 4px 14px; border-radius: var(--radius-pill); border: 1px solid var(--border-default); background: var(--surface-card); font-size: var(--fs-13); color: var(--text-secondary); cursor: pointer; transition: all var(--t); font-family: var(--font-sans); }
.r-recent-chip:hover { border-color: var(--color-primary); color: var(--color-primary); }

/* ════════════════════════════════════════
   LAYOUT UTILITIES
════════════════════════════════════════ */
.r-container { max-width: 1200px; margin: 0 auto; padding: 0 var(--space-6); }

/* Search shell width regression fix (2026-09-23) — Launch Closure Pass,
   Section 10A had narrowed the FULL (pre-search) search widget to a
   centered 900px on desktop, independent of the shared 1200px
   .r-container. In practice this compressed From/To/Depart/Passengers/
   Cabin/Search onto a visibly cramped row with large unused space on
   both sides — a regression from the wider desktop shell the search
   form used to have (and still shares with the results page below it).
   Reverted: the search widget goes back to inheriting .r-container's
   1200px like everything else on the page, restoring the old
   proportions/responsive behaviour. Mobile/tablet breakpoints further
   down were never part of this rule and are unaffected. */
.r-page-body  { padding: var(--space-6) 0 var(--space-16); }
.r-grid  { display: grid; gap: var(--space-4); }
.r-grid--2 { grid-template-columns: repeat(2, 1fr); }
.r-grid--3 { grid-template-columns: repeat(3, 1fr); }
.r-stack { display: flex; flex-direction: column; gap: var(--space-4); }

/* ════════════════════════════════════════
   RESPONSIVE - Mobile-first
════════════════════════════════════════ */

/* Tablet: 900px and below */
@media (max-width: 900px) {
  /* .r-mobile-controls and .r-filters-trigger are already a real flex row
     visible at every width now (see base rules above) - nothing left to
     override here except resizing the sort tabs so they still fit
     comfortably next to the Filters pill at narrower widths. */
  .r-sort-tabs { flex: 1 1 auto; min-width: 0; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .r-sort-tab { flex: 1 1 auto; padding: 6px 8px; font-size: var(--fs-12); white-space: nowrap; }

  .r-flight-main { flex-direction: column; }
  /* Mobile-specific card redesign (reviewed as mockups across several
     rounds before touching real code). Desktop/web is untouched - all of
     this lives inside this media query. Changes from the old mobile
     layout: the leg header now shows the cabin class pill top-right; the
     price+badges+Book zone (.r-price-book-box) becomes a real contained,
     tinted, bordered box instead of just a border-top divider, with price
     and Book sitting side by side inside it and badges wrapping to their
     own row above them; Details gets a small circular chevron so it reads
     as a toggle rather than plain static text next to the Fare Rules
     link. */
  .r-flight-price {
    flex: none; border-left: none; border-top: none;
    /* Explicitly plain white here (not the blue from the desktop base
       rule) - on mobile the blue tint belongs ONLY to .r-price-book-box
       below. Without this override, the whole price area and the inner
       box were the same blue-on-blue with barely any contrast, and worse,
       the surrounding white-card padding above/around the box was
       actually still the OLD grey from the previous base rule, which
       read as a second, disconnected floating card sitting under the
       flight-info card instead of one continuous card. */
    background: var(--surface-card);
    flex-direction: column;
    align-items: center; justify-content: center;
    padding: var(--space-4); gap: var(--space-3);
  }

  .r-leg-header { justify-content: space-between; }
  .r-leg-header__cabin {
    display: inline-flex;
    font-size: 11px; color: var(--text-secondary);
    border: 1px solid var(--border-default);
    padding: 2px 8px; border-radius: var(--radius-pill);
    flex-shrink: 0;
  }
  /* Approved mockup keeps everything except the price box on plain white -
     the grey time-box background is existing desktop styling that was
     never part of this redesign's scope, so it's turned off here rather
     than changed at the base rule (which stays exactly as-is for web). */
  .r-leg-box { background: transparent; padding-left: 0; padding-right: 0; }
  .r-leg-box__line .r-leg-plane { background: var(--surface-card); }

  /* Badges: their own plain row, sitting above the box, left-aligned -
     matches the approved mockup exactly (badges are NOT inside the blue
     box). order:1 puts them first among .r-flight-price's direct items. */
  .r-price-badges { order: 1; justify-content: flex-start; width: 100%; }
  /* Real box again at mobile widths (desktop's .r-price-book-box is
     display:contents - see base rule). order:2 sits it right after
     badges. It now only ever contains two children - price-head and the
     Book button - so they just take their natural DOM order (price
     first) with no further order values needed inside it. */
  .r-price-book-box {
    display: flex; order: 2; width: 100%;
    flex-direction: row; flex-wrap: wrap;
    align-items: center; justify-content: space-between;
    gap: var(--space-2) var(--space-3);
    background: var(--revie-blue-50);
    border: 1px solid var(--revie-blue-100);
    border-radius: var(--radius-lg);
    padding: var(--space-4);
  }
  .r-price-head   { flex: 1 1 auto; text-align: left; align-items: flex-start; }
  /* Price is the single biggest, boldest thing in the box on purpose -
     it and the Book button are the only two things anyone needs to act
     on here, so the price gets real visual weight instead of matching
     the same size as the flight times above it. */
  .r-price-amount { font-size: var(--fs-24); }
  .r-flight-price .book-now-btn { width: auto; flex: 0 0 auto; }

  /* Tighter gap between the flight-info card and the price box - .r-leg
     already ends with its own bottom padding, so an equal top padding
     here on top of that was stacking into a much bigger gap than the
     mockup ever showed. Left/bottom padding stay the same. */
  .r-flight-price { padding-top: 0; }
}

/* Mobile: 768px and below */
@media (max-width: 768px) {
  /* Container no horizontal overflow */
  .r-container { overflow-x: hidden; }

  /* Any text input/select under 16px triggers iOS Safari's (and some
     Android browsers') auto-zoom-on-focus. That zoom is also what was
     causing the airport dropdown to appear to "take over the whole
     screen and extend past it", and the cases where the dropdown didn't
     seem to appear at all until navigating back - the browser's zoomed
     visual viewport no longer lined up with the fixed-position bottom
     sheet below, so it was rendering off the visible area rather than
     actually missing. Bumping every field to 16px removes the zoom
     trigger entirely, which fixes both symptoms at the source. */
  .r-input,
  .r-pax-trigger { font-size: var(--fs-16); }

  /* Search widget: everything stacks, full width, no overflow */
  .r-search-widget { padding: var(--space-4); }

  /* Compact summary bar: stack instead of trying to fit the route, dates
     and Modify-search button on one line, which is what made the search
     card feel oversized on narrow screens in the first place. */
  .r-search-widget--summary { padding: var(--space-4); }
  .r-search-summary { flex-direction: column; align-items: flex-start; gap: var(--space-2); }
  .r-search-summary__edit { align-self: stretch; text-align: center; }
  .r-search-row {
    flex-direction: column;
    gap: var(--space-3);
    width: 100%;
    overflow: hidden;
  }
  /* Multi-city only: box each leg row once its fields stack into a single
     column, so it reads as a standalone unit instead of blurring into the
     leg above/below it - stacked "From/To/Date" blocks with nothing
     marking where one leg ends and the next begins was the actual
     complaint. Scoped to .r-search-leg-row specifically, so the shared
     One Way/Round Trip row above (and the Passengers/Cabin/Search row
     below the legs) are completely untouched - desktop stays exactly the
     plain row it's always been; this is mobile-only, and doesn't need a
     separate wrapper element since "Flight N · From" already labels it. */
  .r-search-leg-row {
    position: relative;
    background: var(--neutral-25);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-lg);
    padding: var(--space-4);
  }
  /* × moves to the top-right corner, opposite the "Flight N" label, once
     the row is a stacked mobile column - it's last in the DOM (comes
     after Date, same as desktop) but position:absolute pulls it out of
     the stack entirely, so it doesn't leave a gap at the bottom and
     doesn't need reordering. margin-bottom/align-self/flex are set
     inline for the desktop row (see index.php) - !important overrides
     them here the same way every other field override in this block
     already does. */
  .r-search-leg-row .r-leg-remove-btn {
    position: absolute !important;
    top: var(--space-3);
    right: var(--space-3);
    margin-bottom: 0 !important;
    align-self: auto !important;
  }
  /* ALL search field wrappers go full width */
  .r-search-field,
  .r-search-field--airport,
  .r-search-field--date,
  .r-search-field--pax,
  .r-search-field--cabin,
  .r-search-field--btn,
  .r-search-dates-row,
  .r-search-pax-cabin-row {
    flex: none !important;
    width: 100% !important;
    min-width: 0 !important;
    max-width: 100% !important;
    box-sizing: border-box;
  }
  /* Within dates row: side by side, each half width */
  .r-search-dates-row {
    display: flex !important;
    gap: var(--space-2);
  }
  .r-search-dates-row .r-search-field--date {
    flex: 1 !important;
    width: auto !important;
  }
  /* Within pax+cabin row: side by side */
  .r-search-pax-cabin-row {
    display: flex !important;
    gap: var(--space-2);
  }
  .r-search-pax-cabin-row .r-search-field--pax,
  .r-search-pax-cabin-row .r-search-field--cabin {
    flex: 1 !important;
    width: auto !important;
  }
  /* Date inputs must not overflow */
  .r-input[type="date"] { width: 100%; min-width: 0; }
  /* Search button full width */
  .r-search-field--btn { align-self: stretch !important; }
  .r-search-field--btn .r-btn { width: 100%; height: 48px; font-size: var(--fs-16); }

  /* Swap button rotated for vertical layout. On mobile the button sits
     between two stacked fields that each look like [LABEL above INPUT],
     so a margin split evenly around the button (the previous -6px/-6px)
     visually centers it against the LABEL TEXT block below it rather
     than the actual input box - since that label (its text + the small
     gap under it) adds extra height the eye doesn't count as "the field",
     the button reads as sitting closer to the From box than the To box.
     Measured against the real rendered label block (18px text + 4px
     gap) and the button's own 36px height against the row's 12px gap:
     shifting the button's resting point down by ~11px (margin-top from
     -6px to +5px, margin-bottom from -6px to -17px - same total margin,
     so the page layout height is unchanged) puts it equidistant from the
     From input's bottom edge and the To input's top edge instead. */
  .r-swap-btn {
    align-self: center;
    transform: rotate(90deg);
    margin: 5px 0 -17px;
    z-index: 5;
  }
  .r-swap-btn:hover { transform: rotate(270deg); }

  /* Pax panel: bottom sheet on mobile, inset from all four edges instead
     of flush left-to-right. Same principle as the dropdown fix above -
     no panel or dropdown on this page should touch the raw screen edges
     with zero margin. */
  .r-pax-panel {
    position: fixed; bottom: 12px; left: 12px; right: 12px; top: auto;
    border-radius: var(--radius-xl);
    max-height: 70vh; overflow-y: auto;
    padding: var(--space-6);
    z-index: 600;
    box-shadow: 0 4px 24px rgba(14,19,24,0.18);
  }
  /* Dropdown: anchored directly under the field being typed into, same as
     desktop - not a full-screen bottom sheet. That previous fixed-to-the-
     physical-bottom-of-the-screen approach had two real problems: (1) it
     stretched flush to the left and right screen edges with no side
     margin at all, and (2) once the on-screen keyboard opens, it covers
     the bottom portion of the actual screen - so a "bottom sheet" pinned
     there was rendering right underneath the keyboard, completely out of
     view, until you closed the keyboard. Keeping it anchored to the input
     (the base .r-dropdown rule above already does this: position:absolute,
     top:calc(100% + 4px)) means it always appears just below whatever
     you're typing into, which is guaranteed to be above the keyboard, and
     it now spans left:0 to right:0 of its field's own padded container
     instead of the raw screen edge, so it keeps visible space on both
     sides matching the input above it. */
  .r-dropdown {
    right: 0;
    max-height: 45vh;
    overflow-y: auto;
    z-index: 700;
  }

  /* Result bar: stack on mobile */
  .r-result-bar { flex-direction: column; align-items: flex-start; gap: var(--space-3); }
  /* This is the ONE place .r-result-controls becomes a real flex column -
     desktop leaves it as display:contents (see base rule). On mobile the
     stops chips could wrap onto their own line, left-aligned, with dead
     space to their right; grouping sort tabs + chips into their own
     full-width stacked column fixes that specific case without touching
     the desktop layout at all. */
  .r-result-controls { display: flex; flex-direction: column; width: 100%; align-items: stretch; gap: var(--space-2); }
  /* .r-sort-tabs sizing is handled entirely by the ≤900px block above now
     (shared row with the Filters pill) - the old width:100%/flex:1 rules
     that used to live here were written for when sort tabs had a full
     row to themselves, and being later in the cascade would otherwise win
     over the ≤900px rules at these narrower widths and stretch the tabs
     back out, crowding the Filters pill off the row again. */

  /* Flight cards: more visible separation between individual options.
     Previously each card only had a thin 1px border and a barely-visible
     shadow, with just 12px between cards - on a narrow screen where you
     can only see one and a sliver of the next at a time, that read as one
     continuous block rather than a stack of distinct, comparable options
     (the TravelTank/Wakanow references both give each card real shadow and
     a visible gap from its neighbors). Bumping the gap and shadow, and
     switching the border to the slightly darker --border-default, makes
     each option read as its own separate, tappable card. */
  .r-flight-card { margin-bottom: var(--space-5); border-color: var(--border-default); box-shadow: var(--shadow-md); }

  /* Flight card legs on mobile - more internal padding/gap than the tight
     12px used at 900px, so the depart/return boxes have real breathing
     room instead of sitting right against the card edge. */
  .r-leg { padding: var(--space-4); gap: var(--space-4); }
  .r-leg-row { gap: var(--space-2); }
  .r-leg-point { min-width: 54px; }
  .r-leg-point__time { font-size: var(--fs-18); }

  /* Depart/Return boxes: stack instead of side by side - two narrow boxes
     squeezed onto one mobile row would force times/codes to wrap or
     truncate, so below this width each leg gets the full row width and a
     dashed divider on top instead of a vertical one on the left. */
  .r-leg-grid { grid-template-columns: 1fr; gap: var(--space-4); }
  .r-leg-col { padding-right: 0; }
  .r-leg-col--return { padding-left: 0; border-left: none; border-top: 1px dashed var(--border-subtle); padding-top: var(--space-4); }
  .r-leg-box__time { font-size: var(--fs-18); }

  /* Flight price row on mobile: horizontal */
  .r-flight-price { gap: var(--space-2); }

  /* Details/Return segment breakdown: same stacking treatment as the
     Depart/Return boxes above - side by side only has room on wider
     screens, so below this width each leg's segment list gets the full
     row width with a dashed divider on top instead of a vertical one on
     the left. */
  .r-detail-grid { grid-template-columns: 1fr; gap: var(--space-4); }
  .r-detail-col { padding-right: 0; }
  .r-detail-col--return { padding-left: 0; border-left: none; border-top: 1px dashed var(--border-subtle); padding-top: var(--space-4); }

  /* Modal: full screen on mobile */
  /* Root cause of "close button hidden off the top of the screen": this
     used to be max-height:100vh with zero overlay padding and the modal
     flush to every edge. On mobile browsers, 100vh is measured including
     the space the address bar/URL bar can hide behind, which is taller
     than what's actually visible on screen - so a modal set to exactly
     100vh (bottom-anchored) had its top edge, including the header and
     close button, pushed above the real visible viewport. This should
     never have felt like a separate full-screen page in the first place -
     it's a quick lookup, not new navigation, so it needs to keep reading
     as an inner panel over the page: real margin on all sides, rounded
     top corners, and a max-height that uses the dvh unit (the *actual*
     visible viewport height on modern mobile browsers, with a plain vh
     fallback for older ones that don't support dvh) so the close button
     is always on-screen no matter how tall the fare-rules content is. */
  .r-modal-overlay { padding: var(--space-3); align-items: flex-end; }
  .r-modal {
    max-width: 100% !important;
    width: 100%;
    max-height: 82vh;
    max-height: 82dvh;
    border-radius: var(--radius-xl) var(--radius-xl) 0 0;
  }
  .r-modal__header { border-radius: var(--radius-xl) var(--radius-xl) 0 0; }

  /* Segment detail more compact */
  .r-seg-row { grid-template-columns: 52px 1fr 52px; gap: var(--space-2); }
  .r-seg-ep__time { font-size: var(--fs-15); }
  .r-flight-details { padding: var(--space-3); }
}

/* Small mobile: 480px and below */
@media (max-width: 480px) {
  .r-container { padding: 0 var(--space-3); }
  .r-search-widget { padding: var(--space-3); border-radius: var(--radius-lg); }
  .r-card { padding: var(--space-4); }
  .r-price-amount { font-size: var(--fs-16); }
  /* The bare rule above pre-dates the flight-card redesign and quietly
     undid it: at 900px the price was deliberately bumped to fs-24 (the
     one thing on the card people need to see clearly), but every real
     phone is 480px or narrower, so THIS rule - being later in the
     cascade at equal specificity - was the one actually winning, shrinking
     the price back to fs-16 for effectively every mobile visitor. Scoped
     override wins on specificity instead of source order, so the search
     results price stays large at every mobile width; whatever else
     .r-price-amount alone is used for elsewhere keeps its original fs-16
     at this breakpoint, untouched. */
  .r-flight-price .r-price-amount { font-size: var(--fs-24); }
  .r-trip-toggle__label { padding: 8px 14px; font-size: var(--fs-13); }
  /* Native date pickers refuse to shrink below their own minimum width on
     many phones, which is why the Depart and Return fields could visually
     collide side-by-side on smaller screens. Below 480px we stack them
     instead, so there's never a fight for space. */
  .r-search-dates-row { flex-direction: column !important; }
  .r-search-dates-row .r-search-field--date { width: 100% !important; }
}