/* ==========================================================================
   While You're Away, house and pet sitting: brand stylesheet
   Minimal, soft, calming. One committed light palette.
   ========================================================================== */

:root {
  /* Colour */
  --cream:      #FCFAF6;
  --sand:       #F3EEE5;
  --mist:       #EAEFEA;
  --white:      #FFFFFF;

  --sage:       #92A896;
  --sage-deep:  #5C7565;
  --sage-dark:  #475C4F;
  --sky:        #AFC4CE;

  /* Soft burgundy, the secondary accent */
  --burgundy:      #9C6A73;
  --burgundy-deep: #7A4D56;
  --burgundy-dark: #5E3A43;
  --blush:         #F4EAEB;

  --ink:        #2B342E;
  --ink-soft:   #5F6B63;
  --ink-faint:  #8B948D;
  --line:       #E4DED3;
  --line-soft:  #EFEAE1;

  /* Type */
  /* Outfit for headings, Inter for prose and eyebrows, the serif reserved
     for numerals and card interiors. */
  --font-heading: "Outfit", "Avenir Next", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --font-display: "Fraunces", Georgia, "Times New Roman", serif;

  /* Space */
  --container: 1120px;
  --gutter: 24px;
  --section: 104px;
  --radius: 14px;
  --radius-lg: 22px;
}

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

/* Any rule that sets an explicit display (.form, .field, .fieldset) would
   otherwise beat the browser default [hidden]{display:none}, so toggling the
   hidden property in JS would silently do nothing. */
[hidden] { display: none !important; }

html {
  scroll-behavior: smooth;
  /* The header is sticky and 74px tall, so anchor targets would otherwise
     land underneath it. This stops them just clear of it. */
  scroll-padding-top: 92px;
}

body {
  margin: 0;
  /* Column layout so a short page still pushes the footer to the bottom of
     the viewport rather than leaving it floating mid-screen. */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4 {
  font-family: var(--font-heading);
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 0 0 0.5em;
  color: var(--ink);
  /* Even out wrapped headings so the last line is not left with one orphan
     word. Ignored by browsers that do not support it, which just wrap. */
  text-wrap: balance;
}

/* Light weight only at display sizes, where the thin strokes have room. */
h1 { font-size: clamp(2.4rem, 5.2vw, 3.9rem); font-weight: 300; line-height: 1.1; letter-spacing: -0.022em; }
h2 { font-size: clamp(1.85rem, 3.4vw, 2.6rem); font-weight: 300; letter-spacing: -0.018em; }
h3 { font-size: 1.22rem; letter-spacing: -0.008em; }
h4 { font-size: 1.02rem; letter-spacing: -0.005em; }

/* Cards keep the serif, as do all numerals (prices, totals, step numbers). */
.card h3, .card h4, .hero__card h3, .summary h3 {
  font-family: var(--font-display);
  font-weight: 400;
  letter-spacing: -0.01em;
}

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }

a { color: var(--sage-dark); text-decoration-color: rgba(92, 117, 101, 0.35); text-underline-offset: 3px; }
a:hover { text-decoration-color: currentColor; }

img { max-width: 100%; display: block; }

/* ---------- Layout primitives ---------- */

.container {
  width: 100%;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.container--narrow { max-width: 760px; }

.section { padding: var(--section) 0; }
.section--tight { padding: 72px 0; }
.section--sand { background: var(--sand); }
.section--mist { background: var(--mist); }

.eyebrow {
  display: block;
  /* Stated rather than inherited: this label sits on a span in some places and
     on the h1 in others, and the h1 rule would otherwise hand it the heading
     font and a display line height. */
  font-family: var(--font-body);
  line-height: inherit;
  font-size: 0.73rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--burgundy-deep);
  margin-bottom: 14px;
}

.lede {
  font-size: 1.16rem;
  line-height: 1.7;
  color: var(--ink-soft);
  max-width: 62ch;
}

/* A step down for ledes that carry an instruction rather than set a scene. */
.lede--sm { font-size: 1.05rem; }

.section-head { max-width: 66ch; margin-bottom: 52px; }

/* A quieter line sitting under a lede, for caveats and qualifications. */
.lede-note {
  font-size: 0.97rem;
  line-height: 1.65;
  color: var(--ink-soft);
  max-width: 62ch;
  margin-top: -0.4em;
}

.lede-note em { font-style: italic; }

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 13px 26px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-family: var(--font-body);
  font-size: 0.96rem;
  font-weight: 500;
  letter-spacing: 0.005em;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 160ms ease, border-color 160ms ease, color 160ms ease, transform 160ms ease;
}

.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

.btn--primary { background: var(--sage-deep); color: var(--white); }
.btn--primary:hover { background: var(--sage-dark); color: var(--white); }

.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn--ghost:hover { border-color: var(--burgundy); background: rgba(156, 106, 115, 0.07); }

.btn--block { width: 100%; }

/* Half-width submit. The forms are grid containers, so a button would
   otherwise stretch to fill the column. */
.btn--half { width: 50%; justify-self: start; }

/* Quiet note beneath a form's submit button. Matches the button's width and
   alignment so it centres under the button rather than the whole form. */
.form-note {
  /* Pulls up against the form's 22px grid gap to sit closer to the button. */
  margin: -10px 0 0;
  font-size: 0.84rem;
  color: var(--ink-faint);
  width: 50%;
  justify-self: start;
  text-align: center;
}
.btn--lg { padding: 16px 34px; font-size: 1rem; }

/* ---------- Header ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: rgba(252, 250, 246, 0.9);
  backdrop-filter: saturate(160%) blur(10px);
  -webkit-backdrop-filter: saturate(160%) blur(10px);
  border-bottom: 1px solid var(--line-soft);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  min-height: 74px;
}

.brand {
  display: inline-flex;
  /* A roofline over the words rather than a badge beside them, which is what
     the mark is drawing -- so it stacks, and centres on the text below it. */
  flex-direction: column;
  align-items: center;
  gap: 5px;
  text-decoration: none;
  color: var(--ink);
}

.brand__mark {
  display: block;
  /* The roofline spans the whole brand block, so it overhangs both the title
     and the tagline under it and lines up with the widest line's edges.
     width:0 keeps the 1561px intrinsic width out of the shrink-to-fit
     calculation for the inline-flex .brand -- a percentage min-width counts as
     zero while that is measured -- and then min-width:100% stretches the mark
     back out to whatever width the text lines settled on. */
  width: 0;
  min-width: 100%;
  /* auto, not a fixed height: the file is 1561x394 and those attributes are on
     the img so the space is reserved before it loads -- but they also set a
     used height, which would squash it. */
  height: auto;
  flex: none;
}

.brand__name { text-align: center; }

/* Header only -- the footer brand keeps the looser default. In the nav the
   roof sits right down on the words, and the tagline gets a little air beneath
   it so the block doesn't read as flush with the bottom of the bar. */
.site-header .brand { gap: 0; }
.site-header .brand__name span { padding-bottom: 6px; }

.brand__name {
  font-family: var(--font-display);
  font-size: 1.02rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.brand__name span {
  display: block;
  font-family: var(--font-body);
  font-size: 0.7rem;
  font-weight: 400;
  letter-spacing: 0.015em;
  color: var(--ink-faint);
  margin-top: 1px;
}

.nav { display: flex; align-items: center; gap: 30px; }

.nav a {
  font-size: 0.94rem;
  color: var(--ink-soft);
  text-decoration: none;
  transition: color 140ms ease;
}

/* Exclude the button so it inherits the standard .btn--primary hover
   rather than the nav link colour, which was overriding it. */
.nav a:not(.btn):hover { color: var(--ink); }
.nav a:not(.btn)[aria-current="page"] { color: var(--ink); font-weight: 500; }

.nav .btn { color: var(--white); }

.nav-toggle {
  display: none;
  background: none;
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 8px 10px;
  cursor: pointer;
  color: var(--ink);
}

/* ---------- Hero ---------- */

.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: clamp(72px, 11vw, 128px) 0 clamp(64px, 9vw, 104px);
  background:
    radial-gradient(900px 460px at 78% -10%, rgba(156, 106, 115, 0.17), transparent 62%),
    radial-gradient(760px 420px at 8% 8%, rgba(146, 168, 150, 0.2), transparent 60%),
    var(--cream);
}

/* --------------------------------------------------- the moving backdrop -- */
/*
 * Ten seconds of West Vancouver, looping forever with the sound off.
 *
 * The photograph is the floor under it: it holds the frame while the video
 * buffers, and it is what stands in when a browser declines to autoplay or a
 * reader has asked for less movement. The video fades over it once it can
 * actually play, so a slow connection never shows an empty hero.
 */
.hero__stage {
  position: absolute;
  inset: 0;
  z-index: -2;
  background-image: url("/images/hero/point-atkinson.jpg");
  background-size: cover;
  background-position: center;
}

.hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* cover, so it fills whatever shape the hero is rather than letterboxing
     into it -- the one thing a fixed-ratio video gets wrong on the web. */
  object-fit: cover;
  opacity: 0;
  transition: opacity 900ms ease;
}

.hero__video.is-playing { opacity: 1; }

/* The picture was never the problem, the movement is. Stop it and leave the
   still underneath, rather than leaving a blank hero. */
@media (prefers-reduced-motion: reduce) {
  .hero__video { display: none; }
}

/* The words have to stay readable over whatever photograph is underneath, and
   the photograph has to stay visible. A cream wash, heaviest under the text on
   the left and thinning out to the right where the card sits. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    /* Held across the text column, then dropped quickly once past it.
       
       The earlier curve was already thinning at 52%, which is where the lede's
       last words sit -- and dark ink on a dark frame under a half-strength
       wash measures about 3.8:1, under the 4.5 body text wants. Holding it to
       58% and falling away faster after costs nothing on the right, where
       there is nothing to read and the video is the point. */
    linear-gradient(100deg,
      rgba(250, 248, 245, 0.90) 0%,
      rgba(250, 248, 245, 0.88) 40%,
      rgba(250, 248, 245, 0.78) 58%,
      rgba(250, 248, 245, 0.22) 76%,
      rgba(250, 248, 245, 0.05) 100%),
    linear-gradient(to bottom,
      rgba(250, 248, 245, 0.30) 0%,
      rgba(250, 248, 245, 0) 30%,
      rgba(250, 248, 245, 0) 70%,
      rgba(250, 248, 245, 0.48) 100%);
}

/* Narrow screens put the card under the text rather than beside it, so the
   wash has to cover the whole width instead of favouring one side. */
@media (max-width: 860px) {
  /* One column, so the wash cannot favour a side -- it has to favour a height.
     Heavy through the headline and the paragraph, easing off below them where
     the rates card brings its own background and nothing needs reading
     straight off a photograph. */
  .hero::before {
    background:
      linear-gradient(to bottom,
        rgba(250, 248, 245, 0.90) 0%,
        rgba(250, 248, 245, 0.87) 46%,
        rgba(250, 248, 245, 0.62) 72%,
        rgba(250, 248, 245, 0.32) 100%);
  }
}


.hero__grid {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: clamp(40px, 6vw, 76px);
  align-items: center;
}

.hero h1 { margin-bottom: 22px; }
.hero .lede { margin-bottom: 32px; }

.hero__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 34px; }

.hero__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 26px;
  font-size: 0.9rem;
  /* Full ink rather than soft. This row sits lowest in the text column, where
     the wash is thinnest and the video busiest, so it was the first thing to
     lose its footing when the scrim came down. */
  color: var(--ink);
  font-weight: 500;
}

.hero__meta span { display: inline-flex; align-items: center; gap: 8px; }
.hero__meta svg { color: var(--sage-deep); flex: none; }

.hero__card {
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 34px 32px;
  box-shadow: 0 18px 44px rgba(63, 59, 55, 0.10);
}

.hero__card h3 { margin-bottom: 20px; }

.rate-line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 18px;
  padding: 13px 0;
  border-bottom: 1px solid var(--line-soft);
}

.rate-line:last-of-type { border-bottom: 0; }
.rate-line dt { color: var(--ink-soft); font-size: 0.95rem; }
.rate-line dd {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.16rem;
  white-space: nowrap;
}

.hero__card .note {
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid var(--line-soft);
  font-size: 0.84rem;
  color: var(--ink-faint);
}

/* ---------- Cards / grids ---------- */

.grid { display: grid; gap: 24px; }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }

.card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 32px 30px;
  display: flex;
  flex-direction: column;
}

.card__icon {
  width: 46px;
  height: 46px;
  border-radius: 13px;
  background: var(--blush);
  color: var(--burgundy-deep);
  display: grid;
  place-items: center;
  margin-bottom: 22px;
}

.card h3 { margin-bottom: 10px; }
.card p { color: var(--ink-soft); font-size: 0.97rem; }

.card__list {
  list-style: none;
  margin: 18px 0 0;
  padding: 0;
  font-size: 0.94rem;
  color: var(--ink-soft);
}

.card__list li {
  position: relative;
  padding-left: 22px;
  margin-bottom: 9px;
}

.card__list li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 0.62em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--burgundy);
}

/* A pet's photo, above their name. Fixed aspect so a portrait and a landscape
   snap sit at the same height and the cards in a row stay level, and cropped
   to the centre because that is where the animal usually is. */
.card__photo {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  object-position: center;
  border-radius: 12px;
  margin-bottom: 14px;
  background: var(--sand);
}

/* The drawn stand-in, before a photo is added. Quieter than a photograph
   would be, so a card with a real picture is plainly the more finished of
   the two and there is a reason to add one. */
.card__photo--drawn {
  color: var(--sage);
  background: var(--mist);
}

/* Question and answer inside a card, for the home details. A list would put
   each answer on one line beside its label, and these answers run to
   sentences, so the label sits above its answer instead. */
.card__pairs {
  margin: 18px 0 0;
  font-size: 0.94rem;
}

.card__pairs dt {
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 3px;
}

.card__pairs dd {
  margin: 0 0 16px;
  color: var(--ink-soft);
}

.card__pairs dd:last-of-type { margin-bottom: 0; }

/* Several answers to one question, one per line. Same marker as the card
   lists elsewhere, tighter spacing, because these sit inside an answer
   rather than being the whole of one. */
.card__lines {
  list-style: none;
  margin: 0;
  padding: 0;
}

.card__lines li {
  position: relative;
  padding-left: 16px;
  margin-bottom: 4px;
}

.card__lines li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--burgundy);
}

.card__price {
  margin-top: auto;
  padding-top: 22px;
  font-family: var(--font-display);
  font-size: 1.34rem;
  color: var(--ink);
}

.card__price small {
  font-family: var(--font-body);
  font-size: 0.82rem;
  color: var(--ink-faint);
  margin-left: 4px;
}

/* Small qualifying note pinned under a card's price. */
.card__note {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--line-soft);
  font-size: 0.86rem;
  color: var(--ink-soft);
}

.card__note svg { color: var(--burgundy-deep); flex: none; }

/* A full-width card closing out the grid. Keeps the icon, rules and bullets
   but drops the panel chrome so it reads as a footnote to the four above. */
.card--wide { grid-column: 1 / -1; }

.card--wide > p { max-width: 62ch; }
.card--wide .card__list { columns: 2; column-gap: 44px; }
.card--wide .card__list li { break-inside: avoid; }
.card--wide .card__price { margin-top: 22px; }
.card--wide .card__note { max-width: 62ch; }

@media (max-width: 720px) {
  .card--wide .card__list { columns: 1; }
}

/* ---------- Rate tables ---------- */

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--white);
}

table { width: 100%; border-collapse: collapse; min-width: 460px; }

caption {
  text-align: left;
  font-family: var(--font-display);
  font-size: 1.1rem;
  padding: 0 0 14px;
  color: var(--ink);
}

th, td {
  text-align: left;
  padding: 14px 20px;
  font-size: 0.94rem;
  border-bottom: 1px solid var(--line-soft);
}

thead th {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  background: var(--cream);
}

tbody tr:last-child td { border-bottom: 0; }
td:last-child, th:last-child { text-align: right; white-space: nowrap; }
td.amount { font-family: var(--font-display); font-size: 1.02rem; }

.rate-note {
  margin: 12px 0 0;
  font-size: 0.86rem;
  color: var(--ink-soft);
}

.rate-block + .rate-block { margin-top: 44px; }

/* ---------- Steps ---------- */

.steps { counter-reset: step; display: grid; gap: 28px; grid-template-columns: repeat(3, 1fr); }

.step { padding-top: 26px; border-top: 2px solid var(--burgundy); }
.step__num {
  counter-increment: step;
  font-family: var(--font-display);
  font-size: 0.9rem;
  color: var(--burgundy-deep);
  display: block;
  margin-bottom: 8px;
}
.step__num::before { content: "0" counter(step); }
.step h3 { margin-bottom: 8px; }
.step p { color: var(--ink-soft); font-size: 0.96rem; }

/* ---------- Zones ---------- */

.zone-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }

.zone {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px 20px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px 24px;
}

.zone strong { font-weight: 500; }
.zone em { font-style: normal; display: block; font-size: 0.9rem; color: var(--ink-soft); margin-top: 3px; }
.zone .tag { font-size: 0.84rem; color: var(--burgundy-deep); white-space: nowrap; }

/* ---------- Forms ---------- */

.form { display: grid; gap: 22px; }

/* align-content keeps inputs on a shared baseline when one field in a row
   carries a hint line and its neighbour does not. */
.field { display: grid; gap: 7px; align-content: start; }

.field > label,
.fieldset > legend {
  font-size: 0.88rem;
  font-weight: 500;
  color: var(--ink);
}

/* Applies inside .fieldset too, not just .field. */
.hint { font-size: 0.82rem; color: var(--ink-faint); }

input[type="text"], input[type="email"], input[type="tel"], input[type="date"],
input[type="number"], select, textarea {
  width: 100%;
  font-family: var(--font-body);
  font-size: 0.97rem;
  color: var(--ink);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 11px;
  padding: 12px 14px;
  transition: border-color 140ms ease, box-shadow 140ms ease;
  -webkit-appearance: none;
  appearance: none;
}

select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' stroke='%235F6B63' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 38px;
}

textarea { min-height: 130px; resize: vertical; }

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--burgundy);
  box-shadow: 0 0 0 3px rgba(156, 106, 115, 0.18);
}

.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }

.fieldset { border: 0; margin: 0; padding: 0; display: grid; gap: 12px; }

/* A legend is laid out specially, so the grid gap does not apply to it. */
.fieldset > legend { margin-bottom: 10px; }
.fieldset > legend + .hint { margin-top: -6px; }

/* Service options are grouped by how they are billed. */
.choice-groups { display: grid; gap: 28px; }

.choice-group__title {
  font-family: var(--font-body);
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--burgundy-deep);
  margin: 0 0 3px;
}

.choice-group__note {
  font-size: 0.84rem;
  color: var(--ink-faint);
  margin: 0 0 12px;
}

.choice-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.choice-col { display: grid; gap: 10px; align-content: start; }

.choice {
  position: relative;
  display: block;
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 14px 16px;
  background: var(--white);
  cursor: pointer;
  transition: border-color 140ms ease, background-color 140ms ease;
}

.choice input { position: absolute; opacity: 0; pointer-events: none; }
.choice span { display: block; font-size: 0.94rem; }
.choice small { display: block; font-size: 0.82rem; color: var(--ink-faint); margin-top: 2px; }
.choice:hover { border-color: var(--burgundy); }
.choice:has(input:checked) { border-color: var(--sage-deep); background: rgba(146, 168, 150, 0.1); }
.choice:has(input:focus-visible) { box-shadow: 0 0 0 3px rgba(156, 106, 115, 0.22); }

.counter { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 11px 0; border-bottom: 1px solid var(--line-soft); }
.counter:last-child { border-bottom: 0; }
.counter__label { font-size: 0.94rem; }
.counter__label small { display: block; font-size: 0.8rem; color: var(--ink-faint); }
.counter__ctrl { display: flex; align-items: center; gap: 4px; }

.counter__ctrl button {
  width: 32px; height: 32px;
  border: 1px solid var(--line);
  background: var(--white);
  border-radius: 9px;
  font-size: 1.05rem;
  line-height: 1;
  color: var(--ink);
  cursor: pointer;
  transition: border-color 140ms ease, background-color 140ms ease;
}

.counter__ctrl button:hover { border-color: var(--burgundy); background: var(--blush); }
.counter__ctrl output { min-width: 30px; text-align: center; font-size: 0.98rem; }

.checkline { display: flex; gap: 11px; align-items: flex-start; font-size: 0.93rem; color: var(--ink-soft); }
.checkline input { margin-top: 4px; flex: none; accent-color: var(--sage-deep); }

/* The caveat under a consent question. Its own line, quieter than the question
   it qualifies, because what is being asked should be read first. */
.checkline__note {
  display: block;
  margin-top: 4px;
  font-size: 0.82rem;
  font-style: italic;
  color: var(--ink-faint);
}

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

.booking-grid {
  display: grid;
  grid-template-columns: 1fr 372px;
  gap: 44px;
  align-items: start;
}

/* The estimate and its savings note pin together as one column. */
.summary-col { position: sticky; top: 100px; }

.summary {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 30px 28px;
}

.summary h3 { margin-bottom: 4px; }
.summary__sub { font-size: 0.86rem; color: var(--ink-faint); margin-bottom: 20px; }

.summary__lines { margin: 0 0 20px; padding: 0; list-style: none; }

.summary__lines li {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  font-size: 0.92rem;
  color: var(--ink-soft);
  padding: 8px 0;
  border-bottom: 1px solid var(--line-soft);
}

.summary__lines li span:last-child { color: var(--ink); white-space: nowrap; }
.summary__lines li.is-empty { justify-content: flex-start; color: var(--ink-faint); border-bottom: 0; }

.summary__total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding-top: 18px;
  border-top: 2px solid var(--ink);
  margin-bottom: 18px;
}

.summary__total dt { font-size: 0.88rem; letter-spacing: 0.04em; text-transform: uppercase; color: var(--ink-soft); }
.summary__total dd { margin: 0; font-family: var(--font-display); font-size: 1.85rem; }

.summary .note { font-size: 0.82rem; color: var(--ink-faint); margin-top: 16px; }
/* Two classes so it outranks .hero__card .note as well as .summary .note. */
.note.note--fine { font-size: 0.76rem; margin-top: 10px; }

/* Savings note under the estimate, shown for monthly packages. */
.savings {
  margin-top: 16px;
  background: var(--mist);
  border: 1px solid var(--sage);
  border-radius: var(--radius-lg);
  padding: 24px 26px;
  text-align: center;
}

.savings__emoji {
  display: block;
  font-size: 1.9rem;
  line-height: 1;
  margin-bottom: 10px;
  animation: tada 2.4s ease-in-out infinite;
  transform-origin: center bottom;
}

.savings__label {
  margin: 0;
  font-size: 0.74rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--sage-dark);
}

.savings__amount {
  margin: 4px 0 8px;
  font-family: var(--font-display);
  font-size: 2rem;
  line-height: 1.1;
  color: var(--sage-dark);
}

.savings__compare {
  margin: 0;
  font-size: 0.84rem;
  line-height: 1.5;
  color: var(--ink-soft);
}

.savings__emoji--pet { animation: wag 2s ease-in-out infinite; }
.savings__emoji--cat { animation: swoon 2.2s ease-in-out infinite; }

/* A double pulse, like a heartbeat, which suits heart eyes better than a
   tail wag does. */
@keyframes swoon {
  0%, 100% { transform: scale(1) rotate(0deg); }
  14%      { transform: scale(1.16) rotate(-5deg); }
  28%      { transform: scale(1) rotate(0deg); }
  42%      { transform: scale(1.16) rotate(5deg); }
  56%      { transform: scale(1) rotate(0deg); }
}

@keyframes wag {
  0%, 100% { transform: translateY(0) rotate(0deg) scale(1); }
  12%      { transform: translateY(-5px) rotate(-9deg) scale(1.06); }
  24%      { transform: translateY(0) rotate(0deg) scale(1); }
  36%      { transform: translateY(-5px) rotate(9deg) scale(1.06); }
  48%      { transform: translateY(0) rotate(0deg) scale(1); }
}

@keyframes tada {
  0%, 60%, 100% { transform: scale(1) rotate(0deg); }
  10%           { transform: scale(0.92) rotate(-6deg); }
  20%, 40%      { transform: scale(1.12) rotate(6deg); }
  30%, 50%      { transform: scale(1.12) rotate(-6deg); }
}

/* ---------- Status / alerts ---------- */

.status {
  border-radius: 12px;
  padding: 14px 18px;
  font-size: 0.92rem;
  border: 1px solid var(--line);
  background: var(--white);
}

.status[hidden] { display: none; }
.status--ok { border-color: var(--sage); background: rgba(146, 168, 150, 0.14); color: var(--sage-dark); }
.status--err { border-color: #E0BDB0; background: #FBF0EB; color: #8A4B32; }
.status--info { border-color: var(--sky); background: rgba(175, 196, 206, 0.16); color: #3E5A67; }

/* ---------- Member area ---------- */

/* What is still missing, above the tabs so it is the first thing read and the
   panels it names are one click away. Blush rather than the sage of an
   ordinary notice, because this asks rather than informs. */
.setup {
  padding: 22px 24px;
  margin-bottom: 30px;
  border: 1px solid #E7D3D6;
  border-radius: var(--radius);
  background: var(--blush);
}

.setup__lede { margin: 0 0 14px; font-size: 0.95rem; color: var(--ink-soft); }
.setup__lede strong { color: var(--ink); }

.setup__steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }

.setup__steps > li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  font-size: 0.92rem;
}

/* A tick that is a tick rather than an emoji, so it takes the page's colour
   and cannot arrive as a missing glyph. */
.setup__steps > li::before {
  content: "";
  flex: none;
  width: 16px;
  height: 16px;
  margin-top: 2px;
  border-radius: 50%;
  border: 1px solid var(--burgundy);
  background: transparent;
}

.setup__steps > li[data-done="true"]::before {
  border-color: var(--sage-deep);
  background: var(--sage-deep) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 8.5l2.5 2.5L12 5.5' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/12px no-repeat;
}

.setup__steps > li[data-done="true"] .setup__name { color: var(--ink-faint); }

.setup__name { font-weight: 500; color: var(--ink); }

.setup__name--go {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-weight: 500;
  color: var(--burgundy-deep);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.setup__name--go:hover { color: var(--burgundy-dark); }

.setup__missing { color: var(--ink-soft); }

/* Said out loud, so nobody feels chased for something they may not have. */
.setup__optional {
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 1px 8px;
}

/* Two buttons side by side, where one of them may not be there. */
/* The foot of the member page: the way onward, then the way out. Stacked and
   left aligned, so a link and a button do not line up as a pair of equals. */
.page-foot { display: flex; flex-direction: column; align-items: flex-start; gap: 20px; }

/* Going somewhere, not doing something. The arrow points the way and steps
   forward a little when you reach for it. */
.link-onward {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--sage-dark);
}

.link-onward svg { transition: transform 160ms ease; }
.link-onward:hover svg { transform: translateX(3px); }

@media (prefers-reduced-motion: reduce) {
  .link-onward svg { transition: none; }
  .link-onward:hover svg { transform: none; }
}

.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 40px;
}

.tabs__tab {
  appearance: none;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  padding: 12px 16px;
  margin-bottom: -1px;
  font-family: var(--font-body);
  font-size: 0.95rem;
  color: var(--ink-soft);
  cursor: pointer;
  transition: color 140ms ease, border-color 140ms ease;
}

/* No hover state. The underline marks where you are; a second, fainter signal
   following the pointer around says something is selected when nothing is. */

.tabs__tab[aria-selected="true"] {
  color: var(--ink);
  font-weight: 500;
  border-bottom-color: var(--burgundy);
}

.tabs__panel > h2 { font-size: 1.5rem; margin-bottom: 6px; }

/* A pet or home entry, repeatable. */
.entry {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 26px 24px;
  margin-bottom: 18px;
}

/* The job a sitter arrived to see, from the link in their offer email. A ring
   rather than a change of background, so it reads as the same card being
   pointed at rather than a different kind of card. */
.entry--focus {
  border-color: var(--sage-deep);
  box-shadow: 0 0 0 3px rgba(92, 117, 101, 0.16);
  transition: box-shadow 400ms ease, border-color 400ms ease;
}

@media (prefers-reduced-motion: reduce) {
  .entry--focus { transition: none; }
}

.entry__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
}

.entry__head h3 { margin: 0; font-size: 1.1rem; }

.entry__remove {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  font-family: var(--font-body);
  font-size: 0.84rem;
  color: var(--ink-faint);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.entry__remove:hover { color: #8A4B32; }

.pet-photo {
  width: 68px;
  height: 68px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--line);
  background: var(--mist);
}

/* Visit log entry */
.visit {
  border-left: 2px solid var(--burgundy);
  padding: 2px 0 2px 20px;
  margin-bottom: 26px;
}

.visit__date {
  font-size: 0.74rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 4px;
}

.visit__summary { margin: 0 0 6px; font-size: 1.02rem; }
.visit__notes { margin: 0; font-size: 0.95rem; color: var(--ink-soft); }

.visit__media {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 10px;
  font-size: 0.9rem;
}

/* Calendar placeholder: a drawn month, not a real one. */
.calendar-placeholder {
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--white);
  padding: 26px;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 8px;
  position: relative;
  overflow: hidden;
}

.calendar-placeholder::after {
  content: "Live availability coming soon";
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(252, 250, 246, 0.82);
  font-size: 0.95rem;
  color: var(--ink-soft);
  letter-spacing: 0.02em;
}

.calendar-placeholder span {
  aspect-ratio: 1;
  border-radius: 8px;
  background: var(--mist);
}

.calendar-placeholder span.is-busy { background: var(--blush); }
.calendar-placeholder span.is-head {
  aspect-ratio: auto;
  background: none;
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  text-align: center;
}

@media (max-width: 720px) {
  .tabs { gap: 0; }
  .tabs__tab { padding: 10px 12px; font-size: 0.9rem; }
}

/* ---------- Contact ---------- */

.contact-grid { display: grid; grid-template-columns: 1fr 380px; gap: 56px; align-items: stretch; }

/* The aside fills the row height. The detail list grows to take the slack and
   spreads its entries evenly, which leaves the call to action sitting at the
   bottom, level with the form's submit button. 22px stays the minimum gap. */
.contact-aside { display: flex; flex-direction: column; }

.contact-aside .detail-list {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.cta-block { padding-top: 22px; }

.detail-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 22px; }
.detail-list dt { font-size: 0.74rem; letter-spacing: 0.13em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 5px; }
.detail-list dd { margin: 0; font-size: 1rem; }
.detail-list dd a { text-decoration: none; }

/* Sidebar call to action, matching the detail-list label and value styling. */
.cta-label {
  display: block;
  font-size: 0.74rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 5px;
}

.cta-sub {
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--ink-soft);
  /* Padding rather than margin so it cannot collapse through the wrapper. */
  margin: 0;
  padding-bottom: 34px;
}

.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  cursor: pointer;
  padding: 20px 0;
  font-size: 1.02rem;
  list-style: none;
  display: flex;
  justify-content: space-between;
  gap: 20px;
  align-items: center;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--burgundy-deep); font-size: 1.3rem; line-height: 1; }
.faq details[open] summary::after { content: "\2013"; }
.faq details p { padding: 0 0 20px; color: var(--ink-soft); max-width: 68ch; }

/* ---------- CTA band ---------- */

.cta-band {
  background: var(--sage-dark);
  color: var(--white);
  border-radius: var(--radius-lg);
  padding: clamp(44px, 6vw, 68px);
  text-align: center;
}

.cta-band h2 { color: var(--white); }
.cta-band p { color: rgba(255, 255, 255, 0.82); max-width: 54ch; margin: 0 auto 14px; }
.cta-band p:last-of-type { margin-bottom: 28px; }
.cta-band .btn--primary { background: var(--white); color: var(--sage-dark); }
.cta-band .btn--primary:hover { background: var(--sand); color: var(--sage-dark); }

/* ---------------------------------------------------- photographs -- */
/*
 * Three places the site carries a picture. Everywhere else stays
 * typographic on purpose -- the calm comes from the space, and a photograph
 * in every section would spend it.
 */

/* The closing call to action, with the picture beside it rather than behind.
   Behind was tried: the overlay has to be heaviest exactly where the heading
   sits, which is exactly where the subject of the photograph was. */
.cta-split {
  display: grid;
  grid-template-columns: 0.9fr 1.1fr;
  gap: clamp(20px, 3vw, 36px);
  align-items: stretch;
}

.cta-split .cta-band { text-align: left; }
.cta-split .cta-band p { margin-left: 0; }

.cta-figure {
  margin: 0;
  border-radius: var(--radius-lg);
  overflow: hidden;
  min-height: 320px;
}

.cta-figure img { width: 100%; height: 100%; object-fit: cover; display: block; }

@media (max-width: 820px) {
  .cta-split { grid-template-columns: 1fr; }
  .cta-figure { min-height: 220px; }
}

/* The service area, with the picture beside the copy. */
.area-split {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(28px, 4vw, 56px);
  align-items: center;
  /* The zone cards underneath set margin:0, and the section-head that used to
     hold this section apart is inside the split now with its own margin
     cleared -- so without this the photograph sits directly on the first
     card. Same rhythm as a section-head's own gap. */
  margin-bottom: clamp(34px, 4.5vw, 52px);
}

/* In the split it is a column, not the whole section's opening, so its own
   bottom margin would push the photograph out of alignment with it. */
.area-split .section-head { margin-bottom: 0; }

.area-figure { margin: 0; position: relative; }

/* A wash up from the bottom edge, so the caption has something to sit on.
   White on a photograph is only legible until the photograph changes -- and
   this one is a driveway at dusk, which is dark in the corner today and would
   not be if the picture were ever swapped. */
.area-figure::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 45%;
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
  background: linear-gradient(to top, rgba(20, 24, 21, 0.62), rgba(20, 24, 21, 0));
  pointer-events: none;
}

/* The radius belongs on the image, not the figure. On the figure it also
   wraps the caption underneath, so the only corners that ever got clipped
   were the two where the image met the figure's own edge -- top left and top
   right -- and the bottom two stayed square. */
.area-figure img {
  width: 100%;
  display: block;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: var(--radius-lg);
}

/* z-index because ::after is generated as the last child, so without it the
   wash meant to sit behind the caption paints over the top of it. */
.area-figure figcaption {
  position: absolute;
  right: 22px;
  bottom: 16px;
  z-index: 1;
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--white);
  text-align: right;
}

@media (max-width: 820px) { .area-split { grid-template-columns: 1fr; } }

/* A card that opens with a photograph. The card's own padding is lifted so
   the picture can reach the edges, then put back on everything under it --
   including a gap above the heading, so the words are not sitting on the
   image the way they would in a news listing. */
.card--photo { padding: 0; overflow: hidden; }

.card--photo > .card__media {
  display: block;
  width: 100%;
  /* height:auto is load-bearing. The width and height attributes on the img --
     which are there so the space is reserved before it loads -- map to CSS as
     presentational hints, and a used height beats aspect-ratio. Without this
     a 1069x1008 photograph renders 1008px tall inside a 522px column. */
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
}

/* The wide card spans the whole grid, so the same crop would be a wall of
   photograph. Shallower, so it reads as a band across the top.

   Only while it is actually wide, though. Once the grid drops to one column
   that card is no broader than its neighbours, and 3:1 across 277px is a
   ninety pixel sliver with a cat somewhere in it. */
@media (min-width: 720px) {
  .card--wide.card--photo > .card__media { aspect-ratio: 3 / 1; }
}

.card--photo > *:not(.card__media) { padding-left: 30px; padding-right: 30px; }
.card--photo > .card__media + * { margin-top: 28px; }
.card--photo > :last-child { padding-bottom: 32px; }

/* ---------- Footer ---------- */

main { flex: 1 0 auto; }

.site-footer {
  margin-top: auto;
  background: var(--sand);
  border-top: 1px solid var(--line);
  padding: 62px 0 34px;
  font-size: 0.92rem;
  color: var(--ink-soft);
}

.site-footer__grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: 40px;
  padding-bottom: 40px;
}

.site-footer h4 {
  font-family: var(--font-body);
  font-size: 0.73rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 14px;
}

.site-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.site-footer a { color: var(--ink-soft); text-decoration: none; }
.site-footer a:hover { color: var(--ink); }

.site-footer__base {
  border-top: 1px solid var(--line);
  padding-top: 24px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 24px;
  justify-content: space-between;
  font-size: 0.84rem;
  color: var(--ink-faint);
}

/* ---------- Utility ---------- */

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

.stack-sm > * + * { margin-top: 12px; }
.text-center { text-align: center; }
.mt-md { margin-top: 34px; }
.mt-lg { margin-top: 56px; }

/* ---------- Responsive ---------- */

@media (max-width: 960px) {
  :root { --section: 76px; }
  .hero__grid { grid-template-columns: 1fr; }
  .grid--3, .grid--4, .steps { grid-template-columns: repeat(2, 1fr); }
  .booking-grid, .contact-grid { grid-template-columns: 1fr; gap: 36px; }
  .summary { position: static; }
  .site-footer__grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 720px) {
  body { font-size: 16px; }
  .nav {
    display: none;
    position: absolute;
    top: 74px; left: 0; right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    background: var(--cream);
    border-bottom: 1px solid var(--line);
    padding: 14px var(--gutter) 22px;
  }
  .nav.is-open { display: flex; }
  .nav a { padding: 10px 0; }
  .nav .btn { margin-top: 8px; justify-content: center; }
  .nav-toggle { display: block; }
  .site-header__inner { position: relative; }
  .grid--3, .grid--4, .grid--2, .steps, .field-row, .choice-grid { grid-template-columns: 1fr; }
  .btn--half, .form-note { width: 100%; }
  .site-footer__grid { grid-template-columns: 1fr; gap: 30px; }
  .card { padding: 26px 24px; }
}

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

@media print {
  .site-header, .site-footer, .hero__actions, .nav-toggle { display: none; }
}

/* Where to send an e-Transfer. Read only on purpose: the client sends money
   to us, so there is nothing here for them to fill in. */
.payinfo {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 20px 22px;
  background: var(--white);
}

.payinfo h3 {
  margin: 0 0 10px;
  font-size: 0.74rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 500;
}

.payinfo p { margin: 0 0 8px; font-size: 0.92rem; color: var(--ink-soft); max-width: 56ch; }
.payinfo p:last-child { margin-bottom: 0; }

.payinfo__to {
  font-size: 1.05rem;
  color: var(--ink);
  word-break: break-all;
}

/* The booking reference a client quotes when paying. Monospaced so a letter
   cannot be mistaken for a digit when it is copied by hand. */
.payref {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.86rem;
  letter-spacing: 0.06em;
  background: var(--mist);
  border-radius: 6px;
  padding: 2px 8px;
  white-space: nowrap;
  display: inline-block;
}

/* One booking's code and the stay it belongs to, so a client can tell which
   is which without leaving the page. */
.payinfo__ref {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 12px;
  margin: 0 0 10px;
}

.payinfo__for { font-size: 0.86rem; color: var(--ink-faint); }

/* Long-form policy pages. Narrower measure and more air between sections than
   marketing copy, because these are read carefully rather than skimmed. */
.prose { max-width: 68ch; }

.prose h2 {
  font-size: 1.35rem;
  margin: 46px 0 14px;
  padding-top: 26px;
  border-top: 1px solid var(--line);
}

.prose h2:first-child { margin-top: 0; padding-top: 0; border-top: 0; }

.prose h3 {
  font-size: 1.02rem;
  font-family: var(--font-body);
  font-weight: 600;
  letter-spacing: 0;
  margin: 26px 0 8px;
}

.prose p { line-height: 1.75; color: var(--ink-soft); margin: 0 0 16px; }
.prose p strong { color: var(--ink); font-weight: 600; }

.prose ul { margin: 0 0 16px; padding-left: 20px; }
.prose li { line-height: 1.75; color: var(--ink-soft); margin-bottom: 6px; }

/* Staff dashboard ---------------------------------------------------------- */

/* The board: an index down the left, the cards on the right.
 *
 * Three named areas rather than a wrapper around the left column, for two
 * reasons the wrapper could not manage. The cards start on the same row as
 * the first index entry, so the two columns begin level instead of the cards
 * floating 68px above the list they belong to. And the left column is `auto`
 * with the spacing carried on margins rather than grid gaps, so when there is
 * no index the column is genuinely zero wide — a fixed track with a gap left
 * the queues indented by 292px of nothing.
 *
 * Below 900px it all stacks: a sidebar on a phone is only a column of cards
 * you have to scroll past to reach the cards. */
.board {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas:
    "sort  ."
    "index cards";
  align-items: start;
}

.board__sort {
  grid-area: sort;
  display: grid;
  gap: 4px;
  width: 236px;
  margin: 0 32px 12px 0;
}

.board__sort > span {
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.board__sort select { width: 100%; font-size: 0.86rem; padding: 8px 12px; }

.board__nav {
  grid-area: index;
  position: sticky;
  top: 24px;
  display: grid;
  gap: 6px;
  width: 236px;
  margin-right: 32px;
  max-height: calc(100vh - 48px);
  overflow-y: auto;
  /* Room for the scrollbar so the last item is never half-hidden under it. */
  padding-right: 4px;
}

#dash-list { grid-area: cards; min-width: 0; }

.board__job {
  display: grid;
  gap: 2px;
  text-align: left;
  padding: 10px 12px;
  border: 1px solid transparent;
  border-radius: 10px;
  background: none;
  font-family: var(--font-body);
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease;
}

.board__job:hover { background: var(--white); border-color: var(--line); }

/* The one being read. Filled rather than outlined, because on a list this
   long an outline is what every item gets on hover. */
.board__job[aria-current="true"] {
  background: var(--sage-deep);
  border-color: var(--sage-deep);
}

.board__job[aria-current="true"] strong,
.board__job[aria-current="true"] span,
.board__job[aria-current="true"] .board__job-who { color: var(--white) !important; }

.board__job:focus-visible { outline: 2px solid var(--sage-deep); outline-offset: 2px; }

.board__job strong {
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  color: var(--burgundy-deep);
  font-variant-numeric: tabular-nums;
}

.board__job span { font-size: 0.82rem; color: var(--ink-soft); }

.board__job-who {
  color: var(--ink-faint) !important;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 900px) {
  .board { grid-template-columns: 1fr; grid-template-areas: "sort" "index" "cards"; }

  .board__sort {
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: 10px;
    width: auto;
    margin: 0 0 10px;
  }

  .board__sort select { max-width: 220px; }

  .board__nav {
    position: static;
    width: auto;
    margin: 0 0 18px;
    max-height: none;
    display: flex;
    gap: 8px;
    overflow-x: auto;
    padding: 0 0 6px;
    /* The strip may run past the container; let it, rather than squeezing
       every job into a width none of them can be read at. */
    scroll-snap-type: x proximity;
  }

  .board__job {
    flex: 0 0 auto;
    min-width: 168px;
    border-color: var(--line);
    background: var(--white);
    scroll-snap-align: start;
  }
}

@media (prefers-reduced-motion: reduce) {
  .board__job { transition: none; }
}


.filters { display: flex; flex-wrap: wrap; gap: 8px; }

.filters__chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--line);
  background: var(--white);
  border-radius: 999px;
  padding: 8px 16px;
  font: inherit;
  font-size: 0.9rem;
  color: var(--ink-soft);
  cursor: pointer;
}

.filters__chip:hover { border-color: var(--burgundy); }

/* How many are waiting in a panel you are not looking at. Burgundy, because
   on this page burgundy marks things rather than doing them, and a count is a
   label on a chip and not a second button inside it. */
.filters__count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--blush);
  color: var(--burgundy-dark);
  font-size: 0.74rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* On the selected chip the ground is sage, so the bubble borrows from it
   rather than sitting on it as a second colour. */
.filters__chip[aria-selected="true"] .filters__count {
  background: rgba(255, 255, 255, 0.22);
  color: var(--white);
}

.filters__chip[aria-selected="true"] {
  background: var(--sage-deep);
  border-color: var(--sage-deep);
  color: #fff;
}

/* The status, and anything that qualifies it, kept together on the right of
   the head so the eye finds a booking's state in one place. */
.entry__tags { display: inline-flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }

/* Money that went back. Burgundy because on this page burgundy marks things
   rather than doing them, and filled rather than outlined because it is the
   one fact on a settled card worth seeing from across the list. */
.entry__refund {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--blush);
  color: var(--burgundy-dark);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* How far through the member area a client has got. Burgundy while there is
   something to chase, quiet once there is not: a finished one still shows,
   because an absent badge would mean both "done" and "never started". */
.entry__setup {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--blush);
  color: var(--burgundy-dark);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: help;
}

.entry__setup--done {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--ink-faint);
  font-weight: 500;
  cursor: default;
}

/* The mark on the end of a badge: a tick normally, two arrows round a tick
   once a client has changed something since. Sized to the tick it replaces and
   nudged up, because a glyph sits on the baseline and an svg box does not. */
.entry__mark {
  /* Bigger than the tick it stands in for. The badge text is 0.7rem, so a mark
     matched to it would be eleven pixels of ring, arrow and tick, which is
     four pixels of each and legible as none of them. */
  width: 1.5em;
  height: 1.5em;
  vertical-align: -0.45em;
  margin-left: 0.15em;
}

/* Changed since it mattered. Green rather than burgundy, because a client
   keeping their own details current is good news and burgundy is the colour
   this site uses for things that still need chasing. The border is the CTA
   green exactly; the fill is its pale counterpart, the same relationship the
   blush has to the burgundy. */
.entry__setup--moved {
  position: relative;
  border: 1px solid var(--sage-deep);
  background: var(--mist);
  color: var(--sage-dark);
  cursor: help;
  /* It is a button now; none of that should show. */
  font: inherit;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: inherit;
}

/* How long ago, inline, where there is room for it. */
.entry__when {
  margin-left: 0.55em;
  padding-left: 0.55em;
  border-left: 1px solid rgba(92, 117, 101, 0.35);
  font-weight: 500;
}

/* Below this a job card is one column and the badge shares its row with the
   status, so the timestamp comes off the pill and lives behind a tap. */
@media (max-width: 640px) {
  .entry__when { display: none; }
}

/* The tap bubble. :focus, not a click handler: tapping a button focuses it and
   tapping anywhere else lets it go, which is the whole behaviour. */
.entry__setup--moved:focus { outline: 2px solid var(--sage-deep); outline-offset: 2px; }

.entry__setup--moved:focus::after {
  content: attr(data-note);
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 20;
  min-width: max-content;
  max-width: 62vw;
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--ink);
  color: var(--cream);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  text-transform: none;
  white-space: normal;
  box-shadow: 0 6px 20px rgba(43, 52, 46, 0.22);
}

/* Everything, condensed: a row to find a booking in, not one to act on. */
.entry--slim { padding: 20px 24px; margin-bottom: 12px; }
.entry--slim .entry__head { margin-bottom: 4px; }
.entry--slim .entry__head h3 { font-size: 1rem; }
.entry--slim .entry__facts { margin-bottom: 0; gap: 10px 28px; }
.entry--slim .entry__facts dt { font-size: 0.7rem; }
.entry--slim .entry__facts dd { font-size: 0.88rem; }

.entry__tag {
  font-size: 0.74rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
}

.entry__meta {
  font-size: 0.82rem;
  color: var(--ink-faint);
  margin: -6px 0 16px;
}

/* Two columns of label/value on a desktop, one on a phone, because a sitter
   reads this standing outside a house. */
.entry__facts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px 28px;
  margin: 0 0 20px;
}

/* Label above value rather than beside it. Three to a row leaves no honest
   width for a 110px label column, and an address wrapping under its own
   heading reads better than one squeezed beside it. */
.entry__facts > div { display: grid; gap: 2px; align-content: start; }

/* Notes is prose, not a field. It takes the whole width and therefore always
   starts its own row, which is what keeps the six above it in their places. */
.entry__facts > [data-wide] { grid-column: 1 / -1; }

.entry__facts dt {
  font-size: 0.74rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.entry__facts dd { font-size: 0.92rem; margin: 0; overflow-wrap: anywhere; }

/* A second way to use the same fact, kept quiet beside the first: the number
   is the thing, "text" is a shortcut. */
.entry__aside {
  margin-left: 8px;
  font-size: 0.8rem;
  color: var(--ink-faint);
}

.entry__aside:hover { color: var(--burgundy-deep); }

@media (max-width: 860px) { .entry__facts { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .entry__facts { grid-template-columns: 1fr; } }

/* What a sitter is walking into, under the booking it belongs to. Set off by
   a rule rather than boxed, because it is more of the same card and not a
   separate object sitting inside one. */
.job-brief {
  border-top: 1px solid var(--line-soft);
  padding-top: 20px;
  margin-bottom: 20px;
}

.job-brief h4 {
  margin: 0 0 12px;
  font-family: var(--font-body);
  font-size: 0.74rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.job-brief .entry__facts { margin-bottom: 0; }
.job-brief h4 + .job-pets { margin-bottom: 22px; }

/* One pet per row rather than several across. Care notes are the longest and
   most important thing on this card, and two columns of them gave the reading
   width of a newspaper column to text somebody has to follow at 6am. A pet
   with nothing special about it simply leaves the right half empty. */
.job-pets { display: grid; gap: 22px; }

/* The animal on the left, what to do about it on the right. Care notes run to
   paragraphs — feeding times, medication, how long at the dog park — and a
   column beside a thumbnail turned them into a stack of two-word lines. */
.job-pet { display: grid; grid-template-columns: 168px 1fr; gap: 18px; align-items: start; }

.job-pet__who { display: grid; gap: 3px; min-width: 0; }

/* As wide as the name under it, so the two read as one object. 4:3 because a
   portrait and a landscape snap should leave the cards in a row level. */
.job-pet__photo {
  width: 100%;
  aspect-ratio: 4 / 3;
  border-radius: 12px;
  object-fit: cover;
  border: 1px solid var(--line);
  background: var(--mist);
  margin-bottom: 6px;
}

.job-pet__photo--none { background: var(--sand); }

.job-pet__who strong { font-family: var(--font-heading); font-weight: 500; font-size: 0.98rem; }
.job-pet__who span { font-size: 0.84rem; color: var(--ink-faint); }

/* The part that changes what a sitter actually does, given room to be read. */
.job-pet__notes {
  font-size: 0.88rem;
  font-style: italic;
  line-height: 1.6;
  color: var(--burgundy-deep);
  overflow-wrap: anywhere;
}

@media (max-width: 620px) {
  .job-pets { grid-template-columns: 1fr; }
  .job-pet { grid-template-columns: 1fr; gap: 10px; }
  .job-pet__photo { max-width: 200px; }
}

.entry__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 10px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}

.entry__price { display: grid; gap: 4px; }
.entry__price span { font-size: 0.86rem; color: var(--ink-faint); }
.entry__price input { width: 130px; }

/* Standing down: the reason, then the confirm. Full width of the action row,
   so it reads as a step rather than another control in the line. */
.entry__standdown { flex-basis: 100%; display: grid; gap: 12px; max-width: 520px; }
.entry__standdown label { display: grid; gap: 4px; }

.entry__standdown label > span {
  font-size: 0.74rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.entry__standdown textarea { width: 100%; min-height: 64px; resize: vertical; }
.entry__standdown-actions { display: flex; flex-wrap: wrap; gap: 10px; }

/* The booking under review, as fields. Same grid as the read-only card above
   it, so a booking does not jump about when it stops being editable: the
   labels stay where the eye already learned to find them. */
.entry__edit {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px 28px;
  margin: 0 0 22px;
}

.entry__edit > label { display: grid; gap: 4px; align-content: start; min-width: 0; }
.entry__edit > [data-span="2"] { grid-column: span 2; }
.entry__edit > [data-wide] { grid-column: 1 / -1; }

.entry__edit > label > span {
  font-size: 0.74rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.entry__edit input,
.entry__edit select,
.entry__edit textarea { width: 100%; }

.entry__edit textarea { min-height: 74px; resize: vertical; }

@media (max-width: 860px) {
  .entry__edit { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .entry__edit > [data-span="2"] { grid-column: 1 / -1; }
}

@media (max-width: 560px) {
  .entry__edit { grid-template-columns: 1fr; }
}

.entry__hint {
  flex-basis: 100%;
  margin: 0;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

.btn--sm { padding: 9px 18px; font-size: 0.88rem; }

/* The team, below the booking queue. A rule across the top rather than a box
   around it, because this is a second subject on the page and not a card in
   the same list as the bookings above it. */
.team {
  border-top: 1px solid var(--line);
  padding-top: 40px;
}

.team > h2 { font-size: 1.5rem; margin-bottom: 6px; }

/* Several to a row, and they wrap rather than stretch: a team of two should
   read as two tiles, not as two bands across the whole page. */
.people {
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fill, minmax(258px, 1fr));
}

/* The same card as a client's own details on the account page, smaller.
   Nothing here is waiting on a decision, so it is lighter than a booking. */
.person {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px 22px;
}

.person__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.person__head h3 {
  margin: 0;
  font-family: var(--font-heading);
  font-weight: 500;
  font-size: 1rem;
  overflow-wrap: anywhere;
}

.person .card__list { margin-top: 12px; font-size: 0.87rem; }
.person .card__list li { padding-left: 17px; margin-bottom: 6px; }
.person .card__list li:last-child { margin-bottom: 0; }
.person .card__list li::before { left: 0; top: 0.58em; width: 5px; height: 5px; }

.person__gap {
  margin: 12px 0 0;
  font-size: 0.82rem;
  color: var(--burgundy-deep);
}

/* Something to know, not something to do, so it stays quiet where the gap
   above it does not. */
.person__note {
  margin: 10px 0 0;
  font-size: 0.8rem;
  color: var(--ink-faint);
}

/* One thing we need from the person reading, sitting above the work. Blush
   rather than the sage of an ordinary notice, because this asks rather than
   informs. */
.nudge {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  background: var(--blush);
  border: 1px solid #E7D3D6;
  border-radius: var(--radius);
  padding: 18px 22px;
  margin-bottom: 26px;
}

.nudge p {
  margin: 0;
  max-width: 56ch;
  font-size: 0.93rem;
  color: var(--ink-soft);
}

.nudge strong { color: var(--ink); }

/* A slow breath, not a blink. The ring grows out of the button's own edge and
   fades, so at any instant the page is still: it catches the eye on the way
   past without anything to look at once you have looked. */
@keyframes cta-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(92, 117, 101, 0.38); }
  70%  { box-shadow: 0 0 0 15px rgba(92, 117, 101, 0); }
  100% { box-shadow: 0 0 0 0 rgba(92, 117, 101, 0); }
}

.cta-pulse { animation: cta-pulse 3s ease-out infinite; }

@media (prefers-reduced-motion: reduce) {
  .cta-pulse { animation: none; }
}

/* Honeypot. Off-screen rather than display:none, because a field that is not
   rendered at all is easier for a bot to notice and skip. A human never sees
   it, never tabs into it, and a screen reader never announces it. */
.hp {
  position: absolute !important;
  left: -9999px !important;
  top: auto !important;
  width: 1px !important;
  height: 1px !important;
  overflow: hidden !important;
}

/* -------------------------------------------------------- the job log -- */
/* The record of who was in the house and when. Sits below the client brief
   and above the actions, because it is what happened rather than what to
   decide next. */
.joblog {
  margin: 16px 0 0;
  padding: 16px 18px;
  border: 1px solid var(--line-soft);
  border-radius: 12px;
  background: var(--cream);
}

.joblog__title {
  margin: 0 0 10px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.joblog__count {
  display: inline-block;
  margin-left: 4px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--sand);
  color: var(--ink-soft);
}

/* Standing advice above the work rather than an alert about it: same shape as
   a status line, quieter, and it does not sit on top of the first card. */
.dash-note { margin-bottom: 14px; font-size: 0.88rem; line-height: 1.5; }
.dash-note strong { display: block; margin-bottom: 2px; }

.joblog__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }

.joblog__list > li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 12px;
  font-size: 0.9rem;
}

.joblog__day { min-width: 6.5em; font-weight: 500; }
.joblog__span { color: var(--ink-soft); font-variant-numeric: tabular-nums; }

/* What is still owed on that visit. Quiet until it is late. */
.joblog__video {
  font-size: 0.78rem;
  color: var(--ink-faint);
}
.joblog__video--done { color: var(--sage-deep); }
.joblog__video--late { color: var(--burgundy-deep); font-weight: 500; }

.joblog__empty { margin: 0; font-size: 0.9rem; color: var(--ink-faint); font-style: italic; }

.joblog__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
  margin-top: 14px;
}

.joblog__now { font-size: 0.85rem; color: var(--ink-soft); }

/* ------------------------------------------------- a sitter is here now -- */
/* The one thing on the member area worth interrupting somebody for. Green
   rather than the burgundy used for things that need doing: this is not a task,
   it is reassurance that the person you are paying has arrived. */
.visit-now {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin: 0 0 18px;
  padding: 14px 18px;
  border: 1px solid var(--sage-deep);
  border-radius: 12px;
  background: var(--mist);
  color: var(--sage-dark);
}

/* A quiet pulse, because the state it marks is genuinely live. Anyone who has
   asked not to see motion gets a plain dot. */
.visit-now::before {
  content: "";
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  margin-top: 7px;
  border-radius: 50%;
  background: var(--sage-deep);
  animation: visit-pulse 2.4s ease-in-out infinite;
}

@keyframes visit-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.45; transform: scale(0.82); }
}

@media (prefers-reduced-motion: reduce) {
  .visit-now::before { animation: none; }
}

.visit-now__line { margin: 0; font-size: 0.95rem; }
.visit-now__line strong { color: var(--sage-dark); }

/* The matching row in the log below, while it is still open. */
.visit--now { border-left: 3px solid var(--sage-deep); padding-left: 14px; }

/* ------------------------------------------------- the client's visit log -- */
/* Visits sit under the booking they belong to. The booking is the thing a
   client recognises -- "our week in October" -- so it carries the heading and
   the dates do the identifying. */
.visit-group { margin: 0 0 26px; }
.visit-group:last-child { margin-bottom: 0; }

.visit-group__title {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  margin: 0 0 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--line-soft);
  font-size: 1.02rem;
  font-weight: 600;
}

.visit-group__when { font-weight: 400; font-size: 0.9rem; color: var(--ink-soft); }

/* Full width so it drops below the service, dates and count rather than
   competing with them on the same line. */
/* Notes read as a short account, so they are a list rather than a paragraph:
   each one its own line with the time it was written in front of it. */
.visit__notes {
  margin: 8px 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 5px;
  font-size: 0.9rem;
  color: var(--ink-soft);
}
.visit__notewhen,
.joblog__notewhen {
  font-variant-numeric: tabular-nums;
  font-size: 0.78rem;
  color: var(--ink-faint);
}

/* Notes read across under the times rather than down the side of them: one
   line each is how they were written, and a visit rarely has many. */
.joblog__noterow {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 16px;
}
.joblog__notes {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 16px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Sits between the booking's heading and its visits, because that is where
   somebody looks when they want the person rather than the record. */
.visit-group__reach {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 12px;
  margin: 0 0 14px;
  padding: 10px 14px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--blush);
  font-size: 0.88rem;
  color: var(--ink-soft);
}

.visit-group__sitter {
  flex: 0 0 100%;
  font-weight: 400;
  font-size: 0.86rem;
  color: var(--ink-soft);
}

.visit-group__count {
  margin-left: auto;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--sand);
  color: var(--ink-soft);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

/* The stay somebody is in the middle of. */
.visit-group--live .visit-group__title { border-bottom-color: var(--sage-deep); }
.visit-group--live .visit-group__count { background: var(--mist); color: var(--sage-dark); }

/* A walk-through video, once there is one. Two per visit: the state of the
   house when the sitter arrived, and when they left. */
.visit__media { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 0; }

.clip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 12px 5px 9px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--white);
  font-size: 0.82rem;
  color: var(--ink-soft);
}

.clip__play {
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 5px 0 5px 8px;
  border-color: transparent transparent transparent var(--sage-deep);
}

/* ------------------------------------------------- notification choices -- */
/* Cosmetic for now. Sits above the log because it is a setting, and the log
   below it is the thing the setting is about. */
.notify {
  margin: 0 0 28px;
  padding: 18px 20px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--sand);
}

.notify__title { margin: 0 0 3px; font-size: 1.05rem; }
.notify__lede { margin: 0 0 14px; font-size: 0.92rem; color: var(--ink-soft); }

.notify__options { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }

.notify__option {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  cursor: pointer;
}

.notify__option input { margin-top: 3px; flex: 0 0 auto; accent-color: var(--sage-deep); }
.notify__name { display: block; font-size: 0.95rem; }
.notify__hint { display: block; font-size: 0.84rem; color: var(--ink-soft); }

/* ----------------------------------------------------- folding a booking -- */
/* Collapsed, a multi-day stay reads as one thing and carries one green edge.
   Opened, that edge goes and each day shows its own, which is what makes the
   separation between days legible. */
.visit-group--fold > details > summary {
  list-style: none;
  cursor: pointer;
  padding-left: 26px;
  position: relative;
}
.visit-group--fold > details > summary::-webkit-details-marker { display: none; }

/* The chevron, drawn rather than typed so it can turn. */
.visit-group--fold > details > summary::before {
  content: "";
  position: absolute;
  left: 6px;
  top: 0.42em;
  width: 7px;
  height: 7px;
  border-right: 2px solid var(--sage-deep);
  border-bottom: 2px solid var(--sage-deep);
  transform: rotate(-45deg);
  transition: transform 0.16s ease;
}
.visit-group--fold > details[open] > summary::before { transform: rotate(45deg); }

.visit-group--fold > details:not([open]) {
  border-left: 3px solid var(--sage-deep);
  padding-left: 14px;
  border-radius: 2px;
}

.visit-group--fold > details:not([open]) > summary { border-bottom-color: transparent; }

.visit-group__body { margin-top: 14px; }

.visit-group--fold > details > summary:focus-visible {
  outline: 2px solid var(--sage-deep);
  outline-offset: 3px;
}

/* --------------------------------------------------- watch it, or keep it -- */
.clip { padding: 0; border: 1px solid var(--line); overflow: hidden; }

.clip__open,
.clip__save,
.clip__again {
  border: 0;
  background: var(--white);
  font: inherit;
  font-size: 0.82rem;
  color: var(--ink-soft);
  cursor: pointer;
}

.clip__open {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 11px 6px 10px;
}

.clip__save,
.clip__again {
  padding: 6px 10px;
  border-left: 1px solid var(--line);
  font-size: 0.95rem;
  line-height: 1;
}

.clip__open:hover,
.clip__save:hover { background: var(--mist); color: var(--sage-dark); }

/* Refilming replaces something that is already there, so it reads as the
   warmer of the three rather than another neutral icon. */
.clip__again { color: var(--burgundy-deep); }
.clip__again:hover { background: var(--blush); }

/* Three choices across the container rather than down it. They are siblings of
   equal weight, and a column of three made the panel taller than the log it
   introduces. Collapses on a narrow screen, where a row of three would put
   two words on four lines. */
.notify__options--row {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 18px;
}

@media (max-width: 720px) {
  .notify__options--row { grid-template-columns: 1fr; gap: 10px; }
}

/* ------------------------------------------------------- what is unread -- */
/* On the tab, so it is visible from any panel. */
.tabs__count {
  display: inline-block;
  min-width: 18px;
  margin-left: 7px;
  padding: 1px 5px;
  border-radius: 999px;
  background: var(--burgundy-deep);
  color: var(--white);
  font-size: 0.68rem;
  font-weight: 600;
  line-height: 1.5;
  text-align: center;
  vertical-align: 1px;
}

.visits-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px 16px;
  margin: 0 0 18px;
  padding: 11px 16px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--blush);
}

.visits-head__line { margin: 0; font-size: 0.92rem; color: var(--burgundy-dark); }

/* ------------------------------------------------ an in-app notification -- */
/* What the count bubble does not say. The bubble tells you something happened;
   this says what, and when, without making you go and look.
   Sits with the "sitter is here now" banner above the tabs, so it is seen from
   whichever panel somebody happens to be on. */
.notice {
  margin: 0 0 18px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--white);
  overflow: hidden;
}

.notice__head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 16px;
  border-bottom: 1px solid var(--line-soft);
  background: var(--sand);
}

.notice__title {
  margin: 0;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.notice__count {
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--burgundy-deep);
  color: var(--white);
  font-size: 0.68rem;
  font-weight: 600;
}

.notice__clear { margin-left: auto; }

.notice__list { list-style: none; margin: 0; padding: 0; }

.notice__list > li {
  display: flex;
  align-items: baseline;
  gap: 10px 14px;
  flex-wrap: wrap;
  padding: 11px 16px;
}
.notice__list > li + li { border-top: 1px solid var(--line-soft); }

/* A filled dot for something not yet read, hollow once it is. */
.notice__dot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--burgundy-deep);
  align-self: center;
}
.notice__list > li[data-read="true"] .notice__dot {
  background: transparent;
  border: 1px solid var(--line);
}
.notice__list > li[data-read="true"] { color: var(--ink-faint); }

.notice__what { flex: 1 1 auto; font-size: 0.93rem; }
.notice__when { font-size: 0.82rem; color: var(--ink-faint); white-space: nowrap; }

/* The New marker on a visit in the log below. */
.visit__new {
  display: inline-block;
  margin-left: 9px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--burgundy-deep);
  color: var(--white);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.08em;
}

.visit--unread { border-left-color: var(--burgundy-deep); }

/* What a sitter still owes on a visit they have already finished. */
.visit__owed {
  margin: 6px 0 0;
  font-size: 0.85rem;
  color: var(--ink-faint);
}
.visit__owed--late { color: var(--burgundy-deep); font-weight: 500; }

/* On a sitter's log the client's name leads and the service follows it. */
.visit-group__svc { font-weight: 400; font-size: 0.92rem; color: var(--ink-soft); }

.notify__status { margin: 14px 0 0; }

/* Why an old booking has no videos on it. */
.visit-group__gone {
  margin: 0 0 14px;
  padding: 9px 13px;
  border-radius: 8px;
  background: var(--sand);
  font-size: 0.86rem;
  color: var(--ink-soft);
}

/* ------------------------------------------- a note on a visit, by hand -- */
/* Written to the client rather than filed about them, so it reads as prose
   under the times rather than as another field beside them. */
.joblog__list > li { flex-direction: column; align-items: stretch; gap: 3px; }

.joblog__list > li > .joblog__day,
.joblog__list > li > .joblog__span,
.joblog__list > li > .joblog__video { align-self: flex-start; }

@media (min-width: 620px) {
  /* Back to a row on anything wide enough, with the note dropping beneath. */
  .joblog__list > li {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 12px;
  }
  /* The clips finish the first line, pushed to its end and sitting on the
     bottom edge rather than the text baseline -- a button aligned by its
     baseline hangs below the line it is supposed to be on. */
  /* Selected through the li so it outranks the shorthand `margin: 0` that
     resets this further down the file. Order would not have saved it. */
  .joblog__list > li > .joblog__clips {
    margin-left: auto;
    align-self: flex-end;
  }

  /* Everything else takes a line of its own beneath: the notes as a row, and
     each editing box full width under them. */
  .joblog__noterow,
  .joblog__noteform,
  .joblog__list > li > .filmer { flex: 1 0 100%; }
}

.joblog__note {
  margin: 2px 0 0;
  font-size: 0.88rem;
  color: var(--ink-soft);
}

.joblog__note--none { color: var(--ink-faint); }

.joblog__edit {
  appearance: none;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 0.82rem;
  color: var(--sage-dark);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.joblog__edit:hover { color: var(--sage-deep); }

.joblog__noteform { margin: 8px 0 2px; }
.joblog__noteform label { display: block; }
.joblog__noteform label > span {
  display: block;
  margin-bottom: 4px;
  font-size: 0.82rem;
  color: var(--ink-soft);
}
.joblog__noteform textarea {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  font: inherit;
  font-size: 0.9rem;
  resize: vertical;
}
.joblog__noteactions { display: flex; gap: 8px; margin-top: 8px; }

/* ------------------------------------------------ filming a walk-through -- */
.joblog__clips { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; }

/* A slot with nothing in it yet. Reads as an instruction rather than a chip,
   because it is the one thing on the row still asking for something. */
.clip--todo {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 13px 6px 11px;
  border: 1px dashed var(--burgundy);
  border-radius: 999px;
  background: transparent;
  font: inherit;
  font-size: 0.82rem;
  color: var(--burgundy-deep);
  cursor: pointer;
}
.clip--todo:hover { background: var(--blush); }

.clip__dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--burgundy); flex: 0 0 auto;
}

.filmer {
  margin: 12px 0 4px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--cream);
}

.filmer__live,
.filmer__play {
  display: block;
  width: 100%;
  max-width: 460px;
  border-radius: 10px;
  background: #000;
}

.filmer__note { margin: 10px 0 0; font-size: 0.86rem; color: var(--ink-soft); }
.filmer__note--bad { color: var(--burgundy-deep); }
.filmer__note:first-child { margin-top: 0; }

.filmer__clock {
  margin: 6px 0 0;
  font-size: 0.86rem;
  font-variant-numeric: tabular-nums;
  color: var(--burgundy-deep);
}
.filmer__actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }

.filmer__file {
  display: inline-block;
  margin-top: 10px;
  padding: 11px 18px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--white);
  font-size: 0.9rem;
  cursor: pointer;
}
.filmer__file input { display: none; }

/* The clip, played where it sits. */
.visit__player { margin-top: 10px; }
.visit__video-el {
  display: block;
  width: 100%;
  max-width: 460px;
  border-radius: 10px;
  background: #000;
}

/* A visit with nothing left owing on it, on the sitter's round-up. */
.visit__done {
  margin: 6px 0 0;
  font-size: 0.85rem;
  color: var(--sage-deep);
}

/* A screenshot inside the sitter guide. Full width of the prose column and
   framed, because a screenshot of our own interface on a page that is itself
   that interface's palette needs an edge or it reads as part of the page.
   height:auto because the width/height attributes reserve the space before it
   loads but also set a used height, which would squash it. */
.guide-shot {
  margin: 20px 0 24px;
}
.guide-shot img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--line, #e4ded9);
  border-radius: 10px;
}

/* The sitter guide runs subheadings under its sections, and at the shared
   8px they read as a label stuck to the paragraph rather than a heading over
   it. Scoped to this page: privacy and terms use h3 for short runs of
   definitions where tight is right. */
.prose--guide h3 {
  margin: 38px 0 16px;
  padding-top: 26px;
  border-top: 1px solid var(--line);
}

/* Except the one that opens a section: the h2 above it has just drawn a rule,
   and two lines a heading apart read as a mistake. Written as "an h3 that
   follows an h2" rather than "the first h3", so it keeps working as more
   subsections are added under each heading. */
.prose--guide h2 + h3 {
  margin-top: 26px;
  padding-top: 0;
  border-top: 0;
}

/* The guide runs four levels deep: section, subsection, the card's own parts,
   and each part by name. h4 groups, h5 labels -- so h4 carries a rule and h5
   is set small and lettered, the way the field labels inside the card itself
   are. Nowhere else on the site needs either. */
.prose--guide h4 {
  font-size: 1.1rem;
  margin: 34px 0 6px;
  padding-top: 20px;
  border-top: 1px solid var(--line-soft);
}
/* h-label is the same small-caps label as h5, for a heading that has to sit
   at h4 in the outline -- the level is about the document, the look is about
   what the reader is being pointed at. */
.prose--guide h5,
.prose--guide h4.h-label {
  font-family: var(--font-body);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 22px 0 6px;
}

/* and it takes none of the h4 grouping treatment it would otherwise inherit */
.prose--guide h4.h-label {
  font-size: 0.72rem;
  padding-top: 0;
  border-top: 0;
}

/* A run of field-by-field notes reads as reference rather than prose, so it is
   set a step down from the body around it. A class rather than "every list in
   the guide": the numbered steps and the policy bullets are prose and should
   stay at reading size. */
.prose--guide .deflist { margin: 0 0 18px; }

/* Label and description on one line, no bullet: this is a reference table
   written as prose, and a bullet in front of every term made it read as a list
   of instructions rather than a key to what is on the card. */
.prose--guide .def {
  font-size: 0.92rem;
  line-height: 1.65;
  margin: 0 0 10px;
  color: var(--ink-soft);
}
.prose--guide .def strong { color: var(--ink); font-weight: 600; }

/* Sub-labels sit under the term they belong to. */
.prose--guide .def--sub { margin-left: 20px; }

/* The quick link beside the dashboard subtitle. Set apart from the sentence it
   follows rather than reading as part of it, and it wraps to its own line on a
   phone rather than squeezing the sentence. */
.dash-sub__guide {
  white-space: nowrap;
  margin-left: 10px;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--burgundy-deep);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.dash-sub__guide:hover,
.dash-sub__guide:focus-visible { border-bottom-color: currentColor; }

/* A fourth level inside the card sections: h5 names the part of the card,
   h6 names a group of labels within it. Sentence case and body face, so it
   reads as a heading over a list rather than another small-caps field label. */
.prose--guide h6 {
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--ink);
  margin: 24px 0 10px;
}

/* Sitter guide: contents column ------------------------------------------ */

/* The guide is long and read in pieces, usually to answer one question, so it
   carries its own contents rather than making a sitter scroll to find the bit
   they need. Two columns on a desktop, a disclosure above the text on a phone.
   The list itself is built from the headings by js/guide-nav.js. */
.guide-layout { display: block; }

.section-head--guide { max-width: 760px; }

.guide-nav__toggle {
  font: 600 0.9rem/1 var(--font-body);
  color: var(--ink);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 11px 18px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.guide-nav__toggle::after {
  content: "";
  width: 7px; height: 7px;
  border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  transform: rotate(45deg) translate(-1px, -1px);
}
.guide-nav.is-open .guide-nav__toggle::after {
  transform: rotate(-135deg) translate(-2px, -2px);
}

/* Closed by default on a phone; the toggle opens it. */
.guide-nav__list { display: none; }
.guide-nav.is-open .guide-nav__list {
  display: block;
  margin-top: 14px;
  padding: 4px 0;
  border-top: 1px solid var(--line-soft);
}

.guide-nav__link {
  display: block;
  padding: 7px 12px;
  font: 400 0.86rem/1.35 var(--font-body);
  color: var(--ink-soft);
  text-decoration: none;
  border-left: 2px solid transparent;
}
.guide-nav__link--l2 { padding-left: 24px; }
.guide-nav__link--l3 { padding-left: 36px; font-size: 0.82rem; }
.guide-nav__link--l4 { padding-left: 48px; font-size: 0.8rem; }
.guide-nav__link:hover,
.guide-nav__link:focus-visible { color: var(--ink); }
.guide-nav__link.is-current {
  color: var(--burgundy-deep);
  font-weight: 600;
  border-left-color: var(--burgundy-deep);
}

/* A heading jumped to must clear the sticky header. */
.prose--guide :is(h2, h3, h5, h6)[id] { scroll-margin-top: 104px; }

@media (min-width: 960px) {
  .guide-layout {
    display: grid;
    grid-template-columns: 232px minmax(0, 1fr);
    gap: 48px;
    align-items: start;
  }
  .guide-nav {
    position: sticky;
    /* under the site header, which is 86px */
    top: 104px;
    /* its own scrollbar when the contents outrun the window, so a long list
       never hides its own tail */
    max-height: calc(100vh - 128px);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .guide-nav__toggle { display: none; }
  .guide-nav__list { display: block; }
  .guide-nav.is-open .guide-nav__list { margin-top: 0; border-top: 0; }
}

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* The guide on a phone -------------------------------------------------- */
/* Read one-handed on a doorstep, not at a desk: the running text comes down a
   step so more of a section fits on screen. Only the prose moves. The labels
   hold their size, because they are what a sitter scans for, and the headings
   hold theirs so the structure stays legible while scrolling past it. */
@media (max-width: 720px) {
  .prose--guide .lede { font-size: 1rem; line-height: 1.6; }
  .prose--guide p,
  .prose--guide li { font-size: 0.94rem; line-height: 1.62; }

  .prose--guide .def { font-size: 0.86rem; line-height: 1.6; }
  .prose--guide .def strong { font-size: 0.92rem; }
}

/* Guide screenshots, full screen ----------------------------------------- */

.guide-shot__open {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  border-radius: 10px;
}
.guide-shot__open:focus-visible {
  outline: 2px solid var(--burgundy-deep);
  outline-offset: 3px;
}

/* The page behind must not scroll while a screenshot is open, or closing it
   lands you somewhere you did not leave. */
.shotbox-open, .shotbox-open body { overflow: hidden; }

.shotbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(24, 28, 25, 0.88);
  display: grid;
  place-items: center;
  padding: 56px 16px 16px;
  overflow: auto;
  overscroll-behavior: contain;
}

.shotbox__stage {
  display: grid;
  place-items: center;
  min-width: 100%;
  min-height: 100%;
}

.shotbox__img {
  display: block;
  max-width: 100%;
  max-height: calc(100vh - 88px);
  width: auto;
  height: auto;
  border-radius: 8px;
  background: var(--white);
  cursor: zoom-in;
}

/* Tapped once: actual pixels, panned by scrolling the overlay. */
.shotbox.is-actual .shotbox__img {
  max-width: none;
  max-height: none;
  cursor: zoom-out;
}

.shotbox__close {
  position: fixed;
  top: 12px;
  right: 12px;
  z-index: 1;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.35);
  background: rgba(24, 28, 25, 0.75);
  color: #fff;
  font: 400 26px/1 var(--font-body);
  cursor: pointer;
}
.shotbox__close:hover { background: rgba(24, 28, 25, 0.95); }
.shotbox__close:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* The one line in the guide that describes something a sitter cannot undo. */
.prose--guide .warn-lead { color: var(--burgundy-deep); }

/* Dashboard first-run nudges -------------------------------------------- */

.coach-open, .coach-open body { overflow: hidden; }

.coach { position: fixed; inset: 0; z-index: 300; }

/* The hole. The dimming is the shadow, so there is one element and no seams,
   and nothing under it moves. pointer-events stay off the ring itself so the
   page cannot be operated by accident while a nudge is up. */
.coach__spot {
  position: absolute;
  border-radius: 12px;
  box-shadow: 0 0 0 9999px rgba(24, 28, 25, 0.72);
  outline: 2px solid var(--white);
  outline-offset: 0;
  pointer-events: none;
  transition: none;
}

.coach__bubble {
  position: absolute;
  width: min(320px, calc(100vw - 24px));
  background: var(--white);
  border-radius: 14px;
  padding: 18px 18px 16px;
  box-shadow: 0 18px 40px rgba(24, 28, 25, 0.28);
}

/* A pointer towards the thing being talked about. */
.coach__bubble::before {
  content: "";
  position: absolute;
  top: -7px;
  left: 50%;
  margin-left: -7px;
  width: 14px;
  height: 14px;
  background: var(--white);
  transform: rotate(45deg);
  border-radius: 2px;
}
.coach__bubble--above::before { top: auto; bottom: -7px; }

.coach__count {
  margin: 0 0 6px;
  font: 600 0.68rem/1 var(--font-body);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.coach__title {
  margin: 0 0 6px;
  font: 400 1.12rem/1.25 var(--font-heading);
  color: var(--ink);
}
.coach__body {
  margin: 0 0 14px;
  font: 400 0.92rem/1.6 var(--font-body);
  color: var(--ink-soft);
}
.coach__actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.coach__skip {
  border: 0;
  background: none;
  padding: 6px 2px;
  font: 400 0.86rem/1 var(--font-body);
  color: var(--ink-faint);
  cursor: pointer;
  text-decoration: underline;
}
.coach__skip:hover { color: var(--ink-soft); }
