/*
 * Guides, the guides hub and the About page (washmates-guides issue 02).
 *
 * Linked only on those pages (BaseLayout `stylesheets`), after styles.css, and written against
 * tokens.css variables so the guides read as the same site: light surface, ink text, aqua-ink
 * links, the brand's uppercase Archivo Black for headings. The one bold element is the answer
 * block, in the teal theme the home page uses for "Rather talk?". Mobile-first; nothing here may
 * make a 360px page scroll sideways (wide tables scroll inside .table-scroll instead).
 */

/* ---------- Page frame ---------- */

/* The article is a `.flow` (washmates-seo 16): its blocks sit --gap-section apart. */
.guide {
  --flow-gap: var(--gap-section);
  max-width: 720px;
}

/*
 * styles.css gives `.page p, .page ul` a bottom margin for plain prose. Inside a guide or service
 * page the `.flow` stacks do the spacing, so clear those margins (and the UA's) here. This lives in
 * the `reset` layer (order in tokens.css): it beats the `prose` layer, and every component rule and
 * the `flow` layer's supporting-line rule beat it, so it can never zero a component's spacing again
 * (it used to, at specificity (0,1,1) and (0,2,0), which washmates-seo 03 had to work around).
 */
@layer reset {
  .guide p,
  .guide ul,
  .guide ol,
  .guide .guide-body > * {
    margin: 0;
  }
}

/* ---------- Breadcrumb ---------- */

.crumbs ol {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--ink-muted);
}

/* `.page li + li` (styles.css) adds an 8px top margin to every crumb after Home; reset it. */
.crumbs li,
.crumbs li + li {
  margin: 0;
}

.crumbs li + li::before {
  content: '›';
  margin-right: var(--space-2);
  color: var(--ink-muted);
}

/* The current page can be a long question: let it wrap anywhere rather than widen the page. */
.crumbs [aria-current='page'] {
  overflow-wrap: anywhere;
}

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

.guide__header {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Guide questions are set in sentence case (owner, 2026-10-07): same display font and sizes as the
   rest of the site, without the capitals. Smaller on phones so a ten-word question stays readable. */
.guide__title {
  margin: 0 0 var(--space-2);
  font-size: 26px;
  line-height: 1.08;
  overflow-wrap: break-word;
}

.guide__meta {
  margin: 0;
  color: var(--ink-muted);
}

.guide__meta a {
  color: var(--aqua-ink);
}

/* ---------- Share links (components/guides/ShareLinks.astro) ---------- */

/* Two sets render (owner, 2026-10-12): `--header` under the byline, `--side` under the TOC. Below
   1024px only the header set shows; from 1024px a guide with a TOC shows only the side set (the
   desktop block below). `display: none` also takes the hidden set out of the accessibility tree. */
.guide-share {
  display: flex;
  gap: var(--space-2);
}

.guide-share--side {
  display: none;
}

/* 36px discs: --surface-sunken fill with an --ink glyph at rest (about 10:1). The focus ring is
   styles.css's site-wide a:focus-visible ring, so it is not restated here. */
.guide-share a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--surface-sunken);
  color: var(--ink);
  text-decoration: none;
  transition: background-color 150ms, color 150ms;
}

/* Hover: the brand accent fill with its own icon colour (--on-aqua on --aqua, 6.9:1), the same
   aqua that marks the TOC's current section. */
.guide-share a:hover {
  background: var(--aqua);
  color: var(--on-aqua);
}

.guide-share svg {
  width: 15px;
  height: 15px;
  fill: currentColor;
}

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

.guide-hub__lede {
  margin: 0;
  color: var(--ink-muted);
}

/* ---------- The answer: the page's one bold element ---------- */

.guide-answer {
  margin: 0;
  padding: var(--space-6);
  border-radius: var(--radius-lg);
  background: var(--surface);
  color: var(--ink);
}

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

/* A `.flow` whose gap IS the supporting-line gap: the note (data-support) sits --gap-support under
   the button on phones. On desktop the note moves beside the button (below). */
.guide-cta {
  --flow-gap: var(--gap-support);
  margin: 0;
  align-items: flex-start;
}

/* The label is always "Get my free quote" (issue 10): one line, never wrapped. */
.guide-cta .wm-btn {
  white-space: nowrap;
}

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

.guide__image {
  width: 100%;
  height: auto;
  border-radius: var(--radius-lg);
}

/* ---------- Columns: the main column and, on desktop, the TOC beside it ---------- */

/* Phones and tablets: one column, TOC inline above the body (its DOM position). Both are `.flow`. */
.guide__columns,
.guide__main {
  --flow-gap: var(--gap-section);
}

/* ---------- Table of contents ---------- */

.guide-toc {
  padding-left: var(--space-3);
  border-left: 1px solid var(--border);
}

.guide-toc h2 {
  margin: 0 0 var(--gap-heading);
}

.guide-toc ol {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

/* Each link carries a left rule that lights up for the section being read (scroll-spy). It
   overlaps the nav's hairline, so the current item reads as a marker on the track. */
.guide-toc a {
  display: block;
  margin-left: calc(-1 * var(--space-3) - 1px);
  padding: var(--space-1) 0 var(--space-1) var(--space-3);
  border-left: 3px solid transparent;
  overflow-wrap: anywhere;
}

.guide-toc a[aria-current='true'] {
  border-left-color: var(--aqua);
  color: var(--ink);
  font-weight: 700;
}

/* ---------- Body (rendered Markdown) ---------- */

/* A `.flow` at the prose rhythm. Its children's margins are cleared by the `reset` layer above, so
   every block in the Markdown body sits --flow-prose apart, H2s included. (The H2s used to declare
   a 24px top margin that the old (0,2,0) reset always beat; it never rendered, so it is gone.) */
.guide-body {
  --flow-gap: var(--flow-prose);
}

.guide-body h2 {
  font-family: var(--font-display);
  font-size: 22px;
  line-height: 1.1;
  font-weight: 400;
  /* A linked section lands below the top edge, not under it. */
  scroll-margin-top: var(--space-4);
}

.guide-body h3 {
  font: var(--text-title);
}

.guide-body ul,
.guide-body ol {
  padding-left: var(--space-6);
}

.guide-body li + li {
  margin-top: var(--space-2);
}

.guide-body img {
  height: auto;
  border-radius: var(--radius-lg);
}

/* Tables: the wrapper (rehypeWrapTables) scrolls; the page never does. */
/* A table's or image's note: a paragraph that is only emphasis (`*…*` in Markdown) straight after a
   table or an image, marked `data-support` at build time (rehypeMarkSupport). The flow layer sets
   its 12px gap; this sets only its caption type. */
.guide-body p[data-support] {
  font: var(--text-caption);
  color: var(--ink-muted);
}

.guide-body p[data-support] em {
  font-style: normal;
}

.table-scroll {
  max-width: 100%;
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
}

.table-scroll:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
}

.table-scroll table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}

.table-scroll th,
.table-scroll td {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  text-align: left;
  vertical-align: top;
}

/* Short cells (prices, property types) stay on one line; the wrapper scrolls instead. */
.table-scroll th,
.table-scroll td:first-child {
  white-space: nowrap;
}

.table-scroll th {
  font: var(--text-label);
  background: var(--surface-sunken);
}

.table-scroll tr:last-child td {
  border-bottom: none;
}

/* ---------- Key takeaways ---------- */

.guide-takeaways,
.guide-faq,
.guide-related {
  /* 24px on top of the column's 24px gap: each closing section gets clear air above its rule. */
  margin-top: var(--gap-section);
  padding-top: var(--gap-section);
  border-top: 1px solid var(--border);
}

.guide-takeaways h2,
.guide-faq h2,
.guide-related h2 {
  margin: 0 0 var(--gap-heading);
}

.guide-takeaways ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.guide-takeaways li {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
}

.guide-takeaways svg {
  flex-shrink: 0;
  margin-top: 2px;
}

/* ---------- FAQ (reuses the home page's .faq__item) ---------- */

.faq__question {
  margin: 0;
  font: inherit;
}

/* ---------- Related guides ---------- */

/*
 * Related guides as small picture cards (issue 12, owner's pick "B + picture"): the guide's photo
 * (or the hub's placeholder) fills the card, a dark teal fade sits over it, and the cluster line,
 * the title and an aqua arrow sit at the foot. The card's link carries data-theme="teal", so
 * --ink, --ink-muted, --surface, --surface-sunken and --on-aqua below are the teal theme's values.
 * 1 column on phones, 2 from 560px (the 720px reading column fits two ~354px cards).
 */
.related-grid {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-3);
}

/* `.page li + li` (styles.css) adds a top margin to every item after the first; the gap spaces here. */
.related-grid > li + li {
  margin-top: 0;
}

.related-card {
  display: flex;
  border-radius: var(--radius-md);
}

/* The focus ring is the <li>'s, so it keeps the light theme's ring colour (the link is teal-themed). */
.related-card:has(.related-card__link:focus-visible) {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
}

.related-card__link:focus-visible {
  outline: none;
}

/* The one link fills the card: the whole card is the hit area. */
.related-card__link {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  width: 100%;
  min-height: 148px;
  padding: var(--space-4);
  border-radius: inherit;
  background: var(--surface);
  color: var(--ink);
  text-decoration: none;
}

.related-card__link:hover {
  color: var(--ink);
}

.related-card__image {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
  transition: transform 0.3s ease;
}

/* A light tint over the whole picture, so the cards read as one set whatever the photos. */
.related-card__link::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--surface) 25%, transparent) 0%,
    color-mix(in srgb, var(--surface) 60%, transparent) 100%
  );
}

.related-card__text {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/*
 * The contrast fade, tied to the text block rather than to a fixed share of the card: it starts
 * 32px above the cluster line and reaches 85% teal at the line, then 94% at the foot, however many
 * lines the title wraps to. On a pure white photo that is ~6:1 for the cluster line (ink-muted)
 * and ~8:1 for the title (ink), so both pass 4.5:1 on any picture.
 */
.related-card__text::before {
  content: '';
  position: absolute;
  inset: calc(-1 * var(--space-8)) calc(-1 * var(--space-4)) calc(-1 * var(--space-4));
  z-index: -1;
  background: linear-gradient(
    180deg,
    transparent 0,
    color-mix(in srgb, var(--surface) 85%, transparent) var(--space-8),
    color-mix(in srgb, var(--surface-sunken) 94%, transparent) 100%
  );
}

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

.related-card__row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-3);
}

.related-card__title {
  min-width: 0;
  font: 700 17px/22px var(--font-sans);
  text-wrap: balance;
  overflow-wrap: break-word;
}

.related-card__arrow {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-pill);
  background: var(--aqua);
  color: var(--on-aqua);
}

.related-card__arrow svg {
  transition: transform 0.15s ease;
}

.related-card__link:hover .related-card__image {
  transform: scale(1.04);
}

.related-card__link:hover .related-card__title {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.related-card__link:hover .related-card__arrow svg {
  transform: translateX(2px);
}

@media (prefers-reduced-motion: reduce) {
  .related-card__image,
  .related-card__arrow svg {
    transition: none;
  }

  .related-card__link:hover .related-card__image,
  .related-card__link:hover .related-card__arrow svg {
    transform: none;
  }
}

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

/* "All guides" stays a plain text link under the cards (.page p would add a bottom margin). */
.page .guide-related__hub {
  margin: var(--space-4) 0 0;
}

.guide-related__hub a {
  font: var(--text-label);
}

/* ---------- Hub ---------- */

/*
 * The hub drops the guides' 720px reading measure (issue 09) so three cards fit across on
 * desktop: it fills main.page's content box, which the --gutter padding already keeps level with
 * the header (16px each side on phones). The lede keeps the measure.
 */
.guide-hub {
  max-width: none;
}

.guide-hub__lede {
  max-width: 720px;
}

.guide-hub__group h2 {
  margin: 0 0 var(--space-3);
}

/* 1 column on phones, 2 from 640px, 3 from 1024px (below). minmax(0, 1fr) so a long word in a
   title can never widen a column past the page. */
.guide-hub__grid {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-3);
}

/*
 * A card: the home page's .service-card (styles.css) for the hub. Flat, as tokens.css asks of
 * cards: raised surface, hairline border, --radius-lg, image clipped to the corners.
 */
.guide-card {
  display: flex;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

/* `.page li + li` (styles.css) adds an 8px top margin to every item after the first; the grid gap
   does the spacing here. */
.guide-hub__grid > li + li {
  margin-top: 0;
}

.guide-card:hover {
  border-color: var(--border-strong);
}

/* The one link fills the card, so the whole card is the hit area and the focus ring outlines it. */
.guide-card__link {
  display: flex;
  flex-direction: column;
  width: 100%;
  color: var(--ink);
  text-decoration: none;
}

.guide-card:has(.guide-card__link:focus-visible) {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
}

.guide-card__link:focus-visible {
  outline: none;
}

/* Same 3:2 box on every card, whatever the source's shape. */
.guide-card__image {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}

.guide-card__body {
  padding: var(--space-3) var(--space-4) var(--space-4);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-1);
  flex-grow: 1;
}

/* Title scale at every width (unlike the home service card, whose phone names are label-size
   because the description is hidden there): here the description always shows, so the title
   must read bigger than it. */
.guide-card__title {
  margin: 0;
  font: var(--text-title);
  overflow-wrap: break-word;
}

.guide-card__link:hover .guide-card__title {
  text-decoration: underline;
  text-underline-offset: 3px;
}

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

/* The label sits at the foot of the card, so the labels in a row line up. */
.guide-card .guide__meta {
  margin-top: auto;
  padding-top: var(--space-2);
}

.guide-hub__draft {
  padding: 0 var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--sun);
  color: var(--on-sun);
}

@media (min-width: 640px) {
  .guide-hub__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1024px) {
  /*
   * Two columns when the guide has a TOC (owner request 2026-10-07): the article left, the TOC in
   * a sticky right-hand column that starts level with the breadcrumb and H1.
   *
   * The frame fills main.page's content box, whose padding is the same --gutter the site header
   * uses, so the TOC's right edge lines up with the header's content (x 80–1200 at 1280px).
   *
   * Source order is untouched (header → answer → CTA → TOC → body), so the answer stays the
   * header's next sibling. The article itself becomes the grid and .guide__columns is
   * `display: contents`, so the TOC and .guide__main are grid items too. The five left-column
   * items (breadcrumb, header, answer, CTA, main) each take one auto row in order; the TOC spans
   * those five rows in column 2. A spanning item only grows its rows when it is taller than the
   * rows it spans together, and the TOC is capped at the viewport height while .guide__main
   * holds the whole body, so the left column's rows and gaps are exactly the one-column ones.
   * If a sixth left-column item is ever added, raise the span.
   *
   * Text keeps the ~720px reading measure; images, figures and tables can use the full
   * left-column width.
   */
  .guide--toc {
    max-width: none;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(240px, 280px);
    column-gap: var(--space-12);
    row-gap: var(--space-6);
    align-items: start;
  }

  .guide--toc > .guide__columns {
    display: contents;
  }

  .guide--toc > :not(.guide__columns),
  .guide--toc .guide__main {
    grid-column: 1;
  }

  .guide > :not(.guide__columns),
  .guide__main > :not(.guide-body):not(.guide__image),
  .guide-body > :not(img):not(figure):not(picture):not(.table-scroll) {
    max-width: 720px;
  }

  /* Markdown wraps a lone image in a <p>: let that paragraph go full width too. Its own rule,
     because a browser without :has() drops a whole selector list it can't parse. Specificity
     (0,2,3) matches the 720px rule above, and this rule comes later, so it wins. */
  main .guide .guide-body > p:has(> img) {
    max-width: none;
  }

  /* The TOC and the share discs under it stick just below the pinned site header (washmates-seo
     14; --site-header-pinned-h comes from styles.css). A column taller than the space left
     scrolls on its own. */
  .guide--toc .guide-side {
    display: flex;
    flex-direction: column;
    gap: var(--space-6);
    grid-column: 2;
    grid-row: 1 / span 5;
    position: sticky;
    top: calc(var(--site-header-pinned-h, 0px) + var(--space-6));
    max-height: calc(100vh - var(--site-header-pinned-h, 0px) - 2 * var(--space-6));
    overflow-y: auto;
    /* overflow-y:auto also clips x, and the 3px + 2px focus ring sits outside each link's box, so
       give the ring room inside the scroller and pull the box back out by the same amount. */
    padding: var(--space-2) calc(var(--space-2) - 2px);
    margin: calc(-1 * var(--space-2)) calc(-1 * (var(--space-2) - 2px));
  }

  .guide--toc .guide-share--side {
    display: flex;
  }

  .guide--toc .guide-share--header {
    display: none;
  }

  .guide__title {
    font-size: 40px;
  }

  .guide-body h2 {
    font-size: 26px;
  }

  /* The note beside the button: only the column gap changes, so --flow-gap (the row gap) stays
     --gap-support and the note's support margin stays 0. */
  .guide-cta {
    flex-direction: row;
    align-items: center;
    column-gap: var(--space-4);
  }

  .faq__item summary .faq__question {
    font: var(--text-title);
  }

  /* The hub's groups take the full frame, not the 720px measure set above for guides. Same
     specificity as `.guide > :not(.guide__columns)` and later in the file, so it wins. */
  .guide.guide-hub > * {
    max-width: none;
  }

  /* Hub: three across, with the service cards' desktop padding. */
  .guide-hub__grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-4);
  }

  .guide-card__body {
    padding: 20px var(--space-6) var(--space-6);
    gap: var(--space-2);
  }
}
