/*
 * nxt design system — loaded together with bootstrap5.min.css only (not the
 * legacy bootstrap.css/style.css, which use Bootstrap 2 class names that
 * collide with Bootstrap 5's for the same components). Brand colors below
 * are pulled from the existing style.css palette (h1/h2 blue #119bd4,
 * .page-button orange gradient #ef9023/#ee7d00) so the redesign stays on
 * brand rather than inventing a new palette.
 *
 * Compatibility shims: `.row-fluid`/`.span1`-`.span12`/`.offset*` and
 * `.page-button` have no Bootstrap 5 equivalent and are still used across
 * ~200 not-yet-ported templates that fall through to this theme via the
 * blank->nxt inheritance chain. Shimming them here means those pages keep a
 * reasonable layout/button look immediately, while newly authored/ported
 * markup uses true Bootstrap 5 classes (row, col-*, btn) styled below.
 */

:root {
  /* Blues darkened to meet WCAG 2.1 AA contrast (4.5:1 for text, 4.5:1 for
     white-on-blue buttons). Previous brand values failed: #119bd4 text=3.15:1,
     #05a3e4 button=2.85:1. Same hue family, deeper tone. See cypress/e2e/a11y.cy.js. */
  --nxt-blue: #0b76a8;              /* was #119bd4 — text on white 3.15 -> 5.0:1 */
  --nxt-blue-dark: #2b3494;
  --nxt-blue-button: #0a6ea0;       /* was #05a3e4 — white text 2.85 -> 5.6:1 */
  --nxt-blue-button-light: #0d7cad; /* was #35bfef — white text -> 4.7:1 (gradient top) */
  --nxt-orange: #ee7d00;
  --nxt-orange-light: #ef9023;
  /* Orange as foreground text. The brand orange fails as text: #ee7d00 on the tinted
     pill #fefaf7 is 2.67:1. Fills keep --nxt-orange. */
  --nxt-orange-text: #a35400;       /* text on #fefaf7 2.67 -> 5.3:1, on white 5.1:1 */
  --nxt-text: #333333;
  --nxt-text-muted: #5f6673;        /* was #6b7280 — on tinted cards 4.39 -> ~5.2:1 */
  --nxt-border: #e5e7eb;
  --nxt-note-bg: #fff8e1;
  --nxt-note-border: #f0dfa0;
  --nxt-radius: 12px;
  --nxt-radius-sm: 8px;
  --nxt-shadow: 0 2px 10px rgba(17, 24, 39, 0.08);
  --nxt-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* This theme is light-only. Without this, browsers auto-dark-mode native
     form controls (select/option popups) to match a dark OS/browser theme,
     so a <select>'s dropdown list renders with a dark background/white text
     even though every other box on the page is light — jarring, and the
     text color contrast at that point is out of our control. */
  color-scheme: light;
}

body {
  font-family: var(--nxt-font);
  color: var(--nxt-text);
  /* .nxt-full-bleed (below) breaks tables out to 100vw, which includes the
     vertical scrollbar's width on desktop browsers, while its `50%` margin
     offset is relative to body's content box (which excludes it) — so the
     element overshoots the viewport by the scrollbar's width and the page
     itself gains a spurious horizontal scrollbar. Wide tables already scroll
     internally via .table-responsive's own overflow-x: auto, so the page
     never needs to. */
  /* overflow-x: hidden; */
}

/* Bootstrap 2's scaffolding.css made every <img> responsive (max-width:100%)
   by default; Bootstrap 5 dropped that in favor of an opt-in .img-fluid class.
   A decade of CMS-authored content HTML (cmscontent bodies, gallery renders)
   embeds raw <img> tags assuming the old global behavior, causing horizontal
   overflow on narrow viewports under nxt without this shim. */
img { max-width: 100%; height: auto; }

h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
  font-family: var(--nxt-font);
  color: var(--nxt-blue);
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: 0 0 0.5rem;
}

h1, .h1 { font-size: rem; }
h2, .h2 { font-size: 1.6rem; }
h3, .h3 { font-size: 1.25rem; }

a { color: var(--nxt-blue); }
a:hover { color: var(--nxt-blue-dark); }

.text-muted-nxt { color: var(--nxt-text-muted); }

/* ---------- Bootstrap 2 grid compatibility shim ---------- */
.row-fluid {
  display: flex;
  flex-wrap: wrap;
  margin-left: -10px;
  margin-right: -10px;
}
.row-fluid::after { content: none; }
[class*="span"] { padding-left: 10px; padding-right: 10px; box-sizing: border-box; }
.span1  { flex: 0 0 8.3333%;  max-width: 8.3333%; }
.span2  { flex: 0 0 16.6667%; max-width: 16.6667%; }
.span3  { flex: 0 0 25%;      max-width: 25%; }
.span4  { flex: 0 0 33.3333%; max-width: 33.3333%; }
.span5  { flex: 0 0 41.6667%; max-width: 41.6667%; }
.span6  { flex: 0 0 50%;      max-width: 50%; }
.span7  { flex: 0 0 58.3333%; max-width: 58.3333%; }
.span8  { flex: 0 0 66.6667%; max-width: 66.6667%; }
.span9  { flex: 0 0 75%;      max-width: 75%; }
.span10 { flex: 0 0 83.3333%; max-width: 83.3333%; }
.span11 { flex: 0 0 91.6667%; max-width: 91.6667%; }
.span12 { flex: 0 0 100%;     max-width: 100%; }
.offset1  { margin-left: 8.3333%; }
.offset2  { margin-left: 16.6667%; }
.offset3  { margin-left: 25%; }
.offset4  { margin-left: 33.3333%; }
.offset5  { margin-left: 41.6667%; }
.offset6  { margin-left: 50%; }
@media (max-width: 767px) {
  .row-fluid [class*="span"] { flex: 0 0 100%; max-width: 100%; }
}

/* ---------- CMS "hotelblock" cards ---------- *
 * fourblocks-horizontal.phtml (homepage bottom cards) and hotel-listing blocks
 * use these legacy classes (greyborder/hotelblock/hotelholder/hotel-image/
 * hotel-tabs/hotel-tab/bigheading/hotel-bottom) that style.css defined but nxt
 * never shimmed — so they rendered as borderless columns with ragged heights
 * and unaligned buttons. Give them the nxt card look: bordered, rounded, image
 * on top, centred heading, full-width button pinned to the bottom so cards in a
 * row line up. The image/button break out of the Bootstrap 5 column gutter
 * padding so they sit flush to the card border. */
.greyborder { border: 1px solid var(--nxt-border); }
/* Equal-height cards: .hotelblock IS the flex column (the col), so it stretches
   to the tallest card via the row's default align-items:stretch. Do NOT set
   height:100% here — against the auto-height .row it resolves to auto and
   overrides the stretch, making cards size to their own content instead. */
.hotelblock {
  display: flex;
  flex-direction: column;
  background: #fff;
  border-radius: var(--nxt-radius-sm);
  overflow: hidden;
}
.hotelblock .hotelholder { position: relative; display: flex; flex-direction: column; flex: 1 1 auto; }
.hotelblock .hotel-image,
.hotelblock .hotel-bottom {
  margin-left: calc(var(--bs-gutter-x, 1rem) * -0.5);
  margin-right: calc(var(--bs-gutter-x, 1rem) * -0.5);
}
.hotelblock .hotel-image { line-height: 0; }
.hotelblock .hotel-image img { display: block; width: 100%; height: 170px; object-fit: cover; }
.hotelblock .hotel-tabs { flex: 1 1 auto; }
.hotelblock .hotel-tab { padding: 0.85rem 0.85rem 0; text-align: center; }
.hotelblock .hotel-tab .h2,
.hotelblock .hotel-tab h2 {
  font-size: 1.2rem;
  font-weight: 700;
  line-height: 1.2;
  margin-bottom: 0.4rem;
}
.hotelblock .hotel-tab .h2 a { color: var(--nxt-blue); }
.hotelblock .hotel-tab a { text-decoration: none; }
.hotelblock .hotel-tab a:hover { text-decoration: underline; }
.hotelblock .hotel-bottom { margin-top: auto; padding: 0.85rem; }
.hotelblock .hotel-bottom .page-button { display: block; }

/* Four blocks: real gaps BETWEEN the cards. The card border/background sits on
   the Bootstrap column (.hotelblock IS the col), and Bootstrap's gutter is
   just padding inside each column — adjacent column border-boxes are flush,
   so no space showed between cards (the image bleeds to that flush edge and
   visibly touches its neighbour; the button only *looks* spaced because of
   its own inner padding). Lay the row out as a grid so the gap lands between
   the cards instead. */
.blacklinks > .row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1.75rem;
  --bs-gutter-x: 0;
  --bs-gutter-y: 0;
}

.blacklinks > .row > [class*="col-"] {
  width: auto;
  max-width: none;
  padding: 0;
  margin: 0;
}

@media (max-width: 767px) {
  .blacklinks > .row {
    grid-template-columns: 1fr;
  }
}

/* CMS content spacing utilities (style.css scoped these to #content). */
#content .margin { margin-top: 1rem; }
#content .double-margin { margin-top: 1.5rem; }
@media (max-width: 767px) {
  #content .margin-mobile { margin-top: 1rem; }
  #content .double-margin-mobile { margin-top: 1.5rem; }
}

/* Full-width CMS promo banner (e.g. Bula Combo Pass, fiji-main-page-header.jpg).
   The source image is ~960px wide, so it left-aligned inside the wider nxt
   container leaving a gap on the right. Make the link + image fill the row and
   round the corners to match the theme. height:auto keeps the aspect ratio, so
   it scales up proportionally with no distortion. */
.row-fluid.margin > a {
  flex: 1 1 100%;
  display: block;
  /* .row-fluid adds -10px side margins that grid spans cancel with +10px
     padding; this bare <a> has no span class, so add the same padding or the
     banner overhangs the content by 10px each side. */
  padding-left: 10px;
  padding-right: 10px;
  box-sizing: border-box;
}
.row-fluid.margin > a > img {
  display: block;
  width: 100%;
  border-radius: var(--nxt-radius);
}

/* Rounded corners for images inside CMS content (route maps, photos, promos)
   to match the theme. Card images (.hotel-image) are excluded — their
   .hotelblock already clips them, so rounding the <img> too would reveal white
   gaps at its bottom corners. */
.cmscontent img { border-radius: var(--nxt-radius); }
.cmscontent .hotel-image img { border-radius: 0; }

/* Bootstrap 2's built-in responsive-visibility utilities (bootstrap.css, not
   loaded here) and its ".gradient" boxed-panel pattern (style.css) have no
   Bootstrap 5 equivalent and are still used across ~20-30 not-yet-ported
   templates each — shimmed here so those pages keep working/looking
   reasonable instead of silently losing show/hide behavior entirely. */
@media (max-width: 767px) { .hidden-phone { display: none !important; } }
@media (min-width: 768px) { .hidden-desktop { display: none !important; } }
/* scripts.js hides native <input class="submit"> elements after wrapping them
   in a styled link — no Bootstrap 5 equivalent for this bare utility class. */
.hidden { display: none !important; }
div.gradient {
  border: 1px solid var(--nxt-border);
  padding: 9px 15px 0 15px;
  border-radius: var(--nxt-radius-sm);
  background: #fafafa;
  overflow: hidden;
}

.site-gilibookings div.gradient {
    padding: 9px 15px 33px 15px;
}

.site-gilibookings .nxt-content-search .nxt-search-card {
    padding: 9px 15px 9px 15px;
}
div.gradient div.gradient { border: none; padding: 0; background: transparent; border-radius: 0; }
div.gradient.gradient-success {
  border-color: #029934;
  color: #029934;
  background-color: #cbecd6;
  font-size: 1rem;
  font-weight: 700;
}

/* Zend_Form (Twitter_Form-decorated) admin forms render as dl > dt(label) +
   dd(controls/help-block/error) — style.css's control-group/dl/dt/dd rules
   aren't loaded under nxt, so every echoed $this->editForm/$this->form was
   rendering as an unstyled definition list. */
/* CMS-authored content (boat/hotel/activity descriptions, blog posts) embeds
   fixed multi-column schedule/timetable HTML tables that predate any
   responsive treatment. Rather than blowing out the page width on mobile,
   scroll them horizontally within their own box (thead/tbody kept as
   display:table so cells still lay out normally; only the outer <table>
   becomes the scroll container, since there's no wrapper div to target).

   div.scheduletables is listed alongside .cmscontent on every rule below
   because the block is not always rendered inside a .cmscontent wrapper:
   clicking a route map on /boat-schedule opens a jQuery UI dialog whose
   markup autodialog2() loads over ajax (nxt/layouts/ajax.phtml is a bare
   `echo $content`) and appends straight to <body>. Scoping on .cmscontent
   alone left that dialog completely unstyled — no cell grid, and the tab
   switcher rendered as plain underlined links. */
.cmscontent table,
div.scheduletables table {
  display: block;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  max-width: 100%;
  margin: 0.5rem 0 1.5rem;
  font-size: 0.9rem;
}
.cmscontent table > thead,
.cmscontent table > tbody,
div.scheduletables table > thead,
div.scheduletables table > tbody {
  display: table;
  width: 100%;
}
/* Give the CMS schedule/timetable tables the nxt look: light-blue bordered
   cells, a tinted header, and row hover. */
.cmscontent table th,
.cmscontent table td,
div.scheduletables table th,
div.scheduletables table td {
  border: 1px solid #cfe8f5;
  padding: 0.5rem 0.65rem;
  vertical-align: top;
  text-align: left;
}
.cmscontent table th,
div.scheduletables table th {
  background: #eaf6fc;
  color: var(--nxt-blue-dark);
  font-weight: 600;
}
.cmscontent table tbody tr:hover > td,
div.scheduletables table tbody tr:hover > td { background: rgba(17, 155, 212, 0.05); }

/* The schedule tab-switcher row (Yasawa Flyer / Bula Pass / Captain's Lounge)
   is a single colspan cell holding <a.table-tab> links — sit it above the
   table rather than styling it as a header cell. */
.cmscontent table tr.tabs th,
div.scheduletables table tr.tabs th {
  background: transparent;
  border: none;
  padding: 1.0rem 0 0;
}
.cmscontent .table-tab,
div.scheduletables .table-tab {
  display: inline-block;
  margin: 0 0.35rem 0 0;
  border: 1px solid var(--nxt-border);
  border-bottom: none;
  border-radius: var(--nxt-radius-sm) var(--nxt-radius-sm) 0 0;
  background: #f3f4f6;
  color: var(--nxt-text-muted) !important;
  text-decoration: none;
  font-weight: 600;
  vertical-align: bottom;
}
.cmscontent .table-tab span,
div.scheduletables .table-tab span { display: inline-block; padding: 0.4rem 0.9rem; cursor: pointer; }
.cmscontent .table-tab:hover,
div.scheduletables .table-tab:hover { color: var(--nxt-blue) !important; }
.cmscontent .table-tab.active,
div.scheduletables .table-tab.active {
  background: var(--nxt-blue-button);
  background: linear-gradient(var(--nxt-blue-button-light), var(--nxt-blue-button));
  border-color: var(--nxt-blue-button);
  color: #fff !important;
}
.cmscontent .table-tab.active:hover,
div.scheduletables .table-tab.active:hover { color: #fff !important; }

/* The ajax-loaded map dialog gets none of the .cmscontent typography either,
   so give the block the same body font/colour it has on the page and keep the
   route map that follows the tables from butting up against them. */
.ajax-dialog-window > div.scheduletables,
.ajax-dialog-window > div.tablemaps {
  font-family: var(--nxt-font);
  color: var(--nxt-text);
  line-height: 1.6;
}
.ajax-dialog-window > div.tablemaps img { max-width: 100%; height: auto; border-radius: var(--nxt-radius); }

/* A CMS page loaded into the dialog brings its whole page furniture with it,
   breadcrumb included. In a modal there is nowhere to navigate to -- the links
   would drop the customer out of checkout -- so hide it. `.breadcrumb` covers a
   page whose template still resolves to the blank theme's markup. */
.ajax-dialog-window .nxt-breadcrumb,
.ajax-dialog-window .breadcrumb { display: none; }

/* =========================================================================
   Schedule tables — GRID layout (gilibookings / gilitickets only)
   =========================================================================
   combineScheduleTables() in nxt-scripts.js picks combinetablesGrid() for
   WEBSITE gilibookings/gilitickets and combinetables() for everyone else, so
   only those two sites ever emit this markup (.schedule-wrapper / -company /
   -tabs / -panel / -grid / -column / -section + table.section-table, all
   appended inside div.scheduletables). Every other site's plain <table> output
   is already styled by the div.scheduletables rules above.

   Moved in from the per-site stylesheets, which nxt does not load. Scoped
   under div.scheduletables so the generic table rules above — which set a full
   cell border and turn the <table> into an overflow-x scroller — do not win
   over the grid's own borderless, fixed-layout sections. gilitickets keeps its
   duplicate in gilitickets.css until it migrates; delete it there rather than
   editing both. The map block sits OUTSIDE div.scheduletables (the tab click
   handler reaches it with .siblings('.schedule-map')), so it stays unscoped. */
.schedule-wrapper {
    clear: both;
}

.schedule-company {
    margin-bottom: 32px;
}

.schedule-company:last-child {
    margin-bottom: 0;
}

.schedule-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    margin-bottom: 20px;
}

.schedule-tab {
    display: inline-block;
    padding: 10px 24px;
    background: #d4edf3;
    border: 1px solid #93CEF8;
    border-bottom: 2px solid #05a3e4;
    color: #333 !important;
    text-decoration: none !important;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    border-radius: 4px 4px 0 0;
}

.schedule-tab:hover {
    background: #c0e4f0;
    color: #111 !important;
}

.schedule-tab.active {
    background: transparent;
    border-color: #93CEF8;
    border-bottom-color: transparent;
    color: #333 !important;
}

.schedule-panel {
    display: none;
}

.schedule-panel.active {
    display: block;
}

.schedule-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    align-items: start;
}

.schedule-column {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.schedule-section {
    border: 1px solid #ddd;
    border-radius: 4px;
    overflow: hidden;
}

div.scheduletables .section-header-row td {
    background: #35bfef;
    background: linear-gradient(to bottom, #35bfef 0%, #05a3e4 100%);
    color: #fff;
    font-weight: 700;
    font-size: 14px;
    padding: 8px 12px;
    text-transform: uppercase;
    text-align: left;
    border: none;
}

div.scheduletables .column-headers td {
    background-color: #bbdefb;
    border: none;
    border-bottom: 2px solid #93CEF8;
    padding: 6px 10px;
    text-align: left;
    font-weight: 600;
    font-size: 12px;
    color: #4F4F50;
}

/* The generic rule above turns every div.scheduletables table into a
   display:block overflow-x scroller; the grid's sections are already narrow
   columns, and table-layout:fixed + the <colgroup> the JS emits only apply to
   a real table box. */
div.scheduletables table.section-table {
    display: table;
    overflow: visible;
    width: 100%;
    margin: 0;
    border-collapse: collapse;
    font-size: 13px;
    table-layout: fixed;
}

/* ...and the matching tbody rule (display:table, width:100%) has to be undone
   too. A tbody that is its own table is no longer a row group of the section
   table, so table-layout:fixed and the <colgroup> stop reaching the cells: the
   rows shrink-to-fit and the section renders about 40% of its column width
   with a wide empty gutter. */
div.scheduletables table.section-table > tbody {
    display: table-row-group;
    width: auto;
}

/* Column widths. The JS also emits a <colgroup> per section (37/13/37/13 for a
   named section, 32/18/32/18 for an unnamed one); these are the per-site
   stylesheet's originals, kept so the rendered widths do not shift. */
div.scheduletables .section-table td:nth-child(1),
div.scheduletables .section-table td:nth-child(3) {
    width: 37%;
}

div.scheduletables .section-table td:nth-child(2),
div.scheduletables .section-table td:nth-child(4) {
    width: 13%;
}

div.scheduletables .section-table td[colspan] {
    background-color: #119bd4;
    border: none;
    border-bottom: 2px solid #93CEF8;
    padding: 6px 10px;
    text-align: left;
    font-weight: 600;
    font-size: 12px;
    color: #fff;
}

div.scheduletables .section-table .spacer td[colspan] {
    background-color: transparent;
    border-bottom: none;
}

div.scheduletables .section-table td {
    padding: 5px 10px;
    border: none;
    border-bottom: 1px solid #e8e8e8;
}

div.scheduletables .section-table td:nth-child(2),
div.scheduletables .section-table td:nth-child(4) {
    text-align: center;
}

div.scheduletables .section-table tbody tr:hover:not(.column-headers):not(.section-header-row) > td {
    background-color: #eef8fc;
}

div.scheduletables .column-headers td:nth-child(even),
div.scheduletables .section-header-row td {
    background-color: #bbdefb;
}

.schedule-map {
    margin-top: 20px;
    text-align: center;
}

.schedule-map img {
    max-width: 100%;
    height: auto;
    border-radius: var(--nxt-radius);
}

@media (max-width: 768px) {
    .schedule-grid {
        grid-template-columns: 1fr;
    }

    .schedule-tabs {
        gap: 6px;
    }

    .schedule-tab {
        padding: 6px 14px;
        font-size: 13px;
    }
}

dl.zend_form { margin: 0; }
dl.zend_form dt {
  font-weight: 600;
  margin-top: 1rem;
  margin-bottom: 0.25rem;
}
dl.zend_form dt:first-child { margin-top: 0; }
dl.zend_form dd { margin: 0 0 0.25rem; }
dl.zend_form input[type="text"],
dl.zend_form input[type="password"],
dl.zend_form input[type="email"],
dl.zend_form input[type="number"],
dl.zend_form select,
dl.zend_form textarea {
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
  padding: 0.45rem 0.65rem;
  font-family: var(--nxt-font);
}
dl.zend_form .help-block { color: var(--nxt-text-muted); font-size: 0.82rem; }
dl.zend_form .errors,
dl.zend_form .error { color: #c0392b; font-size: 0.85rem; list-style: none; padding: 0; margin: 0.2rem 0 0; }
dl.zend_form dd.submit input[type="submit"],
dl.zend_form input.submit {
  background: var(--nxt-blue-button);
  background: linear-gradient(var(--nxt-blue-button-light), var(--nxt-blue-button));
  border: 1px solid var(--nxt-blue-button);
  color: #fff;
  border-radius: var(--nxt-radius-sm);
  font-weight: 600;
  padding: 0.55rem 1.25rem;
}

/* admin_grid: style.css gave these a dark header + zebra stripes; not loaded
   under nxt, so pair the class with Bootstrap 5's own .table utilities in
   markup (already done across the admin conversion pass) and add the header
   treatment here since .table-dark on <th> alone isn't part of that pass. */
table.admin_grid th {
  background: #3a3f47;
  color: #fff;
  font-weight: 600;
}

/* #banner's offers carousel (offers.phtml) slides via JS `transform:
   translateX()` on .carousel; without this flex layout the slides just
   stack in normal flow since there's nothing for the transform to slide
   between. */
#banner, .offers, .carousel-container { overflow: hidden; max-width: 100%; }

/* Fiji homepage hero. #banner (default.phtml) is given the `fiji` class only
   when WEBSITE=fijibookings; its background image lived in the per-site
   style.css that nxt dropped, so restore it here. Desktop only (#banner is
   d-none d-md-block; mobile uses #mobile-banner). Scoped to .fiji so other
   sites' #banner is unaffected. */
#banner.fiji {
  height: 180px;
  margin: 1.5rem 0;
  background: url('../images/fijibookings/Fiji-Bookings-Banner-Image.png') center / cover no-repeat;
  border-radius: var(--nxt-radius);
  position: relative;
}

/* Thaibookings homepage hero, same restoration as .fiji above — its
   background image lived in the per-site style.css that nxt dropped. */
#banner.thai {
  height: 180px;
  margin: 1.5rem 0;
  background: url('../images/thaibookings/headers/header.jpg') center / cover no-repeat;
  border-radius: var(--nxt-radius);
  position: relative;
}

/* Vietnamferries homepage hero, same restoration as .fiji and .thai above —
   nxt drops the per-site stylesheet that used to carry this background. */
#banner.vietnam {
  height: 320px;
  margin: 1.5rem 0;
  background: url('../images/vietnamferries/headers/header.jpg') center / cover no-repeat;
  border-radius: var(--nxt-radius);
  position: relative;
}

/* StMartinbookings homepage hero, same restoration as .fiji, .thai and .vietnam
   above. 185px keeps the height the per-site stylesheet used. One rule covers
   the black-and-white and affiliate banner variants too: the `stmartin` class is
   appended alongside $bannerClass, and all three pointed at the same image. */
#banner.stmartin {
  height: 225px;
  margin: 1.5rem 0;
  background: url('../images/stmartinbookings/headers/header.jpg') center / cover no-repeat;
  border-radius: var(--nxt-radius);
  position: relative;
}

/* Seychellesbookings homepage hero, same restoration as .fiji, .thai, .vietnam
   and .stmartin above. Two differences from those:
   1. Seychelles ships a different image per banner variant, so $bannerClass
      (black-and-white / endorsed-by / affiliate) selects the artwork on top of
      the `seychelles` base rule.
   2. All four images are 960x185 with the headline baked into the artwork, and
      nxt's container is wider than the one they were cut for. A fixed 185px box
      with `cover` therefore crops that headline off. Driving the height from
      `aspect-ratio` instead shows the whole image at every breakpoint, so the
      copy stays readable. Keep the ratio in step if the artwork is re-cut. */
#banner.seychelles {
  aspect-ratio: 960 / 185;
  margin: 1.5rem 0;
  background: url('../images/seychellesbookings/headers/header.jpg') center / cover no-repeat;
  border-radius: var(--nxt-radius);
  position: relative;
}
#banner.seychelles.black-and-white {
  background-image: url('../images/seychellesbookings/headers/black-and-white.jpg');
}
#banner.seychelles.endorsed-by {
  background-image: url('../images/seychellesbookings/headers/header-endorsed-by-desktop.jpg');
}
#banner.seychelles.affiliate {
  background-image: url('../images/seychellesbookings/headers/header-affiliate.jpg');
}

/* Gilibookings homepage hero. Same restoration as the sites above, and the same
   aspect-ratio treatment as .seychelles: all four variants are 960x185 with the
   headline ("Fast boat, hotel and diving / On Bali, Lombok and the Gilli's")
   baked into the artwork, so a fixed 185px box with `cover` crops the copy off
   in nxt's wider container. Keep the ratio in step if the artwork is re-cut.
   The `lonely-planet` variant is not a CMS banner value — default.phtml adds it
   on the /bali-to-gili-fast-boat tree. */
#banner.gili {
  aspect-ratio: 960 / 185;
  margin: 1.5rem 0;
  background: url('../images/gilibookings/headers/header.jpg') center / cover no-repeat;
  border-radius: var(--nxt-radius);
  position: relative;
}
#banner.gili.black-and-white {
  background-image: url('../images/gilibookings/headers/black-and-white.jpg');
}
#banner.gili.affiliate {
  background-image: url('../images/gilibookings/headers/header-affiliate.jpg');
}
#banner.gili.lonely-planet {
  background-image: url('../images/gilibookings/headers/lonely-planet.png');
}

/* Invisible click target over the hero's top-left corner, linking to
   /groupdiscounts. Rendered only where groupdiscount.active = 1, which today is
   gilibookings alone. style.css (not loaded under nxt) placed it at 13px/13px
   400x44 on the 960x185 artwork; expressed as percentages of that box it stays
   on the same spot now the hero scales with its aspect ratio. */
#banner a.groupdiscount {
  display: block;
  position: absolute;
  z-index: 998;
  left: 1.354%;
  top: 7.027%;
  width: 41.667%;
  height: 23.784%;
}

.carousel-container { border-radius: var(--nxt-radius); }
.carousel { display: flex; transition: transform 0.5s ease; width: 100%; }
.carousel-slide { flex: 0 0 100%; width: 100%; min-width: 0; box-sizing: border-box; overflow-wrap: break-word; }
/* The slide's background image normally came from a per-site stylesheet
   (not loaded under nxt); give it a plain promo-card look instead of
   floating unstyled text. */
.carousel-slide a {
  display: block;
  background: linear-gradient(135deg, var(--nxt-blue-button), var(--nxt-blue-dark));
  color: #fff;
  border-radius: var(--nxt-radius);
  padding: 1.25rem 1.5rem;
  text-decoration: none;
  min-height: 90px;
}
.carousel-slide .pricetext { font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.04em; opacity: 0.9; }
.carousel-slide .pricetext .bigger { font-size: 1.15rem; font-weight: 700; text-transform: none; display: block; margin-top: 0.15rem; }
.carousel-slide .price { display: block; margin-top: 0.5rem; font-size: 1.5rem; font-weight: 700; }
.carousel-slide .price .startingat { display: block; font-size: 0.75rem; font-weight: 400; opacity: 0.85; }

/* .search-bottom (form-boat.phtml) relies on a floated .search-button that
   .gradient's overflow:hidden (needed to contain other internal floats)
   was silently clipping since nothing cleared the float. */
.search-bottom {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 0rem;
}
.search-bottom .search-button .page-button.right { float: none; }
@media (max-width: 767.98px) {
  /* Full-width Search button on mobile, stacked below the note text (already
     the DOM order) with breathing room underneath it. */
  .search-bottom .search-button {
    width: 100%;
  }
  .search-bottom .search-button .page-button {
    display: block;
    width: 100%;
    margin-right: 0;
    margin-bottom: 1rem;
  }
}

/* ---------- .page-button compatibility shim ---------- */
.page-button {
  display: inline-block;
  border-radius: var(--nxt-radius-sm);
  border: 1px solid var(--nxt-border);
  background: #fff;
  color: var(--nxt-text);
  text-decoration: none;
  padding: 0;
  margin-right: 3px;
}
.page-button span { display: block; padding: 8px 16px; }
.page-button.emphasize,
.page-button.selected {
  background: var(--nxt-blue-button);
  background: linear-gradient(var(--nxt-blue-button-light), var(--nxt-blue-button));
  border-color: var(--nxt-blue-button);
  color: #fff;
}
.page-button.emphasize span, .page-button.selected span { color: #fff; }
.page-button.orange {
  background: var(--nxt-orange-light);
  background: linear-gradient(to bottom, var(--nxt-orange-light), var(--nxt-orange));
  border-color: var(--nxt-orange);
  color: #fff;
}
.page-button.orange span { color: #fff; }
.page-button.orange:hover { background: var(--nxt-orange); }
.page-button.biggesttext span { font-size: 1.1rem; font-weight: 700; }
.page-button.bigtext span { font-size: 0.95rem; font-weight: 700; }
.page-button.fullwidth,
.page-button.fullwidth span { display: block; text-align: center; }
@media (max-width: 768px) {
  .page-button.fullwidth-mobile,
  .page-button.fullwidth-mobile span { display: block; text-align: center; }
}
.page-button:hover { text-decoration: none; }

/* Bigger, wider Search button everywhere — unscoped (not just
   .nxt-home/.nxt-content-search) so it also reaches the mobile accordion
   boat form, which renders the same form-boat.phtml markup outside those
   desktop-only wrapper classes. */
.search-button .page-button.orange span { padding: 0.5rem 2.4rem; font-size: 1.0rem; }
@media (min-width: 769px) {
  .search-button .page-button.orange { min-width: 220px; }
}

/* Boat form (every nxt site): the note and the Search button share the bottom row as two
   columns that line up with the field grid above (row g-3 = 1rem gutter), so
   the button sits under the "To" field at the same width instead of wrapping
   under a long note on the left. */
@media (min-width: 768px) {
  .search_form.boat_form .search-bottom {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: 1rem;
    row-gap: 0.75rem;
    align-items: center;
  }
  .search_form.boat_form .search-bottom .search-button { grid-column: 2; }
  .search_form.boat_form .search-bottom .search-button .page-button { display: block; width: 100%; min-width: 0; margin-right: 0; text-align: center; }
}

/* ---------- Search form (form-boat / form-hotel) ---------- *
 * Boxed fields with a small inner label, matching the nxt design language.
 * Each .field-select overlays an invisible native <select> on top of the box
 * (search.js inserts a .form-select div that shows the chosen option text);
 * .field-text holds a normal datepicker input. Scoped to .search_form so the
 * admin/back-office forms that also use .field markup are left untouched. */
.form-boat-title {
  color: var(--nxt-blue-dark);
  font-weight: 400;
  margin-bottom: 0.85rem;
}
.form-boat-title strong { font-weight: 800; }

.search_form .field { position: relative; margin-bottom: 0; }

/* WebMCP: controls that share one name (the trip-type radios) collapse into ONE
   tool parameter, and Chrome reads that parameter's description from the nearest
   parent <fieldset> — never from the individual controls. So form-boat.phtml wraps
   the radios in one; see Twm_View_Helper_WebmcpTool. It is a marker, not a box:
   zero it out so it adds nothing to the layout (padding/border/margin because the
   UA sheet draws a groove around a fieldset, min-width because the UA sheet also
   gives it `min-inline-size: min-content`, which Bootstrap 2 does not reset). */
.webmcp-group {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

/* Trip-type radios */
.search_form .field-options {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem 1.4rem;
  margin-bottom: 0.9rem;
}
.search_form .field-options label.radio {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0;
  font-weight: 500;
  color: var(--nxt-text);
  cursor: pointer;
}

.search_form .field-options input[type="radio"],
.hotel_search .radio input[type="radio"] {
  /* Custom-painted rather than relying on accent-color: Safari has a
     long-standing WebKit bug where the checked dot fails to paint on a
     native radio once explicit width/height are set, leaving the selected
     option showing no control at all. */
  -webkit-appearance: none;
  appearance: none;
  width: 1.05em;
  height: 1.05em;
  margin: 0;
  border: 1.5px solid var(--nxt-border);
  border-radius: 50%;
  background: #fff;
  position: relative;
  flex-shrink: 0;
  cursor: pointer;
}

.search_form .field-options input[type="radio"]:checked,
.hotel_search .radio input[type="radio"]:checked {
  border-color: var(--nxt-blue);
}

.search_form .field-options input[type="radio"]:checked::before,
.hotel_search .radio input[type="radio"]:checked::before {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: var(--nxt-blue);
}

.search_form .field-options input[type="radio"]:focus-visible,
.hotel_search .radio input[type="radio"]:focus-visible {
  box-shadow: 0 0 0 3px rgba(17, 155, 212, 0.25);
}

/* Boxed field (select + text) with inner label */
.search_form .field-select,
.search_form .field-text {
  background: #fff;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
  padding: 0.4rem 0.75rem;
  min-height: 58px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.search_form .field-select:focus-within,
.search_form .field-text:focus-within {
  border-color: var(--nxt-blue);
  box-shadow: 0 0 0 3px rgba(17, 155, 212, 0.12);
}
.search_form .field-select > label,
.search_form .field-text > label {
  display: block;
  margin: 0;
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1.2;
  color: var(--nxt-blue);
}

/* Visible value: the datepicker input and the JS .form-select display div */
.search_form .field-select .form-select,
.search_form .field-text input:not([type="radio"]):not([type="checkbox"]) {
  width: 100%;
  border: 0 !important;
  outline: 0;
  background: transparent;
  padding: 0 !important;
  margin: 0;
  height: 1.7rem;
  line-height: 1.7rem;
  font-size: 1rem;
  color: var(--nxt-text);
  box-shadow: none !important;
}
.search_form .field-text input::placeholder { color: var(--nxt-text-muted); }

/* JS-rendered select display: show text, let clicks reach the native select */
.search_form .field-select .form-select {
  pointer-events: none;
  background: none;
  border-radius: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  padding-right: 1.25rem !important;
}
/* Belt-and-braces alongside :root's color-scheme: light — force a white
   dropdown-list background even if a browser only partially honors
   color-scheme for the popup vs. the closed control. */
.search_form .field-select select option {
  background-color: #fff;
  color: var(--nxt-text);
  padding: 4px 8px;
}
/* Native select becomes an invisible click layer covering the whole box */
.search_form .field-select select {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100% !important;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}
/* Custom caret for select boxes */
.search_form .field-select::after {
  content: "";
  position: absolute;
  right: 0.85rem;
  top: 50%;
  width: 0.5rem;
  height: 0.5rem;
  border-right: 2px solid var(--nxt-text-muted);
  border-bottom: 2px solid var(--nxt-text-muted);
  transform: translateY(-75%) rotate(45deg);
  pointer-events: none;
}

/* From/To with more than 10 locations: location-dropdown.js puts a button in
   front of the select that opens a list with a search box on top. The select
   stays in the form (posted, read by WebMCP and nxt-search.js) but stops
   catching clicks, and the button replaces the .form-select display div. */
.search_form .field-select.loc-dd select {
  pointer-events: none;
}
.search_form .field-select.loc-dd .form-select {
  display: none;
}
.search_form .field-select.loc-dd .loc-dd-toggle {
  display: block;
  width: 100%;
  border: 0;
  outline: 0;
  background: transparent;
  padding: 0 1.25rem 0 0;
  margin: 0;
  height: 1.7rem;
  line-height: 1.7rem;
  font-size: 1rem;
  color: var(--nxt-text);
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
}
/* The box, not just the text line, is the click target. */
.search_form .field-select.loc-dd .loc-dd-toggle::before {
  content: "";
  position: absolute;
  inset: 0;
}
.search_form .field-select.loc-dd.is-open::after {
  transform: translateY(-25%) rotate(225deg);
}
.loc-dd-panel {
  position: absolute;
  z-index: 1060;
  background: #fff;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  overflow: hidden;
}
.loc-dd-search-wrap {
  padding: 0.5rem;
  border-bottom: 1px solid var(--nxt-border);
}
.loc-dd-panel .loc-dd-search {
  display: block;
  width: 100%;
  height: 2.4rem;
  padding: 0 0.75rem;
  margin: 0;
  font-size: 1rem;
  color: var(--nxt-text);
  background: #fff;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
  box-shadow: none;
}
.loc-dd-panel .loc-dd-search:focus {
  outline: 0;
  border-color: var(--nxt-blue);
  box-shadow: 0 0 0 3px rgba(17, 155, 212, 0.12);
}
.loc-dd-list {
  position: relative;
  list-style: none;
  margin: 0;
  padding: 0.25rem 0;
  max-height: 300px;
  overflow-y: auto;
}
.loc-dd-option {
  padding: 0.45rem 0.75rem;
  color: var(--nxt-text);
  cursor: pointer;
  font-size: 0.95rem;
  line-height: 1.3;
}
.loc-dd-option.loc-dd-child {
  padding-left: 1.75rem;
}
.loc-dd-option[aria-selected="true"] {
  font-weight: 700;
}
.loc-dd-option.is-active {
  background: var(--nxt-blue);
  color: #fff;
}
.loc-dd-parent {
  display: block;
  font-size: 0.78rem;
  font-weight: 400;
  color: var(--nxt-text-muted);
}
.loc-dd-option.is-active .loc-dd-parent {
  color: rgba(255, 255, 255, 0.85);
}
.loc-dd-empty {
  padding: 0.75rem;
  color: var(--nxt-text-muted);
  font-size: 0.95rem;
}

/* Route message: nxt-search.js drops a .routemessage into the To field's
   .routemessage_container ("There are no boats from the departure point
   selected to this destination") when the picked from/to pair has no route.
   In flow it became a flex item of the boxed field, stretching it to ~3x its
   height and pushing the chosen location out of sight, so float it out of
   flow as a popover sitting above the field, with a caret pointing back at
   it. (style.css does the same thing for the pre-nxt themes; nxt does not
   load that stylesheet.) */
.search_form .routemessage_container { position: relative; }
.search_form .routemessage {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(100% + 10px);
  z-index: 30;
  margin: 0;
  padding: 0.55rem 1.9rem 0.55rem 0.75rem;
  border: 1px solid var(--nxt-note-border);
  border-radius: var(--nxt-radius-sm);
  background: var(--nxt-note-bg);
  box-shadow: var(--nxt-shadow);
  color: var(--nxt-text);
  font-size: 0.85rem;
  line-height: 1.4;
  text-align: left;
}
/* Caret: the ::after triangle is the fill, drawn 1px over the ::before
   triangle that supplies the border edge. */
.search_form .routemessage::before,
.search_form .routemessage::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 1.5rem;
  width: 0;
  height: 0;
  border: 8px solid transparent;
  border-bottom: 0;
}
.search_form .routemessage::before { border-top-color: var(--nxt-note-border); }
.search_form .routemessage::after { margin-top: -1px; border-top-color: var(--nxt-note-bg); }

.search_form .routemessage a.close {
  position: absolute;
  top: 0.3rem;
  right: 0.35rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  background: rgba(17, 24, 39, 0.07);
  color: var(--nxt-text-muted);
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1;
  text-decoration: none;
}
.search_form .routemessage a.close:hover {
  background: var(--nxt-note-border);
  color: var(--nxt-text);
}
/* Stacked layout: From sits directly above To, and the popover would cover the
   very field the message asks the visitor to change — so drop it under the To
   field there and point the caret back up. */
@media (max-width: 767.98px) {
  .search_form .routemessage {
    top: calc(100% + 10px);
    bottom: auto;
  }
  .search_form .routemessage::before,
  .search_form .routemessage::after {
    top: auto;
    bottom: 100%;
    border-top: 0;
    border-bottom: 8px solid transparent;
  }
  .search_form .routemessage::before { border-bottom-color: var(--nxt-note-border); }
  .search_form .routemessage::after {
    margin-top: 0;
    margin-bottom: -1px;
    border-bottom-color: var(--nxt-note-bg);
  }
}
/* div.gradient clips its content (it contains internal floats), which would
   cut the popover off at the top of the search card — the form itself holds
   no floats (.search-bottom is flex), so let this one gradient overflow. */
div.gradient:has(> form.search_form) { overflow: visible; }

/* Passenger age hint (16+ yrs, 2-15 yrs, 0-1 yrs) */
.search_form .control-group > small {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.75rem;
  color: var(--nxt-text-muted);
}
.search_form .control-group.error .field-select,
.search_form .control-group.error .field-text { border-color: #dc3545; }

/* Direct child only: form-boat.phtml nests a .double-col.row and a
   .triple-col.row (departure/return date, adults/children/infants) inside
   the second top-level row's columns — including those would double up this
   margin when they stack on mobile. */
.search_form > .row {
  margin-bottom: 1rem;
}

.nxt-home .search_form > .row {
  margin-bottom: 0rem;
}

/* Accommodation / activities form (form-hotel.phtml). Unlike form-boat it is
   plain label + radio markup with no .field-options wrapper, so without these
   rules the group label runs inline with its own radios and the options wrap
   into a ragged block. Give each group a block label and one radio per line.
   Unscoped on purpose: the form renders on the homepage, on the blockpage
   sidebar and on the hotelpage sidebar, and only the homepage's equal-height
   card sizing below is specific to where it sits. */
.hotel_search label:not(.radio) {
  display: block;
  font-weight: 600;
  color: var(--nxt-text);
  margin-bottom: 0.6rem;
}

.hotel_search .radio {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0;
  font-weight: 500;
  cursor: pointer;
}

/* .with-border/.dark come from style.css, which nxt does not load; make sure
   the budget column never tries to draw a divider of its own. */
.hotel_search .with-border.dark {
  border-left: 0;
}

.hotel_search .submit_button {
  margin-top: 1.35rem;
  align-self: flex-start;
}

/* ---------- Search results (fastboat.phtml) ---------- *
 * The result classes (search_result / price / book-button / fromto / arrow-
 * button …) were styled in style.css but never ported to nxt, so results
 * rendered as an unstyled text list. Give them the nxt look: a clean header,
 * a centred day-navigator with arrow buttons, and bordered result rows with a
 * bold blue price and orange Book button. */
.search_results {
  margin-top: 1.5rem;
  margin-bottom: 1.5rem;
}
.search_result.header {
  padding: 0 0 1rem;
  margin-bottom: 0.5rem;
}
.search_result.header .header-title { color: var(--nxt-blue); font-weight: 700; margin: 0; }
.search_result.header .header-title .searchresult-numbers { color: var(--nxt-text-muted); font-weight: 400; }
.search_result.header .sort-options { display: flex; justify-content: flex-end; }
.search_result.header .sort-options select,
.search_result select {
  display: inline-block;
  width: auto;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
  padding: 0.4rem 0.6rem;
  font-family: var(--nxt-font);
  background: #fff;
}
.search_result.header .fromto {
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--nxt-text);
  text-align: center;
  margin: 0.6rem 0 0.4rem;
}
.search_result.header .pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin: 0.4rem 0;
  padding: 0;
}

.search_results > .gradient {
  padding-bottom: 1rem;
}
@media (max-width: 767.98px) {
  /* Phones: the result cards are cards already, so drop the bordered panel
     around the list (one-way and both round-trip panels) and its padding. */
  .search_results > div.gradient,
  #resultsMoreBoats div.gradient.boatResults {
    padding: 0 0 0.5rem;
    border: 0;
    border-radius: 0;
    background: transparent;
  }
  /* The round-trip columns lose their own side padding on phones
     (#resultsMoreBoats .span6), so keep the cards on the page gutter. */
  #resultsMoreBoats div.gradient.boatResults { padding-left: 10px; padding-right: 10px; }
  /* Without the panel padding the header's Bootstrap row gutters would push
     "Results" and the sort select past the screen edge. */
  .search_results > div.gradient > .search_result.header > .row { margin-left: 0; margin-right: 0; }
  .search_results > div.gradient > .search_result.header > .row > [class*="col-"] { padding-left: 0; padding-right: 0; }
}
.search_result.header .pagination .day { font-weight: 700; color: var(--nxt-blue-dark); font-size: 1.05rem; }
/* Day-nav prev/next rendered as themed CSS triangles (the span text is hidden). */
.arrow-button {
  display: inline-block;
  width: 0;
  height: 0;
  border-top: 9px solid transparent;
  border-bottom: 9px solid transparent;
  overflow: hidden;
  vertical-align: middle; /* centre the triangle on the date, not on its baseline */
}
.arrow-button.previous { border-right: 12px solid var(--nxt-blue); }
.arrow-button.next { border-left: 12px solid var(--nxt-blue); }
.arrow-button.previous:hover { border-right-color: var(--nxt-blue-dark); }
.arrow-button.next:hover { border-left-color: var(--nxt-blue-dark); }
.arrow-button span { display: none; }
.change-search { text-align: right; margin-top: 0.5rem; }

/* Secondary action, not a primary CTA: drop the solid blue "emphasize" fill
   for a quiet outline so it doesn't compete with Search/Select buttons. */
.change-search .page-button.emphasize {
  background: none;
  border-color: var(--nxt-border);
  color: var(--nxt-text-muted);
  box-shadow: none;
}

.change-search .page-button.emphasize span {
  color: var(--nxt-text-muted);
}

.change-search .page-button.emphasize:hover {
  background: #f5f7fa;
  border-color: var(--nxt-blue);
}

.change-search .page-button.emphasize:hover span {
  color: var(--nxt-blue);
}

/* Mobile: the results-count/sort row is two Bootstrap col-12 columns that
   stack full-width below 768px, and the fromto/pagination/change-search
   blocks below each carry their own desktop-sized margin — stacked
   together this ate a large chunk of the viewport before any result card
   was visible. Put results-count and sort back on one row, and tighten
   every gap in the block underneath it. */
@media (max-width: 767.98px) {
  .search_result.header { padding-bottom: 0.5rem; margin-bottom: 0.25rem; }
  .search_result.header .row.preserve {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
  }
  .search_result.header .row.preserve > [class*="col-"] {
    width: auto;
    max-width: none;
    flex: 0 1 auto;
    padding-left: 0;
    padding-right: 0;
  }
  .search_result.header .header-title { font-size: 1.1rem; }
  .search_result.header .header-title .searchresult-numbers { font-size: 0.8rem; }
  .search_result.header .sort-options select { padding: 0.3rem 0.5rem; font-size: 0.85rem; }
  .search_result.header .fromto { font-size: 1rem; margin: 0.5rem 0 0.35rem; }
  .search_result.header .pagination { margin: 0.25rem 0; gap: 0.75rem; }
  .change-search { margin-top: 0.35rem; }
}

/* Result rows */
.search_result:not(.header) {
  margin: 0;
  padding: 1rem 0.25rem;
  align-items: center;
  border-bottom: 1px solid var(--nxt-border);
}
.search_result:not(.header):last-of-type { border-bottom: 0; }
.search_result:not(.header) img { max-width: 110px; height: auto; }
.search_result .small { color: var(--nxt-text); font-size: 0.9rem; line-height: 1.6; }
.search_result .price-box { text-align: right; }
.search_result .price {
  color: var(--nxt-blue);
  font-size: 1.45rem;
  font-weight: 700;
  display: block;
  line-height: 1.2;
}
.search_result .approx-price { display: block; font-size: 0.8rem; color: var(--nxt-text-muted); }
.search_result .book-button { margin-top: 0.6rem; }
/* Logo | details | price ratio closer to the reference than even thirds. */
@media (min-width: 768px) {
  .search_result:not(.header) > .col-md-4:first-child { flex: 0 0 18%; max-width: 18%; }
  .search_result:not(.header) > .col-md-4:nth-child(2) { flex: 0 0 56%; max-width: 56%; }
  .search_result:not(.header) > .col-md-4:last-child { flex: 0 0 26%; max-width: 26%; }
}

/* ---------- Result cards (each search result) ----------
 * Each availability renders as a self-contained card: operator on the left, a
 * departure -> arrival timeline in the middle, price + Book on the right. */
.search_result.nxt-result-card {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem 1.25rem;
  margin: 0 0 0.9rem;
  padding: 1rem 1.15rem;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius);
  background: #fff;
  box-shadow: var(--nxt-shadow);
  transition: box-shadow 0.18s ease, transform 0.18s ease, border-color 0.18s ease;
}
.search_result.nxt-result-card:last-of-type { margin-bottom: 0; }
.search_result.nxt-result-card:hover {
  box-shadow: 0 6px 22px rgba(17, 24, 39, 0.12);
  border-color: #cfe8f5;
  transform: translateY(-2px);
}
.nxt-result-card__logo { flex: 0 0 auto; width: 92px; text-align: center; line-height: 0; }
.search_result.nxt-result-card .nxt-result-card__logo img { max-width: 92px; height: auto; }
.nxt-result-card__body { flex: 1 1 340px; min-width: 0; }
.nxt-result-card__head { display: flex; align-items: baseline; gap: 0.5rem; margin-bottom: 0.55rem; flex-wrap: wrap; }
.nxt-result-card__operator { font-weight: 700; font-size: 1.02rem; color: var(--nxt-blue-dark); text-decoration: none; }
.nxt-result-card__operator:hover { color: var(--nxt-blue); text-decoration: underline; }
.nxt-result-card__details { font-size: 0.82rem; color: var(--nxt-text-muted); }

.nxt-result-card__journey { display: flex; align-items: center; gap: 1rem; }
.nxt-result-card__stop { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.nxt-result-card__stop--arr { text-align: right; align-items: flex-end; }
.nxt-result-card__return { display: flex; flex-direction: column; line-height: 1.25; padding-left: 1rem; margin-left: 0.5rem; border-left: 1px solid var(--nxt-border); }
.nxt-result-card__label { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--nxt-text-muted); }
.nxt-result-card__time { font-size: 1.35rem; font-weight: 700; color: var(--nxt-text); white-space: nowrap; }
.nxt-result-card__time--sm { font-size: 1.05rem; }
.nxt-result-card__time--pass { font-size: 1.05rem; white-space: normal; line-height: 1.25; max-width: 200px; }
.nxt-result-card__place {
  font-size: 0.82rem;
  color: var(--nxt-text-muted);
  max-width: 150px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.nxt-result-card__subtime { font-size: 0.72rem; color: var(--nxt-text-muted); margin-top: 0.15rem; }
.nxt-result-card__conn { flex: 1 1 auto; display: flex; flex-direction: column; align-items: center; gap: 0.3rem; min-width: 56px; }
.nxt-result-card__duration {
  font-size: 0.72rem;
  color: var(--nxt-blue-dark);
  background: #eaf6fc;
  padding: 0.1rem 0.55rem;
  border-radius: 999px;
  white-space: nowrap;
}
.nxt-result-card__track { position: relative; width: 100%; height: 2px; background: var(--nxt-border); }
.nxt-result-card__track::before,
.nxt-result-card__track::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--nxt-blue);
  transform: translateY(-50%);
}
.nxt-result-card__track::before { left: 0; }
.nxt-result-card__track::after { right: 0; }
.nxt-result-card__flexible { display: inline-flex; align-items: center; gap: 0.45rem; font-weight: 600; color: var(--nxt-text); }
.nxt-result-card__flexible .bi { color: var(--nxt-blue); }
.nxt-result-card__meta { margin-top: 0.55rem; font-size: 0.84rem; color: var(--nxt-text-muted); line-height: 1.5; }
.nxt-result-card__meta strong { color: var(--nxt-text); }

/* Result cards that opt in with --compact (gili, stmartin, seychelles, fiji): seat
   name and notes as separate, spaced items in the meta line; a route line there
   duplicates the stop names, so it only shows on phones where those are hidden.
   Origin/destination under the times get more weight. */
.nxt-result-card__meta--split { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 1.25rem; row-gap: 0.15rem; }
.nxt-result-card__meta--split .nxt-result-card__seat { color: var(--nxt-text); }
/* Fiji sells the same boat in very different classes (Captain's Lounge vs
   Standard Economy), so the seat type is what tells two cards apart there. */
body.site-fijibookings .nxt-result-card__meta--split .nxt-result-card__seat { font-weight: 700; }

.nxt-result-card__meta .nxt-result-card__route {
    display: none;
}
.nxt-result-card__meta--split .nxt-result-card__departure { flex-basis: 100%; }
/* portLabel(..., true) marks the main location in "Departure from Main: point".
   Desktop shows it under the departure time already, so keep only the point
   there - and drop the line altogether when it would only repeat the main
   location. Phones hide the names under the times, so they keep it in full. */
@media (min-width: 768px) {
  .nxt-result-card--compact .port-label__main { display: none; }
  .nxt-result-card--compact .nxt-result-card__departure:has(.port-label__main--only) { display: none; }
}
.nxt-result-card--compact .nxt-result-card__place { font-size: 0.95rem; font-weight: 600; color: var(--nxt-text); max-width: 260px; }
@media (max-width: 767.98px) {
  .nxt-result-card__meta--split .nxt-result-card__route { display: inline; font-weight: 600; color: var(--nxt-text); }

    .nxt-result-card__meta:not(.nxt-result-card__meta--split) .nxt-result-card__route {
        display: block;
        font-weight: 600;
        color: var(--nxt-text);
    }

    /* The seat type starts its own line on phones; desktop keeps the one-line meta. */
    .nxt-result-card__meta--split .nxt-result-card__seat {
        flex-basis: 100%;
    }

    .nxt-result-card__meta:not(.nxt-result-card__meta--split) .nxt-result-card__seat::before {
        content: "\A";
        white-space: pre;
    }

    .nxt-result-card__meta .nxt-result-card__sep {
        display: none;
    }
}

/* Pickup/drop-off points behind the "i" on a result card. A native <details>,
   so it needs no JavaScript and keeps keyboard focus of its own; these rules
   only stop it behaving like the block element it is by default. */
.port-info { display: inline-block; position: relative; vertical-align: baseline; }
.port-info__toggle {
  display: inline;
  list-style: none;
  cursor: pointer;
  color: var(--nxt-blue);
  font-size: 0.95em;
  line-height: 1;
  margin-left: 0.25rem;
}
.port-info__toggle::-webkit-details-marker { display: none; }
.port-info__toggle:focus-visible { outline: 2px solid var(--nxt-blue); outline-offset: 2px; }
.port-info__list {
  position: absolute;
  z-index: 20;
  left: 0;
  top: 1.5em;
  min-width: 15rem;
  max-width: min(22rem, 80vw);
  margin: 0;
  padding: 0.5rem 0.75rem;
  list-style: none;
  text-align: left;
  background: var(--nxt-surface, #fff);
  border: 1px solid var(--nxt-border, #d7dde5);
  border-radius: 0.4rem;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);
}
.port-info__list li { padding: 0.15rem 0; }
.port-info__list a { margin-left: 0.35rem; white-space: nowrap; }

@media (max-width: 575.98px) {
  /* No room to float a panel beside a narrow card - let it push the card open. */
  .port-info__list { position: static; max-width: none; box-shadow: none; margin-top: 0.35rem; }
}

.nxt-result-card__cta { flex: 0 0 auto; margin-left: auto; text-align: right; min-width: 128px; }
.search_result.nxt-result-card .nxt-result-card__price .price {
  display: block;
  color: var(--nxt-blue);
  font-size: 1.45rem;
  font-weight: 700;
  line-height: 1.2;
}
.nxt-result-card__price .approx-price { display: block; font-size: 0.8rem; color: var(--nxt-text-muted); }
.nxt-result-card__cta .custom-time { margin-top: 0.5rem; }
.nxt-result-card__cta .book-button { margin-top: 0.55rem; }

/* Below md the card becomes a stacked, centred "ticket": logo on its own row,
   departure/arrival sit side-by-side with the duration badge between them
   (the port name is dropped here since it's already covered by the meta line
   below), and price + Select share one row at the bottom. */
@media (max-width: 767.98px) {
  .search_result.nxt-result-card {
    flex-direction: column;
    justify-content: center;
    text-align: center;
    padding: 1.5rem 1.25rem;
    border-radius: 16px;
  }

  .nxt-result-card__logo {
    width: 100%;
  }

  .search_result.nxt-result-card .nxt-result-card__logo img {
    max-width: 130px;
    margin: 0 auto;
  }

  .nxt-result-card__body {
    flex-basis: 100%;
    width: 100%;
  }
  .nxt-result-card__head { justify-content: center; }

  .nxt-result-card__journey {
    flex-direction: row;
    justify-content: center;
    align-items: center;
    gap: 0.85rem;
  }
  .nxt-result-card__stop,
  .nxt-result-card__stop--arr {
    align-items: center;
    text-align: center;
    width: auto;
    min-width: 0;
  }

  .nxt-result-card__place {
    display: none;
  }
  .nxt-result-card__conn { flex: 0 0 auto; width: auto; min-width: 0; }
  .nxt-result-card__track { display: none; }
  .nxt-result-card__return {
    align-items: center;
    width: 100%;
    border-left: 0;
    padding-left: 0;
    margin-left: 0;
    border-top: 1px solid var(--nxt-border);
    padding-top: 0.4rem;
    margin-top: 0.4rem;
  }

  .nxt-result-card__meta {
    text-align: center;
  }

  .nxt-result-card__cta {
    width: 100%;
    margin: 0.75rem 0 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 0.75rem;
    text-align: left;
  }

  .nxt-result-card__cta .nxt-result-card__price {
    text-align: left;
  }

  .nxt-result-card__cta .custom-time {
    flex: 1 1 100%;
    order: 3;
    margin-top: 0;
  }

  /* nxt-search.js relocates select.custom-time to sit right after the logo on
     mobile, making it a direct child of the card instead of the CTA column. */
  .search_result.nxt-result-card > select.custom-time {
    display: block;
    width: 100%;
    max-width: 220px;
    margin: 0 auto;
  }
  .search_result.nxt-result-card > .error {
    width: 100%;
  }

  .nxt-result-card__cta .book-button {
    margin-top: 0;
  }
}

/* --compact cards put the operator logo top-right beside the text on phones
   (below); on desktop only the round-trip (--select) cards move it, into the
   right-hand column above the price. The one-way desktop card keeps it on the
   left. Grid areas move it without touching the markup, where the logo comes first. */
.search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__logo { grid-area: logo; }
.search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__body { grid-area: body; }
.search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__cta { grid-area: cta; }
@media (min-width: 768px) {
  .search_result.nxt-result-card.nxt-result-card--compact.nxt-result-card--select {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "body logo" "body cta";
    align-items: start;
    column-gap: 1.25rem;
    row-gap: 0.4rem;
  }
  .search_result.nxt-result-card.nxt-result-card--compact.nxt-result-card--select .nxt-result-card__logo { justify-self: end; text-align: right; }
  .search_result.nxt-result-card.nxt-result-card--compact.nxt-result-card--select .nxt-result-card__logo img { max-height: 48px; width: auto; }
  .search_result.nxt-result-card.nxt-result-card--compact.nxt-result-card--select .nxt-result-card__cta { margin-left: 0; }
}

/* --compact results on phones (one-way and both round-trip panels): a compact card
   (small logo top-right, left-aligned text, price + Book/Select on one row) so
   several results fit on a screen instead of two. Overrides the stacked mobile
   card above; the #resultsMoreBoats rules below need their own ID-scoped copies. */
@media (max-width: 767.98px) {
  .search_result.nxt-result-card.nxt-result-card--compact {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 48px;
    grid-template-areas: "body logo" "cta cta";
    column-gap: 0.75rem;
    row-gap: 0.4rem;
    align-items: start;
    text-align: left;
    padding: 0.7rem 0.85rem;
    margin-bottom: 0.6rem;
    border-radius: 12px;
  }
  .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__logo { width: 48px; justify-self: end; }
  .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__logo img { max-width: 48px; margin: 0; }
  .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__head { justify-content: flex-start; margin-bottom: 0.2rem; }
  .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__operator { font-size: 0.95rem; }
  .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__journey { justify-content: flex-start; flex-wrap: wrap; gap: 0.2rem 0.6rem; }
  .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__stop,
  .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__stop--arr { align-items: flex-start; text-align: left; }
  .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__label { display: none; }
  .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__time { font-size: 1.1rem; }
  .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__return { align-items: flex-start; flex-direction: row; gap: 0.5rem; padding-top: 0.25rem; margin-top: 0.2rem; }
  .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__return .nxt-result-card__label { display: inline; }
  .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__meta { margin-top: 0.25rem; font-size: 0.8rem; line-height: 1.4; text-align: left; column-gap: 0.9rem; }
  .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__cta {
    margin: 0;
    padding-top: 0.2rem;
  }

    .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__price .price {
        font-size: 1.4rem;
    }
  .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__price { display: flex; align-items: baseline; gap: 0.4rem; flex-wrap: wrap; }
  .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__price .approx-price { display: inline; }
  .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__cta .page-button span { padding: 6px 18px; }
  .search_result.nxt-result-card.nxt-result-card--compact > select.custom-time,
  .search_result.nxt-result-card.nxt-result-card--compact > .error { grid-column: 1 / -1; }
}

/* ---------- Round-trip select cards (fastboat-more.phtml) ----------
 * Two panels (Select Departure | Select Return); one card is chosen from each,
 * then the bottom .bookcontainer shows the total. Same card look, with a
 * "from" price label and an outlined Select button that fills when active. */
.nxt-result-card__from { display: block; font-size: 0.72rem; color: var(--nxt-text-muted); }
.search_result.nxt-result-card .select.page-button {
  display: inline-grid;
  justify-items: center;
  float: none;
  margin: 0.5rem 0 0;
  padding: 0.2rem 0.4rem;
  border: 1px solid var(--nxt-blue);
  border-radius: var(--nxt-radius);
  background: #eaf6fc;
  color: var(--nxt-blue);
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  transition: background 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
}
.search_result.nxt-result-card .select.page-button span { color: inherit; }
/* "select" and "✓ selected" share one width, so picking a card doesn't shift the
   price column: an invisible zero-height copy of the wider label sits in the same
   grid cell as the real one. Horizontal padding lives on the button, not the span. */
.search_result.nxt-result-card .nxt-result-card__cta .select.page-button span,
.search_result.nxt-result-card .select.page-button::after { grid-area: 1 / 1; padding-left: 0; padding-right: 0; }
.search_result.nxt-result-card .select.page-button::after {
  content: "\2713\2009\2009selected";
  height: 0;
  overflow: hidden;
  visibility: hidden;
  font-weight: 700;
}
.search_result.nxt-result-card .select.page-button:hover { background: #eaf6fc; }
.search_result.nxt-result-card .select.page-button.emphasize { background: var(--nxt-blue); color: #fff; }
/* Checkmark on the selected button (JS sets the span text to "selected"). */
.search_result.nxt-result-card .select.page-button.emphasize span::before {
  content: "\2713";
  margin-right: 0.25rem;
  font-weight: 700;
}

/* Highlight the chosen card; mute the ones disabled by the other leg's pick. */
.search_result.nxt-result-card:has(.select.emphasize) {
  border-color: var(--nxt-blue);
  box-shadow: 0 0 0 2px rgba(17, 155, 212, 0.22), var(--nxt-shadow);
}
.search_result.nxt-result-card.disabled { box-shadow: none; }
.search_result.nxt-result-card.disabled .select.page-button { pointer-events: none; }

/* The two panels are narrow, so tighten the card and drop the (redundant with
   the panel header) origin/destination labels. */
#resultsMoreBoats .nxt-result-card { padding: 0.85rem 0.9rem; gap: 0.5rem 0.7rem; }
#resultsMoreBoats .nxt-result-card__logo { width: 64px; }
#resultsMoreBoats .search_result.nxt-result-card .nxt-result-card__logo img { max-width: 64px; }
#resultsMoreBoats .nxt-result-card__body { flex-basis: 190px; }
#resultsMoreBoats .nxt-result-card__place { display: none; }
#resultsMoreBoats .nxt-result-card__time { font-size: 1.15rem; }
#resultsMoreBoats .nxt-result-card__cta { min-width: 96px; }

/* On mobile the round-trip panel is full-width, so let its card stack like the
   one-way cards (logo on top, content centred) instead of keeping the compact
   190px body that leaves the logo stranded on the left. Placed after the
   #resultsMoreBoats rules above so it wins on equal specificity. */
@media (max-width: 767.98px) {
  #resultsMoreBoats .nxt-result-card__body { flex-basis: 100%; }
  #resultsMoreBoats .span6 { padding-left: 0px; padding-right: 0px; }
}

/* --compact round-trip panels: the panel header only names the islands, so show
   the actual ports under the times (same weight as the one-way card); on phones
   the compact card above takes over. */
@media (min-width: 768px) {
  #resultsMoreBoats .nxt-result-card--compact .nxt-result-card__place { display: block; max-width: 140px; }
}
@media (max-width: 767.98px) {
  #resultsMoreBoats .nxt-result-card--compact { padding: 0.7rem 0.85rem; gap: 0.4rem 0.75rem; }
  #resultsMoreBoats .nxt-result-card--compact .nxt-result-card__logo { width: 48px; }
  #resultsMoreBoats .search_result.nxt-result-card--compact .nxt-result-card__logo img { max-width: 48px; }
  #resultsMoreBoats .nxt-result-card--compact .nxt-result-card__time { font-size: 1.1rem; }
  #resultsMoreBoats .nxt-result-card--compact .nxt-result-card__cta { min-width: 0; }
  #resultsMoreBoats .search_result.nxt-result-card--compact .select.page-button { margin: 0; }
}

/* IB-5275 results tweaks, for the gili / seychelles / stmartin cards only. Phones:
   a bigger operator name, more air around the times, less above the price.
   Round-trip panels on desktop: a bigger operator name and the seat name and
   notes stacked one per line (the templates no longer print the boat name). */
@media (max-width: 767.98px) {
  :is(body.site-gilibookings, body.site-seychellesbookings, body.site-stmartinbookings) .search_result.nxt-result-card.nxt-result-card--compact { row-gap: 0.25rem; }
  :is(body.site-gilibookings, body.site-seychellesbookings, body.site-stmartinbookings) .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__operator { font-size: 1rem; }
  :is(body.site-gilibookings, body.site-seychellesbookings, body.site-stmartinbookings) .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__journey { padding: 0.35rem 0; }
  :is(body.site-gilibookings, body.site-seychellesbookings, body.site-stmartinbookings) .search_result.nxt-result-card.nxt-result-card--compact .nxt-result-card__cta { padding-top: 0; }
}
@media (min-width: 768px) {
  :is(body.site-gilibookings, body.site-seychellesbookings, body.site-stmartinbookings) #resultsMoreBoats .nxt-result-card--compact .nxt-result-card__operator { font-size: 1.2rem; }
  :is(body.site-gilibookings, body.site-seychellesbookings, body.site-stmartinbookings) #resultsMoreBoats .nxt-result-card--compact .nxt-result-card__meta--split { flex-direction: column; align-items: flex-start; row-gap: 0.1rem; }
}

/* Final total + Book bar under the return panel — a prominent boxed summary:
   blue-bordered card, total in blue on the left, orange Book button right. */
#resultsMoreBoats .bookcontainer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  margin-top: 1rem;
    margin-bottom: 1rem;
  padding: 0.7rem 0.7rem 0.7rem 1.15rem;
  border: 1px solid var(--nxt-blue);
  border-radius: var(--nxt-radius);
  background: #fff;
  box-shadow: var(--nxt-shadow);
}
#resultsMoreBoats .bookcontainer .price {
  order: -2;
  color: var(--nxt-blue);
  font-weight: 700;
  font-size: 1.4rem;
  line-height: 1.1;
}
#resultsMoreBoats .bookcontainer .bookmessage { order: -1; color: var(--nxt-orange-text); font-size: 0.88rem; }

#resultsMoreBoats .bookcontainer .book {
    float: none;
    margin: 0 0 0 auto;
    padding: 2px;
    min-width: 120px;
    text-align: center;
}
/* Same height as the compact card's select button on phones. */
@media (max-width: 767.98px) {
  #resultsMoreBoats .bookcontainer .book { padding: 0; }
  #resultsMoreBoats .bookcontainer .book span { padding: 4px 18px; }
}
#resultsMoreBoats .bookcontainer .clear { display: none; }

/* The "2 x One Way" warning nxt-scripts.js appends when the two picked legs
   cannot be combined into one round-trip fare (stmartinbookings only, see
   isFeatureEnabled()). It is appended as a flex child of the bar, so without a
   line of its own it sits to the right of the Book button and pushes the row
   out of the card — the wrap above plus the full basis here put it under the
   total and the button. */
#resultsMoreBoats .bookcontainer #roundtrip-alert {
  order: 1;
  flex: 0 0 100%;
  margin: 0;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--nxt-note-border);
  border-radius: var(--nxt-radius-sm);
  background: var(--nxt-note-bg);
  color: var(--nxt-text);
  text-align: left;
}

/* Bottom pagination control (search/pagination.phtml): a centred row of
   .page-button pills (Previous / 1 2 3 / Next); .selected is the current page. */
.paginationControl {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  margin: 1.5rem 0 0.5rem;
}
.paginationControl .page-button { margin: 0; }
.paginationControl .page-button.disabled { opacity: 0.45; pointer-events: none; }
.paginationControl .clear { display: none; }

/* "View more options" (return-trip expander) */
.more-options { text-align: center; margin: 1.25rem 0 0.25rem; }
.more-options .page-button.right { float: none; }

/* ---------- Booking customer form (your-details.phtml) ---------- *
 * Book_Form_Customer renders Bootstrap-2 .form-vertical / .control-group /
 * .controls / .span* markup that nxt never styled, so the inputs showed at
 * their default width with no border. Scope the nxt form-control look to
 * .customer-form so only this form is affected. */
.customer-form {
  margin-left: -0.9rem;
  margin-right: -0.9rem;
}
.customer-form h1 { color: var(--nxt-blue); }
.customer-form .control-group { margin-bottom: 1rem; }
.customer-form .control-label {
  display: block;
  font-weight: 600;
  font-size: 0.9rem;
  margin-bottom: 0.3rem;
  color: var(--nxt-text);
}
.customer-form label.control-label.required::after { content: "\00a0*"; color: #dc3545; }
.customer-form .controls input[type="text"],
.customer-form .controls input[type="email"],
.customer-form .controls input[type="tel"],
.customer-form .controls input[type="number"],
.customer-form .controls input[type="time"],
.customer-form .controls input[type="password"],
.customer-form .controls select,
.customer-form input.span12,
.customer-form select.span12 {
  width: 100%;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
  padding: 0.5rem 0.7rem;
  font-family: var(--nxt-font);
  font-size: 1rem;
  background: #fff;
  box-sizing: border-box;
}
.customer-form .controls input:focus,
.customer-form .controls select:focus {
  border-color: var(--nxt-blue);
  outline: 0;
  box-shadow: 0 0 0 3px rgba(17, 155, 212, 0.12);
}
.customer-form input::placeholder { color: var(--nxt-text-muted); }
.customer-form .passenger-header {
  color: var(--nxt-blue);
  font-size: 1.3rem;
  font-weight: 700;
  margin: 1.5rem 0 0.75rem;
}
.customer-form .passengergroup strong { color: var(--nxt-text); }
.customer-form .customer-phone-info { color: var(--nxt-text-muted); font-size: 0.9rem; }
@media (min-width: 768px) {
  .customer-form .customer-phone-info { padding-top: 2rem; }
}
/* Legacy Bootstrap-2 checkbox: <label class="checkbox"> wraps an
   <input class="checkbox"> + text (pickup/drop-off/"Same as above"). Render it
   as a neat row — a blue, slightly larger box aligned to the first text line,
   with the label text flowing normally (so "(highly recommended)" stays
   inline). Absolute positioning keeps multi-line labels aligned. */
label.checkbox {
  position: relative;
  display: block;
  padding-left: 1.7em;
  cursor: pointer;
  font-weight: 500;
}
label.checkbox input.checkbox,
label.checkbox input[type="checkbox"] {
  position: absolute;
  left: 0;
  top: 0.2em;
  width: 1.15em;
  height: 1.15em;
  margin: 0;
  accent-color: var(--nxt-blue);
  cursor: pointer;
}
.customer-form .orange { color: var(--nxt-orange-text); font-weight: 600; }
.customer-form .pickup-wrapper,
.customer-form .dropoff-wrapper {
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
  padding: 1rem;
  margin: 0.5rem 0 1rem;
  background: #fafafa;
}
/* The pickup/drop-off holder is a legacy .row-fluid (flex + -10px side margins),
   which pulled the checkbox and the expandable box out of line with the form
   fields above. Make it a plain full-width block so both align. */
.customer-form .pickupdropoff-holder {
  display: block;
  margin-left: 0;
  margin-right: 0;
}
/* ---------- Booking form CRO polish ---------- *
 * Chunk each trip's passengers into a clearly separated panel (much easier to
 * scan and fill in on a multi-leg booking), promote the date/route line to a
 * panel header, highlight the optional transfer upsell, and add a trust bar. */
.customer-form .passengers { margin-top: 0.25rem; }
.customer-form .passengergroup-wrapper {
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius);
  padding: 0.9rem 1rem 1.1rem;
  background: #f8fafc;
  margin-top: 1.25rem;
}
.customer-form .passengergroup-wrapper:first-child { margin-top: 0.75rem; }

/* The date + route line becomes the panel header. */
.customer-form .passengergroup {
  margin: 0 0 0.35rem;
  padding-bottom: 0.65rem;
  border-bottom: 1px solid var(--nxt-border);
}
.customer-form .passengergroup strong {
  color: var(--nxt-blue) !important;
  font-size: 1.02rem !important;
  letter-spacing: -0.01em;
}
/* "Adult passengers" drops to a lighter sub-header under the date. */
.customer-form .passengergroup-wrapper .passenger-header {
  font-size: 1rem;
  margin: 0.9rem 0 0.6rem;
}

/* Each passenger's fields (name/nationality/...) render in a .odd/.even
   wrapper (Book_Form_Customer alternates by a running counter). Shade the
   even rows so passenger 1/2/3... are easy to tell apart at a glance instead
   of reading as one long field list. Bleeds to the panel's own padding. */
.customer-form .passengergroup-wrapper > .even {
  background: rgba(15, 23, 42, 0.045);
  border-radius: var(--nxt-radius-sm);
}

.customer-form .passengergroup-wrapper > .odd,
.customer-form .passengergroup-wrapper > .even {
  margin: 0 -1rem;
  padding: 0.5rem 1rem 0.1rem;
}

/* "Same as above" — a compact convenience toggle. */
.customer-form label.checkbox:has(input.copy) {
  display: inline-block;
  background: #eaf5fb;
  border-radius: var(--nxt-radius-sm);
  padding: 0.5rem 0.85rem 0.5rem 2.1rem;
  margin: 0.75rem 0 0;
  font-weight: 600;
  color: var(--nxt-blue);
}
.customer-form label.checkbox:has(input.copy) input.checkbox { left: 0.7rem; top: 0.6rem; }

/* Optional pickup / drop-off transfer — highlight to lift the attach rate. */
.customer-form label.checkbox:has(input.transfer-checkbox) {
  display: block;
  background: var(--nxt-note-bg);
  border: 1px solid var(--nxt-note-border);
  border-radius: var(--nxt-radius-sm);
  padding: 0.7rem 0.95rem 0.7rem 2.5rem;
  margin: 0.75rem 0 0.25rem;
  font-weight: 600;
}
.customer-form label.checkbox:has(input.transfer-checkbox) input.checkbox { left: 0.95rem; top: 0.9rem; }

/* Trust bar shown just above the booking CTA. */
.customer-form-trust {
  font-size: 0.85rem;
  color: var(--nxt-text-muted);
  row-gap: 0.4rem;
}
.customer-form-trust span { display: inline-flex; align-items: center; gap: 0.4rem; }
.customer-form-trust i { color: var(--nxt-blue); font-size: 1.05rem; }

/* Let each passenger row's fields grow to fill the panel width on desktop
   (name span5 + nationality span3 left a third of the row empty and truncated
   the nationality dropdown). flex-grow keeps their ratio and still fits the
   occasional 3-field passport/DOB rows without wrapping; mobile stays stacked. */
@media (min-width: 768px) {
  .customer-form .passenger-info [class*="span"] { flex-grow: 1; max-width: none; }
}

/* ---------- "Protect your booking" / CFAR opt-in (flex/index/option.phtml) ---------- *
 * A card, not a checkbox row: this is a paid add-on sold on its own merits, so
 * it gets a heading, a Recommended flag, a benefit list and — when the customer
 * switches it off — an explicit warning that the cover cannot be bought later.
 *
 * Both states are server-rendered (the switch re-posts the step), so the "off"
 * look is a modifier class rather than a :has() rule. The :has() below is only
 * belt-and-braces for the instant between the click and the reload.
 *
 * Colours come from the tokens, never from the mockup's raw #119bd4/#ef9023 —
 * those are the pre-accessibility brand values this theme deliberately darkened
 * (see :root). Orange is a fill or --nxt-orange-text as text, never brand orange
 * on a light background. */
.flex-cancellation-heading {
  font-size: 1.35rem;
  margin-bottom: 1rem;
}

.flex-cancellation-option {
  position: relative;
  border: 2px solid var(--nxt-blue-button);
  border-radius: var(--nxt-radius);
  background: #f8fbfe;
  padding: 1.1rem 1.15rem;
  transition: border-color .15s ease, background .15s ease;
}
/* declined: the card recedes to a plain panel so the eye moves on */
.flex-cancellation-option--off,
.flex-cancellation-option:has(.form-check-input:not(:checked)) {
  border: 1px solid var(--nxt-border);
  background: #fafafa;
}

/* The flag overhangs the top border, so it needs the card's own padding as its
   left offset and half its own height as the negative top. */
.flex-cancellation-option__badge {
  position: absolute;
  top: -0.7rem;
  left: 1.15rem;
  /* --nxt-orange as a fill under white text is only 2.8:1, and at 0.7rem this
     is small text needing 4.5:1. --nxt-orange-text is the theme's darkened
     orange; as a FILL it carries white at 5.5:1. */
  background: var(--nxt-orange-text);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: .02em;
  padding: 0.15rem 0.65rem;
  border-radius: 999px;
}

.flex-cancellation-option__head {
  display: flex;
  align-items: flex-start;
  gap: 0.8rem;
}
.flex-cancellation-option__icon {
  flex: 0 0 auto;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: var(--nxt-radius-sm);
  background: #eaf6fc;
  color: var(--nxt-blue);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.3rem;
  margin-top: 0.1rem;
}
.flex-cancellation-option--off .flex-cancellation-option__icon {
  background: #eef0f2;
  color: var(--nxt-text-muted);
}
.flex-cancellation-option__text { flex: 1 1 auto; min-width: 0; }
.flex-cancellation-option__title {
  font-weight: 700;
  color: var(--nxt-text);
  margin-bottom: 0.15rem;
}
.flex-cancellation-option__sub {
  font-size: 0.85rem;
  color: var(--nxt-text-muted);
}
.flex-cancellation-option__aside {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.5rem;
}
.flex-cancellation-option__price {
  font-weight: 700;
  color: var(--nxt-blue);
  white-space: nowrap;
}
.flex-cancellation-option--off .flex-cancellation-option__price { color: var(--nxt-text-muted); }

/* Two columns on anything wider than a phone; one below, where two 12px columns
   would wrap mid-phrase and read worse than a plain list. */
.flex-cancellation-option__benefits {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.45rem 1.25rem;
  margin: 1rem 0 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 576px) {
  .flex-cancellation-option__benefits { grid-template-columns: 1fr 1fr; }
}
.flex-cancellation-option__benefits li {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8rem;
  color: var(--nxt-text-muted);
}
.flex-cancellation-option__benefits i {
  flex: 0 0 auto;
  font-size: 0.95rem;
  color: var(--nxt-blue);
}

.flex-cancellation-option__terms {
  margin: 0.9rem 0 0;
  font-size: 0.75rem;
  color: var(--nxt-text-muted);
}

/* The consequence of switching it off, in the amber the theme already uses for
   "read this before you continue" (.nxt-note). */
.flex-cancellation-warning {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.6rem;
  padding: 0.7rem 1rem;
  border: 1px solid var(--nxt-note-border);
  border-radius: var(--nxt-radius-sm);
  background: var(--nxt-note-bg);
  font-size: 0.85rem;
  color: #6b5a20;
}
.flex-cancellation-warning i {
  flex: 0 0 auto;
  font-size: 1rem;
  color: var(--nxt-orange-text);
}

/* A bigger switch than Bootstrap's 2em default: it opts the customer into a
 * paid add-on, so it has to read as a deliberate choice rather than fine print.
 *
 * Bootstrap sizes the switch in `em` off the input, but pairs it with a
 * padding-left on .form-switch and an equal negative margin-left on the input
 * to hang it in that gutter. Both numbers must move together, or the thumb
 * drifts out of the label's text column -- hence the shared 3.5rem below. */
.flex-cancellation-option .form-switch {
  padding-left: 3.5rem;
  min-height: 2rem;
  margin-bottom: 0;
}
.flex-cancellation-option .form-switch .form-check-input {
  width: 2.75rem;
  height: 1.5rem;
  margin-top: 0;
  margin-left: -3.5rem;
  cursor: pointer;
}
/* on-state in the theme's blue rather than Bootstrap's #0d6efd */
.flex-cancellation-option .form-check-input:checked {
  background-color: var(--nxt-blue-button);
  border-color: var(--nxt-blue-button);
}
.flex-cancellation-option .form-check-input:focus {
  border-color: var(--nxt-blue-button);
  box-shadow: 0 0 0 0.2rem rgba(10, 110, 160, 0.25);
}
.flex-cancellation-option .form-check-label { cursor: pointer; }

/* Stack the price/switch under the text on a phone, where three columns leave
   the promise sentence two words wide. */
@media (max-width: 575.98px) {
  .flex-cancellation-option__head { flex-wrap: wrap; }
  .flex-cancellation-option__aside {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    margin-top: 0.5rem;
  }
}

/* ---------- Payment page (payment.phtml) ---------- *
 * Selectable payment-method rows with clear hover + selected states, a larger
 * accent radio and evenly sized logos, a security-reassurance line above the
 * pay button, and a de-emphasised footer for the secondary actions. */
.payment-methods { display: flex; flex-direction: column; gap: 0.6rem; }
.payment-method-option {
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
  padding: 0.9rem 1.1rem;
  margin: 0;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
}
.payment-method-option:hover { border-color: var(--nxt-blue-button); background: #f8fbfe; }
.payment-method-option.selected {
  border-color: var(--nxt-blue-button);
  background: #eaf6fc;
  box-shadow: 0 0 0 3px rgba(17, 155, 212, 0.12);
}
.payment-method-option input[type="radio"] {
  width: 1.15em;
  height: 1.15em;
  accent-color: var(--nxt-blue-button);
  cursor: pointer;
  flex-shrink: 0;
}
.payment-logo { height: 30px; width: auto; margin: 0; }

/* Card-brand sub-choice. A SIBLING of .payment-method-option, not a child: that row is a
   <label> and nested <label>s are invalid HTML, so the brand radios cannot live inside it. */
.payment-brands {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  margin: -0.2rem 0 0.2rem;
  padding: 0 1.1rem;
}
.payment-brands__hint { width: 100%; color: #6c757d; font-size: 0.85rem; }
.payment-brand-option {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  padding: 0.3rem 0.5rem;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
  cursor: pointer;
}
.payment-brand-option:has(input:checked) {
  border-color: var(--nxt-blue-button);
  background: #eaf6fc;
}
.payment-brand-option input[type="radio"] {
  width: 1.05em;
  height: 1.05em;
  accent-color: var(--nxt-blue-button);
  cursor: pointer;
  flex-shrink: 0;
}
.payment-brands .payment-logo { height: 26px; width: auto; }

.payment-secure {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  font-size: 0.9rem;
  color: var(--nxt-text-muted);
}
.payment-secure i { color: var(--nxt-blue); font-size: 1.15rem; line-height: 1.4; }

.payment-footer { border-top: 1px solid var(--nxt-border); }
.payment-footer a.ajax-dialog { color: var(--nxt-blue); }

/* Full-screen loading overlay for the confirm -> payment step (initialising the
   payment providers can take a few seconds). .submit-with-loader adds .show to
   #loader on click; the nxt theme never styled it, so nothing was visible. */
#loader { display: none; }
#loader.show {
  display: flex;
  align-items: center;
  justify-content: center;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 2000;
  background: rgba(255, 255, 255, 0.72);
  backdrop-filter: blur(2px);
}
.nxt-loader-box { display: flex; flex-direction: column; align-items: center; gap: 1rem; }
.nxt-loader-spinner {
  width: 3rem;
  height: 3rem;
  border: 4px solid rgba(5, 163, 228, 0.2);
  border-top-color: var(--nxt-blue-button, #05a3e4);
  border-radius: 50%;
  animation: nxt-spin 0.8s linear infinite;
}
.nxt-loader-text { color: var(--nxt-text); font-weight: 600; font-size: 1rem; }
@keyframes nxt-spin { to { transform: rotate(360deg); } }

/* ---------- Legacy Zend forms (login / account / admin back-office) ---------- *
 * Every Twm/Twitter form (Twitter_Form) renders Bootstrap-2 markup — a
 * <form class="form-vertical"> with .control-group / .control-label / .controls
 * wrappers and BARE <input>/<select> elements (no .form-control). Bootstrap 5
 * styles none of those, so the fields showed as raw browser inputs on the
 * login page and across every admin form (see "Add location"). Give them the
 * nxt field look here, scoped to .form-vertical: the bespoke .search_form /
 * homepage forms set their own form type (not "vertical") so they are left
 * alone, and .form-horizontal admin forms keep their inline layout. */
.form-vertical fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }
.form-vertical .control-group { margin-bottom: 1.1rem; }
.form-vertical .control-group:last-child { margin-bottom: 0; }
.form-vertical .control-label {
  display: block;
  font-weight: 600;
  font-size: 0.9rem;
  margin-bottom: 0.35rem;
  color: var(--nxt-text);
}

form .control-group.error span.help-block {
  color: #dc3545;
}
.form-vertical label.control-label.required::after { content: "\00a0*"; color: #dc3545; }
.form-vertical .controls input[type="text"],
.form-vertical .controls input[type="email"],
.form-vertical .controls input[type="tel"],
.form-vertical .controls input[type="url"],
.form-vertical .controls input[type="number"],
.form-vertical .controls input[type="search"],
.form-vertical .controls input[type="date"],
.form-vertical .controls input[type="time"],
.form-vertical .controls input[type="password"],
.form-vertical .controls select,
.form-vertical .controls textarea {
  width: 100%;
  max-width: 30rem;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
  padding: 0.55rem 0.75rem;
  font-family: var(--nxt-font);
  font-size: 1rem;
  line-height: 1.4;
  color: var(--nxt-text);
  background: #fff;
  box-sizing: border-box;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.form-vertical .controls textarea { max-width: none; min-height: 6rem; }
.form-vertical .controls input:focus,
.form-vertical .controls select:focus,
.form-vertical .controls textarea:focus {
  border-color: var(--nxt-blue);
  outline: 0;
  box-shadow: 0 0 0 3px rgba(17, 155, 212, 0.12);
}
.form-vertical .controls input::placeholder,
.form-vertical .controls textarea::placeholder { color: var(--nxt-text-muted); }
/* Radios/checkboxes rendered inline (e.g. "Island hopping: None / From / To").
   The wrapped <label class="checkbox"> variant is already handled globally. */
.form-vertical input[type="checkbox"],
.form-vertical input[type="radio"] { accent-color: var(--nxt-blue); }
.form-vertical label.radio {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  margin-right: 1rem;
  font-weight: 500;
  cursor: pointer;
}
/* Help text + inline validation errors (Description / Bootstraperrors decorators
   both emit <span class="help-block">; the error variant adds .error to the
   surrounding .control-group). */
.form-vertical .help-block {
  display: block;
  font-size: 0.85rem;
  color: var(--nxt-text-muted);
  margin-top: 0.3rem;
}
.form-vertical .control-group.error .help-block { color: #dc3545; }
.form-vertical .control-group.error .controls input,
.form-vertical .control-group.error .controls select,
.form-vertical .control-group.error .controls textarea { border-color: #dc3545; }
/* Legacy submit button <input type="submit" class="submit"> → nxt primary. */
.form-vertical .control-group:has(> .controls > input[type="submit"]),
.form-vertical .control-group:has(> .controls > input.submit) { margin-top: 1.4rem; }
.form-vertical input[type="submit"],
.form-vertical input.submit,
.form-vertical button[type="submit"]:not([class*="btn"]) {
  display: inline-block;
  width: auto;
  background: var(--nxt-blue-button);
  background: linear-gradient(var(--nxt-blue-button-light), var(--nxt-blue-button));
  border: 1px solid var(--nxt-blue-button);
  color: #fff;
  border-radius: var(--nxt-radius-sm);
  font-family: var(--nxt-font);
  font-weight: 600;
  font-size: 1rem;
  padding: 0.6rem 1.9rem;
  cursor: pointer;
  transition: filter 0.15s ease, background 0.15s ease;
}
.form-vertical input[type="submit"]:hover,
.form-vertical input.submit:hover,
.form-vertical button[type="submit"]:not([class*="btn"]):hover { background: var(--nxt-blue-button); filter: brightness(1.05); }
.form-vertical input[type="submit"]:focus-visible,
.form-vertical input.submit:focus-visible { outline: 2px solid var(--nxt-blue-dark); outline-offset: 2px; }
/* The booking customer form is the one multi-column .form-vertical: let its
   full-width (.span12) fields fill the row instead of the 30rem single-column
   cap above. Selector is deliberately more specific than the base rule so it
   wins the max-width without !important. */
.customer-form form.form-vertical .controls input,
.customer-form form.form-vertical .controls select { max-width: none; }

/* Book_Form_Customer wraps almost every field in its own span5/span3/span6
   grid cell (email, phone, name, nationality, DOB, ...), so each field's
   .control-group is the *only* child of that cell and therefore matches
   .form-vertical .control-group:last-child above — a rule meant to remove
   the trailing gap after the final field in ordinary single-column forms.
   Here it strips the gap between almost every field instead (worst on
   mobile, where the grid cells stack), while the handful of fields that
   share a wrapper (e.g. pickup name/address/phone) keep their normal
   margin — hence the cramped, inconsistent spacing. Restore it. */
.customer-form form.form-vertical .control-group:last-child {
  margin-bottom: 1.1rem;
}

/* ---------- Activity-list filters (activity-list.phtml) ---------- *
 * Stack the label above a select-styled dropdown instead of the plain small
 * outline buttons. Unselected "Select a …" dropdown-toggles get the select
 * look; applied facets render as .nxt-filter-chip removable pills. */
.filters .btn-group.dropdown { flex-direction: column; align-items: stretch; }
.filters .form-label { color: var(--nxt-text); }
.filters .dropdown-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  min-width: 190px;
  padding: 0.5rem 0.75rem;
  background: #fff;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
  color: var(--nxt-text);
  font-weight: 500;
  text-align: left;
}
.filters .dropdown-toggle:hover,
.filters .dropdown-toggle:focus {
  background: #fff;
  border-color: var(--nxt-blue);
  color: var(--nxt-text);
}
/* Bootstrap squares the toggle's left corners because it follows the <label>
   inside the same .btn-group (.btn-group > :not(.btn-check) + .btn, 0,3,0).
   Restore the full rounded rectangle with a higher-specificity selector. */
.filters .btn-group.dropdown .dropdown-toggle { border-radius: var(--nxt-radius-sm); }

/* Map view: nxt outline button sized to bottom-align with the toggles. */
.filters .btn-nxt-outline {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 42px;
  padding: 0.5rem 0.9rem;
}

/* Applied-filter chip: a removable pill that replaces the "Select a …"
   dropdown once a facet is active. Solid nxt-blue signals "applied"; the
   trailing × in its own circle is the remove affordance. Sized to bottom-align
   with the sibling dropdown-toggles in the same filter row. */
.filters .nxt-filter-chip {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: 0.5rem;
  min-height: 42px;
  padding: 0.4rem 0.5rem 0.4rem 0.9rem;
  background: var(--nxt-blue-button);
  border: 1px solid var(--nxt-blue-button);
  border-radius: 999px;
  color: #fff;
  font-weight: 600;
  font-size: 0.9rem;
  line-height: 1.2;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}
.filters .nxt-filter-chip:hover,
.filters .nxt-filter-chip:focus {
  color: #fff;
  background: var(--nxt-blue-dark);
  border-color: var(--nxt-blue-dark);
}
.filters .nxt-filter-chip .chip-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.2rem;
  height: 1.2rem;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.22);
  font-size: 0.7rem;
  line-height: 1;
  transition: background-color 0.15s ease;
}
.filters .nxt-filter-chip:hover .chip-remove,
.filters .nxt-filter-chip:focus .chip-remove {
  background: rgba(255, 255, 255, 0.4);
}

/* ---------- Buttons (new BS5 markup) ---------- */
.btn-nxt-primary {
  background: var(--nxt-blue-button);
  background: linear-gradient(var(--nxt-blue-button-light), var(--nxt-blue-button));
  border: 1px solid var(--nxt-blue-button);
  color: #fff;
  border-radius: var(--nxt-radius-sm);
  font-weight: 600;
}
.btn-nxt-primary:hover, .btn-nxt-primary:focus { color: #fff; background: var(--nxt-blue-button); }
.btn-nxt-orange {
  background: var(--nxt-orange-light);
  background: linear-gradient(to bottom, var(--nxt-orange-light), var(--nxt-orange));
  border: 1px solid var(--nxt-orange);
  color: #fff;
  border-radius: var(--nxt-radius-sm);
  font-weight: 700;
  padding: 0.75rem 1.25rem;
}
.btn-nxt-orange:hover, .btn-nxt-orange:focus { color: #fff; background: var(--nxt-orange); }
/* Primary checkout CTA next to smaller secondary buttons (your-details, confirm). */
.btn-nxt-orange.btn-nxt-orange--wide { padding-left: 4.5rem; padding-right: 4.5rem; }
.btn-nxt-outline {
  background: #fff;
  border: 1px solid var(--nxt-blue);
  color: var(--nxt-blue);
  border-radius: var(--nxt-radius-sm);
  font-weight: 600;
}
.btn-nxt-outline:hover, .btn-nxt-outline:focus {
  background: var(--nxt-blue-button);
  border-color: var(--nxt-blue-button);
  color: #fff;
}

/* ---------- Breadcrumb ---------- */
.nxt-breadcrumb {
  background: #f4f6f8;
  border-radius: var(--nxt-radius-sm);
  padding: 0.6rem 1rem;
  font-size: 0.9rem;
  color: var(--nxt-text-muted);
}
/* Underlined so breadcrumb links are distinguishable without relying on colour
   alone (WCAG 1.4.1 / axe link-in-text-block). */
.nxt-breadcrumb a { color: var(--nxt-blue); text-decoration: underline; }
.nxt-breadcrumb a:hover { text-decoration: underline; }
.nxt-breadcrumb .divider { color: #b0b8c0; margin: 0 0.35rem; }

/* ---------- Cards ---------- */
.nxt-card {
  background: #fff;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius);
  box-shadow: var(--nxt-shadow);
  padding: 1.25rem;
}

.nxt-booking-card h4 { margin-bottom: 0.15rem; }
.nxt-booking-card .subtitle { color: var(--nxt-text-muted); font-size: 0.85rem; margin-bottom: 1rem; }
.nxt-booking-card .btn-nxt-orange { width: 100%; text-align: center; margin-bottom: 1rem; }
.nxt-booking-highlights { list-style: none; padding: 0; margin: 0 0 1rem; }
.nxt-booking-highlights li { display: flex; align-items: flex-start; gap: 0.5rem; padding: 0.3rem 0; color: var(--nxt-text); font-size: 0.92rem; }
.nxt-booking-highlights li i { color: var(--nxt-blue-button); margin-top: 0.2rem; }

.nxt-note {
  background: var(--nxt-note-bg);
  border: 1px solid var(--nxt-note-border);
  border-radius: var(--nxt-radius-sm);
  padding: 0.85rem 1rem;
  font-size: 0.85rem;
  color: #6b5a20;
}
.nxt-note strong { color: #4a3d10; }

/* Cart / order overview summary table (book/index your-booking.phtml partial).
   Wraps the "Your boats/Price" header band and the "Total payment required"
   footer band in one rounded card so both read as encapsulated, contained
   sections instead of bleeding to the viewport edge; overflow-y stays hidden
   (the table never scrolls vertically) purely so the rounded corners clip the
   table-light row backgrounds, while overflow-x:auto keeps horizontal scroll
   available if a row's content ever overruns on narrow screens. */
.cart-summary {
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius);
  background: #fff;
  overflow-x: auto;
  overflow-y: hidden;
}
.cart_table > :not(caption) > * > * {
  padding: 0.75rem 1rem;
}
/* Merge the last item row -> Total -> Admin fee into one seamless block by
   dropping the two dividers between them; the line above "Total payment
   required" is kept so that footer band still reads as its own section.
   The Total/Admin-fee/discount/footer rows live in an explicit
   tbody.cart-summary-rows (see the partial) specifically so this :has()
   selector can reliably find "the item tbody right before it" — without
   that explicit tbody, stray <tr>s get auto-wrapped by the browser into
   their own implicit tbody, which silently breaks tbody:last-of-type. */
.cart_table tbody:has(+ tbody.cart-summary-rows) tr:last-child > td,
.cart_table tr.cart-total-row > th {
  border-bottom: none;
}

.nxt-summary-card dl { margin: 0; }
.nxt-summary-card .summary-row {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--nxt-border);
}
.nxt-summary-card .summary-row:last-child { border-bottom: none; }
.nxt-summary-card .summary-icon {
  flex: 0 0 36px;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: #eaf6fc;
  color: var(--nxt-blue-button);
  display: flex;
  align-items: center;
  justify-content: center;
}
.nxt-summary-card dt { font-weight: 700; font-size: 0.9rem; color: var(--nxt-text); }
.nxt-summary-card dd { margin: 0; color: var(--nxt-text-muted); font-size: 0.9rem; }

/* ---------- Blog list (blog/index.phtml) ----------
 * The blog index was the last public page in this theme still rendering as
 * unstyled rows: a raw <img> beside a wall of excerpt text, nothing separating
 * one post from the next. Keep the horizontal row — a post gets far more room
 * for its teaser than a grid tile does — but give each one the theme's card
 * treatment and the hover lift from .nxt-result-card. The thumbnail gets a
 * fixed 16:9 box because editors upload anything from a 4:3 phone photo to a
 * panorama, and without it every row starts at a different height. */
.nxt-blog-list {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}
.nxt-blog-card {
  display: flex;
  align-items: flex-start;
  gap: 1.25rem;
  transition: box-shadow 0.18s ease, transform 0.18s ease, border-color 0.18s ease;
}
.nxt-blog-card:hover {
  box-shadow: 0 6px 22px rgba(17, 24, 39, 0.12);
  border-color: #cfe8f5;
  transform: translateY(-2px);
}
.nxt-blog-card__thumb {
  display: block;
  flex: 0 0 260px;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: var(--nxt-radius-sm);
  background: #eef2f6;
}
.nxt-blog-card__thumb img { width: 100%; height: 100%; object-fit: cover; }
/* Posts without a thumbnail keep the box (and its placeholder glyph) so their
   text column still starts on the same line as every other row's. */
.nxt-blog-card__thumb--empty {
  display: flex;
  align-items: center;
  justify-content: center;
  color: #b7c2cd;
  font-size: 2rem;
}
.nxt-blog-card__body { flex: 1 1 auto; min-width: 0; }
/* Underline on hover only: a permanently underlined title would make the row
   read as a block of link text rather than a heading. */
.nxt-blog-card__title { margin-bottom: 0.35rem; }
.nxt-blog-card__title a { color: var(--nxt-blue); text-decoration: none; }
.nxt-blog-card__title a:hover { color: var(--nxt-blue-dark); text-decoration: underline; }
.nxt-blog-card__date {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin-bottom: 0.6rem;
  font-size: 0.82rem;
  color: var(--nxt-text-muted);
}
.nxt-blog-card__excerpt {
  margin-bottom: 1rem;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--nxt-text-muted);
}
/* Below md the two columns stop paying for themselves — shrinking the
   thumbnail to fit leaves a teaser about seven words wide and a very tall row —
   so stack instead, which is the split the markup always had (col-md-3 /
   col-md-9). The height cap keeps a full-width 16:9 thumbnail from taking over
   the screen on a phone. */
@media (max-width: 767.98px) {
  .nxt-blog-card { flex-direction: column; }
  .nxt-blog-card__thumb { flex: 0 0 auto; width: 100%; max-height: 220px; }
}

/* ---------- Blog post (blog/view.phtml) ----------
 * The post body sits in the same .nxt-card + .cmscontent wrapper every other
 * editor-authored page uses, so it picks up the theme's table/image treatment.
 * Title + date on the left of the header, compact share row on the right. */
.blog-post-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.25rem;
}
.blog-post-header__text { flex: 1 1 320px; min-width: 0; }
.blog-post-header h1 { margin-bottom: 0.35rem; }
.blog-post-date {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin: 0;
  font-size: 0.85rem;
  color: var(--nxt-text-muted);
}
.blog-post-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

/* The sidebar an editor puts beside a post body ("About the author", promo
   links) is plain gridcontent markup — a narrow column following the wide one —
   so there is no class of its own to hook. Match on that shape instead of on a
   fixed width, since the sidebar is a .span3 on some sites and a .span4 on
   others, and tint it so it reads as an aside rather than as more article.
   Keying off the wide column means an evenly split row (a 4/4/4 image strip) is
   never caught, and naming the widths explicitly keeps the narrow .span1 some
   layouts use as a gutter from becoming an empty tinted strip. The panel goes
   on .column-inner — which gridcontent always emits — so the column's own 10px
   gutter stays outside it. */
.blog-post-view .cmscontent .row-fluid > .span8 ~ .span3 > .column-inner,
.blog-post-view .cmscontent .row-fluid > .span8 ~ .span4 > .column-inner,
.blog-post-view .cmscontent .row-fluid > .span9 ~ .span3 > .column-inner {
  padding: 1rem;
  background: #f4f6f8;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
}
/* Stacked below md, the panel would otherwise butt straight against the last
   line of the article. */
@media (max-width: 767px) {
  .blog-post-view .cmscontent .row-fluid > .span8 ~ .span3 > .column-inner,
  .blog-post-view .cmscontent .row-fluid > .span8 ~ .span4 > .column-inner,
  .blog-post-view .cmscontent .row-fluid > .span9 ~ .span3 > .column-inner {
    margin-top: 1rem;
  }
}

/* Share buttons. Neutral pills that carry the network's colour on the icon
   only: a row of five saturated brand-coloured buttons would out-shout the
   article, and white-on-brand (#25d366 at 1.8:1, #1877f2 at 3.6:1) cannot meet
   AA for label text anyway. Hover/focus goes to the theme's own button blue,
   which does (5.6:1). */
.nxt-share {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.nxt-share__btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.45rem 0.85rem;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
  background: #fff;
  color: var(--nxt-text);
  font-size: 0.88rem;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.nxt-share__btn .bi { font-size: 1.05rem; line-height: 1; }
.nxt-share__btn--facebook .bi { color: #1877f2; }
.nxt-share__btn--twitter .bi { color: #000; }
.nxt-share__btn--whatsapp .bi { color: #1da851; }
.nxt-share__btn--reddit .bi { color: #ff4500; }
.nxt-share__btn--email .bi { color: var(--nxt-blue-button); }
.nxt-share__btn:hover,
.nxt-share__btn:focus {
  background: var(--nxt-blue-button);
  border-color: var(--nxt-blue-button);
  color: #fff;
}
.nxt-share__btn:hover .bi,
.nxt-share__btn:focus .bi { color: #fff; }
/* Icon-only variant for the article header — the accessible name comes from
   each link's aria-label. */
.nxt-share--compact { gap: 0.4rem; }
.nxt-share--compact .nxt-share__btn {
  width: 38px;
  height: 38px;
  padding: 0;
  justify-content: center;
}

/* ---------- Activity detail layout ----------
   Mobile-first single column in source order: gallery -> booking widget ->
   summary -> content, so the booking CTA sits directly under the gallery
   instead of at the bottom of the page. On desktop it becomes two columns:
   gallery + content on the left, the booking widget + summary stacked on the
   right (the sidebar area spans both left-hand rows). */
.activity-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
}
@media (min-width: 992px) {
  .activity-layout--sidebar {
    grid-template-columns: 8fr 4fr;
    grid-template-areas:
      "gallery sidebar"
      "content sidebar";
    align-items: start;
  }
  .activity-layout--sidebar .al-gallery { grid-area: gallery; }
  .activity-layout--sidebar .al-content { grid-area: content; }
  .activity-layout--sidebar .al-sidebar { grid-area: sidebar; }
}

/* ---------- Underline tabs ---------- */
.nxt-tabs { border-bottom: 1px solid var(--nxt-border); }
.nxt-tabs .nav-link {
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--nxt-text-muted);
  padding: 0.6rem 0.1rem;
  margin-right: 1.5rem;
  border-radius: 0;
  background: none;
}
.nxt-tabs .nav-link.active,
.nxt-tabs .nav-link:hover {
  color: var(--nxt-blue);
  border-bottom-color: var(--nxt-blue);
  background: none;
}

/* ---------- Navbar ---------- */
.nxt-navbar { padding: 0.75rem 0; border-bottom: 1px solid var(--nxt-border); }

/* Reveal a sticky header once the visitor scrolls past the hero/search box
   (threshold computed in nxt-scripts.js). position:sticky never removes the
   element from flow, so toggling this class on/off never jumps the page. */
.nxt-navbar--stuck {
  position: sticky;
  top: 0;
  z-index: 1050;
  background: #fff;
  box-shadow: var(--nxt-shadow);
}

#logo {
  margin-right: 1.0rem;
}
#logo img { display: block; max-width: 100%; height: auto; max-height: 56px; }
@media (max-width: 767px) { #logo img { max-height: 40px; } }

/* Bootstrap 5's .navbar-toggler/.navbar-toggler-icon default look (padding,
   border, the hamburger SVG background) is driven entirely by CSS custom
   properties defined on an ancestor .navbar element. The nxt header keeps
   the toggler in the #top logo row — beside the logo, not nested inside
   .navbar — to match the reference mobile layout, so it needs its own
   standalone values instead of inheriting Bootstrap's. */
.navbar-toggler {
  padding: 0.25rem 0.75rem;
  font-size: 1.25rem;
  line-height: 1;
  color: rgba(0, 0, 0, 0.55);
  background-color: transparent;
  border: 1px solid rgba(0, 0, 0, 0.15);
  border-radius: 0.375rem;
}
.navbar-toggler-icon {
  display: inline-block;
  width: 1.5em;
  height: 1.5em;
  vertical-align: middle;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(0, 0, 0, 0.55)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 100%;
}
.nxt-navbar .navbar-brand { font-weight: 700; font-size: 1.35rem; }
.nxt-navbar .navbar-brand .brand-fiji { color: var(--nxt-blue-dark); }
.nxt-navbar .navbar-brand .brand-rest { color: var(--nxt-blue-button); }
.nxt-navbar .nav-link { color: var(--nxt-text); font-weight: 500; }
.nxt-navbar .nav-link.active,
.nxt-navbar .nav-link:hover { color: var(--nxt-blue); }
.nxt-navbar .nav-link.active {
  text-decoration: underline;
  text-underline-offset: 8px;
  text-decoration-thickness: 2px;
}
/* Airy spacing between the top-level menu items (desktop only). */
@media (min-width: 992px) {
  .nxt-header-nav .navbar-nav > .nav-item > .nav-link { padding-left: 0.8rem; padding-right: 0.8rem; white-space: nowrap; }
}
/* StMartinbookings exception: its top-level menu carries more (and longer)
   items than the rest of the fleet, so the default 0.8rem gutters push the bar
   into a second line. Tightened to 0.4rem for this site only — the site-<WEBSITE>
   class comes from nxt/layouts/default.phtml + no-header.phtml. */
@media (min-width: 992px) {
  body.site-stmartinbookings .nxt-header-nav .navbar-nav > .nav-item > .nav-link {
    padding-left: 0.6rem;
    padding-right: 0.6rem;
    white-space: nowrap;
  }
}

@media (min-width: 992px) {
  body.site-seychellesbookings .nxt-header-nav .navbar-nav > .nav-item > .nav-link {
    padding-left: 0.6rem;
    padding-right: 0.6rem;
    white-space: nowrap;
  }
}

@media (min-width: 992px) {
    body.site-gilibookings .nxt-header-nav .navbar-nav > .nav-item > .nav-link {
        padding-left: 0.6rem;
        padding-right: 0.6rem;
        white-space: nowrap;
    }
}
/* Utility cluster (cart) at the far right of the bar. */
.nxt-navbar .navbar-utility { gap: 1rem; }
.nxt-navbar .nav-cart { position: relative; color: var(--nxt-text); font-size: 1.5rem; line-height: 1; text-decoration: none; }
.nxt-navbar .nav-cart:hover { color: var(--nxt-blue); }
.nxt-navbar .nav-cart .bi { display: block; }

/* Cart count indicator on the bag icon. */
.nav-cart__count {
  position: absolute;
  top: -6px;
  right: -9px;
  box-sizing: border-box;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--nxt-orange);
  color: #fff;
  font-size: 0.68rem;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
  box-shadow: 0 0 0 2px #fff;
  pointer-events: none;
}

/* Empty-cart click tooltip: white bubble with a dark gray border, instead of
   Bootstrap 5's default dark theme. */
.nav-cart-tooltip {
  --bs-tooltip-bg: #fff;
  --bs-tooltip-color: var(--nxt-text);
  --bs-tooltip-font-size: 1rem;
  /* Bootstrap's default .tooltip.show{opacity:var(--bs-tooltip-opacity)} is
     0.9 — a solid white background needs full, non-translucent opacity. */
  --bs-tooltip-opacity: 1;
}
.nav-cart-tooltip .tooltip-inner {
  background-color: #fff;
  border: 1px solid var(--nxt-text);
}
/* Arrow: a small square, rotated 45deg into a diamond, with its center sat on
   the box's top edge (bottom-center of the arrow container) — a negative
   z-index sinks it behind .tooltip-inner's lower half, leaving just the top
   wedge visible. This gives a real border on both visible edges; Bootstrap's
   own arrow is a single 0-height CSS border-triangle, which has no way to
   carry its own border. */
.nav-cart-tooltip .tooltip-arrow {
  /* z-index: -1; */
}
.nav-cart-tooltip .tooltip-arrow::after {
  content: none;
}
.nav-cart-tooltip[data-popper-placement^="bottom"] .tooltip-arrow::before {
  top: 100%;
  bottom: auto;
  left: 50%;
  width: 9px;
  height: 9px;
  border-width: 1px 0 0  1px;
  border-color: var(--nxt-text);
  background-color: #fff;
  transform: translate(-50%, -50%) rotate(45deg);
}

/* Mobile top-bar: keep the bag icon beside the hamburger toggler. */
.nxt-navbar-mobile-actions { gap: 0.85rem; }

/* Hide the textual "My booking" cart entries — the bag icon replaces them. */
.nxt-header-nav .nav-item.shopping-cart { display: none; }
.mobile-cart-button { display: none !important; }

/* Dropdowns open on hover (desktop); the parent stays a clickable link that
   navigates to its own page. No Bootstrap click-to-toggle is wired up. */
@media (min-width: 992px) {
  .nxt-header-nav .nav-item.dropdown { position: relative; }
  .nxt-header-nav .nav-item.dropdown:hover > .dropdown-menu,
  .nxt-header-nav .nav-item.dropdown:focus-within > .dropdown-menu { display: block; }
  .nxt-header-nav .dropdown-menu {
    top: 100%;
    left: 0;
    margin-top: 0; /* flush with the item so the hover target has no gap */
    border: 1px solid var(--nxt-border);
    border-radius: 0.5rem;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
  }
}
.nxt-header-nav .dropdown-item.active,
.nxt-header-nav .dropdown-item:active { background-color: var(--nxt-blue); }

/* Collapsed (mobile) menu: reveal submenus inline so they're reachable
   without hover, while the parent link still navigates on tap. */
@media (max-width: 991.98px) {
  .nxt-header-nav .dropdown-menu {
    display: block;
    position: static;
    float: none;
    border: 0;
    box-shadow: none;
    margin: 0;
    padding: 0 0 0 1rem;
  }
}

.nxt-mobile-tabs { display: flex; gap: 0.5rem; padding: 0.75rem 0; }
.nxt-mobile-tabs a {
  flex: 1;
  text-align: center;
  padding: 0.6rem 0.5rem;
  border-radius: 999px;
  font-weight: 600;
  text-decoration: none;
  font-size: 0.95rem;
  border: 1px solid transparent;
}
/* Default (not the current section): a subtle tinted pill, no border. */
.nxt-mobile-tabs a.primary { background: #fefaf7; color: var(--nxt-orange-text); }
.nxt-mobile-tabs a.secondary { background: #eaf6fc; color: var(--nxt-blue-button); }
/* Current section: white pill with a colored outline, bolder text. */
.nxt-mobile-tabs a.primary:not(.collapsed) {
  background: #fefaf7;
  border-color: var(--nxt-orange);
  color: var(--nxt-orange-text);
  font-weight: 700;
}
.nxt-mobile-tabs a.secondary:not(.collapsed) {
  background: #fff;
  border-color: var(--nxt-blue-button);
  color: var(--nxt-blue-button);
  font-weight: 700;
}

/* Condense the sticky header on mobile: hide the quick-tab pills once
   stuck/scrolled. Scoped to their normal home (#mobile-banner) so it stops
   matching once nxt-scripts.js relocates the pills into the open nav menu
   (they're scrolled out of view otherwise, since #mobile-banner itself isn't
   sticky) — the plain .nxt-mobile-tabs rule above makes them visible there. */
@media (max-width: 767.98px) {
  body.nxt-scrolled #mobile-banner .nxt-mobile-tabs { display: none; }
}
#navNxtCollapse .nxt-mobile-tabs { margin-bottom: 1rem; }

/* ---------- Sticky footer layout ---------- *
 * Make #wrapper a full-height flex column so the footer is pushed to the bottom
 * of the viewport on short pages (login, error, thank-you) instead of floating
 * mid-page with empty space beneath it. */
#wrapper { display: flex; flex-direction: column; min-height: 100vh; }
#wrapper > #footer { margin-top: auto; }

/* ---------- Footer ---------- *
 * Full-bleed branded band (the #footer sits outside the content .container in
 * default.phtml and holds its own inner .container). A deep indigo derived from
 * --nxt-blue-dark gives the page a clear, grounded close and reads as a proper
 * footer rather than a grey box floating in the content column. */
.nxt-footer {
  background: #16205a;
  background: linear-gradient(180deg, #1e2a6d 0%, #141d50 100%);
  color: #c6cde6;
  font-size: 0.9rem;
}
.nxt-footer > .container { padding-top: 2.75rem; padding-bottom: 1.5rem; }

.nxt-footer__top {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 1.5rem 3rem;
  padding-bottom: 1.75rem;
}
.nxt-footer__brand { max-width: 24rem; }
.nxt-footer__title {
  display: block;
  font-size: 1.15rem;
  font-weight: 700;
  color: #fff;
  letter-spacing: -0.01em;
}
.nxt-footer__tagline { margin: 0.45rem 0 0; color: #9aa3cc; line-height: 1.55; }

.nxt-footer__nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, auto);
  gap: 0.6rem 3.5rem;
}
.nxt-footer__nav li { margin: 0; }
.nxt-footer__nav a {
  color: #c6cde6;
  text-decoration: none;
  transition: color 0.15s ease;
}
.nxt-footer__nav a:hover { color: #fff; text-decoration: underline; }

/* Footer Trustpilot badge (trustpilot.badge.enabled sites): plain profile
 * link, or the TrustBox widget container once the dashboard ids are set. */
.nxt-footer__trustpilot {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin-top: 0.85rem;
  color: #c6cde6;
  text-decoration: none;
  transition: color 0.15s ease;
}
a.nxt-footer__trustpilot:hover { color: #fff; text-decoration: underline; }
.nxt-footer__trustpilot .bi-star-fill { color: #00b67a; } /* Trustpilot green */

.nxt-footer__bottom {
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  padding-top: 1.25rem;
}
.footer-legal { color: #868fba; font-size: 0.82rem; line-height: 1.55; margin: 0; }

@media (max-width: 767px) {
  .nxt-footer > .container { padding-top: 2rem; }
  .nxt-footer__nav ul { grid-template-columns: 1fr; gap: 0.55rem; }
}

/* ---------- Misc shims for widgets still inherited from blank/*.phtml ---------- */
.dev-bar { background: #222; color: #fff; text-align: center; padding: 0.35rem; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.05em; }
.dev-bar-development { background: #6b7280; }
/* Dark text, not white: white on the brand orange is 2.77:1. */
.dev-bar-acceptance { background: var(--nxt-orange); color: #1a1a1a; }
#flashmessages .notice {
  background: #eaf6fc;
  border: 1px solid #b8e2f5;
  border-radius: var(--nxt-radius-sm);
  padding: 0.75rem 1rem;
  margin-bottom: 0.75rem;
  position: relative;
}
#flashmessages .notice .close { position: absolute; right: 0.75rem; top: 0.5rem; text-decoration: none; color: var(--nxt-text-muted); }
.contact-button {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: 1030;
}
.contact-button a {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: var(--nxt-blue-button);
  color: #fff;
  padding: 0.6rem 1rem;
  border-radius: 999px;
  text-decoration: none;
  box-shadow: var(--nxt-shadow);
  font-weight: 600;
}
.contact-button a.social-button {
  width: 40px;
  height: 40px;
  padding: 0;
  justify-content: center;
}
.contact-button a.social-button svg { fill: #fff; width: 18px; height: 18px; }
.contact-button a.social-button.facebook { background: linear-gradient(135deg, #1877f2, #0348a3); }
.contact-button a.social-button.instagram { background: linear-gradient(135deg, #E4405F, #a50e29); }
.contact-button a.social-button.whatsapp { background: linear-gradient(135deg, #25d366, #1a994b); }
@media (max-width: 768px) { .contact-button { display: none !important; } }

/* Mobile chat launcher: .contact-button above is desktop-only, so on phones the
   AI chat gets its own round icon button, which opens the same dialog full-screen
   (see .ib-chat-dialog-fullscreen). Rendered only when chat is enabled. */
.chat-fab { display: none; }
@media (max-width: 768px) {
  .chat-fab {
    display: block;
    position: fixed;
    right: 1rem;
    bottom: 1rem;
    z-index: 1031;
  }
  /* Clear of the full-width "My booking" bar / the cookie bar when either shows. */
  .chat-fab--raised { bottom: 4.25rem; }
  .cookiebar-visible .chat-fab { bottom: 4rem; }
  .cookiebar-visible .chat-fab--raised { bottom: 7.25rem; }
  .chat-fab__button {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: var(--nxt-blue-button);
    color: #fff;
    font-size: 1.35rem;
    line-height: 1;
    text-decoration: none;
    box-shadow: var(--nxt-shadow);
  }
  .chat-fab__button:hover,
  .chat-fab__button:focus { color: #fff; background: var(--nxt-blue-button-light); }
  .chat-fab__button:focus-visible { outline: 2px solid var(--nxt-blue-dark); outline-offset: 2px; }
}
.mobile-cart-button {
  position: fixed;
  left: 1rem;
  right: 1rem;
  bottom: 1rem;
  background: var(--nxt-orange);
  color: #fff;
  text-align: center;
  padding: 0.75rem;
  border-radius: var(--nxt-radius-sm);
  text-decoration: none;
  font-weight: 700;
  z-index: 1030;
}
.mobile-toggle-images img { width: 100%; height: auto; display: block; }

.cookiebar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1040;
  background: #222;
  color: #fff;
  font-size: 0.85rem;
  padding: 0.75rem 1rem;
  text-align: center;
}
.cookiebar a { color: #9fd8f5; }
.cookiebar .close-button { margin-left: 0.75rem; text-decoration: underline; }
.cookiebar-visible .contact-button { bottom: 46px !important; }

/* ---------- Availability calendar (hotel-room-detail / hotel-detail) ---------- */
table.availability-calendar th { font-weight: 600; }
table.availability-calendar .noleftborder { text-align: left; }
td.available {
  background: #e6f9ec;
  color: #029934;
  cursor: pointer;
  font-weight: 600;
}
td.available:hover { background: #cbecd6; }
td.selected { background: #029934; color: #fff; }
td.not-available { background: #f4f6f8; color: var(--nxt-text-muted); }
td.availability-cell { font-size: 0.78rem; }

.activity-book-now-btn {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1030;
  padding: 1.75rem 0.75rem 0.75rem;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.7) 40%, #fff 70%, #fff 100%);
}
.nxt-breadcrumb a i { margin-right: 0.15rem; }

/* ==========================================================================
   Homepage tidy-up — equal-height cards, clear spacing, readable content.
   Conservative: keeps the existing structure, palette and system font.
   Scoped to .nxt-home so no other page is affected.
   ========================================================================== */

/* Two search boxes: clean white cards, EQUAL HEIGHT, gutter between them
   (the row supplies the gutter; height:100% makes both fill the stretched
   column so their tops and bottoms line up). */
.nxt-home .nxt-search-card {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: #fafafa;
  border: 1px solid #cfe8f5;
  border-radius: var(--nxt-radius);
  box-shadow: var(--nxt-shadow);
  padding: 1.5rem 1.5rem 0.5rem 1.5rem;
}

/* Card titles: one consistent size, even spacing below. */
.nxt-home .form-boat-title,
.nxt-home .hotel_search > .h1 {
  font-size: 2.25rem;
  line-height: 1.2;
  margin-bottom: 1.15rem;
}

/* Ferry card: the form fills the card height and the note + Search button are
   pinned to the bottom edge, so both cards' buttons line up. */
#content > div > div.row.g-4.hidden-phone > div.col-12.col-md-6.higher-form-boat > div.nxt-search-card { background-color: #eaf6fc; }
.nxt-home .nxt-search-card > .gradient { display: flex; flex-direction: column; flex: 1 1 auto; }
.nxt-home .search_form.boat_form { display: flex; flex-direction: column; flex: 1 1 auto; }
.nxt-home .search_form .field-options { margin-bottom: 1.15rem; row-gap: 0.5rem; }

.nxt-home .search_form .row + .row {
  margin-top: 0rem;
}

.nxt-home .search-bottom {
  margin-top: auto;
  padding-top: 0.5rem;
  align-items: center;
  gap: 1rem 1.25rem;
}
.nxt-home .search-content { font-size: 0.85rem; line-height: 1.5; color: var(--nxt-text-muted); }

/* Accommodation card: stack the two groups into one tidy vertical column so it
   fills the equal-height card neatly instead of leaving a big gap. */
.nxt-home .search_form.hotel_search { display: flex; flex-direction: column; flex: 1 1 auto; }
.nxt-home .hotel_search > .row { flex: 1 1 auto; row-gap: 1.25rem; }
.nxt-home .hotel_search > .row > div { flex: 0 0 100%; max-width: 100%; }

/* Even vertical rhythm down the page. */
.nxt-home .row-fluid.margin { margin-top: 1.75rem; }
.nxt-home .nxt-card.cmscontent { padding: 1.75rem 2rem; margin-top: 1.75rem; }
.nxt-home .blacklinks { margin-top: 1.75rem; }

/* Content card: comfortable padding and a readable line length. */
.nxt-home .nxt-card.cmscontent h1 { margin-bottom: 0.85rem; }
.nxt-home .nxt-card.cmscontent p,
.nxt-home .nxt-card.cmscontent li { line-height: 1.7; color: #454b54; }
.nxt-home .nxt-card.cmscontent p { max-width: 78ch; }
@media (max-width: 767.98px) {
  /* Phones: no card chrome around the homepage text or the CMS text under the
     fast-boat / hotel search results, so it gets the width. */
  .nxt-home .nxt-card.cmscontent,
  div.gradient.margin.cmscontent {
    padding: 0.5rem 0 0;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    background: transparent;
  }
}

/* ==========================================================================
   Content pages with a ferry-search box (templates four-blocks/accordion/default
   when showBoatSearch is set, e.g. /fiji-island-hopping). The search box FLOATS
   into the top-left corner and the article text wraps around it and reclaims the
   full page width below it — the way the old theme laid it out — instead of
   being trapped in a narrow right-hand column with a tall empty gap down the
   left. Styling matches the HOMEPAGE ferry card. Scoped to .nxt-content-page so
   ordinary (search-less) content pages are untouched.
   ========================================================================== */

/* Desktop (lg+): the box floats top-left; h1 + cmscontent flow around and below
   it. Below lg the float would squeeze the text into a thin ragged column, so
   there the box is just a full-width block with the article beneath it (and
   below md it is hidden entirely — mobile uses the header banner search). */
@media (min-width: 992px) {
  .nxt-content-page.has-search::after { content: ""; display: block; clear: both; }
  .nxt-content-page.has-search .nxt-content-search {
    float: left;
    width: 45%;
    max-width: 540px;
    margin: 0 1.75rem 1.5rem 0;
  }
  /* The intro row (first) holds a single column the CMS authored as a lone
     .span6; let it fill the whole width beside the floated box instead of
     sitting at half width and leaving the top-right empty. */
  .nxt-content-page.has-search .cmscontent .grid > .row-fluid:first-child > [class*="span"]:only-child {
    flex: 0 0 100%;
    max-width: 100%;
  }
  /* Every row after the intro clears the floated box so it starts full-width
     BELOW it (a flex row is a block-formatting context and would otherwise be
     shoved into the narrow strip beside the box, re-creating the empty gap). */
  .nxt-content-page.has-search .cmscontent .grid > .row-fluid:not(:first-child) {
    clear: left;
  }
}
@media (min-width: 768px) and (max-width: 991px) {
  .nxt-content-page.has-search .nxt-content-search { margin-bottom: 1.5rem; }
}

/* ==========================================================================
   Blockpage and hotelpage templates: top-level "menu" content pages render a
   promo box (Search_IndexController::form-hotel — "Book your activities" on
   activity-enabled sites, "Book your accommodation" on /caribbean-hotels and
   friends) alongside the article. Same problem/fix as the ferry-search box
   above: float it so the article text wraps around it and reclaims the full
   page width below it, instead of being pinned into a permanent half-width
   column with an empty gap once the box's own content runs out.
   ========================================================================== */
@media (min-width: 992px) {
  .nxt-sidebar-body::after {
    content: "";
    display: block;
    clear: both;
  }

  .nxt-sidebar-box {
    float: right;
    width: 45%;
    max-width: 620px;
    margin: 0 0 1.5rem 1.75rem;
  }

  /* Every row after the intro clears the floated box so it starts full-width
     BELOW it (a row-fluid is a flex formatting context and would otherwise
     keep dodging the float). */
  .nxt-sidebar-body .cmscontent .grid > .row-fluid:not(:first-child) {
    clear: right;
  }
}

/* Some of this content is still authored with the legacy row-fluid/spanN grid
   (e.g. /visit-fiji, /caribbean-hotels), not plain paragraphs (e.g.
   /things-to-do-in-fiji). Same fix as .has-search above: let a lone .span* row
   fill the width, since the author's .span6 meant half the PAGE next to the
   box, not half of an already-halved column. Outside the float media query on
   purpose — between 768px and 991px the box is a full-width block above the
   article, where a half-width lone column leaves the same empty right half. */
.nxt-sidebar-body .cmscontent .grid > .row-fluid:first-child > [class*="span"]:only-child {
  flex: 0 0 100%;
  max-width: 100%;
}
@media (max-width: 991px) {
  .nxt-sidebar-box {
    margin-bottom: 1.5rem;
  }
}

/* The box's "Book your accommodation" / "Book your activities" title is a
   div.h1, which at the page-h1 2rem shouts over the article heading it sits
   beside. Size it as the promo it is, and give the two option groups room. */
.nxt-sidebar-box {
  padding: 1.5rem;
}

.nxt-sidebar-box .search_form > .h1 {
  font-size: 1.6rem;
  line-height: 1.2;
  margin-bottom: 1.15rem;
}

.nxt-sidebar-box .search_form > .row {
  margin-bottom: 0;
  row-gap: 1.25rem;
}

/* Search box: identical treatment to the homepage ferry card — light-blue
   panel, soft blue border, rounded corners, soft shadow, generous padding. */
.nxt-content-search .nxt-search-card {
  background: #eaf6fc;
  border: 1px solid #cfe8f5;
  border-radius: var(--nxt-radius);
  box-shadow: var(--nxt-shadow);
  padding: 1.5rem;
}

/* Same title size, field rhythm and Search-button treatment as the homepage. */
.nxt-content-search .form-boat-title { font-size: 2.0rem; line-height: 1.2; margin-bottom: 1.15rem; }
.nxt-content-search .search_form .field-options { margin-bottom: 1.15rem; row-gap: 0.5rem; }
.nxt-content-search .search_form .row + .row { margin-top: 0.9rem; }
.nxt-content-search .search-bottom { padding-top: 1.35rem; align-items: center; gap: 1rem 1.25rem; }
.nxt-content-search .search-content { font-size: 0.85rem; line-height: 1.5; color: var(--nxt-text-muted); }

/* Body text: readable rhythm and even spacing above the heading. */
.nxt-content-page > h1 { margin-bottom: 0.85rem; }
.nxt-content-page .cmscontent { line-height: 1.7; }
.nxt-content-page .cmscontent p,
.nxt-content-page .cmscontent li { line-height: 1.7; color: #454b54; }

.picker--opened .picker__holder {
  background-color: transparent !important;
}

/* Accordion sections in a CMS page. The `.accordion` class comes from the
   accordion template (FAQ, CFAR terms); the `.ajax-dialog-window` twin of each
   selector is there because book.js accordions whatever it loads into the
   booking dialog whatever that page's template is -- without it a `default`
   template page (the site-wide /terms-and-conditions) got the collapse
   behaviour but none of the styling, i.e. a wall of oversized blue headings. */
.cmscontent.accordion .accordion_item,
.ajax-dialog-window .cmscontent .accordion_item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin: 0;
  padding: 0.95rem 0.35rem !important; /* normalise the inline padding-top the CMS adds */
  font-size: 1.15rem;
  line-height: 1.3;
  color: var(--nxt-blue);
  border-bottom: 1px solid var(--nxt-border);
  cursor: pointer;
  transition: color 0.15s ease;
}
.cmscontent.accordion .accordion_item strong,
.ajax-dialog-window .cmscontent .accordion_item strong { font-weight: 700; }
.cmscontent.accordion .accordion_item:hover,
.ajax-dialog-window .cmscontent .accordion_item:hover,
.cmscontent.accordion .accordion_item.accordion_hover,
.ajax-dialog-window .cmscontent .accordion_item.accordion_hover,
.cmscontent.accordion .accordion_item.accordion_active,
.ajax-dialog-window .cmscontent .accordion_item.accordion_active { color: var(--nxt-blue-dark); }
.cmscontent.accordion .accordion_icon,
.ajax-dialog-window .cmscontent .accordion_icon {
  flex: 0 0 auto;
  width: 1.7rem;
  height: 1.7rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--nxt-blue);
  color: #fff;
  font-size: 1.15rem;
  line-height: 1;
  transition: background 0.15s ease;
}
.cmscontent.accordion .accordion_active .accordion_icon,
.ajax-dialog-window .cmscontent .accordion_active .accordion_icon { background: var(--nxt-orange); }
/* Collapsible body rows (the .row-fluid blocks that hold content,
not a heading)
   get comfortable padding and a readable measure. */
.cmscontent.accordion .grid > .row-fluid:not(:has(.accordion_item)) {
  padding: 0.5rem 0.35rem 1.15rem;
}
.cmscontent.accordion .grid > .row-fluid:not(:has(.accordion_item)) p,
.ajax-dialog-window .cmscontent .grid > .row-fluid:not(:has(.accordion_item)) p { max-width: 74ch; }
.cmscontent.accordion .grid > .row-fluid:not(:has(.accordion_item)) p:last-child,
.ajax-dialog-window .cmscontent .grid > .row-fluid:not(:has(.accordion_item)) p:last-child { margin-bottom: 0; }
/* ==========================================================================
   Admin / back-office list pages (book/admin/list-all-bookings, sales-reports,
   commission-reports, refunds, order-errors, list-booking, …). They share a
   `.bookadmin-header` filter toolbar and an `.admin_grid` data table that the
   nxt pass only lightly touched (dark <th> only). Give them a consistent look:
   a carded filter toolbar with proper inputs and buttons, and a readable,
   zebra-striped, hoverable data grid inside a scroll container.
   ========================================================================== */

/* Filter / search toolbar */
.bookadmin-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1rem;
  padding: 1rem 1.25rem;
  margin-bottom: 1rem;
  background: #f7fafc;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius);
}
.bookadmin-header > div { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.bookadmin-header .search { margin-left: auto; }
.bookadmin-header input[type="text"],
.bookadmin-header input[type="number"],
.bookadmin-header select {
  height: 38px;
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
  background: #fff;
  color: var(--nxt-text);
  font-size: 0.9rem;
}
.bookadmin-header input[type="text"]:focus,
.bookadmin-header input[type="number"]:focus,
.bookadmin-header select:focus {
  outline: none;
  border-color: var(--nxt-blue);
  box-shadow: 0 0 0 3px rgba(17, 155, 212, 0.12);
}
/* A numeric toolbar field only ever holds a few digits — don't let it size
   like a full-width text input next to the selects. */
.bookadmin-header input[type="number"] {
  width: 4.5rem;
  padding-right: 0.3rem;
}

/* Toolbar buttons: promote the plain white .page-button to a solid blue action. */
.bookadmin-header .page-button {
  background: linear-gradient(var(--nxt-blue-button-light), var(--nxt-blue-button));
  border-color: var(--nxt-blue-button);
  color: #fff;
}
.bookadmin-header .page-button span { color: #fff; padding: 9px 18px; }

/* Data grid */
.responsive-table {
  overflow-x: auto;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius);
}

/* Sticky horizontal scrollbar (nxt-scripts.js): tall .table-responsive tables
   (e.g. the boat-prices matrix) put their native horizontal scrollbar at the
   bottom of the WHOLE table, which can be thousands of pixels down the page.
   JS mirrors it into this bar, pinned to the viewport bottom, whenever the
   real table is on screen but its own scrollbar isn't. */
.nxt-sticky-hscroll {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1030;
  overflow-x: auto;
  overflow-y: hidden;
  height: 17px;
  background: #fff;
  border-top: 1px solid var(--nxt-border);
  display: none;
}
.nxt-sticky-hscroll.is-visible { display: block; }
.nxt-sticky-hscroll > div { height: 1px; }
table.admin_grid {
  width: 100%;
  border-collapse: collapse;
  background: #fff;
  font-size: 0.85rem;
}
table.admin_grid th,
table.admin_grid td {
  padding: 0.6rem 0.8rem;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--nxt-border);
}
/* th already gets the dark background from the earlier admin_grid rule. */
table.admin_grid th { white-space: nowrap; border-bottom: none; }
table.admin_grid th a { color: #fff; text-decoration: none; }
table.admin_grid th a:hover { text-decoration: underline; }
table.admin_grid tr.odd td { background: #fff; }
table.admin_grid tr.even td { background: #f8fafc; }
table.admin_grid tr.affiliaterow td { background: #fff8e1; }
table.admin_grid tr:hover td { background: #eaf6fc; }
table.admin_grid td a { color: var(--nxt-text); text-decoration: none; }
table.admin_grid td a:hover { color: var(--nxt-blue); text-decoration: underline; }
table.admin_grid tr:last-child td { border-bottom: none; }

/* Boat seat pricing grid (company/admin/boat-prices): the <colgroup> paints
   pastel column bands (one-way/roundtrip/island-hopping, price vs cost price)
   so the wide table is easier to scan. Bootstrap's `.table` class — added to
   this table during the nxt conversion — paints an opaque cell background
   that sits above the colgroup layer and hides those bands; make cells
   transparent again so the <col> colors show through, matching legacy.css's
   equivalent `.boatprices tr td { background-color: transparent; }` rule. */
table.admin_grid.boatprices > tbody > tr > td,
table.admin_grid.boatprices > tbody > tr > th {
  background-color: transparent;
}

/* The "Copy prices from..." <select> in the Seat column has no .form-select
   or width class, so it inherits Bootstrap 5's reboot `select { width:100% }`
   and stretches to fill the cell — ballooning the whole left (Boat/Seat/
   Route) side of the table. Give it a fixed, content-appropriate width and
   stack it under the seat name instead of running inline with it. */
table.admin_grid.boatprices dd select,
table.admin_grid.boatprices select.copy-prices {
  display: block;
  width: 100px;
  max-width: 100%;
  margin-top: 0.35rem;
  font-size: 0.7rem;
  text-overflow: ellipsis;
}

/* Compact the boat-prices pricing matrix: every ticket type (one-way/
   roundtrip/daytrip/island-hopping) × passenger type (adult/child/infant/
   senior/min-pax) × price/cost-price is its own column, so admin_grid's
   roomier nxt padding/font-size/input sizing push the table far past any
   viewport width, permanently triggering the .nxt-sticky-hscroll fallback
   above. Tighten cells and inputs back down towards style.css's legacy
   sizing, scoped to .boatprices only so other admin_grid tables keep the
   roomier default. */
table.admin_grid.boatprices th,
table.admin_grid.boatprices td {
  padding: 0.1rem 0.1rem;
  font-size: 0.72rem;
}

table.admin_grid.boatprices input[type="text"] {
  width: 45px;
  padding: 1px 3px;
  font-size: 0.72rem;
}

table.admin_grid.boatprices td a.btn {
  padding: 0.15rem 0.4rem;
  font-size: 0.72rem;
}

/* Break a wide admin table out of the layout's centered Bootstrap .container
   (no-header.phtml) so it can use the full viewport width instead of being
   capped at .container's max-width (1320px at >=1400px viewports). Used by
   the boat-prices pricing matrix — where .nxt-sticky-hscroll mirrors the
   table's horizontal scrollbar and is pinned to the full viewport width, so
   it needs to line up with a full-bleed table — and by other admin_grid
   tables with too many columns to fit the centered column comfortably (e.g.
   company/admin/edit-location's transfer-prices table). */
.nxt-full-bleed {
  margin-left: -20px;
  margin-right: -20px;
  box-sizing: border-box;
}

/* Transfer-prices grid (company/admin/edit-location, Company_Form_Location):
   costPriceAdult/costPriceChild/priceAdult/priceChild/costPriceVehicle/
   priceVehicle/vehicleCapacity are the only inputs in this grid with no
   inline width attrib, so they fall through to the generic
   `.form-vertical .controls input[type="text"]` rule below (width: 100%;
   max-width: 30rem) and each balloon to 170px+ — legacy style.css sized the
   equivalent fields to 33-66px. Give them back a compact fixed width, and
   tighten the grid's padding/font-size generally, scoped to this table only
   so other admin_grid tables keep the roomier default sizing. */
#table-transfer-prices.admin_grid th,
#table-transfer-prices.admin_grid td {
  padding: 0.3rem 0.5rem;
}
#table-transfer-prices .controls input[type="text"],
#table-transfer-prices .controls select {
  padding: 0.3rem 0.45rem;
  font-size: 0.8rem;
  max-width: none;
}
#table-transfer-prices input.transfer-person-field,
#table-transfer-prices input.transfer-vehicle-field {
  width: 50px;
}

/* Content-admin reorder lists (default/admin/content -> menu.phtml, driven by
   content-admin.js + jquery.ui.nestedSortable with handle:'span.handle'). The
   drag-handle icon, list reset and drop placeholder lived in the old style.css
   and were never ported to nxt, so the handle span rendered 0x0 (invisible, so
   nothing was draggable) and the <ol> showed default numbers. Restore them. */
ol.sortable,
ol.sortable ol { margin: 0 0 0 1.5rem; padding: 0; list-style: none; }
ol.sortable { margin: 0; border-bottom: 1px solid var(--nxt-border); }
.sortable li { margin: 0; padding: 0; border-top: 1px solid var(--nxt-border); }
.sortable li > .d-flex { padding: 0.45rem 0.35rem; }
.sortable li > .d-flex:hover { background: #f8fafc; }
.sortable li span.handle {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin-top: 2px;
  cursor: move;
  background: url(../images/dragdrop.png) center center no-repeat;
}
/* The jQuery UI icon sprite isn't shipped under nxt (its images/ folder 404s),
   so give the delete control a self-contained trash icon instead. */
.sortable a.ui-icon-trash {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin-top: 2px;
  cursor: pointer;
  text-indent: -9999px;
  overflow: hidden;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23a4231a' viewBox='0 0 16 16'%3E%3Cpath d='M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0z'/%3E%3Cpath d='M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4zM2.5 3h11V2h-11z'/%3E%3C/svg%3E") center center no-repeat;
}
.sortable .placeholder {
  background: #eaf6fc;
  outline: 1px dashed var(--nxt-blue);
  min-height: 1.5rem;
}
.ui-nestedSortable-error { background: #fbe3e4; color: #8a1f11; }

/* Admin order-details customer form (book/admin/view-total-booking header). The
   name/email/phone/country fields carry `.field-locked` (readonly until edited)
   but had no nxt styling, so they rendered as sharp default inputs. Give them
   the same rounded, bordered look as the other admin/back-office inputs, with a
   subtle "locked" tint while readonly. */
input.field-locked,
select.field-locked {
  height: 38px;
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
  background: #fff;
  color: var(--nxt-text);
  font-size: 0.9rem;
  margin-bottom: 0.5rem;
}
input.field-locked[readonly],
select.field-locked[readonly] { background: #f3f5f7; color: #55606b; }
input.field-locked:focus,
select.field-locked:focus {
  outline: none;
  border-color: var(--nxt-blue);
  box-shadow: 0 0 0 3px rgba(17, 155, 212, 0.12);
}
/* The padlock that toggles those fields between readonly and editable. The
   anchor is injected empty by JS (see _view-total-booking-modals.phtml and
   company/admin/edit-activity.phtml); blank draws its icon from style.css,
   which nxt does not load, so here it collapsed to a zero-size invisible
   element and the fields could not be unlocked at all. Give it a real hit
   area plus the icon. Following blank, the icon shows the ACTION available:
   an open padlock while the field is locked ("click to unlock"), a closed one
   once it is editable ("click to lock again"). */
a.field-padlock {
  display: inline-block;
  width: 1.75rem;
  height: 1.75rem;
  margin-left: 0.35rem;
  margin-bottom: 0.5rem;
  vertical-align: middle;
  border-radius: var(--nxt-radius-sm);
  text-decoration: none;
  background-color: transparent;
  background-position: center center;
  background-repeat: no-repeat;
  background-size: 16px 16px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%230b76a8' viewBox='0 0 16 16'%3E%3Cpath d='M8 1a2 2 0 0 1 2 2v4H6V3a2 2 0 0 1 2-2m3 6V3a3 3 0 0 0-6 0v4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2'/%3E%3C/svg%3E");
}
a.field-padlock.field-unlocked-padlock {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%230b76a8' viewBox='0 0 16 16'%3E%3Cpath d='M11 1a2 2 0 0 0-2 2v4a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h5V3a3 3 0 0 1 6 0v4a.5.5 0 0 1-1 0V3a2 2 0 0 0-2-2'/%3E%3C/svg%3E");
}
a.field-padlock:hover,
a.field-padlock:focus {
  background-color: #eef4f8;
  text-decoration: none;
}
a.field-padlock:focus-visible {
  outline: 2px solid var(--nxt-blue);
  outline-offset: 1px;
}
/* Order-details grid: pin the "Toggle all" link to the right of the Details
   header and let the Total row read as a clear summary line. */
table.admin_grid th .right { float: right; font-weight: 400; }
table.admin_grid th .right a { color: #cfe8f5; }
table.admin_grid tr td .total,
table.admin_grid td strong { color: var(--nxt-text); }

/* Cancellation controls (book/admin/view-total-booking, paid-order row): the
   refund <select> and the fee/mail checkboxes had no nxt styling, so they
   fell back to bare browser defaults — a tiny unstyled dropdown and cramped
   inline checkboxes all running into each other. Stack them as a column of
   evenly-spaced, readable rows, and give the select the same height/padding
   used by the other admin form controls above. */
.cancellation-controls {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.55rem;
  padding: 0.75rem 0;
  font-size: 0.9rem;
}
.cancellation-controls label { display: flex; align-items: center; gap: 0.45rem; }
.cancellation-controls select[name="refund_percentage"] {
  height: 38px;
  min-width: 260px;
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
  background: #fff;
  color: var(--nxt-text);
  font-size: 0.9rem;
}
.cancellation-controls select[name="refund_percentage"]:focus {
  outline: none;
  border-color: var(--nxt-blue);
  box-shadow: 0 0 0 3px rgba(17, 155, 212, 0.12);
}
.cancellation-controls input[type="checkbox"] { width: 16px; height: 16px; margin: 0; }
.cancellation-controls .submit_button { margin-top: 0.25rem; }
.cancellation-controls__note { font-size: 0.75rem; color: var(--nxt-text-muted); }

/* "Manually send booking e-mail to" (same view): the email input and submit
   button relied on Bootstrap 2's `.pull-left`, which has no Bootstrap 5
   equivalent — the button's wrapper <div> is block-level by default, so it
   dropped onto its own line under the input instead of sitting beside it. */
.manual-send-email { margin-top: 1rem; }
.manual-send-email label { display: block; margin-bottom: 0.4rem; }
.manual-send-email__row { display: flex; align-items: center; gap: 0.5rem; }
.manual-send-email__row input[type="email"] {
  height: 38px;
  min-width: 220px;
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
  background: #fff;
  color: var(--nxt-text);
  font-size: 0.9rem;
}
.manual-send-email__row input[type="email"]:focus {
  outline: none;
  border-color: var(--nxt-blue);
  box-shadow: 0 0 0 3px rgba(17, 155, 212, 0.12);
}

/* Secondary figures on the view-booking items table: the per-unit supplier cost
   shown under the selling price, and the provenance suffix in the price change
   log. Muted so the price the customer paid stays the primary number. */
.order-item-cost { font-size: 0.75rem; color: var(--nxt-text-muted); }

/* Actions column of the view-booking items table. As bare links these read as
   body copy and wrapped mid-label ("Change / price"), so they are small
   buttons instead: nowrap, stacked, and visibly clickable. */
.row-actions { display: flex; flex-direction: column; align-items: flex-start; gap: 0.3rem; }
table.admin_grid td .row-action {
  display: inline-block;
  white-space: nowrap;
  padding: 0.2rem 0.55rem;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
  background: #fff;
  color: var(--nxt-text);
  font-size: 0.75rem;
  line-height: 1.5;
  text-decoration: none;
  cursor: pointer;
}
table.admin_grid td .row-action:hover,
table.admin_grid td .row-action:focus {
  border-color: var(--nxt-blue);
  color: var(--nxt-blue);
  background: #eaf6fc;
  text-decoration: none;
}

/* "No margin" warning in the change-price modal (cost >= price). Amber, not red:
   it is a heads-up, not a rejection — the save is still allowed. */
.change-price-warning {
  margin: 0 0 0.75rem;
  padding: 0.5rem 0.7rem;
  border: 1px solid #f0c36d;
  border-radius: var(--nxt-radius-sm);
  background: #fdf6e3;
  color: #7a5b12;
  font-size: 0.8rem;
}

/* =========================================================================
   Product / activity image gallery + full-screen lightbox
   (company/gallery/render.phtml + render-activities.phtml, driven by
   /scripts/gallery.js)
   ========================================================================= */

/* --- Main image: signals it opens a full-screen view on click ----------- */
/* A fixed-ratio frame keeps the box height constant as the image is swapped,
   so hovering thumbnails no longer resizes the frame and reflows the page.
   The stacked layout (render.phtml) generates 800x600 large images; the
   side-by-side activities layout (render-activities.phtml, .col-md-7) uses
   800x560. object-fit: cover fills the frame without letterboxing. */
#gallery #lightbox {
  display: block;
  position: relative;
  overflow: hidden;
  border-radius: var(--nxt-radius);
  cursor: zoom-in;
  aspect-ratio: 4 / 3;
  background: #eef1f4;
}
#gallery .col-md-7 #lightbox { aspect-ratio: 800 / 560; }
#gallery #large-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.45s ease;
}
#gallery #lightbox:hover #large-img { transform: scale(1.03); }
/* Magnifier hint, top-right of the main image */
#gallery #lightbox::after {
  content: "";
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 50%;
  background-color: rgba(0, 0, 0, 0.45);
  background-repeat: no-repeat;
  background-position: center;
  background-size: 1.15rem 1.15rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='white' stroke-width='1.4' stroke-linecap='round'%3E%3Ccircle cx='6.8' cy='6.8' r='4.3'/%3E%3Cline x1='10' y1='10' x2='14' y2='14'/%3E%3Cline x1='6.8' y1='5' x2='6.8' y2='8.6'/%3E%3Cline x1='5' y1='6.8' x2='8.6' y2='6.8'/%3E%3C/svg%3E");
  opacity: 0;
  transform: scale(0.85);
  transition: opacity 0.2s ease, transform 0.2s ease;
  pointer-events: none;
}
#gallery #lightbox:hover::after { opacity: 1; transform: scale(1); }

/* --- Thumbnails: clear active/hover state instead of a 50% wash --------- */
#gallery a.lightboxlink {
  display: block;
  position: relative;
  overflow: hidden;
  border-radius: var(--nxt-radius-sm);
}
#gallery a.lightboxlink img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  cursor: pointer;
  opacity: 0.8;
  transition: opacity 0.18s ease, transform 0.28s ease, box-shadow 0.18s ease;
}
#gallery a.lightboxlink:hover img,
#gallery a.lightboxlink:focus-visible img {
  opacity: 1;
  transform: scale(1.07);
}
#gallery a.lightboxlink img.active {
  opacity: 1;
  box-shadow: 0 0 0 3px var(--nxt-blue);
}

/* --- Full-screen lightbox overlay --------------------------------------- */
body.nxt-lb-lock { overflow: hidden; }
.nxt-lightbox {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: none;
  align-items: center;
  justify-content: center;
  padding: clamp(1rem, 4vw, 3rem);
  background: rgba(15, 23, 32, 0.93);
  opacity: 0;
  transition: opacity 0.2s ease;
}
.nxt-lightbox.is-open { display: flex; opacity: 1; }

.nxt-lb-stage {
  margin: 0;
  max-width: 100%;
  max-height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.nxt-lb-img {
  max-width: min(1100px, 92vw);
  max-height: 82vh;
  width: auto;
  height: auto;
  border-radius: var(--nxt-radius);
  box-shadow: 0 12px 48px rgba(0, 0, 0, 0.5);
  opacity: 0;
  transform: scale(0.98);
  transition: opacity 0.25s ease, transform 0.25s ease;
}
.nxt-lb-img.is-loaded { opacity: 1; transform: none; }
.nxt-lb-caption {
  margin-top: 0.9rem;
  max-width: 90vw;
  color: #e7eaee;
  font-size: 0.95rem;
  text-align: center;
}
.nxt-lb-caption:empty { display: none; }

.nxt-lb-btn {
  position: absolute;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s ease, transform 0.15s ease;
}
.nxt-lb-btn:hover { background: rgba(255, 255, 255, 0.24); }
.nxt-lb-btn:focus-visible {
  outline: 3px solid var(--nxt-blue);
  outline-offset: 2px;
}
.nxt-lb-close { top: 1rem; right: 1rem; }
.nxt-lb-prev { left: clamp(0.5rem, 3vw, 2rem); top: 50%; transform: translateY(-50%); }
.nxt-lb-next { right: clamp(0.5rem, 3vw, 2rem); top: 50%; transform: translateY(-50%); }
.nxt-lb-prev:hover { transform: translateY(-50%) scale(1.08); }
.nxt-lb-next:hover { transform: translateY(-50%) scale(1.08); }
.nxt-lb-counter {
  position: absolute;
  bottom: 1rem;
  left: 50%;
  transform: translateX(-50%);
  padding: 0.25rem 0.7rem;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.35);
  color: #cfd4da;
  font-size: 0.85rem;
  letter-spacing: 0.03em;
}
.nxt-lb-single .nxt-lb-prev,
.nxt-lb-single .nxt-lb-next,
.nxt-lb-single .nxt-lb-counter { display: none; }

@media (max-width: 575.98px) {
  .nxt-lb-btn { width: 2.5rem; height: 2.5rem; font-size: 1.05rem; }
  .nxt-lb-img { max-height: 74vh; }
}
@media (prefers-reduced-motion: reduce) {
  #gallery #large-img,
  #gallery a.lightboxlink img,
  .nxt-lightbox,
  .nxt-lb-img,
  .nxt-lb-btn { transition: none; }
  #gallery #lightbox:hover #large-img,
  #gallery a.lightboxlink:hover img { transform: none; }
}

/* =========================================================================
   Boat / fastboat detail page (company/index/fastboat-detail.phtml)
   ========================================================================= */

/* Route-map preview. Was a bare, square-cornered image floating under the
   search form (float:left from the legacy .map-small rule), which left the
   hero lopsided. Now a framed, rounded card that opens the full route map +
   schedule dialog on click — visually consistent with the gallery. */
#content .nxt-route-map { margin-top: 1rem; }
#content .nxt-route-map a.map-small.fastboat-detail {
  float: none;
  display: block;
  margin: 0;
  padding: 0.5rem;
  background: #eaf6fc;
  border: 1px solid #cfe8f5;
  border-radius: var(--nxt-radius);
  box-shadow: var(--nxt-shadow);
  text-align: center;
  overflow: hidden;
  transition: box-shadow 0.18s ease, transform 0.18s ease;
}
#content .nxt-route-map a.map-small.fastboat-detail:hover {
  box-shadow: 0 6px 20px rgba(17, 24, 39, 0.14);
  transform: translateY(-2px);
}
#content .nxt-route-map a.map-small.fastboat-detail img {
  display: block;
  width: 100%;
  height: 380px;
  object-fit: cover;
  border-radius: var(--nxt-radius-sm);
}
#content .nxt-route-map__cta {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.55rem;
  padding: 0.42rem 0.95rem;
  border-radius: 999px;
  background: var(--nxt-blue);
  color: #fff;
  font-size: 0.9rem;
  font-weight: 600;
  line-height: 1;
}
#content .nxt-route-map a.map-small.fastboat-detail:hover .nxt-route-map__cta {
  background: var(--nxt-blue-dark);
}

/* Equal-height hero: let the gallery card fill its column so it lines up with
   the (form + route map) stack on the left instead of leaving a raw gap. */
@media (min-width: 768px) {
  .same-height-desktop > .col-md-6:not(.nxt-content-search) { display: flex; flex-direction: column; }
  .same-height-desktop > .col-md-6:not(.nxt-content-search) > .boat-detail { flex: 1 1 auto; }
}

/* Give every route-map image the gallery's rounded corners. */
.tablemaps img,
#large-map,
a.map-small img { border-radius: var(--nxt-radius-sm); }

/* The large route map inside the schedules/description block: centre it and
   frame it like a card instead of a bare full-bleed image. */
.tablemaps { text-align: center; }
#large-map {
  display: inline-block;
  max-width: 100%;
  height: auto;
  border-radius: var(--nxt-radius);
  border: 1px solid var(--nxt-border);
  box-shadow: var(--nxt-shadow);
}

/* ============================================================
   Accessibility helpers
   ============================================================ */

/* Skip link (rendered first in <body> by start-of-body.phtml). Off-screen until
   focused, then slides into the top-left so keyboard/AT users can jump straight
   to <main id="main-content">. */
.nxt-skip-link {
  position: absolute;
  left: 8px;
  top: -60px;
  z-index: 2000;
  padding: 10px 16px;
  background: #fff;
  color: var(--nxt-blue-dark);
  border-radius: var(--nxt-radius-sm);
  box-shadow: var(--nxt-shadow);
  font-weight: 600;
  text-decoration: none;
  transition: top 0.15s ease-in-out;
}
.nxt-skip-link:focus {
  top: 8px;
  outline: 3px solid var(--nxt-blue-button);
  outline-offset: 2px;
}

/* Visible keyboard-focus indicator. Many nxt controls reset the browser default
   outline; :focus-visible restores a clear ring for keyboard users only (mouse
   clicks keep the clean look). WCAG 2.4.7 Focus Visible. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible,
.page-button:focus-visible {
  outline: 3px solid var(--nxt-blue-dark);
  outline-offset: 2px;
}

#main-content {
  margin-bottom: 1rem;
}

/* Approximate-price disclosure -------------------------------------------
   The trigger has to sit inside .approx-price without disturbing the muted
   one-line look those rules already give it, so the button is stripped back
   to text. The panel is a body-level element positioned by nxt-scripts.js;
   it is fixed rather than absolute because its triggers live in result-card
   columns and cart table cells that would clip an absolute child. */
/* Base rule: the older display:block declarations are scoped to the search
   result cards, but the hint now also appears against cart and confirmation
   totals, where it must not inherit the heading's weight and size. */
.approx-price {
  display: block;
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--nxt-text-muted);
}
.approx-price__toggle {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-decoration: underline dotted;
  text-underline-offset: 0.15em;
}
.approx-price__toggle:hover {
  color: var(--nxt-blue);
}
.approx-price__toggle:focus-visible {
  outline: 2px solid var(--nxt-blue);
  outline-offset: 2px;
  border-radius: 2px;
}
.approx-price__caret {
  display: inline-block;
  margin-left: 0.25em;
  border-top: 0.32em solid currentColor;
  border-right: 0.28em solid transparent;
  border-left: 0.28em solid transparent;
  vertical-align: 0.1em;
}
.approx-price__toggle[aria-expanded="true"] .approx-price__caret {
  transform: rotate(180deg);
}

.approx-panel {
  position: fixed;
  z-index: 1080; /* above Bootstrap's sticky header (1020), below its modals (1055+) */
  min-width: 11rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--nxt-border);
  border-radius: 0.5rem;
  background: #fff;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.14);
  font-size: 0.85rem;
  line-height: 1.45;
  text-align: left;
  color: var(--nxt-text);
}
.approx-panel[hidden] {
  display: none;
}
.approx-panel__row {
  display: flex;
  justify-content: space-between;
  gap: 1.5rem;
  white-space: nowrap;
}
.approx-panel__code {
  color: var(--nxt-text-muted);
}
.approx-panel__value {
  font-weight: 700;
}
.approx-panel__note {
  display: block;
  margin-top: 0.5rem;
  padding-top: 0.45rem;
  border-top: 1px solid var(--nxt-border);
  font-size: 0.75rem;
  font-weight: 400;
  color: var(--nxt-text-muted);
  white-space: normal;
}

/* Below md there is no room to anchor a popover beside a trigger that sits in
   the card's narrow price column, so the panel becomes a bottom sheet. */
@media (max-width: 767.98px) {
  .approx-panel--sheet {
    right: 0;
    bottom: 0;
    left: 0;
    min-width: 0;
    padding: 1rem 1.25rem calc(1rem + env(safe-area-inset-bottom));
    border-width: 1px 0 0;
    border-radius: 0.75rem 0.75rem 0 0;
    font-size: 1rem;
  }
  .approx-panel--sheet .approx-panel__row {
    padding: 0.2rem 0;
  }
}

/* ==========================================================================
   /admin/ai-prompt — the chat assistant's editable system prompt. The prompt is
   tens of kilobytes of prose, so the editor and the read-only preview panes get
   a monospace face, a fixed height and their own scroll rather than pushing the
   history table off the page.
   ========================================================================== */

textarea.ai-prompt-body {
  width: 100%;
  min-height: 60vh;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.85rem;
  line-height: 1.5;
  white-space: pre;
  overflow-wrap: normal;
  overflow-x: auto;
}

.ai-prompt-preview {
  max-height: 45vh;
  overflow: auto;
  padding: 0.75rem 1rem;
  background: #f7fafc;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius);
  font-size: 0.8rem;
  line-height: 1.5;
  white-space: pre-wrap;
}

/* Diffs stay unwrapped so a changed line reads as one line. */
.ai-prompt-diff { white-space: pre; }
.ai-prompt-diff span { display: block; }

/* ============================================================================
   CMS GRID CONTENT (route / boat / company cards, facts, options, FAQ)
   ----------------------------------------------------------------------------
   This markup is authored by the gridcontent importer + AI content generator,
   so it can appear on any site. The rules used to live, duplicated, in the
   per-site stylesheets (gilibookings.css, seychellesbookings.css and — already
   orphaned — thaibookings.css, vietnamferries.css), which nxt does not load:
   head.phtml links bootstrap5 + bootstrap-icons + this file only. Moving the
   block here is what keeps it alive for a site migrating from `blank` to `nxt`.
   Everything stays scoped to .cmscontent / #grideditorholder, the two wrappers
   the CMS renderer and the grid editor supply, so nothing leaks into chrome.
   gilibookings's copy was deleted with its stylesheet when it moved to nxt
   (2026-09-14); no `blank` site carries this block any more, so this is now the
   single source. The orphaned seychelles/thai/vietnam per-site stylesheets still
   contain a stale copy that nothing loads.
   ============================================================================ */

/* =========================
   Gecombineerde CSS via ai....
   (alleen binnen .cmscontent en #grideditorholder)
========================= */

/* Variabelen en basis — scoped */
.cmscontent,
#grideditorholder {
    --bg: #fff;
    --card: #bbdefb;
    --border: #90caf9;
    --muted: #4a5568;

    /* twee accenten bestonden — gekozen: #1976d2 (nieuwere FAQ) en fallback --accent-alt */
    --accent: #1976d2;
    --accent-alt: #64b5f6;

    --success: #16a34a;
    --warning: #f59e0b;
    --danger: #ef4444;

    --radius: 16px;
    --shadow: 0 0 0 1px rgba(0,0,0,.04), 0 8px 20px rgba(0,0,0,.06);

    --light-box: #f5f5f5;

    --fs-sm: .85rem;
    --fs-lg: 1.35rem;

    --card-bg: #bbdefb;
    --card-border: #90caf9;
    --white-card: #fff;
}

/* =========================
   ROUTE CARD + GENERIEKE OPTION/FACTS
========================= */
/* route-card & snippet-summary */
.cmscontent .route-card,
#grideditorholder .route-card,
.cmscontent .snippet-summary,
#grideditorholder .snippet-summary {
    width: 100%;
    max-width: 100%;
    margin: 0 auto;
    padding: 24px;
    box-sizing: border-box;
}

/* route-card specifics */
.cmscontent .route-card,
#grideditorholder .route-card {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    display: flex;
    flex-direction: column;
    gap: 20px;
    color: var(--muted);
}

/* Boat-info card authored without an <article class="route-card"> wrapper:
   some gridcontent places .company-header/.facts/.options directly into a grid
   column instead of wrapping them. Style that column's inner as the blue card
   so it matches the wrapped variant. The "> .company-header" direct-child test
   only matches the wrapper-less case, so route-card content is never
   double-carded. */
.cmscontent .column-inner:has(> .company-header),
#grideditorholder .column-inner:has(> .company-header) {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 24px;
    display: flex;
    flex-direction: column;
    gap: 20px;
    box-sizing: border-box;
    color: var(--muted);
}

/* header/title/label */
.cmscontent .route-header,
#grideditorholder .route-header {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
}

.cmscontent .route-title,
#grideditorholder .route-title {
    margin: 0;
    line-height: 1.3;
    margin-bottom: 8px;
    font-weight: normal;
}

.cmscontent .route-title .label,
#grideditorholder .route-title .label,
.cmscontent .label,
#grideditorholder .label {
    background: #119bd4;
    color: #fff;
    padding: 6px 10px;
    border-radius: 8px;
    font-weight: bold;
    font-size: 14px;
    display: inline-block;
    margin-right: 8px;
}

/* Facts grid (gebruik nieuwere min 180px voor betere layout) */
.cmscontent .facts,
#grideditorholder .facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 16px;
    margin-top: 0;
}

/* fact */
.cmscontent .fact,
#grideditorholder .fact {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px 16px;
    background: var(--bg);
    box-sizing: border-box;
}

.cmscontent .fact .k,
#grideditorholder .fact .k {
    margin-bottom: 4px;
}

.cmscontent .fact .value,
#grideditorholder .fact .value {
    font-weight: normal;
    font-size: inherit;
    line-height: 1.6;
    padding-left: 0;
}

/* list helpers */
.cmscontent .no-bullets,
#grideditorholder .no-bullets {
    list-style: none;
    padding-left: 0;
    margin: 0;
}

.cmscontent .indented-list,
#grideditorholder .indented-list {
    padding-left: 20px;
    margin: 0;
    list-style-type: disc;
}

/* Options (generiek) */
.cmscontent .options,
#grideditorholder .options {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.cmscontent .option,
#grideditorholder .option {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 16px;
    background: var(--bg);
    display: flex;
    justify-content: space-between;
    align-items: center;
}

/* variant: option displayed as row */
.cmscontent .option.row,
#grideditorholder .option.row {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

/* small UI pieces */
.cmscontent .option-title,
#grideditorholder .option-title {
    display: block;
    margin-bottom: 8px;
}

.cmscontent .light-box,
#grideditorholder .light-box {
    background: var(--white-card);
}

/* badges / bubbles */
.cmscontent .best-bubble,
#grideditorholder .best-bubble,
.cmscontent .slow-bubble,
#grideditorholder .slow-bubble,
.cmscontent .expensive-bubble,
#grideditorholder .expensive-bubble {
    display: inline-block;
    color: #fff;
    font-size: .7rem;
    font-weight: 600;
    padding: 1px 6px;
    border-radius: 8px;
    margin-left: 6px;
    vertical-align: middle;
}

.cmscontent .best-bubble,
#grideditorholder .best-bubble { background-color: var(--success); }
.cmscontent .slow-bubble,
#grideditorholder .slow-bubble { background-color: var(--warning); }
.cmscontent .expensive-bubble,
#grideditorholder .expensive-bubble { background-color: var(--danger); }

#grideditorholder .best-bubble,
.cmscontent .best-bubble,
#grideditorholder .slow-bubble,
.cmscontent .slow-bubble,
#grideditorholder .expensive-bubble,
.cmscontent .expensive-bubble {
    line-height:1.2
}
#grideditorholder .value.no-bullets li,
.cmscontent .value.no-bullets li {
    margin-bottom:4px;
}

/* badge used earlier */
.cmscontent .badge,
#grideditorholder .badge {
    padding: 4px 8px;
    border-radius: 999px;
    background: var(--success);
    color: #fff;
}

/* snippet-summary specifics (kept separate small padding) */
.cmscontent .snippet-summary,
#grideditorholder .snippet-summary {
    background: #fff;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 16px;
    margin-top: 16px;
    line-height: 1.5;
    color: #0f172a;
}

.cmscontent .snippet-summary strong,
#grideditorholder .snippet-summary strong {
    color: #0f172a;
}

/* =========================
   FAQ (samengevoegd + scoped)
========================= */
.cmscontent .faq-container,
#grideditorholder .faq-container {
    width: 100%;
    max-width: 1000px;
    margin: 20px auto;
    background: var(--card-bg);
    border: 2px solid var(--card-border);
    border-radius: 20px;
    padding: 40px 20px;
    box-sizing: border-box;
    box-shadow: 0 12px 30px rgba(0,0,0,.06);
}

.cmscontent .faq-container h2,
#grideditorholder .faq-container h2 {
    text-align: center;
    margin-bottom: 40px;
    color: #4f4f50;
}

.cmscontent .faq-item,
#grideditorholder .faq-item {
    max-width: 850px;
    margin: 0 auto 20px auto;
    background: var(--white-card);
    border-left: 4px solid var(--accent);
    border-radius: 12px;
    padding: 18px 24px;
    box-shadow: 0 6px 15px rgba(0,0,0,.08);
}

.cmscontent .faq-item .question,
#grideditorholder .faq-item .question {
    margin-bottom: 10px;
}

.cmscontent .faq-item .answer,
#grideditorholder .faq-item .answer {
    display: block !important;
    line-height: 1.5;
    margin: 0;
    padding: 0;
    color: var(--muted);
}

.cmscontent .faq-item .answer ul,
#grideditorholder .faq-item .answer ul {
    padding-left: 20px;
    margin: 0;
    list-style-type: disc;
}

.cmscontent .faq-item .answer ul li,
#grideditorholder .faq-item .answer ul li {
    margin-bottom: 15px;
}

.cmscontent .faq-item .answer ul li:last-child,
#grideditorholder .faq-item .answer ul li:last-child {
    margin-bottom: 0;
}

/* =========================
   COMPANY CARD
========================= */
.cmscontent .company-card,
#grideditorholder .company-card {
    width: 100%;
    margin-top: 25px;
    padding: 20px;
    box-sizing: border-box;
    background: var(--card);
    border: 1px solid #5a8dd1;
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    display: flex;
    flex-direction: column;
    gap: 22px;
    font-family: inherit;
    font-size: 14px;
    color: var(--muted);
}

.cmscontent .company-title,
#grideditorholder .company-title {
    color: #0f172a;
    display: flex;
    align-items: center;
    gap: 8px;
}

.cmscontent .company-card .label,
#grideditorholder .company-card .label {
    margin-right: 8px;
}

/* small tweaks */
.cmscontent .option .sub,
#grideditorholder .option .sub {
    color: #6b7280;
}

/* =========================
   BOAT CARD
========================= */
.cmscontent .boat-card,
#grideditorholder .boat-card {
    width: 100%;
    margin: 0;
    padding: 22px;
    box-sizing: border-box;
    background: var(--card);
    border: 1px solid #5a8dd1;
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    display: flex;
    flex-direction: column;
    gap: 22px;
    color: var(--muted);
}

/* Vertical spacing between stacked cards so consecutive card rows
   never touch (company-card already sets margin-top; match it here).
   Placed after the boat-card base rule so its margin:0 doesn't win. */
.cmscontent .route-card,
#grideditorholder .route-card,
.cmscontent .boat-card,
#grideditorholder .boat-card {
    margin-top: 25px;
}

.cmscontent .boat-header,
#grideditorholder .boat-header {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.cmscontent .title-text,
#grideditorholder .title-text {
    display: block;
    margin-top: 4px;
}

.cmscontent .option.routes,
#grideditorholder .option.routes {
    padding: 12px;
}

.cmscontent .option.routes .name,
#grideditorholder .option.routes .name {
    margin-bottom: 4px;
}

.cmscontent .option.routes ul,
#grideditorholder .option.routes ul {
    list-style-type: disc;
    padding-left: 16px;
    margin: 0;
    display: block;
    columns: 2;
    column-gap: 16px;
}

.cmscontent .option.routes ul li,
#grideditorholder .option.routes ul li {
    margin-bottom: 4px;
    break-inside: avoid;
}

/* =========================
   RESPONSIVE
========================= */
@media (max-width: 600px) {
    .cmscontent .faq-container h2,
    #grideditorholder .faq-container h2 {
        font-size: 1.25rem;
    }

    .cmscontent .facts,
    #grideditorholder .facts {
        grid-template-columns: 1fr;
    }

    .cmscontent .company-title,
    #grideditorholder .company-title {
        font-size: 28px;
    }

    .cmscontent .option,
    #grideditorholder .option {
        padding: 12px;
    }

    .cmscontent .option.routes ul,
    #grideditorholder .option.routes ul {
        columns: 1;
        column-gap: 0;
    }
}

/* =========================================================================
   Discount vouchers — /book/confirm
   =========================================================================
   modules/discount/.../discount-form.phtml renders an accordion of voucher
   offers ("Choose discount vouchers for any destination below"), grouped by
   location, with one selectable card per partner company. All of its styling
   lived in style.css, which nxt does not load, so under nxt the block rendered
   as bare text: no panel, no card per company, both accordion +/- glyphs
   visible at once, and each checkbox stacked above its label instead of beside
   it. Restyled here to nxt's card language rather than ported verbatim.

   Behaviour the CSS has to support (scripts/book.js + nxt-scripts.js):
   - clicking anywhere on a `.discounts` card toggles that company's checkboxes
     and adds/removes `.selected` — so the card needs a pointer cursor, a hover
     affordance and an unmistakable selected state;
   - `.discount-accordion-title` toggles `.active` on its `.discount-accordion-item`
     and slideToggles the body, with `.minus` shown only while open. */
.discount-accordion {
  margin-bottom: 1.25rem;
  padding: 1.5rem;
  background: #fff;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius);
  box-shadow: var(--nxt-shadow);
}
.discount-accordion > h2 {
  margin: 0 0 0.35rem;
  font-size: 1.5rem;
  color: var(--nxt-blue-dark);
}
/* The "For more information, see special offers" line that follows the h2. */
.discount-accordion > h2 + div {
  color: var(--nxt-text-muted);
  font-size: 0.95rem;
}

.discount-accordion-item + .discount-accordion-item {
  margin-top: 0.75rem;
  border-top: 1px solid var(--nxt-border);
}

/* Location header: a full-width toggle row with the glyph pinned right. */
.discount-accordion-title {
  position: relative;
  display: flex;
  align-items: center;
  margin: 0.75rem 0 0.5rem;
  padding: 0.6rem 2.25rem 0.6rem 0;
  color: var(--nxt-blue);
  font-size: 1.15rem;
  font-weight: 700;
  cursor: pointer;
  user-select: none;
}
.discount-accordion-title:hover { color: var(--nxt-blue-button); }
.discount-accordion-title .accordion_icon {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 1.6rem;
  height: 1.6rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: #eaf6fc;
  color: var(--nxt-blue);
  font-size: 1.1rem;
  font-weight: 700;
  line-height: 1;
}
/* Only one glyph at a time: plus while collapsed, minus while open. */
.discount-accordion-title .minus { display: none; }
.discount-accordion-item.active .discount-accordion-title .minus { display: inline-flex; }
.discount-accordion-item.active .discount-accordion-title .plus { display: none; }

/* One selectable card per partner company. */
.discounts {
  margin-bottom: 0.6rem;
  padding: 0.9rem 1rem;
  background: #fafafa;
  border: 1px solid var(--nxt-border);
  border-radius: var(--nxt-radius-sm);
  cursor: pointer;
  transition: border-color 0.18s ease, background-color 0.18s ease, box-shadow 0.18s ease;
}
.discounts:hover {
  border-color: #bfe0f0;
  background: #fff;
  box-shadow: var(--nxt-shadow);
}
.discounts.selected {
  background: #fff;
  border-color: var(--nxt-blue);
  box-shadow: inset 3px 0 0 var(--nxt-blue);
}

.discounts .discount_table { align-items: center; }
.discounts img { max-width: 100%; height: auto; }
.discounts .discount_table > .col-md-3 {
  color: var(--nxt-text-muted);
  font-size: 0.95rem;
  line-height: 1.45;
}
/* The template writes "<b>Name</b><br>Location", so leave the <b> inline — making
   it a block adds a second break on top of the <br> and splits the pair apart. */
.discounts .discount_table > .col-md-3 b { color: var(--nxt-text); font-size: 1rem; }

/* The options column is a flat run of <input> + .discount-label pairs; a
   2-column grid pairs each checkbox with its own label without floats. */
.discount-options {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.35rem 0.6rem;
  align-items: start;
}
.discount-options input[type="checkbox"] {
  width: 1.05rem;
  height: 1.05rem;
  margin: 0.15rem 0 0;
  accent-color: var(--nxt-blue);
  cursor: pointer;
}
.discount-label { padding: 0; }
.discount-label b { color: var(--nxt-text); }
.discount_description {
  margin-top: 0.1rem;
  color: var(--nxt-text-muted);
  font-size: 0.875rem;
  line-height: 1.5;
}

@media (max-width: 767px) {
  .discount-accordion { padding: 1rem; }
  .discount-accordion > h2 { font-size: 1.25rem; }
  .discounts .discount_table { align-items: flex-start; }
  .discount-label { margin-top: 0; }
}
