/* ==========================================================================
   Sausage Dog Sanctuary Hotel
   Built on the "layer C" landing-page system described in
   CONTEXT/FRONTEND-DESIGN-SYSTEM.md §11: tokens on :root, one CSS file,
   Recoleta + Inter, no framework, no build step.

   Decisions taken from the doc's open questions:
   - ONE green: #099078. Green is CTA-only (§2.4). Bars, badges, icons and
     emphasis use ink or surface, never green, so green always means "click me".
     ONE sanctioned exception, added on request: the review star tile, which
     is --sds-star #01b67a and matches the food site's rating device. It is a
     rating mark, never a control. Nothing else on the page may be green, and
     --sds-green itself is now referenced nowhere.
   - ONE dark: warm near-black #171614, the layer B ink (§2.2), NOT the layer C
     navy #14224b. That navy is cool and appears nowhere in the hotel's own
     material; the warm ink sits against the cool bands and the countryside
     photography, and leaves green as the only colour on the page.
   - ONE breakpoint: 768px (§4.5).
   - ONE gutter: 20px desktop / 16px mobile (§4.1).
   - Recoleta declared properly via @font-face, no !important (§3.1).
   ========================================================================== */

@font-face {
  font-family: 'Recoleta';
  src: url('../fonts/recoleta-medium.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* Inter, self-hosted. It used to come from fonts.googleapis.com, which put a
   render-blocking stylesheet on a third-party origin in front of every first
   paint: DNS, TLS and a round trip to googleapis, THEN the @font-face is
   discovered, THEN a second origin (gstatic) is opened for the file itself.
   Preconnect hints shaved the handshakes but could not remove the serial
   dependency. Self-hosted, the font is same-origin, discoverable in the
   preload scanner before CSS has parsed, and one fewer origin to trust.

   One variable file per subset covering 400-800 rather than five static
   instances: 48KB total for latin against ~90KB for the weights separately,
   and the intermediate weights become available for free. latin-ext carries
   the accented characters and is only fetched if the page actually uses one,
   which for English copy means never. */
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-latin.woff2') format('woff2');
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  src: url('../fonts/inter-latin-ext.woff2') format('woff2');
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
                 U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
                 U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --sds-green:       #099078;
  --sds-green-dark:  #1f6249;
  --sds-orange:      #eb8844;
  --sds-star:        #01b67a;   /* every review star, everywhere */
  --sds-orange-dark: #e36e1e;
  --sds-ink:         #171614;
  --sds-ink-deep:    #0e0d0c;
  --sds-text:        #1d1d1d;
  --sds-muted:       #6a6a72;

  /* Surfaces replace hairline borders. Separation is done with a change of
     ground, not a 1px grey line, because the line is what makes a page look
     like every other template.

     There is exactly ONE neutral ramp and it is cool, matched to the food
     site's #fafafc ground. It was warm before the bands moved, and half a
     move is the thing to avoid: warm and cool neutrals on one page read as
     two unrelated systems, which is what the tan nav pill and tan carousel
     arrows became once everything behind them went grey.

     Three steps, and interaction walks down them:
       surface       resting ground, bands, cards, ghost buttons
       surface-alt   hover, and the current nav item
       surface-deep  pressed, and controls that must read on two grounds
     Cards on white take surface; cards on a surface band flip to white. */
  --sds-surface:      #fafafc;
  --sds-surface-alt:  #f1f1f4;
  --sds-surface-deep: #e8e8ec;
  --sds-hero-bg:      #fafafc;
  --sds-radius:      999px;
  --sds-radius-card: 20px;

  /* ONE content width and ONE gutter for the whole site. Every band that
     holds content — header, hero, sections, footer — measures from these, so
     the left edge of the logo, the headline and every card line up exactly.
     Overriding either locally is what threw the alignment out before. */
  --sds-container:   1180px;
  --sds-gutter:      20px;

  --sds-serif: 'Recoleta', Georgia, 'Times New Roman', serif;
  --sds-sans:  'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

/* --------------------------------------------------------------- reset -- */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--sds-sans);
  font-size: 18px;
  line-height: 1.6;
  color: var(--sds-text);
  background: #fff;
  -webkit-font-smoothing: antialiased;
}

img, video, iframe { display: block; max-width: 100%; }
img { height: auto; }

/* Icons sit inside runs of text as often as they sit in flex rows, so they
   default to inline. Flex and grid parents override this on their own. */
svg { display: inline-block; vertical-align: middle; max-width: 100%; }

h1, h2, h3, h4 {
  font-family: var(--sds-serif);
  font-weight: 400;
  color: var(--sds-ink);
  margin: 0 0 16px;
  text-wrap: balance;
}

p { margin: 0 0 16px; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

a { color: inherit; }

/* §10: focus is only ever removed, never coloured over. */
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--sds-ink); outline-offset: 2px; }

.sds-visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.sds-skip {
  position: absolute; left: 20px; top: -60px; z-index: 100;
  background: var(--sds-ink); color: #fff; padding: 12px 20px;
  border-radius: 0 0 12px 12px; text-decoration: none; font-weight: 600;
  transition: top .15s ease;
}
.sds-skip:focus { top: 0; }

/* ---------------------------------------------------------- typography -- */

.sds-h1   { font-size: clamp(34px, 3.9vw, 54px); line-height: 1.06; letter-spacing: -0.015em; }
.sds-h2   { font-size: clamp(31px, 4.2vw, 50px); line-height: 1.1;  letter-spacing: -0.01em; }
.sds-h3   { font-size: clamp(22px, 2.6vw, 29px); line-height: 1.25; }
.sds-lede { font-size: clamp(17px, 1.8vw, 20px); color: var(--sds-text); }

/* §3.4: <em> in a heading marks emphasis. The doc renders it green; we do
   not, because §2.4's CTA-only rule outranks it. Italic Recoleta against
   the roman is a strong enough signal on its own. */
.sds-h1 em, .sds-h2 em, .sds-h3 em {
  font-style: italic;
  color: inherit;
}

.sds-eyebrow {
  font-family: var(--sds-sans);
  font-size: 13px; font-weight: 700; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--sds-ink);
  margin: 0 0 16px;
}

.sds-measure    { max-width: 52ch; }
.sds-measure-sm { max-width: 46ch; }
.sds-center     { text-align: center; }
.sds-center .sds-measure,
.sds-center .sds-measure-sm { margin-left: auto; margin-right: auto; }
.sds-center h2 { max-width: 20ch; margin-left: auto; margin-right: auto; }

/* ------------------------------------------------------------- layout -- */

.sds-container { width: 100%; max-width: var(--sds-container); margin: 0 auto; }
.sds-container--narrow { max-width: 960px; }

.sds-section         { padding: 72px var(--sds-gutter); background: #fff; }
.sds-section--tight  { padding: 48px var(--sds-gutter); }
.sds-section--hero   { padding: 56px var(--sds-gutter); background: var(--sds-hero-bg); }
.sds-section--surface  { background: var(--sds-surface); }
.sds-section--dark   { background: var(--sds-ink); color: #fff; }
.sds-section--dark h1,
.sds-section--dark h2,
.sds-section--dark h3 { color: #fff; }
.sds-section--dark .sds-lede { color: rgba(255,255,255,.78); }
.sds-section--dark .sds-eyebrow { color: #fff; opacity: .7; }

/* Cards default to --surface, which reads against white. On a surface band
   that pairing goes muddy, so the card takes white instead and the
   figure/ground relationship survives the swap. One rule, both directions. */
.sds-section--surface .sds-service,
.sds-section--surface .sds-addon,
.sds-section--surface .sds-review,
.sds-section--surface .sds-form,
.sds-section--surface .sds-planner,
.sds-section--surface .sds-faq details,
.sds-section--surface .sds-note,
.sds-section--surface .sds-vet-band__quote,
.sds-section--surface .sds-btn--ghost { background: #fff; }
.sds-section--surface .sds-addon__media { background: var(--sds-surface-alt); }
.sds-section--surface .sds-form .sds-field input,
.sds-section--surface .sds-form .sds-field select,
.sds-section--surface .sds-form .sds-field .sds-select__button,
.sds-section--surface .sds-form .sds-field .sds-date__button,
.sds-section--surface .sds-form .sds-field textarea { background: var(--sds-surface); }

/* ------------------------------------------------------------ buttons -- */

.sds-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  padding: 20px 38px; min-height: 48px;
  font-family: var(--sds-sans); font-size: 17px; font-weight: 700;
  line-height: 1; text-decoration: none; white-space: nowrap;
  color: #fff; background: var(--sds-ink);
  border: 0; border-radius: var(--sds-radius);
  cursor: pointer;
  transition: background .18s ease, transform .18s ease;
}
.sds-btn:hover {
  background: #33302b;
  transform: translateY(-1px);
}
/* The arrow is the only affordance on the button, so it carries the hover. */
.sds-btn__arrow {
  display: inline-block;
  transition: transform .22s cubic-bezier(.4, 0, .2, 1);
}
.sds-btn:hover .sds-btn__arrow { transform: translateX(3px); }
/* Press state. The button drops past its resting position rather than back
   to it, so the travel is felt on the way down as well as the way up.
   Snappier easing on the press than the release — 80ms in, 180ms out. */
.sds-btn:active {
  transform: translateY(1px);
  transition-duration: .08s;
}
.sds-btn--xl    { padding: 24px 46px; font-size: 19px; }
.sds-btn--block { width: 100%; }
.sds-btn--ghost { background: var(--sds-surface); color: var(--sds-ink); }
.sds-btn--ghost:hover { background: var(--sds-surface-alt); color: var(--sds-ink); }
.sds-btn--light {
  background: #fff; color: var(--sds-ink);
}
.sds-btn--light:hover { background: var(--sds-surface-alt); color: var(--sds-ink); }

/* These must come after the :hover rules above. A pressed button is also a
   hovered button, and both selectors carry the same specificity, so source
   order is the only thing deciding which one paints. */
.sds-btn--ghost:active { background: var(--sds-surface-deep); color: var(--sds-ink); }
.sds-btn--light:active { background: var(--sds-surface-deep); }

/* Header-only variant: a real 1px black border rather than a fill, and 600
   rather than the 700 the in-page CTAs use, so the one button that is always
   on screen sits quieter than the ones asking for the click. */
.sds-btn--outline {
  background: transparent;
  color: #000;
  border: 1px solid #000;
  font-weight: 600;
}
.sds-btn--outline:hover { background: #000; color: #fff; }
.sds-btn--outline:active { background: #000; color: #fff; }



/* --------------------------------------------------------------- header -- */

.sds-header {
  position: sticky; top: 0; z-index: 30;
  background: #fff;
}
/* Logo left, then nav and CTA grouped hard right. `margin-right: auto` on the
   logo does the pushing, so the nav stays immediately left of the button with
   no empty column between them — which a 1fr/auto/1fr grid would force. */
.sds-header__inner {
  display: flex; align-items: center; gap: 28px;
  max-width: calc(var(--sds-container) + var(--sds-gutter) * 2); margin: 0 auto; padding: 20px var(--sds-gutter);
}
.sds-header__logo { margin-right: auto; }

/* Sized by height, not width, so a horizontal lockup can be dropped in
   without touching this rule — see README. The mark carries a wordmark, so
   it needs real height to stay legible; 74px wide was illegible. */
.sds-header__logo img { height: 56px; width: auto; }

.sds-nav { display: flex; align-items: center; justify-content: center; gap: 4px; }

/* No underline. A rule pinned to the bottom of the padding box sits closer
   to the descenders than to the cap height, which reads as vertically
   unbalanced. A pill uses the symmetric padding that is already there, so
   hover and active states stay optically centred on the text. */
/* Text style matched to the food site's nav: Inter 500, near-black, no
   transform or tracking. Ours was 600 and muted grey, which read as faded
   next to it. Size is deliberately left at our own 16px. */
/* :not(.sds-btn) matters. `.sds-nav a` is (0,1,1) and `.sds-btn` is (0,1,0),
   so without it this rule wins over the button's own colour and the drawer's
   CTA renders ink-on-green instead of white-on-green. */
.sds-nav a:not(.sds-btn) {
  font-size: 16px; font-weight: 500; text-decoration: none;
  color: var(--sds-ink);
  padding: 9px 14px; border-radius: var(--sds-radius);
  transition: background-color .18s ease;
}
@media (hover: hover) {
  .sds-nav a:not(.sds-btn):hover { background: var(--sds-surface-alt); }
}
/* Press deepens the pill one step past hover, so a click on an already
   hovered item still registers as a change. Hover and the current item share
   a step: hovering makes an item look like the one you are on, and the 600
   weight is what tells them apart. */
.sds-nav a:not(.sds-btn):active { background: var(--sds-surface-deep); transition-duration: .08s; }
.sds-nav a:not(.sds-btn)[aria-current="page"] { font-weight: 600; background: var(--sds-surface-alt); }

.sds-header__cta { display: flex; align-items: center; justify-content: flex-end; gap: 12px; }
.sds-header__cta .sds-btn { padding: 15px 26px; font-size: 16px; }

/* The nav carries its own CTA for the mobile drawer. On desktop the header's
   own button is the one on show, so this copy stays hidden. */
.sds-nav .sds-btn { display: none; }

.sds-burger {
  display: none; width: 46px; height: 46px; padding: 0;
  background: none; border: 0; border-radius: 12px;
  cursor: pointer; color: var(--sds-ink);
  transition: background-color .18s ease;
}

/* Two bars, not three. On open they travel to the centre and cross, which is
   only possible because each bar is its own element — an icon-swap cannot be
   tweened. Transform-only, so it stays on the compositor. */
/* Every number here is whole, deliberately. An 11px box flex-centred in a
   46px button left an 17.5px offset, and 1.5px bars are 4.5 device pixels at
   dpr 3 — so one bar rounded up and the other down and the bottom line
   painted visibly thicker than the top. 10px in 46 centres at exactly 18,
   and 1px bars are crisp at every pixel ratio. */
.sds-burger__bars { position: relative; display: block; width: 22px; height: 10px; }
.sds-burger__bars i {
  position: absolute; left: 0; right: 0; height: 1px;
  background: currentColor; border-radius: 2px;
  transition: transform .4s cubic-bezier(.4, 0, .2, 1);
}
.sds-burger__bars i:first-child { top: 0; }
.sds-burger__bars i:last-child  { bottom: 0; }
/* The travel is (box centre - bar centre), so both strokes land on the same
   line and the X crosses at its middle: 5 - 0.5 = 4.5. Recompute if either
   the box height or the bar height changes. */
.sds-burger[aria-expanded="true"] .sds-burger__bars i:first-child {
  transform: translateY(4.5px) rotate(45deg);
}
.sds-burger[aria-expanded="true"] .sds-burger__bars i:last-child {
  transform: translateY(-4.5px) rotate(-45deg);
}
@media (hover: hover) {
  .sds-burger:hover { background: var(--sds-surface-alt); }
}
.sds-burger:active { background: var(--sds-surface-deep); transition-duration: .08s; }
.sds-burger svg { margin: 0 auto; }
.sds-burger__close { display: none; }
.sds-burger[aria-expanded="true"] .sds-burger__open  { display: none; }
.sds-burger[aria-expanded="true"] .sds-burger__close { display: block; }

/* ----------------------------------------------------------------- hero -- */

.sds-hero {
  position: relative;
  min-height: 620px;
  display: flex; align-items: center;
  padding: 80px var(--sds-gutter);
  background-color: var(--sds-hero-bg);
  background-image: linear-gradient(rgba(20,18,16,.42), rgba(20,18,16,.42)),
                    url('../img/hero-home.webp');
  background-size: cover;
  background-position: center;
}
.sds-hero__inner { max-width: var(--sds-container); margin: 0 auto; width: 100%; }
.sds-hero__card { max-width: 640px; color: #fff; }

/* Split hero: copy left, the This Morning feature right. The press
   appearance is the hotel's strongest proof, so it sits above the fold
   rather than a third of the way down the page.

   This variant carries NO background photo. A 16:9 video still on top of a
   busy aerial shot is a photo on a photo — both fight and neither wins. On
   flat grey the video is the only image above the fold, so it reads as the
   subject. The aerial shot gets its own full-bleed band directly below,
   where nothing covers it. */
.sds-hero--split {
  background-image: none;
  background-color: var(--sds-surface);
  min-height: 0;
  padding: 72px var(--sds-gutter);
}
/* The video is the proof on this page, so it gets the larger column and the
   hero runs wider than the standard 1180 container to give it room without
   squeezing the headline into a narrow measure. */
.sds-hero--split .sds-hero__inner {
  display: grid; grid-template-columns: 1fr 1.1fr;
  gap: 56px; align-items: center;
}
.sds-hero--split .sds-hero__card { color: var(--sds-text); }
.sds-hero--split .sds-hero__card h1 { color: var(--sds-ink); }
.sds-hero--split .sds-hero__card .sds-eyebrow { color: var(--sds-ink); opacity: 1; }
.sds-hero--split .sds-hero__card p { color: var(--sds-text); }
/* .sds-hero .sds-trust-tags sets white and is declared later in this file,
   so this needs the extra class to win the tie rather than relying on order. */
.sds-hero.sds-hero--split .sds-trust-tags { color: var(--sds-ink); }

.sds-hero__feature { color: var(--sds-ink); }
/* Sits under the video as a caption rather than a heading over it. */
.sds-hero__feature-label {
  margin: 16px 0 0;
  font-size: 13px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
  color: var(--sds-muted);
}

.sds-hero__card h1 { color: #fff; }
.sds-hero__card .sds-eyebrow { color: #fff; opacity: .85; }
.sds-hero__card p {
  font-size: clamp(16px, 2vw, 20px);
  color: rgba(255,255,255,.92);
  max-width: 46ch;
  margin-bottom: 28px;
}

/* Compact hero for inner pages. */
.sds-hero--inner {
  min-height: 380px;
  /* Fallback only. Pages that have their own photograph overwrite this with
     an inline background-image (see HERO_OVERLAY in build.py) — inline is
     the only form whose relative url() resolves correctly both off a server
     and when the files are opened straight from disk. Keep this gradient and
     HERO_OVERLAY the same. */
  background-image: linear-gradient(rgba(20,18,16,.5), rgba(20,18,16,.5)),
                    url('../img/hero-inner.webp');
  text-align: center;
}
.sds-hero--inner .sds-hero__card { max-width: 720px; margin: 0 auto; text-align: center; }
.sds-hero--inner .sds-hero__card p { margin-left: auto; margin-right: auto; }

/* ------------------------------------------------------------- marquee --

   Two identical groups in one track, separated by the same gap used between
   logos, so the rhythm is unbroken across the seam.

   The loop maths, with G = one group's width and g = the gap:
     track width W = 2G + g          (two groups plus the gap between them)
     one period    = G + g           (group 2 must travel to group 1's start)
     G = (W - g) / 2
     G + g = (W + g) / 2 = 50% of W + g/2
   Hence the translate below. Using a bare -50% ignores the inter-group gap and
   leaves a visible jump every cycle, which is what the first version did.

   Every logo also carries explicit width/height attributes, so the track
   measures correctly before the images decode — a lazy-loaded, unsized image
   contributes zero width and desynchronises the loop on first pass. */

.sds-marquee {
  --marquee-gap: 72px;
  --marquee-duration: 45s;
  overflow: hidden; padding: 34px 0 38px; background: #fff;
}
.sds-marquee__label {
  text-align: center; margin: 0 0 24px;
  font-size: 13px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
  color: var(--sds-muted);
}
.sds-marquee__track {
  display: flex; width: max-content; gap: var(--marquee-gap);
  animation: sds-marquee var(--marquee-duration) linear infinite;
  will-change: transform;
}
.sds-marquee__group {
  display: flex; align-items: center; gap: var(--marquee-gap);
}
/* Height comes from the inline style per logo; width follows the aspect. */
.sds-marquee img {
  flex: none; width: auto;
  filter: grayscale(1); opacity: .6;
}

@keyframes sds-marquee {
  to { transform: translateX(calc(-50% - var(--marquee-gap) / 2)); }
}

@media (hover: hover) {
  .sds-marquee:hover .sds-marquee__track { animation-play-state: paused; }
}
@media (prefers-reduced-motion: reduce) {
  .sds-marquee__track { animation: none; }
  .sds-marquee { overflow-x: auto; }
}
@media (max-width: 768px) {
  .sds-marquee { --marquee-gap: 44px; --marquee-duration: 32s; }
}

/* ---------------------------------------------------------- trust tags -- */

.sds-trust-tags {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px 28px;
  margin: 0; padding: 0; list-style: none;
}
.sds-trust-tags li {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 16px; font-weight: 600;
}
.sds-trust-tags svg { flex: none; width: 18px; height: 18px; }
.sds-hero .sds-trust-tags { margin-top: 28px; color: #fff; }

/* The rating line is an eyebrow, not a heading — it sat too loud at the
   standard 13px/.2em. */
/* ------------------------------------------------------- rating badge --
   The food site's tile star: a rounded square with the star knocked out of
   it. Two identical rows are stacked — a muted one underneath and a filled
   one on top, clipped to (rating / 5) — so any fraction renders correctly
   without needing separate half-star artwork.

   Every rating on the site draws from --sds-star, so the badge, the review
   cards, the hero quotes and the vet band cannot drift apart. */
.sds-rating {
  --sds-rating-fill: var(--sds-star);
  display: inline-flex; align-items: center; gap: 10px;
  margin: 0 0 18px;
}
.sds-rating__stars { position: relative; display: inline-block; line-height: 0; }
.sds-rating__row { display: inline-flex; gap: 2px; }
.sds-rating__row--empty { color: var(--sds-surface-deep); }
.sds-rating__row--full {
  position: absolute; inset: 0;
  color: var(--sds-rating-fill);
  overflow: hidden; white-space: nowrap;
  width: calc(var(--rating-value, 5) / 5 * 100%);
}
/* The star is a hole in the tile, not a shape on top of it, so whatever is
   behind the SVG shows through it. Each tile therefore carries its own white
   plate: the tile art covers the full 24x24 canvas, so the only place that
   plate can show is the star itself. That is what lets these sit straight on
   the grey band, and on the grey review cards, with no white panel around
   them. The inset ring is the tile's own colour over its outer pixel, so the
   plate cannot show as a hairline where the path antialiases at the edge. */
.sds-star {
  width: 20px; height: 20px; flex: none; display: block;
  background: #fff;
  box-shadow: inset 0 0 0 1px currentColor;
}

.sds-rating__count {
  font-family: var(--sds-sans);
  font-size: 14px; font-weight: 600; letter-spacing: 0;
  color: var(--sds-muted); text-transform: none;
}
/* Reads as one line with the tiles rather than wrapping under them on a
   narrow card. */
.sds-rating { flex-wrap: wrap; row-gap: 4px; }

/* ------------------------------------------------------- hero carousel --
   Slides are stacked in a grid cell and cross-faded, so the stage keeps the
   height of the tallest and nothing below it shifts as they rotate. */

/* Arrows straddle the card's left and right edges — half on the white, half
   on the grey band behind it. Absolute rather than flex so they overlap the
   box instead of stealing width from the quote. */
.sds-quotes {
  position: relative;
  margin-top: 32px; max-width: 46ch;
}
.sds-quotes__card {
  background: #fff; border-radius: var(--sds-radius-card);
  padding: 22px 26px;
}
.sds-quotes__stage { display: grid; }
.sds-quote {
  grid-area: 1 / 1; margin: 0;
  opacity: 0; visibility: hidden;
  transform: translateY(6px);
  transition: opacity .5s ease, transform .5s ease, visibility .5s;
}
.sds-quote.is-active { opacity: 1; visibility: visible; transform: none; }

/* .sds-hero__card p is (0,2,1) and .sds-stars-row is (0,1,0), so the hero's
   muted body colour was winning and greying the stars out. Matching on three
   classes settles it. */
.sds-hero__card .sds-quote .sds-stars-row {
  gap: 2px;                      /* matches the hero badge directly above it */
  margin-bottom: 0;              /* the head row carries the spacing now */
  color: var(--sds-star);
}
.sds-hero__card .sds-quote .sds-stars-row .sds-star { width: 16px; height: 16px; }

/* Rating and attribution are one credential, so they share a line. */
.sds-quote__head {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 10px;
}
.sds-quote__by { font-size: 14px; font-weight: 700; color: var(--sds-muted); }

/* Clamped to two lines so every slide is the same height and the stage below
   the CTA cannot jump as the carousel rotates. site.js also cuts the text to
   roughly two lines on a word boundary; this is the hard stop for narrow
   viewports, where 100 characters would still run to three. */
.sds-quote blockquote {
  margin: 0; font-size: 16px; line-height: 1.5; color: var(--sds-text);
  display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 2; line-clamp: 2;
  overflow: hidden;
}


.sds-quotes__arrow {
  position: absolute; top: 50%; z-index: 2;
  transform: translateY(-50%);
  width: 34px; height: 34px; padding: 0; border: 0; border-radius: 50%;
  /* Reads against both grounds it straddles: the white card on one half, the
     grey hero band on the other. White would vanish into the card, and the
     band's own #fafafc would vanish into the band. Same step as the pressed
     state, which is the other place a control has to read on two grounds. */
  background: var(--sds-surface-deep); color: var(--sds-ink); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background-color .18s ease, color .18s ease;
}
.sds-quotes__arrow[data-q-prev] { left: -17px; }
.sds-quotes__arrow[data-q-next] { right: -17px; }
@media (hover: hover) {
  .sds-quotes__arrow:hover { background: var(--sds-ink); color: #fff; }
}
.sds-quotes__arrow:active { background: var(--sds-ink); color: #fff; }

/* ------------------------------------------------- alternating row (§4.3) */

.sds-row {
  display: grid; grid-template-columns: 1fr 1fr; gap: 64px; align-items: center;
}
.sds-row + .sds-row { margin-top: 72px; }
.sds-row--reverse .sds-row__image   { order: 2; }
.sds-row--reverse .sds-row__content { order: 1; }
.sds-row__image img {
  width: 100%; border-radius: var(--sds-radius-card);
  aspect-ratio: 1 / 1; object-fit: cover;
}
/* Landscape source: a square crop of a 2:1 aerial throws away most of the
   property, which is the one thing this row exists to show. */
.sds-row__image--wide img { aspect-ratio: 4 / 3; }

/* --------------------------------------------------------- press strip -- */

.sds-press { text-align: center; }
.sds-press__label {
  font-size: 13px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
  color: var(--sds-muted); margin: 0 0 24px;
}
.sds-press__logos {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 28px 44px; margin: 0; padding: 0; list-style: none;
}
.sds-press__logos img {
  width: auto; opacity: .62;
  filter: grayscale(1);
  transition: opacity .18s ease;
}
.sds-press__logos img:hover { opacity: 1; }

/* ------------------------------------------------------- service cards -- */

.sds-services {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 32px;
}
.sds-service {
  display: flex; flex-direction: column;
  background: var(--sds-surface);
  border-radius: var(--sds-radius-card); overflow: hidden;
}
.sds-service__media { position: relative; }
.sds-service__media img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.sds-service__flag {
  position: absolute; top: 16px; left: 16px;
  padding: 6px 14px; border-radius: var(--sds-radius);
  background: var(--sds-surface-alt); color: var(--sds-ink);
  font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
}
.sds-service__body { padding: 28px; display: flex; flex-direction: column; flex: 1; }
.sds-service__body h3 { margin-bottom: 8px; }
.sds-service__price {
  font-family: var(--sds-serif);
  font-size: 34px; color: var(--sds-ink); margin: 0 0 4px;
}
.sds-service__price small {
  font-family: var(--sds-sans);
  display: block; font-size: 15px; font-weight: 500; color: var(--sds-muted);
  margin-top: 4px;
}
.sds-service__meta {
  font-size: 16px; color: var(--sds-text);
  margin: 0 0 24px;
}
.sds-service .sds-btn { margin-top: auto; }

/* --------------------------------------------------------------- add-on --
   Teeth cleaning lives here: an extra you add to a stay, not a headline
   service. Price is deliberately absent until it is confirmed. */

.sds-addon {
  display: grid; grid-template-columns: 0.85fr 1.15fr;
  border-radius: 28px; overflow: hidden;
  background: var(--sds-surface);
}
.sds-addon__media {
  position: relative; margin: 0; overflow: hidden;
  background: var(--sds-surface-alt);
  aspect-ratio: 1 / 1;
}
/* The source is a square with the Before/After pair stacked vertically and
   the labels baked into the artwork. A vertical crop would slice those labels
   off, so the panel is pinned to 1:1 and the image is never cropped on that
   axis. */
.sds-addon__media img {
  width: 100%; height: 100%; object-fit: cover; object-position: center;
  position: absolute; inset: 0;
}

.sds-addon__icon {
  width: 120px; height: 120px; border-radius: 50%;
  background: #fff; color: var(--sds-ink);
  display: flex; align-items: center; justify-content: center;
}
.sds-addon__icon svg { width: 56px; height: 56px; }
.sds-addon__pill {
  position: absolute; top: 20px; left: 20px;
  padding: 6px 14px; border-radius: var(--sds-radius);
  background: var(--sds-orange); color: #fff;
  font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
}
.sds-addon__body { padding: 40px; }
.sds-addon__body h3 { margin-bottom: 12px; }
.sds-addon__list {
  margin: 0 0 28px; padding: 0; list-style: none;
  display: grid; gap: 10px;
}
.sds-addon__list li {
  display: flex; align-items: flex-start; gap: 10px;
  font-size: 16px; color: var(--sds-text);
}
.sds-addon__list svg { flex: none; width: 20px; height: 20px; color: var(--sds-ink); margin-top: 2px; }

/* ------------------------------------------------------- amenity grid -- */

.sds-routine {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 44px 32px;
}
.sds-routine__item { text-align: center; }
.sds-routine__icon {
  width: 80px; height: 80px; margin: 0 auto 20px;
  border-radius: 50%; background: #fff; color: var(--sds-ink);
  display: flex; align-items: center; justify-content: center;
}
.sds-routine__icon svg { width: 34px; height: 34px; }
.sds-routine__item h3 { font-size: 23px; margin-bottom: 10px; }
.sds-routine__item p { font-size: 16px; color: var(--sds-text); }

/* ---------------------------------------------------------------- rates --
   The pricing page. Same rules as everything else: cards take --sds-surface
   on white and flip to white on a surface band, no hairlines, no shadows.

   The ex-VAT figure is the headline because it is the number Hannah and the
   team quote on the phone, but the inclusive figure sits directly under it in
   full contrast — it is what the customer actually pays, so it is not allowed
   to fade into the unit line. */

.sds-rates { display: grid; grid-template-columns: repeat(2, 1fr); gap: 32px; }

.sds-rate {
  display: flex; flex-direction: column;
  background: var(--sds-surface);
  border-radius: var(--sds-radius-card);
  padding: 36px;
}
.sds-rate__flag {
  align-self: flex-start;
  padding: 6px 14px; margin-bottom: 20px; border-radius: var(--sds-radius);
  background: var(--sds-surface-alt); color: var(--sds-ink);
  font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
}
.sds-rate h3 { margin-bottom: 14px; }
.sds-rate__price {
  font-family: var(--sds-serif);
  font-size: 54px; line-height: 1; color: var(--sds-ink);
  margin: 0 0 20px;
}
.sds-rate__price small {
  font-family: var(--sds-sans);
  display: block; margin-top: 12px;
  font-size: 15px; font-weight: 500; line-height: 1.5; color: var(--sds-muted);
}
.sds-rate__price small b { display: block; font-weight: 600; color: var(--sds-text); }
.sds-rate__meta { font-size: 16px; margin: 0 0 24px; }
.sds-rate .sds-btn { margin-top: auto; }

/* Every modifier to a headline rate, in one list. Three columns so the money
   ends up in a single right-aligned run and the page can be scanned by price
   alone. */
.sds-extras { margin: 0; padding: 0; list-style: none; display: grid; gap: 16px; }
/* Placed cell by cell rather than nested, so the note and the price can be
   moved to their own full-width rows on a phone. Wrapped in a div they would
   be stuck in the 227px column left over beside the icon. */
.sds-extra {
  display: grid; grid-template-columns: auto 1fr auto; gap: 4px 26px;
  align-items: center;
  background: #fff; border-radius: 18px; padding: 24px 28px;
}
.sds-extra__icon {
  grid-column: 1; grid-row: 1 / span 2;
  width: 54px; height: 54px; border-radius: 50%;
  background: var(--sds-surface); color: var(--sds-ink);
  display: flex; align-items: center; justify-content: center;
}
.sds-extra h3 { grid-column: 2; grid-row: 1; font-size: 21px; margin: 0; }
.sds-extra__note {
  grid-column: 2; grid-row: 2;
  font-size: 15px; color: var(--sds-muted); margin: 0;
}
.sds-extra__price {
  grid-column: 3; grid-row: 1 / span 2;
  font-family: var(--sds-serif); font-size: 30px; line-height: 1.1;
  color: var(--sds-ink); margin: 0; text-align: right;
}
.sds-extra__price small {
  font-family: var(--sds-sans);
  display: block; margin-top: 4px; white-space: nowrap;
  font-size: 14px; font-weight: 500; color: var(--sds-muted);
}

/* --------------------------------------------------- holiday planner --
   The cards above answer "what is one night?". People arrive with a
   holiday rather than a night, so this answers "what is a fortnight, with
   two of them, one entire, over Christmas?".

   Two panels: controls on the surface ground, the answer on ink. The
   money is the one thing on this page that must be findable at arm's
   length, so it gets the dark panel and the serif at 54px, the same size
   as the headline rates it is built from. */
.sds-planner__head { margin: 72px 0 32px; }

/* The two panels carry the corners themselves. The obvious way to round a
   two-tone card is overflow:hidden on the parent, but that also clips the
   dropdown lists, which have to escape the card to be any use. */
.sds-planner {
  display: grid; grid-template-columns: 1.1fr .9fr;
  background: var(--sds-surface);
  border-radius: var(--sds-radius-card);
}
.sds-planner__controls {
  padding: 36px;
  border-radius: var(--sds-radius-card) 0 0 var(--sds-radius-card);
}
.sds-planner__label {
  display: block; font-size: 15px; font-weight: 600; color: var(--sds-ink);
}
.sds-planner__count {
  font-family: var(--sds-serif); font-size: 40px; line-height: 1;
  color: var(--sds-ink); margin: 10px 0 18px;
}
.sds-planner__count b { font-weight: 400; }
.sds-planner__count span { font-size: 22px; color: var(--sds-muted); }

/* accent-color rather than a rebuilt track: the native control is already
   accessible, keyboard-operable and correctly sized for touch, and every
   hand-built slider on the web is worse at all three. Ink, not green:
   green on this site means "click me", and this is a control. */
.sds-planner__slider {
  -webkit-appearance: auto; appearance: auto;
  width: 100%; margin: 0; accent-color: var(--sds-ink);
  height: 28px; cursor: grab;
}
.sds-planner__slider:active { cursor: grabbing; }
.sds-planner__slider:focus-visible { outline: 2px solid var(--sds-ink); outline-offset: 4px; }

.sds-planner__presets {
  display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px;
}
.sds-planner__presets button {
  min-width: 48px; min-height: 40px; padding: 0 14px;
  font-family: inherit; font-size: 15px; font-weight: 600;
  color: var(--sds-ink); background: #fff;
  border: 0; border-radius: var(--sds-radius); cursor: pointer;
  transition: background-color .18s ease, color .18s ease;
}
@media (hover: hover) {
  .sds-planner__presets button:hover { background: var(--sds-surface-deep); }
}
.sds-planner__presets button[aria-pressed="true"] {
  background: var(--sds-ink); color: #fff;
}

/* end, not stretch: a label that wraps to two lines would otherwise push
   its own select down and break the row of controls out of line. */
.sds-planner__fields {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px;
  align-items: end; margin-top: 28px;
}
.sds-planner__fields .sds-field { margin-bottom: 0; }
.sds-planner__fields .sds-field label { font-size: 14px; }
/* background-color, not the background shorthand: the shorthand resets
   background-image and takes the chevron data URI down with it, leaving a
   select that looks like a read-only text box. */
.sds-planner__fields .sds-field select,
.sds-planner__fields .sds-select__button { background-color: #fff; font-size: 16px; }

/* A chip, not a tick box. The native checkbox is the wrong shape for this
   page: square, system-blue by default, and sized by the OS rather than by
   the type around it. So the input stays for the semantics and the tab order
   and is taken off screen, and the label is the control.

   On is the same ink fill the preset pills use, so "switched on" looks the
   same everywhere in the planner. :has drives the fill; where it is missing
   the chip stays white and the tick still lands, so the state is never
   ambiguous, only quieter. */
.sds-planner__toggle {
  grid-column: 1 / -1; justify-self: start;
  display: inline-flex; align-items: center; gap: 12px;
  padding: 9px 20px 9px 9px; border-radius: var(--sds-radius);
  background: #fff; color: var(--sds-ink);
  font-size: 16px; font-weight: 500; line-height: 1.35; cursor: pointer;
  -webkit-user-select: none; user-select: none;
  transition: background-color .18s ease, color .18s ease;
}
.sds-planner__toggle input {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.sds-planner__toggle-mark {
  display: flex; align-items: center; justify-content: center;
  flex: none; width: 28px; height: 28px; border-radius: 50%;
  background: var(--sds-surface-deep); color: transparent;
  transition: background-color .18s ease, color .18s ease;
}
.sds-planner__toggle-mark svg { width: 15px; height: 15px; }
/* The tick draws itself on rather than appearing, and the disc pops once.
   Both are keyed to :checked, so the feedback belongs to the state change
   and not to the click: toggling by keyboard animates identically. 24 is
   the length of the checkmark polyline, rounded up. */
.sds-planner__toggle-mark svg polyline {
  stroke-dasharray: 24; stroke-dashoffset: 24;
}
.sds-planner__toggle input:checked ~ .sds-planner__toggle-mark svg polyline {
  animation: sds-tick .3s cubic-bezier(.2, .8, .3, 1) .04s forwards;
}
.sds-planner__toggle input:checked ~ .sds-planner__toggle-mark {
  animation: sds-pop .34s cubic-bezier(.2, .8, .3, 1);
}
@keyframes sds-tick { to { stroke-dashoffset: 0; } }
@keyframes sds-pop {
  0%   { transform: scale(.8); }
  55%  { transform: scale(1.09); }
  100% { transform: scale(1); }
}
/* The line the chip adds to the bill slides in from where the eye already
   is, rather than the panel silently growing a row. */
.sds-planner__lines li.is-new {
  animation: sds-line-in .34s cubic-bezier(.2, .8, .3, 1);
}
@keyframes sds-line-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
.sds-planner__out-num.is-bumped { animation: sds-bump .34s cubic-bezier(.2, .8, .3, 1); }
@keyframes sds-bump {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.045); }
  100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .sds-planner__toggle-mark svg polyline { stroke-dashoffset: 0; }
  .sds-planner__toggle input:checked ~ .sds-planner__toggle-mark,
  .sds-planner__toggle input:checked ~ .sds-planner__toggle-mark svg polyline,
  .sds-planner__lines li.is-new,
  .sds-planner__out-num.is-bumped { animation: none; }
}
.sds-planner__toggle input:checked ~ .sds-planner__toggle-mark {
  background: #fff; color: var(--sds-ink);
}
.sds-planner__toggle:has(input:checked) { background: var(--sds-ink); color: #fff; }
.sds-planner__toggle:has(input:focus-visible) {
  outline: 2px solid var(--sds-ink); outline-offset: 3px;
}
/* Fallback focus ring for browsers without :has, pinned to the mark so the
   keyboard user still sees where they are. */
.sds-planner__toggle input:focus-visible ~ .sds-planner__toggle-mark {
  outline: 2px solid var(--sds-ink); outline-offset: 2px;
}
@media (hover: hover) {
  /* surface-alt, not surface-deep: the empty mark is surface-deep, so the
     deeper hover swallowed the one thing that says the chip is not on. */
  .sds-planner__toggle:hover { background: var(--sds-surface-alt); }
  .sds-planner__toggle:has(input:checked):hover { background: var(--sds-ink-deep); }
}

.sds-planner__out {
  display: flex; flex-direction: column;
  padding: 36px; background: var(--sds-ink); color: #fff;
  border-radius: 0 var(--sds-radius-card) var(--sds-radius-card) 0;
}
.sds-planner__out-label {
  font-size: 13px; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; opacity: .6; margin: 0 0 12px;
}
.sds-planner__out-num {
  font-family: var(--sds-serif); font-size: 54px; line-height: 1;
  margin: 0 0 8px;
}
.sds-planner__out-sub { font-size: 15px; color: rgba(255,255,255,.72); margin: 0 0 22px; }

.sds-planner__lines {
  list-style: none; margin: 0 0 22px; padding: 22px 0 0;
  border-top: 1px solid rgba(255,255,255,.16);
  display: grid; gap: 10px;
  font-size: 15px;
}
.sds-planner__lines li { display: flex; justify-content: space-between; gap: 16px; }
.sds-planner__lines li[hidden] { display: none; }
.sds-planner__lines span:first-child { color: rgba(255,255,255,.72); }
.sds-planner__lines span:last-child { font-weight: 600; white-space: nowrap; }

.sds-planner__note {
  font-size: 13px; line-height: 1.55; color: rgba(255,255,255,.6);
  margin: auto 0 20px;
}

.sds-hours { display: grid; grid-template-columns: repeat(2, 1fr); gap: 24px; }
.sds-hours__item {
  background: var(--sds-surface); border-radius: 20px; padding: 30px 32px;
}
.sds-hours__item h3 { font-size: 25px; margin-bottom: 18px; }
.sds-hours__item dl {
  margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 10px 24px;
}
.sds-hours__item dt { font-size: 16px; color: var(--sds-muted); }
.sds-hours__item dd {
  margin: 0; font-size: 17px; font-weight: 600; color: var(--sds-ink);
}

@media (max-width: 768px) {
  .sds-rates, .sds-hours { grid-template-columns: 1fr; }
  .sds-planner { grid-template-columns: 1fr; }
  .sds-planner__controls, .sds-planner__out { padding: 28px; }
  .sds-planner__controls {
    border-radius: var(--sds-radius-card) var(--sds-radius-card) 0 0;
  }
  .sds-planner__out {
    border-radius: 0 0 var(--sds-radius-card) var(--sds-radius-card);
  }
  .sds-planner__head { margin-top: 56px; }
  /* Three selects side by side leave each about 90px wide, which truncates
     the labels above them rather than the values inside them. */
  .sds-planner__fields { grid-template-columns: 1fr 1fr; }
  /* Six equal columns rather than a wrapping flex row: at 375px the last
     preset drops to a line of its own and the row stops reading as a set. */
  .sds-planner__presets {
    display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px;
  }
  .sds-planner__presets button { min-width: 0; padding: 0 6px; }
  .sds-planner__out-num { font-size: 44px; }
  .sds-rate { padding: 28px; }
  .sds-rate__price { font-size: 44px; }

  /* Icon and title share the top row; the note and the price each take the
     full card width underneath. Kept beside the icon they wrap to four words
     a line and the row grows to half a screen. */
  .sds-extra { grid-template-columns: auto 1fr; gap: 12px 16px; padding: 22px; }
  .sds-extra__icon {
    grid-row: 1; align-self: start; width: 44px; height: 44px;
  }
  .sds-extra__icon svg { width: 22px; height: 22px; }
  .sds-extra__note  { grid-column: 1 / -1; grid-row: 2; }
  .sds-extra__price {
    grid-column: 1 / -1; grid-row: 3; text-align: left; font-size: 27px;
  }
  .sds-extra__price small { display: inline; margin-left: 8px; }
}

/* ---------------------------------------------------------------- press --
   Coverage cards. The whole card is the link rather than a "read more"
   anchor inside it, so the target is the full 300-odd pixels instead of a
   two-word run of text. The arrow is decoration; the headline is the label. */

/* The video rack. auto-fit rather than a fixed column count so one clip sits
   full width and two or more split, with no per-count rule to keep in sync
   with the data. */
.sds-reels {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(420px, 1fr));
  gap: 32px;
}
.sds-reel { margin: 0; }
.sds-reel figcaption { padding-top: 18px; }
.sds-reel__meta {
  font-size: 13px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--sds-muted); margin: 0 0 6px;
}
.sds-reel__title {
  font-family: var(--sds-serif); font-size: 22px; color: var(--sds-ink); margin: 0;
}

@media (max-width: 768px) {
  .sds-reels { grid-template-columns: 1fr; gap: 28px; }
  .sds-reel__title { font-size: 20px; }
}

.sds-clips { display: grid; grid-template-columns: repeat(2, 1fr); gap: 24px; }
.sds-clip {
  display: flex; flex-direction: column;
  background: #fff; border-radius: var(--sds-radius-card);
  padding: 32px; text-decoration: none;
  transition: background .18s ease, transform .18s ease;
}
.sds-clip__logo {
  align-self: flex-start;
  height: 26px; width: auto; margin-bottom: 22px;
  filter: grayscale(1);
}
.sds-clip__date {
  font-size: 13px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--sds-muted); margin: 0 0 12px;
}
.sds-clip h3 { font-size: 23px; line-height: 1.3; margin-bottom: 14px; }
.sds-clip__byline { font-size: 15px; color: var(--sds-muted); margin: 0 0 24px; }
.sds-clip__more {
  margin-top: auto; font-size: 16px; font-weight: 600; color: var(--sds-ink);
}
.sds-clip__more span { display: inline-block; transition: transform .18s ease; }
@media (hover: hover) {
  .sds-clip:hover { background: var(--sds-surface-alt); }
  .sds-clip:hover .sds-clip__more span { transform: translateX(4px); }
}
/* Declared after :hover — equal specificity, so source order decides which
   one paints when a finger is held on the card. */
.sds-clip:active { background: var(--sds-surface-deep); }

.sds-clips__note {
  margin: 28px 0 0; text-align: center;
  font-size: 15px; color: var(--sds-muted);
}

@media (max-width: 768px) {
  .sds-clips { grid-template-columns: 1fr; }
  .sds-clip { padding: 26px; }
  .sds-clip h3 { font-size: 21px; }
}

/* ----------------------------------------------------------------- team --
   Two people, then the four house dogs. Cards take --sds-surface on white,
   same as everywhere; the monogram flips to white so it reads as a mark
   sitting ON the card rather than a hole cut out of it. */

.sds-team { display: grid; grid-template-columns: repeat(2, 1fr); gap: 32px; }
.sds-team__person {
  background: var(--sds-surface); border-radius: var(--sds-radius-card);
  padding: 36px; text-align: center;
}
/* Square, not a circle: both photographs are square at source, so shown
   square they are shown whole. A circular mask would have cropped Hannah,
   who is full-length in hers. Capped at the source's own 480px so it is
   never upscaled. */
.sds-team__photo {
  width: 100%; max-width: 240px; margin: 0 auto 22px;
  aspect-ratio: 1 / 1; object-fit: cover;
  border-radius: var(--sds-radius-card); background: #fff;
}
.sds-team__person h3 { font-size: 25px; margin-bottom: 4px; }
.sds-team__role {
  font-size: 13px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--sds-muted); margin: 0 0 16px;
}
.sds-team__person p:last-child {
  font-size: 16px; color: var(--sds-text); margin: 0;
  max-width: 34ch; margin-inline: auto;
}

/* The dogs are a list of names, not staff profiles, so they get a lighter
   treatment: one band, four names, no invented biographies. */
.sds-pack {
  margin-top: 32px; padding: 40px;
  background: var(--sds-surface); border-radius: var(--sds-radius-card);
}
.sds-pack__intro { text-align: center; margin-bottom: 28px; }
.sds-pack__intro h3 { font-size: 27px; margin-bottom: 8px; }
.sds-pack__intro p {
  font-size: 16px; color: var(--sds-text); margin: 0 auto; max-width: 46ch;
}
.sds-pack__list {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px;
  margin: 0; padding: 0; list-style: none;
}
.sds-pack__list li {
  background: #fff; border-radius: 16px; padding: 22px 16px; text-align: center;
}
.sds-pack__list span {
  display: block; font-family: var(--sds-serif); font-size: 24px;
  color: var(--sds-ink);
}
.sds-pack__list small {
  display: block; margin-top: 4px;
  font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--sds-muted);
}

@media (max-width: 768px) {
  .sds-team { grid-template-columns: 1fr; gap: 20px; }
  .sds-team__person { padding: 30px 24px; }
  .sds-pack { padding: 30px 20px; }
  .sds-pack__list { grid-template-columns: repeat(2, 1fr); }
}

/* ---------------------------------------------------------------- stats -- */

.sds-stats {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 32px;
  text-align: center;
}
.sds-stat__num {
  font-family: var(--sds-serif);
  font-size: clamp(48px, 6vw, 76px); line-height: 1; letter-spacing: -0.02em;
  color: var(--sds-ink); margin: 0 0 8px;
}
.sds-stat__num span { font-size: .5em; }
.sds-section--dark .sds-stat__num { color: #fff; }
.sds-stat__label { font-size: 15px; color: var(--sds-muted); margin: 0; }
.sds-section--dark .sds-stat__label { color: rgba(255,255,255,.7); }

/* --------------------------------------------------------- testimonial -- */

.sds-vet-band {
  display: grid; grid-template-columns: 1.1fr 0.9fr; gap: 56px; align-items: center;
}
.sds-vet-band__quote {
  background: var(--sds-surface);
  border-radius: var(--sds-radius-card); padding: 40px;
}
.sds-vet-band__quote blockquote {
  margin: 0 0 24px;
  font-family: var(--sds-serif);
  font-size: clamp(22px, 2.7vw, 31px); line-height: 1.35; color: var(--sds-ink);
}
.sds-vet-band__image img {
  width: 100%; aspect-ratio: 4 / 5; object-fit: cover;
  border-radius: var(--sds-radius-card);
}
.sds-vet {
  display: flex; align-items: center; gap: 14px;
}
.sds-vet__avatar {
  flex: none; width: 48px; height: 48px; border-radius: 50%;
  background: var(--sds-surface-alt); color: var(--sds-ink);
  font-family: var(--sds-serif); font-size: 21px;
  display: flex; align-items: center; justify-content: center;
}
.sds-vet__name { font-weight: 700; font-size: 16px; margin: 0; display: flex; align-items: center; gap: 6px; }
.sds-vet__role { font-size: 15px; color: var(--sds-muted); margin: 0; }
.sds-verified { color: var(--sds-ink); display: inline-flex; }
.sds-verified svg { width: 16px; height: 16px; }

.sds-stars-row {
  display: inline-flex; align-items: center; gap: 2px;
  color: var(--sds-star); font-size: 16px; margin-bottom: 16px;
}
/* 2px is the tile gap; the trailing score is a separate thing and keeps the
   8px it had when the row was five loose glyphs. */
.sds-stars-row span { margin-left: 6px; color: var(--sds-muted); font-weight: 600; }
.sds-stars-row .sds-star { width: 18px; height: 18px; }

/* -------------------------------------------------------------- reviews --
   Masonry columns rather than a grid: reviews run from one line to a full
   paragraph, and columns let them flow at their natural length instead of
   forcing every card to the height of the longest one, or truncating. */

/* Was masonry columns, which existed only because reviews ran from one line
   to a full paragraph. Every card is clamped to the same excerpt now, so a
   plain grid is both simpler and necessary: expanding a card inside CSS
   columns makes cards migrate between columns mid-animation. align-items
   keeps an expanded card from stretching its neighbours. */
.sds-reviews {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 24px; align-items: start;
}
.sds-review {
  padding: 28px;
  background: var(--sds-surface);
  border-radius: var(--sds-radius-card);
}
.sds-review p { font-size: 16px; color: var(--sds-text); }
/* .sds-review p (0,1,1) outranks .sds-stars-row (0,1,0), which greys the
   stars out. Restate the colour at matching specificity. */
.sds-review .sds-stars-row { margin-bottom: 12px; color: var(--sds-star); }
/* Date is meta, so it keeps the grey the body copy just gave up. Needs the
   parent class because .sds-review p (0,1,1) outranks (0,1,0). */
.sds-review .sds-review__date {
  font-size: 14px; font-style: italic; margin-bottom: 12px;
  color: var(--sds-muted);
}

/* Font size and line-height live on the wrapper so the clamp can be stated
   in lines: 6.4em is exactly four of them at 1.6. */
.sds-review__body { font-size: 16px; line-height: 1.6; overflow: hidden; }
.sds-review__body p { font-size: inherit; line-height: inherit; margin: 0; }
.sds-review.is-clamped .sds-review__body {
  position: relative;
  max-height: 6.4em;
  transition: max-height .38s cubic-bezier(.4, 0, .2, 1);
}
/* Fades the cut instead of guillotining a line, so a clamped card reads as
   shortened rather than broken. */
.sds-review.is-clamped .sds-review__body::after {
  content: ''; position: absolute; inset: auto 0 0 0; height: 2.4em;
  background: linear-gradient(to bottom, rgba(250,250,252,0), var(--sds-surface));
  opacity: 1; transition: opacity .28s ease;
  pointer-events: none;
}
.sds-review.is-open .sds-review__body::after { opacity: 0; }

.sds-review__more {
  margin-top: 12px; padding: 0; border: 0; background: none;
  font-family: var(--sds-sans); font-size: 15px; font-weight: 700;
  color: var(--sds-ink); cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: rgba(23, 22, 20, .3);
  transition: text-decoration-color .18s ease;
}
.sds-review__more:hover { text-decoration-color: currentColor; }
.sds-review__more:active { transform: translateY(1px); }

@media (prefers-reduced-motion: reduce) {
  .sds-review.is-clamped .sds-review__body { transition: none; }
}
.sds-review .sds-review__by {
  margin-top: 14px; font-size: 15px; font-weight: 700; color: var(--sds-ink);
}

/* ------------------------------------------------------------ callouts -- */

.sds-note {
  border-radius: 16px;
  background: var(--sds-surface);
  padding: 24px 28px;
}
.sds-note h3 { font-size: 22px; margin-bottom: 8px; }
.sds-note p { font-size: 16px; color: var(--sds-text); }

/* --------------------------------------------------------------- video --
   §8/§11: facade. Poster + button only; the source is attached on click. */

/* The box owns the 16:9 ratio and the poster and iframe both fill it
   absolutely. If the iframe were left in normal flow it would stack below
   the poster on play and double the height of the block. */
/* -------------------------------------------------- video-as-dog body --
   Head meets the top-left corner, tail leaves the bottom-right, and the 16:9
   frame between them is the dachshund's body.

   The artwork is a 1344x840 canvas holding a 1152x648 video area inset by
   96px on every side. Those insets are restated here as percentages OF THE
   VIDEO BOX, which is what keeps the join registered at any width with no
   per-size media query: 96/1152 = 8.3333% horizontally, 96/648 = 14.8148%
   vertically, because percentage insets resolve against the container's own
   width and height respectively.

   Two wrappers, deliberately. This outer one does not clip, so head and tail
   can hang outside the frame; the inner .sds-video is the rounded box that
   DOES clip, and that is what swallows the neck and the tail's base so the
   joins never have to be drawn. Every ancestor above this is overflow:visible
   too, so nothing upstream crops the illustration. */
.sds-hero__feature-media { position: relative; overflow: visible; }
/* Sized explicitly rather than by opposing insets: an inline <svg> defaults
   to width:100%, which beats width:auto and collapses it to the video's own
   width, throwing the join out by the whole 96px surround. */
.sds-video-dog {
  position: absolute; z-index: 0;
  top: -14.8148%;              /* 96 / 648 */
  left: -8.3333%;              /* 96 / 1152 */
  width: 116.6667%;            /* 1344 / 1152 */
  height: 129.6296%;           /* 840 / 648 */
  /* The base `svg { max-width: 100% }` clamps that width back to the video's
     own, which silently drops the whole left surround and misaligns the head. */
  max-width: none;
  pointer-events: none;   /* fills are pinned to #111111 in the markup */
}

/* Rests, then wags. The pivot is measured in the tail's OWN box rather than
   viewBox units, so the outer positioning translate cannot drag it off the
   base: 6%/86% is where the tail meets the frame. Rotating there swings the
   tip and leaves the buried base buried, so the wag can never open a gap. */
.sds-video-dog__tail {
  transform-box: fill-box;
  transform-origin: 6% 86%;
  animation: sds-wag 4.2s ease-in-out infinite;
}
@keyframes sds-wag {
  0%, 62%, 100% { transform: rotate(0deg); }
  68% { transform: rotate(-9deg); }
  76% { transform: rotate(6deg); }
  84% { transform: rotate(-4deg); }
  92% { transform: rotate(2deg); }
}
@media (prefers-reduced-motion: reduce) {
  .sds-video-dog__tail { animation: none; }
}

.sds-video {
  position: relative; z-index: 1; aspect-ratio: 16 / 9;
  border-radius: var(--sds-radius-card); overflow: hidden;
  background: var(--sds-ink);
}
.sds-video > img,
.sds-video > iframe {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover; border: 0;
}
.sds-video.is-playing > img { display: none; }
.sds-video__btn {
  position: absolute; inset: 0; width: 100%; border: 0; padding: 0;
  background: rgba(20,18,16,.28); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background .18s ease;
}
.sds-video__btn:hover { background: rgba(20,18,16,.4); }
.sds-video__btn:active span { transform: scale(.94); }
.sds-video__btn span { transition: transform .08s ease; }
.sds-video__btn span {
  width: 82px; height: 82px; border-radius: 50%;
  background: #fff; color: var(--sds-ink);
  display: flex; align-items: center; justify-content: center;
}
.sds-video__btn svg { width: 30px; height: 30px; margin-left: 4px; }
.sds-video.is-playing .sds-video__btn { display: none; }

/* ------------------------------------------------------------- gallery -- */

.sds-gallery { columns: 3; column-gap: 20px; }
.sds-gallery button {
  display: block; width: 100%; padding: 0; margin: 0 0 20px;
  border: 0; background: none; cursor: zoom-in;
  break-inside: avoid;
  border-radius: var(--sds-radius-card); overflow: hidden;
  line-height: 0;
}
.sds-gallery img {
  width: 100%; border-radius: var(--sds-radius-card);
  transition: transform .3s ease;
}
.sds-gallery button:hover img { transform: scale(1.03); }
.sds-gallery button:active img { transform: scale(.99); transition-duration: .08s; }

.sds-lightbox {
  position: fixed; inset: 0; z-index: 60;
  max-width: none; max-height: none; width: 100%; height: 100%;
  background: rgba(20,18,16,.94);
  padding: 40px 20px;
  border: 0;
}
/* A closed <dialog> is display:none via the UA sheet. Setting display on the
   base selector overrides that and leaves the lightbox stacked on the page,
   so the layout rules are scoped to [open] instead. */
.sds-lightbox:not([open]) { display: none; }
.sds-lightbox[open] { display: flex; align-items: center; justify-content: center; }
.sds-lightbox::backdrop { background: rgba(20,18,16,.94); }
.sds-lightbox img { max-width: 100%; max-height: 84vh; border-radius: 12px; }
.sds-lightbox__close,
.sds-lightbox__nav {
  position: absolute; width: 52px; height: 52px; border-radius: 50%;
  border: 0; background: rgba(255,255,255,.14);
  color: #fff; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.sds-lightbox__close:hover,
.sds-lightbox__nav:hover { background: rgba(255,255,255,.24); }
.sds-lightbox__close:active,
.sds-lightbox__nav:active { background: rgba(255,255,255,.36); transform: scale(.94); }
.sds-lightbox__nav--prev:active { transform: translateY(-50%) scale(.94); }
.sds-lightbox__nav--next:active { transform: translateY(-50%) scale(.94); }
.sds-lightbox__close { top: 20px; right: 20px; }
.sds-lightbox__nav--prev { left: 20px; top: 50%; transform: translateY(-50%); }
.sds-lightbox__nav--next { right: 20px; top: 50%; transform: translateY(-50%); }

/* ----------------------------------------------------------------- FAQ --
   §5.1: native <details>/<summary>. Marker hidden; ::after is + / –. */

.sds-faq { max-width: 780px; margin: 0 auto; }
.sds-faq details {
  background: var(--sds-surface);
  border-radius: 16px;
  margin-bottom: 10px;
  padding: 0 24px;
}
.sds-faq summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  padding: 24px 0;
  font-family: var(--sds-serif); font-size: clamp(20px, 2.2vw, 24px);
  color: var(--sds-ink);
  transition: opacity .12s ease;
}
.sds-faq summary:hover { opacity: .68; }
.sds-faq summary:active { opacity: .45; transition-duration: .06s; }
.sds-faq summary::-webkit-details-marker { display: none; }

/* The marker is two bars rather than a '+' / '\2013' glyph swap, so it can
   morph: the whole icon turns a quarter and the vertical bar collapses into
   the horizontal one. A text swap cannot be animated. */
.sds-faq__icon {
  position: relative; flex: none; width: 16px; height: 16px;
  transition: transform .28s cubic-bezier(.4, 0, .2, 1);
}
.sds-faq__icon i {
  position: absolute; background: var(--sds-ink); border-radius: 2px;
  transition: transform .28s cubic-bezier(.4, 0, .2, 1);
}
.sds-faq__icon i:first-child { left: 0; right: 0; top: 7px; height: 2px; }
.sds-faq__icon i:last-child  { top: 0; bottom: 0; left: 7px; width: 2px; }

/* On open the icon turns a quarter and the HORIZONTAL bar collapses, leaving
   the vertical one — which the rotation has just laid flat — as the minus.
   Collapsing the vertical bar instead (the obvious-looking choice) leaves the
   horizontal bar rotated upright, i.e. a stray vertical tick. */
.sds-faq details[open] .sds-faq__icon { transform: rotate(90deg); }
.sds-faq details[open] .sds-faq__icon i:first-child { transform: scaleX(0); }

.sds-faq__panel {
  padding: 0 48px 28px 0;
  font-size: 17px; color: var(--sds-text);
}

/* ------------------------------------------------------ contact / form -- */

.sds-contact { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: 56px; }
/* A grid track's automatic minimum is its content's min-content size, and
   hannah@sausagedogsanctuaryfood.com has no break opportunity — 330px of
   unbreakable token. On a 375px phone that floored the single column at
   376px, stretched the form to match, and pushed the page 18px wider than
   the viewport. That was the horizontal scroll on every page carrying the
   enquiry form. min-width lets the track shrink; overflow-wrap gives the
   address somewhere to break so it wraps instead of spilling. */
.sds-contact > * { min-width: 0; }
.sds-contact__details a { overflow-wrap: anywhere; }

.sds-contact__details { margin: 0; padding: 0; list-style: none; display: grid; gap: 22px; }
.sds-contact__details li { display: flex; gap: 14px; align-items: flex-start; }
.sds-contact__details svg { flex: none; width: 22px; height: 22px; color: var(--sds-ink); margin-top: 3px; }
.sds-contact__details a { text-decoration: none; font-weight: 600; }
.sds-contact__details a:hover { text-decoration: underline; }
.sds-contact__details span { display: block; font-size: 14px; color: var(--sds-muted); font-weight: 500; }

.sds-form {
  background: var(--sds-surface);
  border-radius: var(--sds-radius-card); padding: 36px;
}
.sds-field { margin-bottom: 20px; }
/* Two fields on one line. Drop-off and collection are one decision, and
   splitting them over two rows makes the second look optional. */
.sds-form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.sds-field label {
  display: block; font-size: 15px; font-weight: 600;
  color: var(--sds-ink); margin-bottom: 8px;
}
.sds-field input,
.sds-field select,
.sds-field textarea {
  width: 100%; padding: 14px 16px; min-height: 48px;
  font-family: inherit; font-size: 17px; color: var(--sds-text);
  background: #fff;
  -webkit-appearance: none;
  border: 0; border-radius: 12px;
  transition: background-color .18s ease;
}
.sds-field textarea { min-height: 130px; resize: vertical; }
/* type=date, not a hand-built calendar. It brings the platform's own picker,
   which on a phone is the wheel people already know how to use, and it is
   keyboard and screen-reader complete without a line of script. Safari sizes
   the control off the font rather than the box, so the height is pinned and
   the value aligned by hand. */
.sds-field input[type="date"] {
  min-height: 48px; line-height: 20px;
  -webkit-appearance: none; appearance: none;
}
.sds-field input[type="date"]::-webkit-date-and-time-value { text-align: left; }
.sds-field input[type="date"]::-webkit-calendar-picker-indicator {
  opacity: .55; cursor: pointer;
}
.sds-field input[type="date"]::-webkit-calendar-picker-indicator:hover { opacity: 1; }
.sds-field input:focus,
.sds-field select:focus,
.sds-field textarea:focus { outline: 2px solid var(--sds-ink); outline-offset: 0; }

/* §5.1: chevron as a data URI so the select costs no extra request. */
.sds-field select {
  appearance: none; -webkit-appearance: none;
  padding-right: 44px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235b6072' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat: no-repeat;
  background-position: right 16px center;
  background-size: 20px 20px;
}

/* ------------------------------------------------------------ selects --
   The native list is drawn by the operating system, so no rule above can
   reach it: on a phone it arrives as a dark sheet with a system-blue
   highlight and 13px system type, which is the one place this site stops
   looking like itself. site.js builds a listbox alongside the real select
   and adds `is-enhanced`; everything here hangs off that class, so with
   the script absent the native control is what renders.

   The open list is ink. A floating layer needs to separate from what it
   covers, and this site has no borders and no shadows to separate it
   with, so it separates by ground, like every other surface here. */
.sds-select { position: relative; }
.sds-select.is-enhanced > select {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.sds-select__button {
  display: none;
  width: 100%; min-height: 48px; padding: 14px 16px;
  align-items: center; justify-content: space-between; gap: 12px;
  font-family: inherit; font-size: 17px; font-weight: 400; text-align: left;
  color: var(--sds-text); background: #fff;
  border: 0; border-radius: 12px; cursor: pointer;
  transition: background-color .18s ease;
}
.sds-select.is-enhanced > .sds-select__button { display: flex; }
.sds-select__button svg {
  flex: none; width: 20px; height: 20px; color: #5b6072;
  transition: transform .2s ease;
}
.sds-select.is-open .sds-select__button svg { transform: rotate(180deg); }
.sds-select__value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (hover: hover) {
  .sds-select__button:hover { background: var(--sds-surface-alt); }
}
.sds-select__button:focus-visible,
.sds-select.is-open .sds-select__button { outline: 2px solid var(--sds-ink); outline-offset: 0; }

.sds-select__menu {
  position: absolute; z-index: 30; left: 0; right: 0; top: calc(100% + 6px);
  margin: 0; padding: 6px; list-style: none;
  max-height: 292px; overflow-y: auto; overscroll-behavior: contain;
  background: var(--sds-ink); border-radius: 16px;
}
/* Opened near the bottom of a long page the list would run off screen, so
   site.js measures the gap and flips it above the control. */
.sds-select.is-up .sds-select__menu { top: auto; bottom: calc(100% + 6px); }
.sds-select__option {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 11px 14px; border-radius: 10px;
  font-size: 16px; line-height: 1.35; color: rgba(255,255,255,.76);
  cursor: pointer;
}
.sds-select__option svg { flex: none; width: 17px; height: 17px; opacity: 0; }
/* One highlight, driven by JS rather than :hover, so the pointer and the
   arrow keys cannot disagree about which row is the live one. */
.sds-select__option.is-active { background: rgba(255,255,255,.10); color: #fff; }
.sds-select__option[aria-selected="true"] { color: #fff; font-weight: 600; }
.sds-select__option[aria-selected="true"] svg { opacity: 1; }
.sds-select__option[aria-disabled="true"] {
  color: rgba(255,255,255,.32); cursor: default;
}

/* ------------------------------------------------------- date range --
   The browser's own calendar is drawn by the browser: grey chrome, a blue
   day, arrows from another decade, and no notion that these two fields are
   one range. site.js hides the native inputs and puts this over them.

   Ink, like the select lists, because every layer that floats above the
   page on this site is ink. The two triggers stay identical to the other
   fields so the form still reads as one set of controls. */
.sds-form__row.is-enhanced { position: relative; }
.sds-form__row.is-enhanced input[type="date"] {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.sds-date__button {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; min-height: 48px; padding: 14px 16px;
  font-family: inherit; font-size: 17px; text-align: left;
  color: var(--sds-text); background: #fff;
  border: 0; border-radius: 12px; cursor: pointer;
  transition: background-color .18s ease;
}
.sds-date__button.is-empty .sds-date__value { color: #8b8b93; }
.sds-date__button svg { flex: none; width: 20px; height: 20px; color: #5b6072; }
@media (hover: hover) {
  .sds-date__button:hover { background: var(--sds-surface-alt); }
}
.sds-date__button:focus-visible,
.sds-date__button[aria-expanded="true"] { outline: 2px solid var(--sds-ink); }

.sds-cal {
  position: absolute; z-index: 30; top: calc(100% + 8px); left: 0;
  /* right-anchored when the collection field is the one being filled */
  width: min(340px, 100%);
  padding: 16px; border-radius: 20px;
  background: var(--sds-ink); color: #fff;
}
.sds-form__row.is-right .sds-cal { left: auto; right: 0; }
.sds-cal__head {
  display: grid; grid-template-columns: 40px 1fr 40px; align-items: center;
  margin-bottom: 8px;
}
.sds-cal__month {
  margin: 0; text-align: center;
  font-family: var(--sds-serif); font-size: 20px; color: #fff;
}
.sds-cal__nav {
  width: 40px; height: 40px; display: flex; align-items: center; justify-content: center;
  padding: 0; border: 0; border-radius: 50%;
  background: none; color: #fff; cursor: pointer;
  transition: background-color .18s ease, opacity .18s ease;
}
.sds-cal__nav svg { width: 20px; height: 20px; }
.sds-cal__nav:disabled { opacity: .25; cursor: default; }
@media (hover: hover) {
  .sds-cal__nav:not(:disabled):hover { background: rgba(255,255,255,.12); }
}
.sds-cal__week, .sds-cal__grid {
  display: grid; grid-template-columns: repeat(7, 1fr);
}
.sds-cal__week span {
  text-align: center; padding: 6px 0;
  font-size: 12px; font-weight: 600; letter-spacing: .06em;
  color: rgba(255,255,255,.45);
}
/* No gaps between cells: the range band has to run edge to edge, and a gap
   would chop it into separate tiles. The rounding is done on the ends. */
.sds-cal__grid { row-gap: 2px; }
.sds-cal__day {
  position: relative; aspect-ratio: 1 / 1;
  display: flex; align-items: center; justify-content: center;
  padding: 0; border: 0; border-radius: 50%;
  font-family: inherit; font-size: 15px; color: rgba(255,255,255,.86);
  background: none; cursor: pointer;
  transition: background-color .15s ease, color .15s ease;
}
.sds-cal__day.is-out { color: rgba(255,255,255,.28); }
.sds-cal__day:disabled { color: rgba(255,255,255,.22); cursor: default; }
.sds-cal__day.is-today::after {
  content: ''; position: absolute; bottom: 6px; left: 50%;
  width: 4px; height: 4px; margin-left: -2px; border-radius: 50%;
  background: currentColor;
}
@media (hover: hover) {
  .sds-cal__day:not(:disabled):not(.is-picked):hover { background: rgba(255,255,255,.14); }
}
.sds-cal__day.is-between {
  background: rgba(255,255,255,.12); border-radius: 0; color: #fff;
}
.sds-cal__day.is-picked { background: #fff; color: var(--sds-ink); font-weight: 600; }
.sds-cal__day.is-start { border-radius: 50% 0 0 50%; }
.sds-cal__day.is-end   { border-radius: 0 50% 50% 0; }
.sds-cal__day.is-picked.is-today::after { background: var(--sds-ink); }
.sds-cal__day:focus-visible { outline: 2px solid #fff; outline-offset: -2px; }

.sds-cal__foot {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-top: 12px; padding-top: 12px;
  border-top: 1px solid rgba(255,255,255,.16);
}
.sds-cal__foot p { margin: 0; font-size: 14px; color: rgba(255,255,255,.7); }
.sds-cal__clear {
  padding: 8px 14px; border: 0; border-radius: var(--sds-radius);
  font-family: inherit; font-size: 14px; font-weight: 600;
  background: rgba(255,255,255,.12); color: #fff; cursor: pointer;
  transition: background-color .18s ease;
}
@media (hover: hover) {
  .sds-cal__clear:hover { background: rgba(255,255,255,.22); }
}

.sds-form__note { font-size: 14px; color: var(--sds-muted); margin-top: 16px; }

.sds-form__status {
  display: none;
  margin-top: 20px; padding: 16px 20px; border-radius: 12px;
  font-size: 16px; font-weight: 600;
}
.sds-form__status.is-ok   { display: block; background: var(--sds-surface-alt); color: var(--sds-ink); }
.sds-form__status.is-fail { display: block; background: #fdecec; color: #c44; }

/* Honeypot. Moved off-screen rather than display:none, because the better
   bots skip anything that is display:none or type=hidden. */
.sds-hp {
  position: absolute; left: -9999px; width: 1px; height: 1px;
  overflow: hidden;
}

/* The no-endpoint fallback. Deliberately not styled as a success: the form
   has not sent anything, and a green tick would be the same lie the old
   copy told. Neutral ground, and the lead line states plainly where the
   enquiry actually is. */
.sds-form__status.is-pending {
  display: block; background: var(--sds-surface-alt); color: var(--sds-ink);
  font-weight: 400; line-height: 1.55;
}
.sds-form__status.is-pending p { margin: 0 0 12px; }
.sds-form__fallback-lead { font-weight: 700; }
.sds-form__fallback-text {
  display: block; width: 100%; margin-bottom: 14px;
  padding: 12px 14px; border: 0; border-radius: 10px;
  background: #fff; color: var(--sds-ink);
  font-family: var(--sds-sans); font-size: 15px; line-height: 1.5;
  resize: vertical;
}
.sds-form__fallback-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px 18px;
}
.sds-form__fallback-call { font-size: 15px; color: var(--sds-ink); }
.sds-btn--sm {
  padding: 10px 20px; font-size: 15px;
}

/* ------------------------------------------------------------- final CTA */

.sds-final { text-align: center; }
.sds-final h2 { max-width: 22ch; margin-left: auto; margin-right: auto; }
.sds-final p  { max-width: 52ch; margin-left: auto; margin-right: auto; margin-bottom: 32px; }
.sds-final__actions { display: flex; flex-wrap: wrap; gap: 14px; justify-content: center; }

/* --------------------------------------------------------------- footer -- */

.sds-footer { background: var(--sds-ink-deep); color: rgba(255,255,255,.78); }
.sds-footer__inner {
  max-width: calc(var(--sds-container) + var(--sds-gutter) * 2); margin: 0 auto; padding: 64px var(--sds-gutter) 32px;
  display: grid; grid-template-columns: 1.4fr 1fr 1.2fr; gap: 48px;
}
.sds-footer h4 {
  color: #fff; font-family: var(--sds-sans);
  font-size: 13px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  margin: 0 0 20px;
}
.sds-footer ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 12px; }
.sds-footer a { color: rgba(255,255,255,.78); text-decoration: none; font-size: 16px; }
.sds-footer a:hover { color: #fff; }
.sds-footer a:active { opacity: .6; }
.sds-footer address { font-style: normal; font-size: 16px; line-height: 1.7; }

.sds-social { display: flex; gap: 12px; margin-top: 24px; }
.sds-social a {
  width: 42px; height: 42px; border-radius: 50%;
  border: 0; background: rgba(255,255,255,.08);
  display: flex; align-items: center; justify-content: center;
  transition: background .18s ease;
}
.sds-social a:hover { background: rgba(255,255,255,.14); }
.sds-social a:active { background: rgba(255,255,255,.26); transform: scale(.94); }
.sds-social svg { width: 19px; height: 19px; }

.sds-footer__legal {
  max-width: calc(var(--sds-container) + var(--sds-gutter) * 2); margin: 0 auto; padding: 24px var(--sds-gutter) 40px;
  display: flex; flex-wrap: wrap; gap: 8px 28px;
  font-size: 14px; color: rgba(255,255,255,.6);
}
.sds-footer__legal p { margin: 0; }

/* --------------------------------------------------- sticky book bar (§8)
   Fail-visible: the hidden state is gated behind .sds-sticky-ready, which JS
   adds. If the JS never runs, the bar stays visible rather than invisible. */

.sds-claim-sticky {
  position: fixed; z-index: 40;
  left: 20px; bottom: 20px;
  display: flex; align-items: center; gap: 14px;
  padding: 12px 12px 12px 22px;
  background: var(--sds-ink); color: #fff;
  border-radius: var(--sds-radius);
  padding-bottom: max(12px, env(safe-area-inset-bottom));
}
.sds-claim-sticky p { margin: 0; font-size: 15px; font-weight: 600; }
.sds-claim-sticky .sds-btn { padding: 14px 24px; font-size: 15px; }
.sds-claim-sticky__x {
  width: 34px; height: 34px; flex: none;
  border-radius: 50%; border: 0;
  background: rgba(255,255,255,.12); color: #fff; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.sds-claim-sticky__x:hover { background: rgba(255,255,255,.14); }
.sds-claim-sticky__x:active { background: rgba(255,255,255,.26); transform: scale(.92); }

.sds-sticky-ready .sds-claim-sticky {
  opacity: 0; visibility: hidden; transform: translateY(12px);
  transition: opacity .25s ease, transform .25s ease, visibility .25s;
}
.sds-sticky-ready .sds-claim-sticky.is-visible {
  opacity: 1; visibility: visible; transform: none;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
}

/* ==========================================================================
   768px — the single breakpoint (§4.5)
   ========================================================================== */

@media (max-width: 768px) {
  :root { --sds-gutter: 16px; }

  /* ---- phone scale ----
     The type ramp used to be whatever the desktop clamps bottomed out at,
     which is not a scale — it left h1 at 34 and h2 at 31, a 3px step that
     reads as no hierarchy, and a lede (17) SMALLER than body copy (18).
     These are the phone's own steps: 17 body, 18 lede, 23/30/36 headings. */
  body { font-size: 17px; }
  .sds-h1   { font-size: 36px; line-height: 1.06; }
  .sds-h2   { font-size: 30px; line-height: 1.14; }
  .sds-h3   { font-size: 23px; line-height: 1.28; }
  .sds-lede { font-size: 18px; }
  .sds-eyebrow { font-size: 12px; letter-spacing: .16em; margin-bottom: 12px; }

  /* A 67px-tall CTA on a 375px screen was the heaviest thing on the page.
     These land at 50 and 54 — both clear of the 44px tap target. Horizontal
     padding matters less than it looks, since most mobile CTAs are --block
     and stretch to the gutter regardless. */
  .sds-btn     { padding: 16px 26px; font-size: 16px; min-height: 50px; }
  .sds-btn--xl { padding: 18px 30px; font-size: 17px; }

  .sds-section        { padding: 44px var(--sds-gutter); }
  .sds-section--tight { padding: 32px var(--sds-gutter); }
  .sds-section--hero  { padding: 36px var(--sds-gutter); }

  /* The rating row sits directly above the h1 and was competing with it.
     Smaller tiles and smaller count text put it back in its place as a
     credential rather than a headline. */
  .sds-star { width: 15px; height: 15px; }
  .sds-rating { gap: 8px; margin-bottom: 14px; }
  .sds-rating__count { font-size: 13px; }

  /* No cap on the hero lede. It already breaks to three lines at full gutter
     width, and capping it only bought a dead column down the right-hand side
     while the button and review card below still ran edge to edge. */

  /* Review carousel, down a step. The arrows also move inboard: at -17px
     they straddled a card that runs to the gutter, which put them a pixel
     outside the viewport — one of the two causes of the horizontal scroll. */
  .sds-quotes { margin-top: 24px; }
  .sds-quotes__card { padding: 18px 20px; }
  .sds-quote blockquote { font-size: 15px; }
  .sds-quote__by { font-size: 13px; }
  .sds-quotes__arrow { width: 26px; height: 26px; }
  .sds-quotes__arrow svg { width: 15px; height: 15px; }
  .sds-quotes__arrow[data-q-prev] { left: -9px; }
  .sds-quotes__arrow[data-q-next] { right: -9px; }

  /* The other cause. The dachshund overlay is 1.1667x the video box — the
     artwork carries a 96px transparent surround around a 1152px video area —
     so at full gutter width it measured 400px inside a 375px viewport. Inset
     the media and the whole illustration lands on screen, joke intact. */
  .sds-hero__feature-media { margin-inline: 18px; }

  /* The drawer nav is display:none until opened, so it leaves the grid and
     the CTA would slide into the centre column. Flex keeps logo left and
     burger right regardless. */
  .sds-header__inner { padding: 14px var(--sds-gutter); }
  .sds-header__logo img { height: 46px; }
  .sds-burger { display: flex; align-items: center; justify-content: center; }
  .sds-header__cta .sds-btn { display: none; }

  /* Full-screen panel that sits below the header in the stack, so the header
     and its now-a-cross button stay visible and tappable over it.

     It stays in the DOM and moves with opacity/transform instead of display:
     `display` cannot be transitioned, which is why the previous version
     appeared and vanished instantly. padding-top is set by JS to the
     header's real bottom edge, since that shifts with the announcement bar. */
  .sds-nav {
    position: fixed; inset: 0; z-index: 20;
    display: flex; flex-direction: column; align-items: stretch;
    justify-content: flex-start; gap: 0;
    background: var(--sds-surface);
    padding: 120px 20px 40px;
    overflow-y: auto;
    opacity: 0; visibility: hidden;
    transform: translateY(-10px);
    transition: opacity .34s cubic-bezier(.4, 0, .2, 1),
                transform .34s cubic-bezier(.4, 0, .2, 1),
                visibility .34s;
  }
  .sds-nav.is-open { opacity: 1; visibility: visible; transform: none; }

  .sds-nav a:not(.sds-btn) {
    padding: 16px 2px; border-radius: 0;
    font-family: var(--sds-serif); font-size: 28px; font-weight: 400;
  }
  .sds-nav a:not(.sds-btn):hover,
  .sds-nav a:not(.sds-btn):active { background: none; }
  .sds-nav a:not(.sds-btn)[aria-current="page"] {
    background: none; font-weight: 400; opacity: .4;
  }
  .sds-nav .sds-btn { display: inline-flex; margin-top: 28px; }

  /* Rows rise in one after another on open. On close every delay is zero, so
     the panel leaves as one piece rather than unravelling backwards. */
  .sds-nav > * {
    opacity: 0; transform: translateY(-10px);
    transition: opacity .3s ease, transform .3s ease;
    transition-delay: 0s;
  }
  .sds-nav.is-open > * { opacity: 1; transform: none; }
  .sds-nav.is-open > *:nth-child(1) { transition-delay: .05s; }
  .sds-nav.is-open > *:nth-child(2) { transition-delay: .09s; }
  .sds-nav.is-open > *:nth-child(3) { transition-delay: .13s; }
  .sds-nav.is-open > *:nth-child(4) { transition-delay: .17s; }
  .sds-nav.is-open > *:nth-child(5) { transition-delay: .21s; }
  .sds-nav.is-open > *:nth-child(6) { transition-delay: .25s; }

  /* The panel is a descendant of the header, so its z-index resolves inside
     the header's own stacking context — it paints over the logo and burger,
     which are unpositioned. Lifting those two above it in the same context is
     what keeps the mark visible and the close button tappable. */
  .sds-header__logo,
  .sds-header__cta { position: relative; z-index: 21; }

  body.sds-nav-open { overflow: hidden; }

  .sds-hero { min-height: 520px; padding: 56px var(--sds-gutter); }
  .sds-hero--inner { min-height: 300px; }
  .sds-hero--split .sds-hero__inner { grid-template-columns: 1fr; gap: 28px; }
  .sds-hero--split .sds-hero__card { max-width: none; }

  /* The video hangs over the bottom edge of the grey band onto the white
     section below, so the card is read against a clean seam rather than
     sitting flat inside one flat colour. */
  .sds-hero--split { padding: 48px var(--sds-gutter) 0; }
  .sds-hero__feature { position: relative; z-index: 2; margin-bottom: -64px; }
  /* Hidden on phones: the marquee immediately below already says where the
     coverage came from, and this one was being dragged into it. */
  .sds-hero__feature-label { display: none; }
  /* Must clear the 64px overhang above, or the marquee's own label renders
     underneath the video, which sits at z-index 2. 64 + 24 of breathing. */
  .sds-marquee { padding-top: 88px; }
  .sds-hero--split + main > .sds-section:first-child { padding-top: 104px; }

  /* §4.3: this reset is load-bearing — without it every other row
     stacks image-below-copy on mobile. */
  .sds-row { grid-template-columns: 1fr; gap: 28px; }
  .sds-row--reverse .sds-row__image,
  .sds-row--reverse .sds-row__content { order: initial; }
  .sds-row + .sds-row { margin-top: 48px; }

  .sds-services  { grid-template-columns: 1fr; gap: 24px; }
  .sds-addon     { grid-template-columns: 1fr; }

  .sds-addon__body  { padding: 28px; }
  .sds-routine   { grid-template-columns: 1fr; gap: 36px; }
  .sds-stats     { grid-template-columns: repeat(2, 1fr); gap: 28px; }
  .sds-vet-band  { grid-template-columns: 1fr; gap: 28px; }
  .sds-vet-band__quote { padding: 28px; }
  .sds-contact   { grid-template-columns: 1fr; gap: 32px; }
  .sds-form      { padding: 24px; }
  .sds-form__row { grid-template-columns: 1fr; gap: 0; }
  .sds-cal { width: 100%; padding: 14px; }
  .sds-cal__day { font-size: 16px; }
  .sds-reviews   { grid-template-columns: 1fr; }
  .sds-quotes { max-width: none; }
  .sds-gallery   { columns: 2; column-gap: 14px; }
  .sds-gallery button { margin-bottom: 14px; }
  .sds-press__logos { gap: 22px 32px; }
  .sds-press__logos img { height: 26px; }

  .sds-footer__inner { grid-template-columns: 1fr; gap: 36px; padding: 48px var(--sds-gutter) 24px; }

  .sds-claim-sticky {
    left: 12px; right: 12px; bottom: 12px;
    justify-content: space-between;
    padding-left: 18px;
  }
  .sds-claim-sticky p { font-size: 14px; }

  .sds-btn { width: 100%; }
  .sds-header__cta .sds-btn,
  .sds-claim-sticky .sds-btn { width: auto; }
  .sds-final__actions .sds-btn { width: 100%; }
}

@media (max-width: 480px) {
  .sds-gallery { columns: 1; }
  .sds-stats   { grid-template-columns: 1fr; }
}
