/* ============================================================================
   HOMESCHOOL PREP CO — COMPONENT CSS
   ----------------------------------------------------------------------------
   Every literal value is replaced by a token. Colour comes from the surface
   the component sits on — authors choose a surface, never a colour.

   This file is SHIPPABLE. It is copied verbatim into the theme at
   assets/css/components.css. Requires tokens.css to be loaded first.

   INVARIANTS (verified by check-contrast.py)
   - No colour literal, no raw alpha-channel colour, no raw px size appears
     below. Tokens only.
   - No WordPress preset variable is referenced below. Only tokens.css knows
     those. This comment avoids spelling either pattern out so the documented
     greps in STYLEGUIDE.md §13 return genuinely empty.

   State companion classes (.is-hover, .is-focus) exist so the style guide
   gallery can show every state side by side without re-declaring any CSS.
   They are inert in production.

   Version 2.0.0
   ========================================================================== */

/* ==========================================================================
   1. RESET & BASE
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }

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

body {
  margin: 0;
  font-family: var(--sans);
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  color: var(--ink);
  background: var(--mist);
  -webkit-font-smoothing: antialiased;
}

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

/* Sticky header clearance for in-page anchors */
:target,
[id] { scroll-margin-top: calc(var(--s6) + var(--s2)); }


/* ==========================================================================
   2. TYPOGRAPHY
   ========================================================================== */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--display);
  color: var(--ink);
  line-height: var(--lh-display);
  font-weight: var(--fw-normal);
  margin: 0;
}

h1 { font-size: var(--fs-hero); }
h2 { font-size: var(--fs-section); }
h3 { font-size: var(--fs-lg); }

/* NEW — absent from the prototype, required for post content */
h4 { font-size: var(--fs-md); }
h5 { font-size: var(--fs-base); font-weight: var(--fw-semibold); }
h6 {
  font-size: var(--fs-sm);
  font-family: var(--sans);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
}

a { color: var(--pine); }

/* In-body prose links. The prototype styled links by color alone, which risks
   SC 1.4.1 inside running text. Underline is mandatory here.

   SCOPED TO .prose ON PURPOSE — do not add .entry-content back.
   WordPress puts `entry-content` on EVERY core/post-content block, including
   full-width layout pages like the front page. Styling that class as prose
   therefore leaked a 65ch max-width and the link colour onto composed
   layouts, squeezing the homepage to ~655px and rendering link-coloured text
   on same-coloured button fills. Templates that want prose opt in with "prose"
   (page.html, single.html); layout pages simply don't. */
.prose a {
  color: var(--pine);
  text-decoration: underline;
  text-decoration-thickness: var(--border-hairline-w);
  text-underline-offset: .15em;
}
.prose a:hover,
.prose a.is-hover {
  color: var(--pine-hover);
  text-decoration-thickness: var(--border-control-w);
}

.prose { max-width: var(--measure-prose); }
.prose > * + * { margin-top: var(--s3); }

.eyebrow {
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--pine);
  margin: 0 0 .9rem;
}

.cat {
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--slate-deep);
  margin: 0 0 var(--s1);
}

/* NEW — captions */
figure { margin: 0; }
figcaption,
.wp-element-caption {
  font-size: var(--fs-sm);
  color: var(--ink-soft);
  margin-top: var(--s1);
  line-height: var(--lh-body);
}

.visually-hidden,
.screen-reader-text {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}


/* ==========================================================================
   3. SURFACE RECIPES
   A component sits on exactly one surface. The surface supplies every color
   it needs — authors choose a surface, never a color.

   This is also where the FOCUS RING DEFECT is fixed: the ring is drawn
   outside the element, so it is measured against the surface behind it.
   Pine clears 3:1 on all light surfaces but fails on both dark cards
   (1.00:1 on forest, 1.56:1 on moss). Dark surfaces flip the ring to white.
   ========================================================================== */
.surface-mist      { background: var(--mist); }
.surface-sage-pale { background: var(--sage-pale); }
.surface-white      { background: var(--white); }
.surface-celadon      { background: var(--celadon); }

.surface-forest,
.surface-moss {
  color: var(--white);
  --focus-ring: var(--white);     /* the fix */
}
.surface-forest { background: var(--forest); }
.surface-moss { background: var(--moss); }

.surface-forest h1, .surface-forest h2, .surface-forest h3,
.surface-moss h1, .surface-moss h2, .surface-moss h3 { color: var(--white); }

.surface-forest .muted { color: var(--on-forest-muted); }
.surface-moss .muted { color: var(--on-moss-muted); }

/* Emphasis on dark. Moss only — --olive is 3.22:1 on forest. */
.surface-moss .em { color: var(--olive); font-style: italic; }
.surface-forest .em { color: var(--on-forest-muted); font-style: italic; }


/* ==========================================================================
   4. FOCUS — global, uses the surface-scoped ring
   ========================================================================== */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible,
.is-focus {
  outline: var(--focus-width) solid var(--focus-ring);
  outline-offset: var(--focus-offset);
  border-radius: var(--focus-radius);
}

.skip {
  position: absolute;
  left: .75rem; top: -100px;
  z-index: 1000;
  background: var(--ink);
  color: var(--white);
  padding: .7rem 1.1rem;
  border-radius: var(--radius-sm);
  text-decoration: none;
  font-weight: var(--fw-semibold);
  transition: top var(--motion-fast) var(--ease);
}
.skip:focus { top: .75rem; }
@media (prefers-reduced-motion: reduce) { .skip { transition: none; } }


/* ==========================================================================
   5. LAYOUT
   ========================================================================== */
.wrap {
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
}


/* ==========================================================================
   6. BUTTONS
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s1);
  font-family: var(--sans);
  font-size: var(--fs-base);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
  padding: .85rem 1.6rem;
  min-height: var(--target-min);
  border: var(--border-control-w) solid transparent;
  border-radius: var(--radius-sm);
  text-decoration: none;
  cursor: pointer;
  transition: transform var(--motion-fast) var(--ease),
              background-color var(--motion-fast) var(--ease),
              box-shadow var(--motion-fast) var(--ease);
}

.btn-ink   { background: var(--ink);   color: var(--white); }  /* 18.02:1 */
.btn-pine  { background: var(--pine);  color: var(--white); }  /* 8.72:1  */
.btn-olive { background: var(--olive); color: var(--ink);   }  /* 6.63:1 — ink text ONLY */
.btn-ghost { background: transparent;  color: var(--pine); border-color: var(--pine); }

.btn:hover, .btn.is-hover { transform: translateY(-2px); box-shadow: var(--shadow); }
/* --ink is already at the bottom of the ramp, so its hover LIGHTENS. */
.btn-ink:hover,   .btn-ink.is-hover   { background: var(--ink-hover); }
.btn-pine:hover,  .btn-pine.is-hover  { background: var(--pine-hover); }
.btn-ghost:hover, .btn-ghost.is-hover { background: var(--pine); color: var(--white); }

.btn:active { transform: translateY(0); }

.btn[disabled], .btn.is-disabled {
  opacity: .5;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

@media (prefers-reduced-motion: reduce) {
  .btn { transition: background-color var(--motion-fast) var(--ease); }
  .btn:hover, .btn.is-hover { transform: none; }
}

/* Buttons on dark surfaces get a white ring (inherited from .surface-*) */


/* ==========================================================================
   7. LINKS
   ========================================================================== */
.text-link {
  color: var(--pine);
  font-weight: var(--fw-semibold);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.text-link:hover, .text-link.is-hover { color: var(--pine-hover); }

.read-link {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  color: var(--pine);
  font-weight: var(--fw-bold);
  font-size: .92rem;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  text-decoration: none;
}
.read-link::after { content: "→"; transition: transform var(--motion-fast) var(--ease); }
.read-link:hover, .read-link.is-hover { text-decoration: underline; text-underline-offset: 3px; }
.read-link:hover::after, .read-link.is-hover::after { transform: translateX(3px); }
@media (prefers-reduced-motion: reduce) {
  .read-link::after { transition: none; }
  .read-link:hover::after, .read-link.is-hover::after { transform: none; }
}


/* ==========================================================================
   8. HEADER & NAVIGATION
   ========================================================================== */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--mist);
  border-bottom: var(--border-hairline-w) solid var(--border);
}
.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s2);
  padding-block: .85rem;
}
/* Brand lockup — circular badge mark beside the wordmark.
   The badge already carries "Homeschool Prep Co" inside the circle, but at
   header scale that lettering is texture, not type. The wordmark beside it is
   what actually communicates, and it is the only one of the two exposed to
   assistive tech: the badge is decorative (site-logo with isLink false). */
.brand {
  display: flex;
  align-items: center;
  gap: .6rem;
  color: var(--ink);
  font-family: var(--display);
  font-size: var(--fs-lg);
}
.brand .wp-block-site-logo { flex: 0 0 auto; line-height: 0; margin: 0; }
.brand img { display: block; }
.brand .wp-block-site-title { margin: 0; }
.brand a { color: var(--ink); text-decoration: none; }

/* Footer mark — large enough for the inner script to actually read, flanked by
   a mirrored pair of sprigs.

   The sprig is the only one of the three with enough tonal separation to read
   on celadon at all (1.67:1 vs 1.01 and 1.28 for branch and bloom), and even
   then it is a whisper. That is the intent here: a tonal flourish either side
   of the mark, not a graphic element. It carries nothing, so the low ratio is
   not a defect — but do not repurpose this pairing anywhere it must be seen. */
.footer-brand {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--s3);
  margin-bottom: var(--s5);
}
.footer-brand img { display: block; }
.footer-brand::before,
.footer-brand::after {
  content: "";
  flex: 0 0 auto;
  height: var(--ornament-footer);
  aspect-ratio: var(--ratio-sprig);
  background-image: var(--ornament-sprig);
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}
.footer-brand::after { scale: -1 1; }

/* NO dark-surface treatment, deliberately. Only the area OUTSIDE the badge's
   circle is transparent — the disc itself is opaque near-white with black art
   on it. So the mark already reads as a white badge on any surface, light or
   dark, and needs no invert. An invert filter here would be actively wrong:
   it would flip the disc to black and take the line art with it.
   If the source asset is ever reissued with a transparent interior, a dark
   surface will need `filter: brightness(0) invert(1)` added back. */

.nav-toggle { display: none; }

.primary-nav ul {
  display: flex;
  align-items: center;
  gap: 1.6rem;
  list-style: none;
  margin: 0; padding: 0;
}
.primary-nav a {
  color: var(--ink);
  text-decoration: none;
  font-weight: var(--fw-medium);
  font-size: .97rem;
  padding: .4rem 0;
  border-bottom: var(--border-control-w) solid transparent;
}
.primary-nav a:hover, .primary-nav a.is-hover { border-bottom-color: var(--pine); }

/* Current page uses color + weight + underline together — never color alone */
.primary-nav a[aria-current="page"] {
  color: var(--pine);
  border-bottom-color: var(--pine);
  font-weight: var(--fw-bold);
}
.header-cta { margin-left: .4rem; }


/* ==========================================================================
   9. HERO
   ========================================================================== */
.hero { background: var(--mist); overflow: hidden; }
.hero-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s4);
  align-items: center;
  padding-block: var(--s5) var(--s6);
}
.hero h1 { margin-bottom: 1.1rem; }
.hero-lede {
  font-size: var(--fs-md);
  max-width: var(--measure-lede);
  color: var(--ink);
  margin-bottom: 1.8rem;
}
.hero-actions { display: flex; flex-wrap: wrap; gap: .9rem; align-items: center; }


/* ==========================================================================
   10. MEDIA PLACEHOLDERS
   Replace each .media with a real <img alt>. Ratios are load-bearing.
   ========================================================================== */
.media {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--media-gradient);
  aspect-ratio: 5 / 4;
  display: grid;
  place-items: center;
  color: var(--white);
}
.media .media-note {
  font-size: .8rem;
  letter-spacing: .04em;
  padding: .4rem .8rem;
  background: var(--media-note-bg);
  border-radius: 6px;
}

/* Real imagery fills the placeholder's box. The gradient stays underneath as
   the loading backdrop, so a slow image never flashes an empty surface — and
   the ratio is held by the container, so nothing reflows as it arrives. */
.media img,
.video img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}
.hero-media  { aspect-ratio: 5 / 4; }
.final-media { aspect-ratio: 1 / 1; }


/* ==========================================================================
   11. BOTANICAL ORNAMENTS — always aria-hidden / decorative

   Three watercolour botanicals replace the abstract blob, square and
   line-drawn leaf. They share the brand's sage range, so they are DECORATIVE
   ONLY: 1.0–1.9:1 against every light surface. Never behind text, never the
   sole carrier of meaning. --ornament-sprig is 1.00:1 on --celadon.

   All three draw as background-image on an empty box rather than an <img>,
   which keeps them out of the accessibility tree by construction — there is
   no alt attribute to get wrong.
   ========================================================================== */
.ornament-sprig,
.ornament-branch,
.ornament-bloom {
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}
.ornament-sprig  { aspect-ratio: var(--ratio-sprig);  background-image: var(--ornament-sprig); }
.ornament-branch { aspect-ratio: var(--ratio-branch); background-image: var(--ornament-branch); }
.ornament-bloom  { aspect-ratio: var(--ratio-bloom);  background-image: var(--ornament-bloom); }

/* --- Corner placements -------------------------------------------------
   Every ornament sits at z-index 1, ON TOP of the media it overlaps. The
   abstract shapes it replaces used z-index -1, which put them behind the
   section's own opaque background — they never actually rendered. Overlapping
   the media edge is also what makes a watercolour read as deliberate collage
   rather than something stranded beside the photo.
   ---------------------------------------------------------------------- */
.hero-media-wrap { position: relative; }
.hero-media-wrap .ornament-branch {
  position: absolute;
  left: -7%; bottom: -9%;
  width: 26%;
  z-index: 1;
}
/* .workshop-inner clips at its rounded corner, so this one is cut cleanly by
   the panel edge — the same behaviour the corner blob relied on. */
.workshop-inner .ornament-branch {
  position: absolute;
  right: 2%; bottom: -9%;
  width: 14%;
  scale: -1 1;
  z-index: 1;
}
.final-media-wrap { position: relative; }
.final-media-wrap .ornament-sprig {
  position: absolute;
  top: -10%; right: -7%;
  width: 24%;
  z-index: 1;
}
.final-media-wrap .ornament-bloom {
  position: absolute;
  bottom: -6%; left: -5%;
  width: 15%;
  z-index: 1;
}

/* --- Heading enhancers — core/heading block styles ---------------------
   The ornament is a ::before on the heading itself, sized in em so it tracks
   the heading's fluid clamp() with no extra breakpoint.

   Below 720px it stacks ABOVE the text instead of beside it. That is not a
   preference — at 320px a hero heading is 33.6px, and an inline ornament plus
   gap leaves roughly six characters per line. The switch happens on the
   existing 720px breakpoint; no new one is introduced.

   --ornament-align carries the alignment instead of align-items so the
   direction switch below can set align-items freely without a specificity
   fight with the .has-text-align-* rules.
   ---------------------------------------------------------------------- */
.is-style-sprig,
.is-style-branch,
.is-style-bloom {
  display: flex;
  flex-direction: column;
  align-items: var(--ornament-align, flex-start);
  gap: var(--s2);
}
.is-style-sprig::before,
.is-style-branch::before,
.is-style-bloom::before {
  content: "";
  flex: 0 0 auto;
  height: var(--ornament-inline);
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}
.is-style-sprig::before  { aspect-ratio: var(--ratio-sprig);  background-image: var(--ornament-sprig); }
.is-style-branch::before { aspect-ratio: var(--ratio-branch); background-image: var(--ornament-branch); }
.is-style-bloom::before  { aspect-ratio: var(--ratio-bloom);  background-image: var(--ornament-bloom); }

.has-text-align-center.is-style-sprig,
.has-text-align-center.is-style-branch,
.has-text-align-center.is-style-bloom { --ornament-align: center; }

.has-text-align-right.is-style-sprig,
.has-text-align-right.is-style-branch,
.has-text-align-right.is-style-bloom { --ornament-align: flex-end; }

/* --- Separator ornament — core/separator block style ------------------- */
.wp-block-separator.is-style-bloom {
  border: 0;
  height: var(--ornament-rule);
  width: auto;
  max-width: none;
  aspect-ratio: var(--ratio-bloom);
  margin-inline: auto;
  background-image: var(--ornament-bloom);
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}


/* ==========================================================================
   12. CARDS
   ========================================================================== */
.band { background: var(--sage-pale); padding-block: var(--s6); }

.cards-3 { display: grid; grid-template-columns: 1fr; gap: var(--s3); }

.card {
  border-radius: var(--radius);
  padding: 1.9rem;
  box-shadow: var(--shadow);
}
.card-white  { background: var(--white); }
.card-white .eyebrow { color: var(--ink); }
.card-white p { color: var(--ink); margin-bottom: 1.4rem; }

.card-forest {
  background: var(--forest);
  color: var(--white);
  --focus-ring: var(--white);
}
.card-forest h3, .card-forest p { color: var(--white); }
.card-forest h3 { font-size: var(--fs-xl); margin-bottom: .7rem; }
.card-forest .tagline {
  font-size: var(--fs-sm);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  margin-top: 1.3rem;
  color: var(--on-forest-muted);
}

.card-moss {
  background: var(--moss);
  color: var(--white);
  --focus-ring: var(--white);
}
.card-moss blockquote {
  margin: 0;
  font-family: var(--display);
  font-size: var(--fs-xl);
  line-height: var(--lh-quote);
}
.card-moss .em { color: var(--olive); font-style: italic; }
.card-moss cite {
  display: block;
  margin-top: 1.1rem;
  font-style: normal;
  font-size: .95rem;
  color: var(--on-moss-muted);
  font-family: var(--sans);
}


/* ==========================================================================
   13. SERVICES
   ========================================================================== */
.services { background: var(--white); padding-block: var(--s7); }

.section-head {
  text-align: center;
  max-width: var(--measure-head);
  margin-inline: auto;
  margin-bottom: var(--s5);
}
.section-head h2 { margin-bottom: .8rem; }
.section-head p  { color: var(--ink-soft); }

.services-grid { display: grid; grid-template-columns: 1fr; gap: var(--s4) var(--s5); }

.svc { display: grid; grid-template-columns: 1fr; gap: var(--s2); }
.svc .media { aspect-ratio: 4 / 3; }
.svc-body h3 { margin-bottom: .6rem; }
.svc-body p  { color: var(--ink); margin-bottom: .9rem; font-size: .97rem; }


/* ==========================================================================
   14. WORKSHOP BAND
   ========================================================================== */
.workshop { background: var(--mist); padding-block: var(--s6); }
.workshop-inner {
  background: var(--sage-pale);
  border-radius: var(--radius);
  padding: clamp(1.6rem, 4vw, var(--s5));
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s4);
  align-items: center;
  position: relative;
  overflow: hidden;
}
.workshop h2 { font-size: var(--fs-band); margin-bottom: var(--s2); max-width: var(--measure-title); }
.workshop p  { color: var(--ink); margin-bottom: 1.6rem; max-width: var(--measure-copy); }
/* Placement lives with the ornament rules in §11 — .workshop-inner clips at
   its rounded corner, so the branch is tucked inside rather than bled off. */

.video {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--video-gradient);
  aspect-ratio: 16 / 10;
}
.play-btn {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 74px; height: 74px;
  border-radius: var(--radius-pill);
  border: none;
  background: var(--play-bg);
  cursor: pointer;
  display: grid;
  place-items: center;
  box-shadow: var(--shadow-play);
}
.play-btn:hover, .play-btn.is-hover { background: var(--white); }
.play-btn svg { margin-left: 4px; color: var(--ink); }


/* ==========================================================================
   15. TRUSTED-BY LOGO ROW
   ========================================================================== */
.trusted { background: var(--white); padding-block: var(--s6) var(--s5); text-align: center; }
.trusted .eyebrow { color: var(--ink); text-align: center; }
.logos {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: clamp(1.5rem, 5vw, 3.5rem);
  margin-top: 1.6rem;
}
.logo {
  font-family: var(--display);
  color: var(--ink-soft);
  font-size: 1.15rem;
  letter-spacing: .02em;
}
.logo small {
  display: block;
  font-family: var(--sans);
  font-size: .6rem;
  letter-spacing: var(--track-micro);
  text-transform: uppercase;
}


/* ==========================================================================
   16. FINAL CTA
   ========================================================================== */
/* overflow:hidden clips the ornaments that bleed past the media corner. Without
   it the sprig's right:-7% pushes the document 18px wider than the viewport at
   720px and below — the same reason .hero carries it. */
.final { background: var(--white); overflow: hidden; padding-block: var(--s5) var(--s7); }
.final-grid { display: grid; grid-template-columns: 1fr; gap: var(--s4); align-items: center; }
.final h2 { font-size: var(--fs-display); margin-bottom: var(--s2); }
.final p  { color: var(--ink); max-width: var(--measure-narrow); margin-bottom: 1.8rem; }


/* ==========================================================================
   17. FOOTER
   ========================================================================== */
.site-footer {
  background: var(--celadon);
  color: var(--ink);
  padding-block: var(--s6) var(--s4);
}
.footer-top {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s4);
  align-items: center;
  padding-bottom: var(--s5);
  border-bottom: var(--border-hairline-w) solid var(--border-dark);
}
.footer-tagline {
  font-family: var(--display);
  font-size: var(--fs-tagline);
  color: var(--ink);
  max-width: 24ch;
}
.footer-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s4) var(--s3);
  padding-top: var(--s5);
}
/* NOTE: renamed from `.footer-col h4` — this is a LABEL, not a scale-h4.
   The old selector would have leaked label styling into post subheadings. */
.footer-col-title {
  font-family: var(--sans);
  font-size: var(--fs-xs);
  letter-spacing: var(--track-heading);
  text-transform: uppercase;
  color: var(--ink);
  margin: 0 0 .9rem;
  font-weight: var(--fw-bold);
}
/* Grid and flex items default to min-width:auto, so an unbreakable string —
   the contact email — can force its track wider than its 1fr share and push
   the page into horizontal scroll. At 320px that cost 3px and broke A11Y-12.
   min-width:0 lets the track shrink; break-word lets the email wrap. */
.footer-col { min-width: 0; }
.footer-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem; }
.footer-col a {
  color: var(--ink-soft);           /* 5.55:1 on celadon */
  text-decoration: none;
  font-size: .95rem;
}
/* Hover clears AA on celadon (5.31:1). Underline does not substitute for
   contrast under SC 1.4.3, so the hover colour has to pass on its own. */
.footer-col a:hover, .footer-col a.is-hover {
  color: var(--pine);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.contact-item {
  display: flex;
  align-items: center;
  gap: .55rem;
  min-width: 0;
  color: var(--ink-soft);
  font-size: .95rem;
  margin-bottom: .55rem;
}
/* `anywhere`, not `break-word`: only `anywhere` reduces the element's
   min-content width, which is what actually lets the grid track shrink. */
.contact-item a { color: var(--ink-soft); min-width: 0; overflow-wrap: anywhere; }

.socials { display: flex; gap: .65rem; margin-top: var(--s2); }
.icon-link {
  display: grid;
  place-items: center;
  width: var(--target-icon);
  height: var(--target-icon);
  border-radius: var(--radius-pill);
  border: var(--border-control-w) solid var(--border-field);  /* 4.19:1 on celadon */
  color: var(--ink);
  text-decoration: none;
}
.icon-link:hover, .icon-link.is-hover { border-color: var(--pine); color: var(--pine); }

.footer-bottom {
  margin-top: var(--s4);
  padding-top: var(--s3);
  border-top: var(--border-hairline-w) solid var(--border-dark);
  font-size: var(--fs-sm);
  color: var(--ink-soft);
  text-align: center;
}


/* ==========================================================================
   18. FORMS
   Control borders use --border-field (>=3:1, SC 1.4.11). --border-dark is
   1.76:1 on white and is NOT valid for a control boundary.

   The palette carries no red, so error is --ink and success is --pine. Both
   are legible on every light surface, and neither is distinguished by colour
   alone: error pairs with a bold "!" glyph, success with a check. That is
   already what SC 1.4.1 requires here — the palette simply makes it the only
   available route rather than a belt-and-braces extra.
   ========================================================================== */
.newsletter {
  background: var(--white);
  border-radius: var(--radius);
  padding: 1.4rem;
  box-shadow: var(--shadow);
}
.newsletter h3 { font-size: var(--fs-md); margin-bottom: .3rem; }
.newsletter p  { font-size: var(--fs-sm); color: var(--ink-soft); margin-bottom: .9rem; }

.field-label,
.newsletter label {
  display: block;
  font-size: .8rem;
  font-weight: var(--fw-semibold);
  color: var(--ink);
  margin-bottom: .35rem;
}
.field-required { color: var(--pine); }

.nl-row { display: flex; gap: var(--s1); flex-wrap: wrap; align-items: flex-end; }

.field,
input[type="email"],
input[type="text"],
input[type="search"],
input[type="url"],
input[type="tel"],
textarea,
select {
  width: 100%;
  min-width: 0;
  padding: .7rem .85rem;
  border: var(--border-control-w) solid var(--border-field);
  border-radius: var(--radius-sm);
  font-size: var(--fs-base);
  font-family: var(--sans);
  color: var(--ink);
  background: var(--white);
}
.field:focus,
input:focus, textarea:focus, select:focus { border-color: var(--pine); }

.field-help { font-size: var(--fs-sm); color: var(--ink-soft); margin-top: .3rem; }

/* Error — never color alone; pairs with an icon glyph and a text message */
.field.is-error,
input.is-error, textarea.is-error {
  border-color: var(--ink);
  border-width: var(--border-control-w);
}
.field-error {
  display: flex;
  align-items: center;
  gap: .35rem;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--ink);          /* 18.02:1 on white */
  margin-top: .35rem;
}
.field-error::before { content: "!"; font-weight: var(--fw-bold); }

.field-success {
  display: flex;
  align-items: center;
  gap: .35rem;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--pine);         /* 8.72:1 on white */
  margin-top: .35rem;
}
.field-success::before { content: "\2713"; }

.field[disabled], input[disabled], textarea[disabled], select[disabled] {
  background: var(--sage-pale);
  color: var(--gray);
  cursor: not-allowed;
  opacity: .7;
}


/* ==========================================================================
   19. WORDPRESS SURFACES — derived, not in the prototype
   ========================================================================== */

/* Post card — inherits the service item's proportions */
.post-card { display: grid; gap: var(--s2); }
.post-card .media { aspect-ratio: 4 / 3; }
.post-card h3 { font-size: var(--fs-lg); margin-bottom: .4rem; }
.post-card .post-meta { font-size: var(--fs-sm); color: var(--ink-soft); }
.post-card p { color: var(--ink); font-size: .97rem; margin: .5rem 0 .9rem; }

.posts-grid { display: grid; grid-template-columns: 1fr; gap: var(--s5) var(--s4); }

/* Single post */
.post-header { max-width: var(--measure-prose); margin-inline: auto; margin-bottom: var(--s4); }
.post-header h1 { margin-bottom: var(--s2); }
.post-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  font-size: var(--fs-sm);
  color: var(--ink-soft);
}
.post-meta a { color: var(--ink-soft); }

/* Pagination */
.pagination { display: flex; flex-wrap: wrap; gap: var(--s1); justify-content: center; margin-top: var(--s5); }
.pagination a,
.pagination span {
  display: grid;
  place-items: center;
  min-width: var(--target-icon);
  min-height: var(--target-icon);
  padding: 0 .75rem;
  border: var(--border-control-w) solid var(--border-field);
  border-radius: var(--radius-sm);
  color: var(--pine);
  text-decoration: none;
  font-weight: var(--fw-semibold);
}
.pagination a:hover { background: var(--pine); color: var(--white); border-color: var(--pine); }
.pagination [aria-current="page"] {
  background: var(--ink);
  color: var(--white);
  border-color: var(--ink);
  font-weight: var(--fw-bold);
}

/* Breadcrumbs */
.breadcrumbs { font-size: var(--fs-sm); color: var(--ink-soft); display: flex; flex-wrap: wrap; gap: .4rem; }
.breadcrumbs a { color: var(--ink-soft); text-decoration: underline; text-underline-offset: 2px; }
.breadcrumbs a:hover { color: var(--pine); }
.breadcrumbs [aria-current="page"] { color: var(--ink); font-weight: var(--fw-semibold); }

/* Comments */
.comment-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s4); }
.comment-list ol { list-style: none; margin: var(--s4) 0 0 var(--s4); padding: 0; display: grid; gap: var(--s4); }
.comment {
  background: var(--white);
  border: var(--border-hairline-w) solid var(--border);
  border-radius: var(--radius);
  padding: var(--s3);
}
.comment-author { font-weight: var(--fw-semibold); color: var(--ink); }
.comment-date   { font-size: var(--fs-sm); color: var(--ink-soft); }

/* Sidebar widgets */
.widget { margin-bottom: var(--s5); }
.widget-title {
  font-family: var(--sans);
  font-size: var(--fs-xs);
  letter-spacing: var(--track-heading);
  text-transform: uppercase;
  color: var(--ink);
  font-weight: var(--fw-bold);
  margin-bottom: .9rem;
}
.widget ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem; }
.widget a { color: var(--ink-soft); text-decoration: none; }
.widget a:hover { color: var(--pine); text-decoration: underline; }

/* Search + empty states */
.search-form { display: flex; gap: var(--s1); align-items: flex-end; }
.no-results {
  text-align: center;
  padding-block: var(--s6);
  max-width: var(--measure-head);
  margin-inline: auto;
}
.error-404 { text-align: center; padding-block: var(--s7); }
.error-404 .code {
  font-family: var(--display);
  font-size: var(--fs-hero);
  color: var(--pine);
  margin-bottom: var(--s2);
}


/* ==========================================================================
   20. WORDPRESS CORE BLOCKS
   ========================================================================== */
.wp-block-quote {
  border-left: var(--border-control-w) solid var(--pine);
  padding-left: var(--s3);
  margin: 0;
  font-family: var(--display);
  font-size: var(--fs-md);
  line-height: var(--lh-quote);
  color: var(--ink);
}
.wp-block-quote cite {
  display: block;
  margin-top: var(--s1);
  font-family: var(--sans);
  font-size: var(--fs-sm);
  font-style: normal;
  color: var(--ink-soft);
}

.wp-block-pullquote {
  background: var(--sage-pale);
  border-radius: var(--radius);
  padding: var(--s4);
  text-align: center;
}
.wp-block-pullquote p {
  font-family: var(--display);
  font-size: var(--fs-xl);
  line-height: var(--lh-quote);
  color: var(--ink);
}

.wp-block-separator {
  border: 0;
  border-top: var(--border-hairline-w) solid var(--border-dark);
  margin-block: var(--s5);
}

.wp-block-table table { width: 100%; border-collapse: collapse; font-size: .97rem; }
.wp-block-table th,
.wp-block-table td {
  border: var(--border-hairline-w) solid var(--border-dark);
  padding: .7rem .85rem;
  text-align: left;
}
.wp-block-table th {
  background: var(--sage-pale);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: var(--fw-bold);
}
.wp-block-table.is-style-stripes tbody tr:nth-child(odd) { background: var(--mist); }

.wp-block-code, pre {
  background: var(--moss);
  color: var(--white);
  border-radius: var(--radius-sm);
  padding: var(--s3);
  overflow-x: auto;
  font-size: .9rem;
}
code { font-size: .92em; }
:not(pre) > code {
  background: var(--sage-pale);
  padding: .1em .35em;
  border-radius: 4px;
  color: var(--ink);
}

.wp-block-image img { border-radius: var(--radius); }


/* ==========================================================================
   21. REVEAL ON SCROLL
   CONTRACT: content is hidden ONLY when JS is present AND motion is allowed.
   No-JS users and reduced-motion users always see everything.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  .js .reveal {
    opacity: 0;
    transform: translateY(var(--reveal-shift));
    transition: opacity var(--motion-reveal) var(--ease),
                transform var(--motion-reveal) var(--ease);
  }
  .js .reveal.is-visible { opacity: 1; transform: none; }
  .js .reveal[data-delay="1"] { transition-delay: calc(var(--stagger) * 1); }
  .js .reveal[data-delay="2"] { transition-delay: calc(var(--stagger) * 2); }
  .js .reveal[data-delay="3"] { transition-delay: calc(var(--stagger) * 3); }
}


/* ==========================================================================
   22. RESPONSIVE — exactly three breakpoints. Do not add more.
   720 = grid columns · 860 = nav collapse · 920 = two-column layouts
   ========================================================================== */
@media (min-width: 720px) {
  .cards-3       { grid-template-columns: repeat(3, 1fr); }
  .services-grid { grid-template-columns: 1fr 1fr; }
  .posts-grid    { grid-template-columns: repeat(2, 1fr); }
  .svc           { grid-template-columns: 120px 1fr; align-items: start; }
  .svc .media    { aspect-ratio: 1 / 1; }
  .footer-cols   { grid-template-columns: repeat(4, 1fr); }

  /* Heading ornaments move from above the text to beside it. */
  .is-style-sprig,
  .is-style-branch,
  .is-style-bloom {
    flex-direction: row;
    align-items: center;
    justify-content: var(--ornament-align, flex-start);
  }
  /* Right-aligned headings put the ornament after the text, not before. */
  .has-text-align-right.is-style-sprig,
  .has-text-align-right.is-style-branch,
  .has-text-align-right.is-style-bloom { flex-direction: row-reverse; }
}

@media (min-width: 920px) {
  .hero-grid      { grid-template-columns: 1.05fr 1fr; gap: var(--s6); padding-block: var(--s6) var(--s7); }
  .workshop-inner { grid-template-columns: 1fr 1fr; }
  .final-grid     { grid-template-columns: 1fr 1fr; }
  .footer-top     { grid-template-columns: 1.4fr auto 1fr; }
  .posts-grid     { grid-template-columns: repeat(3, 1fr); }
}

/* Mobile navigation
   NOTE: in the block theme this is replaced by core/navigation's overlayMenu,
   which supplies Escape handling and a focus trap that this markup lacks. */
@media (max-width: 860px) {
  .nav-toggle {
    display: inline-flex;
    align-items: center;
    gap: var(--s1);
    background: none;
    border: var(--border-control-w) solid var(--border-field);
    color: var(--ink);
    font-weight: var(--fw-semibold);
    padding: .5rem .8rem;
    border-radius: var(--radius-sm);
    cursor: pointer;
    min-height: var(--target-icon);
  }
  .primary-nav {
    position: absolute;
    top: 100%; left: 0; right: 0;
    background: var(--mist);
    border-bottom: var(--border-hairline-w) solid var(--border);
    box-shadow: var(--shadow);
    padding: var(--s2) var(--gutter) 1.4rem;
    display: none;
  }
  .primary-nav.open { display: block; }
  .primary-nav ul { flex-direction: column; align-items: flex-start; gap: .2rem; }
  .primary-nav a  { display: block; width: 100%; padding: .7rem 0; font-size: 1.05rem; }
  .header-cta     { display: none; }
  .primary-nav .mobile-cta { display: inline-flex; margin-top: .8rem; }
  .header-inner   { position: relative; }
}
@media (min-width: 861px) { .primary-nav .mobile-cta { display: none; } }
