/* ===========================================================================
   Dr. Roz's Healing Place — accessibility & readability layer
   WCAG 2.2 Level AA. Loop: Design for Social Good, 2026.

   This file is built on the design system that was MEASURED from the live
   site, not one invented for it. See DESIGN-SYSTEM.md in this theme for the
   full extraction. Summary:

     Typefaces   Inter (body), Montserrat (navigation, headings)
     Base size   16px
     Type scale  12 · 14 · 16 · 18 · 20 · 24 · 26 · 30 · 42 · 45
     Weights     400 body · 700 bold · 600 occasional
     Line height 1.8–1.9 body (already excellent — preserved, not changed)
     Palette     #d3b4e8 lavender · #7100e2 brand · #550096 dark · #340070 darkest

   COLOUR RULE: every purple used below is a value already present in the
   client's own Customizer settings. No new brand colours were introduced.
   Non-brand tokens are limited to one neutral (meta text), one semantic
   danger colour (crisis numbers), and darkened versions of the WordPress
   block-palette colours the client's own authors chose in the editor.

   Each ratio below was computed against the colour it actually renders on.
   Do not change a value without re-measuring.
   =========================================================================== */

:root {
  /* ---- Client brand palette (unchanged, straight from the Customizer) ---- */
  --drhp-lavender: #d3b4e8;  /* color_menu_background, color_footer_background */
  --drhp-brand:    #7100e2;  /* colorscheme_hex                                */
  --drhp-dark:     #550096;  /* color_footer_text                              */
  --drhp-darkest:  #340070;  /* header_button_textcolor_hover                  */

  /* ---- Foreground assignments, all from the four brand values above ----
     on lavender #d3b4e8 : dark 6.28:1 · darkest 8.31:1
     on white    #ffffff : dark 11.50:1 · darkest 15.22:1
     on grey     #f0f0f0 : dark 10.09:1 · darkest 13.35:1
     on black    #000000 : lavender 11.46:1                                  */
  --drhp-link:         var(--drhp-dark);
  --drhp-link-hover:   var(--drhp-darkest);
  --drhp-on-dark-bg:   var(--drhp-lavender);

  /* ---- Non-brand tokens, each justified ---- */
  --drhp-meta:   #595959;  /* 7.00:1 on white. Closest passing muted grey to
                              the original #999 (2.85:1) — keeps the muted
                              role rather than replacing it with black.      */
  --drhp-danger: #b00000;  /* 7.38:1 on white. Semantic, not brand. Used only
                              for crisis and emergency phone numbers, which
                              were pure #f00 at 4.00:1.                      */
  --drhp-content-green: #00784b;  /* 5.54:1 — author-chosen block green, darkened */
  --drhp-content-pink:  #b0154f;  /* 6.85:1 — author-chosen block pink, darkened  */

  /* ---- Focus indicator (WCAG 2.4.11 / 1.4.11 — 3:1 against adjacent) ---- */
  --drhp-focus-ring:      var(--drhp-brand);    /* 7.50:1 on white   */
  --drhp-focus-ring-dark: var(--drhp-darkest);  /* 8.31:1 on lavender */
  --drhp-focus-width: 3px;
  --drhp-focus-offset: 2px;

  /* ---- Readability ----
     Measured on the live site: 70% of body copy ran at 90–119 characters per
     line against an ideal of 45–75. 70ch caps it near 72 without narrowing
     the page frame or touching images, tables and full-width blocks.        */
  --drhp-measure: 70ch;
}

/* ===========================================================================
   READABILITY — line length
   The single largest readability defect found in the baseline audit.
   Scoped to running text only. Media, tables, embeds, columns and any block
   explicitly set to wide/full alignment keep their existing width.
   =========================================================================== */

.entry-content > p,
.entry-content > ul,
.entry-content > ol,
.entry-content > blockquote,
.entry-content > h2,
.entry-content > h3,
.entry-content > h4,
.entry-summary > p {
  max-width: var(--drhp-measure);
}

/* A max-width block keeps its left edge, so capping the measure silently
   un-centres anything the author centred — measured at up to 122px of drift on
   17 of 60 pages, including the crisis-line paragraph on the contact page.
   Re-centring the block preserves the author's alignment exactly. */
.entry-content > .has-text-align-center,
.entry-content > [style*="text-align: center"],
.entry-content > [style*="text-align:center"],
.entry-content > center,
.has-text-align-center > .drhp-measured {
  margin-inline: auto;
}

/* Right-aligned content needs the mirror treatment. */
.entry-content > .has-text-align-right,
.entry-content > [style*="text-align: right"],
.entry-content > [style*="text-align:right"] {
  margin-inline-start: auto;
  margin-inline-end: 0;
}

/* Never constrain layout containers or media. */
.entry-content > .alignwide,
.entry-content > .alignfull,
.entry-content > .wp-block-columns,
.entry-content > .wp-block-image,
.entry-content > .wp-block-gallery,
.entry-content > .wp-block-embed,
.entry-content > .wp-block-table,
.entry-content > figure,
.entry-content > table,
.entry-content > iframe {
  max-width: none;
}

/* Body copy line-height on the site is already 1.8–1.9, which comfortably
   exceeds the 1.5 that WCAG 1.4.12 asks for. It is asserted here only so a
   future parent-theme update cannot quietly regress it. */
.entry-content p,
.entry-content li {
  line-height: 1.8;
}

/* ===========================================================================
   READABILITY — heading hierarchy
   Measured: h1 renders at 26px/700 while h2 renders at 30px/700, so the
   page's most important heading is visually smaller than the one beneath it.
   Corrected using steps that already exist in the site's type scale
   (42 and 30), so no new sizes are introduced.
   =========================================================================== */

.entry-content h1,
.entry-title,
h1.entry-title {
  font-size: clamp(30px, 3.4vw, 42px);
  line-height: 1.2;
  font-weight: 700;
}
.entry-content h2 { font-size: clamp(24px, 2.6vw, 30px); line-height: 1.3; font-weight: 700; }
.entry-content h3 { font-size: clamp(20px, 2vw, 24px);  line-height: 1.35; font-weight: 700; }
.entry-content h4 { font-size: 18px; line-height: 1.4; font-weight: 700; }

/* Give headings room above so they group with the text they introduce
   rather than floating between two blocks equally. */
.entry-content h2,
.entry-content h3,
.entry-content h4 {
  margin-top: 1.8em;
  margin-bottom: 0.6em;
}

/* Utility classes so an author can use the CORRECT heading level while
   keeping the visual weight they expect. This is what makes the heading-order
   fixes possible without the page looking different. */
.drhp-h-look-1 { font-size: clamp(30px, 3.4vw, 42px) !important; line-height: 1.2 !important; }
.drhp-h-look-2 { font-size: clamp(24px, 2.6vw, 30px) !important; line-height: 1.3 !important; }
.drhp-h-look-3 { font-size: clamp(20px, 2vw, 24px)  !important; line-height: 1.35 !important; }
.drhp-h-look-4 { font-size: 18px !important; line-height: 1.4 !important; }

/* ===========================================================================
   #21 / WCAG 2.4.7, 2.4.11 — VISIBLE FOCUS ON EVERYTHING
   =========================================================================== */

:focus-visible { outline-offset: var(--drhp-focus-offset); }

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible,
[role="button"]:focus-visible,
iframe:focus-visible,
iframe:focus,
.wp-block-button__link:focus-visible {
  outline: var(--drhp-focus-width) solid var(--drhp-focus-ring) !important;
  outline-offset: var(--drhp-focus-offset) !important;
  box-shadow: 0 0 0 calc(var(--drhp-focus-width) + var(--drhp-focus-offset)) #fff !important;
  border-radius: 2px;
}

@supports not selector(:focus-visible) {
  a:focus, button:focus, input:focus, select:focus, textarea:focus {
    outline: var(--drhp-focus-width) solid var(--drhp-focus-ring) !important;
    outline-offset: var(--drhp-focus-offset) !important;
  }
}

/* WCAG 2.4.11 Focus Not Obscured — the theme uses a sticky header, so a
   focused element scrolled to the top can end up underneath it. */
/* scroll-padding-top now lives in header-2026.css, driven by the real header height. */

.skip-link,
a.skip-link.screen-reader-text { position: absolute; left: -9999px; top: 0; z-index: 100000; }
.skip-link:focus,
a.skip-link.screen-reader-text:focus {
  left: 8px; top: 8px; width: auto; height: auto;
  padding: 12px 20px; clip: auto; clip-path: none;
  background: #fff;
  color: var(--drhp-darkest);            /* 15.22:1 on white */
  font-size: 16px; font-weight: 700;
  text-decoration: underline;
  border: 3px solid var(--drhp-focus-ring);
  border-radius: 4px;
}

/* ===========================================================================
   #21 — HOVER AND ACTIVE STATES
   State is never signalled by colour alone (WCAG 1.4.1).
   =========================================================================== */

/* Cover blocks put text over a photograph with a dark scrim, where the correct
   foreground is light, not dark. Excluding them here is essential: applying the
   dark link colour inside a cover drops contrast instead of raising it. */
.entry-content a:not(.wp-block-button__link):not(.button):not(.wp-block-cover *),
.entry-summary a:not(.wp-block-button__link):not(.button):not(.wp-block-cover *) {
  color: var(--drhp-link);               /* 11.50:1 on white */
  text-decoration: underline;
  text-underline-offset: 0.15em;
  text-decoration-thickness: 0.08em;
}
.entry-content a:hover,
.entry-content a:focus-visible {
  color: var(--drhp-link-hover);         /* 15.22:1 on white */
  text-decoration-thickness: 0.16em;
}
.wp-block-button__link:hover, .btn:hover, button:hover { text-decoration: underline; }

/* ===========================================================================
   WCAG 2.2 — 2.5.8 TARGET SIZE (24×24 CSS px)
   Standalone controls only. Links inside a sentence are exempt.
   =========================================================================== */

.entry-content li > a:only-child,
.entry-content li > span > a:only-child,
.entry-content td > a:only-child {
  display: inline-block; min-height: 24px; padding-block: 2px;
}

/* ===========================================================================
   #20 — CONTENT COLOUR CORRECTIONS
   =========================================================================== */

.has-vivid-green-cyan-color,
.entry-content .has-vivid-green-cyan-color,
p.fonts-plugin-block[style*="00d084"],
[style*="color:#00d084"], [style*="color: #00d084"] { color: var(--drhp-content-green) !important; }

.has-pale-pink-color,
.entry-content .has-pale-pink-color,
[style*="color:#f78da7"], [style*="color: #f78da7"] { color: var(--drhp-content-pink) !important; }

.entry-author, .entry-meta, .entry-meta a,
.posted-on, .byline, .entry-date { color: var(--drhp-meta) !important; }
.entry-meta a { text-decoration: underline; }

.entry-content strong span[style*="ff0000"],
.entry-content span[style*="color:#ff0000"],
.entry-content span[style*="color: #ff0000"],
.entry-content [style*="color:#f00"],
.has-vivid-red-color { color: var(--drhp-danger) !important; }

.entry-content table td,
.entry-content table td strong,
.entry-content table th { color: var(--drhp-dark); }   /* 10.09:1 on #f0f0f0 */

.colors-dark .entry-title a, .colors-dark h1 a, .colors-dark h2 a,
[style*="background-color:#000"] a,
[style*="background-color: #000"] a { color: var(--drhp-on-dark-bg) !important; } /* 11.46:1 */

/* ---- Text over photographs (WordPress Cover blocks) ----
   A CSS rule cannot guarantee a ratio against an unknown photograph, so this
   does two things: forces the foreground to pure white (21:1 against the black
   scrim itself) and strengthens the scrim so the underlying image cannot lift
   the effective background above the AA threshold. */
.wp-block-cover,
.wp-block-cover-image { --drhp-scrim: 0.55; }

.wp-block-cover .has-background-dim::before,
.wp-block-cover-image .has-background-dim::before,
.wp-block-cover > .wp-block-cover__background,
.wp-block-cover-image > .wp-block-cover__background {
  opacity: var(--drhp-scrim) !important;
}

.wp-block-cover *,
.wp-block-cover a,
.wp-block-cover h1, .wp-block-cover h2, .wp-block-cover h3,
.wp-block-cover p,
.wp-block-cover-image *,
.wp-block-cover-image a {
  color: #ffffff !important;             /* 21:1 against the scrim */
}
.wp-block-cover a,
.wp-block-cover-image a {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ===========================================================================
   Motion (WCAG 2.3.3) and screen-reader helper
   =========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important; scroll-behavior: auto !important;
  }
}

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

/* Mobile: keep the measure cap from fighting a narrow viewport. */
@media (max-width: 782px) {
  :root { --drhp-measure: 100%; }
  .drhp-submenu-toggle { min-width: 44px; min-height: 44px; }
}

/* Cover-block card titles promoted from <p> to <h2> keep the Cover block's
   own typography — the page is visually identical, but the blog listing is
   now navigable by heading. */
.wp-block-cover h2.drhp-card-title,
h2.drhp-card-title {
  font-size: inherit;
  font-weight: 400;
  margin: 0;
  line-height: inherit;
}
.wp-block-cover h2.drhp-card-title.has-large-font-size { font-size: 36px; }

/* ---- Image captions ----
   A caption is either overlaid on the image (WordPress positions those
   absolutely) or sits below it on the page background. Forcing one treatment
   on both is how these captions ended up white-on-white at 1.00:1.

   Links inside a caption INHERIT the caption's colour rather than taking the
   body link colour. That is what makes this robust: whatever context the
   caption is in, the link matches it, and the underline carries the affordance
   instead of a colour change. */

figcaption a,
figcaption.wp-element-caption a {
  color: inherit !important;
  text-decoration: underline;
  text-underline-offset: 2px;
}
figcaption a:hover,
figcaption a:focus-visible { text-decoration-thickness: 2px; }

/* Caption sitting below the image, on the page background. */
figure.wp-block-image > figcaption.wp-element-caption {
  color: var(--drhp-meta);          /* 7.00:1 on white */
  background: none;
}

/* Inspiro 2.x dims image captions to 80% (.wp-block-image>figcaption{opacity:.8}),
   which turns the #595959 above into an effective #7a7a7a: 4.29:1 on white,
   under the 4.5:1 minimum (measured on staging, 28 Oct 2026). Captions keep
   full opacity, so their colour is the colour that was measured. */
.entry-content .wp-block-image > figcaption,
.entry-content figure > figcaption { opacity: 1; }

/* WCAG 1.4.10 Reflow. Core gives the audio block's player min-width: 300px,
   which sticks out of a 320px screen once the page gutters are added (two
   old copies of the home page measured 330px wide on staging, 28 Oct 2026).
   The player shrinks to its column instead; its controls still fit at 260px. */
.entry-content .wp-block-audio audio { min-width: 0; }

/* Caption overlaid on the image. WordPress's own gradient tops out at 0.4,
   which cannot guarantee white text over a bright photograph, so it is
   strengthened at the text end. */
.wp-block-gallery.has-nested-images figure > figcaption,
.wp-block-gallery figure > figcaption.wp-element-caption {
  color: #ffffff !important;
  /* OPAQUE, not translucent.
     This caption box straddles the bottom edge of the image, so with any
     translucent scrim part of the text sits over whatever the photograph shows
     there — and the resulting ratio depends on an image the client can swap at
     any time. An opaque background removes the variable completely: white on
     #1a1a1a is exactly 17.4:1, by construction, for every image now and later.
     It also means this can be verified from the computed style alone, with no
     pixel sampling and no room for a measurement error to hide a failure. */
  background: #1a1a1a !important;
  padding-bottom: 0.5em;
}



/* ---------------------------------------------------------------------------
   Page banner: white heading over a client-supplied photograph (WCAG 1.4.3)

   The parent theme absolutely positions .entry-header over .entry-cover-image
   with no scrim at all, so the heading's contrast is entirely at the mercy of
   whichever photograph the charity uploads. Measured across all 146 pages with
   the heading hidden and the true background sampled: one page failed outright
   ("The Importance of International Women's Day", 2.43:1 against the 3:1 floor
   for large text) and two more passed only by 0.03–0.09, which any future image
   swap would tip over.

   A uniform scrim removes the dependency on the image. It sits under the
   heading and over the photograph; z-index is set on both so paint order does
   not rely on source order. Alpha was derived, not guessed: the worst sampled
   background was rgb(166,166,166) (relative luminance 0.381), and 0.22 black
   over it yields ~0.23, i.e. about 3.7:1 against white — clear of the floor
   with margin for a darker future banner.
   --------------------------------------------------------------------------- */
.entry-cover-image { position: relative; }

.entry-cover-image::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.22);
  pointer-events: none;   /* never intercept a click meant for the image */
  z-index: 1;
}

.entry-cover-image .entry-header { position: relative; z-index: 2; }

/* The parent absolutely positions the header; keep that where it applies. */
.entry-cover-image > .entry-header { position: absolute; z-index: 2; }

@media (prefers-contrast: more) {
  .entry-cover-image::after { background: rgba(0, 0, 0, 0.42); }
}
