/* ---------- the nav mark is the horizontal lockup ---------- */
.nav-mark{width:72px}
/* the mark and its slot step down together. When they disagreed the mark was
   72px inside a 60px slot and the bar had a pixel of clearance left. */
@media(max-width:900px){ .nav-mark{width:60px} }
@media(max-width:560px){ .nav-mark{width:54px} }

/* the bar's mark waits until the big one has left the sky */
.nav-mark{transition:opacity .34s var(--ease),transform .34s var(--ease)}
/* one slot, two occupants: the mark and the line stack in the same place, so
   the line begins exactly where the mark begins and can never reach the edge */
.nav-slot{position:relative;flex:0 0 auto;width:72px;height:72px;
  display:flex;align-items:center}
.nav-slot .nav-mark{position:absolute;left:0;top:50%;transform:translateY(-50%)}
.nav-slot .nav-say{position:absolute;left:0;top:50%;transform:translateY(-50%)}
.nav:not(.nav-bare) .nav-slot .nav-say{transform:translateY(calc(-50% + 6px))}
@media(max-width:900px){ .nav-slot{width:60px;height:60px} }
@media(max-width:560px){ .nav-slot{width:54px;height:54px} }
/* it waits eight pixels high and settles down into the slot. The centring has
   to be restated here or the transform cancels it and the badge lands low. */
.nav.nav-bare .nav-mark{opacity:0;transform:translateY(calc(-50% - 8px));
  pointer-events:none}

/* ---------- the jeep ---------- */
/* It crosses once, then stays away for fourteen seconds. A vehicle that loops
   without a gap becomes a metronome you start timing; one that appears every so
   often stays a small surprise. Forty percent of the cycle is the crossing.

   The strip carries the shop's own ground and sits flush against it, so this
   reads as the top of the beach rather than as a band with a jeep in it. */
.drive{
  /* The board on the roof is part of the drawing but not part of the vehicle:
     the jeep itself is 0.91 of the artwork's width, so at the old size the
     vehicle came out a tenth smaller than before. This puts the vehicle back
     where it was and lets the board have its own room. */
  --jeep-w:clamp(242px,25.3vw,406px);
  /* No z-index here on purpose. The strip must NOT form a stacking context, or
     its children cannot be sorted against the ticker, which sits between them:
     the dunes go behind the ticker line and the jeep goes in front of it. */
  position:relative;overflow:hidden;
  --band:60px;                       /* the sand. Height and margins set on load */
  height:120px;

  /* The box is tall enough to hold the jeep and is pulled up over the ticker,
     so the jeep can cross in front of it. Only the lower band is sand: above
     the ground line the strip is transparent and the ticker reads through it.

     overflow:hidden rather than a clip-path, because a clip-path trims what is
     painted but not what the page can scroll to, and the ground is several
     screens wide. That put five thousand pixels of empty space to the right of
     every page it appeared on. */
  background:linear-gradient(to bottom,
    transparent 0 calc(100% - var(--band)),
    var(--rope) calc(100% - var(--band)) 100%);
}
/* the fills are set per shape so overlaps deepen, the way the clouds do */
/* the sand sits under the ticker line (z-index 6), the jeep over it */
.terrain{position:absolute;top:0;height:100%;z-index:1;will-change:transform}
/* the ticker gives up its own ground on the page that has dunes, so the sand
   can run up behind the words instead of stopping at a rectangle */
.marquee-sand{background:transparent}
.dunes{position:absolute;left:0;top:0}
/* sun along the near crest, then the shop's own ground below it, so the bottom
   of the strip does not exist either */
/* THE DUNE FIELD: one colour, one alpha, four bands.

   Four hand-picked opaque tans were four decisions that had to keep agreeing
   with each other, and they read as one shape in four flat steps. This is the
   clouds' arithmetic instead: a single sand laid down repeatedly, so the tone
   at any point is simply how many dunes are stacked there. The ramp comes out
   of the geometry rather than out of a palette, and where two cross you see one
   through the other rather than a butt joint.

   The two that climb into the ticker's copy are the crest's own colour thinned.
   That is not a compromise: distance pales things, so the far field being a weak
   version of the sunlit near crest is what atmosphere does, and it settles the
   contrast argument by removing it. A translucent sand dark enough to see always
   darkens the ground under the amber, and no alpha tested cleared AA at two
   layers; pale sand goes the other way, taking rope's 5.93:1 up to 6.6 at one
   layer and 7.5 at four.

   The two held below the copy are warm and deeper, because pale sand alone gave
   a field with no drawing in it: correct, safe and barely there. Weight belongs
   at the bottom of a landscape anyway. Nothing above the glyph line is dark and
   nothing below it has to be pale, so each half is free. */
.dune-b1,.dune-b2{fill:#FBF4E6;fill-opacity:.52}
.dune-b3,.dune-b4{fill:#B9954F;fill-opacity:.42}
.dune-lit{fill:#FBF4E6}
.dune-near{fill:var(--straw)}

/* Three nested jobs, so none of them fight over the transform: the outer one
   holds the jeep's place across the frame, the middle one rides the ground and
   turns to its slope, the inner one is the suspension. */
/* The shadow is its own layer, on the sand and under everything else the strip
   draws. It is not inside the jeep: a shadow that inherits the body's rotation
   is a shadow ruled across the ground rather than lying on it. */
/* Warm, not black. A shadow on sand is sand with the light taken out of it, so
   this is the sand's own hue (39 degrees) held at a fraction of its lightness
   and a little more saturated, which is what sand in shade actually does. Black
   at the same alpha read as a hole cut in the beach rather than a shadow lying
   on it. The gradient stops take currentColor, so the whole shadow is this one
   line. */
.jshade{position:absolute;left:0;top:0;width:100%;height:100%;z-index:2;
  pointer-events:none;overflow:visible;color:#4F3D22}
.jeep{position:absolute;left:0;top:0;z-index:8;width:var(--jeep-w);will-change:transform}
.jeep-ride{
  position:relative;transform-origin:50% 100%;
  will-change:transform;
}
.jeep-body{will-change:transform}
.jeep-art{display:block;width:100%;height:auto;
  /* An svg clips to its own viewport by default, and the board's fin sits at
     the very edge of the drawing's box. Ten units of padding is under two
     pixels at these sizes, which is thin enough for rounding to eat. The strip
     already clips, with sixty pixels of clearance measured over a full lap, so
     this clip does nothing but risk shaving the fin. */
  overflow:visible}

/* The suspension, split the way a suspension is split, and anchored the way
   one actually looks from outside: the tyres stay on the sand and the body
   floats above them. The first attempt had it the other way round and the jeep
   spent half its time airborne.

   So the wheels only flick, a pixel or so, the way a tyre rides a ripple. The
   body is the sprung mass, moving three times as far, slower, and lagging
   behind. What reads as suspension is the gap between the two, which is why
   they cannot share one animation.

   Distances are in the drawing's own units, so they scale with the jeep. */
/* The pivot is the middle of the wheelbase, and it now travels in the drawing
   as an inline transform-origin that make_jeep.py measures. It used to live
   here as a pair of numbers taken off a previous jeep, which is fine right up
   until someone sends a new one. */
.jb{ animation:jeep-heave 1.62s cubic-bezier(.36,.07,.28,1) infinite }
.jwheel{ animation:jeep-jounce .46s cubic-bezier(.30,.02,.38,1) infinite }
/* the front wheel meets a bump first and the rear follows it. At this speed the
   wheelbase is 0.73s of travel, which lands the rear a little over half a cycle
   behind the front. */
.jwheel.rear{ animation-delay:-.19s }

/* mostly on the ground, with brief flicks. Never enough to look airborne. */
@keyframes jeep-jounce{
  0%,100% { transform:translateY(0) }
  14%     { transform:translateY(-9px) }
  28%     { transform:translateY(-1px) }
  50%     { transform:translateY(-6px) }
  70%     { transform:translateY(0) }
  86%     { transform:translateY(-4px) }
}
/* the body: further, slower, and behind them */
@keyframes jeep-heave{
  0%,100% { transform:translateY(0) rotate(0deg) }
  17%     { transform:translateY(-9px) rotate(-.22deg) }
  33%     { transform:translateY(-26px) rotate(-.52deg) }
  52%     { transform:translateY(-4px) rotate(.20deg) }
  68%     { transform:translateY(-17px) rotate(-.30deg) }
  85%     { transform:translateY(2px) rotate(.14deg) }
}

/* The ground shadows come with the drawing now. They are Bruce's own: two pools
   under the wheels and a long wash between them, drawn in Illustrator and
   rasterised as masked bitmaps, so they are copied across untouched rather than
   re-derived. They sit outside .jb, so the body can heave without dragging its
   own shadow up off the sand with it. The CSS shadow that stood in for them is
   gone: two shadows would have been two shadows. */


/* the suspension is the part still driven by CSS, so it is stopped here */
.drive.is-still .jb,
.drive.is-still .jwheel{ animation-play-state:paused }

/* parked, not hidden. The drawing is worth seeing either way. */
@media(prefers-reduced-motion:reduce){
  .jb,.jwheel{animation:none}
}


/* ---------- join the club ---------- */
/* Cedar, not navy. Inside the footer the club shared its ground and the two
   read as one block, so the invitation looked like small print. Cedar is the
   only colour in the palette that is neither blue nor sand, which makes it the
   one step that cannot be mistaken for either the page above or the footer
   below. Linen on cedar measures 8.6:1. */
.club{background:var(--cedar);color:var(--linen);
  padding-block:clamp(46px,6.5vw,88px)}
.club-in{
  display:grid;gap:clamp(24px,3vw,56px);
  grid-template-columns:minmax(0,1fr);
}
@media(min-width:900px){
  .club-in{grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);align-items:start}
  /* centred against the text block rather than pinned to its top, which put the
     field level with the eyebrow and left it floating above the heading */
  .club-form{align-self:center}
}
.club .eyebrow{color:var(--beacon);opacity:.8}
.club h2{
  font-size:clamp(1.8rem,3.6vw,2.8rem);line-height:1.02;letter-spacing:-.025em;
  font-weight:800;margin:.34em 0 0;color:var(--linen);
}
.club p.club-lead{font-family:var(--sans);font-size:1.05rem;line-height:1.6;
  opacity:.8;margin:.7em 0 0;max-width:40ch}

.club-row{display:flex;gap:10px;flex-wrap:wrap}
.club-lab{
  position:absolute;width:1px;height:1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;
}
/* the pill, like every other control on the site */
.club-form input{
  flex:1 1 240px;min-width:0;
  font-family:var(--sans);font-size:1rem;color:var(--linen);
  background:rgba(253,250,243,.08);
  border:1px solid rgba(253,250,243,.30);border-radius:999px;
  padding:17px 24px;
}
.club-form input::placeholder{color:var(--linen);opacity:.42}
.club-form input:focus-visible{outline:3px solid var(--beacon);outline-offset:2px}
.club-form button{
  flex:0 0 auto;cursor:pointer;border:0;border-radius:999px;
  background:var(--beacon);color:var(--harbour);
  font-family:var(--sans);font-size:.78rem;font-weight:800;
  letter-spacing:.1em;text-transform:uppercase;
  padding:17px clamp(28px,3.4vw,40px);
  transition:filter .2s var(--ease),transform .2s var(--ease);
}
.club-form button:hover{filter:brightness(1.06);transform:translateY(-2px)}
.club-form button:active{transform:translateY(0)}
.club-form button:disabled{opacity:.5;cursor:default;transform:none;filter:none}

.club p.club-terms{font-family:var(--sans);font-size:.82rem;line-height:1.7;
  opacity:.62;margin:16px 0 0;max-width:52ch}
.club p.club-said{font-family:var(--sans);font-size:.9rem;line-height:1.6;
  margin:12px 0 0;color:var(--beacon)}
.club p.club-said.is-bad{color:#FFB59C}
.club p.club-said:empty{display:none}


/* ---------- footer ------------------------------------------------------ */
/* Four bands, thinnest first: who we are, where to go, whose land, whose
   company. A hairline between the last two so the legal type reads as
   colophon rather than as more navigation.

   Anchor, not Harbour. The bar and the footer were the same navy, so on a short
   page they read as one element wrapped around the content. Anchor is the floor
   of the palette: linen on it measures 16.7:1, and it lets the bar keep Harbour
   without the two competing. */
:root{ --anchor:#061A34 }
.on-anchor{background:var(--anchor);color:var(--linen)}
.foot{padding-block:clamp(40px,6vw,72px) clamp(28px,4vw,44px)}

/* Two words a line, and never three. Each half is its own unbreakable unit, so
   the only place the line can break is between them. */
.foot-stamp .fd-words{white-space:nowrap;display:inline-block}


/* ---------- one radius for anything you press ---------- */
/* Everything that takes a click is a pill. The brand system's small utility
   button was the last 10px corner on the site and it read as a different kit. */
.btn-sm{border-radius:999px;padding:13px 20px}

.foot-meta{
  display:flex;flex-wrap:wrap;gap:14px 28px;justify-content:space-between;
  align-items:baseline;margin-top:clamp(26px,3.4vw,40px);
}
.foot-meta nav{display:flex;flex-wrap:wrap;gap:12px clamp(12px,2.2vw,30px);align-items:center}
/* the same treatment the bar gives its links, so the two read as one system */
.foot-meta nav a{
  text-decoration:none;font-family:var(--sans);font-size:.72rem;font-weight:700;
  letter-spacing:.16em;text-transform:uppercase;color:var(--linen);opacity:.6;
  padding:6px 0;transition:opacity .25s var(--ease),color .25s var(--ease);
}
.foot-meta nav a:hover{opacity:1;color:var(--beacon)}
.foot-meta nav[aria-label="Follow"]{gap:18px;align-items:center}
.foot-social{display:block;width:46px;height:46px;opacity:.85}
.foot-social svg{width:100%;height:100%;display:block}
.foot-social:hover{opacity:1}

.foot-land{margin-top:clamp(26px,3.4vw,40px)}
.foot-land p{
  font-family:var(--mono);font-size:.68rem;line-height:2;letter-spacing:.01em;
  opacity:.40;max-width:104ch;margin:0;
}

.foot-legal{
  margin-top:clamp(28px,3.6vw,44px);
  display:flex;flex-wrap:wrap;gap:20px 32px;
  align-items:center;justify-content:space-between;
}
.foot-legal p{
  font-family:var(--mono);font-size:.68rem;line-height:1.9;opacity:.42;margin:0;
  max-width:62ch;
}
.foot-legal a{color:inherit;text-decoration:underline;text-underline-offset:3px}
.foot-legal a:hover{opacity:1}
.foot-built{display:block;width:186px;flex:0 0 auto}
.foot-built svg{width:100%;height:auto;display:block}

@media(max-width:640px){
  .foot-legal{flex-direction:column;align-items:flex-start}
  .foot-built{width:158px}
}

/* ---------- the home page leads with the badge, not a carousel ---------- */
.hero-mark{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-52%);
  width:clamp(180px,24vw,330px);color:var(--linen);z-index:3;
  filter:drop-shadow(0 10px 30px rgba(18,36,75,.28));
}
.hero-mark svg{width:100%;height:auto;display:block}

/* links to things that do not exist yet */
.soon-link{opacity:.32;pointer-events:none}

/* ---------- a plain page of words ---------- */
.doc{background:var(--linen);color:var(--harbour);
  padding:clamp(48px,7vw,104px) 0 clamp(56px,8vw,120px)}
.doc-in{width:min(720px,92vw);margin:0 auto;padding:0 clamp(20px,4vw,40px)}
.doc h1{font-size:clamp(2rem,4.6vw,3.2rem);line-height:1.02;letter-spacing:-.028em;
  font-weight:800;margin:.3em 0 0;text-wrap:balance}
.doc .lede{font-size:clamp(1.05rem,2.2vw,1.2rem);opacity:.78;margin:1em 0 0;max-width:56ch}
.doc p{margin:1.25em 0 0;max-width:66ch}
.doc h2{font-size:1.15rem;font-weight:700;letter-spacing:-.01em;margin:2em 0 0}
.doc strong{font-weight:700}
.doc a{color:var(--fathom);text-underline-offset:3px}
.doc .updated{font-family:var(--mono);font-size:.7rem;letter-spacing:.05em;
  opacity:.45;margin-top:3em}

/* A rate card. Four facts that a customer will scan rather than read, so they
   are set as rows and not as a paragraph. Rules between rows, none around the
   outside: the table should read as a list that happens to have two columns,
   not as a box sitting on the page. */
.doc table.rates{width:100%;max-width:66ch;margin:1.5em 0 0;
  border-collapse:collapse;text-align:left}
.doc table.rates th,
.doc table.rates td{padding:14px 0;border-bottom:1px solid var(--rule);
  vertical-align:baseline}
.doc table.rates th{font-weight:600;padding-right:24px}
.doc table.rates td{font-family:var(--mono);font-size:.86rem;
  font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}
.doc table.rates tr:last-child th,
.doc table.rates tr:last-child td{border-bottom:0}

/* A page of words does not need the full sky above it. */
.hero.short{min-height:min(30vh,260px)}
/* no clouds, no card: a band of sky and nothing to wait for */
.hero.bare{min-height:min(16vh,140px);display:block}
.hero.short .hero-mark{width:clamp(180px,22vw,300px)}


/* ---------- the mono is for labels, never for reading ---------- */
.foot p,
.foot-land p,
.foot-legal p{font-family:var(--sans)}
.foot p{font-size:.86rem;line-height:1.75;opacity:.62}
.foot-land p{font-size:.86rem;line-height:1.8;opacity:.55;max-width:88ch}
.foot-legal p{font-size:.84rem;line-height:1.75;opacity:.58}
.foot p.foot-tag{font-family:var(--script)}


/* ---------- the welcome, shorter again ---------- */
/* One arrival, three bands: sky, surf, ticker. The sky is now two fifteen
   percent cuts down from where it started; the surf and the ticker keep theirs,
   because they are already thin and trimming them would only blur the two edges
   the arrival depends on. The mark comes down with the sky so it keeps its air:
   a mark that holds its size while the sky shrinks around it stops reading as
   a horizon and starts reading as a banner. */
:root{ --ticker-h:39px }
.hero{min-height:min(32.3vh,290px)}
.hero-mark{width:clamp(126px,16vw,222px)}
.marquee{padding-block:clamp(19px,2.7vh,29px)}
/* The ticker line, a few steps deeper than the palette's amber. Amber itself
   measures 2.7:1 on the rope band, and the dunes now climb over that band,
   which takes it to 2.2. This value holds 5.9:1 on plain rope and 4.7:1 with
   three dune shapes behind it, so it clears AA everywhere the line can appear
   and still reads as burnt amber rather than brown. */
.marquee span{color:#704100}


/* ---------- the bag ---------- */
/* The word became an icon so the bar holds at any width, and the count moved
   into a flare disc: a number you can read at a glance beats a number in
   brackets you have to stop and parse. The ring in harbour lifts the disc off
   the tote so the two shapes never merge. */
.nav-end{display:flex;align-items:center;gap:6px;flex:0 0 auto;margin-left:12px}
a.bag{
  position:relative;display:flex;align-items:center;justify-content:center;
  width:40px;height:40px;padding:0;margin-right:-7px;
  color:var(--linen);opacity:.72;text-decoration:none;
  transition:opacity .25s var(--ease);
}
a.bag:hover,a.bag.has{opacity:1}
.bag-ico{width:23px;height:23px;display:block}
.bag-n{
  position:absolute;top:2px;right:2px;
  min-width:17px;height:17px;padding:0 4px;border-radius:9px;
  background:var(--flare);color:#FFFFFF;
  font-family:var(--sans);font-size:.66rem;font-weight:600;line-height:17px;
  letter-spacing:0;text-align:center;font-variant-numeric:tabular-nums;
  box-shadow:0 0 0 2px var(--harbour);
}
.bag-n[hidden]{display:none}


/* ---------- the burger ---------- */
/* Three rules that become an X. The gap is 5px and the rule is 1.5px, so the
   outer two travel 6.5px to meet in the middle. */
.burger{
  display:none;width:40px;height:40px;padding:0;border:0;background:none;
  cursor:pointer;color:var(--linen);
  flex-direction:column;align-items:center;justify-content:center;gap:5px;
}
.burger span{
  display:block;width:20px;height:1.5px;border-radius:1px;background:currentColor;
  transition:transform .3s var(--ease),opacity .2s var(--ease);
}
.nav.menu-open .burger span:nth-child(1){transform:translateY(6.5px) rotate(45deg)}
.nav.menu-open .burger span:nth-child(2){opacity:0}
.nav.menu-open .burger span:nth-child(3){transform:translateY(-6.5px) rotate(-45deg)}


/* ---------- the stamp ---------- */
/* Three claims, set like a stamp rather than a sentence: the mono, wide
   letterspacing and the periods do the work. It sits with the mark because
   that is what it is vouching for. */
.foot p.foot-stamp{
  font-family:var(--mono);font-size:.7rem;font-weight:500;
  letter-spacing:.15em;text-transform:uppercase;line-height:2.1;
  opacity:.62;margin:0;max-width:26ch;
}
@media(min-width:900px){
  .foot-in{align-items:center}
  .foot p.foot-stamp{max-width:none;text-align:right}
}

/* on a phone the mark and the stamp stack. The sizing lives with the script
   rule further down, which is the last word on this element. */
@media(max-width:760px){
  .foot-in{flex-direction:column;align-items:flex-start;gap:clamp(12px,2.6vw,18px)}
}


/* the footer signs off with the horizontal lockup, small */
.foot-mark{width:132px}
@media(max-width:560px){ .foot-mark{width:112px} }

@media(max-width:560px){ .foot-social{width:40px;height:40px} }



/* ---------- the water ---------- */
/* The band used to finish on the shoal green, which fought the rope bar
   underneath it. It now runs to the rope's own colour, so the surf and the
   ticker meet as one edge rather than two. */
.water{background:linear-gradient(180deg,
  var(--fathom) 0%, var(--signal) 52%, #9FD3E8 78%, var(--rope) 100%)}
/* the crests are spray. The animation owns opacity, so the alpha lives in the
   colour or it would be overridden the moment the swell starts */
.water .cap{background:rgba(255,255,255,.42);height:1.5px}
/* The whitecap was written to peak at 88 percent of its run, and 88 percent of
   the way down the water is exactly where the sand starts. So every few seconds
   a bright rule drew itself along the waterline. It now brightens in the middle
   of the band, is nearly gone by four fifths, and stops short of the edge. */
@keyframes swell{
  0%   {transform:translate3d(0,calc(var(--ticker-h) * .17),0) scaleY(.4);opacity:0}
  16%  {opacity:.14}
  44%  {opacity:.56}
  62%  {opacity:.70}
  82%  {opacity:.20}
  100% {transform:translate3d(0,calc(var(--ticker-h) * .84),0) scaleY(2.1);opacity:0}
}
@media(prefers-reduced-motion:reduce){ .water .cap{opacity:.3} }

/* ---------- the acknowledgement is not fine print ---------- */
.foot-land p{font-size:.92rem;line-height:1.85;opacity:.86;max-width:86ch}

/* ---------- the stamp, in the script ---------- */
.fd-swash{font-feature-settings:'ss04' 1}
/* One line, at every width. The 26ch cap above was written for the mono version
   of this stamp, three claims wide, and never came off when it became two
   claims in the script. That cap, not the width of the screen, is what kept
   breaking the line in two. */
.foot p.foot-stamp{
  font-family:var(--script);font-size:clamp(1.15rem,2vw,1.5rem);
  letter-spacing:0;text-transform:none;line-height:1.5;
  color:var(--beacon);opacity:1;font-weight:400;
  max-width:none;white-space:nowrap;
}
/* The line measures 15.9 times its own font size. Below about 332px that no
   longer fits between the gutters, so the vw term takes over and holds it on
   one line down to 320. Above that the rem wins and nothing moves. */
@media(max-width:760px){
  .foot p.foot-stamp{font-size:min(1.15rem, 5.3vw)}
}

/* the bar says it until the badge arrives */
/* On a desktop bar there is a great deal of empty space between the mark and
   the links, and a 20px script line sitting in it looked like a caption. At
   this size it is the other half of the mark. */
.nav-say{
  font-family:var(--script);font-size:clamp(1.25rem,2.35vw,2.1rem);
  color:var(--linen);opacity:.78;margin:0;white-space:nowrap;
  transition:opacity .34s var(--ease),transform .34s var(--ease);
}
.nav:not(.nav-bare) .nav-say{opacity:0;transform:translateY(6px);pointer-events:none}
.nav-bare .nav-say{opacity:.78}
/* It used to go at 900, because five links and a bag left it nowhere to sit.
   The burger gave the middle of the bar back, so the line stays at every width
   and holds a legible size instead of shrinking away to a squiggle. */
@media(max-width:900px){ .nav-say{font-size:1.08rem} }
@media(max-width:400px){ .nav-say{font-size:1rem} }


/* ---------- the welcome on a phone ---------- */
/* A tall sky costs more on a small screen than it gives: it is most of the
   first view and the shop is what people came for. */
@media(max-width:760px){
  .hero{min-height:min(22.1vh,173px)}
  .hero-mark{width:clamp(106px,30vw,150px)}
  :root{ --ticker-h:30px }
  .marquee{padding-block:clamp(13px,2vh,20px)}
}
@media(max-width:480px){
  .hero{min-height:min(18.7vh,142px)}
  .hero-mark{width:clamp(96px,29vw,128px)}
  :root{ --ticker-h:26px }
}


/* ---------- the bar on a phone ---------- */
/* One mark at a time holds at every width. Below 900px the script line goes,
   and the slot simply waits empty until the big mark leaves the sky. Forcing
   the badge in early put both marks on screen together, which is the one thing
   the handoff exists to prevent. */

/* Below 760 the links fold into a sheet under the bar. A sideways scroller was
   hiding half the shop behind a gesture nobody knows is there; a burger is
   boring and everybody can already use it. The bag stays outside the fold. */
@media(max-width:760px){
  .burger{display:flex}
  /* the links leave the flow when they become a sheet, so nothing is left to
     push the bag and the burger across. They take the auto margin themselves. */
  .nav-end{margin-left:auto}
  .nav-links{
    position:absolute;left:0;right:0;top:100%;
    flex-direction:column;flex-wrap:nowrap;align-items:stretch;gap:0;
    margin:0;padding:0 var(--gut);
    background:var(--harbour);
    box-shadow:0 18px 26px -18px rgba(0,0,0,.55);
    overflow:hidden;
    max-height:0;opacity:0;pointer-events:none;
    transition:max-height .34s var(--ease),opacity .22s var(--ease);
  }
  .nav.menu-open .nav-links{max-height:70vh;opacity:1;pointer-events:auto;overflow-y:auto}
  .nav-links a{
    padding:15px 0;font-size:.78rem;letter-spacing:.14em;
    border-top:1px solid rgba(253,250,243,.09);
  }
  .nav-links a:first-child{border-top:0}
  /* what is coming stays listed here. The sheet has the room the bar did not,
     and a shop that names its next two lines reads as a shop with a plan. */
  .nav-links a.soon,.nav-links a.soon-link{display:block;opacity:.34}
}


/* ---------- the contrast floor ------------------------------------------ */
/* Quiet text was being made quiet with opacity, and opacity takes contrast
   with it. Measured against the palette, small text needs at least 0.72 on
   linen, straw or rope and 0.70 on anchor, harbour or cedar to clear AA at
   4.5:1. Everything below is a rule that fell under that line.

   This lives in one block rather than scattered through the page styles
   because several of these pages are generated out of the artifact bundles,
   where a fix would be overwritten on the next build. chrome.css loads last,
   so this is the floor for the whole site and there is one place to raise it.

   Sizes and colours are otherwise untouched: the design still reads as quiet,
   it just does not fall out of the standard to get there. */
.hb dt, .spec dt, #sku, .doc .updated{ opacity:.78 }
/* the crumb carries no opacity at all: it sits on the link, and the two
   multiplied to 3.1:1 */
.crumb{ opacity:1; color:#627190 }

/* Opacity multiplies down the tree, so a faded parent with a faded child lands
   at the product of the two: .78 inside .78 is .61, which is back under the
   line. These four are given a colour instead, at full opacity, so nothing can
   compound. #627190 is navy at 68 percent over linen and #5A6682 is navy at 70
   over straw, both measured at better than 4.6:1. */
.rev .who, .later em{ color:#627190; opacity:1 }
.crumb a{ color:#4A5876; opacity:1 }
.pcard-txt i{ color:#5A6682; opacity:1 }

/* nav items for products that do not exist yet. They are still links and still
   in the tab order, so "coming soon" cannot be conveyed by fading them out of
   the standard. They keep a quieter weight than the live ones. */
.nav-links a.soon, .nav-links a.soon-link, .soon-link{ opacity:.72 }
.nav-ver{ opacity:.72 }

/* on cedar. #A4BAB6 measured 4.37 and #D0B410 measured 4.34, both a whisker
   under, so both are lifted rather than redesigned */
.club p.club-terms{ color:#B4CCC8; opacity:1 }
.club .club-say .eyebrow{ color:#E8C911; opacity:1 }

/* Navy on the signal blue is 4.35:1, which passes as large text and fails as
   small. At 18.4px bold it sat a quarter of a pixel under the 18.66px line, so
   the type goes up rather than the brand blue changing. Lightening --signal by
   four percent is the other way to settle it if the size is ever a problem. */
#add, .cart-go{ font-size:19px }


/* A colourway that is not made yet is an unavailable control, not a faint one.
   It was a live button at 40 percent opacity, which put its label at 1.7:1 and
   left it in the tab order offering something nobody can buy. Disabled is the
   honest state: it is exempt from the contrast rule because it is genuinely not
   an option, it is announced as unavailable, and it stops being a tab stop. */
.dz.later[disabled]{ opacity:.4; cursor:default }

/* The way past the navigation. Off screen until focused, then it lands in the
   top left where a keyboard user is already looking. */
.skip{position:absolute;left:8px;top:-60px;z-index:999;
  background:var(--linen);color:var(--harbour);
  padding:12px 20px;border-radius:0 0 6px 6px;
  font-family:var(--sans);font-size:.9rem;font-weight:700;text-decoration:none;
  transition:top .18s var(--ease)}
.skip:focus{top:0}

/* The zoom overlay was aria-hidden while still holding two focusable buttons,
   so a keyboard user could tab into something no screen reader would announce.
   visibility takes them out of the tab order; display would kill the fade. */
#lens[aria-hidden="true"]{visibility:hidden}
#lens[aria-hidden="false"]{visibility:visible}

/* Present to a screen reader, absent to the eye. For a heading a page needs
   structurally but has no room for in the layout. Not display:none, which
   would take it out of the accessibility tree along with the pixels. */
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

/* ---------- the questions ---------- */
/* Open by default and collapsible, not closed by default. A closed answer is
   still in the markup for a crawler, but a person who scrolled here has the
   question and would have to click to get the answer, which is a toll for no
   reason. details/summary gives keyboard and screen reader behaviour for free. */
.faq{background:var(--linen);color:var(--harbour);padding:clamp(56px,7vw,96px) 0}
.faq-in{width:min(760px,92vw);margin:0 auto}
.faq h2{font-size:clamp(1.7rem,3.4vw,2.6rem);line-height:1.05;
  letter-spacing:-.02em;font-weight:800;margin:.3em 0 1.4em}
.faq-q{border-top:1px solid var(--rule);padding:20px 0}
.faq-q:last-child{border-bottom:1px solid var(--rule)}
.faq-q summary{cursor:pointer;list-style:none;display:flex;gap:14px;
  align-items:baseline}
.faq-q summary::-webkit-details-marker{display:none}
.faq-q summary::after{content:"+";margin-left:auto;font-family:var(--mono);
  font-size:1.1rem;line-height:1;opacity:.72;transition:transform .2s var(--ease)}
.faq-q[open] summary::after{content:"\2013"}
.faq-q summary h3{font-size:1.02rem;font-weight:600;line-height:1.4;margin:0}
.faq-q p{font-size:.97rem;line-height:1.72;margin:.9em 0 .2em;max-width:62ch;
  /* a colour, not opacity. See the note below. #34486E is the navy at 86
     percent over linen, so it reads exactly as it did. */
  color:#34486E}
.faq-q summary:focus-visible{outline:2px solid var(--signal);outline-offset:4px}

/* A link in body copy on a light ground. The signal blue is a brand colour for
   large marks and buttons, not for a 14px inline link: on linen it lands at
   3.3:1. Taking it down to #2F6C9E gives 5.4:1 on its own, but the lede sets
   its own quietness with opacity, and opacity multiplies through to the link,
   which dragged it back to 4.47 and under the line. So the lede carries its
   quietness as a colour instead, and then nothing inside it is being faded by
   something it cannot see. #4B5C82 is the same navy at 78 percent, computed,
   so the paragraph looks exactly as it did. */
.doc .lede{ color:#4B5C82; opacity:1 }
.doc .lede a, .doc p a{ color:#2F6C9E; opacity:1; text-underline-offset:3px }


/* ---------------------------------------------------------------------------
   A NOTE, because this has now cost three rounds of the same bug.

   Never fade text with opacity if the element can contain a link.

   Opacity is not inherited, it composites: it applies to the element and
   everything inside it, and nested values multiply. A paragraph at .86 holding
   a link that has been carefully set to 5.4:1 renders that link at 4.4:1, and
   nothing in either rule says so. It has bitten the breadcrumb, the review
   bylines, the unavailable swatches, the document lede and the FAQ body, every
   time in the same way and every time invisibly.

   Quiet text carries its quietness as a colour. The mixes are computed against
   the ground it sits on, so it looks identical and nothing inside it is being
   dimmed by a parent it cannot see. Opacity stays for what it is for: whole
   elements fading in and out.
   --------------------------------------------------------------------------- */
