/*
 * 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;
  --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: 2rem; }
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;
}
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); }

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;
}
.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; }
}

/* ---------- 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; }

/* 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"] {
  /* 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 {
  border-color: var(--nxt-blue);
}
.search_form .field-options 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 {
  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;
}

/* 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;
}

/* ---------- 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;
}
.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;
}
.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); }

.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;
  }
}

/* ---------- 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-block;
  float: none;
  margin: 0.5rem 0 0;
  padding: 0.4rem 1.15rem;
  border: 1px solid var(--nxt-blue);
  border-radius: 999px;
  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; }
.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.4rem;
  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; }
}

/* 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;
  align-items: center;
  gap: 1rem;
  margin-top: 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); font-size: 0.88rem; }
#resultsMoreBoats .bookcontainer .book { float: none; margin: 0 0 0 auto; }
#resultsMoreBoats .bookcontainer .clear { display: none; }

/* 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); 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; }
}

/* ---------- 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; }

.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); }
.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; }

/* ---------- 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; }
}
/* 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); }
.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);
  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; }
.dev-bar-acceptance { background: var(--nxt-orange); }
#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%; }
.nxt-home .hotel_search .with-border.dark { border-left: 0; }
.nxt-home .hotel_search label:not(.radio) {
  display: block;
  font-weight: 600;
  color: var(--nxt-text);
  margin-bottom: 0.6rem;
}
.nxt-home .hotel_search .radio { display: block; padding: 0.35rem 0; font-weight: 500; }
.nxt-home .hotel_search .radio input { accent-color: var(--nxt-blue); margin-right: 0.4rem; }
.nxt-home .hotel_search .submit_button { margin-top: 1.35rem; align-self: flex-start; }

/* 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; }

/* ==========================================================================
   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 template: top-level "menu" content pages on activity-enabled
   sites (e.g. /things-to-do-in-fiji) render a "Book your activities" promo
   box (Search_IndexController::form-hotel) 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-blockpage-body::after { content: ""; display: block; clear: both; }
  .nxt-blockpage-sidebar {
    float: right;
    width: 45%;
    max-width: 620px;
    margin: 0 0 1.5rem 1.75rem;
  }
  /* Some blockpage content is still authored with the legacy row-fluid/spanN
     grid (e.g. /visit-fiji), not plain paragraphs (e.g. /things-to-do-in-fiji).
     Same fix as .has-search above: let a lone .span* row fill the width
     beside the float instead of sitting at half width, and clear every row
     after it so it drops BELOW the float at full width (a row-fluid is a
     flex formatting context and would otherwise keep dodging the float). */
  .nxt-blockpage-body .cmscontent .grid > .row-fluid:first-child > [class*="span"]:only-child {
    flex: 0 0 100%;
    max-width: 100%;
  }
  .nxt-blockpage-body .cmscontent .grid > .row-fluid:not(:first-child) {
    clear: right;
  }
}
@media (max-width: 991px) {
  .nxt-blockpage-sidebar { margin-bottom: 1.5rem; }
}

/* 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;
}

.cmscontent.accordion .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 { font-weight: 700; }
.cmscontent.accordion .accordion_item:hover,
.cmscontent.accordion .accordion_item.accordion_hover,
.cmscontent.accordion .accordion_item.accordion_active { color: var(--nxt-blue-dark); }

.cmscontent.accordion .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 { 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 { max-width: 74ch; }
.cmscontent.accordion .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; }
