/**
 * SingleNotAlone components.
 *
 * Loaded on the front end and inside the block editor, so what an author sees
 * while writing is what a visitor gets. Depends on tokens.css.
 *
 * Mobile first throughout: the base rules are the 360px layout, and media
 * queries only ever add.
 */

/* ---------------------------------------------------------------------------
 * Base
 * ------------------------------------------------------------------------ */

body {
  background-color: var(--brand-ivory);
  color: var(--brand-ink);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4,
.wp-block-heading {
  font-family: var(--font-heading);
  font-weight: 600;
  line-height: var(--lh-heading);
  color: var(--brand-plum);
  text-wrap: balance;
}

h1 { font-size: var(--step-4); }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-2); }
h4 { font-size: var(--step-1); }

/* Measure cap.
 *
 * Applied to text elements rather than to the container, so a card or grid
 * cell is not forced narrow and full width media still spans.
 *
 * Scoped to .entry-content and written at class level specificity on purpose:
 * Kadence caps direct children of the content area at --global-calc-content-width
 * (1242px by default) with a class based selector, so a bare `p` selector loses
 * the cascade and the measure silently does nothing. Verified in the browser,
 * not assumed.
 *
 * The :not() exclusions keep eyebrows and markers full width, since they are
 * short labels that should never wrap at 68ch.
 */
.entry-content :is(p, li, blockquote):not(.sna-eyebrow):not(.sna-marker),
.sna-measure {
  /* Read through a local override so a component can set its own measure by
     declaring --measure-local on itself. A custom property set on the element
     always wins, which avoids an escalating specificity war against this
     rule's own :not() chain. */
  max-width: var(--measure-local, var(--measure));

  /* The constrained layout gives any max-width child automatic margins on both
     sides, which centres the capped text and leaves it 115px adrift from the
     full width heading above it.

     WordPress writes those margins as `margin-left: auto !important`, so a
     normal declaration cannot win no matter how specific it is. Matching the
     !important is the only way to pin the text flush to its heading. This is
     the one place in the theme that uses it. */
  margin-inline-start: 0 !important;
  margin-inline-end: auto !important;
}

/* Explicitly centred text opts back in to symmetric margins. */
.entry-content :is(p, li, blockquote).has-text-align-center,
.has-text-align-center :is(p, li) {
  margin-inline-start: auto !important;
  margin-inline-end: auto !important;
}

/* Dark and tint surfaces inherit their text colour from the alias tokens. */
.is-style-sna-surface-plum,
.is-surface-plum,
.is-style-sna-surface-tint,
.is-surface-tint {
  background-color: var(--surface);
  color: var(--text);
}

.is-style-sna-surface-plum h1,
.is-style-sna-surface-plum h2,
.is-style-sna-surface-plum h3,
.is-style-sna-surface-plum h4,
.is-surface-plum h1,
.is-surface-plum h2,
.is-surface-plum h3,
.is-surface-plum h4 {
  color: var(--brand-ivory);
}

/* ---------------------------------------------------------------------------
 * Kadence reconciliation
 *
 * Almost all of Kadence's chrome follows the variable bridge in tokens.css.
 * The header is the exception: the header builder prints an inline rule with a
 * literal `#masthead { background: #ffffff }`, so no variable can reach it and
 * a white band sits against the ivory page.
 *
 * `body #masthead` outranks the parent's plain `#masthead` on specificity
 * rather than on source order, so this holds no matter where Kadence chooses
 * to print its inline styles.
 *
 * Full header and footer treatment belongs to Phase 3. This is only the colour
 * seam, fixed here so the token layer can be judged on its own.
 * ------------------------------------------------------------------------ */

body #masthead,
body #masthead .kadence-sticky-header.item-is-fixed:not(.item-at-start) > .site-header-row-container-inner {
  background-color: var(--brand-ivory);
}

body #colophon {
  background-color: var(--brand-ivory);
}

/* ---------------------------------------------------------------------------
 * Eyebrows, labels, and the 01 to 05 dimension markers
 *
 * The numbered markers are the signature detail of the framework. Plex Mono,
 * uppercase, wide tracking.
 * ------------------------------------------------------------------------ */

.sna-eyebrow,
.sna-marker {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-secondary);
  margin: 0 0 var(--space-xs);
  max-width: none;
}

.sna-marker {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  color: var(--accent);
}

/* The gold hairline that follows a marker. Gold as a non text element, which
   is unrestricted, unlike gold as text. */
.sna-marker::after {
  content: "";
  display: block;
  width: var(--space-l);
  height: var(--hairline);
  background-color: var(--brand-gold);
}

/* ---------------------------------------------------------------------------
 * Rules and dividers
 * ------------------------------------------------------------------------ */

.wp-block-separator.is-style-sna-hairline {
  border: 0;
  border-top: var(--hairline) solid var(--brand-gold);
  opacity: 1;
  max-width: var(--space-3xl);
  margin-block: var(--space-xl);
}

.wp-block-separator.is-style-sna-hairline.alignwide,
.wp-block-separator.is-style-sna-hairline.alignfull {
  max-width: none;
}

.is-style-sna-surface-plum .wp-block-separator.is-style-sna-hairline,
.is-surface-plum .wp-block-separator.is-style-sna-hairline {
  border-top-color: var(--brand-gold-200);
}

/* ---------------------------------------------------------------------------
 * Buttons
 *
 * The gold variant hardcodes a black label. This pairing measures 8.18:1.
 * Gold with a white label would be 2.1:1, which is why the colour is not left
 * to a picker. See design/contrast-report.md.
 * ------------------------------------------------------------------------ */

.wp-block-button__link {
  font-family: var(--font-body);
  font-weight: 500;
  border-radius: var(--radius);
  padding: 0.85rem 1.5rem;
  text-decoration: none;
  transition:
    background-color var(--motion-duration) var(--motion-easing),
    color var(--motion-duration) var(--motion-easing);
}

.wp-block-button:not(.is-style-outline) .wp-block-button__link {
  background-color: var(--brand-purple);
  color: var(--brand-ivory);
}

.wp-block-button:not(.is-style-outline) .wp-block-button__link:hover,
.wp-block-button:not(.is-style-outline) .wp-block-button__link:focus-visible {
  background-color: var(--brand-purple-700);
  color: var(--brand-ivory);
}

.wp-block-button.is-style-sna-gold .wp-block-button__link {
  background-color: var(--brand-gold);
  color: var(--brand-black);
}

.wp-block-button.is-style-sna-gold .wp-block-button__link:hover,
.wp-block-button.is-style-sna-gold .wp-block-button__link:focus-visible {
  background-color: var(--brand-gold-200);
  color: var(--brand-black);
}

.wp-block-button.is-style-sna-outline-light .wp-block-button__link {
  background-color: transparent;
  color: var(--brand-ivory);
  box-shadow: inset 0 0 0 var(--hairline) var(--brand-gold-200);
}

.wp-block-button.is-style-sna-outline-light .wp-block-button__link:hover,
.wp-block-button.is-style-sna-outline-light .wp-block-button__link:focus-visible {
  background-color: var(--brand-gold-200);
  color: var(--brand-black);
}

/* ---------------------------------------------------------------------------
 * Links
 * ------------------------------------------------------------------------ */

a:where(:not(.wp-block-button__link)) {
  color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

a:where(:not(.wp-block-button__link)):hover {
  color: var(--brand-purple-700);
}

.is-style-sna-surface-plum a:where(:not(.wp-block-button__link)),
.is-surface-plum a:where(:not(.wp-block-button__link)) {
  color: var(--brand-gold-200);
}

/* ---------------------------------------------------------------------------
 * Focus
 *
 * Visible focus is non negotiable for the keyboard pass. Purple on light,
 * gold on dark, both measured above 3:1 against their surface.
 * ------------------------------------------------------------------------ */

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--brand-purple);
  outline-offset: 2px;
  border-radius: 2px;
}

.is-style-sna-surface-plum :focus-visible,
.is-surface-plum :focus-visible,
.is-surface-black :focus-visible {
  outline-color: var(--brand-gold);
}

/* Skip link. Off screen until focused, then pinned top left. */
.sna-skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 999999;
  padding: var(--space-2xs) var(--space-s);
  background-color: var(--brand-plum);
  color: var(--brand-ivory);
  font-family: var(--font-body);
  font-size: var(--step--1);
  text-decoration: none;
  border-radius: 0 0 var(--radius) 0;
}

.sna-skip-link:focus {
  left: 0;
}

/* ---------------------------------------------------------------------------
 * Cards and surfaces
 * ------------------------------------------------------------------------ */

.sna-card {
  background-color: var(--brand-purple-100);
  border-radius: var(--radius);
  padding: var(--space-m);
  box-shadow: var(--shadow);
  --surface: var(--brand-purple-100);
  --text: var(--brand-ink);
  --text-secondary: var(--brand-muted-tint);
  --accent: var(--brand-purple-700);
}

.sna-badge {
  display: inline-block;
  border-radius: var(--radius-badge);
  padding: var(--space-3xs) var(--space-xs);
  background-color: var(--brand-purple-100);
  color: var(--brand-purple-700);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

/* ---------------------------------------------------------------------------
 * Sections
 * ------------------------------------------------------------------------ */

.sna-section {
  padding-block: var(--space-section);
}

/* A full width section loses the content container's horizontal padding, so
   its text runs into the viewport edge. Restore the gutter on the section and
   keep the inner content constrained to the wide width. */
.sna-section.alignfull,
.wp-block-group.alignfull.is-surface-plum,
.wp-block-group.alignfull.is-style-sna-surface-plum {
  padding-inline: var(--gutter);
}

.sna-section.alignfull > :where(:not(.alignfull):not(.alignwide)) {
  margin-inline: auto;
  max-width: var(--width-wide);
}

/* ---------------------------------------------------------------------------
 * Motion
 *
 * Fade and rise, 8px, 240ms. The global reduced motion kill switch lives in
 * tokens.css, so anything added here inherits it.
 * ------------------------------------------------------------------------ */

@media (prefers-reduced-motion: no-preference) {
  .sna-rise {
    animation: sna-rise var(--motion-duration) var(--motion-easing) both;
  }

  @keyframes sna-rise {
    from {
      opacity: 0;
      transform: translateY(var(--motion-travel));
    }
    to {
      opacity: 1;
      transform: none;
    }
  }
}

/* ---------------------------------------------------------------------------
 * Larger viewports
 *
 * Everything above is the 360px layout. These only add.
 * ------------------------------------------------------------------------ */

@media (min-width: 48em) {
  .sna-card {
    padding: var(--space-l);
  }
}

/* ===========================================================================
 * PATTERNS
 *
 * Styles for the thirteen registered block patterns. Everything below is
 * mobile first: base rules are the 360px layout and media queries only add.
 * ======================================================================== */

/* ---------------------------------------------------------------------------
 * Hero
 *
 * Structure borrowed from the reference the owner supplied: a full bleed
 * saturated field, an oversized headline, a solid plus outline CTA pair, and
 * a large artifact breaking out of the field's lower edge.
 *
 * The field is plum rather than a vivid colour because plum is the only
 * surface on which every element clears AA, gold text included (7.70:1).
 * ------------------------------------------------------------------------ */

.sna-hero {
  padding-block: var(--space-section) 0;
  position: relative;
}

.sna-hero__title {
  --measure-local: 16ch;
  font-size: var(--step-4);
  line-height: 1.04;
  letter-spacing: -0.015em;
  color: var(--brand-ivory);
  margin-block: var(--space-s) var(--space-m);
}

.sna-hero__lede {
  --measure-local: 46ch;
  font-size: var(--step-1);
  line-height: 1.5;
  color: var(--brand-ivory);
}

.sna-hero__actions {
  margin-top: var(--space-l);
  gap: var(--space-m);
}

/* The proof line. Currently carries no figure by design: see
   content/NEEDS-VERIFICATION.md item 4. The gold rule to its left is what
   gives it presence without a number to lean on. */
.sna-hero__proof {
  --measure-local: 30ch;
  font-size: var(--step--1);
  color: var(--brand-gold-200);
  padding-left: var(--space-s);
  border-left: var(--hairline) solid var(--brand-gold);
  margin: 0;
}

/* The artifact.
 *
 * A negative bottom margin shortens the hero's content box, so the hero's
 * plum background ends early and the artifact hangs below it over whatever
 * follows. z-index keeps it above the next section's background.
 *
 * `.sna-hero + *` pays the overlap back as top padding on the following
 * section, so the effect is self contained: drop the hero on any page and the
 * spacing is right without the next block having to know about it. */
.sna-hero__artifact {
  position: relative;
  z-index: 1;
  margin-top: var(--space-2xl);
  margin-bottom: calc(var(--space-2xl) * -1);
  padding: var(--space-m);
  background-color: var(--brand-ivory);
  border-radius: var(--radius);
  border: var(--hairline) solid var(--brand-gold);
  box-shadow: var(--shadow);

  /* The artifact sits on ivory, so the dark surface tokens inherited from the
     hero must be reset or its text would be ivory on ivory. */
  --surface: var(--brand-ivory);
  --text: var(--brand-ink);
  --text-secondary: var(--brand-muted);
  --accent: var(--brand-purple);
  color: var(--brand-ink);
}

.sna-hero + * {
  padding-top: calc(var(--space-section) + var(--space-2xl));
}

.sna-artifact__label {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--brand-muted);
  margin: 0 0 var(--space-m);
  max-width: none;
}

.sna-artifact__grid {
  gap: var(--space-m);
}

.sna-artifact__item {
  padding-top: var(--space-2xs);
  border-top: var(--hairline) solid var(--rule);
}

.sna-artifact__name {
  font-family: var(--font-heading);
  font-size: var(--step-1);
  font-weight: 600;
  color: var(--brand-plum);
  margin: var(--space-2xs) 0 var(--space-3xs);
}

.sna-artifact__note {
  font-size: var(--step--1);
  color: var(--brand-muted);
  margin: 0;
}

/* ---------------------------------------------------------------------------
 * Shared layout helpers
 * ------------------------------------------------------------------------ */

.sna-grid {
  gap: var(--space-m);
  margin-top: var(--space-xl);
}

.sna-lede {
  --measure-local: 46ch;   /* aligned to the corrected base */
  font-size: var(--step-1);
  color: var(--text-secondary);
}

.sna-card__link a {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: var(--hairline) solid var(--brand-gold);
  padding-bottom: 2px;
}

.sna-card__link a:hover {
  border-bottom-color: currentColor;
}

.sna-note {
  --measure-local: 45ch;   /* was 60ch: measured 82 chars, see tokens.css */
  font-size: var(--step--1);
  color: var(--text-secondary);
}

/* Anything unfinished announces itself. A half built page should be obvious
   at a glance rather than quietly shipping with filler in it. */
.sna-placeholder__tag {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--brand-purple-700);
  background-color: var(--brand-purple-100);
  border-left: 3px solid var(--brand-gold);
  padding: var(--space-2xs) var(--space-xs);
  border-radius: 0 var(--radius) var(--radius) 0;
  max-width: none;
}

.is-style-sna-surface-plum .sna-placeholder__tag {
  color: var(--brand-plum);
  background-color: var(--brand-gold-200);
}

/* ---------------------------------------------------------------------------
 * Dimension detail band
 * ------------------------------------------------------------------------ */

.sna-band__grid {
  gap: var(--space-l);
  margin-top: var(--space-l);
}

.sna-band__title {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--brand-purple);
}

/* The practice is the one thing the reader can act on today, so it spans the
   full row rather than trailing as a fourth column. At three columns it was
   also being orphaned onto a row of its own, which read as a mistake. */
.sna-band__item--practice {
  grid-column: 1 / -1;
  background-color: var(--brand-purple-100);
  border-radius: var(--radius);
  padding: var(--space-m);
  --text-secondary: var(--brand-muted-tint);
}

/* ---------------------------------------------------------------------------
 * Offers
 * ------------------------------------------------------------------------ */

.sna-offer {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  padding: var(--space-m);
  border: var(--hairline) solid var(--rule);
  border-radius: var(--radius);
  background-color: var(--brand-ivory);
}

.sna-offer--featured {
  border-color: var(--brand-gold);
  box-shadow: var(--shadow);
}

.sna-offer .wp-block-buttons {
  margin-top: auto;
  padding-top: var(--space-s);
}

/* The pricing slot. Visible and styled precisely so a missing price reads as
   deliberate rather than broken. */
.sna-offer__price {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--brand-purple-700);
  margin: 0;
  padding-bottom: var(--space-2xs);
  border-bottom: var(--hairline) solid var(--brand-gold);
}

.sna-offer__who {
  font-size: var(--step--1);
  color: var(--brand-muted);
  font-style: italic;
  margin: 0;
}

/* ---------------------------------------------------------------------------
 * Testimonials
 * ------------------------------------------------------------------------ */

.sna-testimonial {
  padding: var(--space-m);
  border-left: 2px solid var(--brand-gold);
  background-color: var(--brand-purple-100);
  border-radius: 0 var(--radius) var(--radius) 0;
  --text-secondary: var(--brand-muted-tint);
}

.sna-testimonial__quote {
  font-family: var(--font-heading);
  font-size: var(--step-1);
  line-height: 1.4;
  color: var(--brand-ink);
}

.sna-testimonial__who {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: 0.04em;
  color: var(--brand-muted-tint);
  margin: 0;
}

/* ---------------------------------------------------------------------------
 * Pull quote
 * ------------------------------------------------------------------------ */

.sna-pullquote {
  margin-block: var(--space-xl);
}

.sna-pullquote__text {
  --measure-local: 30ch;
  font-family: var(--font-heading);
  font-size: var(--step-2);
  line-height: 1.25;
  color: var(--brand-plum);
  margin-block: var(--space-m);
}

.sna-pullquote .wp-block-separator.is-style-sna-hairline {
  margin-block: 0;
  max-width: var(--space-2xl);
}

/* ---------------------------------------------------------------------------
 * FAQ
 *
 * Native details elements. Keyboard operable and screen reader announced with
 * no JavaScript, and the answers are in the DOM whether open or closed.
 * ------------------------------------------------------------------------ */

.sna-faq__item {
  border-bottom: var(--hairline) solid var(--rule);
  padding-block: var(--space-s);
}

.sna-faq__item summary {
  font-family: var(--font-heading);
  font-size: var(--step-1);
  font-weight: 600;
  color: var(--brand-plum);
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-s);
}

.sna-faq__item summary::-webkit-details-marker {
  display: none;
}

/* A gold plus and minus, drawn in text so it needs no icon font or SVG. */
.sna-faq__item summary::after {
  content: "+";
  font-family: var(--font-mono);
  color: var(--brand-gold);
  font-size: var(--step-1);
  line-height: 1;
  flex-shrink: 0;
}

.sna-faq__item[open] summary::after {
  content: "\2013";
}

.sna-faq__item[open] summary {
  margin-bottom: var(--space-2xs);
}

/* ---------------------------------------------------------------------------
 * Lead magnet
 * ------------------------------------------------------------------------ */

.sna-magnet {
  padding: var(--space-l) var(--space-m);
  border-radius: var(--radius);
  border: var(--hairline) solid var(--brand-gold);
}

/* ---------------------------------------------------------------------------
 * Call to action band
 * ------------------------------------------------------------------------ */

.sna-cta {
  text-align: center;
}

.sna-cta__title {
  --measure-local: 20ch;
  font-size: var(--step-3);
  color: var(--brand-ivory);
  margin-inline: auto;
}

.sna-cta__lede {
  --measure-local: 46ch;   /* aligned to the corrected base */
  margin-inline: auto !important;
  color: var(--brand-ivory);
}

.sna-cta .sna-eyebrow,
.sna-cta .wp-block-buttons {
  justify-content: center;
  text-align: center;
}

/* ---------------------------------------------------------------------------
 * Coach bio
 * ------------------------------------------------------------------------ */

.sna-bio__portrait img {
  border-radius: var(--radius);
  width: 100%;
  height: auto;
}

/* The portrait ships as a real placeholder file rather than an empty src,
   because WordPress removes an image block that has neither a src nor an
   attachment id, which silently deleted the whole column. See the note at the
   top of patterns/coach-bio.php. */
.sna-bio__portrait img {
  display: block;
  aspect-ratio: 4 / 5;
  object-fit: cover;
}

.sna-bio__portrait figcaption {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--brand-muted);
}

/* ---------------------------------------------------------------------------
 * Stat row
 * ------------------------------------------------------------------------ */

.sna-stats__row {
  gap: var(--space-l);
  text-align: center;
}

.sna-stat__figure {
  font-family: var(--font-heading);
  font-size: var(--step-3);
  font-weight: 600;
  color: var(--brand-plum);
  line-height: 1.1;
  margin: 0;
  max-width: none;
}

.sna-stat__label {
  font-size: var(--step--1);
  color: var(--brand-muted);
  margin: var(--space-2xs) auto 0 !important;
  --measure-local: 24ch;
}

/* ---------------------------------------------------------------------------
 * Blog cards
 * ------------------------------------------------------------------------ */

.sna-postcard {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  padding-top: var(--space-s);
  border-top: 2px solid var(--brand-gold);
}

.sna-postcard__title a {
  font-family: var(--font-heading);
  font-size: var(--step-1);
  color: var(--brand-plum);
  text-decoration: none;
}

.sna-postcard__title a:hover {
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

.sna-postcard__date {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--brand-muted);
  margin-top: auto;
}

.sna-postcard .sna-eyebrow a {
  color: var(--brand-purple);
  text-decoration: none;
}

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

.sna-newsletter__title {
  --measure-local: 22ch;
  font-size: var(--step-2);
  color: var(--brand-ivory);
}

/* ---------------------------------------------------------------------------
 * Larger viewports
 * ------------------------------------------------------------------------ */

@media (min-width: 48em) {
  .sna-hero {
    padding-block: calc(var(--space-section) * 1.15) 0;
  }

  .sna-hero__artifact {
    padding: var(--space-l);
  }

  .sna-magnet {
    padding: var(--space-2xl) var(--space-xl);
  }

  .sna-offer {
    padding: var(--space-l);
  }
}

/* ---------------------------------------------------------------------------
 * Pattern gallery label
 *
 * Used only by the internal /pattern-gallery/ review page, which exists so
 * every pattern can be seen rendered in one pass. Not used by the site.
 * ------------------------------------------------------------------------ */

.sna-demo__label p {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--brand-ivory);
  background-color: var(--brand-plum);
  padding: var(--space-2xs) var(--space-s);
  margin-block: var(--space-2xl) 0;
  max-width: none !important;
}

.sna-band__item--practice .sna-band__title {
  color: var(--brand-purple-700);
}

/* ---------------------------------------------------------------------------
 * Offer grid column counts
 *
 * There are exactly four offers, so the column count must divide into four.
 * WordPress's auto-fill grid produced three columns at desktop and orphaned
 * the fourth card on a row of its own, which reads as a mistake rather than a
 * layout. Fixed counts (1, then 2, then 4) mean the row is always complete.
 *
 * .sna-grid.sna-offers outranks the block layout class WordPress generates,
 * so this holds regardless of stylesheet order.
 * ------------------------------------------------------------------------ */

@media (min-width: 40em) {
  .sna-grid.sna-offers {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 64em) {
  .sna-grid.sna-offers {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* ===========================================================================
 * TEMPLATES
 * ======================================================================== */

/* ---------------------------------------------------------------------------
 * Page container for PHP templates
 *
 * Block pages get their width from the layout system. PHP templates (404,
 * search, focused pages) have no blocks, so they need the container drawn
 * explicitly to match.
 * ------------------------------------------------------------------------ */

.sna-page {
  max-width: var(--width-wide);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.sna-page--focused {
  max-width: var(--width-content);
  text-align: left;
}

/* ---------------------------------------------------------------------------
 * Focused pages
 *
 * One job per page, so anything competing with it is hidden. The logo stays,
 * and stays linked home, so the visitor is never trapped.
 * ------------------------------------------------------------------------ */

/*
 * The focused pages no longer suppress navigation.
 *
 * This rule used to hide the header nav, the mobile toggle AND the footer menu
 * on Book a Call, Thank you and Confirmed. The reasoning was the standard
 * conversion one: fewer exits from the page that carries the single action.
 *
 * Removed on instruction, for consistency: the owner's call is that the same
 * header and the same footer on every page matters more than the extra exit
 * paths cost. Worth knowing that is the trade being made, since it is a real
 * one on the booking page specifically.
 *
 * It also fixes something that was almost certainly never intended: the same
 * selector list took the FOOTER menu with it, so those three pages shipped with
 * a footer containing only a copyright line.
 */

/* ---------------------------------------------------------------------------
 * 404 and search
 * ------------------------------------------------------------------------ */

.sna-404__links {
  list-style: none;
  padding: 0;
  margin: var(--space-l) 0;
  max-width: none;
}

.sna-404__links li {
  padding-block: var(--space-s);
  border-top: var(--hairline) solid var(--rule);
  max-width: none;
}

.sna-404__links li:last-child {
  border-bottom: var(--hairline) solid var(--rule);
}

.sna-404__links a {
  display: block;
  font-family: var(--font-heading);
  font-size: var(--step-1);
  font-weight: 600;
  color: var(--brand-plum);
  text-decoration: none;
}

.sna-404__links a:hover {
  color: var(--brand-purple);
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

.sna-404__links span {
  display: block;
  font-size: var(--step--1);
  color: var(--brand-muted);
  margin-top: var(--space-3xs);
}

.sna-search__count {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: 0.04em;
  color: var(--brand-muted);
}

.sna-search__results {
  display: grid;
  gap: var(--space-l);
  margin-block: var(--space-l);
}

@media (min-width: 48em) {
  .sna-search__results {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* Search inputs. Kadence styles its own form; these bring it onto the tokens
   without replacing the markup. */
.sna-page .search-form input[type="search"],
.sna-page .wp-block-search__input {
  font-family: var(--font-body);
  font-size: var(--step-0);
  padding: var(--space-2xs) var(--space-xs);
  border: var(--hairline) solid var(--brand-muted);
  border-radius: var(--radius);
  background-color: var(--brand-ivory);
  color: var(--brand-ink);
  max-width: 24rem;
  width: 100%;
}

.sna-page .search-form input[type="search"]:focus-visible,
.sna-page .wp-block-search__input:focus-visible {
  outline: 2px solid var(--brand-purple);
  outline-offset: 2px;
  border-color: var(--brand-purple);
}

/* ---------------------------------------------------------------------------
 * Header and footer
 *
 * Deferred out of Phase 1, where only the colour seam was fixed. The site is
 * one continuous ivory surface, so the header and footer are separated by gold
 * hairlines rather than by blocks of contrasting colour.
 * ------------------------------------------------------------------------ */

body #masthead {
  border-bottom: var(--hairline) solid var(--rule);
}

body #colophon {
  border-top: var(--hairline) solid var(--brand-gold);
}

/* Navigation.
 *
 * This was mono, uppercase, and widely tracked, matching the eyebrows. The
 * owner's verdict was that it read as terrible, and they were right: uppercase
 * monospace is engineering chrome, and at nav sizes it is both harder to scan
 * and colder than anything else on the page. A coaching practice should not
 * greet you in a terminal font.
 *
 * Now the body face at a slightly heavier weight, sentence case, with only a
 * touch of tracking. It reads as a person's website rather than a dashboard. */
#masthead .main-navigation .menu > li > a,
#masthead .header-navigation .menu > li > a {
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: 0.005em;
  text-transform: none;
  color: var(--brand-ink);
}

#masthead .main-navigation .menu > li > a:hover,
#masthead .header-navigation .menu > li > a:hover {
  color: var(--brand-purple);
}

/* Current page marked with a gold rule rather than a colour change, so it
   reads at a glance without relying on colour alone. */
#masthead .menu .current-menu-item > a,
#masthead .menu .current-menu-ancestor > a {
  color: var(--brand-purple);
  box-shadow: inset 0 -2px 0 0 var(--brand-gold);
}

#colophon .footer-navigation .menu > li > a,
#colophon .menu > li > a {
  font-family: var(--font-body);
  font-size: var(--step--1);
  letter-spacing: 0;
  color: var(--brand-muted);
  text-decoration: none;
}

#colophon .menu > li > a:hover {
  color: var(--brand-purple);
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

/* ---------------------------------------------------------------------------
 * Hero led pages
 *
 * Kadence's content spacing is right for a normal page and wrong for a full
 * bleed hero, which needs to meet the header with nothing between them.
 * The body class comes from sna_body_classes() in functions.php.
 * ------------------------------------------------------------------------ */

.sna-leads-with-hero .content-area {
  margin-top: 0;
}

.sna-leads-with-hero .entry-content-wrap {
  padding-top: 0;
}

/* Kadence also puts a 24px top margin on #inner-wrap, which survived the first
   two fixes and left a thin ivory strip between the header rule and the plum.
   Measured, not guessed: content-area, entry-content-wrap, site-main and
   inner-wrap padding were all already zero, and the remaining 24px was this. */
.sna-leads-with-hero #inner-wrap {
  margin-top: 0;
}

/* ---------------------------------------------------------------------------
 * Pages that CLOSE with a full bleed band
 *
 * The mirror image of the rule above, and the same 136px. Kadence's bottom
 * spacing left a strip of page background between the last band and the
 * footer, so a tint newsletter band and a plum footer read as two things with
 * an accidental gap rather than one join.
 *
 * Body class from sna_body_classes(). Applies to any page ending on a band,
 * not just the homepage.
 * ------------------------------------------------------------------------ */

.sna-closes-with-band .content-area {
  margin-bottom: 0;
}

.sna-closes-with-band .entry-content-wrap {
  padding-bottom: 0;
}

.sna-closes-with-band #inner-wrap {
  margin-bottom: 0;
}

/* Kadence also puts a 24px TOP margin on the footer itself, which survived the
   three rules above and left a thin ivory line between the tint band and the
   plum footer. Exactly the same trap as the #inner-wrap 24px at the top of the
   page: measured, not guessed, after the other four were already zero. */
.sna-closes-with-band .site-footer {
  margin-top: 0;
}

/* ---------------------------------------------------------------------------
 * The booking scheduler
 *
 * Two states. Before the button is pressed, the panel is the whole component
 * and the embed container has no height at all. After, Cal's calendar occupies
 * the space below it and the panel stays as the explanation above.
 *
 * The embed container is deliberately NOT given a placeholder height while
 * empty. An empty reserved box reads as something that failed to load, and it
 * would also be 700px of nothing between the copy and the footer for every
 * visitor who never presses the button.
 *
 * Once mounted it IS given a min-height, because Cal sizes its own iframe
 * asynchronously and without a floor the page jumps as the calendar settles,
 * which is exactly the CLS this project has been keeping at zero.
 * ------------------------------------------------------------------------ */

.sna-booking__panel {
  max-width: 44rem;
  margin-inline: auto;
  padding: clamp(1.75rem, 5vw, 2.75rem);
  border-radius: var(--radius, 8px);
  text-align: center;
}

.sna-booking__title {
  margin-top: 0;
}

.sna-booking__actions {
  justify-content: center;
  margin-block: 1.5rem 1rem;
}

/* The measure rule pins paragraphs hard left with a three-class selector that
   computes to (0,3,1), so a centring rule has to include the element to win.
   Same trap already logged for the newsletter lede in CLAUDE.md. */
.entry-content p.sna-booking__note,
.entry-content p.sna-booking__status {
  margin-inline: auto;
  text-align: center;
}

.sna-booking__note {
  max-width: 34rem;
}

/* Empty until the loader has something to say, so it must not reserve a line
   of blank space in the resting state. */
.sna-booking__status:empty {
  display: none;
}

.sna-booking__status {
  margin-top: 0.75rem;
  font-size: var(--step--1, 0.9rem);
  color: var(--ink-muted, inherit);
}

.sna-booking.is-loading .sna-booking__cta .wp-block-button__link {
  opacity: 0.7;
  pointer-events: none;
}

.sna-booking__embed {
  margin-top: 0;
}

.sna-booking.is-mounted .sna-booking__embed {
  margin-top: clamp(2rem, 5vw, 3rem);
  min-height: 34rem;
}

/* Cal renders its own scroll context. Without this the calendar can push the
   page wider than the viewport on a 360px screen, which is the width this
   project builds at first. */
.sna-booking__embed {
  max-width: 100%;
  overflow-x: auto;
}

.sna-booking__embed:focus {
  outline: none;
}

/* ---------------------------------------------------------------------------
 * Fluent Forms, the stacked base
 *
 * ADDED WHEN THE CONTACT FORM SHIPPED. Every Fluent Forms rule in this project
 * lived in dither.css scoped to .sna-newsletter__card, because for a long time
 * the inline newsletter capsule was the only form on the site. The moment a
 * second form existed, /contact/ and the signup on /resources/ rendered in the
 * plugin's stock blue-and-grey, which is exactly the generic template look the
 * brief bans.
 *
 * This is the STACKED base: label above field, full width, one per row. The
 * newsletter capsule keeps its own treatment, and because dither.css is
 * enqueued after this file its more specific selectors still win there.
 *
 * Colours are tokens, never literals, so a palette change reaches these too.
 * ------------------------------------------------------------------------ */

.entry-content .frm-fluent-form {
  max-width: 34rem;
  margin-inline: auto;
}

.entry-content .frm-fluent-form .ff-el-group {
  margin-bottom: var(--space-m);
}

.entry-content .frm-fluent-form .ff-el-input--label label {
  display: block;
  margin-bottom: var(--space-3xs);
  font-family: var(--font-sans, inherit);
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--text-primary);
}

/* Fluent Forms marks required fields with an asterisk in its own red. Ours,
   and the gold is decorative here rather than carrying meaning on its own:
   the label text and the validation message both say it too. */
.entry-content .frm-fluent-form .ff-el-is-required.asterisk-right label:after,
.entry-content .frm-fluent-form .ff-el-is-required.asterisk-left label:before {
  color: var(--gold-text);
}

.entry-content .frm-fluent-form input[type="text"],
.entry-content .frm-fluent-form input[type="email"],
.entry-content .frm-fluent-form input[type="tel"],
.entry-content .frm-fluent-form input[type="url"],
.entry-content .frm-fluent-form textarea,
.entry-content .frm-fluent-form select {
  width: 100%;
  padding: 0.8rem 1rem;
  border: var(--hairline) solid var(--rule);
  border-radius: var(--radius);
  background: var(--brand-ivory);
  font-family: inherit;
  font-size: var(--t-base);
  line-height: 1.5;
  color: var(--text-primary);
  /* Inherited box-shadow from the plugin reads as a grey inset lip. */
  box-shadow: none;
  transition: border-color 200ms ease, box-shadow 200ms ease;
}

.entry-content .frm-fluent-form textarea {
  min-height: 9rem;
  resize: vertical;
}

.entry-content .frm-fluent-form input::placeholder,
.entry-content .frm-fluent-form textarea::placeholder {
  color: var(--text-muted);
}

/* The focus ring is purple on light grounds, per the brief. Two declarations
   rather than one so the ring is visible even where a browser suppresses
   outline on a field with a custom border. */
.entry-content .frm-fluent-form input:focus,
.entry-content .frm-fluent-form textarea:focus,
.entry-content .frm-fluent-form select:focus {
  outline: 2px solid var(--brand-purple);
  outline-offset: 2px;
  border-color: var(--brand-purple);
}

/* The submit button matches every other call to action on the site: purple
   fill, ivory label, 9.42:1. See the 2026-08-01 decision in CLAUDE.md, which
   settled that there is ONE button treatment and it is not gold. */
.entry-content .frm-fluent-form .ff-btn-submit,
.entry-content .frm-fluent-form button[type="submit"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.85rem 1.75rem;
  border: 0;
  border-radius: var(--radius);
  background: var(--brand-purple);
  color: var(--brand-ivory);
  font-family: inherit;
  font-size: var(--t-base);
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  transition: background-color 200ms ease;
}

.entry-content .frm-fluent-form .ff-btn-submit:hover,
.entry-content .frm-fluent-form button[type="submit"]:hover {
  background: var(--brand-purple-700);
}

.entry-content .frm-fluent-form .ff-btn-submit:focus-visible,
.entry-content .frm-fluent-form button[type="submit"]:focus-visible {
  outline: 2px solid var(--brand-purple);
  outline-offset: 3px;
}

/* Validation messages. Not gold, and not the plugin's default red: this is the
   one place on the site where a colour has to carry an error meaning, so it
   needs to clear 4.5:1 on ivory as body text. */
.entry-content .frm-fluent-form .error,
.entry-content .frm-fluent-form .text-danger,
.entry-content .frm-fluent-form .ff-el-is-error .error {
  margin-top: var(--space-3xs);
  font-size: var(--t-sm);
  color: var(--error);
}

.entry-content .frm-fluent-form .ff-el-is-error input,
.entry-content .frm-fluent-form .ff-el-is-error textarea {
  border-color: var(--error);
}

/* The success message after a form that stays on the page. */
.entry-content .ff-message-success {
  padding: var(--space-m);
  border: var(--hairline) solid var(--rule);
  border-radius: var(--radius);
  background: var(--brand-purple-100);
  color: var(--text-primary);
}

/* Inside the lead magnet panel the form sits on the tint, so the fields need
   the ivory to read as inset rather than blending into their own container. */
.sna-magnet .frm-fluent-form {
  margin-top: var(--space-m);
}

/*
 * Two-column form rows outside the newsletter capsule.
 *
 * The newsletter form's own container is a 66/34 pill and sets align-items:
 * center in dither.css, which wins here on source order at equal specificity.
 * Everywhere else that same form renders as a plain row, and the email cell is
 * taller than the button cell because the email field carries a visually
 * hidden label. Measured on /resources/: the input sat 14px below the button,
 * which reads as a rendering fault rather than a design.
 *
 * Aligning to the end lines their bottom edges up, which is the edge the eye
 * actually reads on a field and a button sitting side by side.
 */
.entry-content .frm-fluent-form .ff-t-container {
  align-items: flex-end;
  gap: var(--space-2xs);
}

/*
 * Bottom spacing inside a two-column row.
 *
 * Two separate margins were fighting here and the first fix made it worse, so
 * both are named. Fluent Forms puts 20px under the submit button, and the
 * .ff-el-group rule further up this file puts 24px under every field group,
 * which is right for a stacked form and wrong inside a row where the field and
 * the button are supposed to share a baseline.
 *
 * Measured: 14px adrift originally, 4px after aligning to flex-end, 24px after
 * zeroing only the button. Both have to go, not either one.
 *
 * Scoped to the magnet rather than written as a general rule, because a
 * general one would out-specify the newsletter capsule's own treatment in
 * dither.css and quietly change the homepage.
 */
.sna-magnet .frm-fluent-form .ff-t-container .ff-el-group {
  margin-bottom: 0;
}

.sna-magnet .frm-fluent-form .ff-t-container button[type="submit"] {
  margin-bottom: 0;
}
