/* ═══════════════════════════════════════════════════════════════════
   Bruda Club — final polish layer

   Loaded after style.css, enhancements.css, vibe.css and
   philosophy-effect.css, so everything in here wins without needing
   !important on rules that already exist elsewhere.

   Two jobs only:
     1. Style the components added in this pass (sunrise/sunset gallery,
        Bike Hub review category, the two Reset price cards, the Bruda
        service note).
     2. Responsive quality control — overflow, touch targets, stacking
        and rhythm fixes found while reviewing the existing pages.

   No new colours, fonts, radii or shadows: everything below comes from
   the tokens already defined in style.css :root.
   ═══════════════════════════════════════════════════════════════════ */


/* ═══════════════════════════════════════════════════════════
   0. TYPE SCALE & PROPORTIONS

   The site was set at a 16px root, and 204 of its font-size
   declarations sat below 15px. On a laptop that reads as small
   and cramped, which is the opposite of the premium, unhurried
   feel the rest of the design has.

   The fix is one line rather than 204: the theme puts *every*
   font size in rem and *every* padding, margin and gap in px
   (377 rem declarations are font-size, exactly one is spacing).
   So moving the root size scales the whole type system in
   proportion and leaves the layout grid untouched.

   16.5px on a phone up to 18.5px on a desktop. Phones were
   nearly right already; desktop gains about 15%.
   ═══════════════════════════════════════════════════════════ */
html{
  /* 16.5px at a 400px viewport, 18.5px from 1400px up. */
  font-size:clamp(16.5px, 15.7px + 0.2vw, 18.5px);
}

/* 0a. A floor for the smallest labels.
   Tags and ribbons go as low as 0.62rem, which is still only ~11px
   once scaled. 0.76rem with a hard 12.5px floor is the point where
   uppercase tracking stays readable.

   Only selectors that actually sit BELOW this are listed. The
   eyebrows at 0.78rem are already above it and are left alone —
   putting them here would have shrunk them. */
.rental-banner__tag,
.focus-card__tag,
.touring-card__tag,
.product-card__label,
.pricing-card__ribbon,
.svc-pkg__ribbon,
.visit-map__go,
.step-indicator__label{
  font-size:max(0.76rem, 12.5px);
}
/* vibe.css pins the currency buttons with !important. */
.price-switcher .price-switcher__btn{
  font-size:max(0.76rem, 12.5px) !important;
}
/* NOT .bw-progress-labels span itself: under 600px it is deliberately
   font-size:0 so the ::before can show a step number instead. Only the
   number gets the floor. */
.bw-progress-labels span::before{
  font-size:max(0.72rem, 12px);
}
/* Same floor for the eyebrow inside the rental block, which this
   stylesheet itself sets at 0.72rem further down. */
.rental-stack__head .base-eyebrow,
.rental-stack__head .rental-banner__tag,
.rental-stack__head .rental-eyebrow{
  font-size:max(0.76rem, 12.5px);
}

/* 0b. Headings should not run away at the new scale.
   The hero clamps were vw-driven with a high rem ceiling; on a
   wide screen that ceiling now lands near 100px. These caps keep
   the display type confident rather than shouty, and let long
   subpage headlines start smaller on a phone. */
.hero__title{
  font-size:clamp(2.3rem, 5.6vw, 4.6rem);
}
.page-hero__content h1{
  font-size:clamp(2.15rem, 6vw, 4.6rem);
}
.hero__subtitle,
.page-hero__content > p{
  font-size:clamp(1.02rem, 1.6vw, 1.25rem);
}

/* 0c. Measure. Prose is comfortable between roughly 60 and 75
   characters a line; several blocks had no cap at all and ran the
   full container width on a wide screen. */
.timeline-item p,
.faq-answer,
.reset-service-note p,
.copy-block p,
.legal-block p,
.legal-intro{
  max-width:68ch;
}
.copy-block--centered p,
.reset-service-note p{
  margin-left:auto;
  margin-right:auto;
}

/* 0d. Buttons keep their proportions.
   Padding was fixed in px against a font-size in rem, so the label
   grew while the button did not. In em both move together. */
.btn{
  padding:0.92em 2.1em;
  line-height:1.25;
}

/* 0e. Navigation is chrome, not reading matter.
   Left to grow with everything else, eight uppercase links plus a
   button start crowding the header around 1200px. It stays legible
   but does not chase the body scale. */
.site-nav a{
  font-size:max(0.82rem, 14px);
}
@media(min-width:900px){
  .site-nav{gap:clamp(18px, 1.9vw, 32px);}
}

/* 0f. More air between sections now that the type is larger.
   Type and whitespace have to grow together, otherwise bigger text
   just looks crowded. */
@media(min-width:900px){
  :root{--section-pad:116px 24px;}
}

/* 0g. iOS zooms the page in when a focused field is under 16px.
   Fields are the one place where a hard floor matters more than
   the scale. */
@media(max-width:768px){
  input,select,textarea{font-size:max(1rem, 16px);}
}

/* 0h. Review cards carry more text at the new scale. */
.cf-card{
  min-height:300px;
}

/* 0i. Section subtitles were capped at 560px, which is only about 47
   characters once the type grew. Too narrow reads as ragged and
   choppy; a character-based cap keeps the measure right at any scale. */
.section-header p{
  max-width:62ch;
}

/* 0j. A visible focus ring. Keyboard and switch users had nothing to
   follow; :focus-visible means it never shows up on a mouse click. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible{
  outline:2px solid var(--orange);
  outline-offset:3px;
  border-radius:4px;
}
/* On the dark hero and footer the orange ring needs a light halo to
   stay visible against a photo. */
.hero a:focus-visible,
.page-hero a:focus-visible,
.site-header a:focus-visible,
.site-footer a:focus-visible,
.closing-line a:focus-visible,
.final-cta a:focus-visible{
  outline-color:var(--gold);
  box-shadow:0 0 0 5px rgba(0,0,0,0.35);
}


/* ═══════════════════════════════════════════════════════════
   1. SUNRISES & SUNSETS
   The bc-slider from the gallery page, given a slightly wider
   frame because these are landscape sky shots.
   ═══════════════════════════════════════════════════════════ */
.sky-section .bc-slider--sky{
  max-width:1000px;
  margin:0 auto;
  border-radius:var(--radius-lg);
  box-shadow:var(--shadow-md);
}
.sky-section .bc-slider--sky .bc-slider__slide{
  aspect-ratio:16/10;
}
/* No crop rules here on purpose. .bc-slider--gallery already shows the
   whole photo (object-fit:contain over a blurred fill of itself), which
   is exactly why the sky never gets cut off in this frame. Forcing
   object-fit:cover would crop the horizon straight back out. */
@media(max-width:640px){
  .sky-section .bc-slider--sky{border-radius:var(--radius-md);}
}


/* ═══════════════════════════════════════════════════════════
   2. BIKE RENTAL — one column, read top to bottom
   Title, then the bikes, then the price, then the call to action.
   Used on the homepage and on the Bike Hub page.
   ═══════════════════════════════════════════════════════════ */
.rental-stack{
  max-width:900px;
  margin:0 auto;
  text-align:center;
}
.rental-stack__head{
  margin-bottom:28px;
}
/* Colour is inherited, never hard-coded: this block sits on the cream
   Bike Hub page AND on the dark green .touring-section of the homepage.
   Pinning it to --ink made the homepage heading dark green on dark
   green, which is what made it unreadable. */
.rental-stack__head h2,
.rental-stack__head h3{
  font-family:var(--font-display);
  font-size:clamp(1.5rem,3vw,2.2rem);
  color:inherit;
  text-transform:uppercase;
  margin:6px 0 10px;
}
.rental-stack__head p{
  color:inherit;
  opacity:0.82;
  max-width:560px;
  margin:0 auto;
}
.rental-stack__head .base-eyebrow,
.rental-stack__head .rental-banner__tag{
  display:block;
  font-size:0.72rem;
  font-weight:700;
  letter-spacing:0.18em;
  text-transform:uppercase;
  color:var(--orange-dark);
  margin:0;
}
.rental-stack__media{
  margin:0 auto 28px;
}
/* The two price lines sit side by side on a wide screen and stack
   underneath each other once there is no room. */
.rental-stack__prices{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  align-items:baseline;
  gap:10px 36px;
  margin-bottom:26px;
}
.rental-stack__prices .rental-price{margin:0;}
.rental-stack__cta{margin-bottom:8px;}
.rental-stack .rental-note{
  margin-top:18px;
  color:inherit;
  opacity:0.62;
  font-size:0.86rem;
}
/* The price label follows the surrounding colour too; the amount stays
   orange, which reads on both the cream and the dark green background. */
.rental-stack__prices .rental-price > span{
  color:inherit;
  opacity:0.72;
}

/* On the homepage this block follows straight after the Special
   Expedition card, which left the two touching. A hairline and real
   breathing room separate them. */
.touring-section .rental-stack{
  margin-top:80px;
  padding-top:56px;
  border-top:1px solid rgba(255,255,255,0.14);
}
@media(max-width:768px){
  .touring-section .rental-stack{margin-top:56px;padding-top:40px;}
}


/* ═══════════════════════════════════════════════════════════
   2a. MANIFESTO ON A SUNSET
   Fuck It / Do It / Be It now sits on a sunset photo, with the
   three explanatory paragraphs dropped. Instagram and a single
   Start Now button close it out.
   ═══════════════════════════════════════════════════════════ */
.manifesto-bg{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:center 40%;
  /* Low enough that the cream type keeps its contrast against the dark
     section colour underneath. */
  opacity:0.30;
  z-index:0;
  pointer-events:none;
}
.manifesto-section--photo{
  position:relative;
  overflow:hidden;
}
/* Without the paragraphs the three words can breathe and line up. */
.manifesto-section--photo .manifesto-part .manifesto-sub{
  margin-bottom:0;
}
.manifesto-section--photo .manifesto-grid{
  align-items:start;
}
.manifesto-cta{
  position:relative;
  z-index:1;
  margin-top:26px;
  display:flex;
  justify-content:center;
}
@media(max-width:800px){
  .manifesto-section--photo .manifesto-grid{gap:38px;}
  .manifesto-cta{margin-top:22px;}
}


/* ═══════════════════════════════════════════════════════════
   2b. WHERE TO FIND US
   Heading plus map, nothing else. The map used to share a
   two-column grid with a block of copy that has been removed.
   ═══════════════════════════════════════════════════════════ */
.visit-map--wide{
  max-width:960px;
  margin:0 auto;
}
/* The "Read All Reviews" link follows straight after the carousel, so it
   only needs closing space, not a full section's worth on both sides. */
.reviews-more{
  padding-top:0 !important;
}
.visit-map--wide iframe{
  min-height:420px;
}
@media(max-width:768px){
  .visit-map--wide iframe{min-height:300px;}
}


/* ═══════════════════════════════════════════════════════════
   2c. ADVENTURE — the touring film outside its old section
   The film used to sit inside the dark .touring-section. On the
   Adventure page it stands on the cream background instead.
   ═══════════════════════════════════════════════════════════ */
.touring-video-wrap{
  max-width:900px;
  margin:44px auto 0;
}
.touring-video-wrap .touring-video{
  margin:0;
  border-radius:var(--radius-lg);
  overflow:hidden;
  box-shadow:var(--shadow-md);
}
@media(max-width:640px){
  .touring-video-wrap{margin-top:32px;}
  .touring-video-wrap .touring-video{border-radius:var(--radius-md);}
}


/* ═══════════════════════════════════════════════════════════
   2d. ABOUT — the single support card
   vibe.css lays .support-links out as two columns, so the one
   remaining card was pinned to the left instead of centred.
   ═══════════════════════════════════════════════════════════ */
.support-links--single{
  grid-template-columns:minmax(0,360px) !important;
  justify-content:center;
  max-width:none !important;
}


/* ═══════════════════════════════════════════════════════════
   3. THE RESET — pricing
   Two cards: the nightly rate, and the 7-night rate at 20% off.
   ═══════════════════════════════════════════════════════════ */
.offer-grid--prices{
  grid-template-columns:1fr 1fr;
  gap:24px;
  max-width:860px;
  margin:0 auto;
  align-items:stretch;
}
/* Both cards start their content at the same height and push the closing
   note to the bottom. That keeps "Standard stay" level with "7-night
   Reset" and both prices on one line, even though only the second card
   carries an extra total. Centring the content vertically is what threw
   them out of line. */
.offer-grid--prices .pricing-card{
  position:relative;
  margin:0;
  max-width:none;
  height:100%;
  display:flex;
  flex-direction:column;
  justify-content:flex-start;
  padding:38px 28px 30px;
}
.offer-grid--prices .pricing-card__name{min-height:1.2em;}
.offer-grid--prices .pricing-card__item{min-height:1.6em;}
.offer-grid--prices .pricing-card__note{
  margin-top:auto;
  padding-top:18px;
}
.pricing-card--featured{
  border-color:var(--orange);
  box-shadow:var(--shadow-md);
}
.pricing-card__ribbon{
  position:absolute;
  top:-13px;
  left:50%;
  transform:translateX(-50%);
  background:var(--orange);
  color:#fff;
  font-size:0.68rem;
  font-weight:700;
  letter-spacing:0.14em;
  text-transform:uppercase;
  padding:6px 16px;
  border-radius:100px;
  white-space:nowrap;
}
.pricing-card__total{
  margin-top:10px;
  font-size:0.95rem;
  color:var(--ink-2);
}
.pricing-card__total .price-amount{
  font-family:var(--font-display);
  font-weight:700;
  color:var(--ink);
}
.pricing-cta{
  text-align:center;
  margin-top:36px;
}
/* The switcher sat inside the old single price card. Standing on its own
   above two cards it needs centring — and since vibe.css pins it to
   inline-flex, that has to come from the wrapper. */
.price-switcher-row{
  text-align:center;
  margin:0 0 32px;
}
.price-switcher-row .price-switcher{
  margin:0;
}

/* The one service note that replaced the add-on list. */
.reset-service-note{
  max-width:860px;
  margin:36px auto 0;
  padding:28px 32px;
  background:var(--card-bg);
  border:1px solid var(--border);
  border-left:3px solid var(--orange);
  border-radius:var(--radius-md);
  box-shadow:var(--shadow-sm);
}
.reset-service-note h3{
  font-family:var(--font-display);
  font-size:1.2rem;
  color:var(--ink);
  margin:0 0 8px;
}
.reset-service-note p{
  color:var(--ink-2);
  font-size:0.98rem;
  margin:0;
}

/* Homepage: the 7-night line under the nightly price. */
.reset-note--deal{
  margin:-14px 0 24px;
  font-size:0.92rem;
  color:var(--ink-2);
}
.reset-note--deal strong{
  font-family:var(--font-display);
  color:var(--orange-dark);
}

@media(max-width:760px){
  .offer-grid--prices{grid-template-columns:1fr;gap:28px;max-width:460px;}
  .offer-grid--prices .pricing-card{padding:32px 22px;}
  .reset-service-note{padding:24px 20px;margin-top:32px;}
}


/* ═══════════════════════════════════════════════════════════
   3b. CAROUSEL CONTROLS
   One treatment for every carousel: arrows always present, the
   position indicator kept quiet.
   ═══════════════════════════════════════════════════════════ */

/* The single-bike carousel is the reference: a 46px circle, dark and
   translucent, white icon, orange on hover, tucked 16px inside the
   frame. Every other carousel now uses exactly that. */
.cf-arrow,
.bc-slider__btn,
.bike-rail__btn,
.review-carousel .bike-rail__btn{
  display:flex !important;
  align-items:center;
  justify-content:center;
  visibility:visible;
  opacity:1;
  width:46px;
  height:46px;
  min-width:46px;
  min-height:46px;
  border-radius:50%;
  background:rgba(18,41,30,0.72);
  border:1px solid rgba(255,255,255,0.28);
  color:#fff;
  cursor:pointer;
  padding:0;
  z-index:5;
  box-shadow:none;
  transition:background .2s ease,transform .2s ease;
}
.cf-arrow:hover,
.bc-slider__btn:hover,
.bike-rail__btn:hover{
  background:var(--orange);
  border-color:rgba(255,255,255,0.4);
  color:#fff;
}
.bc-slider__btn--prev,.bike-rail__btn--prev{left:16px;}
.bc-slider__btn--next,.bike-rail__btn--next{right:16px;}
/* The review coverflow is wider than its card, so its arrows sit at the
   edge of the card rather than the edge of the section. */
.cf-arrow--prev{left:max(12px,calc(50% - 250px));}
.cf-arrow--next{right:max(12px,calc(50% - 250px));}
@media(max-width:600px){
  .cf-arrow{width:42px;height:42px;min-width:42px;min-height:42px;}
  .cf-arrow--prev{left:6px;}
  .cf-arrow--next{right:6px;}
  .bc-slider__btn--prev,.bike-rail__btn--prev{left:10px;}
  .bc-slider__btn--next,.bike-rail__btn--next{right:10px;}
}

/* Dots, again taken from the bike carousel: 8px, quiet, the current one
   an orange pill. The review dots used to be a 22px bar with a 3px
   radius, which read as a chunky progress bar. */
.cf-dot,
.bc-slider__dot,
.bike-dots button,
.reset-gallery__dots button{
  width:8px;
  height:8px;
  padding:0;
  border:0;
  border-radius:50%;
  cursor:pointer;
  background:rgba(23,48,31,0.28);
  transform:none;
  transition:background .25s ease,width .25s ease;
}
.cf-dot.is-active,
.bc-slider__dot.active,
.bike-dots button[aria-current="true"],
.reset-gallery__dots button[aria-current="true"]{
  width:22px;
  border-radius:999px;
  background:var(--orange);
  transform:none;
}
/* Over a photo the inactive dots need to be light to stay visible. */
.bc-slider--gallery .bc-slider__dot,
.reset-gallery__dots button,
.pc-outer .cf-dot{
  background:rgba(255,255,255,0.42);
}
.bc-slider--gallery .bc-slider__dot.active,
.reset-gallery__dots button[aria-current="true"],
.pc-outer .cf-dot.is-active{
  background:var(--orange);
}
/* Dots belong inside the frame, sitting on the photo. */
.bc-slider__dots{
  position:absolute;
  left:0;right:0;bottom:14px;
  display:flex;
  justify-content:center;
  align-items:center;
  gap:8px;
  z-index:5;
}


/* Every photo gallery gets the same frame as the bike carousel and the
   "Discover The Reset" gallery: one rounded card, one photo filling it,
   controls sitting on top. */
.bc-slider--gallery,
.bike-carousel,
.reset-gallery{
  border-radius:var(--radius-lg);
  overflow:hidden;
  box-shadow:var(--shadow-md);
}
/* The 16/9 frame and the contain-over-blur fill already match the bike
   carousel, so only the shell is touched here. */
@media(max-width:640px){
  .bc-slider--gallery,
  .bike-carousel,
  .reset-gallery{border-radius:var(--radius-md);}
}


/* ═══════════════════════════════════════════════════════════
   3c. LIGHTBOX
   Tapping a gallery photo opens it full screen. Behaviour lives
   in js/lightbox.js.
   ═══════════════════════════════════════════════════════════ */
.bc-slider--gallery .bc-slider__slide img,
.pc-photo img{
  cursor:zoom-in;
}
.bl-overlay{
  position:fixed;
  inset:0;
  z-index:100000;
  display:flex;
  align-items:center;
  justify-content:center;
  background:rgba(9,20,9,0.95);
  opacity:0;
  pointer-events:none;
  transition:opacity .25s ease;
}
.bl-overlay.is-open{
  opacity:1;
  pointer-events:auto;
}
.bl-figure{
  max-width:100%;
  max-height:100%;
  padding:12px;
  display:flex;
  align-items:center;
  justify-content:center;
}
.bl-overlay img{
  max-width:100%;
  max-height:88vh;
  max-height:88svh;
  width:auto;
  height:auto;
  object-fit:contain;
  display:block;
  border-radius:var(--radius-sm);
  -webkit-user-drag:none;
  user-select:none;
}
.bl-btn{
  position:absolute;
  display:flex;
  align-items:center;
  justify-content:center;
  width:48px;
  height:48px;
  border-radius:50%;
  border:1px solid rgba(255,255,255,0.22);
  background:rgba(0,0,0,0.45);
  color:#fff;
  cursor:pointer;
  padding:0;
  -webkit-tap-highlight-color:transparent;
  transition:background .2s ease,border-color .2s ease;
}
.bl-btn:hover{background:rgba(0,0,0,0.75);border-color:rgba(255,255,255,0.5);}
.bl-close{top:max(16px,env(safe-area-inset-top));right:16px;}
.bl-prev{left:16px;top:50%;transform:translateY(-50%);}
.bl-next{right:16px;top:50%;transform:translateY(-50%);}
.bl-count{
  position:absolute;
  bottom:max(20px,env(safe-area-inset-bottom));
  left:0;
  right:0;
  text-align:center;
  color:rgba(255,255,255,0.7);
  font-size:0.8rem;
  letter-spacing:0.08em;
  font-variant-numeric:tabular-nums;
}
/* Stop the page behind the overlay from scrolling. */
body.bl-lock{overflow:hidden;}
@media(max-width:600px){
  .bl-btn{width:44px;height:44px;}
  .bl-prev{left:8px;}
  .bl-next{right:8px;}
  .bl-close{right:10px;}
  .bl-figure{padding:6px;}
}


/* Honeypot field on both forms. Moved off-screen rather than
   display:none — a hidden-but-present field is what spam bots fill in,
   and some skip display:none outright. aria-hidden + tabindex="-1" keep
   it away from screen readers and the keyboard. */
.bruda-hp{
  position:absolute !important;
  left:-9999px;
  top:auto;
  width:1px;
  height:1px;
  overflow:hidden;
  pointer-events:none;
}


/* ═══════════════════════════════════════════════════════════
   3d. BOOKING WIZARD — step 1 on a phone
   The four choice cards squeezed an icon, a title, two lines of
   description and a price into one row. Adventure Ride and The
   Reset have the longest descriptions and broke the layout.
   On a phone the card is reduced to what actually decides the
   choice: icon, title, price, and who the price covers.
   ═══════════════════════════════════════════════════════════ */
@media(max-width:560px){
  .bw-entry-card{
    display:flex !important;
    align-items:center;
    gap:12px;
    padding:14px 15px;
    text-align:left;
    min-height:68px;
  }
  /* The description is what overflowed — it is not needed to choose. */
  .bw-entry-sub{display:none !important;}

  .bw-entry-card-body{flex:1 1 auto;min-width:0;}
  .bw-entry-title{
    display:flex;
    flex-direction:column;
    gap:2px;
    font-size:0.95rem;
    line-height:1.25;
  }
  .bw-entry-title small{
    font-size:0.68rem;
    font-weight:600;
    letter-spacing:0.04em;
    opacity:1;
  }

  /* style.css hides the price below 380px; here it is the whole point
     of the card, so it stays and stacks its "for 2 people" underneath. */
  .bw-entry-price{
    display:flex !important;
    flex-direction:column;
    align-items:flex-end;
    justify-content:center;
    gap:1px;
    margin-left:auto;
    flex:0 0 auto;
    font-size:0.95rem;
    line-height:1.2;
    text-align:right;
    white-space:nowrap;
  }
  .bw-entry-price small{
    font-size:0.65rem;
    line-height:1.2;
    white-space:nowrap;
  }
  .bw-entry-icon{flex:0 0 auto;width:40px;height:40px;}
}


/* ═══════════════════════════════════════════════════════════
   4. RESPONSIVE QUALITY CONTROL
   Fixes for things that only show up on a real phone.
   ═══════════════════════════════════════════════════════════ */

/* 4a. Nothing may push the page sideways. Media and embeds are the
       usual culprits, so they are capped explicitly rather than
       relying on the body's overflow-x:hidden to paper over it. */
img,video,iframe,svg,table{max-width:100%;}
iframe{border:0;}

/* 4b. Carousel dots were 6px squares — under the 24px minimum for a
       comfortable tap. The visible dot stays the same size; the hit
       area grows around it. */
.cf-dot,.bc-slider__dot{
  position:relative;
}
.cf-dot::after,.bc-slider__dot::after{
  content:"";
  position:absolute;
  top:50%;
  left:50%;
  transform:translate(-50%,-50%);
  width:24px;
  height:24px;
}
/* With a long review list the dot row could run off the edge. */
.cf-dots{
  flex-wrap:wrap;
  row-gap:8px;
  max-width:min(92vw,560px);
  margin:0 auto;
  padding:0 12px;
}

/* 4c. Carousel arrows: 44px is the minimum comfortable target, and on
       a phone they must not sit on top of the card text. */
.cf-arrow,.bc-slider__btn,.bike-rail__btn{
  min-width:44px;
  min-height:44px;
}
@media(max-width:600px){
  .cf-arrow{
    width:40px;height:40px;
    min-width:40px;min-height:40px;
    background:var(--card-bg);
    box-shadow:var(--shadow-sm);
  }
}

/* 4d. Long unbroken strings (emails, URLs, Vietnamese place names in a
       narrow column) must wrap instead of stretching their container. */
h1,h2,h3,h4,p,li,a,td,th,figcaption,blockquote{
  overflow-wrap:break-word;
}
/* Headings should still break on words, never mid-word. */
h1,h2,h3,h4{
  hyphens:none;
  text-wrap:balance;
}

/* 4e. Every tappable control gets a real target on touch devices. */
@media(hover:none){
  .site-nav a,
  .footer-nav a,
  .faq-question,
  .price-switcher__btn,
  .bw-cur-btn{
    min-height:44px;
    display:flex;
    align-items:center;
  }
  .footer-nav ul a{display:inline-flex;}
}

/* 4f. Section rhythm. --section-pad is 100px 24px, which is a lot of
       air on a 375px screen; the horizontal padding stays so text never
       touches the edge. */
@media(max-width:768px){
  .section,.reviews-section{padding:64px 20px;}
  .container{padding:0 20px;}
  .section-header{margin-bottom:32px;}
  .section-header h2{line-height:1.25;}
  .section-header p{font-size:0.98rem;}
}
@media(max-width:420px){
  .section,.reviews-section{padding:52px 16px;}
  .container{padding:0 16px;}
}

/* 4g. Buttons: full-width stacking on the narrowest screens reads as
       intentional, two half-width buttons squeezed side by side does not.
       (.hero__cta is left out on purpose — style.css hides it outright.) */
@media(max-width:480px){
  .final-cta__ctas,.pricing-cta{
    display:flex;
    flex-direction:column;
    align-items:stretch;
    gap:12px;
  }
  .final-cta__ctas .btn,.pricing-cta .btn{
    width:100%;
    text-align:center;
  }
}
/* 44px is the smallest button that is reliably tappable. */
.btn{min-height:44px;}

/* 4h. The workshop price table is the one wide block on the site.
       It scrolls inside its own box rather than the page. */
.svc-cat__list{
  overflow-x:auto;
  -webkit-overflow-scrolling:touch;
}
.svc-row{
  gap:16px;
}
.svc-row__name{
  min-width:0;
  overflow-wrap:break-word;
}

/* 4i. The photo mosaic went to two columns on tablet but kept a fixed
       180px row height, which cropped portrait shots hard. */
@media(max-width:600px){
  .photo-mosaic{
    grid-template-columns:1fr 1fr;
    grid-auto-rows:120px;
    gap:8px;
  }
  .photo-mosaic .span-2{grid-column:span 2;grid-row:span 2;}
}

/* 4j. Feature list and chip rows: keep the icon from shrinking and let
       the label wrap under it instead of overflowing. */
.feature-list li{align-items:flex-start;}
.feature-list li > span:last-child{padding-top:6px;}
.chip-row{flex-wrap:wrap;}

/* 4k. .map-embed already carries its own height; the homepage visit map
       is a bare iframe in a grid cell and collapses without one. */
@media(max-width:900px){
  .visit-map iframe{min-height:260px;}
}

/* 4l. Respect reduced-motion for the sliders added in this pass. */
@media (prefers-reduced-motion: reduce){
  .bc-slider__track,.cf-track{transition:none;}
}

/* 4m. Homepage "The Reset" on a phone: title, photo, description, price,
       call to action. The gallery is a sibling of the copy, so the copy
       block dissolves into the flex flow and its two halves are ordered
       around the gallery. */
@media(max-width:900px){
  .reset-section .reset-grid{
    display:flex;
    flex-direction:column;
    gap:26px;
  }
  .reset-section .reset-content{display:contents;}
  .reset-section .reset-content__head{order:1;}
  .reset-section .reset-gallery{order:2;}
  .reset-section .reset-content__body{order:3;}
  .reset-section .reset-content__head h2{margin-bottom:0;}
}


/* ═══════════════════════════════════════════════════════════
   5. SECTION-TO-FOOTER FADE
   Subpages ended on a full-bleed photo section that met the dark
   footer as a hard edge. The same soft transition the heroes use
   into the page now carries the last section into the footer.

   Subpages only. The homepage closes on .final-cta instead, and the
   fade broke that section, so it is deliberately left untouched
   there — do not add .final-cta to these selectors.
   ═══════════════════════════════════════════════════════════ */
.closing-line{
  position:relative;
}
.closing-line::after{
  content:"";
  position:absolute;
  left:0;
  right:0;
  bottom:0;
  height:180px;
  pointer-events:none;
  z-index:2;
  background:linear-gradient(to bottom,
              rgba(18,41,30,0) 0%,
              rgba(18,41,30,0.45) 55%,
              var(--bc-green-deep,#12291E) 100%);
}
/* The copy has to stay above the fade. */
.closing-line .container{
  position:relative;
  z-index:3;
}
/* Pages without their own wizard close on a button instead of just the
   brand line. */
.closing-line__cta{
  margin-top:26px;
  display:flex;
  justify-content:center;
}
/* Only where the fade actually runs into it does the footer drop its
   top hairline; on the homepage the footer keeps the border it had. */
body:has(.closing-line) .site-footer{
  border-top:none;
}
@media(max-width:768px){
  .closing-line::after{height:120px;}
}
