/* ==========================================================================
   Purple Sky Cleaning — core stylesheet
   Palette: white backgrounds with neutral greys; purple ink, logo and
   accents all drawn from one family. No competing accent hue.
   Deliberately avoids purple gradients / glassmorphism / icon-card grids.
   ========================================================================== */

:root {
  /* Palette is built outward from the logo's periwinkle, so every purple on
     the page belongs to the same family. The old aubergine + terracotta pair
     fought the logo — three unrelated purples and an orange. */

  /* Backgrounds are plain white with neutral greys. The purple lives in the
     logo, the type and the dark sections — not washed across the page. */
  --bone: #ffffff;       /* page background */
  --bone-deep: #f4f4f7;  /* neutral band for alternating sections */
  --paper: #ffffff;      /* cards and panels */

  --ink: #1c1733;        /* near-black carrying a purple cast */
  --ink-2: #56506e;
  --ink-3: #8b85a3;

  --plum: #2f2559;       /* deep brand purple: footer, top bar, dark sections */
  --plum-2: #6247a8;
  --plum-wash: #ede9f9;
  --periwinkle: #8b7bc8; /* the logo itself — too light for text or buttons */

  /* Primary action colour. A deepened periwinkle: same hue as the logo, dark
     enough that white text on it hits 7:1. */
  --accent: #6247a8;
  --accent-dark: #513a8f;
  --accent-wash: #ede9f9;

  --line: rgba(28, 23, 51, 0.12);
  --line-soft: rgba(28, 23, 51, 0.07);
  --line-invert: rgba(255, 255, 255, 0.18);

  --serif: "Fraunces", "Iowan Old Style", Georgia, serif;
  --sans: "Instrument Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;

  --wrap: 1180px;
  --gutter: 24px;
  --radius: 4px;
  --radius-lg: 10px;
}

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

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

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

body {
  margin: 0;
  background: var(--bone);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

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

a { color: inherit; }

h1, h2, h3, h4 {
  font-family: var(--serif);
  font-weight: 400;
  font-variation-settings: "SOFT" 0, "WONK" 0, "opsz" 40;
  letter-spacing: -0.015em;
  line-height: 1.08;
  margin: 0 0 0.5em;
  text-wrap: balance;
}

h1 { font-size: clamp(2.6rem, 6vw, 4.15rem); }
h2 { font-size: clamp(2rem, 4.2vw, 2.95rem); }
h3 { font-size: clamp(1.25rem, 2.2vw, 1.55rem); line-height: 1.2; }
h4 { font-size: 1.08rem; line-height: 1.3; }

p { margin: 0 0 1.15em; text-wrap: pretty; }

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

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

section { position: relative; }

.pad { padding-block: clamp(64px, 9vw, 118px); }
.pad-sm { padding-block: clamp(44px, 6vw, 76px); }

/* Collapse the seam between two sections that share a background.

   Both .pad and .pad-sm set padding on the top AND bottom, so stacking two
   sections put up to 118px + 118px = 236px of empty space between them. Where
   the background changes, that space is doing real work: it is what separates
   a white band from a grey one. Where it does not change, there is no band to
   separate and it just reads as a hole in the page, which is exactly what it
   looked like on /pricing and on every guide.

   So: only zero the top padding when the section above has the same
   background treatment. `.bg-plum` and `.cta-band` are excluded on both sides
   because a dark band always needs its own full breathing room. */
section:not([class*="bg-"]):not(.cta-band) + section:not([class*="bg-"]):not(.cta-band),
section.bg-paper + section.bg-paper {
  padding-top: 0;
}

/* At a background change the incoming band already carries its own generous
   top padding (up to 118px). The outgoing section's full bottom padding sits
   on top of that, which is where the ~194px holes above the grey FAQ bands
   came from. Trim the outgoing side so the boundary reads as one band of
   space rather than two stacked ones, while keeping enough that the content
   above is not resting on the colour edge. */
section:not([class*="bg-"]):not(.cta-band):has(+ section[class*="bg-"]),
section:not([class*="bg-"]):not(.cta-band):has(+ section.cta-band) {
  padding-bottom: clamp(24px, 3vw, 40px);
}

/* And the mirror: a plain section directly BELOW a coloured band. The band's
   own bottom padding already sits above it, so the plain section's full top
   padding lands on top of that as dead white space. Two adjacent coloured
   bands are left alone, because there the padding is inside the colour and
   is doing the work it was designed for. */
section[class*="bg-"] + section:not([class*="bg-"]):not(.cta-band),
section.cta-band + section:not([class*="bg-"]):not(.cta-band) {
  padding-top: clamp(24px, 3vw, 40px);
}

/* Body is white, so .bg-paper needs its own barely-there grey to keep the
   alternating section rhythm. Cards keep pure white via --paper. */
.bg-paper { background: #fafafc; }
.bg-bone-deep { background: var(--bone-deep); }
.bg-plum { background: var(--plum); color: #f6f1f4; }
.bg-plum h2, .bg-plum h3 { color: #fff; }

/* ---------- Type helpers ---------- */

.eyebrow {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 18px;
  display: block;
}

.bg-plum .eyebrow { color: #b9a9e6; }

.lead {
  font-size: clamp(1.08rem, 1.6vw, 1.24rem);
  line-height: 1.6;
  color: var(--ink-2);
  max-width: 60ch;
}

.bg-plum .lead { color: rgba(255, 255, 255, 0.78); }

.serif-em {
  font-style: italic;
  font-variation-settings: "SOFT" 40, "WONK" 1, "opsz" 40;
}

.muted { color: var(--ink-3); }

.small {
  font-size: 0.86rem;
  line-height: 1.55;
}

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

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55em;
  font-family: var(--sans);
  font-size: 0.97rem;
  font-weight: 600;
  letter-spacing: 0.005em;
  padding: 15px 26px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.18s ease, color 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}

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

.btn-primary {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}
.btn-primary:hover { background: var(--accent-dark); border-color: var(--accent-dark); }

.btn-ink {
  background: var(--plum);
  color: #fff;
  border-color: var(--plum);
}
.btn-ink:hover { background: #241b47; border-color: #241b47; }

.btn-ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--line);
}
.btn-ghost:hover { border-color: var(--ink); background: rgba(28, 23, 51, 0.05); }

/* Ghost buttons sitting on any dark surface. The .cta-band selector is not
   optional — that band is dark but does not carry .bg-plum, and without it
   the button renders near-black on plum. */
.bg-plum .btn-ghost,
.cta-band .btn-ghost,
.calc-out .btn-ghost {
  color: #fff;
  border-color: rgba(255, 255, 255, 0.45);
}
.bg-plum .btn-ghost:hover,
.cta-band .btn-ghost:hover,
.calc-out .btn-ghost:hover { border-color: #fff; background: rgba(255, 255, 255, 0.12); }

/* Now that the accent is a purple, a primary button on a deep-purple panel
   is purple-on-purple and stops reading as the main action. On dark
   surfaces it flips to white with purple text, which is the strongest
   contrast available and keeps the palette to one hue. */
.bg-plum .btn-primary,
.cta-band .btn-primary,
.calc-out .btn-primary {
  background: #fff;
  color: var(--plum);
  border-color: #fff;
}
.bg-plum .btn-primary:hover,
.cta-band .btn-primary:hover,
.calc-out .btn-primary:hover {
  background: var(--plum-wash);
  border-color: var(--plum-wash);
  color: var(--plum);
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

.textlink {
  color: var(--plum);
  text-decoration: none;
  border-bottom: 1px solid rgba(98, 71, 168, 0.32);
  padding-bottom: 1px;
  font-weight: 500;
}
.textlink:hover { border-bottom-color: var(--plum); }

/* ---------- Skip link + focus ---------- */

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--plum);
  color: #fff;
  padding: 12px 20px;
  z-index: 999;
}
.skip:focus { left: 8px; top: 8px; }

a:focus-visible,
button:focus-visible,
select:focus-visible,
input:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* ---------- Announcement bar ---------- */

.topbar {
  background: var(--plum);
  color: rgba(255, 255, 255, 0.9);
  font-size: 0.79rem;
  letter-spacing: 0.02em;
}
.topbar .wrap {
  display: flex;
  gap: 10px 26px;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  min-height: 40px;
  padding-block: 8px;
  text-align: center;
}
.topbar b { color: #fff; font-weight: 600; }
.topbar .dot { color: rgba(255, 255, 255, 0.35); }

/* On a phone the three claims wrap to three lines and eat ~100px of the
   first screen. Keep the strongest one (the rating) and drop the rest. */
@media (max-width: 640px) {
  .topbar .wrap > *:nth-child(n + 2) { display: none; }
  .topbar .wrap { min-height: 34px; padding-block: 6px; }
  .topbar { font-size: 0.76rem; }
}

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

.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: saturate(140%) blur(6px);
  border-bottom: 1px solid var(--line-soft);
}

.site-header .wrap {
  display: flex;
  align-items: center;
  gap: 20px;
  min-height: 72px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  text-decoration: none;
  margin-right: auto;
  flex-shrink: 0;
  color: var(--periwinkle);
}

/* ---------- Logo ----------
   Broom mark + stacked wordmark. Both inherit currentColor from .brand so a
   single inline SVG serves the light header and the plum footer. */
.brand-logo {
  width: 30px;
  height: 43px;
  flex-shrink: 0;
  display: block;
  overflow: visible;
}
.brand-word {
  display: flex;
  flex-direction: column;
  font-family: "Nunito", system-ui, -apple-system, sans-serif;
  font-weight: 800;
  font-size: 1.16rem;
  letter-spacing: -0.025em;
  line-height: 0.95;
  color: inherit;
  white-space: nowrap;
}
.site-footer .brand { color: #fff; }
.site-footer .brand-word { font-size: 1.28rem; }

@media (max-width: 560px) {
  .brand-logo { width: 25px; height: 36px; }
  .brand-word { font-size: 1rem; }
}

.brand-mark {
  font-family: var(--serif);
  font-size: 1.34rem;
  letter-spacing: -0.02em;
  color: var(--plum);
  line-height: 1;
}
.brand-mark i {
  font-style: italic;
  font-variation-settings: "SOFT" 40, "WONK" 1;
}
.brand-sub {
  font-size: 0.62rem;
  letter-spacing: 0.19em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 600;
}

.nav {
  display: flex;
  align-items: center;
  gap: 4px;
}
.nav a {
  text-decoration: none;
  font-size: 0.93rem;
  font-weight: 500;
  color: var(--ink-2);
  padding: 9px 12px;
  border-radius: var(--radius);
  white-space: nowrap;
}
.nav a:hover { color: var(--ink); background: rgba(28, 23, 51, 0.05); }
.nav a[aria-current="page"] { color: var(--plum); font-weight: 600; }

.header-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
}
.header-phone {
  text-decoration: none;
  font-weight: 600;
  font-size: 0.93rem;
  color: var(--ink);
  white-space: nowrap;
}
.header-phone:hover { color: var(--accent); }
.header-actions .btn { padding: 11px 19px; font-size: 0.9rem; }

.nav-toggle {
  display: none;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  width: 42px;
  height: 40px;
  cursor: pointer;
  align-items: center;
  justify-content: center;
}
.nav-toggle span {
  display: block;
  width: 18px;
  height: 1.5px;
  background: var(--ink);
  position: relative;
}
.nav-toggle span::before,
.nav-toggle span::after {
  content: "";
  position: absolute;
  left: 0;
  width: 18px;
  height: 1.5px;
  background: var(--ink);
}
.nav-toggle span::before { top: -6px; }
.nav-toggle span::after { top: 6px; }

@media (max-width: 1000px) {
  .nav {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    background: var(--bone);
    border-bottom: 1px solid var(--line);
    padding: 10px var(--gutter) 20px;
    gap: 0;
  }
  .nav.open { display: flex; }
  .nav a {
    padding: 13px 4px;
    border-bottom: 1px solid var(--line-soft);
    font-size: 1rem;
  }
  .nav-toggle { display: inline-flex; }
  .header-phone { display: none; }
}

/* Below 720px the sticky bottom bar already carries "Get my price" and
   "Call", so the header CTA is a duplicate competing with the logo for a
   narrow row. Drop it and let the header be logo + menu. */
@media (max-width: 720px) {
  .header-actions .btn { display: none; }
  .site-header .wrap { min-height: 64px; gap: 12px; }
}

@media (max-width: 560px) {
  .brand-sub { display: none; }
}

/* Stacked buttons should be the same width, not ragged. */
@media (max-width: 560px) {
  .btn-row { gap: 10px; }
  .btn-row > .btn { flex: 1 1 100%; width: 100%; }
}

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

.hero { padding-block: clamp(48px, 6.5vw, 92px) clamp(56px, 7vw, 96px); }

.hero-grid {
  display: grid;
  grid-template-columns: 1.08fr 0.92fr;
  gap: clamp(32px, 5vw, 68px);
  align-items: center;
}

.hero h1 { margin-bottom: 22px; }
.hero .lead { margin-bottom: 30px; }

.hero-points {
  list-style: none;
  margin: 28px 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
  font-size: 0.88rem;
  color: var(--ink-2);
}
.hero-points li {
  display: flex;
  align-items: center;
  gap: 7px;
}
.hero-points li::before {
  content: "";
  width: 13px;
  height: 13px;
  flex-shrink: 0;
  background: var(--accent);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E") no-repeat center / contain;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E") no-repeat center / contain;
  border-radius: 50%;
  box-shadow: inset 0 0 0 20px var(--accent);
}

.hero-figure { position: relative; }
.hero-figure img {
  width: 100%;
  height: clamp(360px, 46vw, 560px);
  object-fit: cover;
  border-radius: 200px 200px var(--radius-lg) var(--radius-lg);
}

.price-chip {
  position: absolute;
  left: -22px;
  bottom: 34px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 16px 20px;
  box-shadow: 0 14px 34px rgba(28, 23, 51, 0.1);
  max-width: 224px;
}
.price-chip .k {
  font-size: 0.71rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 600;
  display: block;
  margin-bottom: 4px;
}
.price-chip .v {
  font-family: var(--serif);
  font-size: 1.85rem;
  color: var(--plum);
  line-height: 1.05;
  display: block;
}
.price-chip .n {
  font-size: 0.78rem;
  color: var(--ink-3);
  display: block;
  margin-top: 3px;
}

@media (max-width: 900px) {
  .hero-grid { grid-template-columns: 1fr; }
  .hero-figure img { height: clamp(300px, 62vw, 420px); border-radius: 140px 140px var(--radius-lg) var(--radius-lg); }
  .price-chip { left: auto; right: 10px; bottom: -14px; }
}

/* On a phone the floating chip covers half the photo. Drop it below the
   image as its own full-width card instead. */
@media (max-width: 640px) {
  .price-chip {
    position: static;
    max-width: none;
    margin-top: 12px;
    box-shadow: none;
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 2px 10px;
    padding: 14px 16px;
  }
  .price-chip .k { margin: 0; }
  .price-chip .v { font-size: 1.55rem; }
  .price-chip .n { margin: 0; flex-basis: 100%; }
}

/* ---------- Stat rule ---------- */

.statrule {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
.statrule div {
  padding: 26px 22px;
  border-left: 1px solid var(--line);
}
.statrule div:first-child { border-left: 0; }
.statrule .v {
  font-family: var(--serif);
  font-size: clamp(1.5rem, 2.5vw, 2.05rem);
  color: var(--plum);
  display: block;
  line-height: 1.1;
}
.statrule .k {
  font-size: 0.79rem;
  color: var(--ink-3);
  display: block;
  margin-top: 5px;
  letter-spacing: 0.01em;
}
@media (max-width: 760px) {
  .statrule { grid-template-columns: repeat(2, 1fr); }
  .statrule div:nth-child(3) { border-left: 0; }
  .statrule div:nth-child(n + 3) { border-top: 1px solid var(--line); }
}

/* ---------- Section heading ---------- */

.sec-head {
  max-width: 720px;
  margin-bottom: clamp(34px, 4.5vw, 56px);
}
.sec-head.center { margin-inline: auto; text-align: center; }
.sec-head.center .lead { margin-inline: auto; }

.head-split {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 24px;
  align-items: end;
  margin-bottom: clamp(30px, 4vw, 48px);
}
.head-split .sec-head { margin-bottom: 0; }
@media (max-width: 700px) {
  .head-split { grid-template-columns: 1fr; align-items: start; }
}

/* ---------- Editorial numbered list ---------- */

.index-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line);
}
.index-list > li { border-bottom: 1px solid var(--line); }

.index-list a,
.index-row {
  display: grid;
  grid-template-columns: 62px 1fr 1.15fr auto;
  gap: 22px;
  align-items: baseline;
  padding: 26px 4px;
  text-decoration: none;
  color: inherit;
  transition: background-color 0.18s ease, padding 0.18s ease;
}
.index-list a:hover {
  background: rgba(98, 71, 168, 0.045);
  padding-inline: 12px 4px;
}
.index-num {
  font-family: var(--serif);
  font-size: 0.92rem;
  color: var(--accent);
  letter-spacing: 0.02em;
}
.index-title {
  font-family: var(--serif);
  font-size: clamp(1.25rem, 2vw, 1.6rem);
  line-height: 1.15;
  color: var(--ink);
}
.index-desc {
  font-size: 0.94rem;
  color: var(--ink-2);
  line-height: 1.55;
}
.index-meta {
  font-size: 0.88rem;
  color: var(--plum);
  font-weight: 600;
  white-space: nowrap;
}
@media (max-width: 860px) {
  .index-list a,
  .index-row {
    grid-template-columns: 40px 1fr;
    gap: 6px 16px;
    padding-block: 22px;
  }
  .index-desc { grid-column: 2; }
  .index-meta { grid-column: 2; margin-top: 4px; }
}

/* ---------- Feature split ---------- */

.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(32px, 5vw, 72px);
  align-items: center;
}
.split.reverse .split-media { order: 2; }
/* Top-aligned variant for prose + sidebar card layouts, where centering
   leaves a dead pocket of whitespace beside the first heading. */
.split.top { align-items: start; }
.split.top .split-aside { position: sticky; top: 96px; }
@media (max-width: 880px) {
  .split.top .split-aside { position: static; }
}
.split-media img {
  width: 100%;
  height: clamp(320px, 40vw, 480px);
  object-fit: cover;
  border-radius: var(--radius-lg);
}
@media (max-width: 880px) {
  .split { grid-template-columns: 1fr; }
  .split.reverse .split-media { order: 0; }
  .split-media img { height: clamp(260px, 55vw, 380px); }
}

/* ---------- Checklist columns ---------- */

.check-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(232px, 1fr));
  gap: 2px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
}
.check-col {
  background: var(--paper);
  padding: 28px 26px 30px;
}
.check-col h3 {
  font-size: 1.12rem;
  margin-bottom: 4px;
}
.check-col .room-count {
  font-size: 0.75rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 600;
  display: block;
  margin-bottom: 16px;
}
.check-col ul {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 0.91rem;
  color: var(--ink-2);
}
.check-col li {
  padding: 7px 0 7px 21px;
  position: relative;
  line-height: 1.45;
  border-bottom: 1px solid var(--line-soft);
}
.check-col li:last-child { border-bottom: 0; }
.check-col li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 14px;
  width: 9px;
  height: 2px;
  background: var(--plum-2);
}

/* ---------- Calculator ---------- */

.calc {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  display: grid;
  grid-template-columns: 1.35fr 0.85fr;
  align-items: stretch;
}
@media (max-width: 940px) {
  .calc { grid-template-columns: 1fr; }
}

.calc-form { padding: clamp(26px, 3.4vw, 42px); }

/* The plum panel fills its column so the card reads as one block, while the
   content inside sticks — the running price stays on screen as you work down
   a long form instead of scrolling away. */
.calc-out {
  background: var(--plum);
  color: #fff;
}
.calc-out-inner {
  position: sticky;
  top: 88px;
  padding: clamp(26px, 3.4vw, 42px);
  display: flex;
  flex-direction: column;
}
@media (max-width: 940px) {
  /* Price first, then the fields, then the button. Otherwise the summary
     lands below the button the customer has already pressed. */
  .calc { display: flex; flex-direction: column; }
  .calc-out { order: -1; }
  .calc-out-inner { position: static; }
}

.field { margin-bottom: 24px; }
.field > label,
.field > .flabel {
  display: block;
  font-size: 0.79rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 10px;
}

.seg {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.seg input { position: absolute; opacity: 0; pointer-events: none; }
.seg label {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 9px 15px;
  font-size: 0.9rem;
  font-weight: 500;
  cursor: pointer;
  color: var(--ink-2);
  background: var(--paper);
  transition: all 0.15s ease;
  user-select: none;
}
.seg label:hover { border-color: var(--plum-2); color: var(--ink); }
.seg input:checked + label {
  background: var(--plum);
  border-color: var(--plum);
  color: #fff;
}
.seg input:focus-visible + label { outline: 2px solid var(--accent); outline-offset: 2px; }

.calc select,
.calc input[type="text"],
.calc input[type="email"],
.calc input[type="tel"],
.calc textarea {
  width: 100%;
  font-family: var(--sans);
  font-size: 0.97rem;
  color: var(--ink);
  padding: 13px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
}
.calc select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%2356506e' stroke-width='1.6' fill='none'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 38px;
}

.addons {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(196px, 1fr));
  gap: 8px;
}
.addon {
  display: flex;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 11px 13px;
  font-size: 0.89rem;
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}
.addon:hover { border-color: var(--plum-2); }
.addon input { accent-color: var(--plum); width: 16px; height: 16px; flex-shrink: 0; }
.addon .a-price { margin-left: auto; color: var(--ink-3); font-size: 0.84rem; white-space: nowrap; }
.addon:has(input:checked) { border-color: var(--plum); background: var(--plum-wash); }

.calc-out .out-label {
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
  font-weight: 600;
  margin-bottom: 8px;
}
.calc-out .out-price {
  font-family: var(--serif);
  font-size: clamp(3rem, 6vw, 4rem);
  line-height: 1;
  color: #fff;
  margin-bottom: 4px;
}
.calc-out .out-price .cur { font-size: 0.44em; vertical-align: 0.55em; margin-right: 2px; }
.calc-out .out-sub {
  font-size: 0.87rem;
  color: rgba(255, 255, 255, 0.68);
  margin-bottom: 20px;
}
.calc-out .out-strike {
  text-decoration: line-through;
  color: rgba(255, 255, 255, 0.45);
  margin-right: 8px;
}
.calc-out .out-save {
  display: inline-block;
  /* Light periwinkle on the deep panel — the accent purple would sit too
     close to the background to register as a badge. */
  background: #b9a9e6;
  color: var(--plum);
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 4px 9px;
  border-radius: 3px;
}

.out-lines {
  list-style: none;
  margin: 20px 0;
  padding: 18px 0 0;
  border-top: 1px solid var(--line-invert);
  font-size: 0.89rem;
}
.out-lines li {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 5px 0;
  color: rgba(255, 255, 255, 0.76);
}
.out-lines li span:last-child { color: #fff; white-space: nowrap; }

/* Add-ons are itemised one per line. Indent and lighten them so they read as
   items under the base clean rather than as separate charges of equal weight,
   and so a home with six add-ons still scans as one block. */
.out-lines li.addon-line {
  padding-left: 14px;
  font-size: 0.85rem;
  color: rgba(255, 255, 255, 0.62);
}
.out-lines li.addon-line span:last-child { color: rgba(255, 255, 255, 0.86); }
.out-lines li.addon-line + li:not(.addon-line) { margin-top: 6px; }
.out-lines li.total {
  border-top: 1px solid var(--line-invert);
  margin-top: 10px;
  padding-top: 12px;
  font-weight: 600;
  color: #fff;
}

.calc-out .btn { width: 100%; }
.calc-out .out-note {
  font-size: 0.78rem;
  color: rgba(255, 255, 255, 0.55);
  margin: 14px 0 0;
  line-height: 1.5;
}

/* ---------- Quote form ---------- */

.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
.form-grid .full { grid-column: 1 / -1; }
@media (max-width: 640px) { .form-grid { grid-template-columns: 1fr; } }

.form-note {
  font-size: 0.82rem;
  color: var(--ink-3);
  margin-top: 14px;
}

.form-status {
  margin-top: 16px;
  padding: 14px 16px;
  border-radius: var(--radius);
  font-size: 0.92rem;
  display: none;
}
.form-status.show { display: block; }
.form-status.ok { background: var(--plum-wash); color: var(--plum); }
.form-status.err { background: var(--accent-wash); color: var(--accent-dark); }

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

.pullquote {
  font-family: var(--serif);
  font-size: clamp(1.5rem, 3.1vw, 2.25rem);
  line-height: 1.28;
  color: var(--ink);
  margin: 0 0 24px;
  text-wrap: balance;
}
.bg-plum .pullquote { color: #fff; }

.attrib {
  font-size: 0.87rem;
  color: var(--ink-3);
  letter-spacing: 0.02em;
}
.bg-plum .attrib { color: rgba(255, 255, 255, 0.6); }

.review-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(268px, 1fr));
  gap: 1px;
  background: var(--line-soft);
  border-block: 1px solid var(--line-soft);
}
.review {
  background: var(--bone);
  padding: 30px 28px;
}
.review .stars {
  color: var(--accent);
  font-size: 0.9rem;
  letter-spacing: 0.14em;
  margin-bottom: 12px;
}
.review p {
  font-size: 0.96rem;
  color: var(--ink-2);
  line-height: 1.6;
}
.review .attrib { margin-top: 14px; display: block; }

/* ---------- Areas index ---------- */

.area-index {
  columns: 4;
  column-gap: 32px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.area-index li {
  break-inside: avoid;
  border-bottom: 1px solid var(--line-soft);
}
.area-index a {
  display: block;
  padding: 10px 0;
  text-decoration: none;
  font-size: 0.94rem;
  color: var(--ink-2);
}
.area-index a:hover { color: var(--accent); }
@media (max-width: 900px) { .area-index { columns: 2; } }
@media (max-width: 460px) { .area-index { columns: 1; } }

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

.steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
}
.step {
  background: var(--paper);
  padding: 32px 28px 34px;
}
.step .n {
  font-family: var(--serif);
  font-size: 2.4rem;
  color: var(--plum-wash);
  line-height: 1;
  display: block;
  margin-bottom: 14px;
}
.step h3 { font-size: 1.16rem; margin-bottom: 8px; }
.step p { font-size: 0.93rem; color: var(--ink-2); margin: 0; }
@media (max-width: 780px) { .steps { grid-template-columns: 1fr; } }

/* ---------- Pricing table ---------- */

.ptable {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.95rem;
}
/* Table caption lives outside the table. Inside, it inherits the table's
   wider-than-screen width on mobile and gets clipped by the scroll box. */
.table-note {
  font-size: 0.79rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 600;
  margin: 0 0 12px;
}
.ptable th,
.ptable td {
  text-align: left;
  padding: 15px 16px;
  border-bottom: 1px solid var(--line-soft);
}
.ptable thead th {
  font-family: var(--sans);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  border-bottom: 1px solid var(--line);
}
.ptable tbody th { font-family: var(--sans); font-weight: 600; font-size: 0.95rem; }
.ptable td.price { font-family: var(--serif); font-size: 1.2rem; color: var(--plum); white-space: nowrap; }
.ptable tbody tr:hover { background: rgba(98, 71, 168, 0.04); }

.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* On a phone the price table is wider than the screen. It scrolled fine but
   gave no sign it could, so the extra columns were effectively invisible.
   Pin the row label and say so. */
@media (max-width: 720px) {
  .table-scroll { position: relative; }
  .table-scroll::after {
    content: "Swipe the table for more columns →";
    display: block;
    font-size: 0.76rem;
    color: var(--ink-3);
    padding: 10px 2px 0;
  }
  .ptable tbody th,
  .ptable thead th:first-child {
    position: sticky;
    left: 0;
    background: var(--bone);
    z-index: 1;
  }
  .ptable tbody tr:hover th { background: var(--bone); }
}

/* ---------- FAQ ---------- */

.faq { border-top: 1px solid var(--line); }
.faq details {
  border-bottom: 1px solid var(--line);
}
.faq summary {
  cursor: pointer;
  list-style: none;
  padding: 24px 46px 24px 0;
  position: relative;
  font-family: var(--serif);
  font-size: clamp(1.08rem, 1.7vw, 1.28rem);
  line-height: 1.3;
  color: var(--ink);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "";
  position: absolute;
  right: 6px;
  top: 50%;
  width: 13px;
  height: 13px;
  margin-top: -6px;
  background: var(--plum);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 5v14M5 12h14' stroke='%23000' stroke-width='2.4'/%3E%3C/svg%3E") no-repeat center / contain;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 5v14M5 12h14' stroke='%23000' stroke-width='2.4'/%3E%3C/svg%3E") no-repeat center / contain;
  transition: transform 0.2s ease;
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq .faq-body {
  padding: 0 60px 26px 0;
  color: var(--ink-2);
  font-size: 0.98rem;
  max-width: 70ch;
}
.faq .faq-body p:last-child { margin-bottom: 0; }

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

.cta-band {
  position: relative;
  overflow: hidden;
  background: var(--plum);
  color: #fff;
}
.cta-band img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.26;
}
/* Scrim so the headline and buttons keep contrast over the photo. */
.cta-band::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(30, 24, 62, 0.4), rgba(30, 24, 62, 0.66));
}
.cta-band .wrap { position: relative; z-index: 1; }
.cta-band h2 { color: #fff; }
.cta-band .lead { color: rgba(255, 255, 255, 0.82); }

/* ---------- Prose ---------- */

.prose { max-width: 72ch; }
.prose h2 { margin-top: 1.8em; }
.prose h3 { margin-top: 1.6em; font-size: 1.24rem; }
.prose h2:first-child, .prose h3:first-child { margin-top: 0; }
.prose ul, .prose ol { padding-left: 1.15em; margin-bottom: 1.2em; color: var(--ink-2); }
.prose li { margin-bottom: 0.5em; }
.prose a { color: var(--plum); }

/* ---------- Breadcrumbs ---------- */

.crumbs {
  font-size: 0.83rem;
  color: var(--ink-3);
  padding-block: 18px 0;
}
.crumbs ol {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  padding: 0;
}
.crumbs li::after { content: "/"; margin-left: 8px; color: var(--line); }
.crumbs li:last-child::after { content: ""; }
.crumbs a { text-decoration: none; color: var(--ink-3); }
.crumbs a:hover { color: var(--accent); }

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

.site-footer {
  background: var(--plum);
  color: rgba(255, 255, 255, 0.72);
  padding-block: clamp(52px, 6vw, 78px) 32px;
  font-size: 0.91rem;
}
.footer-top {
  display: grid;
  grid-template-columns: 1.5fr repeat(3, 1fr);
  gap: 40px 32px;
  padding-bottom: 44px;
  border-bottom: 1px solid var(--line-invert);
}
.site-footer h4 {
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
  margin-bottom: 16px;
}
.site-footer ul { list-style: none; margin: 0; padding: 0; }
.site-footer li { margin-bottom: 9px; }
.site-footer a { text-decoration: none; color: rgba(255, 255, 255, 0.72); }
.site-footer a:hover { color: #fff; }
.footer-brand .brand { display: inline-flex; }
.footer-brand p { margin: 16px 0 0; max-width: 34ch; color: rgba(255, 255, 255, 0.6); font-size: 0.9rem; }
.footer-contact {
  margin-top: 18px;
  font-size: 0.95rem;
  color: #fff;
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.footer-contact a { color: #fff; font-weight: 500; }
.footer-bottom {
  padding-top: 26px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 28px;
  justify-content: space-between;
  font-size: 0.83rem;
  color: rgba(255, 255, 255, 0.5);
}
@media (max-width: 860px) {
  .footer-top { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 520px) {
  .footer-top { grid-template-columns: 1fr; gap: 32px; }
}

/* ---------- Sticky mobile CTA ---------- */

.mobile-cta {
  display: none;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 70;
  background: var(--paper);
  border-top: 1px solid var(--line);
  padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
  gap: 10px;
}
.mobile-cta .btn { flex: 1; padding: 13px 12px; font-size: 0.92rem; }
@media (max-width: 720px) {
  .mobile-cta { display: flex; }
  body { padding-bottom: 74px; }
}

/* ---------- Utilities ---------- */

.hr { border: 0; border-top: 1px solid var(--line); margin: 0; }
.mt-0 { margin-top: 0; }
.mb-0 { margin-bottom: 0; }
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- Guides ---------- */

/* Long-form prose gets a narrower measure than the marketing pages. Anything
   past roughly 70 characters a line costs comprehension, and these pages are
   meant to actually be read rather than skimmed. */
.guide-body { max-width: 68ch; }
.guide-body h2 {
  margin: 2.4rem 0 0.9rem;
  font-size: clamp(1.35rem, 2.4vw, 1.75rem);
  line-height: 1.25;
}
.guide-body h2:first-child { margin-top: 0; }
.guide-body p { margin: 0 0 1.05rem; }
.guide-body > ol,
.guide-body > ul { margin: 0 0 1.5rem; }
.guide-body .table-scroll { margin: 1.4rem 0 0.4rem; }
.guide-body .table-note { margin-bottom: 1.8rem; }

/* The title block and the prose now share one section, so the prose needs
   its own top spacing rather than inheriting a section break. */
.guide-body { margin-top: clamp(28px, 4vw, 48px); }

.guide-meta {
  margin-top: 1rem;
  font-size: 0.85rem;
  color: var(--ink-3);
  letter-spacing: 0.01em;
}

/* Article images.

   Deliberately NOT `.hero-figure`. That one is the service-page hero: a tall
   arched crop (200px top radius) built to sit beside a column of text. In an
   article it would read as a decorative header rather than a picture in the
   flow of the piece. */
.guide-figure {
  margin: 2rem 0 2.2rem;
}
.guide-figure img {
  display: block;
  width: 100%;
  height: clamp(220px, 34vw, 380px);
  object-fit: cover;
  border-radius: var(--radius-lg);
}
.guide-figure figcaption {
  margin-top: 0.7rem;
  font-size: 0.86rem;
  line-height: 1.5;
  color: var(--ink-3);
  padding-left: 0.9rem;
  border-left: 2px solid var(--line-soft);
}
/* The one above the fold sits tighter to the title and stands a little taller,
   since it is carrying the top of the page. */
.guide-figure-lead {
  margin-top: 0;
  margin-bottom: 2.4rem;
}
.guide-figure-lead img { height: clamp(240px, 38vw, 440px); }

@media (max-width: 640px) {
  .guide-figure img,
  .guide-figure-lead img { height: clamp(200px, 56vw, 280px); }
}

/* Guide lists.

   Deliberately NOT `.steps` or `.ticks`. `.steps` is the homepage three-column
   grid and `.ticks` never existed, so both broke the guide pages. These are
   single-column reading lists, sized to the prose around them. */
.guide-steps,
.guide-ticks {
  margin: 0 0 1.5rem;
  padding: 0;
  list-style: none;
  counter-reset: guidestep;
}
.guide-steps > li,
.guide-ticks > li {
  position: relative;
  padding-left: 2.1rem;
  margin-bottom: 0.85rem;
  line-height: 1.62;
}
.guide-steps > li:last-child,
.guide-ticks > li:last-child { margin-bottom: 0; }

.guide-steps > li { counter-increment: guidestep; }
.guide-steps > li::before {
  /* With the number alone this read as "1 Bathrooms." rather than a list. */
  content: counter(guidestep) ".";
  position: absolute;
  left: 0;
  top: 0.1em;
  width: 1.5rem;
  font-family: var(--serif);
  font-size: 1.02rem;
  color: var(--accent);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.guide-ticks > li::before {
  content: "";
  position: absolute;
  left: 0.45rem;
  top: 0.72em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
}
.guide-steps > li strong { font-weight: 650; }

/* Included / not-included columns on the deep-vs-standard comparison. Colour
   alone would not survive a colourblind reader or a greyscale print, so the
   cells carry the words Yes and No and the glyph is decorative. */
.compare-table td.yes,
.compare-table td.no {
  font-family: var(--sans);
  font-weight: 600;
  font-size: 0.9rem;
  white-space: nowrap;
}
.compare-table td.yes { color: var(--accent); }
.compare-table td.no { color: var(--ink-3); }
.compare-table td.yes::before { content: "✓ "; }
.compare-table td.no::before { content: "· "; }

/* ---------- Inline card entry on /book ---------- */

/* Stripe's Payment Element renders inside its own iframe here. We style the
   container; the fields themselves are themed through the `appearance` object
   in js/book.js, because CSS cannot cross into Stripe's frame. */
/* The Card Element renders one compact row. It needs a real bordered box
   around it, because the iframe itself draws no chrome. */
.card-element {
  margin-top: 14px;
  padding: 13px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.card-element.StripeElement--focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(98, 71, 168, 0.14);
}
.card-element.StripeElement--invalid { border-color: #b3261e; }

/* The submit button sits at the END of the form, under the card field, where
   a form's action belongs. It used to live in the sticky price panel on the
   right, which read as unrelated to the fields being filled in. */
.calc-submit {
  margin-top: 26px;
  padding-top: 24px;
  border-top: 1px solid var(--line-soft);
}
.calc-submit .btn {
  width: 100%;
  padding-block: 15px;
  font-size: 1rem;
}
.calc-submit .form-status { margin-top: 12px; }

.pay-lede {
  margin: 6px 0 0;
  font-size: 0.95rem;
  color: var(--ink-2);
  line-height: 1.55;
}

.pay-trust {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 14px 0 0;
  font-size: 0.85rem;
  color: var(--ink-3);
}
.pay-trust .lock { font-size: 0.95rem; }

.card-fallback {
  margin: 0;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bone-deep);
  font-size: 0.92rem;
  color: var(--ink-2);
}

/* ---------- Address autocomplete on /book ---------- */

.addr-field { position: relative; }

.addr-results {
  position: absolute;
  z-index: 30;
  left: 0;
  right: 0;
  margin: 4px 0 0;
  padding: 4px;
  list-style: none;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 12px 28px rgba(28, 23, 51, 0.14);
  max-height: 280px;
  overflow-y: auto;
}
.addr-results[hidden] { display: none; }

.addr-results li {
  padding: 10px 12px;
  border-radius: var(--radius);
  cursor: pointer;
  line-height: 1.35;
}
/* Hover and keyboard selection look identical on purpose, so arrowing down
   and mousing over do not fight each other visually. */
.addr-results li:hover,
.addr-results li.active { background: rgba(98, 71, 168, 0.09); }

.addr-line { display: block; font-size: 0.95rem; color: var(--ink); }
.addr-rest { display: block; font-size: 0.82rem; color: var(--ink-3); margin-top: 1px; }

.field-hint {
  margin: 6px 0 0;
  font-size: 0.82rem;
  color: var(--ink-3);
}

/* ---------- Booking confirmed page ---------- */

/* The "your email is coming" note is the single most reassuring thing on this
   page, so it gets its own tinted panel rather than being another paragraph
   people skim past. */
.confirm-mail {
  max-width: 560px;
  margin: 22px auto 0;
  padding: 16px 20px;
  background: #f7f6fb;
  border-radius: var(--radius-lg);
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--ink-2);
}
.confirm-mail strong { color: var(--ink); }

.confirm-steps { margin-top: 30px; }
.confirm-steps .eyebrow { display: block; margin-bottom: 14px; }
.confirm-steps .guide-steps > li { margin-bottom: 1rem; }

/* ---------- Internal booking calendar ---------- */

.cal-gate { max-width: 420px; margin: 40px auto; text-align: center; }
.cal-gate-form { display: flex; gap: 10px; margin-top: 20px; }
.cal-gate-form input {
  flex: 1; padding: 12px 14px;
  border: 1px solid var(--line); border-radius: var(--radius);
  font-size: 16px; /* under 16px iOS zooms on focus */
}

.cal-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 20px; flex-wrap: wrap; margin-bottom: 22px;
}
.cal-head h1 { margin: 4px 0 0; font-size: clamp(1.6rem, 3vw, 2.2rem); }
.cal-nav { display: flex; gap: 8px; }
.cal-nav .btn { padding: 9px 16px; }

.cal-stats { display: flex; gap: 12px; margin-bottom: 22px; flex-wrap: wrap; }
.cal-stat {
  background: var(--bone-deep); border-radius: var(--radius-lg);
  padding: 14px 20px; min-width: 150px;
}
.cal-stat .n { display: block; font-family: var(--serif); font-size: 1.7rem; color: var(--plum); line-height: 1.1; }
.cal-stat .l { display: block; font-size: 0.82rem; color: var(--ink-3); margin-top: 3px; }

/* minmax(0,1fr) not 1fr: a grid column's default min-width is auto, so one
   long customer name would stretch its column and squash the rest of the week. */
.cal-grid-head, .cal-grid {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 1px;
}
.cal-grid-head {
  margin-bottom: 6px;
  font-size: 0.74rem; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3);
}
.cal-grid-head span { padding: 0 6px; }

.cal-grid { background: var(--line-soft); border: 1px solid var(--line-soft); border-radius: var(--radius-lg); overflow: hidden; }
.cal-day {
  background: var(--paper); min-height: 104px; padding: 6px; min-width: 0;
  display: flex; flex-direction: column; gap: 4px;
}
.cal-day.out { background: #fbfbfd; }
.cal-day.out .cal-date { color: var(--ink-3); opacity: .5; }
.cal-day.today { box-shadow: inset 0 0 0 2px var(--accent); }
.cal-date { font-size: 0.78rem; color: var(--ink-3); }
.cal-day.has .cal-date { color: var(--ink); font-weight: 600; }

.cal-chip {
  display: block; width: 100%; max-width: 100%; min-width: 0; text-align: left; cursor: grab;
  border: 0; border-radius: 5px; padding: 4px 6px;
  background: rgba(98, 71, 168, 0.12); color: var(--ink);
  font: inherit; font-size: 0.74rem; line-height: 1.25;
  /* Without this a drag off a chip on a phone scrolls the page instead of
     picking the booking up. Everywhere that is not a chip still scrolls. */
  touch-action: none;
}
.cal-chip:hover { background: rgba(98, 71, 168, 0.2); }
/* Finished jobs read as background, not as things still to do. */
.cal-chip.done { background: var(--bone-deep); color: var(--ink-3); cursor: default; }
.cal-chip-time { display: block; font-size: 0.68rem; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-chip-name { display: block; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.cal-upcoming { margin-top: 44px; }
.cal-upcoming h2 { margin-bottom: 16px; }
.cal-empty { color: var(--ink-3); }

.cal-card {
  display: flex; gap: 18px; padding: 18px 0;
  border-top: 1px solid var(--line-soft);
}
.cal-card.flash { background: rgba(98, 71, 168, 0.07); }
.cal-card-when { text-align: center; min-width: 52px; }
.cal-card-when .d { display: block; font-family: var(--serif); font-size: 1.7rem; color: var(--plum); line-height: 1; }
.cal-card-when .mo { display: block; font-size: 0.74rem; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-3); }
.cal-card-body { flex: 1; min-width: 0; }
.cal-card-body h3 { margin: 0 0 4px; font-size: 1.05rem; display: flex; justify-content: space-between; gap: 14px; }
.cal-card-body h3 span { font-family: var(--serif); color: var(--plum); white-space: nowrap; }
.cal-meta { margin: 0 0 6px; font-size: 0.88rem; color: var(--ink-2); }
.cal-addr { margin: 0 0 6px; font-size: 0.9rem; }
.cal-addons { margin: 0 0 6px; font-size: 0.85rem; color: var(--ink-2); }
/* Access notes are the thing you actually need on the doorstep. */
.cal-notes {
  margin: 0 0 8px; font-size: 0.85rem; color: var(--ink-2);
  padding-left: 10px; border-left: 2px solid var(--accent);
}
.cal-contact { margin: 0; font-size: 0.85rem; display: flex; gap: 14px; flex-wrap: wrap; }

@media (max-width: 720px) {
  .cal-day { min-height: 78px; padding: 4px; }
  .cal-chip-time { display: none; }
  /* Taller than the text needs: on a phone a chip is a drag handle, and a
     14px-high target is not one. */
  .cal-chip { font-size: 0.68rem; padding: 6px 5px; min-height: 28px; }
  .cal-grid-head { font-size: 0.66rem; }
}

/* ---------- Calendar: recurrence, dragging, editing ---------- */

/* Projected repeats. Faded and outlined rather than filled, so at a glance
   you can tell a real booking from one the schedule implies. */
.cal-chip.ghost {
  background: transparent;
  box-shadow: inset 0 0 0 1px rgba(98, 71, 168, 0.4);
  color: var(--ink-2);
}
.cal-chip.ghost:hover { background: rgba(98, 71, 168, 0.1); }
.cal-chip.lifted { opacity: 0.35; }

.cal-drag-ghost {
  position: fixed; z-index: 90; pointer-events: none;
  box-shadow: 0 8px 20px rgba(28, 23, 51, 0.25);
  background: var(--plum); color: #fff; opacity: 0.95;
  cursor: grabbing;
}
.cal-drag-ghost .cal-chip-time { color: rgba(255, 255, 255, 0.75); }

.cal-day.drop { background: rgba(98, 71, 168, 0.14); box-shadow: inset 0 0 0 2px var(--plum); }
body.cal-dragging { cursor: grabbing; user-select: none; -webkit-user-select: none; }

.cal-tag {
  display: inline-block; font-size: 0.7rem; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-3);
  border: 1px solid var(--line-soft); border-radius: 20px; padding: 1px 8px;
}

.cal-link {
  border: 0; background: none; padding: 0; cursor: pointer;
  font: inherit; color: var(--plum); text-decoration: underline;
}

.cal-help { margin: 0 0 18px; font-size: 0.86rem; color: var(--ink-3); }

/* ---------- Calendar modal ---------- */

.cal-modal { position: fixed; inset: 0; z-index: 100; display: flex; }
.cal-modal[hidden] { display: none; }
.cal-modal-back { position: absolute; inset: 0; background: rgba(28, 23, 51, 0.45); }
.cal-modal-box {
  position: relative; margin: auto; width: min(560px, calc(100% - 24px));
  max-height: calc(100vh - 40px); overflow-y: auto;
  background: var(--paper); border-radius: var(--radius-lg);
  padding: 28px; box-shadow: 0 24px 60px rgba(28, 23, 51, 0.3);
}
body.cal-modal-open { overflow: hidden; }
.cal-modal-box h2 { margin: 0 0 8px; font-size: 1.3rem; }
.cal-lead { margin: 0 0 16px; color: var(--ink-2); font-size: 0.95rem; }
.cal-lead a { margin-right: 12px; }
.cal-edit-head { margin-bottom: 4px; }

.cal-warn, .cal-note {
  margin: 0 0 16px; padding: 11px 14px; border-radius: 8px;
  font-size: 0.86rem; line-height: 1.55;
  background: var(--bone-deep); color: var(--ink-2);
}
/* Reserved for the one that changes more than the VA asked it to. */
.cal-warn.strong { background: var(--accent-wash); color: var(--accent-dark); }

.cal-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 16px; }
.cal-field { display: block; margin-bottom: 14px; }
.cal-grid2 .cal-field { margin-bottom: 0; }
.cal-field > span {
  display: block; margin-bottom: 5px;
  font-size: 0.78rem; color: var(--ink-3); letter-spacing: .02em;
}
.cal-field input, .cal-field select, .cal-field textarea {
  width: 100%; padding: 9px 11px;
  border: 1px solid var(--line); border-radius: 8px;
  font: inherit; font-size: 16px; /* under 16px and iOS zooms on focus */
  background: var(--paper); color: var(--ink);
}
.cal-field textarea { resize: vertical; }

.cal-addons {
  border: 1px solid var(--line-soft); border-radius: 10px;
  padding: 12px 14px 4px; margin: 0 0 16px;
}
.cal-addons legend { padding: 0 6px; font-size: 0.78rem; color: var(--ink-3); }
.cal-addons label {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 0; font-size: 0.9rem;
}
.cal-addons .p { margin-left: auto; color: var(--ink-3); font-size: 0.85rem; }

.cal-price {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  background: var(--bone-deep); border-radius: 10px;
  padding: 14px 18px; margin-bottom: 16px;
}
.cal-price .was { font-family: var(--serif); font-size: 1.2rem; color: var(--ink-3); text-decoration: line-through; }
.cal-price .now { font-family: var(--serif); font-size: 1.7rem; color: var(--plum); line-height: 1; }
.cal-price .l { font-size: 0.82rem; color: var(--ink-3); }

.cal-notify {
  display: flex; align-items: flex-start; gap: 9px;
  font-size: 0.92rem; margin-bottom: 12px; line-height: 1.45;
}
.cal-notify input { margin-top: 3px; }

.cal-status { min-height: 20px; font-size: 0.88rem; color: var(--ink-3); margin-bottom: 8px; }
.cal-status.err { color: var(--accent-dark); }

.cal-actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.cal-actions .btn { padding: 11px 20px; }
.cal-danger {
  margin-left: auto; border: 0; background: none; padding: 8px 4px;
  font: inherit; font-size: 0.88rem; color: #a3324b; cursor: pointer; text-decoration: underline;
}
.cal-danger.solid {
  margin-left: 0; text-decoration: none; color: #fff; background: #a3324b;
  border-radius: var(--radius); padding: 11px 20px;
}
.cal-actions button[disabled] { opacity: .55; cursor: default; }

.cal-toast {
  position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%); z-index: 110;
  background: var(--ink); color: #fff; border-radius: 999px;
  padding: 11px 22px; font-size: 0.9rem;
  box-shadow: 0 10px 30px rgba(28, 23, 51, 0.3);
}
.cal-toast[hidden] { display: none; }

@media (max-width: 560px) {
  .cal-modal-box { padding: 20px; width: calc(100% - 16px); }
  .cal-grid2 { grid-template-columns: 1fr; }
  .cal-danger { margin-left: 0; }
}
