/* Bouncy Castle Man.
   Layout: persistent left rail + content column. Range shown as horizontal
   scroll shelves, one per category. Sticky action bar on mobile. */

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
/* overflow-x:hidden here is INSURANCE, not a fix. It stops a stray overflow
   becoming a sideways scroll, but it also silently CLIPS the offending content,
   which is how the bento grid ran 85px off every phone for weeks without ever
   producing a scrollbar to notice. Do not treat "no sideways scroll" as proof
   the layout fits: measure element rects against clientWidth instead, skipping
   anything inside a horizontal scroller. */
body{margin:0;overflow-x:hidden}
img,svg{display:block;max-width:100%}
button,input,select,textarea{font:inherit;color:inherit}
/* 16px ON EVERY FORM CONTROL, AND DO NOT LOWER IT.
   iOS Safari zooms the whole page in whenever a focused input is under 16px.
   The zoom widens the layout viewport past the screen, so the page can then be
   dragged sideways, and it STAYS zoomed after the keyboard closes. That is the
   whole "it does not fit on mobile and it scrolls sideways" bug: it is not a
   layout overflow, which is why every static width sweep came back clean.
   16px is Safari's threshold, not a design preference. 15.5px triggers it.
   This rule is last-resort insurance; the individual control rules below are
   all 16px too, and they out-specify this one. */
input,select,textarea{font-size:16px}
a{color:inherit;text-decoration:none}
h1,h2,h3,h4,p,ul,ol,figure{margin:0}
ul{padding:0;list-style:none}

:root{
  /* ---- the category palette ----------------------------------------------
     Every hire category owns a colour. It follows the category everywhere:
     its shelf, its cards, its no-photo panels, its page banner, its dot in the
     rail. Colour is information here, not decoration.

     --c    the category colour, a FILL
     --ct   the same category as TEXT on a light background
     --on-c what goes ON the fill
     All six now work as both fill and text, so --c and --ct match on every
     row. The pair is kept because the moment a light colour is added back the
     two diverge again, as amber did. */
  --c-castle:#0056db;      /* THE LOGO BLUE, sampled from the artwork  white 6.26:1 */
  --c-combi:#6d28d9;       /* violet                                   white 7.10:1 */
  --c-obstacle:#047857;    /* emerald                                  white 5.48:1 */
  --c-disco:#c81e6a;       /* pink                                     white 5.45:1 */
  --c-sumo:#c2410c;        /* orange                                   white 5.18:1 */
  --c-marquee:#0e7490;     /* teal                                     white 5.36:1 */

  /* THE LOGO YELLOW, sampled from the artwork. Every call to action is this
     yellow with ink on it, on every page, so "the thing you press" is
     learnable at a glance. No category uses it, so it never collides.
     A yellow fill is only 1.53:1 against the page, so every yellow button
     carries a 2px ink border, which also echoes the heavy outline the artwork
     is drawn with.
     --accent-text is the same yellow taken down to a tone that works as small
     TEXT on a light ground, which the yellow itself cannot. */
  --accent:#fec521;
  --accent-text:#8a6100;
  --accent-deep:#d9a200;

  /* Ink is the navy the artwork is outlined in, not a neutral black. */
  --ink:#0b1a2e;
  --ink-70:#48566b;
  --ink-45:#54637b;
  --paper:#f8fbff;
  --paper-2:#eaf1fd;
  /* Light surfaces. Navy is not used for anything larger than a line of text
     except the contact band; the rail, the masthead and the footer are light,
     and the weight comes from the logo blue and yellow. */
  --sky:#dbe9ff;
  --sky-line:#bcd4f8;
  --rail-bg:#ffffff;
  --rail-line:#dde8f8;
  --rail-hover:#eaf1fd;
  --line:#d8e5f7;
  --line-strong:#b9cdeb;

  --r:16px;
  --r-sm:12px;
  --r-pill:999px;

  --rail:286px;   /* wide enough for the full wordmark beside the mark */
  --gut:clamp(20px,3vw,52px);

  --step-0:clamp(16px,.3vw + 15px,17.5px);
  --step-1:clamp(19px,.6vw + 17px,22px);
  --step-2:clamp(24px,1.4vw + 20px,32px);
  --step-3:clamp(28px,2.6vw + 18px,44px);
  --step-4:clamp(36px,4vw + 16px,62px);

  --display:'Fredoka','Figtree',system-ui,sans-serif;
  --body:'Figtree',system-ui,-apple-system,'Segoe UI',sans-serif;

  --c:var(--accent-text);
  --ct:var(--accent-text);
  --on-c:#fff;
}

/* --ct is written out on every row rather than defaulting to var(--c). A
   custom property holding a var() is substituted where it is DECLARED, not
   where it is used, so the root value would leak into every category. */
[data-cat="castle"]{--c:var(--c-castle);--ct:var(--c-castle);--on-c:#fff}
[data-cat="combi"]{--c:var(--c-combi);--ct:var(--c-combi);--on-c:#fff}
[data-cat="obstacle"]{--c:var(--c-obstacle);--ct:var(--c-obstacle);--on-c:#fff}
[data-cat="disco"]{--c:var(--c-disco);--ct:var(--c-disco);--on-c:#fff}
[data-cat="sumo"]{--c:var(--c-sumo);--ct:var(--c-sumo);--on-c:#fff}
[data-cat="marquee"]{--c:var(--c-marquee);--ct:var(--c-marquee);--on-c:#fff}

body{font-family:var(--body);font-size:var(--step-0);line-height:1.55;
  color:var(--ink);background:var(--paper);-webkit-font-smoothing:antialiased}

h1,h2,h3,.display{font-family:var(--display);font-weight:600;line-height:1.06;
  letter-spacing:-.015em}
h1{font-size:var(--step-4)}
h2{font-size:var(--step-3);text-wrap:balance}
h3{font-size:var(--step-1);line-height:1.18}

/* ------------------------------------------------------------- the shell -- */
/* Persistent rail on the left, content column on the right. The rail is a
   real <nav> and comes AFTER <main> in the DOM so the h1 is the first thing
   in the document; grid puts it back on the left visually. */
.shell{display:grid;grid-template-columns:var(--rail) minmax(0,1fr);align-items:start}
.col{grid-column:2;grid-row:1;min-width:0}
.rail{grid-column:1;grid-row:1;position:sticky;top:0;height:100dvh;
  display:flex;flex-direction:column;gap:22px;padding:24px 22px;
  background:var(--rail-bg);color:var(--ink-70);overflow-y:auto;z-index:60;
  overscroll-behavior:contain;
  border-right:2px solid var(--rail-line)}
.rail-top{display:flex;align-items:center;justify-content:space-between;gap:12px}
.rail .brand{color:var(--ink)}
.mark{flex:none;width:96px;height:auto}
/* In the rail the lockup stacks: the castle is wide and the rail is narrow, so
   side by side would not fit the name. On the mobile top bar it goes back to a
   row, where vertical space is the scarce thing instead. */
/* The castle is centred over the name, and the lockup is centred in the rail. */
.rail .brand{flex-direction:column;align-items:center;gap:10px;width:100%}
.rail .wordmark{text-align:center}
.rail .mark{width:150px}
.rail .wordmark{font-size:19px}
.rail-label{font-size:11px;font-weight:800;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-45);margin-bottom:10px}
.rail-nav{display:flex;flex-direction:column;gap:1px}
.rail-nav a{display:flex;align-items:center;gap:11px;padding:10px 12px;
  border-radius:var(--r-sm);font-weight:600;font-size:15.5px;
  transition:background .14s,color .14s}
.rail-nav a{color:var(--ink)}
.rail-nav a:hover,.rail-nav a[aria-current="page"]{background:var(--rail-hover);color:var(--ct)}
/* Dots use --ct, not --c: amber sits at 1.99:1 against the light rail. */
.rail-nav .dot{width:11px;height:11px;border-radius:50%;background:var(--ct);flex:none}
.rail-nav .plain{color:var(--ink-70);font-size:14.5px;font-weight:500}
.rail-sec{margin-top:auto}
/* Marquees, one line under the CTA. Adam's point was that the marquee side is
   invisible, and the rail is the one element on every page. It is NOT a second
   button: the rule is one call to action per screen, in the logo yellow, and a
   second filled button beside it would make the page ask twice and answer
   neither. This is a link in the marquee colour that reads as a signpost. */
.rail-marq{display:flex;align-items:center;justify-content:center;gap:8px;
  margin-top:10px;padding:11px 14px;border-radius:var(--r-pill);
  border:2px solid var(--c-marquee);color:var(--c-marquee);
  font-family:var(--display);font-weight:600;font-size:15px;text-align:center;
  transition:background .15s,color .15s}
.rail-marq:hover{background:var(--c-marquee);color:#fff}
.rail-marq::after{content:"";width:8px;height:8px;flex:none;
  border-right:2.5px solid currentColor;border-top:2.5px solid currentColor;
  transform:rotate(45deg)}
.rail-tel{display:block;background:#fff;border-radius:var(--r);
  padding:16px 18px;margin-bottom:10px;transition:background .15s;
  border:2px solid var(--rail-line)}
.rail-tel:hover{background:var(--rail-hover)}
.rail-tel span{display:block;font-size:12px;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink-45);margin-bottom:4px}
.rail-tel b{font-family:var(--display);font-weight:600;font-size:21px;color:var(--ink);
  letter-spacing:-.02em}
.rail .btn{width:100%}
.rail-legal{font-size:12.5px;color:var(--ink-45);line-height:1.5}
.rail-legal a{text-decoration:underline;text-underline-offset:2px}
.rail-legal a:hover{color:var(--accent-text)}
/* The desktop sidebar in the logo blue with a yellow rule, matching the phone
   top bar (Sam, 21 Oct 2026). Desktop widths only: below 1100 the rail is the
   top bar and its drawer stays white so the links read. Category dots get a
   white ring because the castle blue is the rail colour. The phone card keeps
   its white face, so the number still stands out. */
@media(min-width:1101px){
  .rail{background:var(--c-castle);border-right:4px solid #ffd23f;color:rgba(255,255,255,.82)}
  .rail .brand{color:#fff}
  .rail-label{color:rgba(255,255,255,.7)}
  .rail-nav a,.rail-nav .plain{color:#fff}
  .rail-nav a:hover,.rail-nav a[aria-current="page"]{background:rgba(255,255,255,.16);color:#fff}
  .rail-nav .dot{width:14px;height:14px;background:var(--c);border:3px solid #fff;box-sizing:border-box}
  .rail-tel{border-color:transparent}
  .rail-marq{border-color:#fff;color:#fff}
  .rail-marq:hover{background:#fff;color:var(--c-marquee)}
  .rail-legal{color:rgba(255,255,255,.75)}
  .rail-legal a:hover{color:#ffd23f}
}
.burger{display:none;background:none;border:0;padding:8px;cursor:pointer;color:inherit}
.burger span{display:block;width:22px;height:2.5px;border-radius:2px;background:currentColor;
  margin:4px 0}

@media(max-width:1100px){
  .shell{grid-template-columns:1fr}
  .col{grid-column:1;grid-row:2}
  .rail{grid-column:1;grid-row:1;position:sticky;height:auto;flex-direction:column;
    gap:0;padding:12px 20px}
  .rail-top{gap:14px}
  /* width:auto matters. The desktop rail centres the lockup with width:100% on
     .brand; going back to a row here without unsetting that left the brand
     filling the whole bar and pushing the burger 32px past the edge. Because
     the rail sets overflow-y:auto, and CSS resolves the other axis to auto
     along with it, that overflow became a horizontal scroll INSIDE the rail: it
     opened scrolled 32px to the right and the drawer's first characters were
     cut off ("HAT WE HIRE", "ORE"). */
  .rail .brand{flex-direction:row;align-items:center;gap:11px;width:auto}
  .rail .mark{width:96px}
  .rail .wordmark{font-size:17.5px}
  .burger{display:block}
  .rail-body{display:none;padding-top:16px}
  .rail.open .rail-body{display:block}
  .rail-sec{margin-top:18px}
  .rail-nav{gap:0}
}
/* At 320 the mark plus the full name plus the burger is still 42px wider than
   the bar. The name does not wrap and is not abbreviated, so the mark gives way
   instead. */
@media(max-width:380px){
  .rail .mark{width:66px}
  .rail .wordmark{font-size:15.5px}
}

/* ------------------------------------------------------------ the mark --- */
.brand{display:flex;align-items:center;gap:10px;flex:none;min-width:0}
/* One name, one weight, one colour. No word is emphasised over another. */
.wordmark{font-family:var(--display);font-weight:600;font-size:17.5px;letter-spacing:-.02em;
  white-space:nowrap;line-height:1.1}

/* ------------------------------------------------------------- content --- */
.pad{padding-left:var(--gut);padding-right:var(--gut)}
.band{padding:clamp(48px,5.5vw,86px) var(--gut);position:relative}
.band-tight{padding-bottom:clamp(20px,2vw,30px)}
.tint{background:var(--paper-2)}
.lede{font-size:var(--step-1);color:var(--ink-70);max-width:58ch;font-weight:500}
.prose{max-width:65ch;color:var(--ink-70);font-weight:450}
.prose p{margin-bottom:16px}
.prose h2{margin:34px 0 14px}
.narrow{max-width:1080px}

.eyebrow{display:inline-block;font-size:12.5px;font-weight:800;letter-spacing:.1em;
  text-transform:uppercase;color:var(--accent-text);background:#fff2cc;
  border-radius:var(--r-pill);padding:7px 15px;margin-bottom:16px}
.sec-head{margin-bottom:clamp(24px,3vw,40px);max-width:70ch}
.sec-head p{margin-top:14px;color:var(--ink-70);font-size:var(--step-1);max-width:56ch}

/* ------------------------------------------------------------- buttons --- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:9px;
  padding:15px 26px;border-radius:var(--r-pill);border:2px solid transparent;
  font-family:var(--body);font-weight:800;font-size:15.5px;white-space:nowrap;
  cursor:pointer;transition:background .15s,color .15s,border-color .15s,
  transform .12s cubic-bezier(.2,.8,.3,1),box-shadow .15s}
.btn:hover{transform:translateY(-2px)}
.btn:active{transform:translateY(1px)}
.btn-accent{background:var(--accent);color:var(--ink);border-color:var(--ink);
  box-shadow:0 4px 0 var(--ink)}
.btn-accent:hover{background:#ffd45a;box-shadow:0 6px 0 var(--ink)}
.btn-accent:active{box-shadow:0 2px 0 var(--ink)}
.btn-ink{background:var(--ink);color:#fff;box-shadow:0 4px 0 #000}
.btn-ink:hover{box-shadow:0 6px 0 #000}
.btn-line{background:#fff;color:var(--ink);border-color:var(--line-strong)}
.btn-line:hover{border-color:var(--ink)}
.btn-ghost{background:rgba(255,255,255,.1);color:#fff;border-color:rgba(255,255,255,.22)}
.btn-ghost:hover{background:rgba(255,255,255,.18)}
.btn svg{width:17px;height:17px;flex:none}

/* -------------------------------------------------------------- masthead -- */
/* Not a centred hero. A wide colour block with the headline bottom-left and
   the photo bleeding off the right edge, then the facts sitting on the seam.

   The sky block is DRAWN in the mark's language rather than decorated with
   gradients: bunting along the top, outlined clouds behind, and the seam cut as
   a wave with the same heavy ink line the castle is outlined in. All four
   pieces are flat fills with a 3 to 5px ink stroke, which is the one rule the
   mark follows, so the hero reads as the same hand.
   The bunting is the six category colours in order, so even the decoration is
   the palette doing its job.
   Art lives in build/brand/*.svg and is hashed into /assets/ like everything
   else. wave.svg carries --paper as a literal fill (#f8fbff): change --paper
   and the wave has to change with it. */
.mast{color:var(--ink);position:relative;overflow:hidden;
  padding:clamp(58px,5.4vw,84px) var(--gut) clamp(104px,8.4vw,140px);
  background:
    url("/assets/bunting.6c2d0f29.svg") repeat-x left -6px top -2px,
    url("/assets/wave.67f42494.svg") repeat-x left bottom,
    var(--sky)}
/* Three columns above 1280: headline, date picker, photo. The picker is a fixed
   300px because a date grid has a floor below which it stops being tappable;
   the headline and the photo share what is left. */
/* Two columns: everything you read on the left, one big photo on the right.
   align-items:stretch, so the photo is as tall as the copy and the calendar
   together rather than floating at one end of it. */
/* Copy and the slideshow on the left, the date card on the right. The photo is
   a wide rectangle under the headline rather than a full height panel: a tall
   frame cropped every landscape photo we have down to a vertical strip. */
/* TWO COLUMNS, TWO ROWS, AND THE SECOND ROW IS THE POINT.
   Row 1 is the copy. Row 2 is the photo and the date card SIDE BY SIDE, which
   is what makes their top and bottom edges line up.
   It used to be one flex column (copy then photo) with the card in a second
   column at align-items:center, so the card floated against the middle of the
   whole left stack: its top sat level with the paragraph and its bottom
   stopped 130px short of the photo. Neither edge matched anything.
   The card stretches, so the row height is set by the photo and the card
   follows it. Its natural height was within 15px of the photo's anyway, so
   nothing is squashed to make this work. */
.mast-grid{display:grid;grid-template-columns:minmax(0,1.28fr) minmax(280px,.72fr);
  grid-template-rows:auto auto;
  column-gap:clamp(24px,3vw,52px);row-gap:clamp(24px,2.6vw,34px);
  align-items:start;position:relative;z-index:2}
.mast-copy{grid-column:1;grid-row:1;min-width:0}
/* Both stretch, so whichever is naturally taller sets the row and the other
   follows it. The date card is 518 tall and the photo's 16/10 gives 503, so
   without this the bottoms miss each other by 15px, which is exactly the kind
   of near-miss that looks like a mistake rather than a choice. */
.mast-shot{grid-column:1;grid-row:2;align-self:stretch;
  display:flex;flex-direction:column}
.mast-shot .shot-frame{flex:1;display:flex}
/* aspect-ratio has to go, or it wins over the stretch and fixes the height. */
.mast-shot .pic{aspect-ratio:auto;flex:1;min-height:0}
.dpick{grid-column:2;grid-row:2;align-self:stretch}
/* The empty cell this leaves at row 1, column 2 is not waste, it is where the
   balloons go. See .mast::after. */
/* The masthead headline is capped below the global display size: the left
   column is narrow because the rail takes 266px, and the hard rule is that
   the headline never runs past two lines on desktop. */
/* Smaller than it was at two columns. Three columns leave the headline about
   370px at 1440, and the hard rule is still that it never runs past two lines. */
/* No ch cap in the three column hero: the column itself is the measure, and a
   14ch cap was forcing a third line the column had room to avoid. */
.mast h1{font-size:clamp(31px,2.4vw + 8px,46px);max-width:17ch;text-wrap:balance}
.mast h1 em{font-style:normal;color:var(--c-castle)}
/* The company name as the h1, Adam 30 Sep: "we want it to stand out". Bigger
   than the old headline, which is fine now it is three words not six, and a
   hard offset shadow in the accent, the same flat drop the photo frame casts. */
.mast h1.mast-name{font-size:clamp(44px,3.9vw + 10px,76px);font-weight:700;
  line-height:.98;letter-spacing:-.01em;max-width:none;
  text-shadow:3px 3px 0 var(--accent)}
/* Category colours on the nouns in the hero lede. All three are the -ct
   (text-on-light) value, not the fill: these are words on a pale sky and the
   fill values are picked for white text on a colour panel, not the reverse. */
.w-castle{color:var(--c-castle);font-weight:800}
.w-combi{color:var(--c-combi);font-weight:800}
.w-obstacle{color:var(--c-obstacle);font-weight:800}
.mast p{margin-top:18px;font-size:var(--step-1);color:var(--ink-70);max-width:46ch;
  font-weight:500}
.mast-actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:28px}
/* Balloons, drawn in the mark's language: flat fills, one 3.5px ink outline,
   no gradients, colours out of the category palette. They sit in the cell the
   grid leaves empty beside the headline, so they are filling a hole the layout
   already had rather than being sprinkled on top of it.
   Hidden below 980 where the grid stacks and the cell stops existing. */
.mast::after{content:"";position:absolute;z-index:1;pointer-events:none;
  right:calc(var(--gut) + 2vw);top:clamp(40px,5vw,86px);
  width:clamp(150px,13vw,215px);aspect-ratio:250/300;
  background:url("/assets/balloons.c0417773.svg") no-repeat center/contain;
  opacity:.92}
@media(max-width:1180px){.mast::after{display:none}}
.mast-shot{position:relative;min-width:0}
.shot-frame{position:relative}
/* Portrait in the three column hero. Beside a date card that is naturally tall,
   a landscape photo left a lot of empty sky above it and read as an
   afterthought. */
/* Straight. The frame and the caption were both tilted, the calendar sat at a
   third angle between them, and the hero read as clutter rather than as three
   things doing three jobs. Nothing in the hero is rotated now. */
.mast-shot .pic{border:3px solid var(--ink);box-shadow:12px 12px 0 var(--c-castle);
  background:var(--paper-2);aspect-ratio:16/10}
/* Set here, not inline on the element, so the stacked breakpoint can reshape it. */
.mast-tag{position:absolute;left:-10px;bottom:-14px;background:var(--accent);color:var(--ink);
  padding:10px 18px;border-radius:var(--r-pill);font-family:var(--display);font-weight:600;
  font-size:14.5px}
/* Clouds, drawn and outlined rather than blurred blobs. Held back to .55 so
   they sit behind the headline instead of competing with it, and hidden on
   narrow screens where there is no room to be scenery. */
/* No cloud. It was tried and cut: everywhere it fit it sat half behind the
   photo frame and read as a smudge, and the hero already carries bunting, a
   tilted frame and the straddling cards. build/brand/cloud.svg is kept for a
   section that has room for it. */
/* The rail keeps 266px, so between 1100 and 1360 the masthead's left column
   is too narrow to hold the headline to two lines. Stack it instead. */
/* Stacked, the TEXT leads. The photo used to be ordered above it, which put a
   448px tall image between the top bar and the h1 and pushed the headline and
   both buttons below the fold on every phone and small laptop. Below the text
   it also gets to be wider and shallower, which suits a single column. */
/* Below 1280 there is not room for three. The picker goes under the buttons
   beside the photo, which keeps it above the fold, and below 1000 everything
   stacks with the text leading. */
/* Below 980 the two columns stack: copy, then the calendar, then the photo,
   which is the same reading order the desktop layout has. */
@media(max-width:980px){
  .mast-grid{grid-template-columns:1fr;gap:clamp(24px,4vw,34px)}
  .mast-left{gap:26px}
  .dpick{max-width:380px}
  .mast-copy,.mast-shot,.dpick{grid-column:1}
  .mast-copy{grid-row:1} .mast-shot{grid-row:3} .dpick{grid-row:2}
  .mast-shot{max-width:640px;display:block}
  .mast-shot .shot-frame{display:block}
  /* Stacked there is no row to stretch to, so the ratio comes back. */
  .mast-shot .pic{aspect-ratio:4/3;flex:none}}

/* THE DATE PICKER IS OFF ON PHONES. Sam's call, 3 Sep. On a phone the hero is
   already a headline, a paragraph, two buttons and a photo, and a seven column
   calendar between the buttons and the photo pushed the photo most of a screen
   further down for a control almost nobody was going to drive with a thumb.

   It is hidden, not removed, because the desktop layout is built around it:
   .mast-grid's second column IS the picker. Deleting it would reflow the hero
   at every width, and the whole point of hiding it is to change phones only.

   760 rather than the 1100 the rail switches at. Between the two there is
   width for the calendar to sit beside things and it still reads as a layout
   rather than a stack.

   The picker carries the only "Get a price" in the hero, so hiding it would
   leave a phone with a phone number and "see the range" and no way into the
   enquiry form. .mast-cta-m is that button coming back, and it exists ONLY
   below this breakpoint. Above it the picker's own button is the one, and two
   yellow buttons a hundred pixels apart is what the hero was cleaned up to
   avoid in the first place.

   The action bar pinned to the bottom of the screen below 1100 is Call and
   WhatsApp. It is not an enquiry link, so it does not cover this.

   EVERY SELECTOR HERE IS PREFIXED WITH .mast ON PURPOSE. The base .dpick rule,
   the one that sets display:flex, is declared LATER in this stylesheet than
   this block. At equal specificity the later declaration wins, so a plain
   .dpick{display:none} in here loses and the calendar stays on the page: it
   was still rendering, just pushed below the photo by the grid-row swap, which
   is the kind of half fix that looks right in a screenshot of the top of the
   page. .mast .dpick is 0,2,0 against 0,1,0 and wins wherever it sits. */
.mast .mast-cta-m{display:none}
@media(max-width:760px){
  .mast .dpick{display:none}
  .mast .mast-shot{grid-row:2}
  .mast .mast-cta-m{display:inline-flex}}

/* Facts sit across the seam between the masthead and the page. */
.facts{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;
  margin:-38px var(--gut) 0;position:relative;z-index:3}
.facts div{background:#fff;border:2px solid var(--line);border-radius:var(--r);
  padding:20px 22px;box-shadow:0 8px 0 -2px rgba(20,19,16,.07)}
.facts div:nth-child(1){--fc:var(--c-castle)}
.facts div:nth-child(2){--fc:var(--c-obstacle)}
.facts div:nth-child(3){--fc:var(--c-disco)}
.facts b{display:block;font-family:var(--display);font-weight:600;font-size:var(--step-2);
  color:var(--fc);line-height:1.1;margin-bottom:2px}
.facts span{color:var(--ink-70);font-size:14.5px;font-weight:500}
@media(max-width:760px){.facts{grid-template-columns:1fr;margin-top:-26px}}

/* ---------------------------------------------------------- hero stack --- */
/* Four cards on a 4:3 stage, one per side of the business. Straight, not
   rotated: tilted frames were tried in this hero and read as clutter. Each
   frame has its photo's own ratio, so the whole unit is always in shot.
   Widths are % of the stage, tops and bottoms % of its height. Shadow and
   label run the card's category colour (--c, from data-cat), so the hero is
   a legend for the rail and the shelves below it.
   Layout: course top left, marquee top right, castle and a second course
   along the bottom, each overlapping the card behind by a corner. */
/* 21 Oct 2026: a straight 2 x 2 grid. The overlapping pile above read as messy
   (Sam), every card at a different size and corner hidden. Four equal 4:3 cards
   keep each photo whole and line up with the date card beside them. */
.stack{display:grid;grid-template-columns:1fr 1fr;gap:18px 20px;width:100%;
  max-width:760px;margin-inline:auto;padding:0 8px 8px 0}
.stack figure{position:relative;margin:0;overflow:hidden;background:var(--paper-2);
  border:3px solid var(--ink);border-radius:14px;box-shadow:6px 6px 0 var(--c)}
.stack img{display:block;width:100%;height:100%;object-fit:cover}
.stack figcaption{position:absolute;left:10px;top:10px;padding:5px 12px;
  border-radius:var(--r-pill);background:var(--c);color:#fff;border:2px solid var(--ink);
  font-family:var(--display);font-weight:600;font-size:13px;line-height:1.2;white-space:nowrap}
/* Hero range (hero_range in this file). The block fills the row beside the
   date card, so its bottom lines up with the card's. */
.mast-shot .rng{flex:1;min-height:470px;display:grid;gap:14px}
.rng a{position:relative;display:block;overflow:hidden;text-decoration:none;
  background:var(--paper-2);border:3px solid var(--ink);border-radius:14px}
.rng img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.rng-i span{position:absolute;left:0;right:0;bottom:0;padding:26px 14px 11px;color:#fff;
  font-family:var(--display);font-weight:600;font-size:16px;line-height:1.15;
  background:linear-gradient(transparent,rgba(12,18,38,.82))}
.rng-i span::after{content:"\2192";float:right;width:26px;height:26px;margin-top:-4px;
  border-radius:50%;background:var(--c);border:2px solid #fff;display:grid;place-items:center;
  font-size:14px;line-height:22px;text-align:center}
.rng-tiles{grid-template-columns:1.25fr 1fr 1fr;grid-template-rows:1fr 1fr}
.rng-tiles a{box-shadow:5px 5px 0 var(--c)}
.rng-tiles a:first-child{grid-row:1 / span 2}
.rng-tiles a:first-child span{font-size:23px;padding:44px 18px 16px}
.rng-strip{grid-template-rows:1fr auto}
.rng-main{box-shadow:8px 8px 0 var(--c);border-radius:16px}
.rng-main img{transition:opacity .25s ease}
.rng-main em{position:absolute;left:14px;top:14px;font-style:normal;padding:7px 14px;
  border-radius:var(--r-pill);background:var(--c);color:#fff;border:2px solid var(--ink);
  font-family:var(--display);font-weight:500;font-size:14px}
.rng-main em b{font-weight:700}
.rng-main em b::after{content:" \00b7"}
.rng-row{display:grid;grid-template-columns:repeat(5,1fr);gap:10px}
.rng-row a{aspect-ratio:4/3;border-width:2.5px;border-radius:12px}
.rng-row a.on{box-shadow:0 0 0 3px var(--c);border-color:var(--c)}
.rng-row span{padding:5px 4px 6px;text-align:center;font-size:12px;background:var(--c)}
.rng-row span::after{display:none}
@media(prefers-reduced-motion:reduce){.rng-main img{transition:none}}
@media(max-width:980px){.mast-shot .rng{min-height:420px}}

/* Phones (21 Oct 2026, same pattern as Little People Parties): the photos lead
   the hero as one swipeable row, each card whole at 4:3 with the next one
   peeking in. Then the name on one line, Adam's subtitle, and one full width
   "Get a price". The phone button hides here because the action bar at the
   bottom of the screen already says Call us, and "See the range" drops to a
   text link so the hero has one button, not three wrapping into 2 + 1. */
@media(max-width:600px){
  .mast-grid{display:flex;flex-direction:column;gap:20px}
  .mast .mast-shot{order:-1;max-width:none}
  .stack{width:auto;max-width:none;display:flex;gap:12px;overflow-x:auto;
    scroll-snap-type:x mandatory;margin:0 calc(-1 * var(--gut)) 0 0;padding:2px var(--gut) 10px 0;
    scrollbar-width:none}
  .stack::-webkit-scrollbar{display:none}
  .stack figure{flex:0 0 84%;scroll-snap-align:start;border-width:2.5px;border-radius:16px;box-shadow:5px 5px 0 var(--c)}
  .stack figcaption{left:10px;top:10px;padding:5px 11px;font-size:12.5px;border-width:2px}
  .mast h1.mast-name{font-size:39px;white-space:nowrap;margin-top:12px}
  .mast p{font-size:15.5px;line-height:1.5;margin-top:12px}
  .mast-actions{display:grid;grid-template-columns:1fr;gap:6px;margin-top:20px}
  .mast-actions a[href^="tel"]{display:none}
  .mast .mast-actions .mast-cta-m{display:flex;width:100%;justify-content:center}
  .mast-actions a[href="#range"]{background:none;border:0;box-shadow:none;justify-self:center;
    padding:10px 8px;min-height:0}
  .mast-actions a[href="#range"]::after{content:"\2192";margin-left:6px}
  /* Both range layouts become the same swipe row of the five categories. */
  .mast-shot .rng{display:block;min-height:0}
  .rng .rng-main{display:none}
  .mast-shot .rng-tiles,.rng-row{display:flex;gap:12px;overflow-x:auto;scroll-snap-type:x mandatory;
    margin:0 calc(-1 * var(--gut)) 0 0;padding:2px var(--gut) 10px 0;scrollbar-width:none}
  .rng-tiles::-webkit-scrollbar,.rng-row::-webkit-scrollbar{display:none}
  .rng-tiles a,.rng-row a{flex:0 0 84%;aspect-ratio:4/3;scroll-snap-align:start;
    border-width:2.5px;border-radius:16px;box-shadow:5px 5px 0 var(--c)}
  .rng-row a.on{border-color:var(--ink)}
  .rng-tiles a:first-child span,.rng-row span{font-size:16px;padding:26px 14px 11px;text-align:left;
    background:linear-gradient(transparent,rgba(12,18,38,.82))}
  .rng-row span::after{display:grid}}

/* FULL-BLEED PHONE HERO (21 Oct 2026, Sam's pick over the swipe row). The
   Adrenaline Max photo runs edge to edge from the top of the masthead, and the
   eyebrow, name and subtitle sit on its lower part over a dark fade. Then Get
   a price, See the range, and the five categories as pills. The range strip
   and the bunting stand down here; the photo is the hero.
   The photo is shown whole at its own 4:3, so the full course is in shot:
   cropped to fill a tall phone frame it lost both ends and the top of the
   slide (Sam: "cut off and weird"). It fades into a navy band that carries
   the name and subtitle, with the eyebrow sitting on the photo's lower edge.
   One grid: photo row 1, the navy band (a ::before) spans rows 2 to 3. */
.bleed,.hero-chips{display:none}
/* Above phone width the "Family run" eyebrow goes and the hero moves up, so
   the name starts just under the bunting (Sam, 21 Oct 2026). Phones keep the
   eyebrow, where it sits on the photo. */
@media(min-width:601px){
  .mast-copy>.eyebrow{display:none}
  .mast{padding-top:clamp(44px,3.6vw,54px)}
  .mast h1.mast-name{margin-top:0}
}
@media(max-width:600px){
  /* No wave on phones: it needs ~80px of empty sky under the pills to show,
     which read as dead space above the action bar (Sam). */
  .mast{padding-top:0;padding-bottom:0;background:var(--sky)}
  .mast .mast-shot{display:none}
  .mast-copy{display:grid;grid-template-columns:minmax(0,1fr)}
  /* The band runs logo blue into the combi violet, the two strongest colours
     in the palette, so the hero is bright rather than dark (Sam: "add some
     more colour"). The photo fades into the band's starting blue. */
  .mast-copy::before{content:"";grid-row:2 / 6;grid-column:1;margin:0 calc(-1 * var(--gut));
    background:linear-gradient(170deg,var(--c-castle) 0%,#3b3fd8 45%,var(--c-combi) 100%)}
  .bleed{display:block;grid-row:1;grid-column:1;position:relative;
    margin:0 calc(-1 * var(--gut));aspect-ratio:4/3;overflow:hidden;background:var(--c-castle)}
  .bleed img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
  /* The site's bunting, back along the top edge of the photo. */
  .bleed::before{content:"";position:absolute;left:0;right:0;top:-2px;height:44px;z-index:1;
    background:url("/assets/bunting.6c2d0f29.svg") repeat-x left -6px top 0;background-size:auto 44px}
  .bleed::after{content:"";position:absolute;left:0;right:0;bottom:0;height:40%;
    background:linear-gradient(180deg,rgba(0,86,219,0),var(--c-castle))}
  .bleed-tag{position:absolute;right:12px;top:48px;z-index:2;padding:5px 11px;
    border-radius:var(--r-pill);background:var(--c-obstacle);color:#fff;border:2px solid var(--ink);
    font-family:var(--display);font-weight:600;font-size:12px}
  .mast-copy>.eyebrow,.mast-copy>h1,.mast-copy>p{grid-column:1;position:relative;z-index:1}
  .mast-copy>.eyebrow{grid-row:1;align-self:end;justify-self:start;margin-bottom:-6px;
    background:rgba(255,255,255,.94);font-size:10.5px;padding:6px 11px}
  .mast-copy>h1{grid-row:3}
  .mast-copy>p{grid-row:4;padding-bottom:4px}
  .mast h1.mast-name{color:#fff;text-shadow:3px 3px 0 rgba(11,26,46,.55);margin:14px 0 0}
  .mast h1.mast-name em{color:#ffd23f}
  .mast .mast-copy>p{color:rgba(255,255,255,.9);font-size:14.5px;line-height:1.45;margin-top:8px}
  /* Get a price sits inside the colour band too, so the hero has no pale
     strip under it (Sam: "the white is too boring"). */
  .mast-actions{grid-row:5;grid-column:1;position:relative;z-index:1;margin-top:20px;padding-bottom:26px}
  .mast-actions a[href="#range"]{display:none}
  /* The range: five round photos in their category colour rings, on the band
     between the eyebrow and the name. */
  .hero-chips{grid-row:2;grid-column:1;position:relative;z-index:1;display:flex;
    justify-content:space-between;gap:6px;margin:16px 0 2px}
  .hero-chips a{display:flex;flex-direction:column;align-items:center;gap:6px;width:20%;
    min-width:0;text-decoration:none}
  .hero-chips b{display:block;width:min(58px,15vw);aspect-ratio:1;border-radius:50%;overflow:hidden;
    border:3px solid var(--c);box-shadow:0 0 0 2.5px #fff;background:#fff}
  .hero-chips img{display:block;width:100%;height:100%;object-fit:cover}
  .hero-chips span{color:#fff;font-family:var(--display);font-weight:600;font-size:11.5px;
    line-height:1.12;text-align:center}}
@media(max-width:380px){.mast h1.mast-name{font-size:34px}}

/* --------------------------------------------------------- hero slides --- */
.slides{position:relative}
/* 42%: the frame is 16/10 and the photos are 4/3, so there is a little vertical
   overflow and the ground is the half worth losing. */
.slides .slide{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  object-position:center 42%;opacity:0;transition:opacity .7s ease}
.slides .slide.on{opacity:1}
/* No JS: the first slide is already .on and already loaded, so the hero shows a
   photo whatever happens to the script. */
/* Chunky, always on, same round-and-outlined language as the buttons. */
.slide-arrow{display:none;position:absolute;top:50%;margin-top:-24px;z-index:3;
  width:48px;height:48px;border-radius:50%;background:#fff;border:3px solid var(--ink);
  cursor:pointer;padding:0;box-shadow:0 3px 0 var(--ink);
  transition:background .14s,transform .12s,box-shadow .12s}
.js .slide-arrow{display:grid;place-items:center}
.slide-arrow:hover{background:var(--accent)}
.slide-arrow:active{transform:translateY(3px);box-shadow:0 0 0 var(--ink)}
.slide-arrow::before{content:"";width:12px;height:12px;
  border-top:3px solid var(--ink);border-right:3px solid var(--ink)}
.slide-arrow.prev{left:14px}
.slide-arrow.prev::before{transform:rotate(-135deg);margin-left:4px}
.slide-arrow.next{right:14px}
.slide-arrow.next::before{transform:rotate(45deg);margin-right:4px}
@media(max-width:480px){.slide-arrow{width:40px;height:40px;margin-top:-20px}
  .slide-arrow.prev{left:8px}.slide-arrow.next{right:8px}}
.slide-dots{display:none;gap:7px;justify-content:center;margin-top:26px}
.js .slide-dots{display:flex}
.slide-dots .dot{width:9px;height:9px;padding:0;border-radius:50%;cursor:pointer;
  border:2px solid var(--ink);background:transparent;transition:background .16s}
.slide-dots .dot.on{background:var(--ink)}
@media(prefers-reduced-motion:reduce){.slides .slide{transition:none}}

/* ---------------------------------------------------------- date pick --- */
/* Sits between the headline and the photo in the hero. Same card language as
   everything else: white, 3px ink border, chunky offset shadow.
   Deliberately NOT an availability calendar. No day is ever shown as free or
   booked, because we have no booking data and inventing one would be a promise
   Adam has not made. It picks a date and carries it into the enquiry. */
.dpick{background:#fff;border:3px solid var(--ink);border-radius:var(--r);
  padding:18px 18px 16px;box-shadow:8px 8px 0 var(--accent);
  width:100%;display:flex;flex-direction:column}
/* Stretched to the photo's height, so the grid of days takes the slack and the
   button and its note stay pinned to the bottom edge. Without flex:1 here the
   card grows but its content stays at the top and leaves a hole. */
.dpick .dp-grid{flex:1;align-content:space-between}
.dp-label{display:block;font-size:11px;font-weight:800;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-45);margin-bottom:12px}
.dp-head{display:flex;align-items:center;justify-content:space-between;gap:6px;
  margin-bottom:10px}
.dp-month{font-family:var(--display);font-weight:600;font-size:16.5px;
  text-align:center;flex:1;min-width:0}
.dp-nav{width:30px;height:30px;flex:none;border:2px solid var(--line-strong);
  border-radius:50%;background:#fff;cursor:pointer;font-size:17px;line-height:1;
  color:var(--ink);transition:background .14s,border-color .14s}
.dp-nav:hover:not(:disabled){background:var(--accent);border-color:var(--ink)}
.dp-nav:disabled{opacity:.32;cursor:not-allowed}
.dp-dow,.dp-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:3px}
.dp-dow{margin-bottom:4px}
.dp-dow span{text-align:center;font-size:11px;font-weight:800;color:var(--ink-45)}
.dp-grid{display:none}
.js .dp-grid{display:grid}
.dp-grid button{aspect-ratio:1;border:0;background:none;border-radius:8px;
  font-size:13.5px;font-weight:600;color:var(--ink);cursor:pointer;padding:0;
  transition:background .12s,color .12s}
.dp-grid button:hover:not(:disabled){background:var(--paper-2)}
/* Past dates. WCAG exempts disabled controls from contrast, but a date grid is
   read as a whole: you find next Saturday by scanning past the days that are
   gone. #b9cdeb measured 1.62:1 and was effectively invisible. #64748b is
   4.76:1, still obviously muted against the ink of a live day. */
.dp-grid button:disabled{color:#64748b;opacity:.75;cursor:default}
.dp-grid button.today{box-shadow:inset 0 0 0 2px var(--line-strong)}
.dp-grid button.on{background:var(--c-castle);color:#fff}
.dp-grid span{aspect-ratio:1}
/* No JS: a native date input does the same job. */
.dp-fallback{display:block;font-size:13px;font-weight:700;color:var(--ink-70)}
.dp-fallback input{width:100%;margin-top:6px;padding:11px 12px;
  border:2px solid var(--line-strong);border-radius:var(--r-sm);font-size:16px}
.js .dp-fallback{display:none}
.dp-go{width:100%;margin-top:14px}
/* .mast p sets step-1 on everything in the hero, and this lives in the hero, so
   it has to out-specify that or the note renders at headline-adjacent size. */
.mast .dp-note,.dp-note{margin-top:10px;font-size:12.5px;line-height:1.45;
  color:var(--ink-45);font-weight:500;max-width:none}

/* -------------------------------------------------------------- picture -- */
.pic{display:block;position:relative;aspect-ratio:var(--ratio,4/3);overflow:hidden;
  border-radius:var(--r);background:var(--paper-2)}
.pic img{width:100%;height:100%;object-fit:cover}
/* No photo yet: the unit's name set large on its own category colour. Reads as
   a designed object, and colour-codes the shelf. Set img= in data.py to swap. */
.pic-panel{background:var(--c);color:var(--on-c);display:flex;flex-direction:column;
  justify-content:flex-end;padding:18px}
.pic-panel .panel-name{font-family:var(--display);font-weight:600;line-height:1.08;
  font-size:clamp(17px,1.6vw,23px);max-width:13ch;overflow-wrap:break-word}
.pic-panel::after{content:"";position:absolute;width:92px;height:92px;border-radius:50%;
  right:-24px;top:-24px;background:currentColor;opacity:.16}

/* --------------------------------------------------------------- shelves -- */
/* The range is six horizontal shelves, one per category, instead of a tile
   grid plus a filtered grid. Each shelf scroll-snaps and is keyboard and
   touch scrollable; the arrows are an enhancement, not the only way through. */
.shelf{margin-bottom:clamp(34px,4vw,58px)}
.shelf-head{display:flex;align-items:center;gap:14px;padding:0 var(--gut);
  margin-bottom:16px;flex-wrap:wrap}
.shelf-head .dot{width:14px;height:14px;border-radius:50%;background:var(--c);flex:none}
.shelf-head h3{font-size:var(--step-2);margin-right:auto}
.shelf-head .all{font-size:14.5px;font-weight:800;color:var(--ct);white-space:nowrap}
.shelf-head .all:hover{text-decoration:underline;text-underline-offset:3px}
.shelf-nav{display:flex;gap:7px}
.shelf-nav button{width:38px;height:38px;border-radius:50%;border:2px solid var(--line-strong);
  background:#fff;cursor:pointer;display:grid;place-items:center;
  transition:border-color .14s,background .14s,transform .12s}
.shelf-nav button:hover{border-color:var(--c);transform:translateY(-2px)}
.shelf-nav button:disabled{opacity:.35;cursor:default;transform:none;
  border-color:var(--line)}
.shelf-nav svg{width:16px;height:16px}
.track{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(232px,268px);gap:16px;
  overflow-x:auto;scroll-snap-type:x mandatory;scroll-behavior:smooth;
  padding:4px var(--gut) 14px;scrollbar-width:thin;
  /* Without this, a swipe that reaches the end of a shelf CHAINS to the page and
     drags the whole document sideways. Six shelves on the home page, so on a
     phone this is the easiest way to knock the layout off centre. */
  overscroll-behavior-x:contain}
.track>*{scroll-snap-align:start}
.track::-webkit-scrollbar{height:8px}
.track::-webkit-scrollbar-thumb{background:var(--line-strong);border-radius:var(--r-pill)}
/* On touch you swipe the shelf, so the arrows are dead weight and at 320px
   they push the header row past the viewport. */
@media(max-width:640px){.shelf-nav{display:none}}
/* One or two units: not a scroller, a row that fills the band. Without this a
   two card shelf leaves half a 1600px screen empty and reads as broken rather
   than as short. auto-flow row so the cards lay out normally, and a max so two
   cards do not stretch to 700px each. */
.track.short{grid-auto-flow:row;overflow-x:visible;scroll-snap-type:none;
  /* THE CAP IS ON THE TRACK, NOT THE COLUMN. It used to be
     minmax(232px,360px), which reads as "232 minimum, 360 maximum" and is not
     how auto-fit counts: Chrome packs the tracks at the MAX, so an 840px box
     fitted two 360s and sent a third card onto its own row. The folded disco
     and sumo shelf is exactly three cards and it wrapped 2 + 1, which is worse
     than the empty track the fold was meant to fix.
     minmax(232px,1fr) counts at the minimum and then stretches, which is the
     behaviour the old rule was reaching for. --smax caps the whole track so a
     short row still does not span the column: pages.py sets it per shelf from
     the number of cards, about 360px a card at two and 300 at three. Without
     it, 1fr is exactly the bug the 360 was added to fix. */
  grid-template-columns:repeat(auto-fit,minmax(232px,1fr));
  max-width:var(--smax,840px)}
/* On a phone a short shelf swipes like the others. Stacking it one card per
   row made the disco/sumo and marquee shelves ~2,200px of the home page, the
   "too much scrolling" Adam flagged on 3 Sep. */
@media(max-width:560px){.track{grid-auto-columns:minmax(210px,74%)}
  .track.short{grid-auto-flow:column;grid-template-columns:none;overflow-x:auto;
    scroll-snap-type:x mandatory;max-width:none}}

/* ----------------------------------------------------------------- card -- */
.card{min-width:0;display:flex;flex-direction:column;color:inherit;background:#fff;
  border:2px solid var(--line);border-radius:var(--r);padding:11px 11px 15px;
  transition:transform .2s cubic-bezier(.2,.8,.3,1),border-color .16s,box-shadow .16s}
.card:hover{transform:translateY(-5px);border-color:var(--c);box-shadow:0 10px 0 -2px var(--c)}
.card .pic{--ratio:4/3}
.card-tag{position:absolute;top:9px;left:9px;z-index:2;background:#fff;color:var(--ink);
  font-size:10.5px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;
  padding:5px 10px;border-radius:var(--r-pill);box-shadow:0 1px 4px rgba(20,19,16,.18)}

.card h3{margin:13px 3px 0;font-size:17px}
.card p{color:var(--ink-70);font-size:14.5px;margin:6px 3px 0;font-weight:450;flex:1}
.card-foot{margin:13px 3px 0;padding-top:11px;border-top:2px solid var(--line);
  display:flex;align-items:center;justify-content:space-between;gap:10px}
.price{font-family:var(--display);font-weight:600;font-size:15.5px}
.card-cta{font-size:13.5px;font-weight:800;color:var(--accent-text)}
.card:hover .card-cta{text-decoration:underline;text-underline-offset:3px}

/* A plain grid, used on the category, area and unit pages where the set is
   small and complete. The home page uses shelves instead. */
.grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
@media(max-width:1500px){.grid{grid-template-columns:repeat(3,1fr)}}
@media(max-width:1040px){.grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:520px){.grid{grid-template-columns:1fr}}

/* ------------------------------------------------------------- timeline -- */
/* How it works, as a horizontal run with a connecting line rather than cards. */
.line{display:grid;grid-template-columns:repeat(3,1fr);gap:26px;position:relative}
.line::before{content:"";position:absolute;left:23px;right:23px;top:23px;height:3px;
  background:repeating-linear-gradient(90deg,var(--line-strong) 0 9px,transparent 9px 18px)}
.line-step{position:relative}
.line-step:nth-child(1){--lc:var(--c-combi)}
.line-step:nth-child(2){--lc:var(--c-marquee)}
.line-step:nth-child(3){--lc:var(--c-obstacle)}
.line-n{width:46px;height:46px;border-radius:50%;background:var(--lc);color:#fff;
  display:grid;place-items:center;font-family:var(--display);font-weight:600;font-size:20px;
  position:relative;z-index:1;margin-bottom:16px;border:4px solid var(--paper)}
.tint .line-n{border-color:var(--paper-2)}
.line-step p{color:var(--ink-70);font-size:15.5px;margin-top:8px;font-weight:450}
@media(max-width:820px){.line{grid-template-columns:1fr;gap:22px}
  .line::before{left:23px;right:auto;top:23px;bottom:23px;width:3px;height:auto;
    background:repeating-linear-gradient(180deg,var(--line-strong) 0 9px,transparent 9px 18px)}
  .line-step{padding-left:0}}

/* ----------------------------------------------------------------- why --- */
/* Bento, not a list: one wide cell then five. Exactly six cells for six points. */
.bento{display:grid;grid-template-columns:repeat(6,1fr);gap:16px}
.bento li{grid-column:span 2;background:#fff;border:2px solid var(--line);
  border-radius:var(--r);padding:24px}
/* Six points, six cells, no gaps: 1 wide, then 3, then 2 half-width. A bento
   with an empty cell at the end means the grid was planned wrong. */
.bento li:nth-child(5),.bento li:nth-child(6){grid-column:span 3}
.bento li:nth-child(1){grid-column:span 6;display:grid;
  grid-template-columns:auto minmax(0,1fr);gap:20px;align-items:center;
  background:var(--accent);color:var(--ink);border-color:var(--ink)}
.bento li:nth-child(1) p{color:#4a3608;font-size:var(--step-1)}
.bento li:nth-child(1) .n{width:52px;height:52px;font-size:19px}
.bento li:nth-child(6n+1){--wc:var(--c-castle)}
.bento li:nth-child(6n+2){--wc:var(--c-castle)}
.bento li:nth-child(6n+3){--wc:var(--c-obstacle)}
.bento li:nth-child(6n+4){--wc:var(--c-combi)}
.bento li:nth-child(6n+5){--wc:var(--c-disco)}
.bento li:nth-child(6n+6){--wc:var(--c-marquee)}
.bento .n{width:38px;height:38px;border-radius:50%;background:var(--wc);color:#fff;
  display:grid;place-items:center;font-family:var(--display);font-weight:600;font-size:15px;
  margin-bottom:14px}
.bento li:nth-child(1) .n{margin-bottom:0;background:var(--ink);color:var(--accent)}
.bento p{color:var(--ink-70);font-size:15px;margin-top:7px;font-weight:450}
@media(max-width:1000px){.bento{grid-template-columns:repeat(4,1fr)}
  .bento li,.bento li:nth-child(5){grid-column:span 2}
  .bento li:nth-child(1),.bento li:nth-child(6){grid-column:span 4}}
/* EVERY nth-child SPAN ABOVE HAS TO BE NAMED AGAIN HERE. `.bento li` is
   specificity (0,1,1) and `.bento li:nth-child(5)` is (0,2,1), so a blanket
   `.bento li{grid-column:span 1}` inside the media query LOSES to the base
   rule. Cells 5 and 6 were staying at `span 3` in a one column grid, which
   makes the grid invent two implicit columns and pushes both cells about 85px
   off the right of every phone. `body{overflow-x:hidden}` was clipping them,
   so it read as "the page does not fit" rather than as a scrollbar, and no
   width sweep caught it because nothing ever scrolled. */
@media(max-width:620px){.bento{grid-template-columns:1fr}
  .bento li,.bento li:nth-child(1),
  .bento li:nth-child(5),.bento li:nth-child(6){grid-column:span 1}
  .bento li:nth-child(1){grid-template-columns:1fr}}

/* --------------------------------------------------------------- areas --- */
/* Full-bleed colour band, towns as big type. The area checker that used to sit
   inside it is gone; see data.py AREA_OPTIONS for why. Its .checker, .checker-row
   and #areaOut rules went with it. */
.areas-band{background:var(--c-castle);color:#fff;position:relative;overflow:hidden}
.areas-band::after{content:"";position:absolute;width:300px;height:300px;border-radius:50%;
  right:-110px;bottom:-140px;background:#fff;opacity:.08}
.areas-band .sec-head p{color:#dbe7fb}
.town-list{display:flex;flex-wrap:wrap;gap:10px;position:relative;z-index:1}
.town-list a{display:block;padding:12px 22px;border-radius:var(--r-pill);
  border:2px solid rgba(255,255,255,.34);font-family:var(--display);font-weight:600;
  font-size:19px;transition:background .15s,transform .15s,border-color .15s}
.town-list a:hover{background:#fff;color:var(--c-castle);border-color:#fff;
  transform:translateY(-3px)}
/* Areas index: full-width rows with a rule, not a card grid. */
.area-rows{display:grid;gap:0}
.area-row{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.4fr);gap:24px;
  padding:22px 0;border-top:2px solid var(--line);align-items:baseline}
.area-row:last-child{border-bottom:2px solid var(--line)}
.area-row h3{font-size:var(--step-2)}
.area-row h3 a:hover{color:var(--accent-text)}
.area-row p{color:var(--ink-70);font-weight:450}
@media(max-width:760px){.area-row{grid-template-columns:1fr;gap:6px}}

/* ------------------------------------------------------------- reviews --- */
/* Staggered, not three equal columns. */
/* ALIGNED, NOT STAGGERED. Children 1 and 3 carried margin-top:30px and 52px,
   which set the three cards at three different heights on purpose. With three
   quotes of different lengths that read as three cards that had slipped rather
   than as a deliberate stagger, and it left a ragged line under the heading.
   align-items:stretch so all three are the height of the tallest. */
.revs{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;align-items:stretch}
.rev{background:#fff;border:2px solid var(--line);border-radius:var(--r);padding:26px;
  display:flex;flex-direction:column}
.rev:nth-child(1){--rc:var(--c-disco)}
.rev:nth-child(2){--rc:var(--c-castle)}
.rev:nth-child(3){--rc:var(--c-obstacle)}
/* Pushes the attribution to the bottom of every card, so with the cards now
   equal height the three rules under the quotes line up too. */
.rev .who{margin-top:auto}
/* The empty state: one panel across the full row, dashed, so it reads as a slot
   waiting to be filled rather than as a review. */
.revs:has(.rev-empty){grid-template-columns:1fr}
.rev-empty{border-style:dashed;border-color:var(--line-strong);background:var(--paper-2)}
.rev-empty .stars{opacity:.35}
.rev-empty p{color:var(--ink-45)}
.rev .stars{color:var(--accent-text);font-size:14px;letter-spacing:3px;margin-bottom:12px}
.rev p{font-family:var(--display);font-weight:500;font-size:var(--step-1);line-height:1.35}
.rev .who{margin-top:16px;padding-top:14px;border-top:2px solid var(--line);
  font-size:14px;font-weight:700;color:var(--rc)}
@media(max-width:900px){.revs{grid-template-columns:1fr}}
/* Google rating: one full-width card linking to the listing. */
.revs:has(.g-rating){grid-template-columns:1fr}
.g-rating{display:flex;align-items:center;gap:22px;background:#fff;border:2px solid var(--line);
  border-radius:var(--r);padding:22px 26px;transition:border-color .16s}
.g-rating:hover{border-color:var(--line-strong)}
.g-score{font-family:var(--display);font-weight:700;font-size:clamp(40px,5vw,56px);line-height:1}
.g-body{display:flex;flex-direction:column;gap:4px;font-weight:600}
.g-body .stars{margin:0}
.g-cta{margin-left:auto;font-weight:700;color:var(--accent-text);white-space:nowrap}
@media(max-width:600px){.g-rating{flex-wrap:wrap;gap:12px 18px}.g-cta{margin-left:0;width:100%}}

/* ----------------------------------------------------------------- faq --- */
.faq{display:grid;grid-template-columns:1fr 1fr;gap:14px;align-items:start}
.faq-item{background:#fff;border:2px solid var(--line);border-radius:var(--r);
  transition:border-color .16s}
.faq-item.open{border-color:var(--ink)}
.faq-q{width:100%;background:none;border:0;text-align:left;cursor:pointer;
  padding:20px 54px 20px 22px;font-family:var(--display);font-weight:600;
  font-size:var(--step-1);position:relative;line-height:1.25}
.faq-q::after{content:"";position:absolute;right:18px;top:50%;width:26px;height:26px;
  margin-top:-13px;border-radius:50%;background:var(--paper-2);transition:background .2s}
.faq-q::before{content:"";position:absolute;right:24px;top:50%;width:14px;height:14px;
  margin-top:-7px;z-index:1;background:var(--ink);transition:transform .25s,background .2s;
  clip-path:polygon(43% 0,57% 0,57% 43%,100% 43%,100% 57%,57% 57%,57% 100%,43% 100%,43% 57%,0 57%,0 43%,43% 43%)}
.faq-item.open .faq-q::after{background:var(--accent)}
.faq-item.open .faq-q::before{transform:rotate(135deg);background:var(--ink)}
.faq-a{max-height:0;overflow:hidden;transition:max-height .3s ease}
.faq-a p{padding:0 22px 20px;color:var(--ink-70);font-weight:450}
@media(max-width:820px){.faq{grid-template-columns:1fr}}

/* ------------------------------------------------------------- marquee --- */
/* Adam, 27 Aug: "Our marquee hire side of the business is being lost with the
   current website." One card in one shelf was never going to fix that, so
   marquees get their own block on the home page and at the top of their
   category page.

   Its own layout family, not a reuse: a single bordered panel with a solid
   colour header strip and the fit-out running as a row of tiles underneath.
   The areas band is full-bleed colour with pills, the bento is six cells, the
   contact block is a split. This is none of those.

   No sizes are quoted anywhere in it. Adam has not given them, and the copy is
   written so it does not need them rather than guessing at a number. */
/* On the home page the block sits inside a full-bleed tinted band. Floating on
   the paper between the shelves and "How it works" it read as one more card in
   the flow, which is exactly the problem Adam was describing. The band changes
   the ground colour, so the page visibly stops doing castles and starts doing
   marquees. Rules top and bottom in the marquee colour rather than ink, so it
   reads as a section of this site and not a pasted in advert. */
.marq-band{background:#e8f4f7;border-top:4px solid var(--c-marquee);
  border-bottom:4px solid var(--c-marquee)}
.marq-band .marq{box-shadow:10px 10px 0 rgba(14,116,144,.28)}
.marq-eyebrow{display:inline-block;font-size:12.5px;font-weight:800;
  letter-spacing:.1em;text-transform:uppercase;color:var(--c-marquee);
  background:#fff;border-radius:var(--r-pill);padding:7px 15px;margin-bottom:14px}
.marq{border:3px solid var(--ink);border-radius:var(--r);overflow:hidden;
  background:#fff;box-shadow:10px 10px 0 var(--c-marquee)}
.marq-head{background:var(--c-marquee);color:#fff;padding:clamp(26px,3vw,40px);
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.82fr);
  gap:clamp(20px,3vw,42px);align-items:center}
.marq-head-text{min-width:0}
.marq-pic{display:block;border:3px solid var(--ink);border-radius:var(--r);
  overflow:hidden;aspect-ratio:4/3;background:rgba(255,255,255,.14)}
.marq-pic img{width:100%;height:100%;object-fit:cover;display:block}
@media(max-width:900px){.marq-head{grid-template-columns:1fr}
  .marq-pic{aspect-ratio:16/9}}
.marq-head h2{max-width:20ch}
/* #d6eef4 measured 4.44:1 on the teal, just under AA. #e0f3f8 is 4.68:1. */
.marq-head .lede{margin-top:14px;color:#e0f3f8;font-size:var(--step-1);
  font-weight:500;max-width:56ch}
.marq-actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:24px}
.marq-body{padding:clamp(24px,2.6vw,34px)}
.marq-label{font-size:11px;font-weight:800;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-45);margin-bottom:16px}
/* Names, not sales copy. Each item carried a line of description underneath and
   every one of those lines was invented: whether the floor is timber, whether
   the tables are set out before you arrive, what the lighting is. Adam gave us
   five words and those five words are the content. Set them large so the row
   still carries the block. */
.marq-grid{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:12px}
.marq-grid li{border:2px solid var(--line);border-radius:var(--r-sm);
  padding:22px 18px;min-width:0;font-family:var(--display);font-weight:600;
  font-size:var(--step-1);color:var(--c-marquee);text-align:center;
  overflow-wrap:break-word}
/* Furniture on its own is a real hire line, not a footnote to the marquee. */
.marq-also{margin-top:16px;border:2px dashed var(--line-strong);border-radius:var(--r-sm);
  padding:16px 20px;display:flex;gap:14px;align-items:center;flex-wrap:wrap;
  font-weight:500;color:var(--ink-70);font-size:15.5px}
.marq-also a{font-weight:800;color:var(--c-marquee);text-decoration:underline;
  text-underline-offset:3px}
@media(max-width:1100px){.marq-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media(max-width:640px){.marq-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .marq{box-shadow:6px 6px 0 var(--c-marquee)}}
@media(max-width:380px){.marq-grid{grid-template-columns:1fr}}

/* Signpost. A one line cross link to marquees from every page where marquees
   are not the subject: the other five category pages, the 22 other unit pages
   and all 9 town pages. Adam's whole point was that the marquee side of the
   business is invisible, and a block on two pages does not fix that if a
   customer lands on "bouncy castle hire clonmel" and never sees it.

   Kept to one line with a rule and an arrow rather than made into a card, so it
   signposts without competing with the page it is sitting on. The copy changes
   by context so it does not read as the same banner stamped everywhere. */
.signpost{display:flex;align-items:center;gap:18px;flex-wrap:wrap;
  border-top:3px solid var(--c-marquee);background:#fff;
  border-radius:0 0 var(--r) var(--r);padding:20px 24px;margin-top:34px;
  box-shadow:0 8px 0 -2px rgba(20,19,16,.06)}
.signpost .sp-l{font-size:11px;font-weight:800;letter-spacing:.14em;
  text-transform:uppercase;color:var(--c-marquee);flex:none}
.signpost p{flex:1;min-width:220px;font-weight:500;color:var(--ink-70);
  font-size:15.5px;margin:0}
.signpost a{flex:none;display:inline-flex;align-items:center;gap:9px;
  font-family:var(--display);font-weight:600;font-size:16px;color:var(--c-marquee);
  border-bottom:2px solid transparent;transition:border-color .15s}
.signpost a:hover{border-color:var(--c-marquee)}
.signpost a::after{content:"";width:9px;height:9px;border-right:2.5px solid currentColor;
  border-top:2.5px solid currentColor;transform:rotate(45deg);flex:none}
/* Narrow: the label goes on its own line. Left beside the copy it pinched
   the text into half the width and ran it to seven lines. */
@media(max-width:620px){.signpost{flex-direction:column;align-items:flex-start;gap:10px}
  .signpost p{min-width:0}}

/* ------------------------------------------------------------- notices --- */
.note{background:#fff6db;border:2px solid #f2e2ac;border-radius:var(--r);padding:20px 24px;
  font-size:15.5px;font-weight:500;max-width:70ch}
.safety{background:#fff;border:2px solid var(--line);border-radius:var(--r);
  padding:26px 28px;margin-top:30px;max-width:70ch}
.safety h3{margin-bottom:14px}
.safety li{position:relative;padding-left:30px;margin-bottom:11px;color:var(--ink-70);
  font-size:15.5px;font-weight:450}
.safety li::before{content:"";position:absolute;left:0;top:5px;width:16px;height:16px;
  border-radius:50%;background:var(--c-obstacle)}
.safety li::after{content:"";position:absolute;left:4.5px;top:10px;width:7px;height:4px;
  border-left:2px solid #fff;border-bottom:2px solid #fff;transform:rotate(-45deg)}

/* ----------------------------------------------------------- page hero --- */
.page-hero{background:var(--c);color:var(--on-c);padding:clamp(36px,4vw,58px) var(--gut);
  position:relative;overflow:hidden}
.page-hero::after{content:"";position:absolute;width:280px;height:280px;border-radius:50%;
  right:-90px;top:-120px;background:currentColor;opacity:.1}
.page-hero .crumb{font-size:14px;font-weight:700;margin-bottom:16px;opacity:.85}
.page-hero .crumb a:hover{text-decoration:underline}
.page-hero .crumb i{font-style:normal;margin:0 8px;opacity:.55}
.page-hero h1{max-width:17ch}
.page-hero p{margin-top:15px;font-size:var(--step-1);max-width:54ch;font-weight:500;opacity:.93}
.ph-grid{display:grid;grid-template-columns:1.15fr .85fr;gap:clamp(24px,3.5vw,50px);
  align-items:center;position:relative;z-index:1}
.ph-grid .pic{--ratio:16/10;border:3px solid var(--ink)}
@media(max-width:900px){.ph-grid{grid-template-columns:1fr}.ph-grid .pic{display:none}}

/* ------------------------------------------------------------- unit pg --- */
.unit{display:grid;grid-template-columns:minmax(0,1fr) 330px;
  gap:clamp(26px,3.5vw,52px);align-items:start}
.unit>div>.pic{--ratio:16/10;border:3px solid var(--ink)}
.unit h2{font-size:var(--step-2);margin:30px 0 14px}
.unit-side{background:#fff;border:2px solid var(--line);border-radius:var(--r);padding:24px;
  position:sticky;top:22px;display:flex;flex-direction:column;gap:11px}
.unit-side .price{font-size:var(--step-2);color:var(--ct)}
.unit-side>p{color:var(--ink-70);font-size:14.5px;font-weight:450;margin-bottom:6px}
.unit-side .btn{width:100%}
.specs{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;margin:26px 0 0}
.spec{background:#fff;border:2px solid var(--line);border-radius:var(--r-sm);padding:16px 18px}
.spec dt{font-size:11.5px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ct);margin-bottom:5px}
.spec dd{margin:0;font-family:var(--display);font-weight:600;font-size:16.5px}
@media(max-width:1000px){.unit{grid-template-columns:1fr}.unit-side{position:static}}
@media(max-width:520px){.specs{grid-template-columns:1fr}}

/* A unit's own photo strip, under its specs. Only the marquee has one so far. */
.ugal{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-top:26px}
.ugal .pic{--ratio:1/1;border:2px solid var(--line)}
@media(max-width:620px){.ugal{grid-template-columns:repeat(2,1fr)}}

/* ------------------------------------------------------------- gallery --- */
.gallery{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
.gallery .pic{--ratio:1/1}
.gallery a:nth-child(6n+1){grid-column:span 2}
.gallery a:nth-child(6n+1) .pic{--ratio:2/1}
@media(max-width:860px){.gallery{grid-template-columns:repeat(2,1fr)}}

/* ------------------------------------------------------------- contact --- */
.contact{background:var(--ink);color:#fff;position:relative;overflow:hidden}
.contact::after{content:"";position:absolute;width:320px;height:320px;border-radius:50%;
  left:-130px;bottom:-160px;background:#fff;opacity:.08}
.contact-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(28px,3.5vw,58px);
  align-items:start;position:relative;z-index:1}
.contact h2{max-width:15ch}
.contact .lede{color:#c8d6ea;margin-top:16px}
.contact-list{margin-top:26px;display:flex;flex-direction:column;gap:10px}
.contact-list a,.contact-list div{display:flex;align-items:center;gap:12px;
  padding:14px 20px;border-radius:var(--r-pill);background:rgba(255,255,255,.13);
  font-weight:700;font-size:16.5px}
.contact-list a:hover{background:rgba(255,255,255,.22)}
.contact-list svg{width:19px;height:19px;flex:none}
form{background:#fff;border-radius:var(--r);padding:26px;color:var(--ink)}
.fld{display:flex;flex-direction:column;gap:7px;margin-bottom:14px}
.fld label{font-size:13.5px;font-weight:800;color:var(--ink-70)}
.fld input,.fld textarea{padding:13px 15px;border:2px solid var(--line-strong);
  border-radius:var(--r-sm);font-size:16px;background:#fff;color:var(--ink);width:100%}
.fld input:focus,.fld textarea:focus{outline:3px solid var(--c-castle);outline-offset:1px;
  border-color:var(--c-castle)}
.fld textarea{resize:vertical;min-height:84px}
form .btn{width:100%;margin-top:6px}
/* Draft state: the form is not wired to Formspree yet. */
form .btn[disabled]{opacity:.5;cursor:not-allowed;box-shadow:0 2px 0 var(--ink)}
.form-note{margin-top:12px;font-size:14px;font-weight:500;color:var(--ink-70);
  background:#fff6db;border:2px solid #f2e2ac;border-radius:var(--r-sm);
  padding:12px 14px}
@media(max-width:900px){.contact-grid{grid-template-columns:1fr}}

/* -------------------------------------------------------------- footer --- */
footer{background:var(--paper-2);color:var(--ink-70);
  padding:clamp(44px,4.5vw,68px) var(--gut) 28px;font-size:15px;
  border-top:2px solid var(--line)}
.foot-top{display:grid;grid-template-columns:1.5fr 1fr 1fr;gap:34px}
.foot-col h4{font-family:var(--display);font-weight:600;font-size:15px;color:var(--ink);
  margin-bottom:13px}
.foot-col a{display:block;padding:5px 0;transition:color .14s}
.foot-col a:hover{color:var(--accent-text)}
.foot-top>div>p{max-width:36ch;font-weight:450;line-height:1.6;margin-top:14px}
.socials{display:flex;gap:10px;margin-top:18px}
.socials a{width:40px;height:40px;border:2px solid var(--line-strong);border-radius:50%;
  display:grid;place-items:center;transition:background .14s,border-color .14s,transform .14s}
.socials a:hover{background:var(--accent);border-color:var(--ink);color:var(--ink);
  transform:translateY(-2px)}
.socials svg{width:17px;height:17px}
.foot-bottom{margin-top:40px;padding-top:22px;border-top:2px solid var(--line);
  display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;font-size:14px}
.foot-bottom a{text-decoration:underline;text-underline-offset:2px}
.foot-bottom a:hover{color:var(--accent-text)}
@media(max-width:820px){.foot-top{grid-template-columns:1fr 1fr}}
@media(max-width:560px){.foot-top{grid-template-columns:1fr}}

/* ---------------------------------------------------------- action bar --- */
/* Mobile only. Replaces the floating bubbles: the two things a parent actually
   wants are a phone call and WhatsApp, so they get a real bar. */
.actionbar{display:none;position:fixed;left:0;right:0;bottom:0;z-index:80;
  background:rgba(255,253,247,.97);backdrop-filter:blur(8px);padding:10px 14px;
  gap:10px;border-top:2px solid var(--line-strong)}
.actionbar a{flex:1;display:flex;align-items:center;justify-content:center;gap:8px;
  padding:14px 10px;border-radius:var(--r-pill);font-weight:800;font-size:15px}
.actionbar .ab-call{background:var(--accent);color:var(--ink);border:2px solid var(--ink)}
.actionbar .ab-wa{background:#1eaf53;color:#fff}
.actionbar svg{width:18px;height:18px}
/* COLOUR ON THE TOP BAR AND PAGE (21 Oct 2026, Sam: the white header and page
   were too plain). Wherever the rail becomes a top bar, it is the logo blue
   with a yellow rule, the action bar matches, and the page behind the shelves
   is the hero's sky so the white cards sit on colour. The open drawer stays
   white so its links read. Desktop's sidebar is unchanged.
   The wave art is filled with --paper, so on sky it would draw a white stripe:
   it goes, and the masthead's bottom padding with it. */
@media(max-width:1100px){
  body{background:var(--sky)}
  .rail{background:var(--c-castle);border-bottom:4px solid #ffd23f;box-shadow:none}
  .rail .brand,.rail .burger{color:#fff}
  .rail.open .rail-body{background:#fff;margin:12px -20px -12px;padding:16px 20px 20px}
  .actionbar{background:var(--c-castle);border-top:3px solid #ffd23f}
  .mast{background:url("/assets/bunting.6c2d0f29.svg") repeat-x left -6px top -2px,var(--sky);
    padding-bottom:48px}
}
@media(max-width:1100px){.actionbar{display:flex}
  footer{padding-bottom:96px}}

/* Desktop keeps one WhatsApp button, bottom right, out of the rail's way. */
.wa-float{position:fixed;right:20px;bottom:20px;z-index:70;width:54px;height:54px;
  border-radius:50%;background:#1eaf53;color:#fff;display:grid;place-items:center;
  box-shadow:0 6px 22px rgba(20,19,16,.26);transition:transform .18s}
.wa-float:hover{transform:translateY(-4px) rotate(-6deg)}
.wa-float svg{width:27px;height:27px}
@media(max-width:1100px){.wa-float{display:none}}

/* -------------------------------------------------------------- motion --- */
/* Reveal is opt-in via the .js class set by an inline script in the head.
   Without JS, or if the script fails, everything renders visible. Content must
   never be hidden by a broken animation. */
.js [data-reveal]{opacity:0;transform:translateY(18px);
  transition:opacity .55s cubic-bezier(.2,.7,.3,1),transform .55s cubic-bezier(.2,.7,.3,1)}
@media(prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .track{scroll-behavior:auto}
  .js [data-reveal]{opacity:1!important;transform:none!important;transition:none}
  *{animation-duration:.01ms!important;transition-duration:.01ms!important}
}

/* ---------------------------------------------------------------- a11y --- */
:focus-visible{outline:3px solid var(--c-castle);outline-offset:2px;border-radius:4px}

.skip{position:absolute;left:-9999px;top:0;background:var(--ink);color:#fff;
  padding:12px 18px;z-index:100}
.skip:focus{left:0}
::selection{background:var(--accent);color:var(--ink)}
