/* Wool Fish and Chip Shop.
 *
 * Roughly in page order: tokens, the draft banner, the hero and its buttons,
 * then the scrolling scene (sky, sea, beach, boat, net), then the beachfront
 * that docks under it, then the breakpoints.
 *
 * The scene's geometry — where the boat, waterline and menu sit — is set from
 * script.js, because it depends on measurements. What is here is everything
 * that does not: colour, type, artwork, and the sizes the script reads back.
 */
:root {
  --sky: #8ed4f2;
  --ink: #16324a;
  --muted: #3d5d70;
  --paper: #fffdf8;
  --accent: #1b7fb0;
  --display: "Fraunces", Georgia, serif;
  --body: "Outfit", system-ui, sans-serif;
  --max: 1040px;
  /* How much of the beachfront sits below the hero stage, on screen from
     the first frame. The stage and the dock both derive from it, so they
     cannot drift apart. */
  --peek: 12svh;
}
*, *::before, *::after { box-sizing: border-box; }
html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  /* Proximity, not mandatory, so the scene stays freely scrubbable. The one
     snap area on the page (.scroll-break) is here only for its snap-stop. */
  scroll-snap-type: y proximity;
}
body {
  margin: 0;
  font-family: var(--body);
  color: var(--ink);
  /* Sand, not sky: iPhone Safari (iOS 26 on) fills the strip under its
     floating toolbar with the page background once the page runs out, and
     the page ends on sand. */
  background: #e6d3a0;
  line-height: 1.55;
  overflow-x: clip;
}
a { color: var(--accent); }
.proposal-bar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 50;
  background: #16324a; color: #e8f6fb;
  font-size: 12px; line-height: 1.35; text-align: center;
  padding: calc(0.5rem + env(safe-area-inset-top, 0px)) 0.9rem 0.5rem;
}
.wrap { width: min(var(--max), calc(100% - 2.2rem)); margin-inline: auto; }

.sky {
  position: relative;
  z-index: 10;
  /* Clear the fixed proposal bar by its measured height (script.js sets
     --bar), so the kicker is never jammed under it however the bar wraps. */
  padding-top: calc(var(--bar, 2.6rem) + 0.9rem);
  background: transparent;
  pointer-events: none;
}
.sky a, .sky button { pointer-events: auto; }
/* No bar to clear, so the notch is the sky's own problem again. */
.no-bar .sky { padding-top: calc(0.9rem + env(safe-area-inset-top, 0px)); }
.bar-short { display: none; }


.hero {
  padding: 1.15rem 0 1rem;
  max-width: 54rem;
  margin-inline: auto;
  text-align: center;
}
.kicker {
  text-transform: uppercase; letter-spacing: 0.16em; font-size: 0.72rem;
  color: var(--accent); font-weight: 600; margin: 0 0 0.6rem;
}
h1, h2 { font-family: var(--display); font-weight: 650; letter-spacing: -0.02em; }
h1 { font-size: clamp(2.2rem, 5.4vw, 4.7rem); line-height: 1.06; margin: 0 0 0.7rem; text-wrap: balance; }
h2 { font-size: 1.85rem; margin: 0 0 1rem; }
/* Live opening status. Sits where the strapline used to, in the same type. */
.status { display: block; }
.status-dot {
  display: inline-block;
  width: 0.55em; height: 0.55em;
  margin-right: 0.45em;
  vertical-align: 0.06em;
  border-radius: 50%;
  background: currentColor;
}
.status[data-state="open"] { color: #1a8a4a; }
.status[data-state="closing"] { color: #b8720f; }
.lede {
  color: var(--muted); font-size: 1.08rem;
  max-width: 40rem; margin-inline: auto;
}
.actions {
  display: flex; gap: 0.7rem; flex-wrap: wrap; margin-top: 1.2rem;
  position: relative; z-index: 11; justify-content: center;
}
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--accent); color: #fff; text-decoration: none;
  padding: 0.8rem 1.15rem; border-radius: 999px; font-weight: 600; border: 0;
  min-height: 48px;
}
.btn-ghost { background: #fff; color: var(--ink); border: 1px solid #b7d7e6; }

/* The browser default ring vanishes against the sea and the sand, so give
   every link and button a solid one. Outlines follow each element's own
   border-radius, so the pills stay pills. */
a:focus-visible, button:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
}

/* Two 1px strips pinned to the screen's top and bottom edges. iPhone Safari
   (iOS 26 on) paints the bands behind the status bar and its floating toolbar
   in the colour of whatever fixed or pinned element touches that edge. Left
   to itself it took the sand of .ocean for both, so the sky got a sand band
   over it. These give it one solid colour per edge instead; script.js turns
   the top one to sand once the sky has scrolled away. Invisible otherwise. */
.edge {
  position: fixed;
  left: 0; right: 0;
  height: 1px;
  z-index: 60;
  pointer-events: none;
}
.edge-top { top: 0; background: #d7f1fb; }
.edge-top.is-sand { background: #e6d3a0; }
.edge-bottom { bottom: 0; background: #e6d3a0; }

/* The tall box whose scroll drives the scene. Its height is the runway: more
   height, slower animation. The sand colour shows through wherever the pinned
   block does not cover it. */
.ocean { height: 320vh; position: relative; background: #e6d3a0; }
/* A scroll cannot pass over this — flick and momentum included. script.js
   parks it where the menu finishes opening, so one hard swipe stops there. */
.scroll-break {
  position: absolute;
  left: 0;
  width: 1px;
  height: 1px;
  pointer-events: none;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-snap-type: none; }
}
/* The snap stop is there for a phone, where one hard swipe used to blow
   through the whole scene. With a mouse or trackpad it is the wrong tool: the
   browser drags the page onto the snap point whenever a scroll comes to rest
   near it, which felt like the page grabbing the wheel. The short pinned
   pause after the menu opens is enough of a stop there. */
@media (hover: hover) and (pointer: fine) {
  html { scroll-snap-type: none; }
}
/* The scene and the beachfront, pinned as one block for the length of the
   ocean, so the scene plays in place with --peek of the beachfront showing
   underneath. One block, not two sticky siblings: two let go at different
   moments, and the beachfront used to slide up over the open menu while the
   scene was still pinned. Now the scene holds (the last stretch of the
   runway, after the menu opens), then the whole screen scrolls on together. */
.ocean-pin {
  position: sticky;
  top: 0;
}
/* Sized to leave --peek of the beachfront showing underneath. Clips its own
   contents: the net and the sand slide out of frame at the edges. */
.ocean-stage {
  position: relative;
  isolation: isolate;
  height: calc(100svh - var(--peek));
  overflow: hidden;
  background:
    radial-gradient(900px 240px at 78% 8%, #ffffffaa, transparent 55%),
    linear-gradient(180deg, #d7f1fb 0%, #b8e6f7 55%, var(--sky) 100%);
}
/* The water. script.js sets `top` each frame — that edge is the waterline the
   boat floats on. The .wave-layer strips inside scroll sideways on their own. */
.sea {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  top: 28%;
  z-index: 1;
  pointer-events: none;
  background: #0a4d8e;
}
/* Sand at the foot of the stage, drawn over the sea. script.js nudges it down
   as the net lands. Height is a percentage of the stage, so the push and the
   shell band below scale with it. */
.beach {
  position: absolute;
  will-change: transform;
  left: 0; right: 0; bottom: 0;
  height: 30%;
  z-index: 2;
  pointer-events: none;
  background-color: #e6d3a0;
}
/* The stage clips at its own bottom edge and the beach slides down when the
   net lands, so the band stops short of both — otherwise shells get sliced
   in half at the join. */
.beach-shells {
  position: absolute;
  inset: 6% 0 14% 0;
  pointer-events: none;
}
.shell {
  position: absolute;
  height: auto;
  display: block;
  overflow: visible;
  filter: drop-shadow(0 1px 1px rgba(110, 80, 30, 0.22));
}
.s-scallop.a { left: 6%; top: 46%; width: clamp(30px, 5.6vw, 50px); transform: rotate(-22deg); }
.s-star.a { left: 17%; top: 68%; width: clamp(28px, 5.2vw, 46px); transform: rotate(18deg); }
.s-whelk.a { left: 31%; top: 12%; width: clamp(22px, 4.2vw, 36px); transform: translateY(-20px) rotate(28deg); }
.s-star.b { left: 54%; top: 34%; width: clamp(24px, 4.4vw, 38px); transform: rotate(-34deg); }
.s-cowrie.a { left: 76%; top: 62%; width: clamp(20px, 3.8vw, 34px); transform: translateY(-20px) rotate(-8deg); }
.s-star.c { left: 87%; top: 22%; width: clamp(22px, 4vw, 36px); transform: rotate(52deg); }
.s-cockle.b { left: 48%; top: 56%; width: clamp(18px, 3.4vw, 28px); transform: translateY(-20px) rotate(40deg); opacity: 0.9; }
.beach::before {
  content: "";
  position: absolute;
  left: -25%;
  width: 150%;
  top: -40px;
  height: 52px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 720 52'%3E%3Cpath d='M0 28 C90 28 110 8 180 20 C250 32 270 6 360 22 C450 38 470 8 540 24 C610 38 640 12 720 28 V52 H0Z' fill='%23e6d3a0'/%3E%3Cpath d='M0 28 C90 28 110 8 180 20 C250 32 270 6 360 22 C450 38 470 8 540 24 C610 38 640 12 720 28' fill='none' stroke='%23ffffff' stroke-width='7' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: repeat-x;
  background-size: 720px 52px;
  animation: flow720 16s linear infinite;
}

.wave-layer {
  position: absolute;
  left: -20%;
  width: 140%;
  background-repeat: repeat-x;
  background-position: 0 0;
  pointer-events: none;
}
.w1 {
  top: 8px;
  height: 78px;
  background-size: 640px 78px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 78'%3E%3Cpath d='M0 40 C80 40 90 22 160 34 C230 46 240 18 320 36 C400 54 410 22 480 38 C550 54 560 26 640 40 V78 H0Z' fill='%236ec8e8'/%3E%3Cpath d='M0 40 C80 40 90 22 160 34 C230 46 240 18 320 36 C400 54 410 22 480 38 C550 54 560 26 640 40' fill='none' stroke='%23ffffff' stroke-width='5' stroke-linecap='round'/%3E%3C/svg%3E");
  animation: flow640 24s linear infinite;
}
.w2 {
  top: 32px;
  height: 96px;
  background-size: 720px 96px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 720 96'%3E%3Cpath d='M0 50 C90 50 105 20 180 38 C255 56 270 16 360 42 C450 68 465 20 540 44 C615 68 640 28 720 50 V96 H0Z' fill='%233eb7ea'/%3E%3Cpath d='M0 50 C90 50 105 20 180 38 C255 56 270 16 360 42 C450 68 465 20 540 44 C615 68 640 28 720 50' fill='none' stroke='%23ffffff' stroke-width='6' stroke-linecap='round'/%3E%3C/svg%3E");
  animation: flow720 19s linear infinite reverse;
}
.w3 {
  top: 62px;
  height: 118px;
  background-size: 800px 118px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 118'%3E%3Cpath d='M0 60 C100 60 118 20 200 44 C282 68 300 16 400 48 C500 80 518 22 600 52 C682 82 710 30 800 60 V118 H0Z' fill='%231b93d6'/%3E%3Cpath d='M0 60 C100 60 118 20 200 44 C282 68 300 16 400 48 C500 80 518 22 600 52 C682 82 710 30 800 60' fill='none' stroke='%23ffffff' stroke-width='8' stroke-linecap='round'/%3E%3C/svg%3E");
  animation: flow800 16s linear infinite;
}
/* w4 and w-mid-a are the same wave, set at different depths and speeds. */
.w4, .w-mid-a { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 880 140'%3E%3Cpath d='M0 72 C110 72 130 22 220 50 C310 78 330 16 440 56 C550 96 570 24 660 60 C750 96 780 32 880 72 V140 H0Z' fill='%230e6cb8'/%3E%3Cpath d='M0 72 C110 72 130 22 220 50 C310 78 330 16 440 56 C550 96 570 24 660 60 C750 96 780 32 880 72' fill='none' stroke='%23ffffff' stroke-width='9' stroke-linecap='round'/%3E%3C/svg%3E"); }
.w4 {
  top: 100px;
  height: 140px;
  background-size: 880px 140px;
  animation: flow880 13s linear infinite reverse;
}
.w-mid-a {
  top: 210px;
  height: 140px;
  background-size: 880px 140px;
  animation: flow880 14s linear infinite;
}
/* w5 and w-mid-b are the same wave, set at different depths and speeds. */
.w5, .w-mid-b { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 960 160'%3E%3Cpath d='M0 84 C120 84 142 24 240 58 C338 92 360 18 480 64 C600 110 624 28 720 70 C816 112 850 36 960 84 V160 H0Z' fill='%230c5aa3'/%3E%3Cpath d='M0 84 C120 84 142 24 240 58 C338 92 360 18 480 64 C600 110 624 28 720 70 C816 112 850 36 960 84' fill='none' stroke='%23ffffff' stroke-width='11' stroke-linecap='round'/%3E%3C/svg%3E"); }
.w5 {
  top: 150px;
  height: 160px;
  background-size: 960px 160px;
  animation: flow960 11s linear infinite;
}
.w-mid-b {
  top: 330px;
  height: 160px;
  background-size: 960px 160px;
  animation: flow960 12s linear infinite reverse;
}
/* w-deep and w6 are the same wave, set at different depths and speeds. */
.w-deep, .w6 { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1040 110'%3E%3Cpath d='M0 52 C130 52 155 14 260 38 C365 62 390 10 520 42 C650 74 680 16 800 46 C900 70 950 22 1040 52 V110 H0Z' fill='%230a4d8e'/%3E%3Cpath d='M0 52 C130 52 155 14 260 38 C365 62 390 10 520 42 C650 74 680 16 800 46 C900 70 950 22 1040 52' fill='none' stroke='%23ffffff' stroke-width='10' stroke-linecap='round'/%3E%3C/svg%3E"); }
.w-deep {
  top: 460px;
  height: 160px;
  background-size: 1040px 160px;
  animation: flow1040 10s linear infinite;
}
.w6 {
  top: auto;
  bottom: 0;
  height: 110px;
  background-size: 1040px 110px;
  animation: flow1040 9s linear infinite reverse;
}
.w-front {
  z-index: 5;
  top: auto; bottom: -6px;
  height: 64px;
  background-size: 700px 64px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 700 64'%3E%3Cpath d='M0 30 C88 30 104 10 175 22 C246 34 262 8 350 24 C438 40 454 10 525 26 C596 42 620 12 700 30 V64 H0Z' fill='%23083d73'/%3E%3Cpath d='M0 30 C88 30 104 10 175 22 C246 34 262 8 350 24 C438 40 454 10 525 26 C596 42 620 12 700 30' fill='none' stroke='%23ffffff' stroke-width='7' stroke-linecap='round'/%3E%3C/svg%3E");
  animation: flow700 8s linear infinite;
}
@keyframes flow640 { to { background-position: 640px 0; } }
@keyframes flow700 { to { background-position: 700px 0; } }
@keyframes flow720 { to { background-position: 720px 0; } }
@keyframes flow800 { to { background-position: 800px 0; } }
@keyframes flow880 { to { background-position: 880px 0; } }
@keyframes flow960 { to { background-position: 960px 0; } }
@keyframes flow1040 { to { background-position: 1040px 0; } }

/* The boat. Width is set by script.js so it scales with the viewport; the
   parts inside are positioned in percentages of it, so they follow. */
.vessel {
  position: absolute;
  top: 40%;
  left: 8px;
  width: clamp(108px, 26vw, 280px);
  z-index: 5;
  will-change: top, left, width;
}
.boat-bob { animation: boat-bob 2.8s ease-in-out infinite; transform-origin: 42% 86%; }
@keyframes boat-bob {
  0%, 100% { transform: translateY(0) rotate(-1.2deg); }
  50% { transform: translateY(-6px) rotate(1.2deg); }
}
.boat {
  position: relative;
  width: 100%;
  padding-bottom: 31%;
  pointer-events: none;
}
.boat > span {
  position: absolute;
  display: block;
  box-sizing: border-box;
}
.boat-body {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.flagpole {
  left: 12.2%;
  top: 4%;
  width: 3px;
  height: 22%;
  background: #16324a;
  z-index: 6;
}
.flag {
  left: 13%;
  top: 3%;
  width: 8%;
  height: 12%;
  z-index: 7;
  transform-origin: left center;
  animation: flag-fly 2.2s ease-in-out infinite;
  filter: drop-shadow(0 1px 0 #16324a);
}
.flag svg { display: block; width: 100%; height: 100%; }
@keyframes flag-fly {
  0%, 100% { transform: rotate(-6deg); }
  50% { transform: rotate(5deg); }
}
.hook {
  left: 76%;
  top: 48%;
  /* Drawn at a 280px-wide boat; --hook-scale keeps it in proportion as the
     boat resizes with the viewport. */
  transform: scale(var(--hook-scale, 1));
  transform-origin: 0 0;
  width: 16px;
  height: 22px;
  border: 4px solid #e6b325;
  border-top: 0;
  border-radius: 0 0 14px 10px;
  z-index: 6;
}
.hook::before {
  content: "";
  position: absolute;
  top: -7px;
  left: 1px;
  width: 12px;
  height: 12px;
  background: #e6b325;
  border: 2px solid #16324a;
  border-radius: 50%;
}
.hook::after {
  content: "";
  position: absolute;
  right: -1px;
  bottom: 3px;
  width: 8px;
  height: 12px;
  border: 3px solid #16324a;
  border-top: 0;
  border-left: 0;
  border-radius: 0 0 8px 0;
}
.ripple {
  left: 74%;
  top: 78%;
  width: 14%;
  height: 10%;
  border: 2px solid #c5eaf6;
  border-radius: 50%;
  box-shadow: 0 0 0 4px #c5eaf644;
  opacity: 0.85;
  z-index: 1;
}

/* The net, and the menu it becomes. Three states, all driven from script.js:
   hanging from the hook, dropping open, then .is-full — a plain white card.
   .is-tight is the fallback when the menu will not otherwise fit below the
   boat; see the sizes at the bottom of this file. */
.net {
  position: absolute;
  left: 0;
  top: 0;
  width: min(320px, 78vw);
  z-index: 12;
  transform: scaleY(0.04);
  transform-origin: 50% 0;
  opacity: 0;
  pointer-events: none;
  will-change: transform, opacity, left, top, width, height;
}
.net.is-open { pointer-events: auto; }
.net.is-full .net-line { display: none; }
.net.is-full .net-bag {
  height: 100%;
  border-radius: 18px;
  display: block;
  padding: 1.15rem 1.4rem 1.3rem;
  overflow: auto;
}
.net.is-full .net-label { font-size: 1.05rem; }
.net-line {
  width: 3px;
  height: 28px;
  margin-left: 16px;
  background: linear-gradient(#6b4a2a, #c4a574);
  border-radius: 2px;
}
.net-bag {
  margin-top: -2px;
  padding: 0.9rem 0.85rem 1.1rem;
  color: var(--ink);
  background: #ffffff;
  border: 1px solid #e2d5b8;
  border-radius: 0 0 40% 40% / 0 0 18% 18%;
  box-shadow: 0 10px 28px #06305626;
}
.net-label {
  margin: 0 0 0.6rem;
  text-align: center;
  color: var(--accent);
  font-family: var(--display);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 0.78rem;
}

.menu-list {
  list-style: none;
  max-width: 780px;
  margin: 0.5rem auto 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 2.2rem;
}
.menu-list li {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.32rem 0;
  border-bottom: 1px dotted #d8c39a;
}
.menu-list .item { flex: 1 1 auto; }
.menu-list .item em { font-style: normal; color: var(--muted); font-size: 0.85em; }
.menu-list .price { font-weight: 600; font-variant-numeric: tabular-nums; }
.menu-note {
  max-width: 780px;
  margin: 0.75rem auto 0;
  font-size: 0.8rem;
  color: var(--muted);
}


/* The sand carries on out of the hero: same colour, same shells, real content. */
.beachfront {
  position: relative;
  background-color: #e6d3a0;
}
/* Sits straight under the stage inside .ocean-pin, so the top --peek of it is
   on screen from the first frame rather than a blank stretch of sand, and it
   scrolls away with the scene rather than over it. Same sand colour as the
   stage, so the join does not read as an edge. */
#visit.beachfront {
  z-index: 3;
  padding: 0.5rem 0 2.6rem;
}
footer.beachfront { padding: 1rem 0 3rem; }
/* Shells scattered over the top of the section. They are positioned, and
   the panels are not, so without these two z-indexes the shells would paint
   over the cards — visible on a phone, where the column reaches them. */
.beach-strip {
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 8rem;
  z-index: 0;
  pointer-events: none;
}
.beachfront > .wrap { position: relative; z-index: 1; }
.beach-strip .shell { position: absolute; }
.t-scallop { left: 2%; top: 3%; width: clamp(24px, 4vw, 38px); transform: rotate(-16deg); }
.t-star { left: 13%; top: 70%; width: clamp(22px, 3.6vw, 34px); transform: rotate(24deg); }
.t-cockle { left: 85%; top: 30%; width: clamp(22px, 3.6vw, 34px); transform: rotate(-9deg); }
.t-cowrie { left: 93%; top: 86%; width: clamp(18px, 3vw, 28px); transform: rotate(12deg); }
.panel {
  background: var(--paper);
  border: 1px solid #e0cda2;
  border-radius: 16px;
  padding: 1.25rem 1.35rem;
  box-shadow: 0 6px 18px #a8834422;
}
.panel-map { padding: 0.7rem 0.7rem 0.55rem; }
.visit { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: 1.5rem; align-items: start; }
.addr { font-size: 1.1rem; margin: 0 0 0.6rem; }
.phone { font-weight: 700; font-size: 1.15rem; text-decoration: none; color: var(--ink); }
.hours { margin: 1rem 0; }
.hours-row {
  display: flex; justify-content: space-between; gap: 1rem;
  border-bottom: 1px solid #d3e6ee; padding: 0.45rem 0;
}
#map {
  height: 320px; border-radius: 16px; overflow: hidden;
  border: 1px solid #c5e0ec; background: #d9eef6;
}
.map-credit, .fine { font-size: 0.8rem; color: var(--muted); }
.map-credit { margin: 0.4rem 0 0; }
/* Getting there is what most people open this panel for, so it reads as an
   action rather than fine print. */
.directions { margin: 0.9rem 0 0; }
.directions a {
  display: inline-flex; align-items: center; gap: 0.4rem;
  min-height: 44px;
  font-weight: 600; color: var(--accent); text-decoration: none;
}
.directions a::after { content: "\2197"; font-weight: 400; }
.directions a:hover { text-decoration: underline; }
footer { padding: 2rem 0 3rem; color: var(--muted); font-size: 0.9rem; }

@media (prefers-reduced-motion: reduce) {
  .wave-layer, .boat-bob, .flag, .beach::before { animation: none; }
}

@media (max-width: 800px) {
  .wrap { width: min(var(--max), calc(100% - 1.4rem)); }
  /* The long notice wraps to two lines on a phone and steals the hero's air. */
  .bar-long { display: none; }
  .bar-short { display: inline; }
  .visit { grid-template-columns: 1fr; }
  h1 { font-size: clamp(1.7rem, 8vw, 2.2rem); }
  h2 { font-size: 1.45rem; }
  .actions { flex-direction: column; margin-top: 0.7rem; }
  .btn { width: 100%; }
  .vessel { width: clamp(83px, 21.9vw, 179px); }
  /* Show more of the beachfront here: this is where the empty sand was worst. */
  :root { --peek: 15svh; }
  .hero { padding-bottom: 0.4rem; }
  .lede { font-size: 1rem; }
  .net { width: min(260px, 86vw); }
  /* Keep the open net's contents inside the stage: an inner scrollbar here
     would swallow the page scroll that drives the whole scene. */
  .net.is-full .net-bag { padding: 0.75rem 0.9rem 0.85rem; }
  .net.is-full .net-label { font-size: 0.95rem; margin-bottom: 0.2rem; }
  .menu-list { grid-template-columns: 1fr; }
  .menu-list li { padding: 0.14rem 0; font-size: 0.86rem; }
  .menu-note { margin-top: 0.4rem; font-size: 0.72rem; line-height: 1.3; }
  #map { height: 240px; }
  .ocean { height: 360vh; }
}

/* Desktop with room to spare: the sand band between the sea and "Find us"
   read as a big empty stretch, so the beachfront comes further up (a larger
   --peek, which shortens the stage) and the beach is a slimmer strip. Short
   windows keep the defaults — they need every pixel of stage for the menu. */
@media (min-width: 801px) and (min-height: 801px) {
  :root { --peek: 20svh; }
  .beach { height: 22%; }
}

/* A short desktop window gives the beach so little height that the largest
   shells would reach the stage's clip edge once the net pushes the sand down.
   Phones are excluded: they size their shells smaller anyway, and the band is
   tuned there to sit just above the docked beachfront. */
@media (max-height: 800px) and (min-width: 801px) {
  .beach-shells { inset: 6% 0 26% 0; }
  .beach-shells .shell { width: clamp(20px, 3.4vw, 34px); }
}

/* Any short screen — a laptop with a small window as much as a phone — has to
   give hero height back, or the open net cannot show the whole menu without an
   inner scrollbar. */
@media (max-height: 800px) {
  .hero { padding: 0.95rem 0 0.4rem; }
  .kicker { font-size: 0.66rem; margin-bottom: 0.35rem; }
  h1 { font-size: clamp(1.5rem, 4.6vw, 2.6rem); margin-bottom: 0.4rem; }
  .lede { font-size: 0.95rem; line-height: 1.4; }
  .actions { margin-top: 0.7rem; }
}

@media (max-width: 800px) and (max-height: 800px) {
  h1 { font-size: clamp(1.5rem, 7.4vw, 2rem); }
  .lede { font-size: 0.92rem; }
  .actions { flex-direction: row; flex-wrap: nowrap; gap: 0.5rem; }
  .btn { width: auto; flex: 1 1 0; padding: 0.6rem 0.5rem; font-size: 0.9rem; min-height: 44px; }
}

/* iPhone SE and friends (375x667): tightest case — the hero and the menu both
   give a little so the open menu still clears the boat. */
@media (max-width: 800px) and (max-height: 700px) {
  .kicker { font-size: 0.6rem; margin-bottom: 0.25rem; }
  h1 { font-size: clamp(1.35rem, 6.6vw, 1.75rem); margin-bottom: 0.3rem; }
  .lede { font-size: 0.85rem; line-height: 1.35; }
  .actions { margin-top: 0.55rem; }
  .btn { padding: 0.5rem 0.4rem; font-size: 0.85rem; min-height: 42px; }
  .net.is-full .net-bag { padding: 0.6rem 0.8rem 0.7rem; }
  .net.is-full .net-label { font-size: 0.85rem; margin-bottom: 0.1rem; }
  .menu-list li { padding: 0.08rem 0; font-size: 0.8rem; }
  .menu-note { font-size: 0.68rem; margin-top: 0.3rem; }
}

/* Applied by script.js when the menu would otherwise not fit below the boat. */
.net.is-tight .net-bag { padding: 0.55rem 0.75rem 0.65rem; }
.net.is-tight .net-label { font-size: 0.82rem; margin-bottom: 0.1rem; }
.net.is-tight .menu-list li { padding: 0.04rem 0; font-size: 0.78rem; }
.net.is-tight .menu-note { font-size: 0.66rem; margin-top: 0.3rem; }
