/* Magik: page components.
 *
 * Everything here sits on top of magik.css, which holds the design
 * system itself. Same tokens, no new colours.
 */

/* Icons.
 * One inline sprite per page, referenced with <use>. Every icon
 * inherits currentColor and the local font size. */
.ic{
  width:1.15em; height:1.15em; flex:none; display:inline-block;
  vertical-align:-.19em;
}
.ic.flip{transform:scaleX(-1)}
.pill .ic{width:1.05em; height:1.05em; margin-right:-1px}
.rate .ic{color:var(--wa); vertical-align:-.16em}

.ticks{list-style:none; margin:0; padding:0; display:grid; gap:11px}
.ticks li{
  display:flex; gap:11px; align-items:flex-start;
  font-size:15px; color:var(--muted); line-height:1.5;
}
.ticks .ic{color:var(--su-text); margin-top:.22em}
.ticks a{color:var(--ac)}
.ticks-row{
  display:flex; flex-wrap:wrap; gap:10px 26px; margin-top:28px;
  font-size:14px; color:var(--muted);
}
.ticks-row span{display:inline-flex; gap:8px; align-items:center}
.ticks-row .ic{color:var(--su-text)}

.specs{display:flex; flex-wrap:wrap; gap:7px 16px; font-size:13.5px; color:var(--muted)}
.specs span{display:inline-flex; gap:7px; align-items:center}
.specs .ic{color:var(--ac); opacity:.85}
/* The score its own clients gave it, in the row of facts about the boat.
   The star keeps its own colour: it is the one thing in that row that is
   an opinion rather than a measurement. */
.specs .spec-rate{font-weight:600; color:var(--ink)}
.specs .spec-rate .ic{color:var(--wa); opacity:1}
.specs .spec-rate em{font-style:normal; font-weight:400; color:var(--muted); opacity:1}

/* Interior page header: the same water as the home hero, shorter. */
.page-head{position:relative; padding-block:clamp(46px,7vw,86px) clamp(38px,5vw,62px)}
.page-head .wrap{position:relative; z-index:2; max-width:900px}
.page-water{
  position:absolute; left:0; right:0; top:calc(-1 * var(--header-h)); bottom:0;
  z-index:0; pointer-events:none; overflow:hidden; opacity:.86;
  -webkit-mask-image:linear-gradient(#000 0%, #000 56%, transparent 100%);
  mask-image:linear-gradient(#000 0%, #000 56%, transparent 100%);
}
.page-water canvas{width:100%; height:100%; display:block}
.page-head h1{font-size:clamp(36px,5.6vw,64px); margin-bottom:20px}
.page-head .lede{max-width:56ch}

.split-wide{
  display:grid; grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);
  gap:clamp(28px,4vw,56px); align-items:center;
}

/* Price calendar.
 * Each cell is coloured by which third of that month's own prices it
 * falls in, so a quiet month does not paint itself red. */
.cal{padding:20px}
.cal-bar{display:flex; align-items:center; justify-content:space-between; margin-bottom:14px}
.cal-month{
  font-family:"Bricolage Grotesque",sans-serif; font-variation-settings:"wdth" 86;
  font-weight:700; font-size:19px; letter-spacing:-.01em;
}
.cal-nav{
  width:36px; height:36px; border-radius:50%; cursor:pointer;
  border:1px solid color-mix(in srgb, var(--ink) 12%, transparent);
  background:color-mix(in srgb, var(--surface) 70%, transparent);
  color:var(--ink); display:grid; place-items:center;
  transition:border-color .16s, color .16s;
}
.cal-nav:hover{border-color:var(--ac); color:var(--ac)}
.cal-nav:focus-visible{outline:2px solid var(--ac); outline-offset:2px}

.cal-grid{display:grid; grid-template-columns:repeat(7,1fr); gap:5px}
.cal-dow{
  font-size:10.5px; letter-spacing:.09em; text-transform:uppercase;
  color:var(--muted); font-weight:600; text-align:center; padding-bottom:4px;
}
.cal-pad{aspect-ratio:1}
.cal-day{
  aspect-ratio:1; border:1.5px solid transparent; border-radius:13px;
  display:grid; place-content:center; gap:1px; cursor:pointer;
  font-family:"Lexend",sans-serif; line-height:1.1; padding:2px;
  transition:transform .14s, border-color .14s;
}
.cal-day b{font-size:14px; font-weight:600}
.cal-day i{font-style:normal; font-size:9.5px; font-variant-numeric:tabular-nums; opacity:.85}
.cal-day:hover{transform:translateY(-2px)}
.cal-day:focus-visible{outline:2px solid var(--ink); outline-offset:2px}
/* The app paints prices outside the brand palette on purpose: at this
   size the muted success/warning/danger collapse into one olive smudge,
   and a price grid is worthless if you cannot tell cheap from dear at a
   glance. These are PriceShade from PriceCalendar.swift, verbatim. */
:root{ --price-cheap:#00B84F; --price-typical:#F7B500; --price-dear:#F01E2C; }
.cal-day.is-low {background:color-mix(in srgb, var(--price-cheap) 17%, var(--surface));   color:#04702F}
.cal-day.is-mid {background:color-mix(in srgb, var(--price-typical) 22%, var(--surface)); color:#7A5606}
.cal-day.is-high{background:color-mix(in srgb, var(--price-dear) 15%, var(--surface));    color:#A0121C}
/* a cheap weekend is the find worth spotting, so it gets more than its
   tier colour: the price is underlined and the cell is ringed */
.cal-day.is-bargain{box-shadow:inset 0 0 0 1.5px color-mix(in srgb, var(--price-cheap) 55%, transparent)}
.cal-day.is-bargain i{text-decoration:underline; text-decoration-color:var(--price-cheap);
  text-underline-offset:2px; font-weight:600}
.cal-day.is-past{background:none; color:var(--faint); cursor:default; opacity:.5}
.cal-day.is-on{border-color:var(--ink); transform:translateY(-2px)}
/* a day no boat is free on: struck out and unpickable, as the app
   draws an owner's blackout */
.cal-day.is-off{background:color-mix(in srgb, var(--ink) 5%, transparent);
  color:var(--muted); cursor:default}
.cal-day.is-off b{text-decoration:line-through; text-decoration-color:var(--faint)}
.cal-day.is-today{border-color:color-mix(in srgb, var(--su) 60%, transparent)}

/* THE PRICE KEY. Three swatches and three words, and deliberately not a
   bar: a full-width rounded gradient along the bottom of a panel is a
   scrollbar, whatever it is labelled, and the first thing anybody did
   with it was try to drag it. The cells above already carry the ramp;
   this only has to name what the colours mean. */
.cal-scale{
  display:flex; flex-wrap:wrap; align-items:center; gap:6px 16px;
  margin-top:14px; font-size:11.5px; color:var(--muted);
}
.cal-scale span{display:inline-flex; align-items:center; gap:6px; flex:none}
.cal-scale i{width:9px; height:9px; border-radius:3px; display:block; flex:none}
.k-low {background:var(--price-cheap)}
.k-mid {background:var(--price-typical)}
.k-high{background:var(--price-dear)}
.cal-bargain-key{
  margin-top:8px; font-size:11px; color:var(--muted);
  display:flex; align-items:center; gap:7px;
}
.cal-bargain-key b{
  color:#04702F; font-weight:600; text-decoration:underline;
  text-decoration-color:var(--price-cheap); text-underline-offset:2px;
}
.cal-banner{
  margin-bottom:12px; font-size:13.5px; color:var(--muted);
  padding:10px 14px; border-radius:14px;
  background:color-mix(in srgb, var(--price-cheap) 10%, transparent);
}
.cal-banner b{color:var(--ink); font-weight:600}

.cal-readout{
  margin-top:14px; padding-top:14px;
  border-top:1px solid color-mix(in srgb, var(--ink) 9%, transparent);
  display:grid; gap:3px;
}
.cal-readout b{font-size:15.5px}
.cal-readout span{font-size:13px; color:var(--muted)}

/* Searchbar pickers.
 *
 * The two fields that used to be a native date input and an hours select
 * open panels instead: the priced calendar above, drawn small, and the
 * app's trip presets. Nothing new is invented here — the panel borrows
 * the calendar's own classes so a cell means the same thing in both. */
.sb-pick{position:relative}
.sb-val{
  border:none; background:none; padding:0; margin:0; width:100%;
  font-family:"Lexend",sans-serif; font-size:14.5px; line-height:1.35; font-weight:500;
  color:var(--ink); text-align:left; cursor:pointer;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.sb-val:focus{outline:none}
.sb-val .ic{width:14px; height:14px; margin-right:6px; color:var(--muted);
  vertical-align:-2px}
/* The When field answers two questions, so it carries two lines. The
   second is set tight: the bar is only ever as tall as its tallest
   field, so this line alone decides the height of the whole thing. */
.sb-val em{
  display:block; font-style:normal; font-size:11px; line-height:1.25;
  color:var(--muted); margin-top:0;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}

.sb-panel{
  position:absolute; top:calc(100% + 12px); left:0; z-index:40;
  width:min(364px, calc(100vw - 32px)); padding:16px; cursor:default;
  border-radius:var(--r-card); border:var(--cardbd);
  background:color-mix(in srgb, var(--surface) 98%, transparent);
  backdrop-filter:var(--blur); -webkit-backdrop-filter:var(--blur);
  box-shadow:0 3px 8px -4px rgba(var(--sh),.2), 0 30px 54px -28px rgba(var(--sh),.75);
}
.sb-panel[hidden]{display:none}
/* a panel hanging off the last field would run past the right edge */
.sb-panel.to-left{left:auto; right:0}

/* the calendar, at panel size */
.sb-panel .cal-bar{margin-bottom:10px}
.sb-panel .cal-month{font-size:16px}
.sb-panel .cal-nav{width:30px; height:30px}
.sb-panel .cal-nav[disabled]{opacity:.3; cursor:default}
.sb-panel .cal-grid{gap:3px}
.sb-panel .cal-dow{font-size:9.5px; letter-spacing:.04em; padding-bottom:2px}
.sb-panel .cal-day{border-radius:10px; padding:1px}
.sb-panel .cal-day b{font-size:12.5px}
.sb-panel .cal-day i{font-size:8.5px}
.sb-panel .cal-scale{margin-top:12px}
.sb-panel .cal-bargain-key{margin-top:6px}
/* the cheapest day is a button here, not a caption: it fills the field */
button.cal-banner{
  display:flex; align-items:center; gap:7px; width:100%; cursor:pointer;
  border:none; font-family:"Lexend",sans-serif; font-size:12.5px;
  color:var(--muted); text-align:left; padding:9px 12px;
}
button.cal-banner .ic{width:14px; height:14px; color:#04702F; flex:none}
button.cal-banner .cal-take{margin-left:auto; font-weight:600; color:#04702F}
button.cal-banner:hover{background:color-mix(in srgb, var(--price-cheap) 18%, transparent)}

/* Where the day goes: cities, the four runs everyone asks for, anything
   else typed in, and the chart of the run itself. */
.sb-panel.where{width:min(880px, calc(100vw - 32px)); padding:18px}
/* the chart is half the panel: it is the part that answers "how far is
   that, really" */
.where-cols{display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1.05fr); gap:18px}
.where-picks{min-width:0}
.pick-label{
  margin:0 0 8px; font-size:10.5px; letter-spacing:.13em; text-transform:uppercase;
  font-weight:600; color:var(--muted);
}
.pick-row{
  display:grid; gap:1px; width:100%; text-align:left; cursor:pointer;
  padding:8px 11px; margin-bottom:5px; border-radius:13px;
  border:1.5px solid transparent; background:color-mix(in srgb, var(--ink) 4%, transparent);
  font-family:"Lexend",sans-serif; color:var(--ink);
  transition:border-color .15s, background .15s;
}
.pick-row{
  display:flex; align-items:baseline; justify-content:space-between; gap:12px;
}
.pick-row b{font-size:14px; font-weight:600}
.pick-row i{font-style:normal; font-size:11.5px; color:var(--muted); white-space:nowrap}
.pick-row.on i{color:color-mix(in srgb, #fff 70%, transparent)}
.pick-label.mt{margin-top:16px}
.kind-list{display:grid; gap:5px}
.pick-row:hover{border-color:var(--ac)}
.pick-row:focus-visible{outline:2px solid var(--ac); outline-offset:2px}
/* WHAT IS SELECTED IS THE OCEAN, NOT INK.
   These three — the one-day/several-days tabs, the length presets and
   the trip rows — all filled with --ink when chosen, so the busiest
   panel on the site had two or three near-black slabs in it at any
   moment. Black is not in this palette: it is the colour of the type,
   and a fill the same colour as every word around it reads as a hole
   rather than as a choice.
   Caustics Ocean Blue is. White on #1E7F8C is 4.8:1, it is the deep half
   of the brand's own water, and it leaves Living Coral to mean the one
   thing it means everywhere else on this site — the button that does
   something. Selected is not an action; Done is. */
.pick-row.on{background:var(--sea-b); border-color:var(--sea-b); color:#fff}
.pick-row.on i{color:color-mix(in srgb, #fff 76%, transparent)}
.pick-row.is-off{opacity:.42; cursor:default}
.pick-row.is-off:hover{border-color:transparent}
/* A disabled row is still readable — it is telling you what this boat is
   not, and a row you cannot read tells you nothing. */
.pick-row:disabled{opacity:.42; cursor:default}
.pick-row:disabled:hover{border-color:transparent}

.where-custom{margin-top:14px}
.where-typed{display:flex; gap:6px}
.where-go{
  flex:none; width:38px; border-radius:12px; cursor:pointer;
  border:1.5px solid color-mix(in srgb, var(--ac) 45%, transparent);
  background:color-mix(in srgb, var(--tint2) 60%, transparent);
  color:var(--ac); display:grid; place-items:center;
}
.where-go:hover{background:var(--tint2); border-color:var(--ac)}
.where-go:focus-visible{outline:2px solid var(--ac); outline-offset:2px}
.where-go .ic{width:17px; height:17px}
.where-custom input{
  flex:1; min-width:0; padding:9px 12px; border-radius:12px;
  border:1.5px solid color-mix(in srgb, var(--ink) 12%, transparent);
  background:color-mix(in srgb, var(--surface) 70%, transparent);
  font-family:"Lexend",sans-serif; font-size:13.5px; color:var(--ink);
}
.where-custom input:focus{outline:2px solid var(--ac); outline-offset:1px}
.where-custom .fine{margin-top:7px}

/* the chart of the run, floating beside the choices */
.where-map{
  border-radius:16px; overflow:hidden; align-self:stretch;
  display:flex; flex-direction:column;
  border:1px solid color-mix(in srgb, var(--ink) 10%, transparent);
  background:color-mix(in srgb, var(--tint2) 40%, transparent);
}
.rt-chart{display:block; width:100%; height:auto; flex:1; min-height:0; background:#AAD3DF}
.rt-chart[hidden]{display:none}
.rt-line{
  fill:none; stroke:var(--ink); stroke-width:2.6; stroke-linecap:round;
  stroke-dasharray:7 6; opacity:.85;
}
.rt-way{fill:#fff; stroke:var(--ink); stroke-width:1.6; opacity:.9}
.rt-pin circle{fill:#fff; stroke:var(--ink); stroke-width:2}
.rt-pin .rt-dot{fill:var(--ink); stroke:none}
.rt-pin.is-to circle{stroke:var(--da)}
.rt-pin.is-to .rt-dot{fill:var(--da)}
.rt-legend{
  display:flex; flex-wrap:wrap; gap:4px 14px; justify-content:space-between;
  padding:9px 12px 0; font-size:11.5px; color:var(--muted);
}
.rt-legend b{color:var(--ink); font-weight:600}
.rt-note{margin:2px 12px 0; font-size:11px}
.rt-attr{margin:6px 12px 10px; font-size:10.5px}
.rt-attr a{color:var(--muted)}

/* who is coming, and how much beer */
.sb-panel.kind,.sb-panel.beers{width:min(330px, calc(100vw - 32px))}
/* the party rows need room for a name, a line under it and a stepper */
.sb-panel.guests{width:min(376px, calc(100vw - 32px))}
.sb-panel.guests .len-row .qty{min-width:44px}

/* One row per kind of passenger, ruled off from the next: they are four
   separate answers, not one list. */
.guest-rows{display:grid; margin-top:2px}
.guest-row{
  display:flex; align-items:center; justify-content:space-between; gap:16px;
  padding:13px 0;
  border-top:1px solid color-mix(in srgb, var(--ink) 9%, transparent);
}
.guest-row:first-child{border-top:none; padding-top:2px}
.guest-row:last-child{padding-bottom:2px}
.g-name{display:grid; gap:2px; min-width:0}
.g-name b{font-size:14.5px; font-weight:600}
.g-name i{font-style:normal; font-size:11.5px; color:var(--muted)}
.guest-row .stepper .qty{min-width:28px}
/* a spent button does not light up under the cursor */
.stepper button:disabled:hover{background:none; color:var(--ink)}
/* the one question in the panel that is answered with words */
.g-link{
  justify-self:start; padding:0; border:none; background:none; cursor:pointer;
  font-family:"Lexend",sans-serif; font-size:11.5px; color:var(--muted);
  text-align:left; text-decoration:underline; text-underline-offset:2px;
}
.g-link:hover{color:var(--ink)}
.g-link:focus-visible{outline:2px solid var(--ac); outline-offset:2px; border-radius:3px}
/* the notes are about the party as a whole, so they stand off the last row */
.sb-panel.guests [data-out="guestnote"]{
  margin-top:12px; padding-top:11px;
  border-top:1px solid color-mix(in srgb, var(--ink) 9%, transparent);
}
.g-service{margin-top:7px}
.g-service[hidden]{display:none}
/* One bottle per beer. It is the only count on the site kept in pictures,
   and the cooler is the one place that should be. */
.beer-wall{
  display:flex; flex-wrap:wrap; align-items:center; gap:1px 2px;
  margin-top:11px; font-size:16px; line-height:1.3;
}
.beer-wall[hidden]{display:none}
.beer-wall span{animation:beer-pop .34s cubic-bezier(.2,1.5,.5,1) backwards}
.beer-many{
  font-size:12.5px; font-weight:600; color:var(--muted);
  margin-left:6px; animation:none
}
@keyframes beer-pop{
  from{opacity:0; transform:translateY(-7px) scale(.5) rotate(-14deg)}
}
@media (prefers-reduced-motion:reduce){.beer-wall span{animation:none}}

/* The one button on the page that is allowed to shout: it is the only way
   into the menu from the bar. */
.btn.glow{
  width:100%; justify-content:center; margin-top:12px;
  box-shadow:0 0 0 0 color-mix(in srgb, var(--su) 55%, transparent);
  animation:glow-pulse 2.6s ease-in-out infinite;
}
.btn.glow:hover{animation-play-state:paused}
@keyframes glow-pulse{
  0%,100%{box-shadow:0 0 0 0 color-mix(in srgb, var(--su) 52%, transparent)}
  50%{box-shadow:0 0 0 9px color-mix(in srgb, var(--su) 0%, transparent)}
}

/* The calendar and everything that qualifies it, side by side: a control
   below the grid in a popover is a control nobody scrolls to. */
.sb-panel.cal{width:min(700px, calc(100vw - 32px))}
.when-cols{display:grid; grid-template-columns:minmax(0,1fr) minmax(0,.82fr); gap:18px}
.when-cal{min-width:0}
.when-side{
  min-width:0; display:flex; flex-direction:column; gap:10px;
  padding-left:18px; border-left:1px solid color-mix(in srgb, var(--ink) 9%, transparent);
}
.when-side .pick-label{margin:2px 0 0}
.when-side .len-chips{gap:5px}
.when-side .lenchip{padding:7px 11px}
.when-side .lenchip b{font-size:13px}
.when-side .lenchip i{font-size:11px}
.when-side .len-custom{margin:0; padding:10px 0 0; gap:8px}
.when-done{margin-top:auto; width:100%; justify-content:center}

/* One day or a stay, and which leg is being picked. */
.trip-tabs{display:flex; gap:6px}
.trip-tab{
  flex:1; display:flex; align-items:center; justify-content:center; gap:7px;
  padding:9px 10px; border-radius:13px; cursor:pointer; font-size:13px; font-weight:600;
  font-family:"Lexend",sans-serif; color:var(--ink);
  border:1.5px solid color-mix(in srgb, var(--ink) 10%, transparent);
  background:color-mix(in srgb, var(--ink) 4%, transparent);
}
.trip-tab .ic{width:15px; height:15px; color:var(--ac)}
.trip-tab.on{background:var(--sea-b); border-color:var(--sea-b); color:#fff}
.trip-tab.on .ic{color:var(--sea-a)}
/* Several days, on a boat with nowhere to sleep */
.trip-tab:disabled{opacity:.42; cursor:default}
.trip-tab:disabled .ic{color:var(--muted)}
.leg-tabs{display:flex; gap:8px}
.leg-tabs[hidden]{display:none}
.leg-tab{
  flex:1; display:grid; gap:2px; text-align:left; cursor:pointer;
  padding:8px 11px; border-radius:12px; font-family:"Lexend",sans-serif;
  border:1.5px solid color-mix(in srgb, var(--ink) 10%, transparent);
  background:color-mix(in srgb, var(--surface) 60%, transparent); color:var(--muted);
}
.leg-tab i{
  font-style:normal; font-size:9.5px; letter-spacing:.12em; text-transform:uppercase;
  font-weight:600;
}
.leg-tab b{font-size:13.5px; color:var(--ink); font-weight:600}
.leg-tab.on{border-color:var(--sea-b); background:color-mix(in srgb, var(--surface) 92%, transparent)}
.when-side .len-chips[hidden],.when-side .len-custom[hidden]{display:none}

/* both ends of a stay are dark; the nights between are tinted */
.cal-day.is-start{background:var(--su); border-color:var(--su); color:var(--onacc)}
.cal-day.is-start i{font-weight:600}
.cal-day.is-range{background:color-mix(in srgb, var(--tint) 75%, transparent)}

/* how long you are out: the app's presets over the two values the
   search actually carries, the hour you leave and the hours aboard */
.len-chips{display:grid; gap:6px}
.lenchip{
  display:grid; grid-template-columns:auto 1fr; align-items:center;
  column-gap:11px; padding:9px 13px; border-radius:16px; cursor:pointer;
  text-align:left; font-family:"Lexend",sans-serif; color:var(--ink);
  border:1.5px solid color-mix(in srgb, var(--ink) 10%, transparent);
  background:color-mix(in srgb, var(--surface) 60%, transparent);
  transition:border-color .15s, background .15s, color .15s;
}
.lenchip .ic{grid-row:1 / span 2; width:19px; height:19px; color:var(--ac)}
.lenchip b{font-size:13.5px; font-weight:600}
.lenchip i{font-style:normal; font-size:11.5px; color:var(--muted)}
.lenchip:hover{border-color:var(--ac)}
.lenchip:focus-visible{outline:2px solid var(--ac); outline-offset:2px}
.lenchip.on{background:var(--sea-b); border-color:var(--sea-b); color:#fff}
.lenchip.on .ic{color:var(--sea-a)}
.lenchip.on i{color:color-mix(in srgb, #fff 76%, transparent)}

.len-custom{
  margin-top:12px; padding-top:12px; display:grid; gap:9px;
  border-top:1px solid color-mix(in srgb, var(--ink) 9%, transparent);
}
.len-row{display:flex; align-items:center; justify-content:space-between; gap:12px}
.len-row > span{font-size:12.5px; color:var(--muted)}
.len-row .qty{
  font-size:14px; font-weight:600; min-width:62px; text-align:center;
  font-variant-numeric:tabular-nums;
}
.len-foot{display:flex; align-items:center; gap:12px; justify-content:space-between}
.len-foot .fine{margin:0}

@media (max-width:900px){
  /* the chart drops under the choices before it gets too small to read */
  .where-cols{grid-template-columns:1fr 1fr}
  .where-map{grid-column:1 / -1}
  .sb-panel.where{width:min(520px, calc(100vw - 32px))}
}
@media (max-width:760px){
  /* there is no "beside" on a phone */
  .when-cols{grid-template-columns:1fr}
  .when-side{padding-left:0; border-left:none; padding-top:14px;
    border-top:1px solid color-mix(in srgb, var(--ink) 9%, transparent)}
}
/* ---- the bar folds at 1040, and so does what a panel can hang off ----
   A panel is a child of its field and drops from it, which is right for
   as long as a field is a whole column of the bar. At 1040 the bar folds
   to two abreast and the field stops being one: a 668px calendar hung
   off a 334px half-row, then flipped left to keep its right edge on
   screen, put its LEFT edge twelve pixels off the other side of the
   window -- so on a tablet, and on any laptop window under about 760,
   the first column of the month was cut off by the edge of the glass.
   The bar becomes the panel's containing block the moment the bar folds,
   so `left:0` is the bar's left edge and every panel -- each already
   capped at `100vw - 32px` -- lands inside the window by construction.
   Widths are untouched: a guests panel is 376px because that is what it
   was drawn at, and it stays 376 here. Only what it is measured FROM
   changes, and the top, which is the pressed field's -- see the note in
   the phone block below, which is where this went wrong first. */
@media (max-width:1040px){
  .searchbar{position:relative}
  .sb-pick{position:static}
  /* `max-width:100%` is the bar, now that the bar is the containing
     block, and it is doing what each panel's own `calc(100vw - 32px)`
     was written to do and cannot. That cap assumes a 16px gutter; the
     page's gutter is `clamp(20px,5vw,40px)`, which at 700px is 35 -- so
     the calendar capped itself at 668 inside a bar 630 wide, and flipping
     it right-aligned pushed its left edge four pixels off the window.
     Measured against the bar there is nothing to assume. */
  .sb-panel{left:0; max-width:100%; top:calc(var(--sb-top, 100%) + 12px)}
  .sb-panel.to-left{left:auto; right:0}

  /* ---- except the docked bar, which is not a bar to measure against ----
     Docked, the whole search is a 160px strip in the header, and every
     rule above says "as wide as the bar". So the where panel -- a list of
     destinations with a chart under it -- opened at a hundred and forty
     pixels: a column of clipped words beside a sliver of map. It has been
     that since the phone rules were written; hanging the panel off the
     bar is right for a bar that is the width of the page and wrong for
     one that has been folded into the header to get out of the way.
     So it steps back out to the window. Still absolutely positioned
     against the bar -- `position:fixed` would be read against the
     viewport by some browsers and against .header-bar by others, which
     animates its transform and therefore becomes the containing block for
     anything fixed inside it -- but pulled left by exactly the distance
     the bar's own edge sits from the window's, which searchbar.js
     measures as `--sb-dx`. The result is a panel 12px inside each edge of
     the screen, wherever in the header the bar happens to be. */
  .searchbar.is-docked .sb-panel,
  .searchbar.is-docked .sb-panel.to-left{
    left:calc(-1 * var(--sb-dx, 0px)); right:auto;
    width:calc(100vw - 24px); max-width:none;
    max-height:min(72vh, var(--sb-max, 72vh)); overflow:auto;
  }
}

@media (max-width:620px){
  .where-cols{grid-template-columns:1fr}
  .sb-panel.where,.sb-panel.guests,.sb-panel.kind,.sb-panel.beers,.sb-panel.cal{width:auto}
  /* THE PANEL IS AS WIDE AS THE BAR AND AS LOW AS THE FIELD.
     Those are two different questions and this used to answer both with
     the bar. The width has to be the bar's: stacked, a field is the full
     column, but folded two abreast it is half of one, and 160px of
     calendar is not a calendar. So the bar stays the containing block,
     which is what `position:static` on the pick is doing here.
     The TOP is the field's, and getting that from the bar was the bug.
     Along a row every field shares one bottom edge, so `100%` of the bar
     and `100%` of the field are the same line and nobody could tell
     which one was meant. Stacked they are nothing like each other: the
     bar is a column five fields deep, so pressing WHERE -- the FIRST
     row -- opened its panel three hundred and fifty pixels further down,
     under the search button, past the bottom of the screen. The panel
     was drawn, correctly, exactly where nobody would look for it, and
     the press read as nothing having happened.
     `--sb-top` is the pressed field's own bottom edge, measured against
     the bar by the opener in searchbar.js. The fallback is the old
     behaviour, so a panel opened before the script has measured it lands
     where it always did rather than at the top of the bar. */
  .searchbar{position:relative}
  .sb-pick{position:static}
  .sb-panel,.sb-panel.to-left{
    left:6px; right:6px; width:auto;
    top:calc(var(--sb-top, 100%) + 10px);
    /* AND ONLY AS TALL AS THE ROOM UNDER IT.
       72vh was measured against a panel that hung off the bottom of the
       bar, where the bar is the last thing on the screen and the whole
       72 is below it. Hung off a field it is not: the calendar is 608px
       and the WHEN row is 411 down the page, so two hundred pixels of it
       -- including Done -- were off the bottom of the screen, and the
       fix for a panel that is hard to find should not be a panel you
       have to scroll the page to finish reading.
       `--sb-max` is what is actually left below the pressed field. The
       panel already scrolls inside itself, so a long month gives up its
       tail to its own scrollbar rather than to the fold. */
    max-height:min(72vh, var(--sb-max, 72vh)); overflow:auto;
  }
}


/* ---------- Magik people ----------
 *
 * The pillars are a photograph and one sentence each: the picture rises
 * into place as the card arrives and lifts again under the cursor, so the
 * page moves the way the water behind it does rather than by decoration.
 */
.people-pillars{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr));
  gap:clamp(16px,2.4vw,26px);
}
.ppl{
  display:grid; gap:10px; align-content:start; padding:0 0 22px;
  border-radius:var(--r-card); overflow:hidden;
  background:color-mix(in srgb, var(--surface) 62%, transparent);
  border:var(--cardbd); box-shadow:var(--elev);
  backdrop-filter:var(--blur); -webkit-backdrop-filter:var(--blur);
  transition:transform .3s cubic-bezier(.22,.61,.36,1), box-shadow .3s;
}
.ppl:hover{transform:translateY(-5px); box-shadow:0 3px 7px -3px rgba(var(--sh),.24), 0 32px 52px -30px rgba(var(--sh),.75)}
.ppl-art{display:block; aspect-ratio:4/3; margin-bottom:4px; overflow:hidden}
.ppl-art img{width:100%; height:100%; object-fit:cover; transition:transform .5s cubic-bezier(.22,.61,.36,1)}
.ppl:hover .ppl-art img{transform:scale(1.06)}
.ppl .pill-n{margin:2px 22px 0}
.ppl h3{margin:0 22px; font-size:19px}
.ppl p{margin:0 22px; font-size:14.5px; color:var(--muted)}

/* The founders. No photographs yet, so the monogram is the portrait —
   drawn on purpose rather than a grey circle standing in for one. */
/* min(Npx,100%) rather than a bare Npx: a minmax minimum is a floor,
   not a preference, so auto-fit drops to one column and then makes that
   column the minimum WIDE -- wider than the phone it is on, and the
   whole page scrolls sideways. Same fix as `.detail-rest .faq`, which
   is where it was found. */
.founder-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(min(320px,100%),1fr)); gap:clamp(18px,2.6vw,30px)}
.founder{
  display:grid; grid-template-columns:auto 1fr; gap:20px; align-items:start;
  padding:24px; border-radius:var(--r-card);
  background:color-mix(in srgb, var(--surface) 58%, transparent);
  border:var(--cardbd); backdrop-filter:var(--blur); -webkit-backdrop-filter:var(--blur);
}
.mono{
  width:92px; height:92px; border-radius:26px; flex:none; overflow:hidden;
  display:grid; place-items:center; color:#fff;
  font-family:"Bricolage Grotesque",sans-serif; font-variation-settings:"wdth" 86;
  font-weight:700; font-size:30px; letter-spacing:-.02em;
  box-shadow:0 8px 18px -12px rgba(var(--sh),.9);
}
.mono img{width:100%; height:100%; object-fit:cover}
.mono-coral{background:radial-gradient(120% 120% at 20% 10%, var(--hi), var(--wa))}
.mono-ocean{background:radial-gradient(120% 120% at 20% 10%, var(--ac), var(--su))}
.founder-t{display:grid; gap:4px; min-width:0}
.founder-t b{font-size:19px; font-weight:600}
.founder-t i{
  font-style:normal; font-size:11px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--ac); font-weight:600;
}
.founder-t p{margin:8px 0 0; font-size:14.5px; color:var(--muted)}
.founder-line{
  display:flex; gap:8px; align-items:flex-start;
  color:var(--ink) !important; font-weight:500;
}
.founder-line .ic{width:16px; height:16px; flex:none; color:var(--su-text); margin-top:3px}

/* One member of crew, with the figures that describe the job. */
.staff-card{
  display:grid; grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);
  gap:clamp(20px,3vw,36px); padding:0; overflow:hidden; align-items:stretch;
}
.staff-art{position:relative; display:block; min-height:280px}
.staff-art img{width:100%; height:100%; object-fit:cover}
.staff-sticker{
  position:absolute; left:16px; bottom:16px;
  display:inline-flex; align-items:center; gap:7px;
  padding:8px 13px; border-radius:var(--r-chip);
  background:color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter:blur(8px); font-size:12.5px; font-weight:600;
  box-shadow:var(--elev); transform:rotate(-2deg);
}
.staff-sticker .ic{width:15px; height:15px; color:var(--ac)}
.staff-body{padding:clamp(22px,3vw,34px) clamp(22px,3vw,34px) clamp(22px,3vw,34px) 0}
.staff-body h3{margin:6px 0 10px; font-size:clamp(22px,2.4vw,30px)}
.staff-body .lede{font-size:16.5px; margin-bottom:10px}
.staff-body > p{font-size:14.5px; color:var(--muted)}

.kpis{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(120px,1fr)); gap:1px;
  margin:22px 0 12px;
  background:color-mix(in srgb, var(--ink) 8%, transparent);
  border:1px solid color-mix(in srgb, var(--ink) 8%, transparent);
  border-radius:16px; overflow:hidden;
}
.kpi{
  background:color-mix(in srgb, var(--surface) 74%, transparent);
  padding:14px 16px; display:grid; gap:2px;
}
.kpi b{font-size:22px; font-variant-numeric:tabular-nums; letter-spacing:-.01em}
.kpi i{font-style:normal; font-size:12.5px; color:var(--ink)}
.kpi em{font-style:normal; font-size:11.5px; color:var(--muted)}

@media (max-width:820px){
  .staff-card{grid-template-columns:1fr}
  .staff-art{min-height:220px}
  .staff-body{padding:0 clamp(20px,4vw,28px) clamp(22px,4vw,30px)}
  .founder{grid-template-columns:1fr}
  .mono{width:74px; height:74px; font-size:25px}
}


/* ---------- the week ahead ----------
 *
 * One row a day: the name, a bar of that day's wave against the roughest
 * in the week so the shape of the week reads before any number does, then
 * the figures and the verdict.
 */
/* The forecast page brings its own sheet — assets/css/forecast.css. It
   is the only page with a colour scale of its own, and a scale that
   means something is not a component: nothing else on the site may pick
   these up by accident. What used to be here (.fc-bar, the week grid,
   the three-way pill) is all in that file now, four-way and labelled. */

/* Price trend */
.trend{padding:22px 20px 14px}
.trend-svg{width:100%; height:auto; display:block; overflow:visible}
.trend-area{fill:url(#tg)}
.trend-line{fill:none; stroke:var(--su); stroke-width:2.6; stroke-linejoin:round; stroke-linecap:round}
.trend-pt circle{stroke:var(--surface); stroke-width:2.4}
.trend-pt.is-low  circle{fill:#4E9331}
.trend-pt.is-mid  circle{fill:#D9A21A}
.trend-pt.is-high circle{fill:#E0507F}
.trend-x{
  font-family:"Lexend",sans-serif; font-size:11px; fill:var(--muted);
  text-anchor:middle; font-variant-numeric:tabular-nums;
}
.trend-note{margin-top:6px; text-align:center}
.trend-note b{color:var(--ink); font-weight:600}

/* Sea conditions */
.weather{display:grid; gap:18px}
.weather-top{display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap}
.weather-grid{
  display:grid; grid-template-columns:repeat(3,1fr); gap:1px;
  background:color-mix(in srgb, var(--ink) 8%, transparent);
  border:1px solid color-mix(in srgb, var(--ink) 8%, transparent);
  border-radius:16px; overflow:hidden;
}
.weather-grid > div{
  background:color-mix(in srgb, var(--surface) 72%, transparent);
  padding:16px 12px; display:grid; justify-items:center; gap:3px; text-align:center;
}
.wx-ic{color:var(--ac); opacity:.8; font-size:17px; line-height:1}
.weather-grid b{font-size:19px; font-weight:600; letter-spacing:-.01em}
.weather-grid i{font-style:normal; font-size:11px; color:var(--muted)}
.pill.bad{background:color-mix(in srgb, var(--da) 15%, var(--bg)); color:var(--da)}
.weather.is-down .weather-grid{opacity:.5}

/* Featured amenity tiles on the home page */
.amen-featured{display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:16px}
.amen-tile{
  display:grid; gap:8px; align-content:start; padding:24px 22px 26px;
  text-decoration:none; color:inherit;
  background:var(--cardbg); border:var(--cardbd); border-radius:var(--r-card);
  box-shadow:var(--elev);
  backdrop-filter:var(--blur); -webkit-backdrop-filter:var(--blur);
  transition:transform .2s ease, border-color .2s ease;
}
.amen-tile:hover{transform:translateY(-4px); border-color:color-mix(in srgb, var(--ac) 40%, transparent)}
.amen-tile b{font-size:17px; font-weight:600; margin-top:4px}
.amen-tile i{font-style:normal; font-size:14px; color:var(--muted); line-height:1.45}
.amen-from{font-size:13px; color:var(--ac); font-weight:600; margin-top:4px}
.amen-tile .amen-ic{width:44px; height:44px; font-size:20px; color:var(--ac)}
.amen .amen-ic{color:var(--ac)}

/* Included as standard */
.incl{display:grid; gap:10px; align-content:start}
.incl-ic{
  width:44px; height:44px; border-radius:var(--r-chip); display:grid;
  place-items:center; font-size:20px; color:var(--ac);
  background:color-mix(in srgb, var(--tint2) 75%, transparent);
}
.incl p{font-size:14.5px; color:var(--muted)}

/* Role tiles carry icons rather than emoji now */
.ric .ic{width:1.05em; height:1.05em}
.safety-ic .ic{width:1.05em; height:1.05em}
.p-sbtn .ic{width:13px; height:13px}
.p-tabs .ic{width:13px; height:13px; display:block; margin-inline:auto}

/* Nav: current page */
.nav a[aria-current="page"]{color:var(--ink); font-weight:500}
.nav a[aria-current="page"]::after{right:0}

@media (max-width:1040px){
  .split-wide{grid-template-columns:1fr}
  .amen-featured{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:760px){
  .amen-featured{grid-template-columns:1fr}
  .weather-grid{grid-template-columns:repeat(2,1fr)}
  .cal{padding:14px}
  .cal-day{border-radius:10px}
  .cal-day b{font-size:12.5px}
  .cal-day i{font-size:8px}
}

/* ---------------------------------------------------------------
   Live position sharing
   --------------------------------------------------------------- */

/* Shown on every page for as long as a position is actually being
   sent. Someone whose location is leaving their device is told so. */
.share-chip{
  position:fixed; left:clamp(12px,3vw,24px); bottom:clamp(12px,3vw,24px); z-index:60;
  display:grid; grid-template-columns:auto 1fr; align-items:center;
  column-gap:10px; row-gap:1px; padding:10px 16px 10px 13px;
  border-radius:var(--r-card); max-width:min(320px, calc(100vw - 32px));
  background:color-mix(in srgb, var(--surface) 88%, transparent);
  border:var(--cardbd); box-shadow:var(--elev);
  backdrop-filter:var(--blur); -webkit-backdrop-filter:var(--blur);
}
.share-chip b{grid-column:2; font-size:12.5px; font-weight:550; line-height:1.3}
.share-chip i{
  grid-column:2; font-style:normal; font-size:11px; color:var(--muted);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.share-dot{
  grid-row:1 / span 2; width:9px; height:9px; border-radius:50%; background:var(--su);
  box-shadow:0 0 0 4px color-mix(in srgb, var(--su) 20%, transparent);
  animation:share-pulse 2.4s ease-in-out infinite;
}
@keyframes share-pulse{
  0%,100%{box-shadow:0 0 0 3px color-mix(in srgb, var(--su) 26%, transparent)}
  50%    {box-shadow:0 0 0 7px color-mix(in srgb, var(--su) 8%, transparent)}
}
@media (prefers-reduced-motion:reduce){ .share-dot{animation:none} }

/* A boat shown to someone not entitled to know whose it is: position
   only, and drawn so it reads as deliberately withheld rather than as
   missing data. */
.ais-row.anon .ais-swatch{
  background:var(--ac);
  box-shadow:0 0 0 4px color-mix(in srgb, var(--ac) 18%, transparent);
}
.ais-row.anon .ais-who b{color:var(--muted); font-style:italic}

/* Operations: the live board above the trip table */
.ops-live{padding:18px 20px; margin-bottom:18px}
.ops-live-list{list-style:none; margin:12px 0 0; padding:0; display:grid; gap:6px}
.ops-live-row{
  display:grid; grid-template-columns:auto 1fr auto auto; align-items:center; gap:12px;
  padding:11px 12px; border-radius:14px;
  background:color-mix(in srgb, var(--surface) 55%, transparent);
  border:1px solid color-mix(in srgb, var(--ink) 7%, transparent);
}
.olr-who{display:grid; gap:1px; min-width:0}
.olr-who b{font-size:13.5px; font-weight:550}
.olr-who i{
  font-style:normal; font-size:11px; color:var(--muted);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.olr-tel{display:grid; justify-items:end; gap:1px; flex:none}
.olr-tel b{font-size:12.5px; font-weight:600}
.olr-tel i{font-style:normal; font-size:11px; color:var(--muted)}
.ops-live-empty{
  padding:16px 12px; font-size:13px; color:var(--muted); line-height:1.6;
}
@media (max-width:720px){
  .ops-live-row{grid-template-columns:auto 1fr; row-gap:8px}
  .olr-tel{grid-column:1 / -1; justify-items:start}
  .ops-live-row .btn-ghost{grid-column:1 / -1; justify-self:start}
}

/* Result filters: sort on the left, toggles on the right. */
.filters{display:flex; flex-wrap:wrap; gap:10px 26px; margin-bottom:20px; align-items:center}
.filter-set{display:flex; flex-wrap:wrap; gap:7px; align-items:center}
.filter-label{
  font-size:10.5px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--muted); font-weight:600; margin-right:2px;
}
/* a chip with nothing to filter on is not drawn at all */
.chipbtn[hidden]{display:none}
.chipbtn{
  display:inline-flex; align-items:center; gap:6px; cursor:pointer;
  padding:8px 15px; border-radius:999px; font-family:"Lexend",sans-serif;
  font-size:13.5px; font-weight:500; color:var(--muted);
  border:1.5px solid color-mix(in srgb, var(--ink) 11%, transparent);
  background:color-mix(in srgb, var(--surface) 62%, transparent);
  transition:border-color .16s, color .16s, background .16s;
}
.chipbtn:hover{border-color:color-mix(in srgb, var(--ac) 45%, transparent); color:var(--ink)}
.chipbtn:focus-visible{outline:2px solid var(--ac); outline-offset:2px}
.chipbtn.on{
  border-color:var(--su); color:var(--su-text);
  background:color-mix(in srgb, var(--tint) 62%, transparent);
}
.chipbtn .ic{width:1em; height:1em}


/* =====================================================================
   THE BOAT CARD

   The card the fleet is browsed by. It is deliberately not the card the
   rest of this site uses.

   Everywhere else a card is an object: a plate, a border, a shadow, a
   lift on hover. That is right for one thing being offered — the four
   pillars, a role, a captain — and wrong for a list, because every one
   of those is a line drawn around a photograph, and twenty of them is a
   page of boxes with boats in them rather than a page of boats. So this
   one has no plate at all. The photograph is the card, the type sits on
   the page underneath it, and what separates one boat from the next is
   the gap between them.

   Four lines under the picture and no more: what it is called and what
   it scored, what it is, where it lies, what the day costs. Anything a
   fifth line would say is on the boat's own page, one click away, and a
   list that answers everything is a list nobody finishes.
   ===================================================================== */

/* Two rails' worth of cards. `.b-grid` fills the column it is given —
   beside a map that is two up, on a full-width page four — and `.b-rail`
   is the one-row version that scrolls sideways. */
.b-grid{
  display:grid; gap:26px 20px;
  grid-template-columns:repeat(auto-fill, minmax(232px, 1fr));
}
/* A CEILING ON THE TRACK, and it is not decoration. `1fr` has no maximum,
   so the width of a card in this rail was decided by how many cards were
   in it: seven boats gave 216px each, and a search that matched ONE boat
   gave that boat the whole 1100px — which, against a 1:1 crop, is an
   1100px photograph of a speedboat filling the screen under a heading
   that says "Free on Saturday". A rail is a row of cards whether it holds
   one or nine, so the track is bounded at both ends and the leftover
   space is left over. */
.b-rail{
  display:grid; grid-auto-flow:column; grid-auto-columns:minmax(216px, 268px);
  justify-content:start;
  gap:20px; overflow-x:auto; overscroll-behavior-x:contain;
  scroll-snap-type:x proximity; padding-bottom:6px;
  /* the rail runs to the edge of the page rather than stopping at the
     column, so the last card is visibly cut and the row reads as
     continuing rather than as ending */
  margin-inline:calc(-1 * var(--gut)); padding-inline:var(--gut);
  /* AND THE SNAP HAS TO KNOW ABOUT THAT PADDING.
     Snapping is measured against the snapport, which is the scrollport
     inset by scroll-padding — not by padding. With this unset the
     snapport was the whole box, so a card snapped flush to the bleeding
     edge and the row came to rest one gutter LEFT of its own heading:
     every rail on the home page sat 40px out of line with the title over
     it, and the row looked scrolled before anybody had touched it. */
  scroll-padding-inline:var(--gut);
  scrollbar-width:none;
}
.b-rail::-webkit-scrollbar{display:none}
.b-rail > .b-card{scroll-snap-align:start}

.b-card{position:relative; display:grid; gap:9px; align-content:start; min-width:0}

.b-shot{
  position:relative; display:block; aspect-ratio:1/1; overflow:hidden;
  border-radius:14px; background:color-mix(in srgb, var(--ink) 7%, transparent);
  text-decoration:none;
}
.b-shot img{width:100%; height:100%; object-fit:cover; display:block;
  transition:transform .55s cubic-bezier(.2,.9,.3,1)}
.b-card:hover .b-shot img{transform:scale(1.04)}
/* The whole card is one target. The heart is the only thing on it that
   is not, so it sits above the sheet rather than under it. */
.b-shot::after{content:""; position:absolute; inset:0; border-radius:inherit;
  box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--ink) 7%, transparent)}

/* One claim, top left, in the same white pill Instant book already uses
   elsewhere on the site. Never two: a photograph with a badge in every
   corner is an advertisement. */
.b-tag{
  position:absolute; left:10px; top:10px; z-index:2;
  display:inline-flex; align-items:center; gap:5px;
  padding:5px 11px; border-radius:999px;
  background:color-mix(in srgb, #fff 94%, transparent);
  color:var(--ink); font-size:12px; font-weight:600; letter-spacing:.01em;
  box-shadow:0 2px 8px -3px rgba(var(--sh),.5);
}
.b-tag .ic{width:13px; height:13px; color:var(--ac)}
.b-tag.promo{background:var(--su); color:var(--onacc)}
.b-tag.promo .ic{color:var(--onacc)}

.b-fav{
  position:absolute; right:9px; top:9px; z-index:3;
  width:32px; height:32px; display:grid; place-items:center;
  border:none; background:none; padding:0; cursor:pointer;
  color:color-mix(in srgb, #fff 92%, transparent);
  filter:drop-shadow(0 1px 3px rgba(0,0,0,.45));
  transition:transform .2s cubic-bezier(.34,1.5,.5,1);
}
.b-fav .ic{width:22px; height:22px; fill:rgba(0,0,0,.28)}
.b-fav:hover{transform:scale(1.12)}
.b-fav:focus-visible{outline:2px solid #fff; outline-offset:1px; border-radius:50%}
.b-fav.on{color:var(--hi)}
.b-fav.on .ic{fill:var(--hi)}

/* The name and the score share a line: the score is the one number that
   qualifies the name, so putting it anywhere else makes it a fact about
   the boat instead of a verdict on it. */
.b-line{display:flex; align-items:baseline; gap:10px}
.b-line h3{
  font-family:"Lexend",sans-serif; font-size:15.5px; font-weight:600;
  letter-spacing:-.005em; line-height:1.3; margin:0; min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.b-rate{
  margin-left:auto; flex:none; display:inline-flex; align-items:center; gap:4px;
  font-size:14px; color:var(--ink); font-variant-numeric:tabular-nums;
}
.b-rate .ic{width:13px; height:13px; color:var(--ink)}
.b-rate em{font-style:normal; color:var(--muted)}
/* A boat nobody has rated yet says nothing rather than saying zero. */
.b-rate.none{color:var(--muted); font-size:13px}

.b-sub{margin:0; font-size:14.5px; color:var(--muted); line-height:1.35;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.b-price{margin:2px 0 0; font-size:14.5px; color:var(--ink); line-height:1.35}
.b-price b{font-weight:600; text-decoration:underline; text-underline-offset:2px;
  text-decoration-thickness:1px}
.b-price s{color:var(--muted); text-decoration-thickness:1px; margin-right:5px}
.b-price i{font-style:normal; color:var(--muted); font-weight:400}

/* The card the map is pointing at, and the card the pointer is on. Same
   state, because they mean the same thing: this one. */
.b-card.lit .b-shot{outline:2px solid var(--ink); outline-offset:3px}

@media (max-width:520px){
  .b-grid{grid-template-columns:1fr; gap:30px}
  .b-shot{aspect-ratio:4/3}
}

/* The heading over a rail, and the way past it.

   THE TITLE IS THE LINK. It used to be a heading with "Show all" sitting
   off at the right-hand end, which is two objects and a stretch of empty
   rule between them for one errand — and the errand is "more of THIS",
   so the thing to press is the name of the thing. The arrow rides
   directly after the words and steps out under the pointer, which is the
   whole of the affordance: a title that moves is a title you can press.

   Two columns: the name, and the two arrows pinned to the right. */
.rail-head{
  display:grid; grid-template-columns:minmax(0,1fr) auto;
  align-items:center; gap:2px 16px;
  margin:0 0 clamp(14px,2vw,20px);
}
.rail-head h2{font-size:clamp(20px,2.3vw,26px); line-height:1.2; margin:0}
.rail-link{
  /* NOT .rail-title: boat-new.js's progress rail already owns that name
     for the "Your boat" caption over it, app.css loads after this file,
     and its `display:block; font-size:15px` quietly won — which is how
     every heading on the home page came to be set at 15 pixels. */
  display:inline-flex; align-items:center; gap:8px;
  color:inherit; text-decoration:none;
  transition:gap .25s cubic-bezier(.2,.9,.3,1);
}
.rail-link .ic{
  width:.72em; height:.72em; flex:none; color:var(--muted);
  transition:transform .25s cubic-bezier(.2,.9,.3,1), color .18s ease;
}
.rail-link:hover{gap:11px}
.rail-link:hover .ic{color:var(--ink); transform:translateX(2px)}
.rail-link:focus-visible{outline:2.5px solid var(--ac); outline-offset:4px; border-radius:8px}

/* ---- the two arrows ----
   The row hides its scrollbar, because a grey bar under a line of
   photographs is worse than a cut edge — so these are the only thing
   that says the row goes on, and they have to be honest about it. Greyed
   at each end rather than removed: a control that vanishes when you
   reach a wall is a control you have to hunt for again on the way back.
   app.js hides the pair outright when the whole row already fits. */
.rail-nav{grid-column:2; align-self:center; display:flex; gap:8px; flex:none}
.rail-nav[hidden]{display:none}
.rail-arrow{
  width:34px; height:34px; flex:none; display:grid; place-items:center;
  padding:0; cursor:pointer; border-radius:50%;
  background:var(--surface); color:var(--ink);
  border:1px solid color-mix(in srgb, var(--ink) 15%, transparent);
  box-shadow:0 1px 2px -1px rgba(var(--sh),.18);
  transition:background .18s ease, border-color .18s ease,
             opacity .18s ease, transform .18s ease;
}
.rail-arrow .ic{width:16px; height:16px}
.rail-arrow:hover{background:#fff; border-color:color-mix(in srgb, var(--ink) 32%, transparent)}
.rail-arrow:active{transform:scale(.94)}
.rail-arrow:focus-visible{outline:2.5px solid var(--ac); outline-offset:2px}
.rail-arrow:disabled{opacity:.32; cursor:default; box-shadow:none}
.rail-arrow:disabled:hover{background:var(--surface);
  border-color:color-mix(in srgb, var(--ink) 15%, transparent)}

/* A section the fleet could not fill leaves entirely — heading, subtitle
   and rail — rather than standing as an empty shelf. [hidden] alone
   would lose to the section's own display. */
.rail-sec[hidden]{display:none}

/* RAILS SIT CLOSER TOGETHER THAN SECTIONS DO.
   --sec is the gap between two DIFFERENT things — the search and the
   fleet, the fleet and the footer — and at 132px it is right for that.
   Six rails at that spacing is a page you scroll through a screen of
   sand between every row, and the rails stop reading as one list of the
   same fleet cut six ways and start reading as six unrelated pages.
   They are one thing, so they are one rhythm: enough air that a row
   plainly ends, not so much that the next one is a surprise.

   It is the END that gives, not the start: `.section + .section` already
   zeroes the top of every section after the first, so the gap between
   two rails is entirely the first one's bottom padding. Adding to the
   start here would have made the gap bigger, not smaller. The last rail
   keeps a full --sec under it, because the thing after THAT is the
   footer, which is a different thing again. */
.rail-sec{padding-block-end:clamp(34px,4vw,54px)}
.rail-sec:last-of-type{padding-block-end:var(--sec)}

/* The rail is the full width of a phone and it is a control, not the
   content: at 13.5px in 8x15 padding the chips were as heavy as the boat
   names underneath them. Down a size and in a notch, which is what a
   filter row is everywhere -- and the target does not move, because it
   was never the chip's own box (see the pointer:coarse block above). */
@media (max-width:560px){
  .filters{gap:8px 18px}
  .filter-set{gap:6px}
  .filter-label{font-size:9.5px; letter-spacing:.12em}
  .chipbtn{padding:6px 12px; font-size:12.5px; gap:5px}
}

/* On a phone the arrows go: there is nothing to press them with that is
   not already the gesture the row wants, and two 34px circles beside a
   heading that has to wrap is the heading losing. */
@media (max-width:700px){
  .rail-nav{display:none}
  .rail-head{grid-template-columns:minmax(0,1fr)}
}

/* =====================================================================
   THE SEARCH TABS

   Two things Magik sells, dead centre of the header, level with the mark
   and the button.

   THEY CARRY THEIR OWN GROUND. Bare type up here failed twice: white on
   pale turquoise water, then ink on the same water — and the second was
   legible without ever being noticeable, because the header is the one
   strip of this site where the background is a moving photograph of the
   sea and no single colour of type survives all of it.

   So the three of them stand on a plate of their own, and the selected
   one is a solid ink pill rather than a hairline underneath a word. That
   is the whole difference between "you can read which tab is selected"
   and "you can see it from across the room", and this is the control the
   entire site is steered with.

   The marks are the only coloured objects on the site. Everything else
   is one ink and one water, so three small marks in full colour are the
   only place the eye can land — which is what a chooser at the top of a
   page is for.
   ===================================================================== */
.tabs-head{
  position:absolute; left:50%; top:50%; translate:-50% -50%;
  pointer-events:none;                 /* the gap either side is the header's */
}
.tabs-head .search-tabs{pointer-events:auto}
/* A page with no search bar has nothing for these to be about, and
   docked there is a search bar where they were standing. site.js sets
   the first; the second is the dock's own class. */
.tabs-head[hidden],
.docked .tabs-head{display:none}

/* The plate. Same material as the search bar below it and the two
   glyphs beside it, so the header is one family of objects standing on
   the page rather than four unrelated things floating over it.
   The track is a shade darker than the pill that rides in it — that
   difference is the entire selected state, and it is enough. */
.search-tabs{
  display:inline-flex; align-items:stretch; gap:2px; margin:0;
  padding:4px; border-radius:999px;
  background:color-mix(in srgb, var(--ink) 7%, var(--surface));
  border:1px solid color-mix(in srgb, var(--ink) 9%, transparent);
  backdrop-filter:blur(16px) saturate(150%); -webkit-backdrop-filter:blur(16px) saturate(150%);
  box-shadow:0 1px 3px -1px rgba(var(--sh),.2), 0 14px 32px -20px rgba(var(--sh),.75);
}
/* Moved into the page, under a header too narrow to hold them. */
.tabs-slot .search-tabs{margin:0 auto clamp(10px,1.6vw,16px); display:flex; width:fit-content}

.stab{
  position:relative; display:inline-flex; align-items:center; gap:8px;
  padding:7px 16px 7px 9px; border-radius:999px; text-decoration:none;
  color:color-mix(in srgb, var(--ink) 74%, transparent);
  font-size:14.5px; font-weight:500; white-space:nowrap;
  transition:color .2s ease, background .25s ease;
}
.stab:hover{color:var(--ink); background:color-mix(in srgb, var(--surface) 55%, transparent)}
.stab:focus-visible{outline:2.5px solid var(--ac); outline-offset:2px}
/* The selected one is a raised pill in the page's own surface — quiet.
   It has been black and it has been coral and both were wrong for the
   same reason: this sits dead centre of the header, six inches from the
   wordmark, and a saturated block there is the first thing the eye lands
   on when the mark should be. Coral in particular is the site's ACTION
   colour — the search button, the current page in the drawer, every
   primary button — and a tab is not an action, it is where you already
   are.
   So the contrast moves off the pill and into the track behind it: the
   selected tab is lifted out of a slightly darker groove, which is how
   every segmented control on earth says "this one" without raising its
   voice. What colour there is up here belongs to the two marks. */
.stab.on{
  color:var(--ink); font-weight:650;
  background:var(--surface);
  box-shadow:0 1px 2px -1px rgba(var(--sh),.3), 0 3px 10px -5px rgba(var(--sh),.45);
}
.stab.on:hover{background:#fff}

/* ---- the marks ------------------------------------------------------
   Three tones and a warm accent, out of the site's own palette. Two
   tones was a silhouette: legible as a shape, unreadable as a speedboat
   at thirty pixels. The lit deck is what separates the hull from the
   cabin, and the warm line along the sheer is what makes it a boat
   rather than a wedge. */
.stab-ic{display:block; width:32px; height:32px; flex:none}
.stab-ic svg{width:100%; height:100%; display:block; overflow:visible}
.stab .t-deep{fill:var(--ac)}
.stab .t-mid {fill:color-mix(in srgb, var(--ac) 46%, #fff)}
.stab .t-lite{fill:color-mix(in srgb, var(--ac) 16%, #fff)}
/* The selected pill is the page's own surface now, which is the ground
   these marks were drawn for, so nothing has to be re-coloured for it.
   The only difference selection makes to a mark is that it comes up to
   full strength — which, with everything else up here neutral, is the
   loudest thing on the strip and still quieter than the wordmark. */
.stab .t-warm{fill:var(--su)}
/* An unselected mark steps back, it does not grey out. .78 rather than
   the .62 it was: at a third off, the three tones collapsed back into
   the silhouette they were drawn to escape. */
.stab-ic svg{opacity:.78; transition:opacity .25s ease}
.stab.on .stab-ic svg,
.stab:hover .stab-ic svg{opacity:1}

.sb-wake{fill:none; stroke:var(--ac); stroke-width:2.2; stroke-linecap:round; opacity:.42}
.sb-steam path{fill:none; stroke:var(--ac); stroke-width:2.3; stroke-linecap:round; opacity:0}

/* ---- arriving ------------------------------------------------------
   Once, on load. Everything else on this site announces itself when the
   page opens — the mark refracts, the bar drops in, the water starts —
   and these two sat there already finished, which read as two icons
   pasted on rather than two things the page had brought with it.
   The boat rides in on its own wake from the left; the plate and the
   glass land and settle. Both are done inside a second. */
@keyframes stab-sail{
  0%  {translate:-16px 3px; rotate:-9deg; opacity:0}
  55% {opacity:1}
  75% {translate:2px 0; rotate:2.5deg}
  100%{translate:0 0; rotate:0deg; opacity:1}
}
@keyframes stab-land{
  0%  {scale:.35; translate:0 -8px; opacity:0}
  55% {scale:1.1; translate:0 2px; opacity:1}
  78% {scale:.97; translate:0 0}
  100%{scale:1; translate:0 0; opacity:1}
}
@keyframes stab-wake-in{0%{opacity:0; translate:-12px 0} 100%{opacity:.42; translate:0 0}}

.stab[data-tab="boats"] .sb-hull{animation:stab-sail .95s cubic-bezier(.2,.9,.3,1) both}
.stab[data-tab="boats"] .sb-wake{animation:stab-wake-in .95s ease-out .1s both}
.stab[data-tab="food"] .sb-bowl {animation:stab-land .85s cubic-bezier(.2,.9,.3,1) .1s both}
.stab[data-tab="food"] .sb-glass{animation:stab-land .85s cubic-bezier(.2,.9,.3,1) .22s both}
.sb-bowl,.sb-glass{transform-origin:50% 80%}
.sb-hull{transform-origin:50% 78%}

/* ---- and what they do afterwards ------------------------------------
   Continuously, while the tab is selected or under the pointer. A single
   play would be the honest imitation of the sites that do this, but
   nothing else here moves once and stops: the water runs, the mark
   refracts, the sea chip reads. Small enough to be peripheral — you see
   it when you look at it and not before.

   The entrance has to finish first, so these carry its duration as a
   delay. Two animations on one property would otherwise both be running
   from frame one and the later one would win, which is the entrance
   never happening at all. */
@keyframes sb-rock{0%,100%{rotate:-3.5deg} 50%{rotate:3.5deg}}
@keyframes sb-run {0%{opacity:.16; translate:-3px 0} 50%{opacity:.7} 100%{opacity:.16; translate:3px 0}}
@keyframes sb-rise{0%{opacity:0; translate:0 3px} 28%{opacity:.9} 100%{opacity:0; translate:0 -7px}}

.stab.on .sb-hull, .stab:hover .sb-hull{
  animation:stab-sail .95s cubic-bezier(.2,.9,.3,1) both,
            sb-rock 3.4s ease-in-out .95s infinite;
}
.stab.on .sb-wake, .stab:hover .sb-wake{
  animation:stab-wake-in .95s ease-out .1s both,
            sb-run 3.4s ease-in-out 1.05s infinite;
}
.stab .sb-wake.w2{animation-delay:.1s, 2.15s}

.stab.on .sb-steam path, .stab:hover .sb-steam path{
  animation:sb-rise 2.9s ease-in-out infinite;
}
.stab .sb-steam .s2{animation-delay:-.55s}
.stab .sb-steam .s3{animation-delay:-1.25s}

@media (prefers-reduced-motion:reduce){
  .stab .sb-hull,.stab .sb-wake,.stab .sb-steam path,
  .stab .sb-bowl,.stab .sb-glass{animation:none}
  .stab .sb-wake{opacity:.42}
  /* the steam is invisible at rest, so without its animation the plate
     loses half of what it is drawn from */
  .stab .sb-steam path{opacity:.5}
}

@media (max-width:1400px){
  /* four words is a long tab beside a search bar. The mark carries it. */
  .stab[data-tab="food"] .stab-t{font-size:0}
  .stab[data-tab="food"] .stab-t::after{content:"Food"; font-size:15px}
}
@media (max-width:520px){
  .stab{font-size:14px; padding:5px 9px 10px; gap:7px}
  .stab-ic{width:27px; height:27px}
  .stab[data-tab="food"] .stab-t::after{font-size:14px}
}


/* ---- what a finger can hit: the parts this sheet owns ----------------
   The reasoning, and why there is a block like this in five sheets
   rather than one in magik.css, is at the foot of magik.css under WHAT
   A FINGER CAN ACTUALLY HIT. Short version: this file loads after that
   one, so the small sizes are set here and the fix has to be here too. */
@media (hover:none) and (pointer:coarse){
  /* Saving a boat, from the corner of its photograph. It gives back in
     inset what it takes in size, so the heart itself does not move: 32px
     at 9px from the corner and 44px at 3px both centre the glyph on the
     same point. */
  .b-fav{width:44px; height:44px; right:3px; top:3px}

  /* The boat's name and its score, which is the link out of a card whose
     photograph is also a link to the same place. Two targets 23px apart
     for one destination is how you press the wrong one; the row is the
     height of a thumb now and the type has not moved. */
  .b-line{min-height:44px; align-items:center}

  /* The filter chips. Same correction as the by-lines above: the first
     pass gave them `min-height:44px`, which does not give a chip a bigger
     TARGET, it gives it a bigger chip -- eight 44px lozenges filling the
     rail across the top of the results, so the sort control read as the
     loudest thing on a page whose subject is the boats under it. The chip
     keeps the size it is drawn at and carries the target invisibly. */
  .chipbtn{position:relative}
  .chipbtn::after{
    content:""; position:absolute; left:0; right:0; top:50%;
    height:44px; transform:translateY(-50%);
  }

  /* The link at the head of a rail -- "Popular boats ->". Its arrow is
     the only affordance the rail has left on a phone, where the two
     round arrow buttons are dropped. */
  .rail-link{min-height:44px; display:inline-flex; align-items:center}
}

/* ================================================================
   SAVED BOATS
   ================================================================

   Almost nothing, because the grid is .b-grid and the cards are the
   results page's own -- see saved.js for why that is not laziness. What
   is here is the line that says which dates the prices are for, and the
   empty state, which is the whole page for most of the people who ever
   reach it. */
.saved-for{
  margin:0 0 22px; font-size:14.5px; color:var(--muted);
}
.saved-for b{color:var(--ink); font-weight:550}
.saved-for a{color:var(--su-text)}

/* THE EMPTY STATE IS THE PAGE, most of the time. Somebody who has saved
   nothing and opened Saved has asked a question -- what is this for --
   and the answer is a sentence and a way out, not a shrug. */
.saved-none{
  display:grid; justify-items:center; text-align:center; gap:14px;
  max-width:46ch; margin:20px auto 40px; padding:44px 30px;
  background:var(--cardbg); border:var(--cardbd); border-radius:var(--r-card);
  box-shadow:var(--elev); backdrop-filter:var(--blur);
}
.saved-none .ic{width:34px; height:34px; color:var(--su); opacity:.85}
.saved-none h2{margin:0; font-size:22px}
.saved-none p{margin:0; color:var(--muted); font-size:15px; line-height:1.6}

/* ================================================================
   HELP CENTRE
   ================================================================

   A list of questions, not three thousand words. Every answer is folded
   away except the first of each group, because a page that opens with
   everything open is a page nobody reads any of. */
.help{display:grid; gap:34px; max-width:74ch; margin:0 auto}
.help-group h2{
  display:flex; align-items:center; gap:11px;
  margin:0 0 14px; font-size:21px; letter-spacing:-.01em;
}
.help-group h2 .ic{width:22px; height:22px; color:var(--su-text); flex:none}

.help-q{
  border-bottom:1px solid var(--hairline);
}
.help-q:first-of-type{border-top:1px solid var(--hairline)}
.help-q > summary{
  cursor:pointer; list-style:none; padding:15px 34px 15px 2px;
  font-size:16px; font-weight:500; position:relative;
}
.help-q > summary::-webkit-details-marker{display:none}
/* A chevron that turns, drawn rather than typed: a rotating "+" is two
   glyphs pretending to be one, and at 16px the join shows. */
.help-q > summary::after{
  content:""; position:absolute; right:6px; top:calc(50% - 4px);
  width:7px; height:7px; border-right:1.8px solid var(--muted);
  border-bottom:1.8px solid var(--muted); transform:rotate(45deg);
  transition:transform .22s cubic-bezier(.2,.9,.3,1);
}
.help-q[open] > summary::after{transform:rotate(-135deg)}
.help-q > summary:hover{color:var(--su-text)}
.help-q > summary:focus-visible{outline:2px solid var(--ink); outline-offset:3px; border-radius:8px}
.help-a{padding:0 34px 18px 2px; color:var(--muted); font-size:15px; line-height:1.65}
.help-a p{margin:0 0 11px}
.help-a p:last-child{margin-bottom:0}
.help-a b{color:var(--ink); font-weight:600}
.help-a a{color:var(--su-text)}

/* The three flags, and they take the colours the forecast gives them so
   that a client who has read this page recognises the flag on it. */
.help-flags{list-style:none; margin:12px 0 0; padding:0; display:grid; gap:9px}
.help-flag{
  display:grid; gap:3px; padding:12px 15px; border-radius:14px;
  border-left:3px solid var(--hairline);
  background:color-mix(in srgb, var(--ink) 3.5%, transparent);
}
.help-flag b{color:var(--ink); font-weight:600; font-size:14.5px}
.help-flag span{font-size:14px; line-height:1.55}
.help-flag.ok{border-left-color:#2F7D4F}
.help-flag.warn{border-left-color:var(--wa)}
.help-flag.bad{border-left-color:var(--da)}

.help-ask p{color:var(--muted); font-size:15px; line-height:1.65; margin:0 0 16px}
.help-ask-row{display:flex; flex-wrap:wrap; gap:12px}

/* What the total is worth in the money somebody chose, under the total
   it is actually charged in. Small and grey on purpose: it is a courtesy
   and never the figure being agreed to -- see the head of pay.js. */
.sum-fx{
  margin:10px 0 0; padding-top:10px; border-top:1px solid var(--hairline);
  font-size:11.5px; line-height:1.5; color:var(--muted);
}
.sum-fx b{color:var(--ink); font-weight:600}
