/* The readers' site. Sunset Classic with air: sand paper, ink text, coral numerals, ocean
   links, one mango band. Colours, fonts and radii are the brand tokens (tokens.css, generated
   from docs/brand/production/tokens.json and inlined into the page). Phone first. */

/* The coconut's pose (0: waving, 1: hands folded in a wai) and the swing of its waving arm
   are numbers, so that the scroll position and the clock can drive them and every joint can
   be computed from them; --wake (0: asleep, 1: awake) is the third, for the night. The same for the fading edges of a scrolled row of chips. */
@property --pose {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}
@property --wake {
  syntax: "<number>";
  inherits: true;
  initial-value: 1;
}
@property --swing {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}
@property --fade-start {
  syntax: "<length>";
  inherits: false;
  initial-value: 0px;
}
@property --fade-end {
  syntax: "<length>";
  inherits: false;
  initial-value: 0px;
}

:root {
  --gutter: 20px;
  /* The marker the coconut's face and limbs are drawn with. */
  --coconut-ink: var(--color-ink);
  --on-action: #fff;
  /* Motion: one curve that settles softly, one with a little spring in it. */
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  --spring: linear(0, 0.36 9%, 0.74 19%, 1.02 31%, 1.1 40%, 1.06 51%, 1 68%, 0.99 82%, 1);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}
html {
  color-scheme: light;
  -webkit-text-size-adjust: 100%;
}
body {
  margin: 0;
  background: var(--color-sand);
  color: var(--color-ink);
  font: 16px/1.55 var(--font-sans);
  overflow-wrap: anywhere;
}
/* Decoration may reach past the edge (the moon's halo, a waving arm, a paper plane); the
   page never scrolls sideways for it. */
main,
.foot,
.pitch {
  overflow-x: clip;
}
h1,
h2,
h3,
p,
ul,
ol {
  margin: 0;
}
ul,
ol {
  padding: 0;
  list-style: none;
}
a {
  color: var(--color-ocean);
  text-underline-offset: 3px;
}
img,
svg {
  display: block;
  max-width: 100%;
}
a,
button,
summary {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}
:focus-visible {
  outline: 2px solid var(--color-ocean);
  outline-offset: 2px;
}
.skip {
  position: absolute;
  left: var(--gutter);
  top: -100px;
  z-index: 20;
  padding: 10px 14px;
  background: var(--color-ink);
  color: var(--color-sand);
  border-radius: var(--radius-control);
}
.skip:focus {
  top: 10px;
}

/* --- Header --- */

.top,
main,
.foot__inner {
  width: 100%;
  max-width: var(--content-max);
  margin-inline: auto;
  padding-inline: max(var(--gutter), env(safe-area-inset-left)) max(var(--gutter), env(safe-area-inset-right));
}
.top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding-top: max(14px, env(safe-area-inset-top));
  padding-bottom: 12px;
}
.wordmark {
  display: inline-flex;
  flex-direction: column;
  line-height: 1;
  text-decoration: none;
  view-transition-name: wordmark;
}
.wordmark__number {
  font: 400 40px/0.85 var(--font-wordmark);
  color: var(--color-coral);
  letter-spacing: -0.015em;
}
.wordmark__place {
  margin-top: 5px;
  font: 600 9px/1.3 var(--font-display);
  color: var(--color-ocean);
  letter-spacing: 0.19em;
  text-transform: uppercase;
}
.top__nav {
  display: flex;
  align-items: center;
  gap: 2px;
}
.top__nav a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding-inline: 9px;
  color: var(--color-ink);
  font: 500 15px/1 var(--font-display);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
}
.top__nav a[aria-current] {
  text-decoration: underline;
  text-decoration-color: var(--color-coral);
  text-decoration-thickness: 3px;
  text-underline-offset: 7px;
}
.top__nav .top__language {
  min-width: 44px;
  min-height: 36px;
  margin-left: 6px;
  border: 1.5px solid var(--color-ink);
  border-radius: var(--radius-control);
}

/* --- Type --- */

.kicker {
  margin-bottom: 10px;
  color: var(--color-muted);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
h1 {
  font: 500 clamp(32px, 8.6vw, 64px) / 1.06 var(--font-display);
  letter-spacing: 0.005em;
  text-transform: uppercase;
  text-wrap: balance;
}
h2 {
  font: 500 clamp(24px, 6vw, 30px) / 1.15 var(--font-display);
  letter-spacing: 0.01em;
  text-transform: uppercase;
  text-wrap: balance;
}
.lead {
  max-width: 34em;
  margin-top: 14px;
  font-size: 17px;
  text-wrap: pretty;
}
.quiet {
  color: var(--color-muted);
}
/* What a page or its clock hides stays hidden, whatever its own display. */
[hidden] {
  display: none !important;
}

/* --- Buttons --- */

.button {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  padding: 8px 18px;
  border: 1.5px solid var(--color-ocean);
  border-radius: var(--radius-control);
  background: var(--color-surface);
  color: var(--color-ocean);
  font: 600 16px/1.3 var(--font-sans);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--motion-ui), border-color var(--motion-ui);
}
.button small {
  font-size: 13px;
  font-weight: 400;
}
.button:hover {
  background: var(--color-ocean-soft);
}
.button--primary {
  border-color: var(--color-action);
  background: var(--color-action);
  color: var(--on-action);
}
.button--primary:hover,
.button--primary:active {
  border-color: var(--color-action-hover);
  background: var(--color-action-hover);
}
.channels {
  display: grid;
  gap: 12px;
  margin-top: 26px;
}
.web {
  margin-top: 14px;
  color: var(--color-muted);
  font-size: 14px;
}
.web a {
  display: inline-block;
  padding: 8px 4px;
  font-weight: 600;
}

/* --- Hero --- */

.hero {
  display: grid;
  gap: 22px;
  padding-block: 20px 8px;
}
/* The art is layers: the sun, the stamp, a handwritten note, the coconut on the waves. Each
   has its own element so that each can arrive and drift on its own. */
.hero__art {
  position: relative;
  display: grid;
  grid-template: "stamp note" auto "stamp rider" 1fr / auto 1fr;
  gap: 0 18px;
  align-items: start;
  isolation: isolate;
}
.hero__sun {
  position: absolute;
  z-index: -1;
  left: 58px;
  top: -8px;
  width: 112px;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--color-mango);
}
.hero__stamp {
  grid-area: stamp;
  width: 132px;
  height: auto;
  border-radius: var(--radius-art);
  rotate: -4deg;
  box-shadow: 0 0 0 1px var(--color-line);
}
.hero__note {
  grid-area: note;
  margin: 10px 0 0 30px;
  color: var(--color-ocean);
  font: 19px/1.25 var(--font-hand);
  rotate: -5deg;
}
.hero__rider {
  grid-area: rider;
  position: relative;
  justify-self: end;
  width: 150px;
  height: 124px;
}
.hero__rider .coconut {
  position: absolute;
  right: 12px;
  bottom: 6px;
  width: 116px;
}
.hero__waves {
  position: absolute;
  right: 0;
  bottom: 0;
  color: var(--color-ocean);
  opacity: 0.6;
}

/* The coconut greets beside the lead; the text runs round it. */
.hero__copy {
  position: relative;
}
.greeter-spot {
  position: relative;
  /* Above the paragraph it floats in: the paragraph's box lies over a float. */
  z-index: 2;
  float: right;
  width: 122px;
  margin: -4px -14px 0 2px;
  shape-outside: inset(0 14px 0 0 round 44%);
}
.greeter {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  cursor: pointer;
  /* Three numbers pose it: see "The coconut greets" in Motion. */
  --pose: 0;
  --swing: 0;
  --wake: 1;
}
/* What it says with its hands folded, written where the waving hand was. */
.greeter__wai {
  position: absolute;
  top: -10px;
  right: 12px;
  color: var(--color-ocean);
  font: 17px/1 var(--font-hand);
  white-space: nowrap;
  rotate: -8deg;
  opacity: calc(var(--pose) * 4 - 3);
  translate: 0 calc((1 - var(--pose)) * 8px);
  pointer-events: none;
}
.greeter .coconut {
  width: 100%;
}
.greeter__said {
  position: absolute;
  z-index: 3;
  top: 8px;
  right: 86%;
  width: max-content;
  max-width: min(236px, calc(100vw - 150px));
  margin: 0;
  padding: 9px 12px;
  border: 1.5px solid var(--color-ink);
  border-radius: var(--radius-card) var(--radius-card) 2px var(--radius-card);
  background: var(--color-surface);
  color: var(--color-ink);
  font-size: 14px;
  line-height: 1.4;
  text-align: left;
}
.greeter__said a {
  display: inline-block;
  margin-left: 4px;
  font-weight: 600;
  white-space: nowrap;
}
.greeter__said a::after {
  content: " \2192";
}
.channels {
  clear: both;
}
@media (min-width: 900px) {
  .hero {
    position: relative;
  }
  .hero__copy {
    position: static;
  }
  /* The gap below is the first block's top margin, and a little more for the air under its
     feet in the drawing: it stands on that block's rule. */
  .greeter-spot {
    position: absolute;
    bottom: -84px;
    left: 0;
    float: none;
    width: 150px;
    margin: 0;
    shape-outside: none;
  }
  .hero__copy:has(.greeter-spot) {
    padding-bottom: 96px;
  }
  .hero__cloud {
    top: -34px;
    right: 64px;
    left: auto;
    width: 150px;
  }
  .greeter__wai {
    top: -6px;
    right: 4px;
    font-size: 21px;
  }
  .greeter__said {
    top: 18px;
    right: auto;
    left: 92%;
    max-width: 280px;
    border-radius: var(--radius-card) var(--radius-card) var(--radius-card) 2px;
  }
}
/* Each greeting arm is one continuous curve; site.js follows the existing CSS clocks. */
.greet__figure,
.greet__leaf {
  transform-box: view-box;
}
.greet__palms {
  opacity: calc(var(--pose) * 5 - 4);
}
.coconut__smile { fill: none; stroke-width: 4; }
.coconut__mouth.coconut__sleep-mouth { fill: #1f1f1f; stroke: none; }
.fc__wai { display: none; }
.forecaster.is-wai .fc__wai { display: block; }
.forecaster.is-wai .fc__arms,
.forecaster.is-wai .fc__umbrella { opacity: 0; }

/* Under a leaf the word is written above it. */
.greeter[data-mood="rain"] .greeter__wai,
.greeter[data-mood="storm"] .greeter__wai {
  top: -30px;
}
/* It bows a little into the wai, and leans with its wave. */
.greet__torso {
  translate: 0 calc(var(--pose) * 6px);
}
.greet__figure {
  transform-origin: 122px 228px;
  rotate: calc(var(--swing) * -1.8deg * (1 - var(--pose)) * var(--wake));
}
.greet__open {
  opacity: min(var(--wake) * 4 - 3, 3 - var(--pose) * 4);
}
.greet__smile {
  opacity: calc(var(--wake) * 4 - 3);
}
/* Asleep: closed eyes, a small snore, and z's that leave as it wakes. */
.greet__asleep {
  opacity: calc(1 - var(--wake) * 4);
}
.coconut--greet .coconut__z {
  opacity: calc(1 - var(--wake) * 3);
}
.greet__closed {
  opacity: calc(var(--pose) * 4 - 3);
}

/* What the hour and the forecast add to it (app/site/mood.py). */
.greet__lids {
  stroke-width: 7.5;
}
.greet__shades {
  fill: var(--coconut-ink);
  stroke-width: 3;
}
.greet__wide circle {
  fill: var(--color-paper);
  stroke-width: 4;
}
.greet__pupils {
  stroke-width: 8;
}
.greet__blush {
  stroke: var(--color-coral);
  stroke-width: 5;
  opacity: 0.75;
}
.greet__sweat {
  fill: var(--color-ocean-soft);
  stroke: var(--color-ocean);
  stroke-width: 3;
}
.greet__notes path {
  stroke-width: 4.5;
}
.greet__note-head {
  fill: currentColor;
  stroke-width: 2;
}
.greet__leaf {
  transform-origin: 122px 32px;
}
.greet__leaf-blade {
  fill: var(--color-palm);
  stroke-width: 4.5;
}
.greet__leaf-rib {
  stroke: var(--color-paper);
  stroke-width: 2.5;
  opacity: 0.7;
}
.greet__flower ellipse {
  fill: var(--color-surface);
  stroke-width: 2.5;
}
.greet__flower-heart {
  fill: var(--color-mango);
  stroke: none;
}
.greet__cup {
  stroke-width: 4.5;
}
.greet__cup-side {
  fill: var(--color-surface);
}
.greet__steam {
  stroke: var(--color-muted);
  stroke-width: 3;
}
.greet__rain path,
.hero__drops path {
  stroke: var(--color-ocean);
  stroke-width: 3.5;
  stroke-linecap: round;
}

/* A cloud over the sun when the forecast has one; rain under it when it has rain. */
.hero__cloud {
  position: absolute;
  z-index: 1;
  top: -16px;
  left: 104px;
  width: 96px;
  height: auto;
  overflow: visible;
  pointer-events: none;
}
.hero__cloud-shape {
  fill: var(--color-surface);
  stroke: var(--color-ink);
  stroke-width: 2.5;
  stroke-linejoin: round;
}
html[data-weather="storm"] .hero__cloud-shape {
  fill: #c9c7c2;
}
html[data-weather="rain"] .hero__sun,
html[data-weather="storm"] .hero__sun {
  opacity: 0.55;
}

/* The sun on the first screen follows the real one (app/site/sky.py). */
html[data-sky="morning"] .hero__sun {
  translate: -22px 30px;
  scale: 0.9;
}
html[data-sky="evening"] .hero__sun {
  background: #f18a4b;
  translate: 26px 34px;
}
html[data-sky="night"]:not([data-party]) .hero__sun {
  display: none;
}
.stars i {
  position: absolute;
  top: 16px;
  right: 58px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--color-ink);
}
.stars i:nth-child(2) {
  top: 40px;
  right: 46px;
  width: 3px;
  height: 3px;
}
.stars i:nth-child(3) {
  top: 6px;
  right: 92px;
  width: 3px;
  height: 3px;
}
.stars i:nth-child(4) {
  top: 34px;
  right: 108px;
}

/* --- Sections of the main page --- */

.blocks {
  display: grid;
}
.block {
  margin-top: 56px;
}
.block__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 16px;
  margin-bottom: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--color-ink);
}
.block--events .block__head {
  border-top: 4px double var(--color-coral);
}
.block__day {
  margin-bottom: 4px;
  color: var(--color-action);
  font: 500 15px/1.3 var(--font-display);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.more {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 14px;
  font-weight: 600;
}
.more::after {
  content: "\2192";
  margin-left: 6px;
  transition: translate var(--motion-ui);
}
.more:hover::after {
  translate: 3px 0;
}

/* --- Events --- */

.events {
  display: grid;
  gap: 12px;
}
.event {
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr);
  gap: 14px;
  padding: 16px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-card);
  background: var(--color-surface);
}
.event__time {
  color: var(--color-action);
  font: 500 19px/1.2 var(--font-display);
}
.event__time small {
  display: block;
  margin-top: 4px;
  color: var(--color-muted);
  font: 400 12px/1.3 var(--font-sans);
}
.event__title {
  font: 500 21px/1.25 var(--font-display);
}
.event__place {
  margin-top: 4px;
  color: var(--color-muted);
  font-size: 14px;
}
.event__text {
  margin-top: 10px;
  font-size: 15px;
}
.event:has(.event__more[open] .event__full) .event__text {
  display: none;
}
.event__more {
  margin-top: 4px;
  font-size: 15px;
}
.event__more summary,
.sources summary,
.departed summary {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--color-ocean);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.event__more p + p {
  margin-top: 8px;
}
.event__full {
  white-space: pre-line;
}
.event__links {
  display: flex;
  flex-wrap: wrap;
  gap: 0 18px;
  margin-top: 4px;
}
.event__links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 14px;
  font-weight: 600;
}
.live {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 4px;
  color: var(--color-action);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.live::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-coral);
}
/* Not on yet, but soon: the same line counts down, without the dot. */
.live.is-soon {
  color: var(--color-muted);
}
.live.is-soon::before {
  display: none;
}
/* Today's section: what is on right now first, then what is still to come. */
.day__part {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 2px 0 10px;
  color: var(--color-muted);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.events + .day__part {
  margin-top: 22px;
}
.day__part--now {
  color: var(--color-action);
}
.day__over {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 14px;
}
.event--off .event__title {
  color: var(--color-muted);
  text-decoration: line-through;
}
/* The title leads to the event's own page: a quiet underline says so, and the link reaches
   above and below the line, a thumb's height, without moving it. */
.event__title a {
  padding-block: 9px;
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--color-line);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 5px;
  transition: text-decoration-color var(--motion-ui);
}
.event__title a:hover,
.event__title a:active {
  text-decoration-color: var(--color-coral);
}
.event--off .event__title a {
  text-decoration-line: line-through;
}
/* Who is on: names a reader looks for, in the card's own ink; what they are, quieter. */
.event__lineup {
  margin-top: 4px;
  font-size: 14px;
}
.event__lineup span {
  color: var(--color-muted);
}
/* The venue leads to its place's page: the line keeps its quiet colour, the underline says it. */
.event__venue {
  color: inherit;
  text-decoration-color: var(--color-line);
  text-decoration-thickness: 1px;
}
.event__venue:hover,
.event__venue:active {
  text-decoration-color: var(--color-coral);
}
.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
}
.tag {
  padding: 2px 8px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-art);
  background: var(--color-sand);
  font-size: 12.5px;
  font-weight: 500;
}
.tag--price {
  border-color: transparent;
  background: var(--color-warning-soft);
  color: var(--color-warning);
  font-weight: 600;
}
.tag--spoken {
  border-color: transparent;
  background: var(--color-ocean-soft);
  color: var(--color-ocean);
}
.tag--note {
  border-color: transparent;
  background: var(--color-danger-soft);
  color: var(--color-danger);
}
.flag {
  display: inline-block;
  margin-bottom: 6px;
  padding: 3px 8px;
  border-radius: var(--radius-art);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.flag--off {
  background: var(--color-danger-soft);
  color: var(--color-danger);
}
.flag--warn {
  background: var(--color-warning-soft);
  color: var(--color-warning);
  letter-spacing: 0;
  text-transform: none;
}

/* --- Sailings ---
   A row that opens. The open one is the chosen one: it stands out, and on the ferries' page
   it is the one the coconut sails. The next to leave keeps a dot and its countdown. */

.sailings {
  border-top: 1px solid var(--color-line);
}
.sailing {
  position: relative;
  border-bottom: 1px solid var(--color-line);
  transition: opacity var(--motion-ui);
}
.sailing summary {
  display: grid;
  grid-template-columns: 88px minmax(0, 1fr) 14px;
  gap: 12px;
  padding: 14px 0;
  list-style: none;
  cursor: pointer;
}
.sailing summary::-webkit-details-marker {
  display: none;
}
/* The corner that says a row opens, and turns when it has. */
.sailing summary::after {
  content: "";
  width: 8px;
  height: 8px;
  margin-top: 7px;
  border: solid var(--color-muted);
  border-width: 0 2px 2px 0;
  rotate: 45deg;
  transition: rotate var(--motion-ui);
}
.sailing details[open] > summary::after {
  margin-top: 12px;
  rotate: -135deg;
}
.sailing__time,
.sailing__body,
.sailing__ports,
.sailing__meta {
  display: block;
}
.sailing__time b {
  display: block;
  font: 500 27px/1 var(--font-display);
}
.sailing__time span {
  display: block;
  margin-top: 6px;
  color: var(--color-muted);
  font-size: 13px;
}
.sailing__time small {
  display: block;
  margin-top: 2px;
  color: var(--color-muted);
  font-size: 12px;
}
.sailing__ports {
  font-size: 15.5px;
  font-weight: 600;
}
.sailing__meta {
  margin-top: 4px;
  color: var(--color-muted);
  font-size: 13.5px;
}
/* A duration or a wait is one thing: it does not break in the middle. */
.sailing__meta span {
  white-space: nowrap;
}
/* What it sails: a car ferry and a fast boat are told apart before a word is read. */
.vessel {
  display: inline-block;
  margin-right: 6px;
  color: var(--color-ocean);
  vertical-align: -3px;
}
.sailing .tags {
  margin-top: 8px;
}
.tag--vehicles {
  border-color: transparent;
  background: var(--color-ocean-soft);
  color: var(--color-ocean);
  font-weight: 600;
}
/* How long is left: a line of its own, so it never breaks off the end of another. */
.sailing__soon {
  display: block;
  margin-top: 2px;
  color: var(--color-action);
  font-weight: 600;
}
.sailing__soon[hidden] {
  display: none;
}
.sailing .flag {
  margin: 8px 0 0;
}
.sailing.is-past {
  opacity: 0.55;
}
.sailing.is-off .sailing__time b {
  color: var(--color-muted);
  text-decoration: line-through;
}
.sailing.is-next .sailing__time b {
  color: var(--color-action);
}
/* The chosen sailing: a card lifted off the list, as wide as the row was. */
.sailing:has(> details[open]) {
  margin-inline: -12px;
  padding-inline: 12px;
  border-radius: var(--radius-card);
  background: var(--color-surface);
  box-shadow: inset 4px 0 0 var(--color-coral);
  opacity: 1;
}
.sailing__more {
  padding-bottom: 8px;
  font-size: 14.5px;
}
.sailing__more dl {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px 18px;
  padding-top: 12px;
  border-top: 1px dashed var(--color-line);
}
.sailing__more dt {
  color: var(--color-muted);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.sailing__more dd {
  margin: 2px 0 0;
}
.sailing__more small {
  display: block;
  color: var(--color-muted);
  font-size: 13px;
}
.vehicle-fares {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px dashed var(--color-line);
}
.vehicle-fares h3 {
  margin: 0 0 10px;
  font-size: 21px;
}
.vehicle-fares dl {
  grid-template-columns: 1fr;
  border-top: 0;
  padding-top: 0;
}
.vehicle-fares dl > div {
  display: grid;
  grid-template-columns: minmax(90px, 1fr) minmax(140px, 1.5fr);
  gap: 12px;
}
.vehicle-fares dt {
  letter-spacing: 0;
  text-transform: none;
  font-size: 14px;
}
.vehicle-fares dd strong { font-variant-numeric: tabular-nums; }
.vehicle-fares p { margin: 10px 0 0; }
.vehicle-fares .sailing__source a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
/* Whose word the timetable is, where it is not the boat's own. */
.sailing__source {
  margin: 10px 0 0;
  color: var(--color-muted);
  font-size: 13px;
}
.sailing__links {
  display: flex;
  flex-wrap: wrap;
  gap: 0 20px;
  margin-top: 6px;
}
.sailing__links a,
.sailing__show {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 14px;
  font-weight: 600;
}
.sailing__links a::after {
  content: "\00a0\2197";
}
/* Up to the map, where the coconut is sailing this very route: only where there is a map
   and a script to send it. */
.sailing__show {
  display: none;
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-ocean);
  font-family: inherit;
  cursor: pointer;
}
.js .results:has(.map) .sailing__show {
  display: inline-flex;
}
.departed {
  margin-bottom: 4px;
}
.departed .sailings {
  border-top: 0;
}

/* --- Pages with filters --- */

.page-head {
  padding-block: 20px 22px;
}
/* The ferries' page is a board: its first screen is for the map and the next sailing. */
.page-head--board {
  padding-block: 14px 14px;
}
.filters {
  display: grid;
  gap: 10px;
  margin-inline: calc(-1 * var(--gutter));
}
.filters--after {
  margin-top: 14px;
}
.chips {
  display: flex;
  gap: 8px;
  padding: 2px var(--gutter);
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  /* A flick comes to rest on a chip's edge. */
  scroll-snap-type: x proximity;
  scroll-padding-inline: var(--gutter);
}
.chip {
  scroll-snap-align: start;
}
.chips::-webkit-scrollbar {
  display: none;
}
/* A row that goes on past the edge fades there, and stops fading when scrolled to its end. */
.chips {
  mask-image: linear-gradient(
    to right,
    transparent,
    #000 var(--fade-start),
    #000 calc(100% - var(--fade-end)),
    transparent
  );
}
.chip {
  display: inline-flex;
  flex: none;
  align-items: center;
  min-height: 44px;
  padding-inline: 14px;
  border: 1px solid var(--color-control-border);
  border-radius: var(--radius-control);
  background: var(--color-surface);
  color: var(--color-ink);
  font-size: 14.5px;
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--motion-ui), color var(--motion-ui);
}
/* A shore opened into its piers: the shore's chip stays marked, its piers follow it. */
.chip--open {
  border-color: var(--color-ink);
  box-shadow: inset 0 -3px 0 var(--color-ink);
}
.chip--pier {
  border-style: dashed;
}
/* A switch standing first in a row of choices: set a little apart from them. */
.chip--toggle {
  margin-right: 8px;
}
.chip[aria-current],
.segmented a[aria-current] {
  border-color: var(--color-ink);
  background: var(--color-ink);
  color: var(--color-sand);
}
.segmented {
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin-inline: var(--gutter);
  border: 1.5px solid var(--color-ink);
  border-radius: var(--radius-control);
  overflow: hidden;
}
.segmented a {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 4px 8px;
  color: var(--color-ink);
  font: 500 16px/1.2 var(--font-display);
  letter-spacing: 0.05em;
  text-align: center;
  text-decoration: none;
  text-transform: uppercase;
}
.filters__date {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  padding-inline: var(--gutter);
  color: var(--color-muted);
  font-size: 14px;
}
.filters__date input {
  min-height: 44px;
  padding: 0 10px;
  border: 1px solid var(--color-control-border);
  border-radius: var(--radius-control);
  background: var(--color-surface);
  color: var(--color-ink);
  font: inherit;
}
.filters__date .button {
  min-height: 44px;
}
/* With the script the date applies as soon as it is picked. */
.js .filters__date .button {
  display: none;
}
.results[aria-busy="true"] {
  opacity: 0.6;
  pointer-events: none;
  transition: opacity var(--motion-ui);
}
.day__title {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 10px;
  margin: 28px 0 14px;
  padding: 12px 0 10px;
  border-bottom: 4px double var(--color-coral);
  background: var(--color-sand);
  font-size: 21px;
}
/* The day's list in one sentence: what a reader skims and an assistant quotes. */
.summary {
  margin: -6px 0 14px;
  color: var(--color-muted);
  font-size: 14px;
  text-wrap: pretty;
}
.day__title span {
  color: var(--color-action);
}
.nudge {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 20px;
  margin-top: 24px;
  padding: 16px;
  border: 1.5px dashed var(--color-ocean);
  border-radius: var(--radius-card);
}
.nudge p {
  flex: 1 1 240px;
  font-size: 15px;
}
.nudge .button {
  flex: 1 1 200px;
}
.sources {
  margin-top: 16px;
  color: var(--color-muted);
  font-size: 14px;
}
.sources li {
  padding-block: 4px;
}
.empty {
  display: grid;
  justify-items: center;
  gap: 12px;
  padding-block: 36px 8px;
  text-align: center;
}
.empty .coconut {
  width: 190px;
  margin-bottom: -8px;
}
.empty p {
  max-width: 30em;
  color: var(--color-muted);
}
.empty .button,
.empty .channels {
  width: 100%;
  max-width: 340px;
}
.empty .channels {
  margin-top: 8px;
}
.empty--page {
  padding-block: 48px 16px;
}
.empty--list {
  padding-block: 20px 8px;
}

/* --- The ferries' map ---
   A route sign, not a chart: land printed in ocean ink on paper as the island is on the
   stamp, dotted marker lines between piers, the coconut in a boat. Every pier is a link;
   what the coconut says is written above the sea it sits on. */

.map {
  margin: 12px 0 0;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-card);
  background: var(--color-surface);
  overflow: hidden;
  view-transition-name: ferry-map;
}
.map svg {
  display: block;
  width: 100%;
  height: auto;
}
.map__sea {
  fill: none;
  stroke: var(--color-ocean);
  stroke-width: 1.4;
  stroke-linecap: round;
  opacity: 0.35;
}
.map__sea .map__north {
  stroke: var(--color-ink);
  stroke-linejoin: round;
}
.map__land {
  fill: var(--color-ocean);
}
.map__name {
  fill: var(--color-ink);
  font: 600 12px var(--font-display);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.map__name--on {
  fill: var(--color-surface);
}
/* A name printed on the worn land keeps a margin of clean ink round its letters. */
.map__name--on,
.map__pier-name--on {
  stroke: var(--color-ocean);
  stroke-width: 2.4px;
  stroke-linejoin: round;
  paint-order: stroke;
}
.map__name--coast {
  font-size: 10px;
}
.map__names .map__scale {
  fill: var(--color-muted);
  font: 600 8px var(--font-sans);
}
.map__credit text {
  fill: var(--color-muted);
  font: 500 6.5px var(--font-sans);
}
.map__route {
  fill: none;
  stroke: var(--color-ink);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-dasharray: 1 6;
  opacity: 0.5;
  transition:
    stroke var(--motion-ui),
    opacity var(--motion-ui);
}
.map__route.is-active {
  stroke: var(--color-coral);
  stroke-width: 2.8;
  stroke-dasharray: 7 6;
  opacity: 1;
}
/* A pier: its dot, its name, and room for a thumb around them. */
.map__hit {
  fill: transparent;
}
.map__pier {
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.map__dot {
  fill: var(--color-surface);
  stroke: var(--color-ink);
  stroke-width: 2;
  transition: scale 0.14s var(--ease);
}
.map__pier-name {
  fill: var(--color-ink);
  font: 600 9.5px var(--font-sans);
}
.map__pier-name--on {
  fill: var(--color-surface);
}
/* An operator's own pier apart from the port's: named by whose it is, a size smaller. */
.map__pier-name--apart {
  font-size: 8px;
}
/* The pier the boat waits at: its name makes room, and comes back when the boat has left. */
.map__pier-name {
  transition: translate 0.3s var(--ease);
}
.map:not(.is-sailing) .is-berth > .map__pier-name--end {
  translate: -12px 1px;
}
.map:not(.is-sailing) .is-berth > .map__pier-name--start {
  translate: 13px 0;
}
.map:not(.is-sailing) .is-berth > .map__pier-name--middle {
  translate: 0 6px;
}
/* No sailing of this list calls there: still a place to tap, drawn fainter. */
.map__dot.is-quiet {
  stroke-dasharray: 2 2;
}
/* The pier the list is narrowed to. */
.map__pier.is-chosen .map__dot {
  fill: var(--color-coral);
  scale: 1.4;
}
.map__pier.is-chosen .map__pier-name {
  font-weight: 800;
  text-decoration: underline;
}
.map__pier:active .map__dot {
  scale: 1.6;
}
.map__pier:focus-visible,
.map__boat:focus-visible {
  outline: none;
}
.map__pier:focus-visible .map__hit,
.map__boat:focus-visible .map__hit {
  stroke: var(--color-action);
  stroke-width: 2;
}
/* The ring the pier sends out when the boat comes in: still water without motion. */
.map__ripple {
  fill: none;
  stroke: var(--color-coral);
  stroke-width: 1.8;
  opacity: 0;
}
.map__dot,
.map__ripple,
.map__hull {
  transform-box: fill-box;
  transform-origin: center;
}
/* The coconut in its boat: at the pier until a sailing is chosen; with one chosen and no
   motion it waits halfway. */
.map__boat {
  offset-rotate: 0deg;
  offset-distance: 0%;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.map.is-sailing .map__boat {
  offset-distance: 50%;
}
.map__face circle {
  fill: var(--coconut-ink);
}
.map__smile {
  fill: none;
  stroke: var(--coconut-ink);
  stroke-width: 1.4;
  stroke-linecap: round;
}
.map__hull,
.map__hull > :first-child {
  fill: var(--color-surface);
  stroke: var(--color-ink);
  stroke-width: 2;
  stroke-linejoin: round;
}
.map__hull .map__line {
  fill: none;
  stroke-width: 1.7;
  stroke-linecap: round;
}
/* It dresses for the forecast as the one on the main page does: a banana leaf for a hat in
   the rain, and before a thunderstorm it does not smile. */
.map__leaf,
.map__worry {
  display: none;
}
.map__leaf {
  fill: var(--color-palm);
  stroke: var(--coconut-ink);
  stroke-width: 1.2;
  stroke-linejoin: round;
}
.map__worry {
  fill: none;
  stroke: var(--coconut-ink);
  stroke-width: 1.4;
  stroke-linecap: round;
}
html:is([data-weather="rain"], [data-weather="storm"]) .map__leaf,
html[data-weather="storm"] .map__worry {
  display: inline;
}
html[data-weather="storm"] .map__smile {
  display: none;
}
/* What it sails in is what the chosen sailing sails; the bow points where it goes. */
.map__hull--ferry,
.map__hull--fast,
.map[data-vessel] .map__hull--own {
  display: none;
}
.map:is([data-vessel="car_ferry"], [data-vessel="ferry"]) .map__hull--ferry,
.map[data-vessel]:not([data-vessel="car_ferry"], [data-vessel="ferry"]) .map__hull--fast {
  display: inline;
}
/* Only a car ferry has a ramp. */
.map[data-vessel="ferry"] .map__ramp {
  display: none;
}
.map[data-heading="west"] .map__hull {
  scale: -1 1;
}
/* What it says: a bubble over the sea, its tail towards the boat. */
.map__talk {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  padding: 12px 6px 2px 12px;
}
.map__said {
  flex: 1;
  min-height: 2.8em;
  margin: 0;
  padding: 9px 12px;
  border: 1.5px solid var(--color-ink);
  border-radius: var(--radius-card) var(--radius-card) var(--radius-card) 2px;
  font-size: 14.5px;
  line-height: 1.4;
  text-wrap: pretty;
}
.map__said:empty {
  display: none;
}
.map__said a {
  font-weight: 600;
  white-space: nowrap;
}
.map__said a::after {
  content: " \2192";
}
.map__more {
  display: none;
  min-width: 48px;
  min-height: 44px;
  padding: 0 6px;
  border: 0;
  background: none;
  color: var(--color-ocean);
  font: 600 13.5px var(--font-sans);
  cursor: pointer;
}
.js .map__more {
  display: block;
}
.map figcaption {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 2px 12px;
  padding: 8px 12px 10px;
  border-top: 1px solid var(--color-line);
  font-size: 13px;
}
.map__caption {
  font-weight: 600;
}
.map figcaption .map__scale {
  color: var(--color-muted);
}

/* --- Posts from the channel --- */

.posts {
  display: grid;
  gap: 12px;
}
.post {
  display: flex;
  gap: 14px;
  height: 100%;
  padding: 12px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-card);
  background: var(--color-surface);
  color: var(--color-ink);
  text-decoration: none;
  transition: border-color var(--motion-ui);
}
.post:hover {
  border-color: var(--color-ocean);
}
.post img {
  flex: none;
  width: 96px;
  height: 96px;
  border-radius: var(--radius-art);
  object-fit: cover;
}
.post__text {
  display: grid;
  align-content: start;
  gap: 4px;
  min-width: 0;
}
.post time {
  color: var(--color-muted);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.post strong {
  font-size: 16px;
  font-weight: 600;
  line-height: 1.35;
}
.post__text > span {
  display: -webkit-box;
  overflow: hidden;
  color: var(--color-muted);
  font-size: 14px;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
}

/* --- The mango band: why the channel --- */

.pitch {
  display: grid;
  gap: 8px 24px;
  margin-top: 64px;
  padding: 24px 20px 26px;
  border-radius: var(--radius-card);
  background: var(--color-mango);
}
.pitch {
  position: relative;
  /* Mango stays mango at night: its ink stays dark. */
  --coconut-ink: #1f1f1f;
  color: #1f1f1f;
}
.pitch__art {
  position: relative;
  display: block;
  width: 150px;
  margin-left: -14px;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  cursor: pointer;
}
.pitch__coconut {
  width: 150px;
  height: auto;
  margin-bottom: -10px;
}
.pitch__plane {
  position: absolute;
  left: 138px;
  top: 36px;
  width: 26px;
  height: 26px;
}
/* The plane in the air lies over the whole band, so that it and the button it is sent to
   are measured from the same corner; the script says where from and where to. */
.pitch__flight {
  position: absolute;
  z-index: 2;
  top: 0;
  left: 0;
  width: 26px;
  height: 26px;
  translate: var(--from-x, 0) var(--from-y, 0);
  visibility: hidden;
  pointer-events: none;
}
.pitch__flying {
  display: block;
  width: 100%;
  height: 100%;
}
/* The button the plane is sent to answers with a ring and keeps the plane, where a "send"
   mark would be. */
.pitch .button {
  position: relative;
}
.button__dock {
  position: absolute;
  top: 50%;
  right: 14px;
  width: 22px;
  height: 22px;
  margin-top: -11px;
  pointer-events: none;
}
.button__plane {
  display: block;
  width: 100%;
  height: 100%;
  opacity: 0;
}
.has-plane .button__plane {
  opacity: 1;
}
.button__sparks {
  position: absolute;
  inset: -13px;
  width: 48px;
  height: 48px;
  opacity: 0;
}
.pitch .button::after {
  content: "";
  position: absolute;
  inset: -5px;
  border: 2px solid var(--color-action);
  border-radius: 10px;
  opacity: 0;
  pointer-events: none;
}
.pitch p {
  max-width: 36em;
  margin-top: 10px;
}
.pitch .button {
  width: 100%;
  max-width: 340px;
  margin-top: 18px;
}

/* --- The coconut ---
   A photograph of the shell with a marker face and limbs over it (_coconut.html). The ink is
   one colour, --coconut-ink; what moves is in "Motion" below. */

.coconut {
  width: 132px;
  height: auto;
  overflow: visible;
  color: var(--coconut-ink);
}
.coconut__eyes circle,
.coconut__eyes ellipse,
.coconut__mouth {
  fill: currentColor;
  stroke: none;
}
.coconut__z {
  stroke: var(--color-ocean);
  stroke-width: 5;
}
.coconut__sigh {
  stroke-width: 4.5;
}
.coconut__glow,
.coconut__paint {
  stroke-width: 7;
}
.coconut__glow--a,
.coconut__paint--a {
  stroke: var(--uv-pink, #ff3d9a);
}
.coconut__glow--b,
.coconut__paint--b {
  stroke: var(--uv-green, #5cff8f);
}
.coconut__paint--c {
  stroke: var(--uv-yellow, #ffe44d);
  stroke-width: 9;
}
.roller {
  position: fixed;
  left: 0;
  bottom: 8px;
  z-index: 30;
  width: 84px;
  pointer-events: none;
  animation: roll 2.8s linear forwards;
}
.roller .coconut {
  width: 100%;
  animation: none;
}
@keyframes roll {
  from {
    translate: -100px 0;
    rotate: 0deg;
  }
  to {
    translate: calc(100vw + 20px) 0;
    rotate: 1080deg;
  }
}

/* --- The moon: tonight's real phase, top right of every page --- */

.sky {
  position: relative;
  height: 0;
}
.moon {
  position: absolute;
  z-index: 2;
  top: 8px;
  right: 0;
  width: 38px;
  height: 38px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  cursor: pointer;
  anchor-name: --moon;
  view-transition-name: moon;
}
/* A thumb needs more than the disc. */
.moon::after {
  content: "";
  position: absolute;
  inset: -6px;
}
.moon svg {
  width: 100%;
  height: 100%;
  overflow: visible;
}
/* This close to the equator the lit edge points down: the moon hangs like a bowl. */
.moon--waxing svg {
  rotate: 50deg;
}
.moon--waning svg {
  rotate: -50deg;
}
.moon__night {
  fill: var(--color-ink);
}
.moon__lit {
  fill: var(--color-surface);
}
.moon__seas {
  fill: var(--color-mango);
  opacity: 0.5;
}
.moon__info {
  position: fixed;
  inset: 70px 16px auto auto;
  max-width: min(280px, calc(100vw - 32px));
  margin: 0;
  padding: 12px 14px;
  border: 1.5px solid var(--color-ink);
  border-radius: var(--radius-card);
  background: var(--color-surface);
  color: var(--color-ink);
  font-size: 14px;
  line-height: 1.4;
}
.moon__party {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid var(--color-line);
  font-style: italic;
}
.moon__more a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--color-ocean);
  font-weight: 600;
}
.foot__credit {
  font-size: 12px;
  opacity: 0.7;
}
.moon__name {
  font: 500 18px/1.2 var(--font-display);
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
@supports (top: anchor(bottom)) {
  .moon__info {
    position-anchor: --moon;
    inset: anchor(bottom) anchor(right) auto auto;
    margin-top: 10px;
  }
}

/* --- The Full Moon Party's dates: a night per row, the party's date the one in colour --- */
.nights {
  max-width: 680px;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--color-line);
  list-style: none;
}
.night {
  display: grid;
  gap: 6px 20px;
  padding: 14px 0;
  border-bottom: 1px solid var(--color-line);
}
.night__label {
  display: block;
  color: var(--color-muted);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.night__party strong {
  font: 500 21px/1.2 var(--font-display);
}
.night--set .night__party strong {
  color: var(--color-action);
}
/* The party's date leads to the party's own page. */
.night__event {
  text-decoration-color: var(--color-line);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 5px;
}
.night__state {
  margin-left: 6px;
  color: var(--color-muted);
  font-size: 14px;
}
.night__ferries {
  justify-self: start;
}
@media (min-width: 960px) {
  /* The same columns in every row, whether or not it links to the morning's ferries. */
  .nights {
    max-width: 780px;
  }
  .night {
    grid-template-columns: 16rem 16rem 1fr;
    align-items: end;
  }
  .night__ferries {
    justify-self: end;
    white-space: nowrap;
  }
}

/* --- A page of plain prose: about the site --- */
.prose {
  max-width: 680px;
}
.prose h2 {
  margin: 28px 0 10px;
}
.prose > p,
.prose li {
  font-size: 17px;
  line-height: 1.55;
}
.prose ul {
  display: grid;
  gap: 10px;
  margin: 0;
  padding-left: 1.2em;
  list-style: disc;
}
.prose li::marker {
  color: var(--color-coral);
}
.prose a {
  color: var(--color-ocean);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.prose .prose__links {
  padding-left: 0;
  list-style: none;
}
.prose__links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* --- A post of the channel as a page ---
   One column a reader's eye crosses without effort; the post's own words, a little larger
   than a list's. No decoration: a post may be news. */
.story {
  max-width: 680px;
  margin-inline: auto;
  padding-block: 8px 12px;
}
.story__head {
  margin-bottom: 20px;
}
.story__head h1 {
  /* Clear of the night sky's stars, which stand beside the moon. */
  margin-top: 12px;
  font-size: clamp(30px, 8vw, 46px);
  text-wrap: balance;
}
.story__head--long h1 {
  font-size: clamp(23px, 6.2vw, 34px);
  line-height: 1.12;
}
.story__hero {
  margin: 0 0 22px;
}
.story__hero img,
.story__pictures img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-art);
  background: var(--color-line);
}
.story__body {
  font-size: 17px;
  line-height: 1.62;
  overflow-wrap: anywhere;
}
.story__body p {
  margin-block: 0 1em;
}
.story__body a {
  color: var(--color-ocean);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.story__body blockquote {
  margin: 0 0 1em;
  padding: 2px 0 2px 16px;
  border-left: 3px solid var(--color-coral);
  color: var(--color-muted);
}
.story__body pre,
.story__body code {
  font-family: ui-monospace, monospace;
  font-size: 0.92em;
}
.story__body pre {
  margin: 0 0 1em;
  padding: 12px;
  overflow-x: auto;
  border-radius: var(--radius-control);
  background: var(--color-surface);
}
.story__pictures {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 8px;
  margin: 8px 0 20px;
  padding: 0;
  list-style: none;
}
.story__pictures img {
  height: 100%;
  aspect-ratio: 1;
  object-fit: cover;
}
/* A video is its still frame and a way to where it plays. */
.story__video {
  position: relative;
  display: block;
}
.story__video span {
  position: absolute;
  right: 8px;
  bottom: 8px;
  padding: 6px 10px;
  border-radius: var(--radius-control);
  background: var(--color-ink);
  color: var(--color-surface);
  font-size: 13px;
  font-weight: 600;
}
.story__tags {
  margin-bottom: 4px;
}

/* --- An event's own page ---
   Its card opened up: the facts as a panel a reader scans (the day and the hour first, in the
   card's own type), then the announcement's words, then where to go next. */
.happening {
  max-width: 680px;
}
.happening__head h1 {
  margin-top: 4px;
  font-size: clamp(30px, 8vw, 46px);
  overflow-wrap: anywhere;
}
.happening__head .kicker a {
  color: inherit;
  text-decoration: none;
}
.happening--off h1 {
  color: var(--color-muted);
  text-decoration: line-through;
  text-decoration-thickness: 2px;
}
.flag--past {
  border: 1px solid var(--color-line);
  background: var(--color-surface);
  color: var(--color-muted);
  letter-spacing: 0;
  text-transform: none;
}
.facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 14px 24px;
  margin: 0;
  padding: 16px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-card);
  background: var(--color-surface);
}
.facts dt {
  color: var(--color-muted);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.facts dd {
  margin: 3px 0 0;
  font-size: 16px;
  overflow-wrap: anywhere;
}
.facts small {
  display: block;
  margin-top: 2px;
  color: var(--color-muted);
  font-size: 14px;
}
.facts > div:first-child dd {
  color: var(--color-action);
  font: 500 20px/1.25 var(--font-display);
}
.facts > div:first-child small {
  color: var(--color-ink);
  font: 500 18px/1.3 var(--font-display);
}
.happening--over .facts > div:first-child dd {
  color: var(--color-muted);
}
/* A place's facts: nothing in them is a date to stand out. */
.facts--plain > div:first-child dd {
  color: inherit;
  font: inherit;
  font-size: 16px;
}
.facts--plain > div:first-child small {
  color: var(--color-muted);
  font: inherit;
  font-size: 14px;
}
/* --- A place's page (ADR 0036): the sky over a beach, an editor's words, the island --- */
.skyboard {
  margin-top: 20px;
  padding: 18px 16px 14px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-card);
  background: linear-gradient(180deg, var(--color-surface) 0%, var(--color-sand) 100%);
}
.skyboard__title {
  margin: 0;
  color: var(--color-muted);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.skyboard__sunset {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas: "label label" "time left";
  align-items: baseline;
  column-gap: 14px;
  margin-top: 10px;
}
.skyboard__label {
  grid-area: label;
  margin: 0;
  font: 500 18px/1.3 var(--font-display);
}
.skyboard__time {
  grid-area: time;
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 0;
  color: var(--color-action);
  font: 500 clamp(44px, 12vw, 64px)/1 var(--font-display);
  font-variant-numeric: tabular-nums;
}
.skyboard__sun {
  width: 0.42em;
  height: 0.21em;
  border-radius: 0.42em 0.42em 0 0;
  background: var(--color-mango);
  box-shadow: inset 0 -2px 0 var(--color-coral);
}
.skyboard__left {
  grid-area: left;
  margin: 0;
  font: 500 20px/1.2 var(--font-display);
  min-height: 1.2em;
}
.skyboard__view {
  margin: 12px 0 0;
  font-size: 16px;
  line-height: 1.5;
}
.skyboard__cloud {
  color: var(--color-muted);
  white-space: nowrap;
}
.skyboard__cloud::before {
  content: "(";
}
.skyboard__cloud::after {
  content: ")";
}
.skyboard__facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px 24px;
  margin: 14px 0 0;
  padding: 12px 0 0;
  border-top: 1px solid var(--color-line);
}
.skyboard__facts dt {
  color: var(--color-muted);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.skyboard__facts dd {
  margin: 3px 0 0;
  font-size: 16px;
  overflow-wrap: anywhere;
}
.skyboard__facts small {
  display: block;
  margin-top: 2px;
  color: var(--color-muted);
  font-size: 14px;
}
.skyboard__flag {
  display: inline-block;
  width: 18px;
  height: 13px;
  margin-right: 8px;
  vertical-align: -1px;
  border-left: 2px solid var(--color-ink);
  background: var(--color-line);
  clip-path: polygon(0 0, 100% 0, 86% 50%, 100% 100%, 0 100%);
}
.skyboard__sea--green .skyboard__flag { background: var(--color-palm); }
.skyboard__sea--yellow .skyboard__flag { background: var(--color-mango); }
.skyboard__sea--red .skyboard__flag { background: var(--color-coral); }
.skyboard__source {
  margin: 12px 0 0;
  color: var(--color-muted);
  font-size: 13px;
}
.skyboard__source a {
  display: block;
  margin-top: 4px;
}
.place__text p {
  margin: 0 0 12px;
  font-size: 17px;
  line-height: 1.6;
  white-space: pre-line;
  overflow-wrap: anywhere;
}
.place__text p:last-child {
  margin-bottom: 0;
}
.place__where {
  display: grid;
  grid-template-columns: 120px 1fr;
  gap: 16px 20px;
  align-items: start;
}
@media (max-width: 420px) {
  .place__where {
    grid-template-columns: 96px 1fr;
  }
}
.island {
  width: 100%;
  height: auto;
  overflow: visible;
}
.island__land {
  fill: var(--color-ocean);
  stroke: var(--color-ocean);
  stroke-width: 1.2;
  stroke-linejoin: round;
}
.island__ring {
  fill: none;
  stroke: var(--color-coral);
  stroke-width: 1.4;
}
.island__dot {
  fill: var(--color-coral);
  stroke: var(--color-surface);
  stroke-width: 1.2;
}
.place__tips {
  margin: 0;
  padding-left: 22px;
  font-size: 16px;
  line-height: 1.55;
}
.place__tips li {
  margin: 6px 0;
}
.nudge--keep {
  border-style: solid;
  border-color: var(--color-line);
  background: var(--color-surface);
}
.block__day--next {
  margin-top: 20px;
}
.happening .tags {
  margin-top: 14px;
}
.happening__text {
  margin-top: 20px;
  font-size: 17px;
  line-height: 1.6;
  white-space: pre-line;
  overflow-wrap: anywhere;
}
.happening .event__links {
  margin-top: 8px;
}
.happening .block {
  margin-top: 40px;
}
.dates {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* --- The places events happen at ---
   The list is rows of names a thumb hits, each saying when something is on there next; a
   place's page lists its past as dates and titles, the latest first. */
.venues {
  display: grid;
  gap: 10px;
  max-width: 680px;
}
.venue {
  padding: 14px 16px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-card);
  background: var(--color-surface);
}
.venue__name {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-block: -8px -4px;
  color: var(--color-ink);
  font: 500 21px/1.25 var(--font-display);
  text-decoration: underline;
  text-decoration-color: var(--color-line);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 5px;
}
.venue__name:hover,
.venue__name:active {
  text-decoration-color: var(--color-coral);
}
.venue__meta {
  color: var(--color-muted);
  font-size: 14px;
}
.venue__next {
  margin-top: 4px;
  font-size: 14px;
}
.venue__next b {
  color: var(--color-action);
  font-weight: 600;
}
.past {
  display: grid;
  max-width: 680px;
}
.past li {
  display: flex;
  gap: 14px;
  align-items: baseline;
  border-bottom: 1px solid var(--color-line);
}
.past__day {
  flex: none;
  width: 4.5em;
  color: var(--color-muted);
  font-size: 14px;
}
.past a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--color-ink);
  text-decoration-color: var(--color-line);
}

/* --- The postmark: which one of a printed code's readers this is ---
   A reader who scanned a sticker or a pier's sign gets a stamp with their number and a word
   from the coconut that asked them to scan. It lies over the bottom of the page, moves
   nothing, and leaves by itself or at a tap. */
.postmark {
  position: fixed;
  z-index: 40;
  right: 12px;
  bottom: calc(12px + env(safe-area-inset-bottom));
  left: 12px;
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 12px;
  align-items: center;
  max-width: 460px;
  margin-inline: auto;
  padding: 10px 6px 10px 12px;
  border: 2px solid var(--color-ink);
  border-radius: var(--radius-card);
  background: var(--color-surface);
  box-shadow: var(--shadow-floating);
  color: var(--color-ink);
  animation: postmark-in 0.45s var(--ease) both;
  transition:
    opacity 0.3s var(--ease),
    translate 0.3s var(--ease);
}
.postmark.is-leaving {
  opacity: 0;
  translate: 0 14px;
}
.postmark__stamp {
  width: 78px;
  height: 78px;
  color: var(--color-coral);
  rotate: -9deg;
  animation: postmark-thud 0.5s 0.3s var(--ease) both;
}
.postmark__stamp text {
  fill: currentColor;
}
.postmark__top {
  font: 600 8px var(--font-display);
  letter-spacing: 0.08em;
}
.postmark__number {
  font: 600 30px var(--font-display);
}
.postmark__zip {
  font: 400 15px var(--font-wordmark);
  letter-spacing: 0.06em;
}
.postmark__text {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.35;
}
.postmark__place {
  display: block;
  margin-bottom: 2px;
  color: var(--color-muted);
  font: 600 12px var(--font-display);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.postmark__place:empty {
  display: none;
}
.postmark__close {
  align-self: start;
  width: 44px;
  height: 44px;
  border: 0;
  background: none;
  color: var(--color-muted);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
}
@keyframes postmark-in {
  from {
    opacity: 0;
    translate: 0 24px;
  }
}
/* The stamp comes down on the paper: large and faint, then home with a small bounce. */
@keyframes postmark-thud {
  from {
    opacity: 0;
    scale: 1.7;
  }
  60% {
    opacity: 1;
    scale: 0.94;
  }
}

/* --- The weather page (ADR 0028) ---
   Not a bureau's report: a scene of the sky the island is under, with the coconut standing
   in it, then the hours ahead, the radar's picture of the island, what to do in it, today's
   events under the open sky, the sun and the moon, the season. The scene's colours are the
   brand's, mixed lighter or darker for the sky; at night its marker turns light. */

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.wx-hero {
  display: grid;
  gap: 18px;
  padding-block: 20px 4px;
}
.wx-hero__title {
  max-width: 14em;
}
.wx-hero__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 12px;
  margin-top: 10px;
  color: var(--color-muted);
  font-size: 14px;
}
.wx-hero__meta > span + span::before {
  content: "·";
  margin-right: 12px;
}
.wx-hero__temp {
  color: var(--color-ink);
  font: 500 34px/1 var(--font-display);
}
.wx-hero__meta > .wx-hero__temp + span::before {
  content: none;
}
.wx-hero__story {
  margin-top: 12px;
}
.wx-hero__window {
  padding: 0 4px;
  background: color-mix(in srgb, var(--color-mango) 45%, transparent);
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

/* The scene: sky, sea and a strip of beach the coconut stands on. */
.wx-scene {
  --sky: color-mix(in srgb, var(--color-mango) 16%, var(--color-surface));
  --sea: var(--color-ocean);
  --beach: color-mix(in srgb, var(--color-mango) 22%, var(--color-sand));
  position: relative;
  height: 268px;
  margin-inline: calc(-1 * var(--gutter));
  overflow: hidden;
  isolation: isolate;
  background: linear-gradient(var(--sky) 0 76%, var(--beach) 76%);
  border-block: 1px solid var(--color-ink);
}
.wx-scene--hot {
  --sky: color-mix(in srgb, var(--color-mango) 34%, var(--color-surface));
}
.wx-scene--cloudy {
  --sky: color-mix(in srgb, var(--color-ocean-soft) 80%, var(--color-surface));
}
.wx-scene--rain {
  --sky: color-mix(in srgb, var(--color-ocean) 22%, var(--color-ocean-soft));
  --beach: color-mix(in srgb, var(--color-muted) 22%, var(--color-sand));
}
.wx-scene--storm {
  --sky: color-mix(in srgb, var(--color-ocean) 30%, color-mix(in srgb, var(--color-muted) 45%, var(--color-ocean-soft)));
  --beach: color-mix(in srgb, var(--color-muted) 30%, var(--color-sand));
}
.wx-scene--evening {
  --sky: color-mix(in srgb, var(--color-coral) 16%, color-mix(in srgb, var(--color-mango) 26%, var(--color-surface)));
}
.wx-scene--night {
  --sky: color-mix(in srgb, var(--color-ocean) 55%, var(--color-ink));
  --sea: color-mix(in srgb, var(--color-ocean-soft) 70%, var(--color-ocean));
  --beach: color-mix(in srgb, var(--color-ink) 70%, var(--color-muted));
  --coconut-ink: var(--color-surface);
}
.wx-scene--night.wx-scene--rain,
.wx-scene--night.wx-scene--storm {
  --sky: color-mix(in srgb, var(--color-ocean) 40%, var(--color-ink));
}
.wx-scene__sky {
  position: absolute;
  inset: 0 0 24% 0;
  z-index: -1;
}
.wx-scene__sea {
  position: absolute;
  left: -40px;
  bottom: calc(24% - 4px);
  z-index: -1;
  width: calc(100% + 80px);
  height: 22px;
  overflow: visible;
  color: var(--sea);
  animation: swell 6s ease-in-out infinite alternate;
}
@keyframes swell {
  to {
    translate: 28px 0;
  }
}
.wx-scene__coconut {
  position: absolute;
  left: 6px;
  bottom: 4px;
  width: 132px;
}
.forecaster {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.forecaster .coconut {
  width: 100%;
}
.forecaster__said {
  position: absolute;
  z-index: 3;
  top: 14px;
  right: 12px;
  left: 128px;
  max-width: 260px;
  margin: 0 0 0 auto;
  padding: 10px 13px;
  border: 1.5px solid var(--color-ink);
  border-radius: var(--radius-card) var(--radius-card) var(--radius-card) 2px;
  background: var(--color-surface);
  color: var(--color-ink);
  font-size: 14px;
  line-height: 1.42;
  transform-origin: 0 100%;
  animation: say 0.32s var(--spring);
}
.forecaster__said a {
  font-weight: 600;
  white-space: nowrap;
}
.forecaster__said a::after {
  content: " \2192";
}

.wx-scene__stars,
.wx-scene__rain,
.wx-scene__heat {
  position: absolute;
  inset: 0;
}
/* The sun, with its rays turning slowly; hotter, it is bigger and coral at the edge. */
.wx-scene__sun {
  position: absolute;
  top: 26px;
  left: 36px;
  width: 58px;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--color-mango);
}
.wx-scene__sun i {
  position: absolute;
  inset: -16px;
  border-radius: 50%;
  background: repeating-conic-gradient(var(--color-mango) 0 6deg, transparent 6deg 30deg);
  mask: radial-gradient(circle, transparent 0 58%, #000 59% 100%);
  animation: rays 40s linear infinite;
}
.wx-scene--hot .wx-scene__sun {
  width: 74px;
  box-shadow: 0 0 0 7px color-mix(in srgb, var(--color-coral) 30%, transparent);
}
.wx-scene--evening .wx-scene__sun {
  top: auto;
  bottom: -18px;
  left: 54px;
  background: color-mix(in srgb, var(--color-coral) 70%, var(--color-mango));
}
@keyframes rays {
  to {
    rotate: 360deg;
  }
}

/* Clouds drift, each at its own pace; in a storm they are heavier. */
.wx-scene__cloud {
  position: absolute;
  width: 120px;
  overflow: visible;
  fill: var(--color-surface);
  stroke: var(--color-ink);
  stroke-width: 2.2;
  animation: drift-cloud 26s ease-in-out infinite alternate;
}
.wx-scene__cloud--0 {
  top: 18px;
  left: 18px;
}
.wx-scene__cloud--1 {
  top: 6px;
  left: 46%;
  width: 92px;
  animation-duration: 34s;
  animation-delay: -12s;
}
.wx-scene__cloud--2 {
  top: 66px;
  right: -20px;
  width: 104px;
  animation-duration: 30s;
  animation-delay: -6s;
}
.wx-scene--storm .wx-scene__cloud,
.wx-scene--rain .wx-scene__cloud {
  fill: color-mix(in srgb, var(--color-muted) 35%, var(--color-surface));
}
.wx-scene--storm .wx-scene__cloud {
  fill: color-mix(in srgb, var(--color-ink) 45%, var(--color-muted));
}
.wx-scene--night .wx-scene__cloud {
  fill: color-mix(in srgb, var(--color-ocean) 40%, var(--color-ink));
  stroke: var(--color-surface);
  opacity: 0.85;
}
.wx-scene.is-nudged .wx-scene__cloud--1 {
  translate: 46px 0;
  transition: translate 1.4s var(--ease);
}
@keyframes drift-cloud {
  from {
    translate: -14px 0;
  }
  to {
    translate: 22px 0;
  }
}

/* The rain falls across the whole scene, slanting with the wind; a storm's is twice as fast. */
.wx-scene__rain i {
  position: absolute;
  top: -24px;
  left: var(--x);
  width: 2px;
  height: var(--len, 16px);
  border-radius: 2px;
  background: var(--color-ocean);
  rotate: 14deg;
  opacity: 0;
  animation: fall 0.95s linear var(--d) infinite;
}
.wx-scene--night .wx-scene__rain i {
  background: var(--color-ocean-soft);
}
.wx-scene--storm .wx-scene__rain i {
  animation-duration: 0.55s;
}
@keyframes fall {
  10% {
    opacity: var(--o, 0.85);
  }
  to {
    opacity: var(--o, 0.85);
    translate: -46px 230px;
  }
}

/* Lightning: the sky flashes, the bolt shows, and (in the same rhythm) the coconut flinches. */
.wx-scene__flash {
  position: absolute;
  inset: 0;
  background: var(--color-surface);
  opacity: 0;
  animation: flash 7.5s linear infinite;
}
.wx-scene__bolt {
  position: absolute;
  top: 34px;
  right: 22%;
  width: 26px;
  fill: var(--color-mango);
  stroke: var(--color-ink);
  stroke-width: 2.5;
  stroke-linejoin: round;
  opacity: 0;
  animation: flash 7.5s linear infinite;
}
@keyframes flash {
  0%,
  88%,
  91%,
  93%,
  100% {
    opacity: 0;
  }
  89%,
  92% {
    opacity: 0.85;
  }
}
.mood--storm.coconut--forecast .fc__figure {
  animation: startle 7.5s linear infinite;
}
@keyframes startle {
  0%,
  88.5%,
  96%,
  100% {
    translate: 0 0;
    scale: 1;
  }
  90%,
  93% {
    translate: 0 6px;
    scale: 1.04 0.92;
  }
}

/* The heat rises off the beach. */
.wx-scene__heat i {
  position: absolute;
  bottom: 22%;
  left: calc(36% + var(--n, 0) * 18%);
  width: 10px;
  height: 46px;
  border-inline: 2px solid color-mix(in srgb, var(--color-coral) 55%, transparent);
  border-radius: 50%;
  opacity: 0;
  animation: heat 3.2s ease-in infinite;
}
.wx-scene__heat i:nth-child(2) {
  --n: 1;
  animation-delay: -1.1s;
}
.wx-scene__heat i:nth-child(3) {
  --n: 2;
  animation-delay: -2.2s;
}
@keyframes heat {
  20% {
    opacity: 0.8;
  }
  to {
    opacity: 0;
    translate: 0 -40px;
    scale: 1 1.3;
  }
}

/* Stars twinkle, each in its own time; a tap on a clear night sends one across the sky. */
.wx-scene__stars i {
  position: absolute;
  top: var(--y);
  left: var(--x);
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--color-surface);
  animation: twinkle 2.8s ease-in-out var(--d) infinite alternate;
}
.wx-scene__stars i:nth-child(3n) {
  width: 4px;
  height: 4px;
}
.wx-scene--cloudy .wx-scene__stars {
  opacity: 0.35;
}
.wx-scene__shooting {
  position: absolute;
  top: 24px;
  right: 18%;
  width: 70px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, transparent, var(--color-surface));
  opacity: 0;
  rotate: -24deg;
}
.wx-scene.is-wishing .wx-scene__shooting {
  animation: shoot 0.9s var(--ease);
}
@keyframes shoot {
  from {
    opacity: 0;
    translate: 60px -24px;
  }
  30% {
    opacity: 1;
  }
  to {
    opacity: 0;
    translate: -150px 66px;
  }
}

/* The coconut of the weather page: its parts and what they do while it stands there. */
.coconut--forecast {
  transform-origin: 50% 90%;
  animation:
    bob 3.2s ease-in-out infinite alternate,
    rock-soft 5.4s ease-in-out infinite alternate;
}
.fc__figure,
.fc__leaf,
.fc__fan,
.fc__point,
.fc__cup,
.fc__hello,
.fc__brow,
.fc__catch,
.fc__umbrella {
  transform-box: view-box;
}
.fc__figure {
  transform-origin: 122px 228px;
}
.fc__stem {
  stroke-width: 5;
}
.fc__leaf {
  transform-origin: 150px -14px;
  animation: leaf 3.4s ease-in-out infinite alternate;
}
.mood--storm .fc__leaf {
  animation-duration: 0.5s;
}
.fc__leaf-blade {
  fill: var(--color-palm);
  stroke-width: 4.5;
}
.fc__leaf-rib {
  stroke: var(--color-paper);
  stroke-width: 2.5;
  opacity: 0.7;
}
.fc__splash path {
  stroke: var(--color-ocean);
  stroke-width: 3.5;
  opacity: 0;
  animation: splash 1.1s ease-out infinite;
}
.fc__splash path:nth-child(2) {
  animation-delay: -0.4s;
}
.fc__splash path:nth-child(3) {
  animation-delay: -0.75s;
}
@keyframes splash {
  0% {
    opacity: 0;
  }
  30% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    translate: 0 -6px;
  }
}
.fc__catch {
  transform-origin: 64px 112px;
  animation: catch 2.6s ease-in-out infinite alternate;
}
@keyframes catch {
  to {
    rotate: -6deg;
  }
}
.fc__fan {
  transform-origin: 180px 112px;
  animation: fan 0.9s ease-in-out infinite alternate;
}
.fc__fan-leaf {
  fill: color-mix(in srgb, var(--color-mango) 60%, var(--color-surface));
  stroke-width: 4;
}
.fc__fan-rib {
  stroke-width: 2.5;
}
@keyframes fan {
  from {
    rotate: -8deg;
  }
  to {
    rotate: 10deg;
  }
}
.fc__point {
  transform-origin: 64px 112px;
  animation: point 2.4s ease-in-out infinite alternate;
}
@keyframes point {
  to {
    rotate: 5deg;
  }
}
.fc__cap-cloth {
  fill: var(--color-ocean);
  stroke-width: 4;
}
.fc__cap-pom {
  fill: var(--color-surface);
  stroke-width: 3.5;
}
.fc--sleepy .coconut__z path {
  animation: doze 1.7s ease-in infinite;
}
.fc--sleepy .coconut__z path + path {
  animation-delay: 0.55s;
}
.fc--dance {
  animation: groove 0.48s ease-in-out infinite alternate;
}
.fc__spray path {
  stroke: var(--color-ocean);
  stroke-width: 3.5;
  opacity: 0;
}

/* What it does as it says a line (site.js sets the class for the moment it takes). */
.forecaster.is-shake .fc__figure {
  animation: shake-off 0.6s ease-in-out;
}
.forecaster.is-shake .fc__spray path {
  animation: spray 0.6s ease-out;
}
@keyframes shake-off {
  0%,
  100% {
    rotate: 0deg;
  }
  15%,
  55% {
    rotate: -7deg;
  }
  35%,
  75% {
    rotate: 7deg;
  }
}
@keyframes spray {
  20% {
    opacity: 1;
  }
  to {
    opacity: 0;
    scale: 1.5;
  }
}
.forecaster.is-flinch .fc__figure {
  animation: flinch 0.55s var(--spring);
}
@keyframes flinch {
  30% {
    translate: 0 7px;
    scale: 1.05 0.9;
  }
}
.forecaster.is-fan .fc__fan {
  animation: fan 0.16s ease-in-out 8 alternate;
}
.forecaster.is-point .fc__figure {
  animation: lean 0.8s var(--ease);
}
@keyframes lean {
  40% {
    rotate: 6deg;
    translate: 4px 0;
  }
}
.forecaster.is-look .fc__figure {
  animation: look-up 1.3s var(--ease);
}
.forecaster.is-look .fc__eyes {
  animation: eyes-up 1.3s var(--ease);
}
@keyframes look-up {
  35%,
  70% {
    rotate: -6deg;
  }
}
@keyframes eyes-up {
  35%,
  70% {
    translate: 0 -3px;
  }
}
.forecaster.is-sip .fc__cup {
  transform-origin: 64px 112px;
  animation: sip 1.2s var(--ease);
}
@keyframes sip {
  40%,
  65% {
    rotate: 28deg;
    translate: 18px -18px;
  }
}
.forecaster.is-hop .coconut {
  animation: hop 0.3s cubic-bezier(0.3, 0, 0.7, 1) 4 alternate;
}
.forecaster.is-dance .coconut {
  animation: groove-hard 0.24s ease-in-out 8 alternate;
}
.forecaster.is-wai .fc__figure {
  animation: bow 1s var(--ease);
}
@keyframes bow {
  40%,
  60% {
    rotate: 9deg;
    translate: 0 4px;
  }
}
.forecaster:active .coconut {
  scale: 0.95;
}
.forecaster.is-thinking .coconut__body {
  animation: think 0.5s ease-in-out infinite alternate;
}
@media (max-width: 719px) {
  .wx-sky__tile--moon {
    grid-column: 1 / -1;
  }
}

/* The hours ahead: twelve columns, the first one now; the dry window between rains in mango,
   the sunset as a coral line where it falls. */
.wx-strip {
  display: grid;
  grid-template-columns: 50px repeat(11, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
}
.wx-slot {
  position: relative;
  display: grid;
  justify-items: center;
  gap: 5px;
  padding: 8px 0 6px;
  border-radius: 6px;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.wx-slot.is-window {
  background: color-mix(in srgb, var(--color-mango) 30%, transparent);
  border-radius: 0;
}
.wx-slot.is-window:not(.is-window + .is-window) {
  border-radius: 6px 0 0 6px;
}
.wx-slot.is-window:has(+ :not(.is-window)),
.wx-slot.is-window:last-child {
  border-radius: 0 6px 6px 0;
}
.wx-slot.is-window:not(.is-window + .is-window):has(+ :not(.is-window)) {
  border-radius: 6px;
}
.wx-slot.is-now {
  background: var(--color-surface);
  box-shadow: inset 0 0 0 1.5px var(--color-ink);
}
.wx-slot__hour {
  color: var(--color-muted);
  font-weight: 600;
}
.is-now .wx-slot__hour {
  color: var(--color-action);
  font-size: 10px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.wx-slot__temp {
  min-height: 1.2em;
  font-weight: 600;
}
.wx-slot__rain {
  display: flex;
  align-items: end;
  width: 60%;
  height: 22px;
  border-bottom: 1px solid var(--color-line);
}
.wx-slot__rain i {
  width: 100%;
  height: calc(var(--level) * 33.3%);
  border-radius: 2px 2px 0 0;
  background: var(--color-ocean);
  transform-origin: bottom;
  animation: grow 0.6s var(--ease) both;
}
.wx-slot--storm .wx-slot__rain i {
  background: var(--color-coral);
}
@keyframes grow {
  from {
    scale: 1 0;
  }
}
.wx-slot__sunset {
  position: absolute;
  inset: 4px auto 4px calc(var(--at) * 100%);
  width: 0;
  border-left: 2px dashed var(--color-coral);
}
.wx-slot__sunset span {
  position: absolute;
  bottom: -18px;
  left: -14px;
  color: var(--color-action);
  font-size: 10px;
  white-space: nowrap;
}
.wx-icon {
  overflow: visible;
}
.wx-icon__sun,
.wx-icon__moon {
  fill: var(--color-mango);
}
.wx-icon__cloud {
  fill: var(--color-surface);
}
.wx-icon--rain .wx-icon__cloud,
.wx-icon--storm .wx-icon__cloud {
  fill: color-mix(in srgb, var(--color-muted) 25%, var(--color-surface));
}
.wx-icon__drops {
  stroke: var(--color-ocean);
}
.wx-icon__bolt {
  stroke: var(--color-coral);
}

/* The radar's picture: the island's coast over the rain, the places it rains named. */
.wx-radar__figure {
  display: grid;
  gap: 14px;
  margin: 0;
}
.wx-radar__map {
  width: 100%;
  max-width: 440px;
  height: auto;
  border: 1px solid var(--color-ink);
  border-radius: var(--radius-art);
}
.wx-radar__sea {
  fill: color-mix(in srgb, var(--color-ocean-soft) 75%, var(--color-surface));
}
.wx-radar__land {
  fill: var(--color-sand);
}
.wx-radar__coast {
  fill: none;
  stroke: var(--color-ink);
  stroke-width: 1.1;
  vector-effect: non-scaling-stroke;
}
.wx-cell {
  fill: var(--color-ocean);
  animation: breathe-cell 3.6s ease-in-out calc(var(--i) * -0.5s) infinite alternate;
}
.wx-cell--2 {
  opacity: 0.26;
}
.wx-cell--3 {
  opacity: 0.48;
}
.wx-cell--4 {
  opacity: 0.7;
}
.wx-cell--5,
.wx-cell--6 {
  fill: var(--color-coral);
  opacity: 0.8;
}
.wx-cell--6 {
  opacity: 0.95;
}
@keyframes breathe-cell {
  to {
    translate: 0 -0.12px;
  }
}
.wx-pin circle {
  fill: var(--color-ink);
}
.wx-pin.is-wet {
  animation: pin-wet 1.6s ease-in-out infinite alternate;
}
@keyframes pin-wet {
  to {
    opacity: 0.7;
  }
}
.wx-pin text {
  fill: var(--color-ink);
  font: 600 1.05px/1 var(--font-sans);
  paint-order: stroke;
  stroke: var(--color-surface);
  stroke-width: 0.32px;
  stroke-linejoin: round;
}
.wx-pin.is-wet circle {
  fill: var(--color-ocean);
  stroke: var(--color-surface);
  stroke-width: 0.25px;
}
.wx-radar__said {
  font-weight: 600;
}
.wx-radar__at,
.wx-radar__legend {
  color: var(--color-muted);
  font-size: 13px;
}
.wx-radar__legend {
  display: flex;
  align-items: center;
  gap: 6px;
}
.wx-key {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 2px;
  background: color-mix(in srgb, var(--color-ocean) 55%, transparent);
}
.wx-key--heavy {
  margin-left: 10px;
  background: var(--color-coral);
}

/* What to do: the good ideas as cards, what to put off as a quiet list. */
.wx-todo__label {
  margin-bottom: 10px;
  color: var(--color-palm);
  font: 500 14px/1.3 var(--font-display);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.wx-todo__label--skip {
  margin-top: 22px;
  color: var(--color-action);
}
.wx-todo__good {
  display: grid;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.wx-todo__card {
  display: grid;
  grid-template-columns: 44px 1fr;
  gap: 2px 12px;
  align-items: start;
  padding: 14px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-card);
  background: var(--color-surface);
}
.wx-todo__card .wx-todo__icon {
  grid-row: span 2;
  color: var(--color-ocean);
}
.wx-todo__card--go {
  border-color: var(--color-ink);
}
.wx-todo__card h3 {
  font: 500 19px/1.2 var(--font-display);
  text-transform: uppercase;
}
.wx-todo__card p {
  font-size: 14px;
}
.wx-todo__skip {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.wx-todo__skip li {
  display: grid;
  grid-template-columns: 32px 1fr;
  gap: 10px;
  align-items: start;
  color: var(--color-muted);
  font-size: 14px;
}
.wx-todo__skip .wx-todo__icon {
  width: 30px;
  height: 30px;
}
.wx-todo__skip b {
  color: var(--color-ink);
}

/* Today's events under the open sky, each with its sky. */
.wx-events__list {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.wx-event a {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 2px 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--color-line);
  color: inherit;
  text-decoration: none;
}
.wx-event__time {
  grid-row: span 2;
  min-width: 3.2em;
  font: 500 18px/1.2 var(--font-display);
}
.wx-event__title {
  font-weight: 600;
}
.wx-event__sky {
  display: inline-flex;
  align-items: center;
  justify-self: start;
  gap: 6px;
  padding: 2px 10px 2px 6px;
  border-radius: 99px;
  background: var(--color-success-soft);
  font-size: 13px;
}
.wx-event--rain .wx-event__sky {
  background: var(--color-ocean-soft);
}
.wx-event--storm .wx-event__sky {
  background: var(--color-danger-soft);
}
.wx-event--unknown .wx-event__sky,
.wx-event--now .wx-event__sky {
  background: transparent;
  color: var(--color-muted);
}

/* The sun and the moon. */
.wx-sky__tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
  margin: 0;
}
.wx-sky__tile {
  padding: 12px 14px;
  border-top: 3px solid var(--color-mango);
  background: var(--color-surface);
}
.wx-sky__tile--set {
  border-top-color: var(--color-coral);
}
.wx-sky__tile--moon {
  border-top-color: var(--color-ocean);
}
.wx-sky__tile dt {
  color: var(--color-muted);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.wx-sky__tile dd {
  display: grid;
  gap: 2px;
  margin: 4px 0 0;
  font-size: 13px;
}
.wx-sky__tile b {
  font: 500 24px/1.1 var(--font-display);
}

/* Where in the year we are: how wet each month usually is. */
.wx-year {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  align-items: end;
  gap: 4px;
  height: 84px;
  margin: 4px 0 0;
  padding: 0;
  list-style: none;
}
.wx-year__month {
  display: grid;
  justify-items: center;
  gap: 4px;
}
.wx-year__bar {
  width: 100%;
  height: calc(10px + var(--wet) * 17px);
  border-radius: 3px 3px 0 0;
  background: color-mix(in srgb, var(--color-ocean) calc(22% + var(--wet) * 20%), transparent);
}
.wx-year__month.is-now .wx-year__bar {
  background: var(--color-coral);
}
.wx-year__letter {
  color: var(--color-muted);
  font-size: 12px;
  font-weight: 600;
}
.is-now .wx-year__letter {
  color: var(--color-action);
}
.wx-season__text {
  max-width: 40em;
  margin-top: 14px;
}
.wx-note {
  max-width: 40em;
  margin-top: 14px;
  font-size: 13px;
}

@media (min-width: 720px) {
  .wx-scene {
    height: 320px;
    margin-inline: 0;
    border: 1px solid var(--color-ink);
    border-radius: var(--radius-art);
  }
  .wx-scene__coconut {
    left: 24px;
    width: 168px;
  }
  .forecaster__said {
    top: 26px;
    left: 200px;
    max-width: 320px;
    font-size: 15px;
  }
  .wx-todo__good {
    grid-template-columns: repeat(3, 1fr);
  }
  .wx-todo__card {
    grid-template-columns: 1fr;
  }
  .wx-todo__card .wx-todo__icon {
    grid-row: auto;
  }
  .wx-radar__figure {
    grid-template-columns: minmax(0, 440px) 1fr;
    align-items: end;
  }
}
@media (min-width: 960px) {
  .wx-hero {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
    align-items: center;
    gap: 32px;
  }
}

/* --- Footer --- */

.foot {
  margin-top: 72px;
  background: var(--footer-bg, var(--color-ink));
  color: var(--footer-fg, var(--color-sand));
}
.foot__inner {
  position: relative;
  display: grid;
  gap: 14px;
  padding-top: 40px;
  padding-bottom: max(32px, env(safe-area-inset-bottom));
}
.foot__mark {
  font: 400 64px/0.85 var(--font-wordmark);
  color: var(--color-coral);
}
.foot__about {
  max-width: 30em;
}
.foot__links p {
  display: flex;
  flex-wrap: wrap;
  gap: 0 22px;
}
.foot__links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: inherit;
}
.foot__made {
  opacity: 0.7;
  font-size: 13px;
}
.foot :focus-visible {
  outline-color: var(--color-mango);
}

/* --- Wider screens: the same page with more air --- */

/* Three sections and the language fit a phone's width: the words never break. */
.wordmark,
.top__nav a {
  flex-shrink: 0;
  overflow-wrap: normal;
  white-space: nowrap;
}
@media (max-width: 419px) {
  .top__nav {
    gap: 0;
  }
  .top__nav a {
    padding-inline: 5px;
    letter-spacing: 0.03em;
  }
  .top__nav .top__language {
    min-width: 40px;
    margin-left: 4px;
  }
}
@media (max-width: 359px) {
  .wordmark__place {
    display: none;
  }
  .top__nav a {
    padding-inline: 4px;
    font-size: 14px;
  }
}
@media (min-width: 720px) {
  :root {
    --gutter: 32px;
  }
  .map {
    max-width: 560px;
  }
  .channels {
    grid-template-columns: repeat(2, minmax(0, 260px));
  }
  .posts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .pitch {
    grid-template-columns: auto 1fr;
    align-items: center;
    padding: 32px 36px;
  }
  .pitch__art {
    width: 190px;
    margin-left: -20px;
  }
  .pitch__coconut {
    width: 190px;
  }
  .pitch__plane {
    left: 176px;
    top: 50px;
  }
  .filters {
    margin-inline: 0;
  }
  .chips {
    flex-wrap: wrap;
    padding-inline: 0;
  }
  .segmented {
    max-width: 420px;
    margin-inline: 0;
  }
  .filters__date {
    padding-inline: 0;
  }
  .results {
    max-width: var(--reading-max);
  }
}
@media (min-width: 960px) {
  .top {
    padding-block: 22px 18px;
  }
  .top__nav a {
    padding-inline: 14px;
    font-size: 16px;
  }
  .hero {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    align-items: center;
    gap: 48px;
    padding-block: 48px 24px;
  }
  .hero__art {
    order: 2;
    display: block;
    min-height: 470px;
  }
  .hero__sun {
    left: auto;
    right: 4%;
    top: 0;
    width: 260px;
  }
  .hero__stamp {
    display: block;
    width: min(360px, 100%);
    margin: 24px auto 0;
  }
  .hero__note {
    position: absolute;
    left: 0;
    bottom: 18px;
    margin: 0;
    font-size: 26px;
  }
  .hero__rider {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 190px;
    height: 130px;
  }
  .hero__rider .coconut {
    right: 46px;
    bottom: 22px;
    width: 104px;
  }
  .hero__waves {
    width: 170px;
    height: auto;
  }
  .moon {
    top: 18px;
    width: 46px;
    height: 46px;
  }
  .blocks {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: 0 56px;
  }
  .block {
    margin-top: 72px;
  }
  .page-head {
    padding-block: 40px 28px;
  }
}

/* A wide screen has room for the map beside the list: it stays in sight while the list
   scrolls, so a sailing opened anywhere is sailed where the reader can see it. */
@media (min-width: 1080px) {
  .results:has(> .map) {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 420px;
    column-gap: 56px;
    align-items: start;
    max-width: none;
  }
  .results:has(> .map) > * {
    grid-column: 1;
  }
  .results:has(> .map) > .map {
    position: sticky;
    top: 20px;
    grid-column: 2;
    grid-row: 1 / span 12;
    max-width: none;
    margin-top: 0;
  }
  .js .results:has(.map) .sailing__show {
    display: none;
  }
}

/* --- Motion ---
   Everything that moves changes only transform and opacity, so the phone's compositor does it
   without laying the page out again. What depends on scrolling is a scroll-driven animation:
   it runs off the main thread and needs no script. Readers who asked their device for less
   motion get a still page. */

.button,
.chip,
.segmented a {
  transition:
    scale 0.14s var(--ease),
    background var(--motion-ui),
    color var(--motion-ui),
    border-color var(--motion-ui);
}
.button:active {
  scale: 0.97;
}
.chip:active,
.segmented a:active {
  scale: 0.95;
}
/* A coconut that can be tapped squats under the thumb, and the moon gives under it and
   stays swollen while its note is open. */
.greeter .coconut,
.pitch__art .coconut {
  transform-origin: 50% 92%;
  transition: scale 0.25s var(--spring);
}
.greeter:active .coconut,
.pitch__art:active .coconut {
  scale: 0.94;
}
.moon svg {
  transition: scale 0.35s var(--spring);
}
.moon:active svg {
  scale: 0.9;
}
.moon:has(+ .moon__info:popover-open) svg {
  scale: 1.14;
}
.event,
.post {
  transition:
    translate 0.25s var(--ease),
    border-color var(--motion-ui);
}
@media (hover: hover) {
  .event:hover,
  .post:hover {
    translate: 0 -3px;
    border-color: var(--color-ocean);
  }
  .hero__stamp {
    transform: perspective(700px) rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg));
    transition: transform 0.3s var(--ease);
  }
}
/* The next sailing breathes: a dot beside its hour, and in its last hour a line under it
   that fills up. */
.sailing.is-next::after {
  content: "";
  position: absolute;
  left: -13px;
  top: 23px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-coral);
  animation: ping 2s var(--ease) infinite;
}
.sailing:has(> details[open]).is-next::after {
  left: 8px;
  top: 6px;
}
.sailing.is-next::before {
  content: "";
  position: absolute;
  inset: auto 0 -1px;
  height: 2px;
  background: var(--color-coral);
  transform: scaleX(var(--gone, 0));
  transform-origin: left;
  transition: transform 1s linear;
}
/* An event that is on right now. */
.live::before {
  animation: ping 2s var(--ease) infinite;
}
.stars i {
  animation: twinkle 2.8s ease-in-out infinite alternate;
}
.stars i:nth-child(2n) {
  animation-delay: -1.3s;
}
@keyframes twinkle {
  from {
    opacity: 0.25;
    scale: 0.7;
  }
}
/* What has scrolled out of sight does not keep moving: the script marks it (a phone's
   battery is the reader's). */
.is-offscreen,
.is-offscreen * {
  animation-play-state: paused !important;
}
@keyframes ping {
  0% {
    scale: 1;
    opacity: 0.9;
  }
  70%,
  100% {
    scale: 2.6;
    opacity: 0;
  }
}
.sailing__soon.is-ticking {
  animation: tick 0.5s var(--spring);
}
@keyframes tick {
  from {
    opacity: 0.2;
    translate: 0 -5px;
  }
}
/* "Details" open and close with their height, where the browser can animate to auto. */
@supports (interpolate-size: allow-keywords) {
  :root {
    interpolate-size: allow-keywords;
  }
  details::details-content {
    block-size: 0;
    overflow: clip;
    transition:
      block-size 0.3s var(--ease),
      content-visibility 0.3s allow-discrete;
  }
  details[open]::details-content {
    block-size: auto;
  }
}
/* The moon's note fades in from the moon. */
.moon__info {
  opacity: 0;
  translate: 0 -6px;
  transition:
    opacity 0.2s,
    translate 0.2s var(--ease),
    display 0.2s allow-discrete,
    overlay 0.2s allow-discrete;
}
.moon__info:popover-open {
  opacity: 1;
  translate: 0 0;
}
@starting-style {
  .moon__info:popover-open {
    opacity: 0;
    translate: 0 -6px;
  }
}

/* The coconut is alive: it blinks and sways a little, and each pose has its own habit. */
.coconut {
  animation: bob 3.2s ease-in-out infinite alternate;
}
.coconut__eyes {
  transform-box: fill-box;
  transform-origin: center;
  animation: blink 5.6s infinite;
}
.coconut__hand {
  transform-box: view-box;
  transform-origin: 180px 108px;
}
.coconut__hand--left {
  transform-origin: 64px 110px;
}
.coconut--wave .coconut__hand {
  animation: wave 5s var(--ease) infinite;
}
.is-waving .coconut__hand {
  animation: wave-now 0.5s ease-in-out 3;
}
/* The coconut greets: the clock swings its waving forearm, and scrolling the page on folds
   its hands into a wai (scrolling back unfolds them). Both only move two numbers on the
   button around it; the joints, the bow and the written word follow (see .greet__arm). */
.greeter {
  animation: hail 4.6s var(--ease) infinite;
}
/* It is never quite still: it rocks a little on its feet. */
.coconut--greet {
  transform-origin: 50% 90%;
  animation:
    bob 3.2s ease-in-out infinite alternate,
    rock-soft 5.4s ease-in-out infinite alternate;
}
@keyframes rock-soft {
  from {
    rotate: -2.5deg;
  }
  to {
    rotate: 2.5deg;
  }
}
/* At night it is found asleep, and wakes a moment after the page opens. */
.greeter--waking {
  animation:
    hail 4.6s var(--ease) 2.2s infinite,
    wake 0.9s var(--ease) 1.6s both;
}
.greeter--waking .coconut__z path {
  animation: doze 1.7s ease-in infinite;
}
.greeter--waking .coconut__z path + path {
  animation-delay: 0.55s;
}
@supports (animation-timeline: scroll()) {
  .greeter {
    animation:
      hail 4.6s var(--ease) infinite,
      wai linear both;
    animation-timeline: auto, scroll(root block);
    animation-range: normal, 16px 150px;
  }
  .greeter--waking {
    animation:
      hail 4.6s var(--ease) 2.2s infinite,
      wake 0.9s var(--ease) 1.6s both,
      wai linear both;
    animation-timeline: auto, auto, scroll(root block);
    animation-range: normal, normal, 16px 150px;
  }
}
@keyframes wake {
  from {
    --wake: 0;
  }
  to {
    --wake: 1;
  }
}
/* Four beats of the hand, then a rest. (Not "swing": the dancers' rocking has that name,
   and of two keyframes with one name the later wins.) */
@keyframes hail {
  0%,
  44%,
  100% {
    --swing: 0;
  }
  52%,
  68%,
  84% {
    --swing: 1;
  }
  60%,
  76% {
    --swing: -0.9;
  }
}
@keyframes wai {
  to {
    --pose: 1;
  }
}
/* What it has with it is alive too: the leaf takes the wind, drops fall past it, steam rises
   from the cup, a drop of sweat runs down in the heat. */
.greet__rain path,
.hero__drops path {
  animation: drop 1.1s linear infinite;
}
.greet__rain path:nth-child(2n),
.hero__drops path:nth-child(2n) {
  animation-delay: -0.45s;
}
.greet__rain path:nth-child(3n),
.hero__drops path:nth-child(3n) {
  animation-delay: -0.8s;
}
.mood--storm .greet__rain path {
  animation-duration: 0.6s;
}
.mood--rain .greet__leaf {
  animation: leaf 3.4s ease-in-out infinite alternate;
}
.mood--storm .greet__leaf {
  animation: leaf 0.5s ease-in-out infinite alternate;
}
.greet__steam {
  animation: steam 2.6s ease-in-out infinite;
}
.greet__sweat {
  animation: sweat 3.2s ease-in infinite;
}
/* A night with a party on: notes drift up from somewhere, and it sways to the beat. */
.greet__notes > g {
  animation: note 2.6s ease-out infinite;
}
.greet__notes > g:nth-child(2) {
  animation-delay: -0.9s;
}
.greet__notes > g:nth-child(3) {
  animation-delay: -1.7s;
}
.mood--nightlife.coconut--greet {
  animation: groove 0.48s ease-in-out infinite alternate;
}
/* Tapped while it tells about a party, it answers with a few harder beats. */
.greeter.is-dancing .coconut--greet {
  animation: groove-hard 0.24s ease-in-out 8 alternate;
}
@keyframes note {
  0% {
    opacity: 0;
    translate: 0 10px;
  }
  25% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    translate: 6px -18px;
  }
}
@keyframes groove {
  from {
    rotate: -4deg;
    translate: 0 0;
  }
  to {
    rotate: 4deg;
    translate: 0 -4px;
  }
}
@keyframes groove-hard {
  from {
    rotate: -10deg;
    translate: 0 0;
  }
  to {
    rotate: 10deg;
    translate: 0 -8px;
  }
}
.hero__cloud {
  animation: cloud 9s ease-in-out infinite alternate;
}
@keyframes drop {
  from {
    opacity: 0;
    translate: 0 0;
  }
  15% {
    opacity: 1;
  }
  to {
    opacity: 0;
    translate: -16px 46px;
  }
}
@keyframes leaf {
  from {
    rotate: -3deg;
  }
  to {
    rotate: 4deg;
  }
}
@keyframes steam {
  0% {
    opacity: 0;
    translate: 0 6px;
  }
  40% {
    opacity: 0.9;
  }
  100% {
    opacity: 0;
    translate: 0 -8px;
  }
}
@keyframes sweat {
  0%,
  35% {
    opacity: 0;
    translate: 0 0;
  }
  45% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    translate: 2px 34px;
  }
}
@keyframes cloud {
  to {
    translate: 14px 0;
  }
}
/* A storm in the forecast: the sea is rougher, on the first screen and on the ferries' map. */
html[data-weather="storm"] .map__bob {
  animation-duration: 0.9s;
}
/* The one main action draws the eye once, after the page has arrived. */
.channels .button--primary {
  position: relative;
}
.channels .button--primary::after {
  content: "";
  position: absolute;
  inset: -5px;
  border: 2px solid var(--color-action);
  border-radius: 10px;
  opacity: 0;
  pointer-events: none;
  animation: ring 0.9s var(--ease) 1.5s;
}
/* Back from Telegram, the coconut is glad. */
.greeter.is-glad .coconut {
  animation: hop 0.3s cubic-bezier(0.3, 0, 0.7, 1) 4 alternate;
}
/* Tapped, it thinks for the moment the answer takes. */
.greeter.is-thinking .coconut__body {
  animation: think 0.5s ease-in-out infinite alternate;
}
@keyframes think {
  to {
    rotate: 5deg;
  }
}
.greeter__said {
  transform-origin: 100% 100%;
  animation: say 0.32s var(--spring);
}
@keyframes say {
  from {
    opacity: 0;
    scale: 0.7;
  }
}
/* The paper plane is a chain in which every link answers the one before: the arm swings,
   the plane crosses to the Telegram button, the button takes the hit and keeps the plane,
   the coconut is glad it got there. The script measures the way (site.js). */
.coconut--throw .coconut__hand {
  transform-origin: 180px 110px;
}
.is-throwing .coconut__hand {
  animation: throw 0.55s var(--spring);
}
@keyframes throw {
  0% {
    rotate: -42deg;
  }
}
/* The hand is empty while the plane is away; then it has folded another. */
.pitch__plane {
  transition:
    opacity 0.2s,
    scale 0.4s var(--spring);
}
.pitch.is-throwing .pitch__plane,
.pitch.is-empty .pitch__plane {
  opacity: 0;
  scale: 0.3;
  transition: none;
}
/* Across at an even speed, while it climbs out of the hand, tips over and comes down nose
   first: two transforms on two elements, so the path is an arc and the compositor draws it. */
.pitch.is-throwing .pitch__flight {
  visibility: visible;
  animation: fly-across var(--flight, 0.9s) linear both;
}
.pitch.is-throwing .pitch__flying {
  animation: fly-arc var(--flight, 0.9s) both;
}
@keyframes fly-across {
  to {
    transform: translateX(var(--fly-x, 140px));
  }
}
@keyframes fly-arc {
  0% {
    transform: translateY(0) rotate(var(--fly-rise, -30deg));
    animation-timing-function: cubic-bezier(0.2, 0.6, 0.4, 1);
  }
  36% {
    transform: translateY(var(--fly-up, -40px)) rotate(38deg);
    animation-timing-function: cubic-bezier(0.5, 0, 0.85, 0.7);
  }
  100% {
    transform: translateY(var(--fly-y, 180px)) rotate(var(--fly-dive, 110deg));
  }
}
/* The hit: the button gives under the plane and springs back, a ring goes out, marker lines
   burst from where it landed, and the plane turns upright into its place. */
.pitch .button.is-hit {
  animation: hit 0.55s var(--ease);
}
.pitch .button.is-hit::after {
  animation: ring 0.75s var(--ease);
}
.is-hit .button__sparks {
  animation: spark 0.5s var(--ease);
}
.is-hit .button__plane {
  animation: dock 0.55s var(--spring);
}
@keyframes hit {
  18% {
    scale: 0.94;
    translate: 2px 3px;
  }
  52% {
    scale: 1.035;
    translate: 0 0;
  }
  76% {
    scale: 0.992;
  }
}
@keyframes spark {
  from {
    opacity: 1;
    scale: 0.35;
  }
  60% {
    opacity: 1;
  }
  to {
    opacity: 0;
    scale: 1.25;
  }
}
@keyframes dock {
  from {
    rotate: var(--fly-dive, 110deg);
    scale: 1.3;
    translate: -5px -7px;
  }
}
.pitch.is-glad .pitch__coconut {
  animation: hop 0.26s cubic-bezier(0.3, 0, 0.7, 1) 2 alternate;
}
@keyframes ring {
  from {
    opacity: 0.9;
    scale: 1;
  }
  to {
    opacity: 0;
    scale: 1.07 1.32;
  }
}
.coconut--sleep {
  animation: none;
}
.coconut--sleep .coconut__body {
  transform-box: view-box;
  transform-origin: 122px 178px;
  animation: breathe 3.4s ease-in-out infinite alternate;
}
.coconut--sleep .coconut__z path {
  animation: doze 3.4s ease-in infinite;
}
.coconut--sleep .coconut__z path + path {
  animation-delay: 1.1s;
}
.coconut--look {
  transform-origin: 50% 90%;
  animation: scan 5s ease-in-out infinite alternate;
}
.coconut--facepalm .coconut__body {
  transform-box: view-box;
  transform-origin: 122px 170px;
  animation: shake 6s ease-in-out infinite;
}
.coconut--dance {
  transform-origin: 50% 92%;
  animation:
    hop 0.46s cubic-bezier(0.3, 0, 0.7, 1) infinite alternate,
    sway 1.84s ease-in-out infinite;
}
.coconut--dance .coconut__hand {
  animation: swing 0.92s ease-in-out infinite alternate;
}
.coconut--dance .coconut__hand--left {
  animation-direction: alternate-reverse;
}
@keyframes bob {
  to {
    translate: 0 -3px;
  }
}
@keyframes blink {
  0%,
  93%,
  100% {
    scale: 1 1;
  }
  96% {
    scale: 1 0.08;
  }
}
@keyframes wave {
  0%,
  58%,
  100% {
    rotate: 0deg;
  }
  66%,
  82% {
    rotate: 15deg;
  }
  74%,
  90% {
    rotate: -7deg;
  }
}
@keyframes wave-now {
  50% {
    rotate: 16deg;
  }
}
@keyframes breathe {
  to {
    scale: 1.03 1.02;
  }
}
@keyframes doze {
  0% {
    opacity: 0;
    translate: -6px 10px;
  }
  30% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    translate: 8px -16px;
  }
}
@keyframes scan {
  from {
    rotate: -4deg;
  }
  to {
    rotate: 4deg;
  }
}
@keyframes shake {
  0%,
  12%,
  100% {
    rotate: 0deg;
  }
  3%,
  9% {
    rotate: -3deg;
  }
  6% {
    rotate: 3deg;
  }
}
@keyframes hop {
  to {
    translate: 0 -9px;
  }
}
@keyframes sway {
  0%,
  100% {
    rotate: -6deg;
  }
  50% {
    rotate: 6deg;
  }
}
@keyframes swing {
  from {
    rotate: -16deg;
  }
  to {
    rotate: 14deg;
  }
}

/* The crossing, once a sailing is chosen: out from the pier, across, and in; then again.
   Until then the boat only rocks at its pier. */
.map.is-sailing .map__boat {
  animation: sail var(--crossing, 9s) var(--ease) infinite;
}
.map__bob {
  animation: rock 1.7s ease-in-out infinite alternate;
}
/* The pier answers the boat coming in: it swells, and a ring goes out over the water. They
   run on the crossing's clock (and are started over together with it), so they meet: the
   hull reaches the pier 43% into the crossing and drifts the last few points after that. */
.map.is-sailing .map__ripple {
  animation: moor var(--crossing, 9s) linear infinite;
}
.map.is-sailing .map__dot.is-port {
  animation: berth var(--crossing, 9s) var(--ease) infinite;
}
.is-resetting :is(.map__boat, .map__ripple, .map__dot) {
  animation: none !important;
}
/* Tapped, the coconut squats under the thumb, hops in its boat, and what it says pops up. */
.map__boat:active .map__face {
  translate: 0 1.5px;
}
.map__boat.is-talking .map__bob {
  animation:
    rock 1.7s ease-in-out infinite alternate,
    hop 0.16s cubic-bezier(0.3, 0, 0.7, 1) 2 alternate;
}
.map__said.is-said {
  transform-origin: 12% 100%;
  animation: say 0.32s var(--spring);
}
@keyframes moor {
  0%,
  41% {
    opacity: 0;
    scale: 1;
  }
  43% {
    opacity: 1;
    scale: 1;
  }
  60%,
  100% {
    opacity: 0;
    scale: 5;
  }
}
@keyframes berth {
  0%,
  41%,
  55%,
  100% {
    scale: 1;
  }
  45% {
    scale: 1.75;
  }
}
@keyframes sail {
  0% {
    offset-distance: 0%;
    opacity: 0;
  }
  6% {
    opacity: 1;
  }
  86% {
    offset-distance: 100%;
    opacity: 1;
  }
  100% {
    offset-distance: 100%;
    opacity: 0;
  }
}
@keyframes rock {
  from {
    rotate: -7deg;
  }
  to {
    rotate: 7deg;
  }
}

/* Arrival: the first screen assembles itself, once. */
.hero__copy > *,
.page-head > * {
  animation: arrive 0.6s var(--ease) both;
}
.hero__copy > :nth-child(2),
.page-head > :nth-child(2) {
  animation-delay: 0.06s;
}
.hero__copy > :nth-child(3),
.page-head > :nth-child(3) {
  animation-delay: 0.12s;
}
.hero__copy > :nth-child(4) {
  animation-delay: 0.18s;
}
.hero__copy > :nth-child(5) {
  animation-delay: 0.24s;
}
.hero__sun {
  animation: rise 0.9s var(--ease) 0.1s both;
}
.hero__stamp {
  animation: stamp 0.55s var(--spring) 0.2s both;
}
/* Tapped, it is pressed onto the paper once more. (The arrival stays in the list, or it
   would play again when the press is over.) */
.hero__stamp.is-pressed {
  animation:
    stamp 0.55s var(--spring) 0.2s both,
    press 0.4s var(--ease);
}
@keyframes press {
  30% {
    scale: 0.93;
    rotate: -7deg;
  }
  66% {
    scale: 1.03;
  }
}
.hero__note {
  animation: write 0.7s steps(18, end) 0.55s both;
}
.hero__rider {
  animation: arrive 0.6s var(--ease) 0.5s both;
}
.hero__waves path {
  stroke-dasharray: 140;
  animation: draw 0.9s var(--ease) 0.6s both;
}
.hero__waves path:nth-child(2) {
  animation-delay: 0.72s;
}
.hero__waves path:nth-child(3) {
  animation-delay: 0.84s;
}
.moon {
  animation: moonrise 0.9s var(--ease) 0.25s both;
}
@keyframes arrive {
  from {
    opacity: 0;
    translate: 0 14px;
  }
}
@keyframes rise {
  from {
    opacity: 0;
    translate: 0 44px;
  }
}
/* Pressed onto the paper like a postal stamp. */
@keyframes stamp {
  from {
    opacity: 0;
    scale: 1.45;
    rotate: -14deg;
  }
}
@keyframes write {
  from {
    clip-path: inset(0 100% 0 0);
  }
  to {
    clip-path: inset(0 -10% 0 0);
  }
}
@keyframes draw {
  from {
    stroke-dashoffset: 140;
  }
}
@keyframes moonrise {
  from {
    opacity: 0;
    translate: 0 26px;
    scale: 0.6;
  }
}

/* Scrolling: what comes into view rises into place, and the layers of the first screen
   drift apart at their own speeds. The scroll position itself is the clock. */
@supports (animation-timeline: view()) {
  .block__head,
  .events > .event,
  .sailings > .sailing,
  .posts > li,
  .pitch,
  .nudge,
  .sources,
  .empty > :not(svg) {
    animation: reveal linear both;
    animation-timeline: view();
    animation-range: entry 0% entry 70%;
  }
  .hero__sun {
    animation:
      rise 0.9s var(--ease) 0.1s both,
      drift linear both;
    animation-timeline: auto, scroll(root block);
    animation-range: normal, 0 700px;
    --drift: 70px;
  }
  .hero__note {
    animation:
      write 0.7s steps(18, end) 0.55s both,
      drift linear both;
    animation-timeline: auto, scroll(root block);
    animation-range: normal, 0 700px;
    --drift: -46px;
  }
  .hero__rider {
    animation:
      arrive 0.6s var(--ease) 0.5s both,
      drift linear both;
    animation-timeline: auto, scroll(root block);
    animation-range: normal, 0 700px;
    --drift: 34px;
  }
  .moon {
    animation:
      moonrise 0.9s var(--ease) 0.25s both,
      drift linear both;
    animation-timeline: auto, scroll(root block);
    animation-range: normal, 0 600px;
    --drift: 110px;
  }
  .pitch__art {
    animation: lift linear both;
    animation-timeline: view();
    animation-range: entry 0% exit 100%;
  }
  /* A row of chips fades at the edge it continues past. */
  .chips {
    animation: fade-edges linear both;
    animation-timeline: scroll(self inline);
  }
}
@keyframes fade-edges {
  from {
    --fade-start: 0px;
    --fade-end: 30px;
  }
  to {
    --fade-start: 30px;
    --fade-end: 0px;
  }
}
@keyframes reveal {
  from {
    opacity: 0;
    transform: translateY(26px);
  }
}
@keyframes drift {
  to {
    transform: translateY(var(--drift));
  }
}
@keyframes lift {
  from {
    transform: translateY(26px);
  }
  to {
    transform: translateY(-18px);
  }
}
/* Browsers without scroll-driven animations: the script marks what has come into view. */
.io .will-reveal {
  opacity: 0;
  transform: translateY(22px);
}
.io .will-reveal.is-seen {
  opacity: 1;
  transform: none;
  transition:
    opacity 0.5s var(--ease),
    transform 0.5s var(--ease);
}

/* Between pages and between filters: the page slides, and what is on both sides (the
   wordmark, the moon, a card that stays in the list) travels to its new place. */
@view-transition {
  navigation: auto;
}
main {
  view-transition-name: main;
}
::view-transition-group(*) {
  animation-duration: 0.34s;
  animation-timing-function: var(--ease);
}
::view-transition-old(main) {
  animation: 0.16s ease-in both leave;
}
::view-transition-new(main) {
  animation: 0.3s var(--ease) 0.08s both enter;
}
@keyframes leave {
  to {
    opacity: 0;
    translate: 0 -8px;
  }
}
@keyframes enter {
  from {
    opacity: 0;
    translate: 0 14px;
  }
}

/* --- The night of the Full Moon Party ---
   The same page under ultraviolet: night instead of paper, the brand's inks turned neon. Only
   the tokens change; every component reads them as before. */

html[data-party] {
  color-scheme: dark;
  --color-sand: #150f2e;
  --color-paper: #150f2e;
  --color-surface: #221a47;
  --color-ink: #fff6e6;
  --color-muted: #b9aed6;
  --color-line: #3b2f6b;
  --color-control-border: #7767b8;
  --color-ocean: #5fe3ff;
  --color-ocean-soft: #1c2a57;
  --color-coral: #ff4d8d;
  --color-mango: #ffd23f;
  --color-action: #ff4d8d;
  --color-action-hover: #ff7aa8;
  --on-action: #1a1030;
  --color-danger: #ff9db0;
  --color-danger-soft: #4a1730;
  --color-palm: #7cffb2;
  --color-success-soft: #123a2a;
  --color-warning: #ffd23f;
  --color-warning-soft: #3d3210;
  --footer-bg: #0c0820;
  --footer-fg: #fff6e6;
  --uv-pink: #ff3d9a;
  --uv-green: #5cff8f;
  --uv-yellow: #ffe44d;
}
html[data-party] .hero__sun {
  background: var(--uv-pink);
}
html[data-party] .hero__stamp {
  box-shadow:
    0 0 0 2px var(--uv-yellow),
    0 0 28px rgb(255 61 154 / 55%);
}
html[data-party] .hero__note,
html[data-party] .wordmark__number,
html[data-party] h1 {
  text-shadow: 0 0 18px rgb(255 77 141 / 45%);
}
html[data-party] .coconut {
  filter: drop-shadow(0 0 5px rgb(95 227 255 / 65%));
}
html[data-party] .pitch .coconut,
html[data-party] .roller .coconut {
  filter: none;
}
html[data-party] .event,
html[data-party] .post {
  border-color: var(--color-control-border);
}
html[data-party] .greeter__said,
html[data-party] .moon__info {
  border-color: var(--uv-pink);
}
/* The moon is the host tonight: larger, with a halo that breathes. */
html[data-party] .moon {
  width: 60px;
  height: 60px;
}
html[data-party] .moon::before {
  content: "";
  position: absolute;
  inset: -70%;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgb(255 246 230 / 55%), rgb(255 246 230 / 0%));
  animation: halo 3.6s ease-in-out infinite alternate;
}
html[data-party] .moon__night {
  fill: #2b2160;
}
html[data-party] .moon__lit {
  fill: #fff6e6;
}
@keyframes halo {
  from {
    opacity: 0.45;
    scale: 0.9;
  }
  to {
    opacity: 1;
    scale: 1.08;
  }
}
/* Three coconuts dance on the waves where one waved. */
.hero__rider .hero__dancer--a {
  right: 78px;
  width: 58px;
  animation-delay: -0.2s;
}
.hero__rider .hero__dancer--b {
  right: 34px;
  width: 70px;
}
.hero__rider .hero__dancer--c {
  right: -6px;
  width: 54px;
  animation-delay: -0.33s;
}
/* The running line under the header. */
.ticker {
  display: block;
  overflow: hidden;
  padding-block: 7px;
  background: var(--uv-pink);
  color: #150f2e;
  font: 600 13px/1.4 var(--font-display);
  letter-spacing: 0.14em;
  text-decoration: none;
  text-transform: uppercase;
  white-space: nowrap;
}
.ticker__run {
  display: inline-flex;
  animation: run 26s linear infinite;
}
.ticker__run span {
  padding-inline: 22px;
}
.ticker__run span::after {
  content: "\2726";
  margin-left: 44px;
}
@keyframes run {
  to {
    translate: -50% 0;
  }
}
/* Lights rising through the night behind the page. */
.party-sky {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}
.party-sky i {
  position: absolute;
  left: calc(var(--i) * 7.2% + 1%);
  bottom: -24px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--uv-pink);
  opacity: 0;
  animation: lantern calc(11s + var(--i) * 0.9s) linear calc(var(--i) * -1.7s) infinite;
}
.party-sky i:nth-child(3n) {
  width: 6px;
  height: 6px;
  background: var(--uv-green);
}
.party-sky i:nth-child(3n + 1) {
  width: 14px;
  height: 14px;
  background: var(--uv-yellow);
}
.party-sky i:nth-child(4n) {
  background: var(--color-ocean);
}
@keyframes lantern {
  0% {
    opacity: 0;
    transform: translate(0, 0);
  }
  12% {
    opacity: 0.55;
  }
  50% {
    transform: translate(18px, -55vh);
  }
  88% {
    opacity: 0.35;
  }
  100% {
    opacity: 0;
    transform: translate(-10px, -112vh);
  }
}
@media (min-width: 960px) {
  html[data-party] .moon {
    width: 84px;
    height: 84px;
  }
  .hero__rider .hero__dancer--a {
    right: 112px;
    width: 80px;
  }
  .hero__rider .hero__dancer--b {
    right: 50px;
    width: 98px;
  }
  .hero__rider .hero__dancer--c {
    right: -8px;
    width: 76px;
  }
}

/* Mood-specific acting: props on the ground stay outside the coconut's movement. */
.mood--morning.coconut--greet { animation: none; }
.mood--morning .greet__figure { animation: morning-sway 3.6s ease-in-out infinite alternate; }
@keyframes morning-sway { from { rotate: -2deg; } to { rotate: 2deg; } }
.mood--storm .greet__leaf,
.mood--storm .fc__leaf { animation: leaf-blown-away var(--storm-cycle) linear infinite; }
@keyframes leaf-blown-away {
  0%, 30% { opacity: 1; translate: 0 0; rotate: -2deg; }
  33% { opacity: 1; translate: 8px -3px; rotate: 12deg; }
  36% { opacity: 1; translate: 40px -14px; rotate: 30deg; }
  44%, 100% { opacity: 0; translate: 260px -90px; rotate: 110deg; }
}

/* Rain first, then a gust; sheltering starts only once the leaf has gone. */
@property --shelter { syntax: "<number>"; inherits: true; initial-value: 1; }
.mood--storm.coconut { --storm-cycle: 8s; --shelter: 1; animation: storm-reaction var(--storm-cycle) linear infinite; }
.mood--storm .greet__figure { rotate: 0deg; }
.mood--storm .greet__torso { translate: 0 calc(14px * var(--shelter) * (1 - var(--pose)) + var(--pose) * 6px); }
.mood--storm .fc__torso { translate: 0 calc(14px * var(--shelter)); }
.forecaster.is-wai .mood--storm .fc__torso { translate: 0 0; }
.mood--storm .coconut__legs > path { animation: storm-legs var(--storm-cycle) linear infinite; }
@keyframes storm-reaction {
  0%, 48%, 100% { --shelter: 0; }
  62%, 90% { --shelter: 1; }
}
.fc__shelter-left > path { animation: storm-left-hand var(--storm-cycle) linear infinite; }
.fc__shelter-right > path { animation: storm-right-hand var(--storm-cycle) linear infinite; }
.fc__shelter-left > ellipse { cx: calc(43px + 63px * var(--shelter)); cy: calc(162px - 130px * var(--shelter)); }
.fc__shelter-right > ellipse { cx: calc(208px - 68px * var(--shelter)); cy: calc(-2px + 34px * var(--shelter)); }
@keyframes storm-left-hand {
  0%, 48%, 100% { d: path("M64 112 Q39 129 43 162"); }
  62%, 90% { d: path("M64 112 Q25 30 106 32"); }
}
@keyframes storm-right-hand {
  0%, 48%, 100% { d: path("M180 112 Q246 50 208 -2"); }
  62%, 90% { d: path("M180 112 Q219 30 140 32"); }
}
@keyframes storm-legs {
  0%, 48%, 100% { d: path("M100 170 C94 196 97 210 97 220 Q97 224 94 226 M144 170 C151 196 150 210 150 220 Q150 224 150 226"); }
  62%, 90% { d: path("M100 183 C76 194 74 205 89 211 Q101 215 94 226 M144 183 C168 194 170 205 155 211 Q143 215 150 226"); }
}
.coconut__gust { opacity: 0; animation: storm-gust var(--storm-cycle) linear infinite; }
@keyframes storm-gust {
  0%, 30%, 46%, 100% { opacity: 0; translate: -16px 0; }
  34% { opacity: .8; translate: 0 0; }
  42% { opacity: .6; translate: 30px 0; }
}
.mood--storm .greet__figure,
.mood--storm .fc__figure { animation: storm-brace var(--storm-cycle) linear infinite; }
@keyframes storm-brace {
  0%, 30%, 44%, 100% { translate: 0 0; }
  34%, 40% { translate: 4px 0; }
  37% { translate: -3px 0; }
}
.fc--sleepy { animation: none; }
.fc--sleepy .coconut__body { transform-box: view-box; transform-origin: 122px 125px; animation: breathe 3.4s ease-in-out infinite alternate; }

@media (prefers-reduced-motion: reduce) {
  @view-transition {
    navigation: none;
  }
  *,
  *::before,
  *::after,
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
    transition: none !important;
  }
  .party-sky {
    display: none;
  }
}

/* A trip quote inside the chosen sailing, with room for a thumb at 375px. */
.fare-calculator {
  min-width: 0;
  margin: 18px 0 0;
  padding: 12px;
  border: 1px solid var(--color-line);
  border-radius: 4px;
}
.fare-calculator legend { padding: 0 6px; font-weight: 600; }
.fare-calculator label { display: block; margin-bottom: 12px; font-size: 14px; }
.fare-calculator select, .fare-calculator input {
  display: block;
  width: 100%;
  min-height: 44px;
  margin-top: 4px;
  padding: 8px;
  border: 1px solid var(--color-line);
  border-radius: 4px;
  color: var(--color-ink);
  background: var(--color-paper);
  font: inherit;
  font-size: 16px;
}
.fare-calculator__total strong { display: block; font-size: 20px; font-variant-numeric: tabular-nums; }
.fare-calculator select {
  appearance: none;
  height: 44px;
  padding-right: 30px;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 16px center, right 11px center;
  background-size: 5px 5px;
  background-repeat: no-repeat;
}

.postmark [data-postmark-extra]:not([hidden]) { display: flex; align-items: center; min-height: 44px; color: inherit; font-weight: 600; }

/* Thai needs natural word breaking, room for marks above/below, and no Latin tracking. */
:lang(th) { letter-spacing: normal; word-break: normal; overflow-wrap: anywhere; }
html:lang(th) { --font-body: "Thonburi", "Leelawadee UI", Tahoma, sans-serif; }
html:lang(th) body { font-family: "Thonburi", "Leelawadee UI", Tahoma, sans-serif; }
html:lang(th) :is(h1, h2, h3, .kicker, .button, .hero__note, .greeter__wai) {
  font-family: "Thonburi", "Leelawadee UI", Tahoma, sans-serif;
  line-height: 1.5;
  letter-spacing: normal;
}
.top__nav { flex-wrap: wrap; }
